My context menus are working fine however if a user of the plugin right clicks on a line (not a group or component) an error gets thrown in the Ruby console.
My code is:
unless file_loaded?(File.basename(__FILE__))
UI.add_context_menu_handler do |context_menu_medeek1|
if Sketchup.active_model.selection[0].name.include?('TRUSS_ASSEMBLY_')
# context_menu_medeek1.add_separator
context_menu_medeek1.add_item("Edit Truss Assembly") {
# UI.messagebox("#{MDK_TRUSS} Assembly - Editing coming soon...")
Sketchup.load(File.join(this_dir,"MEDEEK_ROOF_TRUSS.rbs"))
Medeek_Engineering_Inc_Extensions::MedeekTrussPlugin::MedeekMethods.roof_truss_edit_menu pluginversion, pluginserial, pluginlang
}
end
end
UI.add_context_menu_handler do |context_menu_medeek2|
if Sketchup.active_model.selection[0].name.include?('RAFTER_ASSEMBLY_')
# context_menu_medeek2.add_separator
context_menu_medeek2.add_item("Edit Rafter Assembly") {
UI.messagebox("#{MDK} Rafter Assembly - Editing coming soon...")
}
end
end
UI.add_context_menu_handler do |context_menu_medeek3|
if Sketchup.active_model.selection[0].name.include?('FLOOR_ASSEMBLY_')
# context_menu_medeek3.add_separator
context_menu_medeek3.add_item("Edit Floor Assembly") {
# UI.messagebox("#{MDK} Floor Assembly - Editing coming soon...")
Sketchup.load(File.join(this_dir,"MEDEEK_FLOOR_TRUSS.rbs"))
Medeek_Engineering_Inc_Extensions::MedeekTrussPlugin::FloorTruss::MedeekMethods.floor_truss_edit_menu pluginversion, pluginserial, pluginlang
}
end
end
end
The error is:
Error: #<NoMethodError: undefined method `name' for #<Sketchup::Edge:0x0000000fee9e68>>
c:/users/administrator/appdata/roaming/sketchup/sketchup 2017/sketchup/plugins/medeek_truss_ext/medeek_load.rbs:314:in `block in <module:MedeekTrussPluginModuleLoader>'
SketchUp:1:in `call'
Error: #<NoMethodError: undefined method `name' for #<Sketchup::Edge:0x0000000fee9e68>>
c:/users/administrator/appdata/roaming/sketchup/sketchup 2017/sketchup/plugins/medeek_truss_ext/medeek_load.rbs:329:in `block in <module:MedeekTrussPluginModuleLoader>'
SketchUp:1:in `call'
Error: #<NoMethodError: undefined method `name' for #<Sketchup::Edge:0x0000000fee9e68>>
c:/users/administrator/appdata/roaming/sketchup/sketchup 2017/sketchup/plugins/medeek_truss_ext/medeek_load.rbs:341:in `block in <module:MedeekTrussPluginModuleLoader>'
SketchUp:1:in `call'
Obviously the issue is that there is no name parameter associated with certain geometry.
I need to make my conditional probably first determine whether this is a group or not. I just wanted to put this out there so that I don’t inadvertently create something that somehow bogs down the model or SketchUp.
Context menus are not something I deal with on a daily basis so I’m trying to avoid beginner errors.
You do not need 3 separate context menu handler blocks. One will do.
You need not qualify the block menu object reference as it is local to the block and will not ever clash with any other reference. (And your handlers should always be within your coding namespaces (modules and classes, so there is no need to worry about clashing references here.)
Menu item object command blocks should always call a method so that you can tweak the code (as you develop it,) and simply reload the code that redefines the command’s method.
The way you’ve organized this the commands are dependent upon the load, so should be wrapped in a begin ... rescue ... else clause.
module Medeek_Engineering_Inc_Extensions::MedeekTrussPlugin::FloorTruss
extend self
def edit_menu(menu_symbol, filename, version, serial, language)
begin
Sketchup.load(File.join(__dir__,filename))
rescue
raise
else
MedeekMethods.send( menu_symbol, version, serial, language )
end
end
unless file_loaded?(File.basename(__FILE__))
UI.add_context_menu_handler do |context_menu|
selection_set = Sketchup.active_model.selection
if selection_set.single_object?
if selection_set.first.respond_to?(:name)
obj_name = selection_set.first.name
if obj_name.include?('TRUSS_ASSEMBLY_')
context_menu.add_item("Edit Truss Assembly") {
edit_menu(
:roof_truss_edit_menu,
"MEDEEK_ROOF_TRUSS.rbs",
pluginversion, pluginserial, pluginlang
)
}
elsif obj_name.include?('RAFTER_ASSEMBLY_')
context_menu.add_item("Edit Rafter Assembly") {
edit_menu(
:rafter_edit_menu,
"MEDEEK_RAFTER.rbs",
pluginversion, pluginserial, pluginlang
)
}
elsif obj_name.include?('FLOOR_ASSEMBLY_')
context_menu.add_item("Edit Truss Assembly") {
edit_menu(
:floor_edit_menu,
"MEDEEK_FLOOR.rbs",
pluginversion, pluginserial, pluginlang
)
}
end
end # group and component handling
# Handle other kinds of objects here ...
end # single object selected
# Handle multiple selections of objects here ...
end # context menu handler block
end # run once upon first load block
end # wrapping namespaces
Indexing without knowing whether an element exists at that index! One of the most common error sources.
The return value of Array#[](index) is [Object, nil], either an object or nil. Your code must handle both cases, or the second case must be provable impossible (because in every possible program flow, the array would have already an element in this position).
Similarly, Sketchup::Selection#[](index) returns [Sketchup::Drawingelement, nil], once checked whether it is not nil, you can call any method of drawing element, but you would still have to check whether it is a ComponentInstance.