Jump to content
  • Advertisement
Sign in to follow this  
Wavesonics

Passing script objects as base pointers?

This topic is 3466 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Well I had a huge long post here. But in writing the post, I worked through the problem and figured it out :) I must say, I don't totally grasp the difference between REF and VALUE. Are VALUE types only valid in the scripts, and REF types actual *real* objects? Anyway. I'm creating an object in my script which is a derived type. But I want to be able to pass it to the application as it's base type. Any ideas for how to accomplish this? I figure there is no direct way since I saw inheritance is on the road map.

Share this post


Link to post
Share on other sites
Advertisement
The value types are allocated on the stack and never outlive the scope in which they were created. The reference types are allocated on the heap, and live on until all references to them have been removed.

Value types are used mainly for smaller, less complex types, e.g. 3D vectors. Reference types are used for all types that need dynamic memory management.




You can register the reference cast behaviour for the derived type. This will allow the script engine to cast the type to the base type.

There is an example for this in the manual: Type behaviours (look for cast operators further down on the page)

Share this post


Link to post
Share on other sites
Ok, I went ahead and implemented the implicit case behavior, and it *works.

* It works in every case but this obscure one:
When trying to call to a function using the implicit case, and the function is virtual, and only implemented in the base class of the object it is actually being called on.

It still compiles and runs, but the function is just never called.

Share this post


Link to post
Share on other sites
Sure can. Also, I did some checking, and the implicit conversion function I registered is definitely firing and succeeding.

Here is the script it's self:

void fireEffects( TurretClient@ t, CreepClient@ c, WorldClient@ w ) {
if( c.health() != 0 ) {
// Create an explosion
OverlayExplosion@ o = OverlayExplosion( 1.0 );

// Add the explosion to the creep we fired on
c.addOverlay( o ); // This one doesn't ever fire off
}
else {
// Create an explosion
OverlayExplosion@ o = OverlayExplosion( 0.5 );

// Give the explosion the world coordinates where the creep died
float x = c.x();
float y = c.y();
o.position( x, y );

// Add the explosion to the world
w.addOverlay( o ); // This on works just fine
}
}





Here is the offending class:

#ifndef CREEPCLIENT_H_INCLUDED
#define CREEPCLIENT_H_INCLUDED

#include "Creep.h"
#include "Drawable.h"

class CreepClient : public Creep, public Drawable {
private:
protected:
public:
CreepClient( const class DescriptionCreep* description );
virtual ~CreepClient();
};

#endif // CREEPCLIENT_H_INCLUDED






And it's base class which is where the function is:



#ifndef GAMEOBJECTCLIENT_H_INCLUDED
#define GAMEOBJECTCLIENT_H_INCLUDED

#include <vector>

#include <SFML/Graphics.hpp>

class Drawable {
private:
class GameObject& m_obj;
std::vector< class Overlay* > m_overlay;
protected:
sf::Sprite m_sprite;

public:
Drawable( GameObject& obj );
virtual ~Drawable();

virtual void addOverlay( Overlay* overlay );
sf::Int32 numOverlays();
Overlay& getOverlay( sf::Uint32 index );
bool removeOverlay( sf::Uint32 index );

virtual void setSprite( const sf::Sprite& s );
virtual sf::Sprite& getSprite();
virtual sf::Drawable& getDrawable();
};

#endif // GAMEOBJECTCLIENT_H_INCLUDED





And here is where I register the class:

// Here is where we register the class

// CreepClient
r = engine->RegisterObjectType("CreepClient", sizeof(CreepClient), asOBJ_REF ); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("CreepClient", asBEHAVE_ADDREF, "void f()", asFUNCTION(DumbyAddRef), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("CreepClient", asBEHAVE_RELEASE, "void f()", asFUNCTION(DumbyReleaseRef), asCALL_CDECL_OBJFIRST); assert( r >= 0 );

r = engine->RegisterObjectMethod("CreepClient", "void addOverlay( Overlay@+ overlay )", asMETHOD(CreepClient, addOverlay), asCALL_THISCALL); assert( r >= 0 );

r = engine->RegisterObjectMethod("CreepClient", "int16 health() const", asMETHODPR(CreepClient, health, (void) const, sf::Int16), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("CreepClient", "void health( int16 )", asMETHODPR(CreepClient, health, (sf::Int16), void), asCALL_THISCALL); assert( r >= 0 );

r = engine->RegisterObjectMethod("CreepClient", "float speed() const", asMETHODPR(CreepClient, speed, (void) const, float), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("CreepClient", "void speed( float )", asMETHODPR(CreepClient, speed, (float), void), asCALL_THISCALL); assert( r >= 0 );

r = engine->RegisterObjectMethod("CreepClient", "int8 reward() const", asMETHODPR(CreepClient, reward, (void) const, sf::Int8), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("CreepClient", "void reward( int8 )", asMETHODPR(CreepClient, reward, (sf::Int8), void), asCALL_THISCALL); assert( r >= 0 );

r = engine->RegisterObjectMethod("CreepClient", "float x() const", asMETHOD(CreepClient, x), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("CreepClient", "float y() const", asMETHOD(CreepClient, y), asCALL_THISCALL); assert( r >= 0 );

r = engine->RegisterObjectMethod("CreepClient", "void position( float, float )", asMETHODPR(CreepClient, position, (float, float), void), asCALL_THISCALL); assert( r >= 0 );

// Global object behavior
r = engine->RegisterGlobalBehaviour(asBEHAVE_IMPLICIT_REF_CAST, "Overlay@+ f( OverlayExplosion@+ )", asFUNCTION(castOverlayExplosionToOverlay), asCALL_CDECL); assert( r >= 0 );



Share this post


Link to post
Share on other sites
How are you calling the 'fireEffects' function?

This isn't a problem with the implicit cast behaviour, because c is already a handle to a CreepClient, thus AngelScript won't cast it to anything else when calling the addOverlay method.

When you pass the pointer to the CreepClient to the context, is the pointer declared as a CreepClient or one of the Creep or Drawable classes? It's important that is a CreepClient, because the value of the pointer won't be the same if it is one of the other (due to multiple inheritance).

Share this post


Link to post
Share on other sites
Damn, i thought thats what it was when I read it, but looking at my source, I am passing it as a CreepClient:


void ProcessFireTurretsClient::fireAction( Turret& t, Creep& c ) {
TurretClient& tc = dynamic_cast< TurretClient& >( t );
CreepClient& cc = dynamic_cast< CreepClient& >( c );

// Run the turrets "void fireEffects()" script
const DescriptionTurret* description = t.getDescription();
asIScriptContext* ctx = gScriptEngine.prepare( description->effectsScript, "void fireEffects( TurretClient@, CreepClient@, WorldClient@ )" );
ctx->SetArgObject( 0, &tc );
ctx->SetArgObject( 1, &cc );
ctx->SetArgObject( 2, &m_world );
gScriptEngine.execute( ctx );
}

Share this post


Link to post
Share on other sites
It could be a bug with how AngelScript handles virtual methods for classes with multiple inheritance. I'll have to look into this.

Could you make a quick test?

Instead of registering the addOverlay method directly, try registering the following wrapper function:


void CreepClient_addOverlay( Overlay* overlay, CreepClient *c )
{
c->addOverlay(overlay);
}

r = engine->RegisterObjectMethod("CreepClient", "void addOverlay( Overlay@+ overlay )", asFUNCTION(CreepClient_addOverlay), asCALL_CDECL_OBJLAST); assert( r >= 0 );


If it is a problem with the way multiple inheritance is handled, the above should be a work around until I get the bug fixed. If the above doesn't work either, then the problem is another.

Share this post


Link to post
Share on other sites
Yes, I actually made a proxy function as a member of CreepClient:


CreepClient::addOverlay( Overlay* o ) {
Drawable::addOverlay( o );
}



And it works fine.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!