[code] undoable place_component() "MoveTool" clone

Continuing the discussion from:

Model.place_component component_definition, boolean cannot be undone?:

Here is an example of a single undoable place component operation.

It is not a tool, rather it is a command.

It achieves the single undo, via 3 linked operations. The first is attached to the following model#place_component() operation, and the last is attached to it’s predecessor.

It can move both compound (groups, images and component instances,) and primitive objects.

move_selection_set.rb (1.8 KB)


# encoding: UTF-8

module Author; end
module Author::SomePlugin

  extend self
  
  @@loaded ||= false
  @@opname ||= "MoveObjects"
  
  class DefSpy < Sketchup::DefinitionObserver
    OUTER = Module::nesting[1]
    def onComponentInstanceAdded(definition, instance)
      definition.remove_observer(self)
      UI.start_timer(1.0,false) {
        OUTER::remove_definition(definition, instance)
      }
    end
  end

  def move_selection_set(sel)
    #
    choice = UI::messagebox("Erase original selection ?",MB_YESNO)
    #
    return if choice == IDCANCEL
    #
    mod  = sel.model
    ents = mod.active_entities
    mod.start_operation(@@opname,true,true)
      #
      cdef = mod.definitions[@@opname]
      if cdef
        cdef.clear! if cdef.entities.size > 0
        grp = cdef.entities.add_group(sel.to_a)
        t = grp.transformation
        grp.explode
        if choice != IDYES
          ents.add_instance(cdef,t)
        end
      else
        grp = ents.add_group(sel.to_a)
        ins = grp.to_component
        cdef = ins.definition
        cdef.name= @@opname
        if choice == IDYES
          ins.erase!
        else
          ins.explode
        end
      end
      #
    mod.commit_operation
    #
    cdef.add_observer(DefSpy::new)
    mod.place_component(cdef)
    #
  end ###

  def remove_definition(definition, instance)
    #
    mod = definition.model
    mod.start_operation(@@opname,true,false,true)
      #
      instance.explode rescue nil
      definition.entities.clear! rescue nil
      #
    mod.commit_operation
    #
  end ###


  if !@@loaded
    UI.add_context_menu_handler {|popup|
      sel = Sketchup.active_model.selection
      if !sel.empty?
        popup.add_item(@@opname) { move_selection_set(sel) }
      end
    }
    @@loaded = true
  end

end

Tested in SketchUp 2016.

1 Like