Selecting Specific Entity, Group or Component (By Name)

Not sure if it is on the ruby end or if can be done in c. Is there a way to find a specific component in a model by its definition?

Also this is from the ruby api. If [0] assumes the first entity, is there a way to get the last added entity or component?

# Assumes that the board group is the first entity in the model.
board = Sketchup.active_model.entities[0]

you can use -1 by that I mean

entities[-1] 

john

Sketchup.active_model.entities[-1]

is the last added entity in the modelā€™s entities collection.

Sketchup.active_model.active_entities[-1]

is the last added entity in the current contextā€™s collection.

Sketchup.active_model.definitions[-1]

is the last added definition [which you must remember might be a component, group or image].

[0] is a synonym of .first in the list.
[-1] is for .last in the list.
You count forwards in the list thus:
[1] for the second in the list etc.
and backwards in the list thus:
[-2] for the last but one etc.

Thank you for your help.

Can you search for components by name?

[quote=ā€œecw, post:5, topic:11469, full:trueā€]
Can you search for components by name?
[/quote] Of courseā€¦

componame="MyLovelyComponent"
compo = Sketchup.active_model.definitions[componame]
if compo
  puts "#{componame} found: doing something else..."
  ### do something with 'compo' definition
else
  puts "#{componame} does NOT exist!"
  return
end

Can I suggest you install and read the code in many of the available ā€˜freeā€™ Plugins.
They are usually not encrypted and will include many of the SketchUp API methods you seekā€¦
Do not copy them verbatim, but use them to inform your own ideasā€¦

See: Sketchup::DefinitionList.[]

Because you are asking about filtering and searching, (and the API docs do not actually say so,ā€¦) Iā€™ll assume you do not know that most SketchUp API collection classes mix in the Ruby Enumerable library.

So say that wasnā€™t exactly the definition name that you wanted to find, but one of a certain definitionā€™s instances.

Using the definition list subscript method, you get the definition reference, then use one of the Enumerable search methods to find the exact instance by either guid or instance name (which can be different from, but based upon, itā€™s definitionā€™s name.)

dlist = Sketchup.active_model.definitions
cdef = dlist["PocketDoor"]
if cdef # test for nil (not found)
  if !cdef.instances.empty?
    obj = cdef.instances.find {|i| i.name == "PocketDoor - Master Bath" }
  else
    obj = nil
  end
end

EDIT: (Adding this note on zooming to a found object, because of a post in another thread.)

Once the object is found, to zoom extents around the entity use:

Sketchup.active_model.active_view.zoom(obj) unless obj.nil?

ADD: For how to find a group instance by name, see [u]this post further down the thread[/u].

3 Likes

As @DanRathbun explainedā€¦
There are TWO names for what you might term a ā€˜Componentā€™.
The name of the Component-Definition itself as displayed in the Components Browser, in Entity Info, also and available via model.definitions[...] - and the name of a Component-Instance - also seen in Entity Info.
A definition might have several instances - each can have its own instance-name, while the definition itself has one name.
Danā€™s code extracts the instance names, which have a certain nameā€¦

It actually finds the first match only,ā€¦ to return all matches use find_all, instead of find.

So itā€™s
instance name versus instance namesā€¦
:innocent:

This tips are same for Groups? Like search a especific group and rotate them.

Very similar for groups, because groups are disguised components.
That means they have definitions. And their definitions have a separate name attribute, than the group instances.

But there are a few quirks. The group.description method is an wrapper for group.definition.description. (So like a component instance, they share their definitionā€™s description attribute.)

So to find groups through the definition list, we need to filter out the definitions for images and normal components.

dlist = Sketchup.active_model.definitions
grps = dlist.find_all {|d| d.group? }
return if grps.empty? # test for empty array (not found)
  
gdef = grps.find {|d| d.name == "PocketDoor" }
if gdef # test for nil (not found)
  if !gdef.instances.empty?
    gdef.instances.find {|i| i.name == "PocketDoor - Master Bath" }
  else
    nil
  end
end

OK?

But you can also simplify the code by combining boolean arguments in the find and find_all blocks, and other test expressions:

dlist = Sketchup.active_model.definitions
gdef = dlist.find {|d| d.group? && d.name == "PocketDoor" }
if gdef && !gdef.instances.empty?
  gdef.instances.find {|i| i.name == "PocketDoor - Master Bath" }
else
  return nil
end

The find iterator will return nil if no match is found. (But be careful, as the find_all iterator always returns an array, so it will be an empty array if no matches are found.)

So to wrap it up in a method:

def find_group_by_name(
  definition_name = "Group#1",
  instance_name   = ""
)
  #
  if !definition_name.is_a?(String) || !instance_name.is_a?(String)
    raise(TypeError,"String arguments required.",caller)
  end
  #
  dlist = Sketchup.active_model.definitions
  gdef = dlist.find {|d| d.group? && d.name == definition_name }
  if gdef && !gdef.instances.empty?
    gdef.instances.find {|i| i.name == instance_name }
  else
    return nil
  end
  #
end ###
3 Likes