Hook ruby method in class

Hi,

I am a c++ developer and not quite familiar with ruby stuff. Is there any approach to hook into existing ruby classes and class member functions?

For example, hook into InputPoint and change the behavior of the InputPoint.pick, so I can add some custom function in the pick.

Regards,
Han

First of all, you should not change Core Ruby classes or API classes as this will cause havoc for other extensions.

In Ruby there are refinements that allow a single file or class to change Ruby classes so only the file using the refinement can see the changes.
File: refinements.rdoc [Ruby 2.7.1]

But Ruby is actually implemented in C. And there are ways to call Ruby methods from C/C++.
But I’m not quite sure how Ruby refinements would be done from C.
You should probably read this …

It is a bit old and predates Ruby refinements, but will allow you to understand how to use Ruby from the C side.

As Dan says the Ruby API methods are implented using the Ruby C API, and are closed source. You can’t read these methods and base your own on their code.

What you can do is to check if the changes you want to InputPoint#pick is logged in our Ruby API Issue Tracker, or otherwise add it.

Refinement seems to be the way. But can it be inherited to others? That is I refine InputPoint, but all the other plugins or even native SU tool will also respond to my refinement?

I am afraid that it is not an issue with InputPoint point. Because what I want to pick is native OpenGL objects, not SU entities.

NO. That is the purpose of a Ruby refinement. A Ruby class (or file) must specifically use the refinement.

The whole point is that it will not be “used” by the SketchUp core C code (native tools) or by other Ruby extensions.


And again, native SketchUp tools can not be modified by the APIs. But some of these tools can be “watched” by observers and respond to their actions.

Usually extension authors must result in coding their own Ruby tools if they need custom behaviors.

Thanks to your explanation.

In usual ways it is, but I am quite sure it’s possible. Because as mentioned in another thread (Snap to point clouds similar to Trimble Scan Essential - #4 by saedrna), the Trimble Scan Essential plugin gas changed the behavior of InputPoint.

I can hook into standard Win32 API in C, but don’t get the function for stuff like InputPoint.

Well, Trimble itself can create “secret hooks” because they have access to the C++ core of SketchUp’s code. We “lowly” API developers do not have access to these “secrets”.

Also, I had asked in that topic if you could post a model with a small point cloud created using that extension. Then I could look at the cloud objects. (I do have the Scan extension nor a laser scanner myself.)

I don’t know what use you could make of OpenGL objects rather than their SketchUp source entities. But nonetheless, the SketchUp API does not provide any way to access OpenGL data directly. You can generate OpenGL objects within a Tool’s draw method, but it is one-way; you don’t get a reference to them and there is method to request one. I’d be leery of hacking around this because there is a risk you could completely disrupt SketchUp’s heavy entanglement with OpenGL.

1 Like

I will post a point clouds tomorrow. The plugin has a 30 day trial.

In fact, it’s not that dangerous than you think. Many plugins do this stuff, such as undet and Trimble Scan Essential.

I would challenge “many”. But regardless of that, what makes you believe either of those extensions directly reads OpenGL data? Don’t they add geometry to a SketchUp model’s contents, which is then displayed in the view? I don’t see the point of “importing” point cloud data if all that results is a visual, not geometry, since there would be no resulting model in SketchUp.

Because there is no way su can handle that amount of data if they were part of the editing model.

By visually bringing them in, a user can see them, snap to them, and use them as an underlayment to draw a model.

I don’t think SketchUp has any way to snap to anything that isn’t in its geometry database?

Not out of the box, no. But that is what OP attempts to achieve with coding.

I have upload a video to demonstrate this from my development. InputPoint can not do this, but only my own Tool can. However, Trimble Scan Essentials does not do this way. It affect all tools using InputPoint.

I have attached a point clouds. You probably need to make a new project from the point clouds S1.laz.
pointclouds.skp (301.9 KB)

Maybe I misunderstood the task, but at least just for fun, I did a test … how do I imagine snapping on opengl points: (I have no idea influencing the performance…)

class Tool_test_snapto_gl_points
  ###dirty!!###
  def initialize
    p_cloud = spiral_sphere( 1000 )
    @segments = p_cloud.map{|p| p.transform!( Geom::Transformation.scaling(10) ) }
  end
  
  def onMouseMove(flags, x, y, view)
    ph = view.pick_helper
    ph.init(x, y, 10)
    @picked = ph.pick_segment(@segments)
    if( @picked && @picked >= 0 )
      @point_to_draw = @segments[@picked]
    end
    view.invalidate
  end
  
  def draw(view)
    view.tooltip = @picked.to_s if( @picked && @picked >= 0 )
    view.draw_points( @segments, 5, 2, "peru" ) if @segments
    view.line_width = 2
    view.draw_points( @point_to_draw, 15, 4, "green" ) if @point_to_draw
  end
   
  #-----------------------------------------------------------------------------
  # Borrowed from:
  # Thomas Thomassen
  # thomas[at]thomthom[dot]net
  # TT_Lib2
  def spiral_sphere( number_of_points, origin=ORIGIN )
    t = Geom::Transformation.new( origin )
    n = number_of_points
    node = Array.new( n )
    dlong = Math::PI * (3-Math.sqrt(5))
    dz = 2.0/n
    long = 0
    z = 1 - dz/2
    (0...n).each { |k|
      r = Math.sqrt( 1-z*z )
      pt = Geom::Point3d.new( Math.cos(long)*r, Math.sin(long)*r, z )
      node[k] = pt.transform( t )
      z = z - dz
      long = long + dlong
    }
    node
  end
  # Thanks
  #-----------------------------------------------------------------------------
   
end
Sketchup.active_model.select_tool(Tool_test_snapto_gl_points.new)

Your example is interesting, but it does not actually snap to OpenGL objects.

Your code just happens to draw OpenGL “peru” colored squares at the same locations as the Geom::Point3d points in a “virtual” curve vertex array, which is what PickHelper is snapping to. (Ie, virtual in that an actual curve object does not exist. This is what I find most interesting about the example.)


The point of this topic and the related topic is that the OP (is saying) he does not have access to “read” the point positions of the “special” point clouds created by the Trimble Scan Essentials extension. In that topic, Christina said …

1 Like

Indeed, without knowing the underlying C API for InputPoint.pick. I have no idea how to implement this.