How do you make individual components
-
I'm having a quick look at it.
However, when posting code, please wrap it in Code tags to the formatting is preserved. And when posting whole scripts like this you might as well just post the .rb file itself.
-
I see.
The reason you're not getting any components are because you are not creating any.
You must explicitly create a group or component and add the entities to it.
You are doing it once in the script:
group = entities.add_group
http://code.google.com/apis/sketchup/docs/ourdoc/entities.html#add_groupHere you are creating a group. You must do this for each object you want and add the entities to that group.
-
I looked at the link Thomas but I didn't see the answer. If you want to make a component instead of a group, would you replace
group = entities.add_group
with
component = entities.add_component
?
-
To to create a component you first need to create a component definition and add the entities to it. Then place instances of that definitions
entities.add_instance
.I deliberately just explained groups as they are more straight forward. So that Brendon could see the concept of creating isolated geometry via Ruby.
-
Thanks Thomas.
I was just asking because I downloaded Dan's revision of box.rb and was wondering about changing it to make components instead of groups. I was thinking that it might be a tool to speed up some of my drawing processes but in thinking about it, I decided it will just replace one operation with another.
Thanks again.
-
Thank you Thomas and Dave for your replies. I was pretty sure there had to be more script for each piece (object). I'm not too familar with the syntax. And reading all this is daunting for me. Basically, I was just cannabalizing open files to suit my purpose; and beyond what I understood from doing that, I'm a bit lost when off the beaten track. I read the links you gave, and I tried, but came up lacking.
I do not know what to put with say,
ls=[] #left panel
ls[0] = [0, depth, kick]
ls[1] = [0, depth, height-thick]
ls[2] = [0, thick, height-thick]
ls[3] = [0, thick, kick]
ls_base = entities.add_face ls
ls_base.pushpull thickto turn it into a component. I pasted every line you gave, this way and that- front and back. But I couldn't figure it. Monkey see-monkey do, has it limits. ha ha.
-
Hi,
My first post, so before anything else, hello
A bit of background on my component issue...
I have a model that I have 'inherited' (approximately 130 buildings) that need to be cleaned up - basically lots of unconnected entities, and components with materials applied to the back face etc. I have thrown together a quick and dirty script to fix these issues (I was a little surprised at how easy it was to fix all that; ruby is very nice to use)
Where things have gone a little screwy, is when I try to re-create the individual components.All my searching keeps pointing me back to the API documentation, which is fine, but I must not be interpreting it correctly, and am now just going round in circles?..
The basic process I am trying to do is:
temp_group = exploded_entities.add_group adjusted_component = temp_group.to_component
The API docs state that calling the explode method on a ComponentInstancewill return an Entitiesobject. I read this as an Entities container (array?) filled with the individual Entityobjects that make up the building - the Entities container class is the only one with the add_group method!?
Functionally I am able to access the exploded building as expected, as I said above the clean up steps work no worries, what I am finding is that the exploded_entities object is of type Array and as such throws a no method error when calling add_group?Here is the code in question:
# output working component puts e.typename + "; " + compname if exploded_component = e.explode puts "Exploded into; " + exploded_component.class.to_s # parse component entities exploded_component.each do |ce| ...fixing stuff here end #end do #re-create component temp_group = exploded_component.add_group adj_component = temp_group.to_component puts "Recreated; " + adj_component.name puts "Total Faces; " + totalfaces.to_s + ";;Adjusted; " + adjusted.to_s
Here is the console output:
I know it'll be something really simple - it usually is
Thanks in advance
-
When you explode a ComponentInstance it returns an Array of Entities NOT an 'Entities' object.
There are several ways to get available 'entities'
Sketchup.active_model.entities
ALL model's entities
Sketchup.active_model.active_entities
accessible entities in this 'edit' session - if not edit it is == previous example
definition.entites
the entities in the definition
group.entities
the entities in the group.
The
add_...
methods apply to Entities.
So to add a group to the model use
new_group=Sketchup.active_model.entities.add_group()
then get that group's entities and add to them
new_group.entities.add_cpoint([1,2,3])
So in your case let's assume the grouped building is done something like this...
### we have already somehow got an array of the required 'bits'... group=Sketchup.active_model.entities.add_group(an_array_of_entities) ### this method can lead to Bugsplats BUT with the recent SUp MR it seems more stable ### now you have group in the model that holds the 'bits'... inst=group.to_component defn=inst.definition defn.name="defn_name" defn.decription="defn_desc" ### you could then erase the 'inst' and reinsert an new one if needed, or just transform! it to anew location etc...
-
Hi TIG,
thanks for the clarification, it is nice to know I wasn't completely lost and was heading down the right track in one of my circular attempts - when I encountered an "All entities must have a common parent" error I went back to my initial attempt for my first post...
The current issue now seems to be that my exploded_entities need a reference to their 'parent' before being added to the group, yet I thought this is what add_group/to_component process was doing? From what I understand from the API, you must have a Component Instance first, then use it to create the Component Definition - then multiple Instances can be created under the Definition?
Using your example, my code becomes:
orig_entities = Sketchup.active_model.entities ### Note; there is (correctly) no difference between calling .entities, or .active_entities here ... #re-create component temp_group = orig_entities.add_group(exploded_component) adj_component = temp_group.to_component adj_definition = adj_component adj_definition.name= orig_definition.name adj_definition.description= orig_definition.description
The console throws:
Line 42 is the temp_group = orig_entities.add_group(exploded_component) method call.
If it helps, here is the entire script:
require 'sketchup.rb' # # # def parsecomponents # containers adjustedcomps = Sketchup;;Entities.new # data model = Sketchup.active_model orig_entities = model.entities layers = model.layers unattached_layer = layers.add "Unattached Elements" #anything that ends up here to be deleted... puts "Starting-----------------------------" orig_entities.each do |e| case e when Sketchup;;ComponentInstance totalfaces = 0 adjusted = 0 orig_definition = e.definition orig_transform = e.transformation # output working component puts e.typename + "; " + orig_definition.name if exploded_component = e.explode puts "Exploded into; " + exploded_component.class.to_s # parse component entities exploded_component.each do |ce| # swap material if required if ce.is_a? Sketchup;;Face totalfaces += 1 if !ce.material && ce.back_material ce.material= ce.back_material ce.back_material= nil adjusted += 1 end #end if end #end if end #end do #re-create component temp_group = Sketchup.active_model.entities.add_group(exploded_component) adj_component = temp_group.to_component adj_definition = adj_component adj_definition.name= orig_definition.name adj_definition.description= orig_definition.description puts "Recreated; " + adj_definition.name puts "Total Faces; " + totalfaces.to_s + ";;Adjusted; " + adjusted.to_s else UI.messagebox "Failed to Explode Component!" end else # anything other than a component is not wanted... e.layer= unattached_layer puts e.typename + " moved to Unattached Layer!" end # end case end # end do puts puts "Completed----------------------" end # end parsecomponents ########################################### if(file_loaded("swapmaterials02.rb")) menu = UI.menu("Plugins"); menu.add_item("Parse Model") {parsecomponents} end #------------------------------------------ file_loaded("swapmaterials02.rb")
Cheers Doi!
-
Try this...
require 'sketchup.rb' # # # def parsecomponents # containers ###adjustedcomps = Sketchup;;Entities.new ###NOT USED LATER ??? # data model = Sketchup.active_model # model.start_operation("parsecomponents") ### SEE BELOW...*** orig_entities = model.entities layers = model.layers ###??? unattached_layer = layers.add "Unattached Elements" #anything that ends up here to be deleted... ??? puts "Starting-----------------------------" orig_entities.to_a.each do |e| ### NOTE HOW I MADE IT AN array FOR SAFETY if e.class == Sketchup;;ComponentInstance ### PROBABLY EASIER THAN class ??? totalfaces = 0 adjusted = 0 orig_definition = e.definition orig_transform = e.transformation # output working component puts e.typename + "; " + orig_definition.name if exploded_component = e.explode ### THIS IS AN array puts "Exploded into; " + exploded_component.class.to_s # parse component entities exploded_component.each do |ce| # swap material if required if ce.is_a? Sketchup;;Face totalfaces += 1 if !ce.material && ce.back_material ce.material= ce.back_material ce.back_material= nil adjusted += 1 end #end if end #end if end #end do #re-create component temp_group = orig_entities.add_group(exploded_component) ### ADD it were it was adj_component = temp_group.to_component adj_definition = adj_component.definition ##### POINT TO THE DEFN !!!!! # name=orig_definition.name ### USED below*** adj_definition.name= orig_definition.name ##### THIS will add [1] to the end as the original exists adj_definition.description= orig_definition.description puts "Recreated; " + adj_definition.name puts "Total Faces; " + totalfaces.to_s + ";;Adjusted; " + adjusted.to_s ### YOU COULD remove the original definition too... ### neeeds start/commit ### *** # orig_definition.name = orig_definition.name+rand.to_s ### rename temporarily # orig_definition.entities.erase_entites(orig_definition.entities) # adj_definition.name = name ### the orig_defn is now emppty and will go from the browser after the 'commit' *** ### the new definition has it's name else UI.messagebox "Failed to Explode Component!" end else # anything other than a component is not wanted... e.layer= unattached_layer puts e.typename + " moved to Unattached Layer!" ### alternatively ADD erase! HERE AND AVOID layer COMPLICATIONS # e.erase! if e.valid? # puts e.to_s+" ERASED." ### valid? traps if you delete an edge that had aface that's then not available to erase next! end # end IF ### end # end do puts puts "Completed----------------------" # model.commit_operation ###*** end # end parsecomponents ########################################### if(file_loaded("swapmaterials02.rb")) menu = UI.menu("Plugins"); menu.add_item("Parse Model") {parsecomponents} end #------------------------------------------ file_loaded("swapmaterials02.rb")
BUT to be honest I think you are making it overly complicated, as you can edit the definition's contents directly thus
require 'sketchup.rb' def parsecomponents model = Sketchup.active_model model.start_operation("parsecomponents",true) ### makes it undobale ents = model.entities puts "Starting-----------------------------" ents.to_a.each{|e| if e.class == Sketchup;;ComponentInstance totalfaces = 0 adjusted = 0 defn = e.definition begin defn.entities.each{|e| if e.class==Sketchup;;Face totalfaces += 1 if !e.material && e.back_material e.material= e.back_material e.back_material= nil adjusted += 1 end #end if end #end if } rescue UI.messagebox "Failed to Edit Component!" end#begin else # anything other than a component is not wanted... e.erase! if e.valid? puts e.to_s+" ERASED." end # end IF ### } puts "Recreated; " + defn.name puts "Total Faces; " + totalfaces.to_s + "; Adjusted; " + adjusted.to_s puts "Completed----------------------" model.commit_operation end # end parsecomponents ########################################### if(file_loaded("swapmaterials02.rb")) menu = UI.menu("Plugins"); menu.add_item("Parse Model") {parsecomponents} end #------------------------------------------ file_loaded("swapmaterials02.rb")
-
Wow TIG,
thank you so much! Both edits work a treat , but yes yours is definitely more succinct - I have always had issues with my code being a tad too verbose, and possibly missing the trees for the forest...
After my previous post, I was thinking it did seem odd that I wasn't working directly with the definition, but I'm sure I would never have found it without the help
Thanks again - now onto the next tweak...
Cheers,
Doi!
Advertisement