sketchucation logo sketchucation
    • Login
    🤑 SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    Observers work differently depending on how Sketchup starts?

    Scheduled Pinned Locked Moved Developers' Forum
    9 Posts 3 Posters 1.2k Views 3 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.
    • S Offline
      spring.freediver
      last edited by

      Has anyone else seen this:

      We have a plugin which uses observers. It also stores attributes in the model.

      If we start Sketchup by selecting the desktop icon, and then open a model with our attributes in it, everything works fine.

      However, if we start Sketchup by double-clicking on the model name in explorer, the model opens, and our tools are present, but they do not work correctly. Our attributes are present in the model, but observer callbacks which use the attributes do not work.

      We have Sketchup::AppObservers set up for both onNewModel and onOpenModel events, but in the second case described above, they don't seem to be triggered.

      Thanks for any help.

      1 Reply Last reply Reply Quote 0
      • Dan RathbunD Offline
        Dan Rathbun
        last edited by

        Yes old problem...

        AND... it's quite clear in the text of the API dictionary:

        @unknownuser said:

        (https://developers.google.com/sketchup/docs/ourdoc/appobserver#onOpenModel)":2oo7mjja]

        NOTE: If a skp file is loaded via the command line or double-clicking on a skp in explorer (which is also is the command line) then this observer will not be called. The Ruby interpreter in SketchUp is initialized after command line processing so the observer won't be added in time to get the notification.

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • Dan RathbunD Offline
          Dan Rathbun
          last edited by

          OK here's a brainstormin' session for a workaround:

          1) Assume each time Sketchup starts, it gets a different process id (during a certain time frame, likely 24 hours, if your computer is always on.)

          2) This pid is stored in the Ruby global $$ or you can call: Process.pid()

          3) You can get the time via Time.now()

          4) Your plugin has it's AttributeDictionary attached to the model, so you can write a "secret" attribute (these usually begin with an underscore character,) for registering the fact of if the model has been "init'ed" with respect to your plugin.

          5) In your code, use a UI.start_timer block to check for a situation where a model has not been "init'ed" normally, with respect to your plugin. If not, the timer times out after say 20 seconds, and explicitly calls your AppObserver subclass instance's onOpenModel callback.
          In a normal situation, your code will stop the timer, before it times out.

          6) In both scenarios, you write a attribute value consisting of the date and the pid number to your "_inited" attribute.

          Challenges:

          a) What if the user closes a particular model, by opening another one, then opens the first model again manually ?

          • The date will be the same.* Sketchup's pid will still be the same.

          I'm not here much anymore.

          1 Reply Last reply Reply Quote 0
          • Dan RathbunD Offline
            Dan Rathbun
            last edited by

            I just thought of something else...

            .. users do not like it when a plugin modifies the model, when they have not made any manual changes.

            If they open a model just to view it, they expect to be able to close it, (or open another,) without being prompted to save the model.

            Be sure that any plugin settings you are saving within any model's attribute dictionary, is specific to THAT particular model.

            Any general plugin settings should instead be saved to a config file, or into the registry (Windows) or plist (Mac.)
            see: Sketchup # write_default()
            and: Sketchup # read_default()

            So in the previous post... strike out saving a "secret" attribute in a model's attribute dictionary, and instead save a attribute using write_default().

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • P Offline
              Pout
              last edited by

              We needed a Sceneobserver being attached whenever a model is openend (through the menu item or when double clicking a skp file in Windows Explorer.
              And did it like this:

              Ath the end of the ruby file:

              PRODUCE.sceneobserver
              # Observer that watches the application for opening of models from the file menu and creates scenes observer automatically.
                   class MyAppObserver < Sketchup;;AppObserver
                     def onOpenModel(model)
              			PRODUCE.sceneobserver
                 end
              end
              

              This handles both possibilities.
              Now to avoid creating 2 observers just check if there is already an observer present

              
              def PRODUCE.sceneobserver #add the scene observer after PRODUCE.scenes or when scenes need to be reloaded
              	#
              	if ($xDframesobserverid==nil or $xDframesobserverid=='') #no frame observer existing or it has been removed
              	#UI.messagebox ('make observer')
              		$xDframesobserverid=Sketchup;;Pages.add_frame_change_observer(XdFrameObserver.new) 
              	end
              end
              

              Hope this helps

              1 Reply Last reply Reply Quote 0
              • Dan RathbunD Offline
                Dan Rathbun
                last edited by

                Cleaned up examples:
                (1) Using global variables for a certain plugin is a no-no (use module variables instead.)
                (2) Defining "author" or specific plugin classes at within Object is a no-no (define them within an author or company module namespace.)
                (3) Class and module identifiers should be CamelCase. Constants should be ALLCAPS.

                module Pout; end
                module Pout;;Produce
                
                  # Declare module variables at top of module;
                  @@xDframesobserverid==nil
                
                  # Observer that watches the application for opening
                  # of models from the file menu and creates scenes
                  # observer automatically.
                  class ProduceAppObserver < Sketchup;;AppObserver
                    def onOpenModel(model)
                      Pout;;Produce.sceneobserver
                    end # callback
                  end # class
                
                  # at end of module;
                  Sketchup.add_observer( ProduceAppObserver.new )
                
                end # module
                

                Now to avoid creating 2 observers just check if there is already an observer present:

                module Pout;;Produce
                
                  # define a Frame Change Observer
                  class XdFrameObserver
                    def frameChange(fromPage,toPage,percent_done)
                      # respond depending on float value of percent_done
                    end # callback
                  end # class
                
                  def self.sceneobserver()
                    #
                    # Add the scene observer after Pout;;Produce.scenes(),
                    # or when scenes need to be reloaded.
                    #
                    if (@@xDframesobserverid==nil or @@xDframesobserverid=='')
                      # No frame observer existing or it has been removed
                      @@xDframesobserverid=Sketchup;;Pages.add_frame_change_observer(XdFrameObserver.new) 
                    end # if
                  end # def method
                
                end # module Pout;;Produce
                

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • Dan RathbunD Offline
                  Dan Rathbun
                  last edited by

                  @pout said:

                  This handles both possibilities.

                  The API docs say this won't work... because the file is already open (on PC,) by the time the AppObserver gets loaded.

                  Are you sure it works on PC ??

                  On the Mac, the model is opened AFTER all the scripts are processed.

                  I'm not here much anymore.

                  1 Reply Last reply Reply Quote 0
                  • P Offline
                    Pout
                    last edited by

                    Dan,

                    I have done some testing with this and it seems to work yes.

                    Thx for cleaning up the script!

                    1 Reply Last reply Reply Quote 0
                    • P Offline
                      Pout
                      last edited by

                      @dan rathbun said:

                      The API docs say this won't work... because the file is already open (on PC,) by the time the AppObserver gets loaded.

                      Dan,
                      In my script:
                      When double-click on SU file

                      1. opening the model in SU
                      2. execute PRODUCE.sceneobserver (automatically)
                      3. A Appobserver is also created (which fires PRODUCE.sceneobserver again, but since there already is an observer there is no new one created)
                      4. When a model is then opened from the file menu the Appobserver is called

                      Logically and after testing this seems to work ok.

                      My code here is not complete though, since in my code there is another check to see if the framobserver must be created or not (depending if the opened model has some specific settings)

                      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