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

**URL:** <https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425>\
**Category:** Ruby API\
**Created:** [April 11, 2016, 2:32pm UTC](https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425 "2016-04-11T14:32:57Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [April 11, 2016, 2:32pm UTC](https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425/1 "2016-04-11T14:32:57Z")

</div>

Continuing the discussion from [Ruby API model.importToPoint](http://forums.sketchup.com/t/ruby-api-model-importtopoint/18747/4):

> [@Ruby API model.importToPoint](https://forums.sketchup.com/t/ruby-api-model-importtopoint/18747/4):
>
> Is there an equivalent way that will also work for non-.skp files? Say, **.3ds** or **.dae** models?

## **NOTE:** This is a hacky workaround for **old** versions. With the **2021.1** release we now have a [`Sketchup::DefinitionList#import`](https://ruby.sketchup.com/Sketchup/DefinitionList.html#import-instance_method) method that can import non-SKP files directly as a component definition. A subsequent code statement can then place an instance of the imported component at a given point.

For the 2021.1 and newer recommended coding pattern, see:  
[How to import SKP to a 3dpoint? Why is it stuck on my mouse? - #8 by DanRathbun](https://forums.sketchup.com/t/how-to-import-skp-to-a-3dpoint-why-is-it-stuck-on-my-mouse/18746/8)

* * *

Here is my example for versions older than 2021.1. **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](https://forums.sketchup.com/uploads/short-url/cXYiYcTSfpCVgqwbVOySmaCOQzr.rb) (2.5 KB)

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

```ruby
# 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](https://forums.sketchup.com/t/model-import-skp-file-without-activate-the-component-tool/96663/14) 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 …

```ruby
      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 …

```ruby
      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

```

---

<div class="post-metadata">

**Author:** ![alecjacobson](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/alecjacobson/32/16881_2.png) [@alecjacobson](https://forums.sketchup.com/u/alecjacobson)\
**Post date:** [April 11, 2016, 2:47pm UTC](https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425/2 "2016-04-11T14:47:35Z")

</div>

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…

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [April 11, 2016, 2:49pm UTC](https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425/3 "2016-04-11T14:49:06Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [April 11, 2016, 3:08pm UTC](https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425/4 "2016-04-11T15:08:17Z")

</div>

```ruby
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

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [April 11, 2016, 3:10pm UTC](https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425/5 "2016-04-11T15:10:56Z")

</div>

> [@john\_drivenupthewall](#):
>
> # closes Ruby Console … so do it twice when testing…

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.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [April 13, 2016, 7:48pm UTC](https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425/6 "2016-04-13T19:48:03Z")

</div>

> [@alecjacobson](#):
>
> Too bad I’m on Mac OS X. I wonder if I can use AppleScript to send key events for the same effect…

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

**The [example](http://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-win-only/23425/1) should now be cross-platform**.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [April 13, 2016, 9:12pm UTC](https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425/8 "2016-04-13T21:12:10Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [April 13, 2016, 9:14pm UTC](https://forums.sketchup.com/t/example-import-a-3ds-using-a-specific-transform-cross-platform/23425/9 "2016-04-13T21:14:27Z")

</div>

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

john
