michael.zhang Posted August 9, 2011 Share Posted August 9, 2011 Functions such as: engine.controls.setKeyPressCallback("WindowsControls::keyPressed"); The given callback function seems to need to be a global function. Is there any way we can use a member function, since I would like my WindowsControls to be an object. Link to comment
danni.coy Posted August 9, 2011 Share Posted August 9, 2011 Functions such as: engine.controls.setKeyPressCallback("WindowsControls::keyPressed"); The given callback function seems to need to be a global function. Is there any way we can use a member function, since I would like my WindowsControls to be an object. Kind of... It's a bit ugly but it looks like this. class Foo { Foo() { setCallback("Foo::button_clicked_",this); } void button_clicked_(Foo foo) { foo.button_clicked();} void button_clicked() { // do actual code here } }; the underscore at the end of the called function is just a convention I use. magic is in passing the object itself. Link to comment
michael.zhang Posted August 19, 2011 Author Share Posted August 19, 2011 Hey, I finally got around to giving this a try. However: setKeyPressedCallback() takes only 1 argument. Your method works for setContactCallback for example, but doesn't seem to work for setKeyPressedCallback/setKeyRelease etc. Link to comment
manguste Posted August 24, 2011 Share Posted August 24, 2011 Try the following: Foo { void KeyPressed(int a) { "my code\n" }; } Foo foo; void KeyPressed(int a) { foo.KeyPressed(a); } Link to comment
michael.zhang Posted August 24, 2011 Author Share Posted August 24, 2011 Hi Manguste, Thanks you for the suggestion. I had already been using that approach. class WindowsControls : Controls{ WindowsControls(ActionInterface actionInterface); ~WindowsControls(); void update(); void keyReleased(int key); void keyPressed(int key); void buttonPressed(int button); }; namespace Windows{ WindowsControls controls; } I also enclosed the global variable into a namespace. However, I'm not a big fan of this, as this approach effectively makes the class to be a singleton. I think Unigine should implement something like this: #ifndef CALLBACK_H_ #define CALLBACK_H_ class Callback{ string function; int argc; int a; int b; int c; Callback(string function, int argc = 0, int a = 0, int b = 0, int c = 0); int callback(); int callback0(); int callback1(); int callback2(); int callback3(); }; void Callback::__Callback__(string function, int argc = 0, int a = 0, int b = 0, int c = 0){ this.function = function; this.argc = argc; this.a = a; this.b = b; this.c = c; } int Callback::callback(){ return call("callback" + string(argc)); } int Callback::callback0(){ return call(function); } int Callback::callback1(){ return call(function, a); } int Callback::callback2(){ return call(function, a, :); } int Callback::callback3(){ return call(function, a, b, c); } class MemberCallback : Callback{ int object; MemberCallback(int object, string function, int argc = 0, int a = 0, int b = 0, int c = 0); int callback0(); int callback1(); int callback2(); int callback3(); }; void MemberCallback::__MemberCallback__(int object, string function, int argc = 0, int a = 0, int b = 0, int c = 0){ Callback::__Callback__(function, a, b, c); this.object = object; } int MemberCallback::callback0(){ if(object != NULL){ return object.call(function); }else{ return call(function); } } int MemberCallback::callback1(){ if(object != NULL){ return object.call(function, a); }else{ return call(function, a); } } int MemberCallback::callback2(){ if(object != NULL){ return object.call(function, a, B); }else{ return call(function, a, B); } } int MemberCallback::callback3(){ if(object != NULL){ return object.call(function, a, b, c); }else{ return call(function, a, b, c); } } #endif I've only implemented up to 3 args, since I rarely write functions with more than 3 args. Link to comment
manguste Posted August 30, 2011 Share Posted August 30, 2011 You are right, this seems like a more convenient callback implementation. Our developers will take notice of your suggestion, thank you. Link to comment
michael.zhang Posted August 30, 2011 Author Share Posted August 30, 2011 Awesome. Just so you know, the implementation posted was written moments before posting... so likely bugs abound :) Has not been tested. A few corrections have been made since: void MemberCallback::__MemberCallback__(int object, string function, int argc = 0, int a = 0, int b = 0, int c = 0){ __Callback__(function, argc, a, b, c); this.object = object; } This second modification brings into question why a polymorphic call from an inherited method does not call the subclass' method? Or, is it because the call() does not consider polymorphism? // forced to add this: int MemberCallback::callback(){ return call("callback" + string(argc)); } To clarify, without the above identical overriding of the superclass' callback() if you have: int Callback::callback0(){ log.message("super"); // for debug purposes return 1; } int MemberCallback::callback0(){ log.message("subclass"); // for debug purposes return 1; } Callback cb = new MemberCallback(obj, "function", 1); cb.callback(); // this call calls superclass' inherited implementation // but superclasses' implementation will now execute: call("callback0"); // Polymorphic call would call MemberCallback::callback0 and print "subclass" // Instead, we get a console print out of: "super" // Which indicates that despite the class being a MemberCallback, the inherited implementation calls upon the super class' callback0 Link to comment
manguste Posted September 5, 2011 Share Posted September 5, 2011 The reason is that in its current implementation call() does not know anything about virtual functions. Link to comment
Recommended Posts