I'm currently working on a chess-like game in c++ and was wondering if there were any pattern or good programming ways to check for messages between classes.
In my problem I have two classes, a boardSquare- and a GameBoard-class (BoardSquareManager). The boardsquare has functionality that when you click a square a boolean value will be set to true meaning the boardSquare has been clicked. Currently in the GameBoard-class I have an array of BoardSquares and in order to check if one boardsquare has been clicked I go through every BoardSquare each tick and see if anyone has been clicked, it looks like this.
void AGameBoard::CheckMessages()
{
for (int i = 0; i < 64; i++)
{
if (BoardSquareArray[i]->GetWasClicked())
{
iClickedTile = BoardSquareArray[i]->GetSquareNum();
BoardSquareArray[i]->DeactivateClick();
bTileWasClicked = true;
}
}
}
In my opinion it feels unnecessary to have to look through the entire array all the time just so I can get information if a tile has been clicked or not, do you know any better way of doing this on?
I appreciate all answers!
Have considered the Observer pattern? The classic Design Patterns book from E. Gamma contains a lot patterns which come from implementing GUI applications. Other patterns which are probably interesting are Command (do want to undo moves?), Decorator, Chain of Command, Composite, Strategy, Template Method. I would definitely recommend to read the book.
For now I have gone with making a static class which has a queue. I use this class to send messages from the BoardSquare to the Gameboard. (Making a static class might not be the "best" solution in long term goals but since this is a prototype I was figuring it might work out for now)
Code for Static MessageClass:
/*
* Public variables
*/
static void SendMsgToBoard(int& tile) { TileNumbers.push_back(tile); }
static int& RecieveMsgFromSquare() { return TileNumbers.front(); }
static void SquareMsgRecieved() { TileNumbers.pop_front(); }
static bool IsEmpty() { return TileNumbers.empty(); }
private:
/*
* Private Variables
*/
static std::deque<int> TileNumbers;
New Code for Boardsquare:
messagePasser::SendMsgToBoard(iSquareNum);
New Code for Gameboard:
if (!MessagePasser::IsEmpty())
{
if (IsTileOccupied)
{
//Do stuff...
}
else
//Do Other Stuff...
MessagePasser::SquareMsgRecieved();
}
Make some std::vector or std::stack and push there click events with coordinates of tile which was clicked. You can also make some onClick method which takes pointer do AGameBoard and sent to it message about clicked tile.
Search something on the internet about events handling.
Related
I am very new to C++, having only used Unrealscript previously, and I'm trying to write a relatively simple console game to teach myself the basics (using OneLoneCoder engine). I've set myself a goal of implementing pause/dialog screens which can call specific functions depending on player input (eg pressing Y or N when given an option, which could then lead to another dialog box, or something happening to the player). My first instinct was to create a base class like this:
wstring PauseText,PromptText;
PauseScreen CurrPauseScreen;
class PauseScreen
{
public:
virtual wstring GetPText()
{
return L"NO PAUSE TEXT";
}
virtual wstring GetPPText()
{
return L"NO PROMPT TEXT";
}
virtual void EFunc()
{
UnPause();
}
virtual void YFunc()
{
}
virtual void NFunc()
{
}
virtual void SetPrompts()
{
PauseText = GetPText();
PromptText = GetPPText();
}
PauseScreen()
{
SetPrompts();
}
~PauseScreen()
{
}
};
int main()
{
if (m_keys[L'E'].bPressed || m_keys[L'P'].bPressed)
{
CurrPauseScreen->EFunc();
}
else if (m_keys[L'Y'].bPressed)
{
CurrPauseScreen->YFunc();
}
else if (m_keys[L'N'].bPressed)
{
CurrPauseScreen->NFunc();
}
return 0;
}
and override functions as necessary. At the moment, I'm using a global CurrPauseScreen variable to store the currently used PauseScreen info, and simply take all necessary values and methods from that (remembering to delete it when game is unpaused or a new screen is created).
I initially attempted to use function pointers which pointed to class methods and didn't use the 'new' operator in order to avoid using heap memory because I know it's ill-advised, but I felt like I was chasing my own tail figuring out how to use them properly, as it doesn't seem easy to have a pointer point to a class method. Basically I want to know if there is a simpler way of setting/changing all necessary functions and variables through classes on a one-off basis, or if using classes and an Object-Oriented approach is advised at all in this situation, as from what I've seen through my google searching, it's often looked down upon in C++.
EDIT: The code I have at the moment works as I intended, but is just a little too 'messy' for my liking, having to place a class on the heap and ensure it's deleted appropriately at each step. Ideally I would like to simply instantiate a class on the stack and have the class handle all of the setting within itself, including changing the PauseText,PromptText and the various functions (EFunc(), YFunc() and NFunc()). Changing the text is easy enough, but changing function behaviour from within a class is where I am having the most trouble.
The code which I am working with is creating a bunch of objects from a sensor class. When the application receives a questions like : "report all broken sensors" I am Iterating over all of my sensors objects with the help of a static vector inside my sensor class.
public:
static std::vector<Sensor*>objList;
bool isBroken
std::vector<Sensor*>Sensor::objList;
Sensor::Sensor(ComponentId, component Id....){
...
objList.push_back(this);
...
}
Sensor::IsBroken(){
isBroken = adValue == broken
}
Then we can respond with
bool Logger::BrokenSensors(std::string ComponentName){
for ( auto i = Sensor::objList.begin(); i != Sensor::objList.end(); i++ ) {
if((*i)->GetStringId()==ComponentName){
return (*i)->isBroken;
}
}
return 0;
}
Is this considered to be bad practice? I cannot figure out a nicer way to do this. Also, the sensors objects are created from a bunch of difference places.
Yes, this design can be improved. You should consider separating what a sensor is from how many sensors your system has. Introduce a SensorManager which takes care of managing sensor lifetime and leave your Sensor class to only care about what a sensor should do.
class SensorManager
{
// maybe use a map<sensorid, shared_ptr<Sensor>> here instead?
vector<shared_ptr<Sensor>> sensors;
public:
void Add( /* parameters */ )
{
sensors.push_back(make_shared<Sensor>( /* parameters */ ));
}
vector<shared_ptr<Sensor>> GetBrokenSensors()
{
// Your logic goes here.
}
void RemoveSensor( /* some sort of Id */ )
{
// remove this sensor from sensors.
}
// rest of stuff
};
I have left a lot of open details here, like whether your sensors have shared or unique ownership, how exactly their life time is controlled, how are they identified etc.
It depends.
If you need to check for all the sensors regularly, so there is no way except looping over them like you did.
However, if what you need is to only spot the broken sensor, a better pattern to follow is the observer design pattern, which simply lets every sensor class reports it's failure to the main component once it happens.
You can also find a C++ implementation for it here.
I am implementing some Deep Learning Neural Networks and existing code from Matlab normaly just prints out to the console such users have an idea of progress.
When I am doing my design for C++ and have put core parts of the algorithms into separate functions that I do not want to print stuff out to the console, are there ways or design principles for leaving a option to the users who use the algorithm to get some kind of progress indication?
Could one let a optional parameter be a function pointer that people could hook into, or how would I do this?
void my_heavy_algorithm(int * data, int n,...);
If you are exposing your algorithm as a collection of functions then the way to go would be to have one of the parameters be a function pointer with a signature like this:
void (*reportProgress)(void*, int)
But if you are designing your algorithm in C++ you should probably take advantage of encapsulation and create a class (or set of classes) for your algorithm. In this case you wouldn't want to add the function pointer as a parameter to the individual functions.
Rather you might make the function pointer a member of your class. And have accessor methods to get/set it. Or even better, provide an abstract class for reporting progress.
class ProgressReporter
{
public:
virtual ~ProgressReporter() = 0;
virtual void notifyProgressChanged(void* source, int progressValue) = 0;
}
class Algo
{
private:
ProgressReporter* _userProvidedReporter = NULL;
public:
void set_ProgressReporter(ProgressReporter*); // set accessor
ProgressReporter* get_ProgressReporter(); // get accessor
void my_heavy_algorithm(int*, int, ...); // your algo. implementation fn.
}
void Algo::set_ProgressReporter(ProgressReporter* reporter){
_userProvidedReporter = reporter;
}
ProgressReporter* Algo::get_ProgressReporter(){
return _userProvidedReporter;
}
void Algo::my_heavy_algorithm(int * data, int n,...){
// do stuff
if(_userProvidedReporter != NULL)
_userProvidedReporter->notifyProgressChanged((void*)this, currentProgress);
// do more stuff
if(_userProvidedReporter != NULL)
_userProvidedReporter->notifyProgressChanged((void*)this, currentProgress);
// so on and so forth..
}
Of course the above is a pretty simplistic example. If you expect your algorithms to support concurrency you should synchronize access to the internal user reporter and you might consider creating a base class for your algorithm and provide concrete derived implementations..
STL style functors may help you. This would also allow yor algorithm be used withoud any progress indicator.
For example, let's say you'd like to give a percent progress indicator.
// disclaimer - I didn't compile this code
class NoProgressFeedback; // see below
void my_heavy_algorithm(int * data, int n, ProgressFeedback giveFeedback = NoProgressFeedback() {
int percentProgress = 0;
giveFeedback(percentProgress);
/* start calculations, do stuff */
percentProgress++;
giveFeedback(percentProgress);
/* continue over and repeat percentProgress updates and giveFeedback calls */
}
/* NoProgressFeedback will do no progress feedback */
class NoProgressFeedback {
public:
operator()(int percent) {}
}
If user code wants feedback, then it should pass your my_heavy_algorithm function a different progress indicator, that sould look like this:
class GetProgressFeedback {
public:
void operator()(int percent) { std::cout << "percent advance: " << percent; }
}
Take a look at Dependancy Injection.
You can pass an object that implements an IProgress interface. A NullProgress object could just have the stubs but does no real work for objects you aren't interested in monitoring.
The usual way is to run your computationally heavy work in seperate thread and use that to update a section of memory via a lock. The UI thread then reads periodically from this memory location and updates the screen accordingly.
To report proper progress, you need three things:
An estimate of the total work to be done.
An estimate of how much work has been done so far.
A source of time.
You also need some way for your "heavy math" function to "report in". One way to do that is to have some sort of function that you call in the "start of function", "progress so far" and "end of function". The start of function also sets "total amount of work to do". Progress so far reports "how much is done now", and "end of function" says "I'm complete".
In a C++ class environment, this could be done as:
class Progress
{
Progress() { };
virtual void Start(int todo) = 0;
virtual void Done(int doneSoFar) = 0;
virtual void Finish();
};
This provides an interface that other classes can be derived from.
Of course, you still need to find a useful pace to put your "Done()" - if you put it too deep inside some tight loop, it will impact performance, but you need to do it often enough that it shows some useful progress too.
I'm in a bit of a pickle: say I'm making a simple, 2D, Zelda-like game.
When two Objects collide, each should have a resulting action. However, when the main character collides with something, his reaction depends solely on the type of the object with which he collided. If it's a monster, he should bounce back, if it's a wall, nothing should happen, if it's a magical blue box with ribbons, he should heal, etc. (these are just examples).
I should also note that BOTH things are part of the collision, that is, collision events should happen for both the character AND the monster, not just one or the other.
How would you write code like this? I can think of a number of incredibly inelegant ways, for instance, having virtual functions in the global WorldObject class, to identify attributes - for instance, a GetObjectType() function (returns ints, char*s, anything that identifies the object as Monster, Box, or Wall), then in classes with more attributes, say Monster, there could be more virtual functions, say GetSpecies().
However, this becomes annoying to maintain, and leads to a large cascading switch (or If) statement in the collision handler
MainCharacter::Handler(Object& obj)
{
switch(obj.GetType())
{
case MONSTER:
switch((*(Monster*)&obj)->GetSpecies())
{
case EVILSCARYDOG:
...
...
}
...
}
}
There's also the option of using files, and the files would have things like:
Object=Monster
Species=EvilScaryDog
Subspecies=Boss
And then the code can retrieve the attributes without the need for virtual functions cluttering everything up. This doesn't solve the cascading If problem, however.
And THEN there's the option of having a function for each case, say CollideWall(), CollideMonster(), CollideHealingThingy(). This is personally my least favourite (although they're all far from likeable), because it seems the most cumbersome to maintain.
Could somebody please give some insight into more elegant solutions to this problem?
Thanks for any and all help!
I would do it vice versa - because if the character collides with an object, an object collides with the character as well. Thus you can have a base class Object, like this:
class Object {
virtual void collideWithCharacter(MainCharacter&) = 0;
};
class Monster : public Object {
virtual void collideWithCharacter(MainCharacter&) { /* Monster collision handler */ }
};
// etc. for each object
Generally in OOP design virtual functions are the only "correct" solution for cases like this:
switch (obj.getType()) {
case A: /* ... */ break;
case B: /* ... */ break;
}
EDIT:
After your clarification, you will need to adjust the above a bit. The MainCharacter should have overloaded methods for each of the objects it can collide with:
class MainCharacter {
void collideWith(Monster&) { /* ... */ }
void collideWith(EvilScaryDog&) { /* ... */ }
void collideWith(Boss&) { /* ... */ }
/* etc. for each object */
};
class Object {
virtual void collideWithCharacter(MainCharacter&) = 0;
};
class Monster : public Object {
virtual void collideWithCharacter(MainCharacter& c)
{
c.collideWith(*this); // Tell the main character it collided with us
/* ... */
}
};
/* So on for each object */
This way you notify the main character about the collision and it can take appropriate actions. Also if you need an object that should not notify the main character about the collision, you can just remove the notification call in that particular class.
This approach is called a double dispatch.
I would also consider making the MainCharacter itself an Object, move the overloads to Object and use collideWith instead of collideWithCharacter.
How about deriving all collidable objects from one common abstract class (let's call it Collidable). That class could contain all properties that can be changed by a collission and one HandleCollision function. When two objects collide, you just call HandleCollision on each object with the other object as the argument. Each object manipulates the other to handle the collision. Neither object needs to know what other object type it just bounced into and you have no big switch statements.
Make all colidable entities implement an interface (lets say "Collidable") with a collideWith(Collidable) method.
Then, on you collision detection algorithm, if you detect that A collides with B, you would call:
A->collideWith((Collidable)B);
B->collideWith((Collidable)A);
Assume that A is the MainCharacter and B a monster and both implement the Collidable interface.
A->collideWith(B);
Would call the following:
MainCharacter::collideWith(Collidable& obj)
{
//switch(obj.GetType()){
// case MONSTER:
// ...
//instead of this switch you were doing, dispatch it to another function
obj->collideWith(this); //Note that "this", in this context is evaluated to the
//something of type MainCharacter.
}
This would in turn call the Monster::collideWith(MainCharacter) method and you can implement all monster-character behaviour there:
Monster::CollideWith(MainCharacter mc){
//take the life of character and make it bounce back
mc->takeDamage(this.attackPower);
mc->bounceBack(20/*e.g.*/);
}
More info: Single Dispatch
Hope it helps.
What you call "an annoying switch statement" i would call "a great game" so you are on the right track.
Having a function for every interaction/game rule is exactly what I would suggest. It makes it easy to find, debug, change and add new functionality:
void PlayerCollidesWithWall(player, wall) {
player.velocity = 0;
}
void PlayerCollidesWithHPPotion(player, hpPoition) {
player.hp = player.maxHp;
Destroy(hpPoition);
}
...
So the question is really how to detect each of these cases. Assuming you have some sort of collision detection that results in X and Y collide (as simple as N^2 overlap tests (hey, it works for plants vs zombies, and that's got a lot going on!) or as complicated as sweep and prune + gjk)
void DoCollision(x, y) {
if (x.IsPlayer() && y.IsWall()) { // need reverse too, y.IsPlayer, x.IsWall
PlayerCollidesWithWall(x, y); // unless you have somehow sorted them...
return;
}
if (x.IsPlayer() && y.IsPotion() { ... }
...
This style, while verbose is
easy to debug
easy to add cases
shows you when you have
logical/design inconsistencies or
omissions "oh what if a X is both a
player and a wall due to the
"PosessWall" ability, what then!?!"
(and then lets you simply add cases
to handle those)
Spore's cell stage uses exactly this style and has approximately 100 checks resulting in about 70 different outcomes (not counting the param reversals). It's only a ten minute game, that's 1 new interaction every 6 seconds for the whole stage - now that's gameplay value!
If I am getting your problem correctly, I would sth like
Class EventManager {
// some members/methods
handleCollisionEvent(ObjectType1 o1, ObjectType2 o2);
// and do overloading for every type of unique behavior with different type of objects.
// can have default behavior as well for unhandled object types
}
Warning: This is super in-depth. I understand if you don't even want to read this, this is mostly for me to sort out my thought process.
Okay, so here's what I'm trying to do. I've got these objects:
When you click on one (or select several) it should display their properties on the right (as shown). When you edit said properties it should update the internal variables immediately.
I'm trying to decide on the best way to do this. I figure the selected objects should be stored as a list of pointers. It's either that, or have an isSelected bool on each object, and then iterate over all of them, ignoring the non-selected ones, which is just inefficient. So we click on one, or select several, and then the selectedObjects list is populated. We then need to display the properties. To keep things simple for the time being, we'll assume that all objects are of the same type (share the same set of properties). Since there aren't any instance-specific properties, I figure we should probably store these properties as static variables inside the Object class. Properties basically just have a name (like "Allow Sleep"). There is one PropertyManager for each type of property (int,bool,double). PropertyManagers store all the values for properties of their respective type (this is all from the Qt API). Unfortunately, because PropertyManagers are required to create Properties I can't really decouple the two. I suppose this means that I have to place the PropertyManagers with the Properties (as static variables). This means we have one set of properties, and one set of property managers to manage all the variables in all the objects. Each property manager can only have one callback. That means this callback has to update all the properties of its respective type, for all objects (a nested loop). This yields something like this (in pseudo-code):
function valueChanged(property, value) {
if(property == xPosProp) {
foreach(selectedObj as obj) {
obj->setXPos(value);
}
} else if(property == ...
Which already bothers me a little bit, because we're using if statements where we shouldn't need them. The way around this would be to create a different property manager for every single property, so that we can have unique callbacks. This also means we need two objects for each property, but it might be a price worth paying for cleaner code (I really don't know what the performance costs are right now, but as I know you'll also say -- optimize when it becomes a problem). So then we end up with a ton of callbacks:
function xPosChanged(property, value) {
foreach(selectedObj as obj) {
obj->setXPos(value);
}
}
Which eliminates the entire if/else garbage but adds a dozen more event-listeners. Let's assume I go with this method. So now we had a wad of static Properties, along with their corresponding static PropertyManagers. Presumably I'd store the list of selected objects as Object::selectedObjects too since they're used in all the event callbacks, which logically belong in the object class. So then we have a wad of static event callbacks too. That's all fine and dandy.
So now when you edit a property, we can update the interal variables for all the selected objects via the event callback. But what happens when the internal variable is updated via some other means, how do we update the property? This happens to be a physics simulator, so all the objects will have many of their variables continuously updated. I can't add callbacks for these because the physics is handled by another 3rd party library. I guess this means I just have to assume all the variables have been changed after each time step. So after each time step, I have to update all the properties for all the selected objects. Fine, I can do that.
Last issue (I hope), is what values should we display when multiple objects are selected an there is an inconsistency? I guess my options are to leave it blank/0 or display a random object's properties. I don't think one option is much better than the other, but hopefully Qt provides a method to highlight such properties so that I can at least notify the user. So how do I figure out which properties to "highlight"? I guess I iterate over all the selected objects, and all their properties, compare them, and as soon as there is a mismatch I can highlight it. So to clarify, upon selected some objects:
add all objects to a selectedObjects list
populate the properties editor
find which properties have identical values and update the editor appropriately
I think I should store the properties in a list too so that I can just push the whole list onto the properties editor rather than adding each property individually. Should allow for more flexibility down the road I think.
I think that about covers it... I'm still not certain how I feel about having so many static variables, and a semi-singleton class (the static variables would be initialized once when the first object is created I guess). But I don't see a better solution.
Please post your thoughts if you actually read this. I guess that's not really a question, so let me rephrase for the haters, What adjustments can I make to my suggested design-pattern to yield cleaner, more understandable, or more efficient code? (or something along those lines).
Looks like I need to clarify. By "property" I mean like "Allow Sleeping", or "Velocity" -- all objects have these properties -- their VALUES however, are unique to each instance. Properties hold the string that needs to be displayed, the valid range for the values, and all the widget info. PropertyManagers are the objects that actually hold the value. They control the callbacks, and the value that's displayed. There is also another copy of the value, that's actually used "internally" by the other 3rd party physics library.
Trying to actually implement this madness now. I have an EditorView (the black area drawing area in the image) which catches the mouseClick event. The mouseClick events then tells the physics simulator to query all the bodies at the cursor. Each physics body stores a reference (a void pointer!) back to my object class. The pointers get casted back to objects get pushed onto a list of selected objects. The EditorView then sends out a signal. The EditorWindow then catches this signal and passes it over to the PropertiesWindow along with the selected objects. Now the PropertiesWindow needs to query the objects for a list of properties to display... and that's as far as I've gotten so far. Mind boggling!
The Solution
/*
* File: PropertyBrowser.cpp
* Author: mark
*
* Created on August 23, 2009, 10:29 PM
*/
#include <QtCore/QMetaProperty>
#include "PropertyBrowser.h"
PropertyBrowser::PropertyBrowser(QWidget* parent)
: QtTreePropertyBrowser(parent), m_variantManager(new QtVariantPropertyManager(this)) {
setHeaderVisible(false);
setPropertiesWithoutValueMarked(true);
setIndentation(10);
setResizeMode(ResizeToContents);
setFactoryForManager(m_variantManager, new QtVariantEditorFactory);
setAlternatingRowColors(false);
}
void PropertyBrowser::valueChanged(QtProperty *property, const QVariant &value) {
if(m_propertyMap.find(property) != m_propertyMap.end()) {
foreach(QObject *obj, m_selectedObjects) {
obj->setProperty(m_propertyMap[property], value);
}
}
}
QString PropertyBrowser::humanize(QString str) const {
return str.at(0).toUpper() + str.mid(1).replace(QRegExp("([a-z])([A-Z])"), "\\1 \\2");
}
void PropertyBrowser::setSelectedObjects(QList<QObject*> objs) {
foreach(QObject *obj, m_selectedObjects) {
obj->disconnect(this);
}
clear();
m_variantManager->clear();
m_selectedObjects = objs;
m_propertyMap.clear();
if(objs.isEmpty()) {
return;
}
for(int i = 0; i < objs.first()->metaObject()->propertyCount(); ++i) {
QMetaProperty metaProperty(objs.first()->metaObject()->property(i));
QtProperty * const property
= m_variantManager->addProperty(metaProperty.type(), humanize(metaProperty.name()));
property->setEnabled(metaProperty.isWritable());
m_propertyMap[property] = metaProperty.name();
addProperty(property);
}
foreach(QObject *obj, m_selectedObjects) {
connect(obj, SIGNAL(propertyChanged()), SLOT(objectUpdated()));
}
objectUpdated();
}
void PropertyBrowser::objectUpdated() {
if(m_selectedObjects.isEmpty()) {
return;
}
disconnect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)),
this, SLOT(valueChanged(QtProperty*, QVariant)));
QMapIterator<QtProperty*, QByteArray> i(m_propertyMap);
bool diff;
while(i.hasNext()) {
i.next();
diff = false;
for(int j = 1; j < m_selectedObjects.size(); ++j) {
if(m_selectedObjects.at(j)->property(i.value()) != m_selectedObjects.at(j - 1)->property(i.value())) {
diff = true;
break;
}
}
if(diff) setBackgroundColor(topLevelItem(i.key()), QColor(0xFF,0xFE,0xA9));
else setBackgroundColor(topLevelItem(i.key()), Qt::white);
m_variantManager->setValue(i.key(), m_selectedObjects.first()->property(i.value()));
}
connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)),
this, SLOT(valueChanged(QtProperty*, QVariant)));
}
With a big thanks to TimW
Did you have a look at Qt's (dynamic) property system?
bool QObject::setProperty ( const char * name, const QVariant & value );
QVariant QObject::property ( const char * name ) const
QList<QByteArray> QObject::dynamicPropertyNames () const;
//Changing the value of a dynamic property causes a
//QDynamicPropertyChangeEvent to be sent to the object.
function valueChanged(property, value) {
foreach(selectedObj as obj) {
obj->setProperty(property, value);
}
}
Example
This is an incomplete example to give you my idea about the property system.
I guess SelectableItem * selectedItem must be replaced with a list of items in your case.
class SelectableItem : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName );
Q_PROPERTY(int velocity READ velocity WRITE setVelocity);
public:
QString name() const { return m_name; }
int velocity() const {return m_velocity; }
public slots:
void setName(const QString& name)
{
if(name!=m_name)
{
m_name = name;
emit update();
}
}
void setVelocity(int value)
{
if(value!=m_velocity)
{
m_velocity = value;
emit update();
}
}
signals:
void update();
private:
QString m_name;
int m_velocity;
};
class MyPropertyWatcher : public QObject
{
Q_OBJECT
public:
MyPropertyWatcher(QObject *parent)
: QObject(parent),
m_variantManager(new QtVariantPropertyManager(this)),
m_propertyMap(),
m_selectedItem(),
!m_updatingValues(false)
{
connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)), SLOT(valueChanged(QtProperty*,QVariant)));
m_propertyMap[m_variantManager->addProperty(QVariant::String, tr("Name"))] = "name";
m_propertyMap[m_variantManager->addProperty(QVariant::Int, tr("Velocity"))] = "velocity";
// Add mim, max ... to the property
// you could also add all the existing properties of a SelectableItem
// SelectableItem item;
// for(int i=0 ; i!=item.metaObject()->propertyCount(); ++i)
// {
// QMetaProperty metaProperty(item.metaObject()->property(i));
// QtProperty *const property
// = m_variantManager->addProperty(metaProperty.type(), metaProperty.name());
// m_propertyMap[property] = metaProperty.name()
// }
}
void setSelectedItem(SelectableItem * selectedItem)
{
if(m_selectedItem)
{
m_selectedItem->disconnect( this );
}
if(selectedItem)
{
connect(selectedItem, SIGNAL(update()), SLOT(itemUpdated()));
itemUpdated();
}
m_selectedItem = selectedItem;
}
private slots:
void valueChanged(QtProperty *property, const QVariant &value)
{
if(m_updatingValues)
{
return;
}
if(m_selectedItem && m_map)
{
QMap<QtProperty*, QByteArray>::const_iterator i = m_propertyMap.find(property);
if(i!=m_propertyMap.end())
m_selectedItem->setProperty(m_propertyMap[property], value);
}
}
void itemUpdated()
{
m_updatingValues = true;
QMapIterator<QtProperty*, QByteArray> i(m_propertyMap);
while(i.hasNext())
{
m_variantManager->next();
m_variantManager->setValue(
i.key(),
m_selectedItem->property(i.value()));
}
m_updatingValues = false;
}
private:
QtVariantPropertyManager *const m_variantManager;
QMap<QtProperty*, QByteArray> m_propertyMap;
QPointer<SelectableItem> m_selectedItem;
bool m_updatingValues;
};
Calm down, your code has not O(n^2) complextity. You have a nested loop, but only one counts to N (the number of objects), the other counts to a fixed number of properties, which is not related to N. So you have O(N).
For the static variables, you write "there aren't any instance-specific properties", later you write about updates of the individual properties of your objects, which are exactly instance-specific properties. Maybe you are confusing the "class Properties" (which is of course shared among all properties) with the individual properties? So I think you don't need static members at all.
Do you want to display changes to the objects only if they appear, or do you want a continuos display? If your hardware is able to handle the latter, I would recommend going that way. In that case, you have to iterate over all objects anyway and update them along the way.
Edit: The difference is that in the former (update on change) the drawing is initiated by the operation of changing the values, for example a object movement. For the latter, a continuos display, you would add a QTimer, which fires say 60 times a second and calls a SLOT(render()) which does the actual rendering of all objects. Depending on the rate of changes this may actually be faster. And it is probably easier to implement.
Another possibilty is let Qt handle the whole drawing, using a Graphics View, which handles the objects-to-draw internally in a very efficient tree structure. Take a look at
http://doc.trolltech.com/4.5/graphicsview.html
If you want to display only the changes, you could use individual callbacks for each properties value. Each time the value of a property is changed (in this case making the properties vlaues private and using setSomeThing(value)), you call the update function with an emit(update()). If you are absolutly concernd about emit being slow, you could use "real" callbacks via function pointers, but I don't recommend that, Qt's connect/signal/slot is so much easier to use. And the overhead is in most cases really neglible.