Dynamic Components reacting to Scene (aka Page) changes
-
Hi All,
I just wrote a blogpost about Dynamic Components reacting to scene changes.
You can find it at http://sketchupapi.blogspot.com/2009/07/dynamic-components-that-react-to-scene.html
enjoy.
Simone. -
That's great, thanks Simone! I'll look it over when I get a chance, but it sounds quite interesting.
Chris
-
Here is an sample file that Simone created.
After installing the script and opening SU and the .skp file, click on each scene to see what it looks like.
Then add any geometry to the model and replay the scenes and observe what a scene then displays.I think you can see the possibilities for creating "triggers" to a model.
-
That is cool. Thanks Simone
-
the plugin works perfectly. But I would like to add the ability to input values for scene changes.
I added code first :menu = UI.menu("PlugIns").add_item("Scenes") { prompts = ["looping scene ? "] input = UI.inputbox prompts $sOptions_scenes=input }
you can now set the number of scenes in the cycle
and changed the code:attributes[SCENE_TRIGGER] = (((attributes[SCENE_TRIGGER].to_i+1)%5)).to_s
...to this:
scene_loop = [$sOptions_scenes].to_i attributes[SCENE_TRIGGER] = (((attributes[SCENE_TRIGGER].to_i+1)%scene_loop)).to_s
unfortunately the last piece of code does not work
Can someone suggest a solution ?
Here's the entire code of the modified plugin:#useful constants # Copyright 2005-2008, Google, Inc. # Permission to use, copy, modify, and distribute this software for # any purpose and without fee is hereby granted, provided that the above # copyright notice appear in all copies. # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # This code snippets allows you to have Dynamic Components # that modify themselves based on a Scene Change # # They need to have at the top level the following attributes # "scene_change" a boolean value that if true force the DC to react to scene changes # and if false has the DC ignore the scene change # and # "scene_trigger" which is the index that is incremented every time there is a scene change and # it is used to change attributes for the DC. # Attach our observer. menu = UI.menu("PlugIns").add_item("Scenes") { prompts = ["looping scene ? "] input = UI.inputbox prompts $sOptions_scenes=input } # Copyright 2005-2008, Google, Inc. # Permission to use, copy, modify, and distribute this software for # any purpose and without fee is hereby granted, provided that the above # copyright notice appear in all copies. # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # This code snippets allows you to have Dynamic Components # that modify themselves based on a Scene Change # # They need to have at the top level the following attributes # "scene_change" a boolean value that if true force the DC to react to scene changes # and if false has the DC ignore the scene change # and # "scene_trigger" which is the index that is incremented every time there is a scene change and # it is used to change attributes for the DC. # # # Author; Simone Nicolo require 'sketchup.rb' # Define the Frame Change Observer which is documented in the Pages class. class FrameChangeObserver def initialize # @current page is used to make sure that the observer is only triggered by page changes # This is to workaround the PC bug that does not correctly populate the fromPage variable in the # callback to frameChange. @current_page = Sketchup.active_model.pages.selected_page end # Callback triggered by the Frame change observer. # fromPage is populated with the page we were coming from, toPage is # populated with the page we were transitioning to # and percent done contains the percentage of the transition that # has completed. def frameChange(fromPage, toPage, percent_done) # If there has been a page change and it has completed if (not toPage.nil? and percent_done == 1) then if @current_page != toPage then #update the current page @current_page = toPage #find the DCs that need redrawing, and redraw them. find_dc_for_redraw end end end # This function finds all the DC's that need to be redrawn based on a scene transition and # on the boolean scene_change attribute if scene_change is true, change and redraw # the DC on a scene transition, if it is false do not change or redraw the DC. def find_dc_for_redraw entities_list = Sketchup.active_model.entities if entities_list != [] # For all the entities in the model entities_list.each do |item| type = item.typename case type # Find the Dynamic Component instances when "ComponentInstance" if not item.attribute_dictionaries.nil? attributes = item.attribute_dictionaries[DICTIONARY_NAME] # If they have a scene_change attribute that contains true if (not attributes.nil? and attributes[SCENE_CHANGE] == 1.to_s) # Increment the scene_trigger attribute. # Here we are allowing the scene trigger attributes to only have the values # 1, 2, 3, and 4. scene_loop = [$sOptions_scenes].to_i attributes[SCENE_TRIGGER] = (((attributes[SCENE_TRIGGER].to_i+1)%scene_loop)).to_s if attributes[SCENE_TRIGGER] == "0" then attributes[SCENE_TRIGGER] = 1.to_s end # Redraw the DC using the $dc_observers global variable. $dc_observers.get_latest_class.redraw_with_undo(item) end end end end else UI.messagebox("There are no entities in this model!") end end end if not file_loaded? 'scenes.rb' # Useful constants # Dynamic Components dictionary name DICTIONARY_NAME = "dynamic_attributes" # Boolean attribute that turns on and off the reaction to a scene change for the DC SCENE_CHANGE = "scene_change" # Index attribute for the DC that is used to drive changes in the DC. SCENE_TRIGGER = "scene_trigger" # Attach the frame chage observer to the global Pages object. id = Sketchup;;Pages.add_frame_change_observer(FrameChangeObserver.new) file_loaded 'scenes.rb' end
-
(1) It is NOT a plugin, it is a code example.
(2) It is NOT a very good example. (It was written long ago when Simone was new at Ruby.)
Because:
It defines plugin specific objects at the toplevel "main" instance of
Object
. This includes constants and classes.It needs to be totally overhauled. (I see at least 1 bug in it.
entities_list != []
will always betrue
because it is not anArray
(or subclass,) object.)Your modifications also violate community rules. Your creating a global var for use with only 1 plugin.
Please explain more specifically what you want to change with an inputbox ?
-
Dan, thank you for taking the time to answer my question
In the source code in line :# Here we are allowing the scene trigger attributes to only have the values # 1, 2, 3, and 4. attributes[SCENE_TRIGGER] = (((attributes[SCENE_TRIGGER].to_i+1)%5)).to_s
determined how many scenes will loop. I would like to change this setting without changing the code. For this I am trying to use the InputBox. Вut my knowledge is not enough. can you help me ?
P.S. Sorry for my English, I use Google translator -
The whole example STILL needs an overhaul... but for now:
UI.inputbox
returns an array of values, even if there is only 1 input item.$sOptions_scenes[0]= "5" $sOptions_scenes[1]= 5 menu = UI.menu("PlugIns").add_item("Scenes") { prompts = ["looping scene ? "] input = UI.inputbox( prompts,[$sOptions_scenes[1]], "Enter Scenes" ) rescue [$sOptions_scenes[1]] $sOptions_scenes[0]=input[0].to_s $sOptions_scenes[1]=input[0] }
and further down:
scene_loop = $sOptions_scenes[0].to_i
EDIT: DC redraws when the limit is reached, and trigger is reset to 0.
-
Dan , thanks for your help. I will study it.
Advertisement