Component Browser Alternative?

I HATE the native Component Browser. I don’t want searches linked to the internet. I don’t want 12 folders hard-coded into the drop down that I don’t use. I don’t want to have to set all my local folders I commonly use as “Favorites” for them to show up in the drop down. I DO want to be able to search the current model component definitions rather than having to scroll scroll scroll scroll scroll scroll scroll!

And no, I don’t need anything like FlexTool’s Component Finder which is nice but does not search the current model’s components.

In autocad I could hit “i” (for insert) then start typing the first few letters of a block name and the dialog would scroll to matches… something like that. Super lightweight, quick, and functional.

Any thoughts?

I am trying to avoid developing this myself because I’m sure someone has done it already or someone with way more coding chops than me could do it in 12 seconds.

Thank you all!

2 Likes

Certainly not in 12 seconds.

There are a lot of Component browser clones out there and you may have to be satisfied with what you find. And every little furniture maker wants developers to make a full component browser for them that is limited to showcase only their components. It’s a lot of effort requested for little gain.

1 Like

You can use the outliner panel for that.

4 Likes

I’ve also asked for a long time for a simple search field in the component browser. Disconnecting it from the 3D Warehouse would also be an improvement in my view (we already have File > 3D Warehouse and Window > 3D Warehouse to search the 3D Warehouse).

Regarding making a replacement it would require some more work than 12 seconds. Also it wouldn’t be dockable to the tray and other inspectors. In the end I think this would outweigh the benefits for me to use such an extension.

3 Likes

I see. Well, i am a keyboard shortcut guy so I am imagining something that doesn’t dock but you’d hit like “cntrl i”, and start typing a component name into a dropdown. Basically, any component in the model could be about 3 keystrokes away which would be very helpful for modeling.

1 Like

I see what you mean! Aerilius has created a similar UI, but for finding SketchUp commands. If it’s open source it could perhaps even be used as a base for a component placer extension. Extension | SketchUp Extension Warehouse

I’m afraid I don’t have the time to create this, but if someone does it could be a quite nice little extension.

OK, I may try something too if I can get a hot minute free! Thanks for your input!

Have you tried Component Finder by Flextools, it searches all your folders and has a really fast and easy window, it really is what the finder/ browser in sketchup should be… I have been using it for a bit and think its great

hope this helps

Dan B

Thanks Dan and yes, Component Finder is WAY better than the native palette BUT, it will not search the current model (strangely enough).

I have started the code below to begin muddling through it but still a ways to go:

def self.z_insert()
@m = Sketchup.active_model.definitions
@components = ""
@m.each{|key,val|
    @components += "#{key.name}|"
}
if(@components)
    #UI.messagebox(@components, MB_MULTILINE)
    
    # With four params, it shows a drop down box for prompts that have
    # pipe-delimited lists of options. In this case, the Gender prompt
    # is a drop down instead of a text box.
    prompts = ["Select Component"]
    defaults = [""]
    list = [@components]
    selected = UI.inputbox(prompts, defaults, list, "Z Insert")
    
    print "user selected component: #{selected[0]}"
    
end
end

Early Notes…

  1. There may NOT be an obvious way to load from the active model memory? The add_instance method in the API only seems to accept a component definition with a pre-loaded external path

    point = Geom::Point3d.new 10,20,30
    transform = Geom::Transformation.new point
    model = Sketchup.active_model
    entities = model.active_entities
    path = Sketchup.find_support_file “Bed.skp”, “Components/Components Sampler/”
    definitions = model.definitions
    componentdefinition = definitions.load path
    instance = entities.add_instance componentdefinition, transform

Well that stinks.

  1. When I pull the Definition list, it is clearly VERY different from the list shown in the nateiv Components Palette. There are like 4 items in the native list but the Definition List has about 30. I’d need to somehow limit/filter the definition list OR access whatever list the native on is accessing.

one is showing all the definitions in the model which includes nested, hidden, un-used/un-purged. the browser shows the parents, but not children [less cluter]…

I’d move this to the ruby section if you want to try and solve this with code…

john

Sketchup.active_model.definitions gives you a list of all definitions already in the model. You don’t need to “load” them anew. ComponentDefinitions also have a hidden? method, that tells you whetehr they are hidden or not in the component browser. Nested components of components associated with external files (those were internal? is false) are by default hidden. You can also exclude those were group? is trur from your list, or maybe make it a user option.

Remove the @ please, if you are not sure why you use it. It is for instance variables when you do object-oriented programming with classes.

1 Like

OK, I’ll get on that…

  1. Remove @ for variables… I think I could not get the script to work with the Modules and Classes that we are supposed to use to protect namespaces. In other words, no I don’t understand when to or when not to use!

  2. Top level components only… Thinking I will do a parent check saying something like if parent is not Model to get only the top level components… @enroth3 Yes, perhaps a nested toggle would be useful.

Thanks!

OK here is the latest…

require 'sketchup.rb'
module ZCode
module ZInsert

def self.z_insert()
    
    model_defs = Sketchup.active_model.definitions
    comp_list = ""
    comp_names = Array.new
    comp_defs =  Array.new
    model_defs.each_with_index{|cdef,index|
        #print model_defs[index].hidden?
        if(!model_defs[index].hidden?) && (!model_defs[index].group?)
            comp_list += "#{cdef.name}|"
            comp_names.push(cdef.name)
            comp_defs.push(cdef)
        end
    }
    
    #UI.messagebox(comp_list, MB_MULTILINE)
    
    prompts = ["Select Component"]
    defaults = [""]
    list = [comp_list]
    selected = UI.inputbox(prompts, defaults, list, "Z Insert")

    selected_name = selected[0]
    print "user selected component: #{selected_name}\n"
    selected_index = comp_names.index(selected_name)
    print "selected index: #{selected_index}\n"
    selected_def = comp_defs[selected_index]
    print "selected comp: #{selected_def}\n"
    
end
    
end # end of module ZInsert
end # end of module ZCode

Now what? how do I actually insert the selected component now that I have it?

This’ll point you in the correct direction

require 'sketchup.rb'
module ZCode
  module ZInsert

    def self.z_insert()
      model_defs = Sketchup.active_model.definitions
      comp_list = ""
      comp_names = Array.new
      comp_defs =  Array.new
      model_defs.each_with_index{|cdef,index|
          #print model_defs[index].hidden?
          if(!model_defs[index].hidden?) && (!model_defs[index].group?)
              comp_list += "#{cdef.name}|"
              comp_names.push(cdef.name)
              comp_defs.push(cdef)
          end
      }
      #UI.messagebox(comp_list, MB_MULTILINE)
      
      prompts = ["Select Component"]
      defaults = [""]
      list = [comp_list]
      selected = UI.inputbox(prompts, defaults, list, "Z Insert")

      #user may have canceled or chosen the blank item at the top of your drop down list
      if selected.is_a?(Array) && (selected[0].size != 0)
        selected_name = selected[0]
        print "user selected component: #{selected_name}\n"
        selected_index = comp_names.index(selected_name)
      
        print "selected index: #{selected_index}\n"
        selected_def = comp_defs[selected_index]
        print "selected comp: #{selected_def}\n"
      
        Sketchup.active_model.place_component(selected_def, false)
      end
    end
      
  end # end of module ZInsert
end # end of module ZCode

ZCode::ZInsert.z_insert

is equal to

comp_names = []

Model#place_component gives you an interactive positioning tool (interrupts Ruby execution, waiting until user has placed it). If you every need to automate this without user interaction, you will want to add an instance of that component definition to the entities: Entities#add_instance

It works! That is perfect. Thank you.

Also thanks Aerilius, I much prefer that array def approach.

Now my one last feature is to make the list focused so, being a keyboard shortcut user, I can either start typing the first few characters of the component name to select it OR use the up/down arrow keys to select. Obviously, you’d want pressing enter to be equivalent to hitting the OK button.

There do not seem to be focus controls for Ui.inputbox so I may have to switch to html dialog?

UI.inputbox does not give you any control. You could maybe hit the key (tab).

UI.inputbox does not give you any control. You could maybe hit the key (tab).

I’d prefer not to because it is sort of the point of all this to get down to as few keystrokes as possible.

Here is an htmldialog version that is getting closer…

require 'sketchup.rb'
module ZCode
module ZInsert

def self.z_insert()
    
    model_defs = Sketchup.active_model.definitions
    option_list = ""
    comp_defs =  []
    model_defs.each_with_index{|cdef,index|
        #print model_defs[index].hidden?
        if(!model_defs[index].hidden?) && (!model_defs[index].group?)
            option_list += "<option value='#{cdef}'>#{cdef.name}</option>"
            comp_defs.push(cdef)
        end
    }
    
    html_dialog = UI::HtmlDialog.new()
    html_dialog.center
    html = "
        <b>Select Component</b>
        <select id='sel' onchange='if(this.selectedIndex) sketchup.comp_selected(this.selectedIndex);'>
    "
    html += option_list
    html += "
    </select>
    "
    html_dialog.set_html(html)
    html_dialog.show
    
    html_dialog.add_action_callback("comp_selected") { |action_context, sel_index|
        Sketchup.active_model.place_component(comp_defs[sel_index], false)
        html_dialog.close
    }
    
end
    
end # end of module ZInsert
end # end of module ZCode

just need to figure out how to focus the select element onLoad.

I tried some of the stuff mentioned here:

https://forums.sketchup.com/t/how-to-pass-values-to-htmldialog/47968

to no avail.