Ruby code to retrive sketchup version of a model
-
You need to read the start of the SKP to get its version, before you try to open it or try to load it...
This with get the SKP file's version - referenced as 'v' [string]vv=File.open(skp_path, 'rb'){|f| f.read }.unpack('m*').pack('m').gsub(/SketchUpModel/,'').to_i.to_s;if v=~/^1/;v=vv[0..1];else;v=vv[0];end
It could be greatly improved, but it works - tested in v2014/v2015 !
-
I find it interesting that model#save includes an argument to tell SketchUp what format to use when saving a model, but like @glro I can find no method to determine either the format that was in effect when the file was opened nor the format used the last time it was saved. Obviously, the data needs to be in the correct form for the running version of SketchUp while in memory, but if it can be converted on load and save, shouldn't the API remember these things?
-
I have to improve a lot to be able to understand such code...
i'll trythank you for your quick answer
@tig said:
You need to read the start of the SKP to get its version, before you try to open it or try to load it...
This with get the SKP file's version - referenced as 'v' [string]vv=File.open(skp_path, 'rb'){|f| f.read }.unpack('m*').pack('m').gsub(/SketchUpModel/,'').to_i.to_s;if v=~/^1/;v=vv[0..1];else;v=vv[0];end
It could be greatly improved, but it works - tested in v2014/v2015 !
-
@giro
here's a slightly different version I use, with a bit of explanation...# 'IO.read' reads the open model file's first '50' bytes # which we 'unpack' from binary using 'm' however many times '*' until we get to the end # we 'pack' these with 'm' to give a human readable string # then we use ruby 'sub' to substitute using a Regular expression '/\D+/' any non Digits with a nothing '' # of the remaining string, it's the first 2 digit we want to check '[0..1]' ver = IO.read(Sketchup.active_model.path, 50).unpack('m*').pack('m').sub(/\D+/,'')[0..1] # to check, we ask if the first '[0]' is a '1', if it is we use both, if not we only use it ver[0].to_i == 1 ? ver ; ver = ver[0] puts ver
john
-
I said it could be improved
-
Thank you both of you
my skills in ruby are very limited; using this code , i get in the ruby console:
"56" for a model made with SU8
"49" for a model made with SU13it's exactly what i was looking for
i shall make a test and filter the skps to process according to the number i getthanks again
@driven said:
@giro
here's a slightly different version I use, with a bit of explanation...# 'IO.read' reads the open model file's first '50' bytes > # which we 'unpack' from binary using 'm' however many times '*' until we get to the end > # we 'pack' these with 'm' to give a human readable string > # then we use ruby 'sub' to substitute using a Regular expression '/\D+/' any non Digits with a nothing '' > # of the remaining string, it's the first 2 digit we want to check '[0..1]' > ver = IO.read(Sketchup.active_model.path, 50).unpack('m*').pack('m').sub(/\D+/,'')[0..1] > # to check, we ask if the first '[0]' is a '1', if it is we use both, if not we only use it > ver[0].to_i == 1 ? ver ; ver = ver[0] > puts ver
john
-
My way should return "8" or "13" ?
Not sure what's happening... -
@sam, why would it return the octal char?
mmm... so should mine return '8' or '13' in your case...
but break it down and post the result...ver = IO.read(Sketchup.active_model.path, 50).unpack('m*').pack('m')
that should return the first 50bytes...
e.g.SketchUpModel151
if not try 100 for the bytes, maybe windows sees it differently?
john -
56 is the octal character value for "8" and 49 for "1". It is a function of V8 Ruby vs V14.
-
@driven said:
@sam, why would it return the octal char?
mmm... so should mine return '8' or '13' in your case...
but break it down and post the result...ver = IO.read(Sketchup.active_model.path, 50).unpack('m*').pack('m')
that should return the first 50bytes...
e.g.SketchUpModel151
if not try 100 for the bytes, maybe windows sees it differently?
johnAs I added to my previous post, it is the difference between Ruby 1.8 and 2.0. If you run Sketchup8 and enter your code you will get 56 returned. If you change the last line to Puts ver.chr, you will get 8.
glro is running V8, so TIG's code should be
vv=File.open(skp_path, 'rb'){|f| f.read }.unpack('m*').pack('m').gsub(/SketchUpModel/,'').to_i.to_s;if vv=~/^1/;v=vv[0].chr+v[1].chr;else;v=vv[0].chr;end
and yours
# 'IO.read' reads the open model file's first '50' bytes # which we 'unpack' from binary using 'm' however many times '*' until we get to the end # we 'pack' these with 'm' to give a human readable string # then we use ruby 'sub' to substitute using a Regular expression '/\D+/' any non Digits with a nothing '' # of the remaining string, it's the first 2 digit we want to check '[0..1]' ver = IO.read(Sketchup.active_model.path, 50).unpack('m*').pack('m').sub(/\D+/,'')[0..1] # to check, we ask if the first '[0]' is a '1', if it is we use both, if not we only use it ver[0].to_i == 1 ? ver ; ver = ver[0].chr puts ver
-
As I said in my first posted code - it was only tested in Ruby2 [v2014/2015]...
As @sdmitch says you need to do it slightly differently in <=v2013 - the vv[0] is NOT the character as it would be with >=v2014, but the 'octal' code which needs translating with.chr
...
For v8/2013 my version should then be:vv=File.open(skp_path, 'rb'){|f| f.read }.unpack('m*').pack('m').gsub(/SketchUpModel/,'').to_i.to_s;if vv[0].chr=='1';v=vv[0].chr+vv[1].chr;else;v=vv[0].chr;end
Then 'v' is the version as '8', '13', '14 or '15'.
For Sup versions >2013 [with Ruby2] you must omit all of the.chr
codes... -
so it is much more complex than what i thought i understood..
programming ruby for sketchup is a never ending game
thank you all for the details
-
unpack("m*").pack("m")
gobbles up some characters. Here's an old snippet I used in the past to sniff out the version number: (Works for Ruby 1.8 and 2.0)<span class="syntaxdefault"><br />module Example<br /><br /> def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">read_skp_version</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">file</span><span class="syntaxkeyword">)<br /> </span><span class="syntaxcomment"># Get the size of the file ID block;<br /> </span><span class="syntaxdefault">id_size </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">IO</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">read</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">file</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">1</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">3</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">unpack</span><span class="syntaxkeyword">(</span><span class="syntaxstring">'C'</span><span class="syntaxkeyword">)[</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">] * </span><span class="syntaxdefault">2<br /> </span><span class="syntaxcomment"># => 28<br /><br /> # Get the size of the file version block;<br /> </span><span class="syntaxdefault">version_size </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">IO</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">read</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">file</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">1</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">4 </span><span class="syntaxkeyword">+ </span><span class="syntaxdefault">id_size </span><span class="syntaxkeyword">+ </span><span class="syntaxdefault">3</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">unpack</span><span class="syntaxkeyword">(</span><span class="syntaxstring">'C'</span><span class="syntaxkeyword">)[</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">] * </span><span class="syntaxdefault">2<br /> </span><span class="syntaxcomment"># => 20<br /><br /> # Get the version block data. This will be UTF-16LE encoded. Since Ruby 1.8<br /> # doesn't have the encoding methods we hack it by zapping out all the zero bytes<br /> # in the data string which will give us a regular ASCII string. This works<br /> # because we know the version string is within the ASCII range.<br /> </span><span class="syntaxdefault">version </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">IO</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">read</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">file</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">version_size</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">4 </span><span class="syntaxkeyword">+ </span><span class="syntaxdefault">id_size </span><span class="syntaxkeyword">+ </span><span class="syntaxdefault">4</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">gsub</span><span class="syntaxkeyword">(</span><span class="syntaxstring">"\x00"</span><span class="syntaxkeyword">,</span><span class="syntaxstring">""</span><span class="syntaxkeyword">)<br /> </span><span class="syntaxcomment"># => {15.1.106}<br /><br /> # Extract the version components.<br /> </span><span class="syntaxdefault">version</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">match</span><span class="syntaxkeyword">(/\{(\</span><span class="syntaxdefault">d</span><span class="syntaxkeyword">+)\.(\</span><span class="syntaxdefault">d</span><span class="syntaxkeyword">+)\.(\</span><span class="syntaxdefault">d</span><span class="syntaxkeyword">+)\}/).</span><span class="syntaxdefault">captures</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">map </span><span class="syntaxkeyword">{ |</span><span class="syntaxdefault">x</span><span class="syntaxkeyword">| </span><span class="syntaxdefault">x</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_i </span><span class="syntaxkeyword">}<br /> </span><span class="syntaxcomment"># => [15, 1, 106]<br /> </span><span class="syntaxdefault">end<br /><br />end </span><span class="syntaxcomment"># module<br /><br /># Example usage;<br /></span><span class="syntaxdefault">major</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">minor</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">revision </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">Example</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">read_skp_version</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault"></span>
-
If the file has not yet been saved or the file does not exist, need a bailout.
-
Is the a .chr inverse? 65.chr returns A but what if I want the ascii code for a given character?
-
"A".ord
-
Advertisement