We are currently working on a sun study for a new home. We know how to create an animation just fine, however, we now wish to include a time stamp within the animation so the client can see the time and date while viewing it so they can see the sun position at any given time and date. Has anyone been able to do something this?
It’s not a feature that you may have overseen in the animation export or in the scenes inspector. You could think of it like a “screen text” (or “note”) that updates whenever the time or date changes.
For such specific needs, SketchUp has been made extensible, and you can use the following short script as an extension. Paste it in Window → Ruby Console or paste it in an empty plain text (txt) file with file extension .rb and save it in the Plugins folder.
You can move the text using the move tool. Do you need a specific time format?
module AE
module DynamicTimestamp
def self.add_timestamp(model)
time = model.shadow_info["ShadowTime"]
string = time.strftime("%Y-%m-%d %H:%M:%S")
note = model.add_note(string, 0.8, 0.99)
observer = TimeObserver.new(note)
model.shadow_info.add_observer(observer)
end
class TimeObserver < Sketchup::ShadowInfoObserver
def initialize(entity)
@entity = entity
end
def onShadowInfoChanged(shadow_info, type)
if type == 0 && @entity.valid? # time / date sliders
time = @entity.model.shadow_info["ShadowTime"]
string = time.strftime("%Y-%m-%d %H:%M:%S")
@entity.text = string
end
end
end # class TimeObserver
unless file_loaded?(__FILE__)
command = UI::Command.new("Add Timestamp"){
self.add_timestamp(Sketchup.active_model)
}
UI.menu("Plugins").add_item(command)
file_loaded(__FILE__)
end
end # module DynamicTimestamp
end # module AE
I’m was really excited to find your response because I’m trying to do a similar thing. I’d like to display a real-time count of instances of components, along with some other information. I’m new to using Ruby, and using Ruby with SketchUp, so I was trying to puzzle your code out.
Could you explain your TimeObserver class? I’m mostly confused about the following:
def initialize(entity)
@entity = entity
end
and
time = @entity.model.shadow_info["ShadowTime"]
string = time.strftime("%Y-%m-%d %H:%M:%S")
@entity.text = string
These seem like they might be crucial to having one updating note, instead of an endless amount of new notes on top of each other.
It is not very clear to me what is unclear to you because I don’t know what you tried to do or what confuses you.
If you get an endless amount of new notes, your code probably creates a new note entity every time the observer is notified about a change of the observered property. That’s why we need to have a reference to the one single note (that we create once when the tool is launched) and just change its text.
By passing the note entity into the constructor of the observer, we tell the observer which note entity to update (and the observer does not need to create any note entities).
def initialize(entity)
@entity = entity
end
When the update method of the observer is called, we can access the entity (because we saved it as an instance variable in the observer instance). We read the new value that we want to display and then apply it as the entity’s text.
In case of a components counter, the desired property is not in shadow info, but we would have to count either from the definitions list, or from a specific component’s instances list. Here the question which observer class to use depends on how you want the counter to work and what it should count (instances of which component, or of all). Potentially you would have to deal with several observers which makes it complicated.
On which event should the number be updated?
One could also simply use a selection observer, and if the selection has size==1 and is a component instance, you read the number of instances of the component and set it as the note’s text. You could even add the component’s name:
Thanks for your response - it was exactly what I was hoping for, especially the second paragraph.
I had a hunch that this was what I needed to do, but your explanation helps to confirm my conceptual understanding. I’m familiar with Java and C, somewhat, but the differences between those two languages (especially C, which is what I’m currently actively using) and Ruby was tripping me up. A local friend helped me understand your code at a syntax level; I think I get it now.
I’m in the middle of an apartment design project, and am attempting to write something simple that could display a real-time count of the number of each apartment unit type (each unit type as a component) on the screen, unwindowed (e.g. 1 bedroom = 5, 2 bedroom = 10, total units = 15). I was also thinking of keeping track of the square footages (per unit type, total). This way, I can glance at the numbers while I design, instead of stopping my thought process to manually count the units / calculate square footage, etc.
I was thinking of using a DefinitionsObserver, updating the entire note whenever a component was added or removed, and iterating over the entire definitions array (array?) to get each component’s count (or each relevant component’s count).
One thing that might be troublesome is when I have variations of a base component which I want to display as one type of component (e.g. components A1 = 2, A2 = 5, A3 = 3, B1 = 3, C1 = 1 to display as A = 10, B = 3, C = 1). I think I might be able to figure something out by looking at this, though!
thanks for the reply on this post. So i tried to do as you have mentioned here and would like to have some clarification since it doesn’t seem to work as expected for me. I pasted the code in ruby console and exported the animation. However, it shows a static time stamp. I would like to see a real time change in the time stamp depending on the shading time of each slide (although it is dynamic in the slides, it is static in the exported video). Also, the time stamp is UTC which I would ilke to change to my time zone. What should I do? TIA.
The plugin listens for changes of the shadow settings in the model. It looks like SketchUp’s animation exporter renders “off screen” without running the model through all scenes, thus the shadow info is not really changed. I wonder how animation plugins can make objects move in exported animations, when I change the ShadowInfoObserver to a FrameChangeObserver, it is also not triggered (maybe @thomthom knows more).
What you can do is to do a screen recording of that area of the screen and run the animation with View → Animation.
@Aerilius.
I have added this script, and the date stamp is showing up. However, it is not updating as the clock advances from scene to scene when I export an animation. It works fine in the model, but not in the exported video. The time stays constant, even as the sun moves.
time = model.shadow_info["ShadowTime"]
time.localtime("-08:00")
string = time.strftime("%Y-%m-%d %H:%M:%S")
The method for string formatting has also a %z flag to include the UTC offset literally, but that does not do a conversion. I believe the reason was that the shadow time did not include the time zone and setting it, the string formatter probably respects it by default.
I don’t know how to solve the animation export issue; if SketchUp’s animation exporter uses alternative, inconsistent way to animate shadows between scene transitions without updating shadow info, there is nothing to do. You could fallback to screen recording or taking a timed series of screenshots.