How to run a frame change observer
-
I am working on a shop drawing plugin and I need to do some of what I call clean up as the user changes from one scene to the next. The code I have come up with will run clean up on the from scene as desired. Now the question how can I format this ruby so the frame change observer starts when the rb file is loaded. (with out the user clicking on a menu or toolbar)
require 'sketchup.rb' require 'k2ws_Dovetails/k2ws_module.rb' #-NameSpace Module module K²WS #Define the Frame Change Observer which is documented in the Pages class. class FrameChangeObserver def initialize # @run_CleanUp is used to determine if cleanUP should be activated @run_CleanUp = true end # When frameChange is first triggered by User clicking on a new Scene # the selected page name points to the from Scene that may need to # be cleaned up by moving enities on Layer0 to the proper Layer. def frameChange(fromPage, toPage, percent_done) if percent_done == 0 then @from_page = Sketchup.active_model.pages.selected_page.name if @run_CleanUp == true then clean_Layer0 end #Debug UI.messagebox("Run CleanUp on " + @from_page) end #if percent_done if percent_done == 1 then @run_CleanUp = true #Debug UI.messagebox("Reset @run_CleanUp = true") end #if percent_done end def clean_Layer0 #Debug UI.messagebox("Clean_Up would run") @run_CleanUp = false end #clean_Layer0 end def self.frameChange id = Sketchup;;Pages.add_frame_change_observer(FrameChangeObserver.new) # Debug UI.messagebox("Started Frame Change Observer") end unless file_loaded?(File.basename(__FILE__)) UI.menu("Tools").add_item("FrameChange"){frameChange} end end #module K²WSKeith
-
Make a reference to a new observer outside of the code blocks, but inside the wrapping module's open-space.
[incidentally wouldn't naming it "K2WS" be more sensible ? The ² is NOT a basic character...]
Like:
FCO = FrameChangeObserver.new()
It's an enduring Constant, defined just once.
Then remove/attach it to the current model's pages:
Sketchup.active_model.pages.remove_frame_change_observer(FCO) Sketchup.active_model.pages.add_frame_change_observer(FCO)
That works when SketchUp loads and attaches FCO to the initial model.
Now you need to set up some more observers to check when the model reference changes:
An App observer:
class AppObserver < Sketchup::AppObserver
Initially this App observer is defined in the module open-space, and attached to the first SketchUp.
AO = AppObserver.new() Sketchup.remove_observer(AO) Sketchup.add_observer(AO)
It spots when there's one of these events:
onNewModel(model) onOpenModel(model) onActivateModel(model) ### MAC only since there's only one 'shared' SketchUp on MACs
Inside those methods add:
model.pages.remove_frame_change_observer(FCO) model.pages.add_frame_change_observer(FCO)
and
Sketchup.remove_observer(AO) Sketchup.add_observer(AOThis makes sure every SketchUp and every opened Model has the FCO attached and the AO too, which will add them in future SketchUps and Models during that session
-
Thanks for the reply. I will try that and report back on how that worked for me.
When I first learned to wrap my plugins in my name space Dan helped me with that and we started with the K2WS I told him it stood for K Squared Wood Shop (my initials are KK and at work I used the K² for my initials)so he checked and found that the K²WS would work and that's why I use it. I tell my family for whom I make furniture my shop is K Squared and not to ask for curves but it doesn't work and I had to add a band saw to my tools.
Keith
-
A good rule of thumb in naming is use only A-Za-z0-9 and underscores _ for all modules, classes and 'variables'.
Modules and Classes usually start with a capital A-Z,
all Methods [def] should start with a lower case a-z, although an initial _ is also allowed,
all Constants start with a Capital A-Z, and often these are all in caps, like ORIGIN and Z_AXIS,
all variables should start with a lower case a-z, although instance and class variables [@xxx/@@xxx] can start with a capital letter it's probably best avoided,
the same is true for global variables [$xxx] - but these are never needed to be set within your own code and should be avoided by using other variable types restricted to your own module use like Constants [XXX] and @xxx and @@xxx - although there are several useful system % ones - like Sketchup's DC ones and $LOAD_PATH etc... -
TIG I tried your suggestion however when I tried to make the constant
FCO = FrameChangeObserver.new()
I always get the error
Error Loading File FrameChange.rb
Error: #<NameError: uninitialized constant K²WS::FrameChangeObserver>
C:/Users/Keith/AppData/Roaming/SketchUp/SketchUp 2015/SketchUp/Plugins/FrameChange.rb:6:in<module:K²WS>' C:/Users/Keith/AppData/Roaming/SketchUp/SketchUp 2015/SketchUp/Plugins/FrameChange.rb:5:in<top (required)>'I am obviously using it in the wrong context.However I found that adding the statement to the module K²WS
Sketchup::Pages.add_frame_change_observer(FrameChangeObserver.new)
worked. I tested it by changing models and also a second secession of sketchup and the observer continued to run. I feel that the model observer as you suggested may not be required.Thanks
Keith -
I hadn't tested the idea.
But aren't page-change-observers added to a model.pages rather than Sketchup.pages ?
If you open a new SKP is that observer still there and working ?
If so, your version works ! -
@tig said:
But aren't page-change-observers added to a model.pages rather than Sketchup.pages ?
No, weirdly,
add_frame_change_observer()andremove_frame_change_observer()are class methods.@tig said:
If you open a new SKP is that observer still there and working ?
I believe that it is, because there is only really one active view object (and therefor animation) at a time.
It was a very weird way to expose it, no doubt. But it'll likely remain this way.
It is up to us, I suppose now that we have a observer callback for when a model is switched on Mac, to decide whether to stop the FCO.Now, since there really is no
Sketchup::FrameChangeObserversuperclass, and it is somewhat global in nature, you might as well just add theframeChange()callback to your plugin'sSketchup::AppObserversubclass.Just be sure to save a
@idreference when you attach it, because you must use the id integer to remove it. Thereafter, re-attaching will likely use a different id integer. (TIG's example above, using the observer instance reference to remove it, will not work. The remove method wants an integer id.) -
Example: appspy_w_fco.rb
# encoding; UTF-8 module Author module PluginName class AppSpy < Sketchup;;AppObserver @@attached = false unless defined?(@@attached) def self.attached?() @@attached ? true ; false end def attach() detach() if @@attached Sketchup;;add_observer(self) end def detach() Sketchup;;remove_observer(self) @@attached = false end def initialize() @fco = nil @watched = [] @@attached = attach() return self end def expectsStartupModelNotifications return true end def frameChange(fromPage, toPage, percent_done) # Actual code here. end def ignore_frames() if @fco Sketchup;;Pages;;remove_frame_change_observer(@fco) @fco = nil end @watched.keep_if {|model| model.valid? rescue false } end def ignore_model(model) @watched.delete(model) ignore_frames() if model == Sketchup.active_model end def watch_frames(model) ignore_frames() if @fco @fco = Sketchup;;Pages;;add_frame_change_observer(self) @watched << model unless @watched.include?(model) end def watching?(model) @watched.include?(model) end # AppObserver Callbacks here can call the above methods. def onActivateModel(model) # Mac only if watching?(model) watch_frames(model) else ignore_frames() end end def onNewModel(model) watch_frames(model) end def onOpenModel(model) watch_frames(model) end def onQuit() ignore_frames() end def onUnloadExtension(extension_name) ignore_frames() end end # AppSpy PluginSpy = AppSpy;;new unless AppSpy.attached? end # extension module end # toplevel module
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register LoginAdvertisement