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

    Fixing the Undo-stack (and others!)

    Scheduled Pinned Locked Moved Developers' Forum
    13 Posts 3 Posters 789 Views 3 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.
    • J Offline
      Joclo
      last edited by

      Good morning everyone,

      I'm currently writing my first Ruby for Sketchup, a fairly simple plugin that goes through a model assigning colours to faces for the purpose of separating the faces in Photoshop. The end goal is to have a companion PS script to do the separating; this isn't dissimilar to the 'Render ID' function in VRay (https://www.google.co.uk/search?q=vray+render+id).

      Right now it's working fairly well, recursively colouring faces in nested groups and giving adjacent softened faces the same colour. However, there are a few problems:

      • The Undo-stack is picking up every method call, leaving a bit of a mess.. I've read ThomThom's article on it but I still don't entirely understand model.start_operation, I've also tried playing with the arguments but to little effect. Any assistance would be most welcome!
      • ComponentDefinition classes aren't getting picked up by the main method (which currently treats them in the same way it treats the Group classes)

      I'd also appreciate any tips on style and refactoring, as I'm very much a ruby noobie. Cheers!

      -CJ


      CJ_allFacesColoured.rb

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

        I'd use { self.colourfaces() }
        and set @model etc in the called method thus:

        def self.colourfaces(entities=[])
          @colour_selection = Sketchup;;Color.names
          @colour_number = @colour_selection.length
          @colour_current = @colour_selection[rand(@colour_number)]
          @model = Sketchup.active_model
          ###
          @model.start_operation("Colour faces", true) ### NOTE
          ###
          @entities = Sketchup.active_model.entities
          entities = @entities unless entities[0]
          entities.each do |entity|
            ...
            ### set ents to the container's entities THEN
            ### self.colourfaces(ents)
            ...
          end
          ###
          @model.commit_operation
          ###
        end # self.colourfaces
        

        You also need to spot Groups and Instances separately

          ...
        elsif entity.is_a?(Sketchup;;Group)
          ents = entity.entities
          self.colourfaces(ents)
        elsif entity.is_a?(Sketchup;;ComponentInstance) ### NOTE
          ents = entity.definition.entities ### NOTE
          self.colourfaces(ents)
        end
        

        TIG

        1 Reply Last reply Reply Quote 0
        • J Offline
          Joclo
          last edited by

          Fantastic, thanks TIG

          1 Reply Last reply Reply Quote 0
          • J Offline
            Joclo
            last edited by

            Hi again,

            I've managed to fix the undo-stack, as well as implement a couple of other features (same colour across groups/components, reset all materials to default) but the Component section is still not working as intended on some models.

            On simpler models it seems to work fine, however on larger models (like the one attached) it seems to get stuck. Any suggestions would be most appreciated! I've noticed when I take out the is_a?(Sketchup::ComponentInstance) section the rest of the script works fine and as intended.

            Also, once this is sorted a better UI is the next on the list
            -CJ


            latest version


            The model that's causing hangups

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

              When you process a ComponentInstance its definition.entities is altered, you only need to do that once...
              There might be several instances...
              So set up an initial array before the iterated tests: @defns=[]
              So when it's an instance the first thing you do it test if it's already been done...
              This is cod-code - adjust it to your needs...
              ` next if @defns.include?(instance.definition)
              @defns << instance.definition

              process definition.entities`

              That way each definition is only processed once...

              TIG

              1 Reply Last reply Reply Quote 0
              • J Offline
                Joclo
                last edited by

                Thanks for highlighting this TIG, unfortunately this didn't fix the issue. The script hangs and doesn't update the faces until the next user action, then only updates one component definition. Does this yield any clues?

                I'm going to sleep on it πŸ˜„

                -CJ

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

                  Any errors in the Ruby Console ?

                  TIG

                  1 Reply Last reply Reply Quote 0
                  • J Offline
                    Joclo
                    last edited by

                    Hi TIG, I realised that I hadn't run it through the console straight after I finished yesterday. I've now run it through the console & found there's a problem in the self.softcheck method that gives a Error: #<NoMethodError: undefined method `material' for nil:NilClass> when run in some models.

                    I changed the condition from if @face_array[0] && @face_array[0].material == nil and got a Error: #<SystemStackError: stack level too deep>.. Ouch. I believe this is because of excessive recursion, the model comes back with smoothed surfaces half finished so I don't think there's an infinite loop in there. I presume this means I need to rewrite the code algorithmically?

                      def self.softcheck(face)
                        face.edges.each do |edge|
                          if edge.soft?
                          @face_array = edge.faces 
                          @face_array.delete(face)
                            if @face_array[0] && @face_array[0].material == nil
                              @face_array[0].material = @colour_current
                              self.softcheck(@face_array[0])
                            end
                          else next
                          end
                        end
                      end
                    

                    I'm guessing I'm not the first person to try and 'select' all faces in a softened surface, so if there's a good existing definition I could have a look at I'd be most obliged. Cheers

                    -CJ

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

                      As I recall thomthom wrote an example code method, to select all faces in a smoothed surface...
                      Here http://sketchucation.com/forums/viewtopic.php?p=365381#p365381 and others like Jim http://sketchucation.com/forums/viewtopic.php?p=453845#p453845

                      TIG

                      1 Reply Last reply Reply Quote 0
                      • J Offline
                        Joclo
                        last edited by

                        It works πŸ˜„

                        I had a good look at ThomThom's code and saw how he did it, very neat - going to have a good think about how to optimise it now as it should only iterate each surface once; if the softcheck returns an array faces in a surface I presume I could subtract this from the array of entities being coloured. Time to experiment!

                        In the meantime, here are the results:

                        -CJ


                        Colourfaces demo

                        1 Reply Last reply Reply Quote 0
                        • J Offline
                          Joclo
                          last edited by

                          And of course thank you hugely for your time and expertise TIG, I've thoroughly enjoyed my first foray into Ruby for Sketchup. Thanks again

                          -CJ

                          1 Reply Last reply Reply Quote 0
                          • tt_suT Offline
                            tt_su
                            last edited by

                            @joclo said:

                            I changed the condition from if @face_array[0] && @face_array[0].material == nil and got a Error: #<SystemStackError: stack level too deep>.. Ouch. I believe this is because of excessive recursion, the model comes back with smoothed surfaces half finished so I don't think there's an infinite loop in there. I presume this means I need to rewrite the code algorithmically?

                            Recursive methods to traverse geometry is likely to cause stack overflow as you'll be recursing thousands of times. Geometry walkers need to "unroll" their loop to avoid this.

                            1 Reply Last reply Reply Quote 0
                            • J Offline
                              Joclo
                              last edited by

                              Got it, thanks Thom. I realised that I could have optimised it to recurse fewer times, but at some point with increasingly complex surfaces it will run into a stack overflow again. I had a little read elsewhere and found that there are workarounds (ulimit and altering the interpreter, sounds like a bit of a dodgy hack to me..), but eventually it's always got an upper limit.

                              I very much like the idea of a Geometry walker traversing geometry, and ended up using a solution very similar to yours. Cheers!

                              -CJ

                              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