Advertisement

AngelScript class property with indirection

Started by August 23, 2015 06:01 PM
5 comments, last by PyemanKOP 9 years, 3 months ago
I have a class named "Actor" that has a pointer to class "Transform" that represent actors position;

here is Actor.h:

using namespace DirectX;
class Actor
{
public:
Actor();
void Update();
void Render();
void Start();
int AddRef();
int Release();
asILockableSharedBool *GetWeakRefFlag();
void Send(CScriptHandle msg, Actor *other);


const char * GetName() { return this->m_name; }
int GetX() { return this->x3; }
int GetY() { return this->y; }




void SetX(int _x) { this->x3 = _x; }
public:
int                    refCount;
asILockableSharedBool *weakRefFlag;
const char *m_name;
int x3;;
int y;
int z;
bool active;
AngelCore::AngelTools::AngelMathHelper::Vector<3> rotation;
AngelCore::AngelTools::AngelMathHelper::Vector<3> *Position;
asIScriptObject *controller;
Transform  *t;
~Actor();
};

And Actor.cpp


asILockableSharedBool *Actor::GetWeakRefFlag()
{
 if (!weakRefFlag)
  weakRefFlag = asCreateLockableSharedBool();


 return weakRefFlag;
}
void Actor::Start()
{
 //this->t = new Transform();
 scriptMgr->Start(controller);
}
int Actor::AddRef()
{
 return ++refCount;
}


int Actor::Release()
{
 if (--refCount == 0)
 {
  delete this;
  return 0;
 }
 return refCount;
}


void Actor::Send(CScriptHandle msg, Actor *other)
{
 if (other && other->controller)
  scriptMgr->OnSendMessage(other->controller, msg, this);
}



Actor::Actor()
{


 refCount = 1;
 this->t = new Transform();


 //t->position->y = 150;
 this->x3= 21000;
 this->y = 510;
 controller = 0;
 //this->active = true;
 weakRefFlag = 0;


}


void Actor::Update()
{
 scriptMgr->Update(controller);

//HERE I WANT THIS VALUE BE SAME AS IN SCRIPT******************************************************
 std::cout << "\n\n\nCurrent : " << this->t->position->x;

}

and Transform.h:


class Transform
{
public:
Transform();
~Transform();


public:
AngelCore::AngelTools::AngelMathHelper::Vector<3> *position;
AngelCore::AngelTools::AngelMathHelper::Vector<3> rotation;
AngelCore::AngelTools::AngelMathHelper::Vector<3> scalling;


};

in my script manager i register "t" as one of actors properties:(t is actor pointer to class transform)


engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);


// Set the message callback to print the human readable messages that the engine gives in case of errors
r = engine->SetMessageCallback(asMETHOD(ScriptManager, MessageCallback), this, asCALL_THISCALL); assert( r >= 0 );


// Register the string type
RegisterStdString(engine);


// Register the generic handle type, called 'ref' in the script
RegisterScriptHandle(engine);




// Register the weak ref template type
RegisterScriptWeakRef(engine);


// Register the game object. The scripts cannot create these directly, so there is no factory function.
r = engine->RegisterObjectType("Actor", sizeof(Actor)*10, asOBJ_REF);
assert( r >= 0 );
r = engine->RegisterObjectBehaviour("Actor", asBEHAVE_ADDREF, "void f()", asMETHOD(Actor, AddRef), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("Actor", asBEHAVE_RELEASE, "void f()", asMETHOD(Actor, Release), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("Actor", asBEHAVE_GET_WEAKREF_FLAG, "int &f()", asMETHOD(Actor, GetWeakRefFlag), asCALL_THISCALL); assert( r >= 0 );


// The object's position is read-only to the script. The position is updated with the Move method
r = engine->RegisterObjectMethod("Actor", "int get_x() const", asMETHOD(Actor, GetX), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("Actor", "int get_y() const", asMETHOD(Actor, GetY), asCALL_THISCALL); assert( r >= 0 );


RegisterType<Transform>("Transform");
RegisterType<Vector3>("Vector3");
RegisterType<Vector2>("Vector2");
RegisterType<Vector4>("Vector4");


r = engine->RegisterObjectProperty("Vector3", "float x", asOFFSET(Vector3, x));
if (r < 0) return r;
r = engine->RegisterObjectProperty("Vector3", "float y", asOFFSET(Vector3, y));
if (r < 0) return r;
r = engine->RegisterObjectProperty("Vector3", "float z", asOFFSET(Vector3, z));




r = engine->RegisterObjectProperty("Vector2", "float x", asOFFSET(Vector2, x));
if (r < 0) return r;
r = engine->RegisterObjectProperty("Vector2", "float y", asOFFSET(Vector2, y));
if (r < 0) return r;


r = engine->RegisterObjectProperty("Vector4", "float x", asOFFSET(Vector4, x));
if (r < 0) return r;
r = engine->RegisterObjectProperty("Vector4", "float y", asOFFSET(Vector4, y));
if (r < 0) return r;
r = engine->RegisterObjectProperty("Vector4", "float z", asOFFSET(Vector4, z));


r = engine->RegisterObjectProperty("Vector4", "float w", asOFFSET(Vector4, w));


struct MyStruct
{
Vector3 * a = new Vector3();
MyStruct()
{
a->x = 12;
}
};
MyStruct * m = new MyStruct();
//REGISTER TRANSFORM POSITION /*/*/*/*/**************************************************************
r = engine->RegisterObjectProperty("Transform", "Vector3 @position", asOFFSET(Transform, position));


//r = engine->RegisterGlobalProperty("Vector3 &data", data);
if (r < 0) return r;
r = engine->RegisterObjectProperty("Transform", "Vector3 rotation", asOFFSET(Transform, rotation));
if (r < 0) return r;
r = engine->RegisterObjectProperty("Transform", "Vector3 scalling", asOFFSET(Transform, scalling));


if (r < 0) return r;
//assert(r >= 0);
engine->RegisterObjectProperty("Actor", "Vector3 Position", asOFFSET(Actor, Position));


//HERE I REGISTER t /*//*/*/*/*/*/*/*/*/*********************************************************************
r = engine->RegisterObjectProperty("Actor", "Transform @transform", asOFFSET(Actor, t));


r = engine->RegisterObjectProperty("Actor", "bool active", asOFFSET(Actor, active));


r = engine->RegisterObjectMethod("Actor", "void Send(ref msg, const Actor @+ to)", asMETHOD(Actor, Send), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterGlobalFunction("void DebugString(string &in)", asFUNCTION(Print), asCALL_CDECL);

above is registeration of all properties so far.
my problem is when i change actors transform from script file like below the actual actor transform in .cpp file is not changed!

I mean i want that a change from user in transform position in script take effect in c++ file but it dose not!

And here is my AngelScript code:


class Player : Component
{
// The constructor must take a CGameObj handle as input,
// this is the object that the script will control
Player(Actor @obj)
{
// Keep the owner for later reference
@self = obj;
}
float ChangeValue(int x)
{
return x+=150;
}
void Start()
{
self.transform.position.x=42242;
self.transform.rotation.y=1;
self.transform.scalling.z=2;
DebugString("StartCalled \n \n ++++++++++++++++++++");
self.active=false;
//self.Position.x=10000;
}
void Update()
{
bool data;
DebugString("Active : " + self.active);
DebugString("\n Transform PositionY:" + self.transform.position.x);
DebugString("\n Transform RotationX:" + self.transform.rotation.y);
DebugString("\n Transform ScallingZ:" + self.transform.scalling.z);


//self.transform.position.y++;


}


Actor @self;
}

Thanks!

Are you getting any errors when executing the script? Is asIScriptContext::Execute returning asEXECUTION_FINISHED or something else?

Why is the Transform::position registered as a handle (@) when Transform::rotation and Transform::scalling aren't? Is the Transform class allocating the position member in the constructor?

I suggest you debug your code to make sure the script is actually having the correct reference to the Transform object in the Actor class.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

Are you getting any errors when executing the script? Is asIScriptContext::Execute returning asEXECUTION_FINISHED or something else?

Why is the Transform::position registered as a handle (@) when Transform::rotation and Transform::scalling aren't? Is the Transform class allocating the position member in the constructor?

I suggest you debug your code to make sure the script is actually having the correct reference to the Transform object in the Actor class.

Thanks for response.

I got no error at all!
i just do that for test,position is pointer but rotation is not as i want to test that.

Here is my transform.cpp


Transform::Transform()
{
this->position = new AngelCore::AngelTools::AngelMathHelper::Vector<3>();
/*this->rotation= new AngelCore::AngelTools::AngelMathHelper::Vector<3>();
this->scalling = new AngelCore::AngelTools::AngelMathHelper::Vector<3>();;*/
}




Transform::~Transform()
{
}

Yeah i'm sure that i have correct refrence to transform and also position as you can see i print Position->x property in actor.cpp in update function.

I want to register Position as refrence type is that correct to use @? i saw in documentation that i have to us e& but it gave me error!

I don't see any immediate error in the code that you have shared so far.

As far as I can tell, it should work as you want it.

Perhaps you can show how you're calling the script's Update method. It might be that the problem is there.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I don't see any immediate error in the code that you have shared so far.

As far as I can tell, it should work as you want it.

Perhaps you can show how you're calling the script's Update method. It might be that the problem is there.

I have an actor factory class that represent creating and destroying actors.

here is code:


class ActorsFactory
{
public:
ActorsFactory();
void Update();
~ActorsFactory();
void Start();


private:
std::vector<Actor*> m_actors;
Actor *SpawnObject(const std::string &type, char dispChar, int x, int y);






};


extern ActorsFactory *factory;

Actorfactory.cpp:


ActorsFactory::ActorsFactory()
{
}




ActorsFactory::~ActorsFactory()
{
}


void ActorsFactory::Update()
{
//for (int i = 0;i < 200;i++)
for (unsigned int n = 0; n < m_actors.size(); n++)
m_actors[n]->Update();
}




Actor *ActorsFactory::SpawnObject(const std::string &type, char dispChar, int x, int y)
{
Actor *obj = new Actor();
m_actors.push_back(obj);


// Set the controller based on type
obj->controller = scriptMgr->CreateController(type, obj);


return obj;
}


void ActorsFactory::Start()
{


// Create the player
Actor *obj = SpawnObject("player", 'p', rand() % 10, rand() % 10);
obj->Start();


//Actor *obj1 = SpawnObject("enemy", 'p', rand() % 10, rand() % 10);
//obj1->Start();


// Check if there were any compilation errors during the script loading
if (scriptMgr->hasCompileErrors)
{
std::cout << "SCRIPT COMPILT ERROR";
}
//return -1;
}

And below is the result of script and code as you see position.x in script is different from actual code!

Current is called in actor.cpp Update function to print position.x in c++.

Untitled.png

And Here is the full solution you can test it on you own ;)
http://s000.tinyupload.com/?file_id=04822932865189830393

I downloaded the source code and reviewed the code.

These are the problems I found:

  1. You're using version 2.30.0 WIP. Upgrade to 2.30.1 to get the support for registering the position member as a &. (while you're at it you might as well upgrade to 2.30.2 WIP to get the very latest code).
  2. You're registering the value types Transform, Vector3, etc with the flag asOBJ_ASHANDLE. This what is causing the problem you're facing.

I understand you came to the conclusion that you needed asOBJ_ASHANDLE because your members are pointers, but this is not what asOBJ_ASHANDLE is meant for. This flag has a very specific use case, which is to build a container class that should function as a handle. You can see its use in the ScriptHandle add-on.

Upgrade the library, change the code to remove the asOBJ_ASHANDLE in RegisterType<T>, and then change to register the Transform::position as:

r = engine->RegisterObjectProperty("Transform", "Vector3 &position", asOFFSET(Transform, position));

Doing this should make your code work as you want.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

I downloaded the source code and reviewed the code.

These are the problems I found:

  1. You're using version 2.30.0 WIP. Upgrade to 2.30.1 to get the support for registering the position member as a &. (while you're at it you might as well upgrade to 2.30.2 WIP to get the very latest code).
  2. You're registering the value types Transform, Vector3, etc with the flag asOBJ_ASHANDLE. This what is causing the problem you're facing.

I understand you came to the conclusion that you needed asOBJ_ASHANDLE because your members are pointers, but this is not what asOBJ_ASHANDLE is meant for. This flag has a very specific use case, which is to build a container class that should function as a handle. You can see its use in the ScriptHandle add-on.

Upgrade the library, change the code to remove the asOBJ_ASHANDLE in RegisterType<T>, and then change to register the Transform::position as:

r = engine->RegisterObjectProperty("Transform", "Vector3 &position", asOFFSET(Transform, position));

Doing this should make your code work as you want.

Hey! :)
That fixed my problem thanks :)

This topic is closed to new replies.

Advertisement