sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    New to Ruby - I want to write a script to...

    Scheduled Pinned Locked Moved Developers' Forum
    26 Posts 5 Posters 924 Views 5 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.
    • K Offline
      keithswd
      last edited by

      This code appears to work on a test folder of 10 .skp files. Haven't let it loose on the main folder of 500!

      model = Sketchup.active_model
      
      # set folder and get array of filenames
      loadFolder = "/Users/Keith/Illustration Library/Testfolder"
      skpFiles = Dir[File.join(loadFolder, "*.skp")]
      
      
      # Returns a DefinitionList
      definitions = model.definitions
      
      # iterate through files
      
      skpFiles.each do |compFile|
      	compDefinition = definitions.load compFile
      	behavior = compDefinition.behavior
      	behavior.always_face_camera = true
      	behavior.shadows_face_sun = true
      	compDefinition.save_as compFile
      	definitions.purge_unused
      	end
      

      no error handling of course so it's a bit 'quick and dirty'.

      1 Reply Last reply Reply Quote 0
      • Dan RathbunD Offline
        Dan Rathbun
        last edited by

        @unknownuser said:

        This code appears to work on a test folder of 10 .skp files. Haven't let it loose on the main folder of 500!

        no error handling of course so it's a bit 'quick and dirty'.

        Yes make backups first.

        And when it comes to file work trapping errors is best.

        I would think that the user would be prompted to overwrite the old skp file.

        You don't see a confirm MB on the Mac ?

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • TIGT Offline
          TIG Moderator
          last edited by

          If you make a subfolder then you can save the reformatted SKPs into there and leave the original SKPs alone...
          That way you never change the original SKPs' data and don't need prompts etc... 😕

          TIG

          1 Reply Last reply Reply Quote 0
          • K Offline
            keithswd
            last edited by

            As the code stands it runs without any prompts at all. It processed 10 files in the folder in an instant. For my purposes I'd rather manually copy files to be processed into the folder and run the script unattended, knowing I had my own backups. It's only for me to use so I c an leave it rough and ready... Might be nice to select the folder via the file open dialog, other than that I think it serves my needs

            Thanks to all for the help and encouragement.

            1 Reply Last reply Reply Quote 0
            • Dan RathbunD Offline
              Dan Rathbun
              last edited by

              @unknownuser said:

              Might be nice to select the folder via the file open dialog, ...

              folder = UI.openpanel("Choose a skp file to set folder","*.skp")
              if folder && folder = File.dirname(folder)
                # do your stuff
              end
              

              I'm not here much anymore.

              1 Reply Last reply Reply Quote 0
              • D Offline
                driven
                last edited by

                @unknownuser said:

                Thanks to all for the help and encouragement.

                no problem Keith,
                we need to encourage mac users who are prepared to dip into coding, we're in a minority,
                if nothing else, there are always PC authored scripts that need a bit of ironing before they're fully mac compatible.

                @dan wrote a good 'chunking' script for me to process a 3D text sampler that may be useful/adaptable for handling a 500 file array. I'll see if I can find the link.
                FOUND: http://sketchucation.com/forums/viewtopic.php?f=180&t=48761&p=444342&hilit=3d+text+chunk#p444342
                john

                PS, are you in London UK, or one of the impostors, I'm in East Dulwich?

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

                1 Reply Last reply Reply Quote 0
                • K Offline
                  keithswd
                  last edited by

                  Ah - I was wondering what might happen if I loaded a really huge folder - actually I have a couple of thousand file to process. Not all at once though... I will check out that link when I have more time, at first glance looks a bit scary for a novice!

                  Yes, I really am in London UK (live in W14, work SE11)!

                  1 Reply Last reply Reply Quote 0
                  • K Offline
                    keithswd
                    last edited by

                    Thanks Dan for the pointer to UI.openpanel, that all works fine.

                    Not sure if it is because I need to learn about chunking my array, but my routine stops every time after processing 33 or 34 files (it is always after 33 or 34 files) and then SU8 crashes. Given that such a small number of files are processed before the hang/crash, I am not sure the array size is the problem? When the script stops running, I am left with the last loaded component in the component list. If I try and and check its 'Face-Me' status, SU crashes.

                    def setcompfm
                    
                    model = Sketchup.active_model
                    # set folder and get array of filenames
                    folder = UI.openpanel("Choose a skp file to set folder","*.skp")
                    
                    if folder && folder = File.dirname(folder)
                    	skpFiles = Dir[File.join(folder, "*.skp")]
                    end
                    
                    length = skpFiles.length
                    
                    result = UI.messagebox "Process " + length.to_s + " files?", MB_YESNO
                    
                    if result == 6 # Yes
                    
                    # Returns a DefinitionList
                    definitions = model.definitions
                    
                    # iterate through files
                    begin
                    
                    	skpFiles.each do |compFile|
                    
                    		compDefinition = definitions.load compFile
                    		behavior = compDefinition.behavior
                    		behavior.always_face_camera = true
                    		behavior.shadows_face_sun = true
                    		compDefinition.save_as compFile
                    		definitions.purge_unused
                    
                    	end #end do
                    
                    rescue
                    	puts compFile
                    
                    end #end begin
                    
                    end #end if
                    
                    end #end def
                    
                    1 Reply Last reply Reply Quote 0
                    • Dan RathbunD Offline
                      Dan Rathbun
                      last edited by

                      The folder check was meant to enclose everything... but I see you have a empty folder check (which probably cannot happen because an actual file must be selected. BUT...

                      change line 7 to:
                      return unless folder && folder = File.dirname(folder)

                      REMOVE the end (line 9)

                      If you cancel the open panel, NOW your method exits (because the result of UI.openpanel will eval falsely.)

                      I'm not here much anymore.

                      1 Reply Last reply Reply Quote 0
                      • Dan RathbunD Offline
                        Dan Rathbun
                        last edited by

                        change the name of THAT 33rd or 34th file to ".OFF" or whatever.

                        Then try again. Just eliminate the bad file scenario.

                        I'm not here much anymore.

                        1 Reply Last reply Reply Quote 0
                        • K Offline
                          keithswd
                          last edited by

                          Thanks for the correction - I see my mistake now. However, the corrected syntax doesn't fix the crash. The folder selection works as it did before and populates the array with all the .skp files in the folder (about 200 for testing purposes), and my message box pops up and correctly reports the number to be processed.

                          However it stops on the 33rd or 34th file no matter what that file is. Each time I run the script, I move the 33/34 successfully modified files out of the folder, so I am never processing the same files twice. I don't know what might be special about the 33/34 mark, but it bails at that point.

                          Some kind of limit appears to be reached? Memory? I've no clue!

                          1 Reply Last reply Reply Quote 0
                          • D Offline
                            driven
                            last edited by

                            not sure how to do it in ruby but in the osascript/applescript/bash I tend to use, if you don't add a distinct delay point, the process reaches some limit and errors. [That's what happening with the one I posted earlier]

                            maybe adding a puts "done" after definitions.purge_unused will allow a break before opening the next?

                            total stab in the dark
                            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
                            • Dan RathbunD Offline
                              Dan Rathbun
                              last edited by

                              (1) The iterator block.. use curly braces instead of do ... end
                              So the block can have access to external references, such as definitions

                              (2) Make sure the loading is done before proceeding.

                              (3) perhaps use undo operations ?

                              Try an iterator like:

                                i = 0
                                puts()
                                #
                                skpFiles.each { |compFile|
                                  ###
                                  model.operation( "Update '#{File.basename(compFile)}'", true )
                                  ###
                                  compDefinition = definitions.load compFile
                                  begin
                                    if compDefinition.internal?
                                      behavior = compDefinition.behavior
                                      behavior.always_face_camera = true
                                      behavior.shadows_face_sun = true
                                      compDefinition.save_as compFile
                                    else
                                      putc(46) # period char
                                      redo
                                    end
                                  rescue => e
                                    ###
                                    model.abort_operation()
                                    ###
                                    puts()
                                    puts "ERROR saving component file;"
                                    puts "  #{compFile}\n"
                                    puts e.message
                                    puts e.backtrace if $VERBOSE
                                    puts()
                                  else
                                    i += 1
                                    if i >= 10
                                      definitions.purge_unused
                                      i = 0
                                    end
                                    ###
                                    model.commit_operation()
                                    ###
                                  end
                                  # each skp file
                                }
                                definitions.purge_unused if definitions.length > 0
                              
                              

                              I'm not here much anymore.

                              1 Reply Last reply Reply Quote 0
                              • K Offline
                                keithswd
                                last edited by

                                Thanks again for your help and suggested code. As it stands it does not modify any components. I discovered this is because it seems that even when the component file is loaded successfully, compDefinition.internal? returns false. I can only imagine that this is actually testing whether the component was created within the model or loaded from a file - in which case we are getting the expected result. I commented it out and it runs but... sadly it still bombs out at around 33 components.

                                I really don't want to take up any more of anyone's time - this was just a little project for me to play with but it seems rather trickier than I could have forseen. But I thought you might like an update!

                                def setcompfm
                                
                                model = Sketchup.active_model
                                # set folder and get array of filenames
                                folder = UI.openpanel("Choose a skp file to set folder","*.skp")
                                
                                return unless folder && folder = File.dirname(folder)
                                
                                skpFiles = Dir[File.join(folder, "*.skp")]
                                
                                length = skpFiles.length
                                
                                result = UI.messagebox "Process " + length.to_s + " files?", MB_YESNO
                                
                                return unless result == 6 # Yes
                                
                                # Returns a DefinitionList
                                definitions = model.definitions
                                
                                # iterate through files
                                i = 0
                                  puts()
                                  #
                                  skpFiles.each { |compFile|
                                    ###
                                    model.start_operation( "Update '#{File.basename(compFile)}'", true )
                                    ###
                                    compDefinition = definitions.load compFile
                                    begin
                                      #if compDefinition.internal?
                                        behavior = compDefinition.behavior
                                        behavior.always_face_camera = true
                                        behavior.shadows_face_sun = true
                                        compDefinition.save_as compFile
                                      #else
                                      #  putc(46) # period char
                                      #  redo
                                      #end
                                    rescue => e
                                      ###
                                      model.abort_operation()
                                      ###
                                      puts()
                                      puts "ERROR saving component file;"
                                      puts "  #{compFile}\n"
                                      puts e.message
                                      puts e.backtrace if $VERBOSE
                                      puts()
                                    else
                                      i += 1
                                      if i >= 10
                                        definitions.purge_unused
                                        i = 0
                                      end
                                      ###
                                      model.commit_operation()
                                      ###
                                    end
                                    # each skp file
                                  }
                                  definitions.purge_unused if definitions.length > 0
                                
                                
                                end #end def
                                
                                1 Reply Last reply Reply Quote 0
                                • D Offline
                                  driven
                                  last edited by

                                  Hi Keith,

                                  I'm sitting at home recovering from having my ear cut off [and put back on] on Friday.
                                  So, glad for the distraction...
                                  Anyhow, heres an Automator script that has a safe test action, so won't hurt any files...
                                  I missed a filter function, in the first...

                                  1. opens each .skp in a 'pre-selected' folder in SU v2013 [should use your version if not]
                                  2. opens 'Ruby Console' and 'types' some safe for testing code Sketchup.send_action('viewIso:');Sketchup.send_action('viewZoomExtents:')clicks return
                                  3. 'Saves' the changes
                                  4. closes 'RC'
                                  5. closes the .skp
                                  6. loops to the next skp in folder... and repeats

                                  You need to open SU first with an empty new drawing... this just saves hassle.
                                  Pre-Sellect skps in a Folder.
                                  Open the workflow in 'Automator.app' by double clicking after unzipping it.

                                  Click Run, watch the show [I like the way it types for me, rather than just inserting it en-masse]

                                  If your not using v2013 you'll may need replace the SketchUp.app shown with the one on your path [I know it looks right but I did a trick to avoid using v8, so just swap it if you need to, run it once to see if it fails...]

                                  Once your happy the safe version works, edit the applescript with your SU [a 'one-liner' is probably best]

                                  try it on a subset, if it runs those, it will run hundreds as long as you adjust the timeout [in loop field] to cover it...

                                  Let me know if it works

                                  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
                                  • K Offline
                                    keithswd
                                    last edited by

                                    Hi John,
                                    The ear sounds painful! I hope you are recuperating well.
                                    Thanks for the workflow. I have got it to work, with SU loading a script automatically (which defines a function to set the current model behavior as I want it) and I call that function in console. It runs slowly compared to the all-Ruby solution - but at least it processes without crash. So I can send lots of files and leave it to run over lunch, or night!
                                    Many thanks again,
                                    Keith

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

                                    Advertisement