Jump to content

[SOLVED] New Player-derived Class through API


photo

Recommended Posts

Hello,

 

We are trying to create a new sub-class of Player but can't seem to get it done through the API. For reference, the new Player class would be a combination of PlayerActor and PlayerSpectator, where users could switch between 'walking' and 'flying' with a button press.

 

I started with the example from the documentation (https://developer.unigine.com/en/docs/1.0/cpp_api/application) and added a new class successfully, just to test the C++ API implementation. But in trying to create a new class as an extension from Player caused a lot of problems, even though I am still just trying to mirror the exact functionality of PlayerDummy or PlayerSpectator. 

 

Here is the header file for PlayerGhost, to show the current approach

 

 

#ifndef PLAYERGHOST

#define PLAYERGHOST
 
#include <UnigineEngine.h>
#include <UnigineMathLib.h>
#include <UnigineWorld.h>
#include <UniginePlayer.h>
#include <UniginePlayerDummy.h>
#include <UnigineNode.h>
#include <vector>
#include "PlayerGhostInterface.h"
 
class PlayerGhost : public Unigine::PlayerDummy
{
protected:
 
template <class> friend class Unigine::Ptr;
 
private:
 
PlayerGhost();
virtual ~PlayerGhost();
 
std::vector<Unigine::NodePtr> nodes;
 
Unigine::NodePtr create_node(const char *name, const UNIGINE_MAT4 &transform);
 
void remove_node(Unigine::NodePtr node);
 
// copy player
PlayerGhost *copy(PlayerGhost *node) const;
 
mutable Unigine::vec3 direction;
 
::PlayerGhost *player;
 
public:
 
void player_init();
 
void player_shutdown();
 
static Unigine::Ptr<PlayerGhost> create(const Unigine::NodePtr &node);
 
virtual Unigine::PlayerPtr getPlayer() const;
 
virtual void setViewportMask(int mask) const;
virtual int getViewportMask() const;
 
virtual void setReflectionMask(int mask) const;
virtual int getReflectionMask() const;
 
virtual void setSourceMask(int mask) const;
virtual int getSourceMask() const;
 
virtual void setReverbMask(int mask) const;
virtual int getReverbMask() const;
 
virtual void setFov(float fov) const;
virtual float getFov() const;
 
virtual void setZNear(float znear) const;
virtual float getZNear() const;
 
virtual void setZFar(float zfar) const;
virtual float getZFar() const;
 
virtual void setProjection(const Unigine::mat4 &projection) const;
virtual Unigine::mat4 getProjection() const;
 
virtual void setSProjection(const Unigine::mat4 &sprojection) const;
virtual Unigine::mat4 getSProjection() const;
 
virtual void setModelview(const UNIGINE_MAT4 &modelview) const;
virtual UNIGINE_MAT4 getModelview() const;
virtual UNIGINE_MAT4 getIModelview() const;
 
virtual void setOldModelview(const UNIGINE_MAT4 &modelview) const;
virtual UNIGINE_MAT4 getOldModelview() const;
 
virtual void setUp(const Unigine::vec3 &up) const;
virtual Unigine::vec3 getUp() const;
 
virtual void setView(const Unigine::vec3 &view) const;
virtual Unigine::vec3 getView() const;
 
virtual void setOffset(const Unigine::mat4 &offset) const;
virtual Unigine::mat4 getOffset() const;
 
virtual void setVelocity(const Unigine::vec3 &velocity) const;
virtual Unigine::vec3 getVelocity() const;
 
virtual void setPostMaterials(const char *materials) const;
virtual const char *getPostMaterials() const;
 
virtual void setControlled(int controlled) const;
virtual int isControlled() const;
 
virtual void setControls(const Unigine::ControlsPtr &controls) const;
virtual Unigine::ControlsPtr getControls() const;
 
virtual void updateControls(float ifps) const;
virtual void flushTransform() const;
 
};
 
/**
* PlayerDummy smart pointer.
*/
typedef Unigine::Ptr<PlayerGhost> PlayerGhostPtr;
 
#endif

 

You can see the attempt mimic some of the internal Player-derived classes but there seems to be a barrier on the create function, which works off of the internal-only PlayerInterface class.

 

For example: 

 

Unigine::Ptr<PlayerGhost> PlayerGhost::create(const Unigine::NodePtr &n)

{
//Node *node = Unigine::GetNodeInterface(n.get());
if (n.get() == NULL || n->isPlayer() == 0) return PlayerGhostPtr();
return PlayerGhostPtr(new PlayerInterface(static_cast< Unigine::Player*>(node), 0));
}

 

But PlayerInterface is totally inaccessible so I don't know what I should be doing instead. Is there a way to accomplish this with the C++ API that I am not understanding? Or would we need to make modifications inside the engine source and re-compile (we really don't want to do this if at all possible!!)?

 

Help is greatly appreciated! 

Taylor

Link to comment

Hi, Taylor.

 

When you subclass from Unigine::PlayerDummy, you only subclass from wrapper. You can create a trully Player-derived class only inside engine and make a wrapper to it.

Or you can do the following:

static Unigine::Ptr<PlayerGhost> create(const Unigine::NodePtr &node) {
        //Node *node = Unigine::GetNodeInterface(n.get());
        if (node.get() == NULL || node->isPlayer() == 0) return PlayerGhostPtr();
        return create(PlayerDummy::create(node));
    }

    static Unigine::Ptr<PlayerGhost> create(const Unigine::PlayerDummyPtr &player) {
        return Ptr<PlayerGhost>(static_cast<PlayerGhost*>(player.get()));
    }
Link to comment

Thanks for the assistance! I have been working with this all day and still can't find a way through.

 

For the create functions, I have updated them to

Unigine::Ptr<PlayerGhost> PlayerGhost::create(const Unigine::PlayerDummyPtr &player) {

PlayerGhost * pGhost = static_cast<PlayerGhost*>(player.get());
return Unigine::Ptr<PlayerGhost>(pGhost);
}
 
Unigine::Ptr<PlayerGhost> PlayerGhost::create(const Unigine::NodePtr &node) {
Unigine::PlayerDummyPtr pDummy = PlayerDummy::create(node);
PlayerGhost * pGhost = static_cast<PlayerGhost*>(pDummy.get());
return Unigine::Ptr<PlayerGhost>(pGhost);
}

 

And the creation event logic is 

NodePtr pNode = NodeDummy::create()->getNode();

PlayerDummyPtr pDummy = PlayerDummy::create(pNode);
pPlayer = PlayerGhost::create(pDummy);

 

All of this compiles and runs, but a Null Pointer assert gets tripped every time pPlayer is accessed. Any ideas? From all my tests today, it looks like the problem is with the use of static_cast...

Link to comment

Hi, Taylor.

 

You have a pDummy = NULL, because PlayerDummy::create() method expectes only a ::PlayerDummy argument, not ::NodeDummy.

The following code creates pPlayer

PlayerDummyPtr pDummy = PlayerDummy::create();
PlayerGhostPtr pPlayer = PlayerGhost::create(pDummy);
Link to comment
  • 2 weeks later...

Thanks for the help. We found that the problem was in the creation logic, the PlayerDummyPtr needed to be a class variable, as the new Player still contained that pointer and it was being destroyed after the creation event completed.

 

But we also learned that the C++ API is probably not the best way to create a new 'player' class. Instead, we will be starting a new one through UnigineScript only

 

Thanks again!

Link to comment
×
×
  • Create New...