• Login
sketchucation logo sketchucation
  • Login
⚠️ Libfredo 15.4b | Minor release with bugfixes and improvements Update

Ruby code to retrive sketchup version of a model

Scheduled Pinned Locked Moved Developers' Forum
18 Posts 8 Posters 1.1k Views 8 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    glro
    last edited by 16 Dec 2014, 09:26

    i found the code to retrieve the version of sketchup running on the computer, but i don't find anything to retrieve the version in which the model has been saved?

    is there anything?

    this would be useful to avoid processing a file that has not been saved in the current version of sketchup

    1 Reply Last reply Reply Quote 0
    • T Offline
      TIG Moderator
      last edited by 16 Dec 2014, 11:42

      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 !

      TIG

      1 Reply Last reply Reply Quote 0
      • S Offline
        slbaumgartner
        last edited by 16 Dec 2014, 13:05

        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?

        1 Reply Last reply Reply Quote 0
        • G Offline
          glro
          last edited by 16 Dec 2014, 16:09

          I have to improve a lot to be able to understand such code...
          i'll try

          thank 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 !

          1 Reply Last reply Reply Quote 0
          • D Offline
            driven
            last edited by 16 Dec 2014, 18:06

            @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

            learn from the mistakes of others, you may not live long enough to make them all yourself...

            1 Reply Last reply Reply Quote 0
            • T Offline
              TIG Moderator
              last edited by 16 Dec 2014, 18:44

              I said it could be improved 😉

              TIG

              1 Reply Last reply Reply Quote 0
              • G Offline
                glro
                last edited by 16 Dec 2014, 20:11

                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 SU13

                it's exactly what i was looking for
                i shall make a test and filter the skps to process according to the number i get

                thanks 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

                1 Reply Last reply Reply Quote 0
                • T Offline
                  TIG Moderator
                  last edited by 16 Dec 2014, 20:15

                  My way should return "8" or "13" ?
                  Not sure what's happening...

                  TIG

                  1 Reply Last reply Reply Quote 0
                  • D Offline
                    driven
                    last edited by 16 Dec 2014, 21:48

                    @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

                    learn from the mistakes of others, you may not live long enough to make them all yourself...

                    1 Reply Last reply Reply Quote 0
                    • sdmitchS Offline
                      sdmitch
                      last edited by 16 Dec 2014, 21:57

                      56 is the octal character value for "8" and 49 for "1". It is a function of V8 Ruby vs V14.

                      Nothing is worthless, it can always be used as a bad example.

                      http://sdmitch.blogspot.com/

                      1 Reply Last reply Reply Quote 0
                      • sdmitchS Offline
                        sdmitch
                        last edited by 16 Dec 2014, 22:01

                        @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?
                        john

                        As 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
                        

                        Nothing is worthless, it can always be used as a bad example.

                        http://sdmitch.blogspot.com/

                        1 Reply Last reply Reply Quote 0
                        • T Offline
                          TIG Moderator
                          last edited by 16 Dec 2014, 23:11

                          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...

                          TIG

                          1 Reply Last reply Reply Quote 0
                          • G Offline
                            glro
                            last edited by 17 Dec 2014, 08:15

                            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

                            1 Reply Last reply Reply Quote 0
                            • tt_suT Offline
                              tt_su
                              last edited by 17 Dec 2014, 11:11

                              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&nbsp;Example<br /><br />&nbsp;&nbsp;def&nbsp;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 />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxcomment">#&nbsp;Get&nbsp;the&nbsp;size&nbsp;of&nbsp;the&nbsp;file&nbsp;ID&nbsp;block;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">id_size&nbsp;</span><span class="syntaxkeyword">=&nbsp;</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">,&nbsp;</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">,&nbsp;</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">]&nbsp;*&nbsp;</span><span class="syntaxdefault">2<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxcomment">#&nbsp;=>&nbsp;28<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Get&nbsp;the&nbsp;size&nbsp;of&nbsp;the&nbsp;file&nbsp;version&nbsp;block;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">version_size&nbsp;</span><span class="syntaxkeyword">=&nbsp;</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">,&nbsp;</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">4&nbsp;</span><span class="syntaxkeyword">+&nbsp;</span><span class="syntaxdefault">id_size&nbsp;</span><span class="syntaxkeyword">+&nbsp;</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">]&nbsp;*&nbsp;</span><span class="syntaxdefault">2<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxcomment">#&nbsp;=>&nbsp;20<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Get&nbsp;the&nbsp;version&nbsp;block&nbsp;data.&nbsp;This&nbsp;will&nbsp;be&nbsp;UTF-16LE&nbsp;encoded.&nbsp;Since&nbsp;Ruby&nbsp;1.8<br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;doesn't&nbsp;have&nbsp;the&nbsp;encoding&nbsp;methods&nbsp;we&nbsp;hack&nbsp;it&nbsp;by&nbsp;zapping&nbsp;out&nbsp;all&nbsp;the&nbsp;zero&nbsp;bytes<br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;in&nbsp;the&nbsp;data&nbsp;string&nbsp;which&nbsp;will&nbsp;give&nbsp;us&nbsp;a&nbsp;regular&nbsp;ASCII&nbsp;string.&nbsp;This&nbsp;works<br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;because&nbsp;we&nbsp;know&nbsp;the&nbsp;version&nbsp;string&nbsp;is&nbsp;within&nbsp;the&nbsp;ASCII&nbsp;range.<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">version&nbsp;</span><span class="syntaxkeyword">=&nbsp;</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">,&nbsp;</span><span class="syntaxdefault">version_size</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">4&nbsp;</span><span class="syntaxkeyword">+&nbsp;</span><span class="syntaxdefault">id_size&nbsp;</span><span class="syntaxkeyword">+&nbsp;</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 />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxcomment">#&nbsp;=>&nbsp;{15.1.106}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Extract&nbsp;the&nbsp;version&nbsp;components.<br />&nbsp;&nbsp;&nbsp;&nbsp;</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&nbsp;</span><span class="syntaxkeyword">{&nbsp;|</span><span class="syntaxdefault">x</span><span class="syntaxkeyword">|&nbsp;</span><span class="syntaxdefault">x</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_i&nbsp;</span><span class="syntaxkeyword">}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxcomment">#&nbsp;=>&nbsp;[15,&nbsp;1,&nbsp;106]<br />&nbsp;&nbsp;</span><span class="syntaxdefault">end<br /><br />end&nbsp;</span><span class="syntaxcomment">#&nbsp;module<br /><br />#&nbsp;Example&nbsp;usage;<br /></span><span class="syntaxdefault">major</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">minor</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">revision&nbsp;</span><span class="syntaxkeyword">=&nbsp;</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 />&nbsp;</span><span class="syntaxdefault"></span>
                              
                              1 Reply Last reply Reply Quote 0
                              • Dan RathbunD Offline
                                Dan Rathbun
                                last edited by 17 Dec 2014, 23:28

                                If the file has not yet been saved or the file does not exist, need a bailout.

                                I'm not here much anymore.

                                1 Reply Last reply Reply Quote 0
                                • sdmitchS Offline
                                  sdmitch
                                  last edited by 15 Jul 2015, 01:39

                                  Is the a .chr inverse? 65.chr returns A but what if I want the ascii code for a given character?

                                  Nothing is worthless, it can always be used as a bad example.

                                  http://sdmitch.blogspot.com/

                                  1 Reply Last reply Reply Quote 0
                                  • J Offline
                                    Jim
                                    last edited by 15 Jul 2015, 03:26

                                    "A".ord

                                    Link Preview Image
                                    Class: String (Ruby 2.0.0)

                                    Class : String - Ruby 2.0.0

                                    favicon

                                    (ruby-doc.org)

                                    Hi

                                    1 Reply Last reply Reply Quote 0
                                    • sdmitchS Offline
                                      sdmitch
                                      last edited by 15 Jul 2015, 13:46

                                      @jim said:

                                      "A".ord

                                      Link Preview Image
                                      Class: String (Ruby 2.0.0)

                                      Class : String - Ruby 2.0.0

                                      favicon

                                      (ruby-doc.org)

                                      Thanks for the info and especially the link.

                                      Nothing is worthless, it can always be used as a bad example.

                                      http://sdmitch.blogspot.com/

                                      1 Reply Last reply Reply Quote 0
                                      • 1 / 1
                                      • First post
                                        Last post
                                      Buy SketchPlus
                                      Buy SUbD
                                      Buy WrapR
                                      Buy eBook
                                      Buy Modelur
                                      Buy Vertex Tools
                                      Buy SketchCuisine
                                      Buy FormFonts

                                      Advertisement