Search code examples
rubysketchup

onSaveModel observer in Ruby Sketchup causes infinite loop


I'm trying to use the built-in ModelObserver class in Sketchup to trigger a file export when the user saves the current model. For some reason my code triggers an infinite loop - the text 'onSaveModel' outputs just once, but the exportModel() gets caught in a loop.

My Ruby skills are low, but I've also heard the SketchUp Ruby API is flakey from time to time. Anyone seen this problem before?

Code:

def protohypeEntry
    Sketchup.active_model.add_observer(ProtohypeModelObserver.new)
end

class ProtohypeModelObserver < Sketchup::ModelObserver
    def onSaveModel(model)
        puts "onSaveModel" + model.to_s
        exportModel()
    end
end

def exportModel()
    puts "exportModel()"
    model = Sketchup.active_model

    options_hash = { :triangulated_faces   => true,
     :doublesided_faces    => true,
     :edges                => false,
     :author_attribution   => true,
     :texture_maps         => true,
     :selectionset_only    => false,
     :preserve_instancing  => true }

     status = model.export 'C:\Users\Pelle\Test\test.dae', options_hash

 end

 protohypeEntry() 

Solution

  • An export also triggers onSaveModel (the API docs isn't clear on this, I'll add an issue internally), so your export within the observer event will trigger the infinite loop.

    Set an internal flag to indicate the state of your script and break early when you are in the process of exporting.

    module Example
    
      def self.protohypeEntry
        Sketchup.active_model.add_observer(ProtohypeModelObserver.new)
      end
    
      class ProtohypeModelObserver < Sketchup::ModelObserver
        def onSaveModel(model)
          puts "onSaveModel" + model.to_s
          Example.exportModel()
        end
      end
    
      def self.exportModel()
        return if @exporting
    
        puts "exportModel()"
        model = Sketchup.active_model
    
        options_hash = { :triangulated_faces   => true,
          :doublesided_faces    => true,
          :edges                => false,
          :author_attribution   => true,
          :texture_maps         => true,
          :selectionset_only    => false,
          :preserve_instancing  => true
        }
    
        @exporting = true
        status = model.export 'C:/test.dae', options_hash
      ensure
        # Just in case model.export should raise an exception we guarranty the flag
        # is reset.
        @exporting = false
      end
    
    end
    
    Example.protohypeEntry()