I wouldn’t try to subclass SketchUp’s entity classes. The API methods that gives you a reference to a group, e.g. from the selection, gives a reference to an object of the type defined in the API.
What you can do is to create your own stud class, and have an instance variable pointing to the corresponding Sketchup::Group. The stud object represent the stud as an idea, and defines all behavior related to the stud concept. The corresponding group is the physical/visual representation of the stud, but not the stud per se. This gives a nice separation of your conceptual object (stud) and SketchUp’s “physical” object (a group containing some faces and edges).
I typically have a superclass for all classes that represents objects that can be drawn in the model. This class defines methods for serializing custom objects and save them to SketchUp entities, as well as to later revive these custom objects from said entities.
Here’s an example of a scalable implementation:
class Serializable
# In this example all serializable objects are represented as groups in the
# model.
attr_accessor :group, :name
# Edit this. I typically reference a PLUGIN_ID constant defined in plugin
# loader as the basename of the plugin loader file (same as the plugin
# dirname).
DICT_NAME = "my_extension".freeze
ATTR_CLASS_NAME = "type".freeze
def initialize(group = nil)
@group = group
read_attributes if group
end
# Write instance variables as attributes to @group.
#
# @return [Void]
def write_attributes
class_base_name = self.class.name.split("::").last
@group.set_attribute(DICT_NAME, ATTR_CLASS_NAME, class_base_name)
@group.name = @name
instance_variables.each do |var_name|
# Purge leading @ from key.
key = var_name.to_s[1..-1].to_sym
next if key == :name
next if key == :group
@group.set_attribute(DICT_NAME, key.to_s, instance_variable_get(var_name))
end
nil
end
# Read attributes saved to @group and assign them as instance variables.
#
# @return [Void]
def read_attributes
@group.attribute_dictionaries[DICT_NAME].each_pair do |key, value|
next if key == ATTR_CLASS_NAME
# Prefer public attribute writer method over just setting the instance
# variable, as setting some attributes may have side affects, like
# updating other values or parsing into objects used internally.
setter_name = "#{key}=".to_sym
send(setter_name, value) if respond_to?(setter_name)
end
@name = @group.name
end
end
class Stud < Serializable
# Sett attr_accessors for length, width, height, start, end etc.
def draw
# Create a @group if not defined, or deleted.
# Set group transformation according to instance variables for position.
# Set group scale flag (if needed).
# Call write_attributes.
# Clear group.
# Draw anew into group according to the instance variables.
end
end
You can then create a new stud, give it some attributes, draw it, and at a later time read it, change some attributes and then redraw it.
stud = Stud.new
stud.length = 3.m
stud.width = 5.cm
stud.draw
# Later...
stud = Stud.new(Sketchup.active_model.selection.first)
stud.length = 7.m
stud.draw