Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
115 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Introduction to GameMonkey Script Part 2
Embedding GameMonkey


SetDot Operator

If you experiment with some scripts on the new Vector type, you will notice that you can read data from it but not alter the data in any way outside of actual construction of the variable. We will now provide a SetDot operator override to handle the setting of the member data. The operands are similar to that of GetDot:

Operand   Purpose
0The variable being operated upon and the return variable on exit (e.g.: 'v' in v.x = a; )
1The data passed for assignment (e.g.: 'a' in v.x = a; )
2The 'member' being accessed (as a gmStringObject) (e.g.: 'x' in v.x = a; )

A function to handle the Set Dot operator for our vector class is as follows:

void GM_CDECL OpSetDot(gmThread * a_thread, gmVariable * a_operands)
{
    GM_ASSERT(a_operands[0].m_type == Type);
    Vector* thisVec = static_cast<Vector*>(static_cast<gmUserObject*>(GM_OBJECT(a_operands[0].m_value.m_ref))->m_user);
    
    GM_ASSERT(a_operands[2].m_type == GM_STRING);
    gmStringObject* stringObj = static_cast<gmStringObject*>(GM_OBJECT(a_operands[2].m_value.m_ref));
    const char* propname = stringObj->GetString();
    
    // Create a variable to hold the data to assign
    // handle both ints and floats
    float newFloat = 0.0f;
    if(a_operands[1].m_type == GM_FLOAT)
    {
      newFloat = a_operands[1].m_value.m_float;
    }
    else if(a_operands[1].m_type == GM_INT)
    {
      newFloat = (float)a_operands[1].m_value.m_int;
    }
    
    // Assign the data
    if(::stricmp( propname, "x") == 0)
    {
      thisVec->x = newFloat;
    }
    else if(::stricmp( propname, "y") == 0)
    {
      thisVec->y = newFloat;
    }
    else if(::stricmp( propname, "z") == 0)
    {
      thisVec->z = newFloat;
    }
}

Example: vector_3.cpp

As you can see, it follows a similar progression from the previous example, except this time we need to retrieve the value passed to the function by the script (operand #1). As before, the member is compared to the exported members and the assignment made accordingly. Adding the following line to the BindLib function will complete the simple type.

a_machine->RegisterTypeOperator(Type, O_SETDOT, NULL, OpSetDot);

I mentioned previously that GameMonkey Script user variables are reference types; this becomes evident now that you have working dot operators. For example, if one were to write a script such as:

    a = Vector( 20, 20, 30 );
    b = a;
    b.x = 10;
    print(a.x);
    print(b.x);

You would see that updating the value of b.x would also update the value of a.x as they both reference the same data. The solution to this would be to implement a copy constructor for the Vector type (or add a Copy function to the type) which would be used as such:

    a = Vector( 20, 20, 30 );
    b = Vector( a );
    b.x = 10;
    print(a.x);
    print(b.x);

In this case you would notice that the data is copied and the two variables retain their own data.

And there we have it; an almost complete simple vector type for you to use in your scripts. It is almost complete because we have not yet touched on the subject of Garbage Collection, which plays an important role in any bound type you create.





Garbage Collection


Contents
  Basic Embedding Concepts
  Executing a String as a Script
  Executing a Script from File
  More on Script Execution
  gmVariable Object
  Calling a Scripted Function
  Creating a host-bound function
  Creating a simple type
  Constructor with Parameters
  Operator Overrides
  SetDot Operator
  Garbage Collection

  Source code
  Printable version
  Discuss this article

The Series
  Language Introduction
  Embedding GameMonkey