Sub-component creation, decoration, etc?
-
Let's say that the user has selected a single component and I have created edges in all of its faces where they intersect the X=5 plane. I would now like to create a pair of sub-components which contain everything to the left (right) of the intersection plane, adding assorted attributes.
I'm not too worried about finding out which faces are on which side of the plane, but I am mystified by the way SU handles groups, components, etc. I see that I can create a group and turn it into a component, but I'm not sure how to add faces to the group (as opposed to creating new faces), add attributes, etc.
Could someone provide a pointer to an example or a description of how to do this sort of thing?
-
Add existing faces?
group = entities.add_group(array_of_faces)
But, usingadd_group
with entities as arguments has a sad tendency to crash SU. You are safer out recreating the faces yourself inside the group.To create a component:
DefinitonList
http://code.google.com/intl/nb/apis/sketchup/docs/ourdoc/definitionlist.htmlEntities.add_instance
http://code.google.com/intl/nb/apis/sketchup/docs/ourdoc/entities.html#add_instancemyDef = Sketchup.active_model.definitions.add('definiton name') entities.add_instance(myDef, myTransformation)
-
I already have a component with a lot of attributes, edges, faces, etc. My preference would be to collect these into assorted sub-components.
It sounds like you are saying that this isn't a workable approach. So, I need to create a new component and sub-components, then copy the content of the first component into appropriate locations in it.
I'm willing to try this, but I'm not at all sure how to proceed, what things I have to copy, etc. Can you provide a bit more detail and/or pointers to example code?
-
Well, you could try to use groups - see how/if it works. But just be warned that you might see bugsplats.
Recreating entities into a component isn't something I've tried myself. It's one of our main complaints about the Ruby API.
-
Let's say you have a component that has the definition
defn
and an instanceinst
.
The component'sentities
- like faces and edges - all reside indefn
- none are ininst
. Attributes can be assigned todefn
and/orinst
.
Materials
andlayers
can be assigned to theentities
withindefn
, BUT they can also be given to each instance of it, likeinst
.
For example, if defn is a car and most of it's geometry is on 'Layer0' you could put the driver and passengers on a layer 'people'. You could also give the car's bodywork the <default> material [nil] but other parts fixed colors like the seats, lights and tires...
Now you can give any instance - e.g.inst
- its own layer which you can switch on/off [as well as showing the driver et al or not by toggling their layer] AND color each instance of the car differently - inst=red, inst2=blue etc, although parts like the lights will keep their color...
So, why am I explaining this...
You ask if you can add sub-components to a component.
You can only add component-instances into a component-definition's entities.
You cannot add component-instances into another component-definition's instance, as that is simply a 'marker' for the definition and has no 'entities' of its own.
So let's take the earlier car example - you have the car as a component-definition [defn
] and an instance of it [inst
].
You want to add a driver to the car. Manually you would editinst
and use the Component Browser to find a suitable driver component-definition and insert an instance of that into the open entities.
Close the edit and now any other instances ofdefn
will also have a driver, as will the definition in the Browser and any future versions you add.
IF you wanted to add a driver to only one or two instances of the car then you need to use 'make unique' on an instance [select and right-click context-menu], and edit that as above... and then swap whichever driver-less cars you want to become the type with a driver, using 'replace selected' from the right-click option in the Browser.
So that's the manual version...
You can do this with a script.
driver=cardefn.entities.add_instance(driverdefn, transformation)
where thetransformation
gives the point of insertion, you can thendriver.transform!(tran)
wheretran
is a rotation, scaling, translation, etctransformation
to suit your needs...
If you want to do this only to one instance of the car thencarunique=inst.make_unique
and then process as above but withcardefn=carunique.definition
...
Materials or layers or attributes already assigned to the definition of the car, or to any instances of the car, are not affected by the addition of an instance of the driver-component to the entities of the car's definition.
The driver instance within the car's definition itself can also have materials, layers and attributes assigned to it independently of the driver-component's definition
Adding a sub-component instance into a definition is straightforward - the transformation part can be tricky.
I have a 'ComponentInstance-add_entities.rb' that adds a method that allows you to add selected entities - including instances into a selected instance's entities...
componentinstance.add_entities(entities,copy,unique)
entities
= entities to add into the component-instance's definition.
The other arguments are optional, and can be given as true or false.
If they are not given 'false' is assumed.
copy
= true - the entities are copied into the component-instance's definition, the originals remain as they are.
= false - [default] the entities are moved into the component-instance's definition, the originals are erased from the model.
unique
= true - the component-instance's definition is 'made unique', any other instances of that definition are therefore unchanged.
= false - [default] the component-instance's definition is updated, and all other instances of that definition are also changed, the '~SCRAP~' version of the former definition is deleted...
Thus the simplest form is:
componentinstance.add_entities(entities)
which moves the entities into the component-instance's definition, changes all instances of that definition globally and then purges the original '~SCRAP~' definition.
Added entities keep their material, layer and attributes.
The entities are added to the component-instance's definition using the same orientation and location, even if the instance had been manipulated in 3D etc.
An instance cannot be in its own 'add_entities' list, BUT another instance of that instance's definition can - therefore if the instance is in the list it is removed and a 'duplicate' added.
An 'add_entities' list that contains another instance of the instance's definition recursively could bugsplat - if so then any of these instances are 'made unique' to avoid this.
It can sometimes BugSplat if the Outliner window is open when it runs... so it can now be forced to rollup first - using Jim's code ideas - you'll need 'toggleWindows.rb' and 'Win32API.so' - sorry it's for Windows only - Mac users ???
If you are on a PC and don't install toggleWindows.rb/Win32API.so then it'll still work BUT please close the Outliner to avoid BugSplats !
You might see how to do what you want with this OR using some of it's ideas - here's a link http://forums.sketchucation.com/viewtopic.php?p=145009#p145009 -
@thomthom said:
using
add_group
with entities as arguments has a sad tendency to crash SU.I've read this in the doc, but haven't experienced it. Is this a fixed bug?
-
@martinrinehart said:
@thomthom said:
using
add_group
with entities as arguments has a sad tendency to crash SU.I've read this in the doc, but haven't experienced it. Is this a fixed bug?
I'm not sure. I've not had to do anything like this recently. Though I think Chris recently ranted about this. Try to give him a nudge.
-
It will splat if you try to move entities into the entities of a definition and they are cross-threaded to another entity set.
Somodel.active_entities.add_group(face)
will crash because the face's edges are still in the model !!!
face=[face]+[face.all_connected]
model.active_entities.add_group(face_connected)
shouldn't fail as nothing will be left behind...
However, you probably don't want all of the connected bits AND the safe way is to 'clone' it.pts=[];face.vertices.each{|v|pts<<v.position} mat=face.material bac=face.back_material lay=face.layer attrdicts=face.attribute_dictionaries ### grp.model.active_entities.add_group() face_clone=grp.entities.add_face(pts) ### OK if know it's first and so it's the one and only face ? ### if there might be more that one face made by this first make an array of the grp's faces ### and after adding face_clone repeat array and the difference is the faces - then loop through each as set out below... face_clone.material=mat face_clone.back_material=bac face_clone.layer=lay attrdicts.each{|attrdict| name=attrdict.name attrdict.each_pair{|key,value|face_clone.set_attribute(name,key,value)} }if attrdicts ### etc - this doesn't copy the face's edges' attributes/layers/materials, but you get the idea... face.erase! ### 'face' has been cloned into the group, leaving its edges behind. It looks like it's 'moved'. If you had any variables pointing at face that are still used then add face=face_clone ###
-
The one that caught me for a while is if you add an edge, but it is part of a curve, and you are not adding the rest of the edges in the curve - that will splat.
So exploding curves is necessary too.
Chris
-
@chris fullmer said:
The one that caught me for a while is if you add an edge, but it is part of a curve, and you are not adding the rest of the edges in the curve - that will splat.
So exploding curves is necessary too.
Chris
From what I understood of TIG, even exploding the curve and adding one segment will crash, as the edge is still connected to other edges on either side.
Or did I misunderstand? -
@thomthom said:
@chris fullmer said:
The one that caught me for a while is if you add an edge, but it is part of a curve, and you are not adding the rest of the edges in the curve - that will splat.
So exploding curves is necessary too.
ChrisFrom what I understood of TIG, even exploding the curve and adding one segment will crash, as the edge is still connected to other edges on either side.
Or did I misunderstand?No - moving a loose Edge [that is neither part of a Curve or defining a Face] into a Group shouldn't splat... It's the splitting of thing that rely on each other that splats - an Edge might be connected to another Edge at it's end, BUT it shouldn't splat as each can survive without the other - A Curve or a Face need other things [Edges] to define them so moving them 'trans-entities' could be fatal !
-
Gotcha!
-
And there is a feautre request submitted and I heard they are seriously thinking about trying to fix all of this for us.
I often find it would be nice to move existing entities into existing groups.
Chris
-
@chris fullmer said:
And there is a feautre request submitted and I heard they are seriously thinking about trying to fix all of this for us.
I often find it would be nice to move existing entities into existing groups.
Chris
Feature request? Surely it's a bug report? They already added the API for it, with the arguments for add_group, but it's bugged.
-
heh! you're right. I filed it as a bug report (with an ill-advised threat to to do bodily harm to whoever did not get it implemented).
Hopefully they fix it. It would be nice.
Chris
-
Also, I think it is not as bad as you are pointing to TIG. If I add a face without its edges, it works just fine.
---tested more and came back---
hmm, just adding a face that is bound by an edge that is part of a curve ALSO does not necessarily cause a splat like I had thought.
But I do know that in my faces to components script, I ran into problems and when I first exploded all curves in the model, I was able to overcome the splats.
But now I'm confused again as to what causes it.
Chris
-
Sounds like it's one of them fun SmartBugs. Genetically manipulated to be invisible when you look directly at it.
-
Chris
I have also tried it afresh - hadn't tried it recently as who needs bugsplats! I can't get it to splat either has something been fixed in v7.1[M1] and they're just not telling us ?
It didn't always splat before, BUT trans-entities selections seem to be a major contributor.
One thing it does do, which I sure it didn't used to, is if you draw a cube and select just the one face [no edges] and run the code below it groups the face and replicates its edges leaving the original edges behind but the face has been cut from the model: BUT if you erase one of the cube's faces and then select an adjacent face [again no edges] and run the code the face is cut from the model and so is its edge that had no other attachments, however, the common edges with the other faces are just replicated in the group and remain intact so their other faces are kept... I'm sure it never did that before !group=Sketchup.active_model.active_entities.add_group(Sketchup.active_model.selection.to_a)
In passing I also noticed that running a group intensive script with the Outliner open doesn't seem to splat now ? Again I avoid it but did do it accidentally yesterday a couple of times and no splats... mysterious...
-
Yea - I miss a bug-fix list in the release notes.
Gotto test this with older SU versions though.
Advertisement