Problems with Sketchup Classes
-
Disclaimer: I'm not that experienced at ruby programming, so please excuse me if I've missed something obvious!
At the moment I'm having a play at getting a form of RPC going between 2 sketchup processes (over the network). But before I can do that I've had to face a number of problems. one being the lack of proper sockets in the embedded interpreter (i've gotten around that now by using an external process), the second being the challenge of getting YAML basics working in sketchup (my chosen form of text based serialisation). But now I think I've hit a brick wall:
As far as I can guess, yaml subclasses/extends every object and adds an automatic to_yaml method (please correct me if I'm wrong here!), that tries it's best to make sense of the objects it deals with. I got it working fine on my own simple classes/object hierarchies, but yaml seemed to draw the line at sketchup!
After much mucking about with the sketchup classes (such as face, vertex, and so on...), I found that if I did something like this:
class Sketchup;;Geom;;Point3d def testing puts "Yay the test worked" end end
or this
class MyPoint < Sketchup;;Geom;;Point3d def testing puts "Yay the test worked" end end
I could only get the "testing" method to work when i called it from an instance of the class (that I created) myself:
pt = Sketchup;;Geom;;Point3d.new(1, 2, 3)
or
pt = MyPoint.new(1, 2, 3)
(they both seem to be the same)
anyway, to cut a long story short I finally cracked the code on how to get yaml to work with sketchup objects (so I thought):
class Sketchup;;Geom;;Point3d def initialize(x, y, z) super() @x = x @y = y @z = z end end
It seemed as though the Point3d class did not even have instance variables (weird!), I can only assume that this is because they were created from the closed side of Sketchup.
but as I said before, this only worked on objects that I created myself, not even new one created using sketchup tools. Now I'm not blaming this all on Sketchup, because I'm sure they have their reasons for preventing (or not inventing) this kind of interoperability, but If anyone can see a way for this to work (can prove me wrong please!) , or a workaround please reply.
-
Sketchup::Geom::Point3d
?
Geom
isn't located under theSketchup
module.See the example of
Point3d.new
:
pt1 = Geom::Point3d.new
it belong only under theGeom
class.And, can you even use
Geom::Point3d
syntax when you extend classes/methods?I always do this instead when I extend:
module Geom class Point3d def testing puts "Yay the test worked" end end
(But I avoid extending Sketchup and Ruby base classes - don't take the risk of causing conflicts.)
-
@l.frisken said:
I could only get the "testing" method to work when i called it from an instance of the class (that I created) myself:
That is correct. Most methods of classes are instance methods. You should be able to call them from inside the class (ie another method of the same class,) using it as a private method.@l.frisken said:
anyway, to cut a long story short I finally cracked the code on how to get yaml to work with sketchup objects (so I thought):
class Sketchup;;Geom;;Point3d > def initialize(x, y, z) > super() > @x = x > @y = y > @z = z > end > end
It seemed as though the Point3d class did not even have instance variables (weird!), I can only assume that this is because they were created from the closed side of Sketchup.
Ignoring the nesting error (that ThomThom pointed out,) the other error is that you are calling super(). Why call the superclass ? I think Google boo-booed and made Point3d a subclass of Object, when they should have made it a subclass of Array.
Anyway besides the fact that your override is erroneous, and does not account for the variable argument list (ie: you can pass 1 object in such as Vector3d, or an Array [of 1 to 3 Numerics,] OR 1 to 3 Numeric arguments.)IF your not going to handle the argument list, then you must let the embedded API object do it. But you DON'T do it by calling super(args) because that just passes the argument list to class Object.
[IN your example above, what your super() does is actually call Object.initialize() without actually passing the argument list. Also in many cases .initialize* is set private, and you can't call it directly from outside a class; instead you normally call the public method .new from outside a class. ]
You must FIRST alias the class method so the original code can be called, THEN redefine the class method using the oldname. alias_method :newName, :oldName
Example:module ;;Geom class Point3d(*args) alias_method(;orig_new,;new) def new(*args) pt=orig_new(*args) # You could add some values the args array args << "My Point3d class Overrride" # .new automatically calls initialize(*args) # before returning the object handle. return pt end def initialize(*args) # prior to initialize, .new has already # created the Point3d object. # @x,@y,@z should have been setup by .new puts args.last # should print string added in .new end end # class end # module
(It's possible initialize may get called twice in above example)
You can do anything you want FOR YOUR OWN USE.
BUT Google OWNS the Sketchup, UI, and Geom Namespaces. The Terms of use prevent you from causing other people's installations of Sketchup to be degraded or broken or such. The license agreement is at: http://sketchup.google.com/intl/en/download/license.html
At the very least, if you wanted to extend Sketchup classes (and release those extensions,) you'd need to have Google Sketchup Team consent AND Sketchup Developer Community approval.
You might join the SKX project, or monitor the SKX forum.You'd need to make a very good case for extending the SU classes with the community, especially if it can be done quite easily without extending them.
Example. IF the yaml lib already provides String.to_yaml, and most Sketchup classes provide SUclass.to_s, then you have conversion by using SUclass.to_s.to_yaml
-
Thanks for the replies guys!
@unknownuser said:
That is correct. Most methods of classes are instance methods. You should be able to call them from inside the class (ie another method of the same class,) using it as a private method.
Yes it is an instance method, but it seems to have no effect on objects created in the sketchup ui, presumably because they have their own read-only/inaccessible templates/classe for creating objects?
And yet I still fail to see why rewriting the instance variable declaration (if that's what it's called!) for x, y, z has an effect on yaml. Have they not already been declared? I just have a funny feeling that something weird is going on under the hood.
I actually had no real purpose when extending those classes, except to try and get them to expose x, y, z values to yaml. It worked in that instnce, I have no Idea how, and was unable to do anything similar for other types. The workaround only partially worked (ie, it does not work on objects created in the sketchup ui).
@unknownuser said:
You can do anything you want FOR YOUR OWN USE.
BUT Google OWNS the Sketchup, UI, and Geom Namespaces. The Terms of use prevent you from causing other people's installations of Sketchup to be degraded or broken or such. The license agreement is at: http://sketchup.google.com/intl/en/download/license.html
At the very least, if you wanted to extend Sketchup classes (and release those extensions,) you'd need to have Google Sketchup Team consent AND Sketchup Developer Community approval.
You might join the SKX project, or monitor the SKX forum.Normally I would have given up trying to get yaml to work and come up with my own alternative way of transmitting the object information via text through stdio, but I have thought of another interesting concept, the possibility of using other languages such as python or java with sketchup... with yaml. If there is no interest in that, and I can't find a quick fix to this problem I have with yaml, then I'll drop that Idea!
I think I need to learn how yaml works (on the inside) in order to find out why it struggles with sketchup.
I did have one Idea for a work around, and that was to deep copy the objects created in sketchup to what I have dubbed (if my theory is correct) a "True Ruby Object" and then use the .extend method to append the yaml methods on the objects. In order to do this I guess it would be easiest to make the change to the way yaml works (otherwise I may as well just copy all the attributes manually!).
By having my own copy of the objects, and then using the .extend method will I still be voiding this license aggreement?
A big problem I think I can see with that Idea is performance. Having a copy of every object doesn't seem like good, common sense to me!
Advertisement