sketchucation logo sketchucation
    • Login
    πŸ€‘ SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    OnElementAdded inside Group or Component

    Scheduled Pinned Locked Moved Developers' Forum
    4 Posts 2 Posters 489 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M Offline
      maricanis
      last edited by

      Hi,

      I've defined EntitiesObserver class to observe when new Face object is added to entities collection.

      class DLEntitiesObserver < Sketchup;;EntitiesObserver
          def onElementAdded( ents, new_ent )
              if new_ent.class == Sketchup;;Face 
                 puts "Face added #{new_ent}"
              end
          end
      end
      Sketchup.active_model.entities.add_observer(DLEntitiesObserver.new() )
      
      

      This code catches when Face is added directly in model, but doesn't catch when face is added inside some Group or Component instance.
      I tried to add another observer to catch when active path is changed and to attach observer to active_entities.

      
      class DLModelObserver < Sketchup;;ModelObserver
          def onActivePathChanged(model)
              Sketchup.active_model.active_entities.add_observer(DLEntitiesObserver.new())
          end
      end
      
      

      This catches faces added inside group, but when I open and close group multiple times it adds each time new observer -> so each new face is detected multiple times.

      I've tried to find solution on forum, but didn't have success (or used wrong keywords πŸ˜„.

      So my question is how to detect when new face is added in model, or inside any group, component instance, and how to detect that exactly once?

      Thanks in advance,
      Marija

      1 Reply Last reply Reply Quote 0
      • TIGT Offline
        TIG Moderator
        last edited by

        In the observer class code [outside of the 'def' methods], initially set up a hash as an enduring class variable...

        @@obs = {}

        Then in the method itself, remove any existing observer, so we never get more that one in each entities context...

        Sketchup.active_model.active_entities.remove_observer(@@obs[Sketchup.active_model.active_entities])

        It fails silently if there is not an observer to remove !

        Then add a new observer...

        @@obs[Sketchup.active_model.active_entities] = Sketchup.active_model.active_entities.add_observer(DLEntitiesObserver.new()

        This is untested, but it should give you the idea...

        TIG

        1 Reply Last reply Reply Quote 0
        • M Offline
          maricanis
          last edited by

          Thanks TIG,

          Your post give me the idea and after few modifications and tests code looks like this:

          
          class DLModelObserver < Sketchup;;ModelObserver
              @@observers = {}
          
              def onActivePathChanged(model)
                  #if active_path is nill (no group or component is opened)
                  #skip adding new observer to model entities - since it is added on startup
                  if !Sketchup.active_model.active_path
                      return
                  end
                  Sketchup.active_model.active_entities.remove_observer(@@observers[Sketchup.active_model.active_entities])
                  #define observer object and try to add it to active_entities
                  #if it is successfully added, update class variable @@observers
                  observer = DLEntitiesObserver.new()
                  if Sketchup.active_model.active_entities.add_observer(observer)
                      @@observers[Sketchup.active_model.active_entities] = observer
                  end
              end
          end
          
          

          It works correctly and each time only single observer is defined for active_entities.

          Thanks again,
          Marija

          1 Reply Last reply Reply Quote 0
          • M Offline
            maricanis
            last edited by

            Hi,

            I've been experimenting on adding/removing EntitiesObservers when groups/components are opened/closed, and I've found difference in behavior in old and new Sketchup versions.

            When I have few nested groups and I open/close them multiple times (without leaving top parent group):

            • Sketchup 8 and Sketchup 2013 - observers are added/removed as expected and each new entity is detected only once
            • Sketchup 2014 and Sketchup 2015 - it seems like observers aren't removed each time 'onActivePathChanged' is called (although in console is printed that they are removed). When I add new face inside some nested group it is detected multiple times. Number of times EntitiesObserver is called is increased each time I open/close some subgroup.
              Below it the code which is independent from my plugin and can be simply loaded in Sketchup for testing purposes:
            
            module DL;;Daylighting
            
            #Attach observers to model, entities and materials
            class DLAppObserver < Sketchup;;AppObserver
                def initializeObservers(model)
                    model_observer = DL;;Daylighting;;DLModelObserver.new()
                    model_observer.initializeObservers(model)
                    model.add_observer(model_observer)
                end
            	
                def onNewModel(model)
                    initializeObservers(model)
                end
                
                def onOpenModel(model)
                    initializeObservers(model) 
                end
            end
            
            class DLModelObserver < Sketchup;;ModelObserver
                @@observers = {}
                @@entitiesObserver = nil
            	
                def initializeObservers(model)
                    @@entitiesObserver = DL;;Daylighting;;DLEntitiesObserver.new()
                    model.entities.add_observer(@@entitiesObserver)
                end
            
                #When new group is opened remove old observers and add new observer for active_entities
                def onActivePathChanged(model)
                    puts "active path changed"
                    #remove all previous observers
                    @@observers.each_pair{|entities,observer|
                        begin
                            puts "***entities #{entities} remove observer #{observer}; #{entities.remove_observer(observer)}"
                        rescue Exception => e  
                            puts "Can't remove observer",e.message  
                            end
                    }
                    @@observers={}
            
                    #if all groups are closed -> don't add observers
                    if !Sketchup.active_model.active_path
                        return
                    end
                    entitiesObserver = DL;;Daylighting;;DLEntitiesObserver.new()
                    entities = Sketchup.active_model.active_entities
                    puts "***entities #{entities} add observer #{entitiesObserver}"
                    if entities.add_observer(entitiesObserver)
                        @@observers[entities] = entitiesObserver
                    end
                end
            end
            
            class DLEntitiesObserver < Sketchup;;EntitiesObserver
                def onElementAdded( ents, new_ent )
                    #detect only Sketchup;;Face entities
                    if new_ent.class == Sketchup;;Face 
                        puts "onElementAdded #{ents}; #{new_ent}"
                    end    
                end 
            end 
            
            end #DL;;Daylighting
            

            To attach these observers to the application just in call in Ruby console

            app_observer = DL;;Daylighting;;DLAppObserver.new()
            app_observer.initializeObservers(Sketchup.active_model)
            Sketchup.add_observer(app_observer)
            

            I don't understand what I'm doing wrong, because printed messages in ruby console show that old observer is always removed from entities when Active path is changed, but still new faces are detected multiple times.
            Once I leave all groups and go back to model (active_path=nil), all observers are like reset and I have only one EntitiesObserver.
            When I go inside groups and subgroups again, the number of observers increases again.

            And to repeat, in Sketchup 8 and Sketchup 2013 - this problem doesn't exist.

            Any suggestion is welcome, because I'm moving in circles with this observers.

            Thanks in advance,
            Marija

            1 Reply Last reply Reply Quote 0
            • 1 / 1
            • First post
              Last post
            Buy SketchPlus
            Buy SUbD
            Buy WrapR
            Buy eBook
            Buy Modelur
            Buy Vertex Tools
            Buy SketchCuisine
            Buy FormFonts

            Advertisement