🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Operator assignment question

Started by
8 comments, last by howie_007 5 years, 6 months ago

Should I be able to do this in the script code? The question is about the last line of the below code example.


CPoint velocity;
velocity.x = cos( rotation ) * PROJECTILE_SPEED;
velocity.y = sin( rotation ) * PROJECTILE_SPEED;

float time = HighResTimer.getElapsedTime();
sprite.incPos( velocity * time );

sprite.incPos receives a CPoint as a parameter. There's no compiler error and the code runs but the CPoint recieved by sprite.incPos is all zeros.

Here's my assignment code. Perhaps I'm missing something.

Thank you for all your hard work providing us this amazing scripting tool along with your other tools like the font creator.


// binary operators
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opAdd ( CPoint & in )", asMETHODPR(CPoint<float>, operator +, (const CPoint<float> &) const, CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opSub ( CPoint & in )", asMETHODPR(CPoint<float>, operator -, (const CPoint<float> &) const, CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opMul ( CPoint & in )", asMETHODPR(CPoint<float>, operator *, (const CPoint<float> &) const, CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opDiv ( CPoint & in )", asMETHODPR(CPoint<float>, operator /, (const CPoint<float> &) const, CPoint<float>), asCALL_THISCALL) );

Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opAdd ( float )", asMETHODPR(CPoint<float>, operator +, (float) const, CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opSub ( float )", asMETHODPR(CPoint<float>, operator -, (float) const, CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opMul ( float )", asMETHODPR(CPoint<float>, operator *, (float) const, CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opDiv ( float )", asMETHODPR(CPoint<float>, operator /, (float) const, CPoint<float>), asCALL_THISCALL) );

// compound assignment operators
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opAddAssign ( CPoint & in )", asMETHODPR(CPoint<float>, operator +=, (const CPoint<float> &), CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opSubAssign ( CPoint & in )", asMETHODPR(CPoint<float>, operator -=, (const CPoint<float> &), CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opMulAssign ( CPoint & in )", asMETHODPR(CPoint<float>, operator *=, (const CPoint<float> &), CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opDivAssign ( CPoint & in )", asMETHODPR(CPoint<float>, operator /=, (const CPoint<float> &), CPoint<float>), asCALL_THISCALL) );

Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opAddAssign ( float )", asMETHODPR(CPoint<float>, operator +=, (float) , CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opSubAssign ( float )", asMETHODPR(CPoint<float>, operator -=, (float) , CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opMulAssign ( float )", asMETHODPR(CPoint<float>, operator *=, (float) , CPoint<float>), asCALL_THISCALL) );
Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opDivAssign ( float )", asMETHODPR(CPoint<float>, operator /=, (float) , CPoint<float>), asCALL_THISCALL) );

 

Advertisement

Yes, it should be possible to do what you've done. There can be many different causes for the problem you're facing. The most likely is that something is wrong with how you've registered the CPoint type, but I cannot at this point exclude a possible bug in the library.

 

Can you show how you've registered the CPoint (other than the operators). I need to see the RegisterObjectType, behaviours and also opAssign (if you have registered it).

Also, does incPos take the CPoint by value or by reference? Can you show the declaration?

 

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

Here is the c++ angelscript wrapper function that receives the point.


void IncPos1(CPoint<float> & pos, CSprite & sprite)
{
    sprite.getObject()->incPos(pos);
}

Here's the CPoint class registration code



/************************************************************************
 *    FILE NAME:       scriptpoint.cpp
 *
 *    DESCRIPTION:     CPoint script object registration
 ************************************************************************/

// Physical component dependency
#include <script/scriptpoint.h>

// Game lib dependencies
#include <common/point.h>
#include <script/scriptmanager.h>
#include <script/scriptglobals.h>

// AngelScript lib dependencies
#include <angelscript.h>

namespace NScriptPoint
{
    /************************************************************************
     *    DESC:  Constructor
     ************************************************************************/
    void Constructor(void * thisPointer)
    {
        new(thisPointer) CPoint<float>();
    }

    /************************************************************************
     *    DESC:  Copy Constructor
     ************************************************************************/
    void CopyConstructor(const CPoint<float> & other, void * pThisPointer)
    {
        new(pThisPointer) CPoint<float>(other);
    }

    void ConstructorFromThreeFloats(float x, float y, float z, void * pThisPointer)
    {
        new(pThisPointer) CPoint<float>(x, y, z);
    }

    void ConstructorFromTwoFloats(float x, float y, void * pThisPointer)
    {
        new(pThisPointer) CPoint<float>(x, y);
    }

    /************************************************************************
     *    DESC:  Destructor
     ************************************************************************/
    void Destructor(void * pThisPointer)
    {
        ((CPoint<float>*)pThisPointer)->~CPoint();
    }
    
    /************************************************************************
    *    DESC:  Wrapper function due to type being a template
    ************************************************************************/
    float GetLengthSquared2D1(CPoint<float> & point)
    {
        return point.getLengthSquared2D();
    }
    
    float GetLengthSquared2D2(CPoint<float> & in, CPoint<float> & point)
    {
        return point.getLengthSquared2D( in );
    }
    
    float GetLength2D1(CPoint<float> & point)
    {
        return point.getLength2D();
    }
    
    float GetLength2D2(CPoint<float> & in, CPoint<float> & point)
    {
        return point.getLength2D( in );
    }
    
    float GetLengthSquared1(CPoint<float> & point)
    {
        return point.getLengthSquared();
    }
    
    float GetLengthSquared2(CPoint<float> & in, CPoint<float> & point)
    {
        return point.getLengthSquared( in );
    }
    
    float GetLength1(CPoint<float> & point)
    {
        return point.getLength();
    }
    
    float GetLength2(CPoint<float> & in, CPoint<float> & point)
    {
        return point.getLength( in );
    }
    
    bool IsEquilEnough(CPoint<float> & in, float val, CPoint<float> & point)
    {
        return point.isEquilEnough( in, val );
    }

    float GetDotProduct(CPoint<float> & in, CPoint<float> & point)
    {
        return point.getDotProduct( in );
    }
    
    float GetDotProduct2D(CPoint<float> & in, CPoint<float> & point)
    {
        return point.getDotProduct2D( in );
    }
    
    CPoint<float> GetCrossProduct(CPoint<float> & in, CPoint<float> & point)
    {
        return point.getCrossProduct( in );
    }
    
    void Cap(float value, CPoint<float> & point)
    {
        point.cap(value);
    }


    /************************************************************************
     *    DESC:  Register the class with AngelScript
     ************************************************************************/
    void Register()
    {
        using namespace NScriptGlobals; // Used for Throw
        
        asIScriptEngine * pEngine = CScriptMgr::Instance().getEnginePtr();
        
        // Register type
        Throw( pEngine->RegisterObjectType("CPoint", sizeof(CPoint<float>), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS | asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR ) );

        // Register the object operator overloads
        Throw( pEngine->RegisterObjectBehaviour("CPoint", asBEHAVE_CONSTRUCT, "void f()",                    asFUNCTION(Constructor), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectBehaviour("CPoint", asBEHAVE_CONSTRUCT, "void f(const CPoint & in)",   asFUNCTION(CopyConstructor), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectBehaviour("CPoint", asBEHAVE_CONSTRUCT, "void f(float, float, float)", asFUNCTION(ConstructorFromThreeFloats), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectBehaviour("CPoint", asBEHAVE_CONSTRUCT, "void f(float, float)",        asFUNCTION(ConstructorFromTwoFloats), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectBehaviour("CPoint", asBEHAVE_DESTRUCT, "void f()",                     asFUNCTION(Destructor), asCALL_CDECL_OBJLAST) );

        // assignment operator
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint & opAssign(CPoint & in)", asMETHODPR(CPoint<float>, operator =, (const CPoint<float> &), CPoint<float> &), asCALL_THISCALL) );

        // binary operators
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opAdd ( CPoint & in )", asMETHODPR(CPoint<float>, operator +, (const CPoint<float> &) const, CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opSub ( CPoint & in )", asMETHODPR(CPoint<float>, operator -, (const CPoint<float> &) const, CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opMul ( CPoint & in )", asMETHODPR(CPoint<float>, operator *, (const CPoint<float> &) const, CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opDiv ( CPoint & in )", asMETHODPR(CPoint<float>, operator /, (const CPoint<float> &) const, CPoint<float>), asCALL_THISCALL) );

        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opAdd ( float )", asMETHODPR(CPoint<float>, operator +, (float) const, CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opSub ( float )", asMETHODPR(CPoint<float>, operator -, (float) const, CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opMul ( float )", asMETHODPR(CPoint<float>, operator *, (float) const, CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opDiv ( float )", asMETHODPR(CPoint<float>, operator /, (float) const, CPoint<float>), asCALL_THISCALL) );

        // compound assignment operators
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opAddAssign ( CPoint & in )", asMETHODPR(CPoint<float>, operator +=, (const CPoint<float> &), CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opSubAssign ( CPoint & in )", asMETHODPR(CPoint<float>, operator -=, (const CPoint<float> &), CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opMulAssign ( CPoint & in )", asMETHODPR(CPoint<float>, operator *=, (const CPoint<float> &), CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opDivAssign ( CPoint & in )", asMETHODPR(CPoint<float>, operator /=, (const CPoint<float> &), CPoint<float>), asCALL_THISCALL) );

        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opAddAssign ( float )", asMETHODPR(CPoint<float>, operator +=, (float) , CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opSubAssign ( float )", asMETHODPR(CPoint<float>, operator -=, (float) , CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opMulAssign ( float )", asMETHODPR(CPoint<float>, operator *=, (float) , CPoint<float>), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opDivAssign ( float )", asMETHODPR(CPoint<float>, operator /=, (float) , CPoint<float>), asCALL_THISCALL) );

        // Register property
        Throw( pEngine->RegisterObjectProperty("CPoint", "float x", asOFFSET(CPoint<float>, x)) );
        Throw( pEngine->RegisterObjectProperty("CPoint", "float y", asOFFSET(CPoint<float>, y)) );
        Throw( pEngine->RegisterObjectProperty("CPoint", "float z", asOFFSET(CPoint<float>, z)) );

        // Class members
        Throw( pEngine->RegisterObjectMethod("CPoint", "void clearX()",       asMETHOD(CPoint<float>, clearX), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void clearY()",       asMETHOD(CPoint<float>, clearY), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void clearZ()",       asMETHOD(CPoint<float>, clearZ), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void clear()",        asMETHOD(CPoint<float>, clear), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "bool isEmpty()",      asMETHOD(CPoint<float>, isEmpty), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "bool isXEmpty()",     asMETHOD(CPoint<float>, isXEmpty), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "bool isYEmpty()",     asMETHOD(CPoint<float>, isYEmpty), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "bool isZEmpty()",     asMETHOD(CPoint<float>, isZEmpty), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void invert()",       asMETHOD(CPoint<float>, invert), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void invertX()",      asMETHOD(CPoint<float>, invert), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void invertY()",      asMETHOD(CPoint<float>, invert), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void invertZ()",      asMETHOD(CPoint<float>, invert), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint getInvert() const",  asMETHOD(CPoint<float>, getInvert), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void normalize()",    asMETHOD(CPoint<float>, normalize), asCALL_THISCALL) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void normalize2D()",  asMETHOD(CPoint<float>, normalize2D), asCALL_THISCALL) );
        
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getLengthSquared2D() const",            asFUNCTION(GetLengthSquared2D1), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getLengthSquared2D(CPoint & in) const", asFUNCTION(GetLengthSquared2D2), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getLengthSquared() const",              asFUNCTION(GetLengthSquared1), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getLengthSquared(CPoint & in) const",   asFUNCTION(GetLengthSquared2), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getLength2D() const",                   asFUNCTION(GetLength2D1), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getLength2D(CPoint & in) const",        asFUNCTION(GetLength2D2), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getLength() const",                     asFUNCTION(GetLength1), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getLength(CPoint & in) const",          asFUNCTION(GetLength2), asCALL_CDECL_OBJLAST) );
        
        Throw( pEngine->RegisterObjectMethod("CPoint", "bool isEquilEnough(CPoint & in, float val)", asFUNCTION(IsEquilEnough), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getDotProduct(CPoint & in) const",           asFUNCTION(GetDotProduct), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "float getDotProduct2D(CPoint & in) const",         asFUNCTION(GetDotProduct2D), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint getCrossProduct(CPoint & in) const",        asFUNCTION(GetCrossProduct), asCALL_CDECL_OBJLAST) );
        Throw( pEngine->RegisterObjectMethod("CPoint", "void cap(float)",                            asFUNCTION(Cap), asCALL_CDECL_OBJLAST) );
    }
}

 

In doing some experimentation, I noticed doing the below didn't work. I'm sure I don't have the overloaded operators setup correctly for this.


CPoint point1(5, 2, 7);
CPoint point2(3, 4, 9);
CPoint result;
result = point1 * point2;
Print( "point1: " + point1.x + ", " + point1.y + ", " + point1.z );
Print( "point2: " + point2.x + ", " + point2.y + ", " + point2.z );
Print( "Result: " + result.x + ", " + result.y + ", " + result.z );

-------------------------------------------------------

point1: 5, 2, 7
point2: 3, 4, 9
Result: 1.49854e-33, -1.03028e+37, 3.97328e-34

 

I suspect the problem is related to how you've registered the operators. You're not using 'const CPoint &in' for the arguments. The fact that you don't use 'const' causes the script compiler to have to make unnecessary copies of the object in order to guarantee that the value is not modified by the called function. Try changing how you register the operators and see if that works.   


    Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint & opAssign(const CPoint & in)", asMETHODPR(CPoint<float>, operator =, (const CPoint<float> &), CPoint<float> &), asCALL_THISCALL) );

    Throw( pEngine->RegisterObjectMethod("CPoint", "CPoint opMul ( const CPoint & in )", asMETHODPR(CPoint<float>, operator *, (const CPoint<float> &) const, CPoint<float>), asCALL_THISCALL) );

 

Of course, if this turns out to be the cause, then there is a bug in the library that I need to fix, because it should work even without the 'const'.

 

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

Unfortunately, adding "const" didn't solve the problem.

OK. Maybe it is the RegisterObjectType that is wrong, causing the native ABI to not understand how C++ is returning the CPoint.

Try changing the RegisterObjectType to the following:


Throw( pEngine->RegisterObjectType("CPoint", sizeof(CPoint<float>),
  asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<CPoint<float>>() | asOBJ_APP_CLASS_ALLFLOATS ) );

 

Unfortunately I have not been able to reproduce the problem you're reporting, and without being able to debug the problem myself I can only guess what might be wrong.

BTW, what compiler and OS are you using? 

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

What does operator* look like, and does that method get the right input values?

I changed the RegisterObjectType as you suggested and that worked! Awesome! Thank you for the help!

The computer is an aging home built gaming rig repurposed as a development maching using an AMD Phenom chip running Arch Linux.

This topic is closed to new replies.

Advertisement