Can a Ruby tool return a value to a 'calling' program?
-
I'm trying to extend the Parametric 3D Shapes plugin to allow the user to pick an origin point for the shape to be drawn, and also to develop another plugin to draw the five Platonic solids (the regular polyhedra: Tetrahedron, Cube, Octahedron, Dodecahedron and Icosahedron).
I've successfully adapted Matt666's 2008 plugin point.rb to allow me to pick a single point, or specify it in the VCB, and draw a cpointat the specified location.
But I can't quite see how to connect this with either of the two existing plugins I have - 3D shapes.rb and a new and as yet unpublished plugin polyhedra.rb. These draw a selected shape at the ORIGIN point.
I can (rather crudely) include the Polyhedron module code into the PickPointTool, and call for a new instance of the relevant solid Class (Icosahedron, etc), and use a Geom::Transformation.translation to move the polygon mesh which constructed Dodecahedron or Icosahedron, and use it with a global variable set at the pick point by the pickpoint tool.
But since I didn't construct the Tetrahedron, Cube, or Octahedron as a PolygonMesh object, I can't do exactly the same there.
I'd rather have the PickPoint tool be callable from another program, and return the value (somehow - perhaps just as a global variable?) to the calling shapes or Polyhedra plugin.
Is this doable? Do I have to use a global variable to return the pickpoint value?
And how would I tell the PickPointTool which Class (shape or polyhedron) is 'calling' so as to set an appropriate cursor? Can a Tool object be sent a parameter, and/or return a value or values? I've not seen any example tool which does, nor been able to see from the documentation how it might.
I'm still a relatively newbie Ruby programmer, and have so far mainly modified others plugins rather than developing them from scratch. In particular, I've found good starting points in the original SU Shapes plugin, the ClineTool, and in Matt666's Point plugins, and in the eBook From Edges to Rubies. So I have some pragmatic sense of what works, and have used the API documentation to help in my modifications.
My code is public at GitHub - see https://github.com/johnwmcc. It doesn't yet include latest mods to link the polyhedra and pick_point code, which is still in rough draft and developing. The versions on GitHub are self contained - the polyhedra plugin just draws the shapes at the origin, and the pick_point one just draws a cpoint at either the picked point, or at a point specified by entry into the VCB.
Any help would be gratefully welcomed.
Thanks in advance if you can advise me further.
-
You should never use global varibles. They can mess up other peoples code.
It's not just a matter of personal preference. Your plugin would most likely be banned if using it.There are several solutions for solving communication between classes, I can think of.
Not sure which one will suit you best for your project or is considered "best practice".
But you could for ex call other classes/modules through getter or setter methods with arguments from within your toolclass. I suspect at launch, you will activate a tool that collects the data from mouse movements with inference and at mouseup or similar you call a method outside this tools class for your shapes. Something like Cube::draw(args).
CONSTANTS are reachable within a class. So you could store a hash like this. DATABASE={}.
Neatly namespaced in your module off course..There are plenty of Tools/plugins to have a peak in. Be sure to look for plugins that use the toolclass.
For ex camera Tools has some view.draw examples for displaying transient Open GL geometry to aid user feedback/or display transient geometry before drawing the actuall geometry in Sketchup..
http://sketchucation.com/forums/viewtopic.php?t=43290
Just some ideas. Not a real answer. The question is quite broad..
-
Thank you.
What you describe (calling the shapes or polyhedra routine from within the Tool class) is what I've tried.
And your hint and link has given me a lead to think about and experiment with. Won't have time to follow up tonight, but will look hard tomorrow.
Is it possible or allowable to have module-wide variables that aren't global? I don't think a class @@variable can be transferred between class instances of different classes or modules, if I understand correctly.
Or could I use a global variable that is named with an author prefix - like my initials jwm - to avoid namespace clashes? So, for example, $jwm_picked_point? Would that avoid clashes with other authors' plugins? Or are global variables just totally banned in SU plugins?
I was hoping to work the other way round from what you suggest, and indeed what I've already tried with partial success. I would like to invoke the PickPointTool from within the Polyhedra plugin, and return the picked point. Is that possible?
And if it is, and I invoke from polyhedra.rb an instance of the PickPointTool, how can I wait until that tool has been used to pick an origin point before continuing to the next line of code?
At the moment, I can only think of using a ToolsObserver to check the state of the PickPointTool, and having a timed loop checking until it responds with a 'point picked' state. Or, perhaps, defining getter and/or setter methods in the tool
-
Global
$var
variables are almost always avoidable, if you keep all of your code inside its own 'module'.
Then using@var
will suffice, when that's used seen inside that module as it's always accessible by other methods...
Even I [ ] still have a few 'globals', but as I edit/update code these do get flushed out...
-
@johnwmcc said:
Is it possible or allowable to have module-wide variables that aren't global?
YES.
ALL of your plugins should be within a company or author namespace module.
Each of your separate plugins would be within a sub-module of that toplevel module.
Let us say for example your toplevel module is named
McC
and within that you define a@@last_point
variable.You can also define getter and setter methods to set and access that variable within the toplevel module:
module McC def McC;;last_point @@last_point end def McC;;;astPoint=(pt) @@last_point = pt.is_a?(Geom;;Point3d) ? pt ; Geom;;Point3d.new(0,0,0) end end # module McC
OR you could define your shared functionality within a mixin module, and then
include
it within any of your sub-modules or classes, with which you want to share it with.See the the "Pick-Axe" book on Programming Ruby. It's in the Ruby Resources thread. AND also online in HTML format.
Advertisement