Attaching arbitrary data to a model
-
Is there a way to attach what was once called a blob to a model? Perhaps I'm blind, but I'm just not seeing it. If not, is there some other magic method to accomplish something similar?
Cheers
-
model.set_attribute('MyLovelyBlob', 'some_key', value)
To read that key use:
val = model.get_attribute('MyLovelyBlob', 'some_key', nil)
Returnsnil
if not set.The
value
can be integer/float/length/string/boolean/array [array of any of the other types]Attributes can be set/got for most kinds of things in SketchUp - from the model itself down through collections and entities...
-
I interpret "blob" to mean "binary large object", that is, a sizeable chunk of otherwise opaque binary data. You might need to pack your blob into a Ruby type that set/get_attribute handles correctly. Test with specific examples to see whether what you have survives the round trip or needs to be packed.
-
If the 'blob' is actually binary data you can convert it with ruby into a string for the set_..., then convert it back to binary after the string is returned by the get...
There is a length limit for a single string attribute [~20000]...
Before the API introduced the ability to download a SKP [binary-file] from a URL, in the oldie system I invented a temporary fix using the then API, to allow you to do it by downloading/inserting a remote almost empty [binary] SKP and then extracting its special string attribute[s] and reworking them back into binary data - concatenating multiple strings into one if the max length was exceeded.
You then had an RBZ to install...RBZ2SKP [note: some references etc need setting initially !]
defn = model.definitions.add(File.basename(path)) ### make defn [if needed] defn.entities.add_cpoint([0,0,1]) ### so NOT empty data = File.open(path, "rb"){|io| io.read}.unpack('H*')[0] ### tidy up in case observers have added stuff ? defn.attribute_dictionaries.each{|attd| attd.keys.each{|k| attd.delete_key(k) } defn.attribute_dictionaries.delete(attd) } if defn.attribute_dictionaries ### divide up key = 'x0001' chunk = 20000 ### size limit start = 0 parts = data.length / chunk (parts + 1).times{ part = data[start..(start+chunk)] defn.set_attribute("RBZdata", key, part) start = start + chunk + 1 key.next! } ### save as SKP nname = File.basename(path).gsub(/^[^A-Za-z0-9._-]/, '').gsub(/[^A-Za-z0-9._-]/, '_') + '.skp' ### strip out leading # and all non A0Z etc as '_' skp = File.join(File.dirname(path), nname) defn.save_as(skp) defn.entities.clear!
SKP2RBZ [note again: you'll need to define some references and decide on the exact code !]
### after the SKP is added... defn = model.definitions[-1] return false unless defn ### reassemble attd = defn.attribute_dictionaries['RBZdata'] return unless attd data = '' attd.keys.sort.each{|key| data << defn.get_attribute('RBZdata', key, '') } datax = [data].pack('H*') ### fi = File.open(path,'wb') fi.write(datax) fi.close @model.start_operation('SKP2RBZ') defn.entities.clear! Sketchup.send_action("editUndo;") @model.commit_operation
You might be able to extract a 'blob' set/get from this...
-
Please forgive me. I was convinced that I'd already replied. This is exactly what I needed (and I'm further at a loss wrt how I didn't see that in the the API reference). Thanks very much
Advertisement