[Example] Import a 3DS using a specific transform (Cross-Platform)

Continuing the discussion from Ruby API model.importToPoint:

Here is my example. It should now be cross-platform. I found a reference to a cancel action string at the Apple Developer website.

Here is v 2.0.0:

import_3ds_to_point_cross_platfrom.rb (2.5 KB)

NOTE: The imported definition will have triangulated faces.(You’ll need to deal with that issue separately.)

# encoding: UTF-8
#
# Example of importing a 3ds file to a specific transformation.
#
# by Dan Rathbun, v 2.0.0, made cross-platform


module Author
  module SomePlugin

    extend self
    
    WIN = Sketchup::platform == :platform_win rescue RUBY_PLATFORM !~ /darwin/i
    
    if WIN
      require "win32ole"
    end

    @@loaded = false unless defined?(@@loaded)

    def send_escape()
      if WIN
        WIN32OLE::new('WScript.Shell').SendKeys('{ESC}')
      else
        Sketchup::send_action('cancelOperation:')
      end
    end

    # Import a 3ds file to a given transform, point, etc.
    #
    # The 1st (xform) argument is required, and can an Array,
    #  point, vector or transformation object.
    # If a path string is not supplied (2nd argument,)
    #  a file open dialog will prompt for the file to import.
    #
    # Returns nil if user cancels file open dialog.
    # Returns the added component instance if successful.
    def import_3ds_to_point(
      xform, # an Array, point, vector or transformation object
      path = UI.openpanel("Choose 3ds file to import...","*.3ds")
    )
      #
      return nil if path.nil?
      #
      unless path.is_a?(String)
        fail(
          TypeError,
          "String pathname to importable model file expected.",
          caller
        )
      else
        unless File.exist?(path)
          fail(
            ArgumentError,
            "Invalid pathname to importable model file.",
            caller
          )
        end
      end
      if xform.is_a?(Geom::Point3d) || xform.is_a?(Geom::Vector3d) || xform.is_a?(Array)
        transform = Geom::Transformation::new( xform )
      elsif !xform.is_a?(Geom::Transformation)
        fail(
          TypeError,
          "Geom::Transformation, Geom::Point3d, Geom::Vector3d, or Array expected.",
          caller
        )
      else
        transform = xform
      end
      #
      mdl = Sketchup.active_model
      result = mdl.import(path)
      if result # returned as soon as definition is loaded
        send_escape() # to cancel placing with the mouse
        cdef = mdl.definitions[-1]
        cinst = mdl.active_entities.add_instance(
          cdef,
          transform
        )
      end
      #
    end ###

    if !@@loaded

      UI.add_context_menu_handler {|popup|
        popup.add_item("Test 3ds Import") do
          import_3ds_to_point([30,30,30])
        end
      }

    end

  end # specific plugin namspace
end # toplevel namespace

~


It has been pointed out that reliance upon [-1] on API collections is not a contract to always return the most recently added member of a collection.

So we can substitute an array snapshot subtraction pattern …

In the example above, in the import_3ds_to_point() method, the following code snippet …

      mdl = Sketchup.active_model
      result = mdl.import(path)
      if result # returned as soon as definition is loaded
        send_escape() # to cancel placing with the mouse
        cdef = mdl.definitions[-1]
        cinst = mdl.active_entities.add_instance(
          cdef,
          transform
        )
      end

… would change to …

      mdl = Sketchup.active_model
      before = mdl.definitions.to_a # array snapshot of definitions collection
      result = mdl.import(path)
      if result # returned as soon as definition is loaded
        send_escape() # to cancel placing with the mouse
        added = mdl.definitions.to_a - before
        cdef = added.first
        cinst = mdl.active_entities.add_instance(
          cdef,
          transform
        )
      end
2 Likes

Thanks, DanRathbun. Too bad I’m on Mac OS X. I wonder if I can use AppleScript to send key events for the same effect…

Probably, let’s ask @john_drivenupthewall, he has used AppleScript for all kinds of things. Perhaps he can modify the example so that it’s cross-platform.

Sketchup.active_model.import("/tmp/room.3ds")
`/usr/local/bin/cliclick kp:esc` # closes Ruby Console
`/usr/local/bin/cliclick kp:esc` # so do it twice when testing...

instal cliclick using Homebrew and you can move a copy to your plugins bin folder and call it relative…

john

ROFL, yea I ran into that from the console. That’s why I added a context menu command,… so SketchUp would be the active window.

Good news, we found a usable Mac cancel action string at the Apple Developer website.

The example should now be cross-platform.

FYI, In normal operation, the Ruby Console will not have the focus, so the cancel / escape is what abandons the mouse placement.

The example script creates a test command in the right-click context menu. Please test using that rather than entering qualified method call from the console.

yes, it works on a mac when run that way…

john

1 Like