Dynamic Components - Conditional edge softening/hiding

Hi,

I am trying to create dynamic components for wood trim that can be spliced or joined at outside corners to appear as continuous pieces. For example a toe kick trim component that belongs to a cabinet that butts to another cabinet with its own toe kick component. Obviously in the world this would exist as a single piece of wood. I can place these two components, select the nested toe kick trim piece component, make it unique if need be, enter it and select and hide the 4 edges that butt to the other, then do the same series of steps on the other component, but that’s painful. The toekick component that I have configured is pretty advanced and has options to connect a return toe kick to the wall - like for a finished end cabinet. In this case, its a different edge condition where you’d want to see the outside corner as a visible/snappable line segment, but you wouldn’t want to see the butt joint seam between the front trim and the side trim. So in that case I’d have to go in manually and hide a different set of edges. For those having trouble visualizing this:

this is what the dynamic component wants to make it look like

this is what it needs to look like - automatically if possible

The only thing I can think of is to add more nested dynamic components that are 2d polylines - wired into the trim components that have logic saying “if I am an end, make me visible”, “if I am a splice, hide me”, “if I am a miter, only hide part of me”. I can do this, it just adds more bloat to our components for what is at the end of the day a pretty minor aesthetic benefit.

Might it be simpler to have 2 different base components and hide whichever one is not required instead?

Yeah I’d considered that too. I think it would be more than two for some of my use cases though.

I guess I just need a dynamic component guru to tell me with authority that it’s not possible to manipulate the faces and edges of a dynamic component. I know a fair bit about them and am pretty sure that it’ strue, but there are some functions that I don’t have experience using. I thought there was a small chance of some obvious trick to do what I’m trying to do that I’m just not seeing.

No you can’t manipulate raw geometry with the DC extension. You can to some degree manipulate them by stretching like in this deck board, the end angles are lenX set with trig. You could do 0 for a butt end and 45 for mitres the same way.

Deck Board.skp (900.8 KB)

You could manipulate an ‘edge’ by creating a single line as a sub component correctly positioned to overlap the hidden edge you want to toggle, and then use a hide IF statement to control visibility.

Yeah I think this is what I’m looking at. Doing real miters with corners could work too but it kills the OpenCutList integrity of having only one component per board. I’ve dealt with subcomponent groups but am still not 100% sure it’s a great idea to use groups in dynamic components that need to be resilient enough for production work.

I avoid this completely, it’s in the name Dynamic Components. @pcmoor Philip uses groups at the lowest nesting level, but there are some best practices to keep in mind.

Some other cool DC resources to be aware of:

@ryan.moore

Thanks for the effort sharing this. I’ll look it over.

If you use dynamic components a lot or if others here have any interest, I have created a plugin for our millwork/cabinet work that I may make public. I created a 2-way bridge that lets you program them via yaml text files. Here’s an example of one of mine:

---
component_name: __Toe Kick Config
schema_version: 1
opencutlist:
  tags: [Exclude]
attributes:
  a10_class:
    value: __Toe Kick Config
    units: STRING
    access: TEXTBOX
    formlabel: Class
  a11_setback:
    value: '3'
    units: INCHES
    access: TEXTBOX
    formlabel: Setback
  a19_line_break:
    value: ________________________________________
    units: STRING
    access: VIEW
    formlabel: ___Returns____________________
  a20_left_return:
    value: '0'
    units: STRING
    access: LIST
    formlabel: Add Left Return
    options:
      No - default: '0'
      Yes: '1'
  a21_right_return:
    value: '0'
    units: STRING
    access: LIST
    formlabel: Add Right Return
    options:
      No - default: '0'
      Yes: '1'
  a22_nudge_left:
    value: '-0.25'
    units: INCHES
    access: TEXTBOX
    formlabel: Left Return Nudge
  a23_nudge_right:
    value: '-0.25'
    units: INCHES
    access: TEXTBOX
    formlabel: Right Return Nudge
  hidden:
    formula: IF(Parent!hidden=1, 1, IF(Parent!a31_zone_bottom<=0, 1, a99_hide_self))
    units: STRING
  a99_hide_self:
    value: '0'
    units: STRING
    access: LIST
    formlabel: Hide
    options:
      Show - default: '0'
      Hide: '1'
  lenx:
    formula: gross_width
    units: INCHES
  leny:
    formula: base_depth
    units: INCHES
  lenz:
    formula: zone_bottom
    units: INCHES
  a12_tk_trim_thickness:
    value: '0.75'
    units: INCHES
    access: TEXTBOX
    formlabel: TK Trim Thickness
  material:
    formula: IF(a94_material_override="auto", Parent!material_case, a94_material_override)
    units: STRING
  x:
    formula: '0'
    units: INCHES
  y:
    formula: '0'
    units: INCHES
  z:
    formula: '0'
    units: INCHES
  zone_left:
    formula: Parent!a20_zone_left
    units: INCHES
  zone_right:
    formula: Parent!a21_zone_right
    units: INCHES
  case_width:
    formula: Parent!a22_case_width
    units: INCHES
  base_depth:
    formula: Parent!a01_case_depth - a11_setback
    units: INCHES
  gross_width:
    formula: Parent!a02_gross_width
    units: INCHES
  case_depth:
    formula: Parent!a01_case_depth
    units: INCHES
  zone_back:
    formula: Parent!a41_zone_back
    units: INCHES
  zone_bottom:
    formula: Parent!a31_zone_bottom
    units: INCHES
children:
  - class: TK Trim
    transform:
      rotate:
        x: 90
      flip: z
  - class: __EZ Level
    id: ez_left
    transform:
      rotate:
        x: 180
        z: 90
      flip: [x, y]
    attributes:
      x:
        formula: IF(Parent!a20_left_return=1, IF((Parent!zone_left+Parent!a22_nudge_left-Parent!a12_tk_trim_thickness)<0,
          -Parent!a22_nudge_left+Parent!a12_tk_trim_thickness, Parent!zone_left),
          Parent!zone_left)
        units: INCHES
  - class: __EZ Level
    id: ez_right
    transform:
      rotate:
        x: 180
        z: 90
      flip: x
    attributes:
      x:
        formula: IF(Parent!a21_right_return=1, IF((Parent!zone_right+Parent!a23_nudge_right-Parent!a12_tk_trim_thickness)<0,
          Parent!gross_width+Parent!a23_nudge_right-Parent!a12_tk_trim_thickness,
          Parent!gross_width-Parent!zone_right), Parent!gross_width-Parent!zone_right)
        units: INCHES
  - class: __EZ Level
    id: ez_center
    transform:
      rotate:
        x: 180
        z: 90
      flip: [x, y]
    attributes:
      x:
        formula: Parent!zone_left + Parent!case_width/2 - 0.375
        units: INCHES
      hidden:
        formula: IF(Parent!hidden=1, 1, IF(Parent!case_width>36, a99_hide_self, 1))
        units: STRING
  - class: TK Return Trim
    id: tk_return_l
    transform:
      rotate:
        x: 90
        y: 90
    attributes:
      x:
        formula: -Parent!a22_nudge_left
        units: INCHES
      hidden:
        formula: IF(Parent!hidden=1, 1, IF(Parent!a20_left_return=1, a99_hide_self,
          1))
        units: STRING
  - class: TK Return Trim
    id: tk_return_r
    transform:
      rotate:
        x: 90
        y: 90
      flip: z
    attributes:
      x:
        formula: Parent!gross_width + Parent!a23_nudge_right
        units: INCHES
      hidden:
        formula: IF(Parent!hidden=1, 1, IF(Parent!a21_right_return=1, a99_hide_self,
          1))
        units: STRING

I got frustrated with how difficult and error prone it was to create and maintain DCs using the dynamic attributes dialog so I thought this would be an easier method. It ended up creating pretty long text files but the real benefit was that I kind of incidentally created a LLM dynamic component protocol. It’s enabled us to create some pretty complex DC systems that, due to just being based on plain text are far more maintainable than skps and can be tracked easily with Git.

If there are people here who are more code savvy than me who would be interested in improving it, I’ll make the repo public. It would be worth it to me just to improve the plugin. It is definitely AI slop but it pretty stably and reliably stamps and modifies DCs and I’ve added extra functionality like sketchup tagging and adding opencutlist dictionary values.

Cool. I have done something similar in the sense I got frustrated with the DC extension, so I built a tailored companion extension that enhances my DC workflow and addresses a couple of DC bugs, and adds a dynamic volume attribute. I wonder if @pcmoor Philip and @boris.beaulant would be interested in your approach?

That’s a great idea—thanks for the suggestion, @ryan.moore
However, I am currently actively working on OCL to create tools that aim to recapture some of the dynamic nature of cabinet manipulation, without having to resort to “hacking” dynamic components—which requires breaking parts down into artificial segments.

Quick way to draw any shape of cabinet

And stretching to resize.

Of course, it doesn’t cover all dynamic aspect of DC.

That’s really neat! When you are done building that out, perhaps you could cook up a completely new DC extension…? :wink: Seriously though we need someone to do that…

@ryan.moore, maybe not so far because I’m writing a JSON spec to build hardware parts.

@renton555, the fundamental problem you’ve outlined in this thread is one I’d like to solve by finding ways to remodeling geometry without needing Dynamic Component hacks.

Example:

In the research I did (not much, and I’m not a professional computer scientist), it seemed to be a choice between either going fully-parametric-- objects are instructions that redraw the raw geometry from scratch based on parameters-- or utilizing the existing flawed DC engine. It seemed like a lot less total code needed to go the second route, not to mention our company was already using dynamic components, so it was an easier transition. I’ve found the most annoying “hacks” to be:

  1. an excessive amount of “wrappers” - components that do nothing but to contain and parameterize children

  2. any component requiring copies I decided to throw away the DC copy mechanic and just place the maximum allowable number and use logic to show the ones that are needed. This causes our cabinet component to have many extra instances that bloat the outliner while being hidden in 90% of our use cases.

I managed to solve a lot of problems using the script. It can handle mirroring and rotation which always gave us trouble when using dynamic components in the past. A yaml file can contain parameters for the component itself, child references that point to other yaml files (for example cabinet.yml references carcass.yml, doors.yml, toekick.yml, etc). For complex geometry like blum hardware, I added the ability to add a path to a template skp, which the script will use as a geometric base instead of drawing a simple box from scratch, which is its default.

@boris.beaulant I am really excited to see where you go with parametric objects in OCL and am an avid follower of the dev version changelog. I see your approach as working best for general millwork design composition. The advantage to my approach that I’ve seen is that it lets us add our proprietary information - SOPs - cut list naming format - design standards like typical door reveals and face frame widths/overhangs - baked into a dynamic component asset that is maintainable with Git.

My method of using DCs also made it easy to show 2d linework for elevations such as door swings and dashed lines for adjustable shelves occluded by doors. I think that the parametric approach could do this as well but I’m not sure that’s something that’s on the roadmap or scope for OCL.

I would also be curious to know if the capability to make fast changes to models is part of the roadmap. The DC engine pretty easily facilitates having top level ‘god’ wrappers that allow you to toggle switches such as overlay, face frame, inset, slab or shaker doors, or make changes to materials which can then automatically cascade to descendant components on a redraw.