October 21st, 2008 | Published in Google SketchUp
Posted by Scott Lininger, SketchUp Engineer
Drawing foodstuffs in SketchUp is fantastically cool, but at the end of the day you wind up with a meal that is, sigh, static. You can push your food about manually, of course, or you can hide or change its appearance by using scenes, but wouldn't it be fun if there were a way to make it animate on its own?
There are many plugins out there to help you create certain kinds of animations (Sketchy Physics and Podium are a couple that come to mind), but what if you're a gastric megalomaniac? What if you want to animate food using Ruby and thus have TOTAL CONTROL?
Glad you asked. Let's sling some code (and some gouda).
Our Example: Black hole ate my cheese
We're going to write a ruby script that allows you to right-click on any component and suck it magically to the model origin. (The origin is where the red, green, and blue axes of your model intersect.) It will work on any component, but especially well on cheese, 'cause it's delicious.
Step 1: Create our "move" method
The first thing we need to realize our dream of ballistic curds is code that moves a component one step at a time toward a target. There are lots of ways to create these kinds of tweening animations. We're going to use a simple averaging method, where the object moves halfway toward the destination with each call...
blackhole.rb
# Define our method that does the transform.
def move_halfway_toward(entity, target_pt)
current_pt = entity.transformation.origin
halfway = Geom::Point3d.linear_combination(0.5, current_pt, 0.5,
target_pt)
# Undo our current transform with inverse,
# then move to the halfway point.
entity.transform! entity.transformation.inverse
entity.transform! Geom::Transformation.new halfway
# Invalidate our view to force SU to refresh the screen.
Sketchup.active_model.active_view.invalidate
end
# Create a rightclick handler that'll activate it.
UI.add_context_menu_handler do |context_menu|
context_menu.add_item('Move halfway to origin') {
entity = Sketchup.active_model.selection[0]
origin_pt = Geom::Point3d.new 0, 0, 0
move_halfway_toward(entity, origin_pt)
}
end
Create this new file called blackhole.rb, and save it in your SketchUp/Plugins directory. When you restart SketchUp, you can now right click on Bryce (or any other component), and activate our new command. Do it over and over again and you can start to visualize a wheel of cheddar blazing through space. (Insert evil laugh here)
Step 2: use UI.start_timer to provide a timeline
Now we add a bit more to make the method fire again and again and again, auto-magically. The secret is SketchUp's UI.start_timer method, which instructs the API to call a snippet of code on a regular basis.
blackhole.rb (add these to the bottom of the existing file)
# Define our method that starts an animation.
def start_animation(entity, target_pt)
# This calls our code snippet once every 10th of a second...
frames_per_second = 10.0
pause_length = 1.0 / frames_per_second
timer_id = UI.start_timer(pause_length, true) {
move_halfway_toward(entity, target_pt)
# If we're within an inch of the origin, turn off the timer.
new_location = entity.transformation.origin
distance_from_target = new_location.distance target_pt
if distance_from_target
UI.stop_timer timer_id
end
}
end
# Create a rightclick handler that'll activate it.
UI.add_context_menu_handler do |context_menu|
context_menu.add_item('Animate to origin') {
entity = Sketchup.active_model.selection[0]
origin_pt = Geom::Point3d.new 0, 0, 0
start_animation(entity, origin_pt)
}
end
Restart SU, download some cheese, and get to animating! If you're motivated, you could try these fun, extra credit assignments:
- Experiment with the frames_per_second to change the speed. (easy)
- Use UI.inputbox to ask for an X, Y, Z location to animate to. (medium)
- Send a raytest from the base of your cheese downward, to determine the nearest "ground" geometry, and have the cheese animate to land right on it! (tough)
- Use a custom tool to activate animations with a single click! (semi-soft, with a salty rind)