Good morning,
I wrote a class that places a component instance in the model. an observer is placed on the definition, and on the model.tool
This observer on onComponentInstanceAdded initiates a series of actions like opening a form and applying attribute.
Everything works well !
But if user chooses to cancel during form, I want the new placed instance to be cleared.
I can’t close the observers correctly before doing the undo.
I don’t know if I should, and in which case how to implement a begin rescue. I’ve done lots of iterations of different code, but I can’t find a solution to this crash.
I would like a helping hand and explanations so that I understand.
THANKS
module SimJoubert
module SJ_Pins
require 'securerandom'
### CLASSE PUNAISE DE POSITION
class SJDCA_Pins
attr_accessor :name, :position, :pid, :color, :pins_name
@@defpath = "D:/Sketchup/Composants/SJDCAnnimation/SJDCA_pins.skp"
@@defspy = nil
def initialize()
@uuid = SecureRandom.uuid
@name = "new pin"
@color = "red"
@pid
@position
@size
self.add_new_pin()
end
def add_new_pin()
# On verifie que la définition n'est pas déja chargée dans le model sinon on la charge
path = @@defpath
model = Sketchup.active_model
model.start_operation('add new pin',true,false,false)
definitions = model.definitions
cdef = nil
definitions.each do |d|
if d.path == path
cdef = d
break
end
end
if cdef == nil
cdef = model.definitions.load(path)
end
# On place un observer sur la définition quand une instance est ajouter
if @@defspy == nil
@@defspy = PlaceInstanceSpy.new(cdef, self)
cdef.add_observer(@@defspy)
end
# On place l'instance sur le contexte courant du model
model.place_component(cdef)
model.commit_operation
end
def delete_pin(instance)
#model = Sketchup.active_model
#model.commit_operation
#model.abort_operation
#instance.make_unique
#instance.erase!
return false
end
def new_pin_form_setting(definition, instance, title="Define new pin",default_name="New pine name",default_color="red")
pins_names = Sketchup.active_model.get_attribute("sjdca_pins","pins_names",[])
puts "Get model pins_names #{pins_names}"
# Formulaire
colors = Sketchup::Color.names
colors_options = colors.join("|")
prompts = ["Pins label", "Colors"]
defaults = [default_name, default_color]
list = ["",colors_options]
input = UI.inputbox(prompts, defaults, list, )
#Resultat formulaire
if input == false
#Annulation de l'opération
puts "anulation opération"
#self.delete_pin(instance)
return false
elsif (pins_names.include?(input[0])) == true
title = "#{input[0]} already existe, set a uniq name"
default_name = "New pine name must be uniq"
default_color = input[1]
self.new_pin_form_setting(definition, instance, title,default_name,default_color)
else
@name = input[0]
@color = input[1]
pins_names << @name
Sketchup.active_model.set_attribute("sjdca_pins","pins_names", pins_names)
self.new_pin_setting(definition, instance)
end
end
def new_pin_setting(definition, instance)
@pid = instance.persistent_id
instance.set_attribute("dynamic_attributes","itemcode",@pid)
instance.name = @name
instance.set_attribute("dynamic_attributes","description",@name)
instance.set_attribute("sjdca_pins","uuid",@uuid)
instance.set_attribute("sjdca_pins","name",@name)
#Application de la matiere
instance.material = @color
mat = Sketchup.active_model.materials.filter{|mat|mat.name == @color }[0]
unless mat == nil
instance.material = mat
end
# Placement de la punaise sur le calque SJDCA Pins
layer = Sketchup.active_model.layers.filter{|lay| lay.name == "SJDCA Pins"}[0]
if layer == nil
Sketchup.active_model.layers.add("SJDCA Pins")
end
instance.layer = layer
#On récupère sa position
@position = instance.transformation.origin.to_a.map{|p| p.to_m}
# edition du texte
ents = instance.parent.entities
ents_instance = instance.definition.entities
bb = instance. Bounds
point=Geom::Point3d.new(0, 0, (bb.depth))
vector = Geom::Vector3d.new(0, 0, (bb.depth)/2)
face = ents_instance.grep(Sketchup::Face).filter{|f| point.on_plane?(f.plane)==true}[0]
instance_path = Sketchup::InstancePath.new([instance,face])
text = ents.add_text("SJ DC Animation Pin\n#{@name}", [instance_path, point], vector)
text_layer = Sketchup.active_model.layers.filter{|lay| lay.name == "SJDCA Pins Label"}[0]
if text_layer == nil
Sketchup.active_model.layers.add("SJDCA Pins Label")
end
text.layer = text_layer
return true
end
end
# component placement event.
class PlaceInstanceSpy
def initialize(definition, parent)
@definition = definition
@parent = parent
# Attach this observer also to watch the tools collection
# because the active tool changes as the placement proceeds:
@definition.model.tools.add_observer(self)
end
def onComponentInstanceAdded(definition, instance)
# Set attributes on the definition or the instance here,
# # by calling a method in the parent module:
model = Sketchup.active_model
model.start_operation('pin setting',true,false,false)
status = @parent.new_pin_form_setting(definition, instance)
model.commit_operation
if status == false
Sketchup.undo
if instance.deleted? == false
instance.erase!
end
end
end #onComponentInstanceAdded
def onComponentInstanceRemoved(definition, instance)
name = instance.set_attribute("sjdca_pins","name",nil)
pins_names = Sketchup.active_model.get_attribute("sjdca_pins","pins_names",[])
if (pines_names.include?(name)) == true
pins_names.delete(name)
end
if instance.deleted? == false
instance.erase!
end
puts "onComponentInstanceRemoved(#{definition}, #{instance})"
end #fin onComponentInstanceRemoved
end#Fin Class PlaceInstanceSpy
end#fin module plugin
end#fin espace de nom auteur