Non Maya c++ object attribute in a MPxNode - c++

I'm developing a C++ plugin and I would like to know a way to work with a non-Maya class objects through the scene. I mean, I want to have an instance of a class external to Maya API as attribute of the Node class. The class is quite complex and is composed by multiple classes.
What I've seen is that a Node can give me Structured Data Storage, but as far as I know it works only with Maya types which is not enough for my purposes.
Right now I'm using MPxCommand to execute the computation of that object, but once it has finished, it's destroyed. I want to keep it alive in the scene so I need to use Nodes somehow. At the moment it's not necessary storing the data.
So, do you know a way to do the equivalent in Maya of a typical OOP class? I've not found any example in the devkit or documentation.
class Foo : public MPxNode
{
public:
Foo () {};
virtual ~Foo () {};
virtual MStatus compute(const MPlug& plug, MDataBlock& data);
static void* creator();
static MStatus initialize();
static MObject inputMesh;
static MTypeId id;
// I want to keep it alive through the scene.
// static ClassBar myBarObject; // How can I do this??
// barFunction(...); // use ClassBar myBarObj
};
MObject Foo::inputMesh;
MTypeId Foo::id( 0x80000 );
//ClassBar Foo::myBarObj; // ????
Thank you very much

No, there is no way for you to create a Maya node from a pure OOP point of view and derive from what ever classes coming from our libraries. Maya MPxNode is a proxy class which encapsulate the Maya internal node logic. However, when you implement a custom node, you describe what the attributes should be, so Maya can work with your data and create connections in the DG. The way to set, and process the attribute is up to you. You would need to put your own logic in the computer() method when Maya request an attribute value to be re-computed.
For further details on custom nodes and libraries integration, see the articles posted there
http://around-the-corner.typepad.com/

Related

software architecture - how should a plugin get information from caller (c++?)

say that we have some process and it uses a plugin to do an unknown implementation -
so the plugin implements an header and called with virtual functions to do some work.
now what if the plugin wants data back from the main process? get some gui stuff or other changed states of objects that cannot given at the time the virtual function was called ?
easiest thing to do is to make the interface bi -directional so plugin can ask questions
but it feels wrong to me.
i have read that interfaces should be one directional and actually i should have input and output interface for the plugin , but is still not answering the basic question of how to get data from the caller?
class A
{
...
void doWork()
{
plugin->doWorkInPlugin();
}
private:
MYinterafce* plugin;
}
class MYinterface
{
virtual doWorkInPlugin();
...
}
class MYPlugin : public MYinterface
{
doWorkInPlugin();
{
**** i want to know something in class A or GUI status or class Z ***
output->hello("blah");
}
private:
MYoutputInterface *output;
}
update * clarify why i use empty parameter in the function *
the thing is doWorkInPlugin is long running function ,mayby in thread needs to know changed states of objects that changed after the call has been made

Q_PROPERTY with parameterized read and write accessors

I have a Configuration that holds some basic information about file locations like download, install, picture, music, document etc. location.
These are currently exposed to QML using Q_PROPERTY. They all have their own accessors:
Q_PROPERTY(QUrl download_location READ download_location WRITE set_download_location NOTIFY download_location_changed)
These accessors basically do all the same stuff and I'd like to get rid of all this redundant code I have to write.
My first idea is to have a little nested class FileLocation that provides get, set and validation functions. But then, how would I connect these to the Q_PROPERTY?
Also, if I had something like a static functions which took parameters, (e.g. check_validity( QUrl location )), how would I hand over this parameter from QML side?
I think I'm on the wrong path here, so my question is how to keep redundant code in the context of Q_PROPERTY within reasonable limits, avoiding to write loads and loads of get, set and changed functions for very similar objects?
Here's some more code:
class Configuration : public QObject
{
QObject
Q_PROPERTY(QUrl download_location READ download_location WRITE set_download_location NOTIFY download_location_changed)
Q_PROPERTY(QUrl music_location READ music_location WRITE set_music_location NOTIFY music_location_changed)
...
signals:
void download_location_changed();
void music_location_changed();
...
public slots:
void set_download_location(QUrl location)
{
download_location = location;
emit download_location_changed(download_location);
}
void set_music_location(QUrl location)
{
music_location = location;
emit music_location_changed(music_location);
}
...
private:
QUrl download_location,
music_location,
...;
}
So as you see there's a lot of recurring code that does the same, and I'd like to damp that down a little. How do I do that? I was thinking about some general functions set, get, changed etc. that get the member to work on was a parameter. But then I didn't know how to hand over which member to work on from qml.
I just found out about the possibility to expose C++ classes to qml via qmlRegisterType(...) - maybe this is the way to go here?
You could go for an evil macro:
#define IMPL(data, name) \
inline decltype(data) name() const { return data; } \
inline void set_##name(decltype(data) value) { if (value != data) { data = value; emit name##Changed();} }
Of course, if you don't need any extra stuff, you can simply use a MEMBER property and have Qt auto generate accessors for you.
This will however not work if you need to do custom things in the accessors, the macro will, just add your stuff to it.
Lastly, when you declare a Q_PROPERTY, you can right-click the property, go to refactoring, and select "generate missing members...", Qt will generate the default stubs for the accessors, and you will only have to add your custom stuff in. The downside to this is it has the nasty habit of putting the generated code in the silliest place possible, so if you want your class to look neat, you have to move it by hand.
qmlRegisterType() is when you want to register a type so it can be created in QML, you generally don't have to do anything to access a QObject derived object from QML - it works for QObject derivatives, you only need to register a metatype for types which do not have meta information generated.
Last but not least - I don't see any point in having your configuration as a C++ object, you can just as well do it in QML, and use Qt.labs.settings to make your settings persistent. C++ is optimal for performance critical parts only. If you do your configuration in QML, you don't need to worry about any of that boilerplate code, as it is all automatic in QML, no need to write accessors, no need to recompile your project on every tiny change.

How would I separate this class?

I'm learning computer graphics and OpenGL, and I load models from my own binary format with a JSON manifest file to keep track of the assets.
The Model class I have right now keeps track of the OpenGL objects necessary to draw it with, as well as handling the processing of the 3D model files:
class Model
{
public:
Model(const std::string &filename);
// read the manifest
// load the appropriate binary files
// finally make the OpenGL objects this class keeps track of
// ... etc, like draw()
private:
// handles for various OpenGL objects
}
I would like to separate the file processing from the bookkeeping of OpenGL graphics stuff as I feel like that's too much responsibility for a single class. How would I go about doing that?
I thought about making a ModelLoader class, but I don't think there's any state that needs keeping track of in order to load this. So maybe I should make it a function inside a ModelLoader namespace. I played around with it but ended up with:
// ModelLoader.hpp
#include "Model.hpp"
namespace ModelLoader
{
Model load(const std::string &filename);
}
// ModelLoader.cpp
#include "ModelLoader.hpp"
Model ModelLoader::load()
{
return Model();
}
// Model.hpp
class Model;
namespace ModelLoader
{
Model load();
};
class Model
{
friend Model ModelLoader::load();
public:
// ... etc, like draw()
private:
Model(const std::string &filename); // accessible only through ModelLoader::load()
// handles for various OpenGL objects
}
There was a circular dependency between Model and ModelLoader, and what I have up there was the only way I could get it to compile. But as you can see, that kind of defeats the purpose of the declarations inside ModelLoader.hpp, plus it's duplicated code. I'm still not too good with C++ and object oriented design. Should I just go with what I had before? If I really wanted to separate file loading from bookkeeping, how should I do it? What's wrong with my attempts?
I'd recommend a slightly different approach. Make your class know how to serialize and deserialize itself from a stream.
That way you can use string streams, file streams, network streams, etc.

Class design for device driver and graphics

Banging my head on the wall trying to organize what I feel should be (and probably is) a simple set of relationships between some classes.
Basically trying to tie together 3 classes together in a way that makes sense.
Simplified scenario with 3 classes:
1 - LCD device driver
2 - Simple graphics library
3 - Counter display class
What I've got so far in pseudocode:
class Driver : public Graphics
{
public:
void loadImage(int * image){
// load image into device memory
}
};
class Graphics
{
public:
int image[10];
void displayImage(int * image){
// create/ manipulate image here and...
loadImage(image); //send to device
}
virtual void loadImage(int * image){}
};
class Counter
{
public:
int counterImage[10];
void makeCounter(int * counterImage){
//make a clock counter graphic and…
displayImage(counterImage);
}
};
Obviously, I've not figured out how to get the displayImage(counterImage) function integrated into the Counter class. I could virtual a version of displayImage() in the Counter class, but I'm assuming that that would entail that Graphics would always have to inherit Counter, which I'm not keen on. Is there a better way to allow Counter to access the Graphics class functions (ultimately passing through to the LCD driver) while still remaining separate from it?
Why do you want to use inheritance at all?
Based on the description on your classes, I don't see any specialization / kind of relation between them, which means you you should use composition in this case:
the graphics Driver needs the ability to display some Image (a type not present in your example)
the Graphics image loading library needs the ability to load an Image
the Counter display should use both a Driver and a Graphics, both given to it in its constructor, displaying the counter with them.
This concept is called composition over inheritance, you can get a lot more good articles on it with google. (Basically: OOP and using classes doesn't mean you have to use inheritance for everything)

C++/Qt - multiple inheritance with QGraphicsItem doesn't work as expected

I recently met a strange problem of my little program and it would be great if you help me to get the reason of this behavior.
My task is quiet simple - I want to use Qt Graphics Framework to show some objects and I want Box2D to calculate bodies position. So my class hierarchy looks like the following:
I have 1 base abstract class B2DObject. It contains some Box2D staff + some common parameters for its successors (names, some flags, etc.). It also has couple of pure virtual functions that will be reimplemented in successor classes.
Then I implement some classes that represent basic shapes: circles, rectangles, polygons, etc. I am doing it in the following way:
class ExtendedPolygon : public B2DObject, public QGraphicsPolygonItem { ... };
class ExtendedCircle : public B2DObject, public QGraphicsEllipseItem { ... };
etc.
(for those who are not familiar with Qt, QGraphics***Item is inherited from QGraphicsItem).
Also I inherited QGraphicsScene and reimplemented its mousePressEvent. In this function I request an object placed at some point on the screen using QGraphicsScene::itemAt function (which returns QGraphicsItem*), convert it to B2DObject* and try to get some internal field from this object:
void TestScene::mousePressEvent (QGraphicsSceneMouseEvent *event)
{
QGraphicsItem* item = itemAt (event->scenePos ());
if (item)
{
B2DObject* obj = reinterpret_cast < B2DObject* > (item);
QString objName = obj->Name(); // just for example,
// getting other internal fields has
// the same effect (described below)
// use retrieved field somehow (e.g. print in the screen)
}
// give the event to the ancestor
}
Unfortunately, dynamic_cast will not work here because these classes are completely unrelated.
Then I create necessary objects and add it to my scene:
ExtendedPolygon* polygon = new ExtendedPolygon (parameters);
polygon->setName (QString ("Object 1"));
...
TestScene scene;
scene.addItem (polygon);
(for those who are not familiar with Qt, here is the prototype of the last function:
void QGraphicsScene::addItem(QGraphicsItem *item);
I guess it just stores all items in internal index storage and calls QGraphicsItem::paint (...) when item needs to be repainted. I suppose QGraphicsScene doesn't make any significant changes to this item).
So my problems start when I run the program and click on an item on the screen. TestScene::mousePressEvent is called (see a piece of code above).
Mouse click position is retrieved, item is found. Casting works fine: in the debugger window (I'm using Qt Creator) I see that obj points to ExtendedPolygon (address is the same as when I add the item to the scene and in the debugger window I can see all the fields). But when I get some field, I receive garbage in any case (and it does not matter, what I'm trying to get - a QString or a pointer to some other structure).
So first of all, I would like to get any advice about my multiple inheritance. In 95% of cases I try to avoid it, but here it is very effective in the programming point of view. So I would appreciate it if you provide me with your point of view about the architecture of the classes hierarchy - does it even suppose to work as I expect it?
If on this level everything is quite fine, then it would be great if someone gets any idea why doesn't it work.
I have some ideas about workaround, but I really would like to solve this problem (just in order not to repeat the same error anymore).
Looks like I've found the root cause of my problem. It was just lack of knowledge regarding how multiple inheritance really works on data layer.
Let's assume that we have 2 basic classes, A and B. Each of them provides some internal data fields and some interfaces.
Then we create a derived class AABB, inheriting both A and B:
class AABB : public A, public B {...}
AABB could add some additional data fields and reimplement some of the interfaces, but it is not necessary.
Let's create and object of class AABB:
AABB* obj = new AABB ();
For example, obj points at address 0x8416e0. At this address starts data from ancestor class A. Data from ancestor class B starts with some offset (it should bw equal to sizeof (A)), for example, at 0x841700.
If we have some function f (B* b), and if we pass a pointer at AABB object to that function (like this: f (obj), obj is created above), actually not obj start address is passed, but rather a pointer at a start of B data section of AABB object.
Thus this misunderstanding of multiple inheritance inner works has led me to the problem I've got.
I guess Qobjects and multiple inheritance has been already treated. As an example: QObject Multiple Inheritance