Insert object on mouse click

Hello everyone, I wrote a small file Api Ruby, with which I create a pillar, setting the two
measurements at the base of the pillar, side along the x-axis and y and the height, all by entering the measurements
inputbox… in creating the face for the “pushpull”, the first point equals pt1 [0, 0, 0]
origin of the X, Y, Z axes … I would like the pillar object to remain momentarily attached
cursor and subsequently inserted on screen at a precise point at the click of the mouse insertion,
I hope I have explained myself… Possibly? What should I write to the Ruby file, for this insertion wait
pillar object… Thank you.

Greetings

Joseph

Pil_1_piano.rb (1.1 KB)

You can use model.place_component for that:

Thanks for the answer, I’ve already tried watching " model.place.component",
but I understood very little, if he was kind enough to show me with practical example
using my ruby file, it would be great…Thank you

Joseph

Currently your code adds a group and then creates geometry in it.

You could add a new definition into the model’s definitions, and then add your geometry into its entities context, much as you did with the group.entities.
http://ruby.sketchup.com/Sketchup/DefinitionList.html#add-instance_method
http://ruby.sketchup.com/Sketchup/ComponentDefinition.html#entities-instance_method

Then use model.place_component(…) with the reference to this new component definition.


Also note that you should wrap your method inside your own module, so that it remains separate from everyone elses...
1 Like

I understand very little…Thanks all the same

Joseph.

Greetings Thomas. I feel like a fan talking to my idol here. :grinning:
Small follow up question to place_component method.
It returns Sketchup::Model instead of the ComponentInstance. Seems reasonable since repeat argument could be set to true and it would return something like an array OR ComponentInstance.

Therefore, how would you grab a handle to the ComponentInstance (assuming repeat set to false).
Should I go with Sketchup.active_model.entities[-1] or is there something more intuitive.

Thanks, Felipe.

There are several ways.

1. Since you must have a reference to the component definition, you can take an array snapshot of it’s instances collection before and then subtract it from the array afterward.

before = cdef.instances
model.place_component(cdef,false)
# Wait some time because place_component returns immediately.
new_instances = cdef.instances - before

But the main problem is knowing when the placing has been completed (as place_component is non-blocking and returns immediately.)

This is the reason why it just returns the model object - ie the method call returns immediately and does not wait for the user to place any instances.

Changing how it works now is not possible. But adding a sister method that does wait and retrun an array of placed instances is an option.


A better approach is likely to use a temporary definition observer …

module Author::SomePlugin
  # inside your plugin module ...
  extend self

  def onComponentInstanceAdded(definition, instance)
    @instance = instance
    definition.remove_observer(self)
  end

  def place_component(definition)
    @instance = nil
    # Set up a timer to check for the new instance and remove observer
    # if the timeout is reached (ie, user canceled the placement.)
    @timeout = 10.0
    @elapsed = 0
    @tid = UI.start_timer(1.0,true) do
      @elapsed += 1.0
      if @instance
        UI.stop_timer(@tid)
        respond_to_instance(@instance)
      elsif @elapsed > @timeout
        UI.stop_timer(@tid)
        definition.remove_observer(self)
      end
    end
    # Attach this module as temporary observer:
    definition.add_observer(self)
    # Place the instance with the MoveTool:
    definition.model.place_component(definition,false)
  end

  def respond_to_instance()
    # Do something with @instance
  end

end # plugin module

You might also watch the toolstack. The PlaceComponent tool will change to the MoveTool at some point.


There are a bunch of open API Issues regarding placing components with the API(s) …

1 Like

Perfect. It is working like a charm using the sister method. Thanks. Appreciate it.

Makes perfect sense for me now. And once again thanks for going further and explaining the main reason behind it returns Sketchup::Model.

sister method?

Thks dan,i’m also troubled by this question,I try a test.rb
as the code

$mod = Sketchup.active_model # 
$ent = $mod.entities # 
#sel = mod.selection # 

#

class Creatgz
 
  def onLButtonDown flags,x,y,view
    ip1 = Sketchup::InputPoint.new
    ip1.pick view,x,y
    @ip = ip1.position
    crt_wrb
  end
  
  def crt_wrb

prompts = ["high", "wight", "depth"] #
defaults = ["2400mm","800mm","600mm"]
yjgz = UI.inputbox(prompts, defaults, "test")

h                 = yjgz[0] #
w               = yjgz[1] #
d                = yjgz[2] 

h = h.to_i.mm
w = w.to_i.mm
d = d.to_i.mm

@wrb = [] #

#
box1 = $ent.add_face [0,0,0],[w,0,0],[w,d,0],[0,d,0]
box1.pushpull -h
box1_group = $ent.add_group box1.all_connected
lb = box1_group.to_component

@wrb << Sketchup.active_model.active_entities[-1] #

box2 = $ent.add_face [w*2,0,0],[w*3,0,0],[w*3,d,0],[w*2,d,0]
box2.pushpull -h
box2_group = $ent.add_group box2.all_connected
rb = box2_group.to_component

@wrb << Sketchup.active_model.active_entities[-1] #

wrb_newname = Sketchup.active_model.entities.add_group (@wrb) #

wrb_newname = wrb_newname.to_component #


  $ent.transform_entities @ip,wrb_newname

   end

end

cm1 = UI::Command.new("test-box"){
Sketchup.active_model.select_tool Creatgz.new
}

toolbar = UI::Toolbar.new"test-box"
toolbar.add_item cm1
toolbar.show

how can I put the component when my code create the test-box at the point I want to,and it can be catch the mid-point or endpoint. at the same time, we can see the icon like this无标题
I have searched many examples of similar problems in the forum,but there’s no completed code。can u help me finish the code then i can understand the methods to put components.Thks again!

Refer to the official examples repository.


@SHAWO I’ve looked at your code a bit and it is off-topic.

It is not inserting a component instance using a tool, and should have been in it’s own topic rather than reviving this topic after 2 years.

All this said, I previously posted a complete example Instance DragTool here …

Draw model while moving mouse in custom tool - #11 by DanRathbun

Note that the forums is not usually the place for “completed code”.
(I myself have posted a smattering of complete code examples here, but intend to move them to GitHub gists or full code repositories.)

I did post a complete example Instance Drag Tool here …

Draw model while moving mouse in custom tool - #11 by DanRathbun


Please learn Ruby best practices for a shared environment. ( ...click to expand... )

Regarding your “test” code. Please learn Ruby best practices for a shared environment.
No global variables.

A unique namespace module wrapping everything (but even a name like “Testing” for namespace sake is fine for posting snippets.)
A namespace module is important because it is a no-no to define classes at the top level for your own use. (Only Ruby Core and API classes that everyone will use should be defined in the top level ObjectSpace.)

Within your top level namespace module is where you define extension submodules. This is important because each extension’s code needs to be separated from each other so that they do not interfere.

Define custom classes inside extension submodules where they will be used.

When coding use good practice so that when you need help others are able to understand what your code is trying to do:

  • Comment your classes and methods with at least a simple description. This lets other readers know what a class or method is intended to do. And later when you yourself come back to the code months later, these comments will help you remember how things work.

  • Insert comments in between code statements when more explanation is needed.

  • Use descriptive reference (variable) names, except for the simplest iterator index variables in loops.

  • Use proper 2 space indentation. (Set your code editor to replace tabs with spaces so that when you need to post code snippets the forum can display the code correctly.)

~

Thank a lot,Dan!
I have solved the problem ,i find the answer in official examples with writing notes myself。
As a beginner without coding experience, i think it’s too bad that there’s no notes in official examples’ code,many people can’t understand every method in code and why coding like this.people should search the API document and try to guess the way for complete codes。
Cos English is not my mother language,it’s too slow to learn skp develop。
fortunately,Dan help many beginner persevere in his study^_^

1 Like

The examples editions have no comments, but if they have a tutorials edition then that will have comments.

The API documentation is a concise dictionary of API objects, not a teaching tool.

I created lists of resources for learning Ruby …

Have a look in the tutorials folder: sketchup-ruby-api-tutorials/tutorials at main · SketchUp/sketchup-ruby-api-tutorials · GitHub

These examples are heavily commented:

1 Like

Thank you so much!TT