SketchUp Trim Extension

You are still not following my advice.

  1. I clearly showed above that the selection check for edges is the first thing that should happen in the command method.
    Ie, there is no point in subjecting the user to enter trim options if the command is going to have to exit because they’ve not selected any edge path(s).
    And … re:
    #Checking if edges exist in the selection - returns false if no edges are selected and closes program
    … it’s too long (lines should be 80 characters of less,) and it doesn’t “close the program”, … it exits your command method which to the enduser appears as a command cancel.
    (I’m also not fond of omitting a space after the # and the beginning of a comment. (Readability)

  2. You’ve misplaced the creation of the model and selection reference. (Ie, the if selection.empty? ||… conditional will raise a NameError exception as the reference selection is not yet defined until lower in your code.)

  3. I’ve told you repeatedly, that the results from calling UI.inputbox must be checked for a boolean falsity, as this means the user has canceled the inputbox. (Refer to previous topic threads.)

  4. I carefully explained above that the UI command procs are a snapshot and should be executed last. But you’ve pasted them in first, before even a method that the proc calls is even defined.

How could my post be a solution if you do not follow the advice ?


Endusers are not likely to be reading your code, and if this will be a commerical extension then you’ll probably encrypt all the .rb files in your extension subfolder to .rbe format. (This means endusers couldn’t read anything in the files anyway.)

Contact and support information would go in a help file and/or the unencrypted extension registrar script that goes one folder up in the “Plugins” folder. You could also put this in the extension object’s description field and the users could see it in the Extension Manager.
But most coders would put it html help files that are distributed along with your extension.


Back to the creation of the menu item command.

You are not running the program from the menu item. (SketchUp is the application program.)
Your code is executing just what the proc attached to the menu item does, which is a command (consisting of methods.)

The following will not work, as NONE of the following local reference objects have been created at the extension module level within the menu item command proc:
height, thickness, quarter_round, entities, trimdef, transgroup, edges

    #Only loading UI object creation once
    if !@loaded
      plugins_menu = UI.menu("Plugins")
      submenu = plugins_menu.add_submenu("ProTrim")
      submenu.add_item("Create Base Trim") {create_base_trim(height, thickness, quarter_round, entities, trimdef, transgroup, edges)}
      @loaded = true
    end

Secondly, (again) please stop making us and yourself scroll horizontally to read code.
Blocks, literal Arrays and Hashes, and method argument lists can span multiple lines.
You put the opening delimiter on the first line, indent the internal lines, and put the non-indented closing delimiter on the last line.

calling_some_method(
  height, thickness, quarter_round, entities, trimdef, transgroup, edges
)

# A literal array:
  prompts = [
    "Trim Height:                        ",
    "Trim Thickness: ",
    "Quarter Round: "
  ]

# A block
undo(model,"Nifty Command") {
  # a bunch of statements or a long method call
}

I told you what kind of transformation you will need. It is actually 2 (or more) transformations multiplied together.

In this snippet … vector is the equivalent of the global vector Y_AXIS.
But is also a unit vector. SketchUp and it’s APIs use inches internally regardless of what the model’s display units are set to.
So your vector used as a translational transform will result in something being moved 1 inch in the Y direction. This is not really what you need.

Your code will need to split the edges array into path arrays, with the edges in start to end order.
Then for each path array, get the start vertex from the start edge, and get it’s point position, get the vector from ORIGIN to this point and use that for the translational part of the transform …

paths.each |path| do
  start_edge = path.first
  point = start_edge.start.position
  vector = ORIGIN.vector_to(point)
  vt = Geom::Transformation.translation(vector)
  # The followme tool needs the face to be perpendicular
  # to the starting edge of the extrusion path.
  path_vector = point.vector_to(start_edge.end.position)
  # face_vector is probably one of the global axis vectors or it's reverse
  face_vector = Y_AXIS
  rt = Geom::Transformation.rotation(
    ORIGIN,
    Z_AXIS,
    face_vector.angle_between(path_vector)
  )
  transgrp = rt * vt
  extrude_base_trim(trimdef, transgrp, path)
end

Again, this is a simple example for a possibility. It assumes all trim paths will be perpendicular to the Z_AXIS (parallel to the ground plane,) which might not always be true. Some trim runs diagonally up along stairwells, and not all edges where ceiling meets walls are horizontal for crown molding trim.

Also the face_vector is only known to you, as I don’t know in what plane you plan to draw your trim face profiles. If you draw them on the XY ground plane, then you’ll also need to rotate the instances 90 degrees to stand them up. So I’d suggest draw upon the XZ plane with the front face toward the screen. The front face’s normal vector pointing toward you, it’s reverse pointing in the Y_AXIS direction.

There may bee an issue with the vector.angle_between method. It may not give angles greater than 180 degrees.

The other thing that I’ve left out is the determination of which side on the edge path to position the face group on. Your code will need to check the faces that adjoin the edge for their normal vector which would indicate a direction pointing inward toward the center of the room. (Ie, the reversed vector from the wall faces normals would point inside the wall.)

Yes, it is an exercise in iteration. I believe it has been covered here in the past.
Regardless if you can find the topic, you iterate through the edge objects until you find the ones that have a start or end vertex used only by one edge.

I’ll leave that as an exercise for you to solve.

1 Like