Wednesday, November 5, 2008

Storing and Retrieving with AttributeDictionary



The AttributeDictionary class allows you to store information into a SketchUp Entity. A good way to demonstrate this is to store camera settings into an object in an AttributeDictionary, then activate a context menu on the Entity to get these camera parameters and return to the same camera. This is also a great way to visualize important views in 3D space.

Our first method definition will create the camera geometry and put it into a group Entity. Then we will create an AttributeDictionary in the group and store the camera settings into the
AttributeDictionary.

We will start by getting the current camera parameters and storing them into variables:


def reveal_view
   m=Sketchup.active_model
   m.start_operation("reveal view")
   ents=m.entities
   view=m.active_view
   cam=view.camera
   up=cam.up
   target=cam.target
   persp=cam.perspective?
   fov=cam.fov
   eye=cam.eye
   focus_ray=Geom::Vector3d.new(eye,target)
   eye_axes=focus_ray.axes

Next, we'll make a simple representation of the camera, using the stored camera settings to determine the geometry,

   target_pointer = ents.add_cline(eye,target)
   eye_point = ents.add_cpoint(eye)
   target_point = ents.add_cpoint(target)
   circle = ents.add_circle(eye, focus_ray, 20, 8)

and store them into a group. For better organization, create a "cameras" layer and put the group into this layer. Also, be sure to lock the group, so the camera geometry can't move.

   camera_geom = []
   camera_geom.push(target_pointer,eye_point,target_point,circle)
   camera_geom.flatten!
   cam_group=ents.add_group(camera_geom)
   cam_group.name="camera"
   cam_layer=m.layers.add("cameras")
   cam_group.layer=cam_layer
   cam_group.locked=true


We will then be storing the camera settings into the AttributeDictionary called "is_a_camera".
Create the AttributeDictionary in the cam_group Entity:

   is_camera=cam_group.attribute_dictionary("is_a_camera", true)

The "true" indicates that the AttributeDictionary doesn't yet exist and needs to be created. AttributeDictionary objects store arbitrary amounts of key/value pairs. Add key/value pairs to AttributeDictionary for the camera settings,

   is_camera["cam"]=cam
   is_camera["up"]=up
   is_camera["target"]=target
   is_camera["persp"]=persp
   is_camera["fov"]=fov
   is_camera["eye"]=eye
   is_camera["focus_ray"]=focus_ray
   is_camera["eye_axes"]=eye_axes

and commit the undo operation.

   m.commit_operation
end

UI.menu("Plugins").add_item("reveal view"){reveal_view}


Finally, we add a context menu option to call a method only on objects which contain the AttributeDictionary "is_a_camera". If the AttributeDictionary exists, then the option "go to view" is added to the context menu.

UI.add_context_menu_handler do |menu|
   select_one=Sketchup.active_model.selection[0]
   if select_one.class==Sketchup::Group
      if select_one.attribute_dictionary("is_a_camera",false)!=nil
         menu.add_item("go to view"){go_to_view(select_one)}
      end
   end
end


When this is clicked, it calls the go_to_view() method. Our second method, go_to_view(), will take a selected Entity and recall the values stored in the AttributeDictionary "is_a_camera". It then uses these values to return to the stored camera position and settings.

def go_to_view(sel)
   info=sel.attribute_dictionary("is_a_camera")
   m=Sketchup.active_model
   view=m.active_view
   view.camera=Sketchup::Camera.new(info["eye"],info["target"],
      info["up"],info["persp"],info["fov"])
end