Jump to content

Experimental actor class for C++ entity management


Josh
 Share

Recommended Posts

I'm tentatively thinking about including an extendable class like this:

#pragma once

#include "../Leadwerks.h"

 

namespace Leadwerks

{

class Actor : public Object

{

public:

Entity* entity;

 

Actor();

virtual ~Actor();

 

virtual void Collision(Entity* entity, const Vec3& position, const Vec3& normal, float speed);

virtual void UpdateWorld()

virtual void UpdatePhysics()

virtual void UpdateMatrix()

virtual void Draw()

virtual void DrawEach(Camera* camera)

}

}

You would declare your own class derived from the Leadwerks actor class, and set an entity's actor to your object. The engine would then call your object's methods at various points in the program. (The default functions declared above would just be empty functions that don't do anything.)

#pragma once

#include "../MyGame.h"

 

namespace MyGame

{

        class MyActor : public Actor

        {

        public:

                virtual void UpdatePhysics()

        }

}

The hooks system will not be removed, but the recommended way of interfacing with entities in C++ would be through this method. Thoughts?

  • Upvote 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

A clever way of disabling calls to methods the user does not declare in their derived class would be to store a Boolean member for whether each function should be used. For example, useCollisionMethod.

useCollisionMethod = true;

 

The default function could then deactivate this function the first time it is run:

void CollisionHook(Entity* entity, const Vec3& position, const Vec3& normal, float speed)

{

useCollisionMethod = false;

}

 

Next time a collision occurs, the engine will see that the useCollisionMethod member is false, and skip the function call.

 

Your function would override the one above, ensuring that it continues to be called. So you wouldn't actually need to know about this at all, but I thought it was cool.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

This is available in the beta branch now.

 

UpdatePhysics, UpdateWorld, and PostRender functions will not work right now. The other functions will work.

 

This is experimental. Please let me know if you use it and tell me how it works for you.

  • Upvote 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

  • 3 weeks later...

This works right now, but is not official and may change.

 

The UpdateWorld, PostRender, and UpdatePhysics functions will not get called at this time.

 

My plan is to let people play with this some more and then listen to what they need in the editor, as they use this.

  • Upvote 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Alright, sounds understandable. It's not too hard to do a hook to get those functions working again. Thanks for answering, just wanted to know if there was any improvement since the 22nd.

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

I just put it together; can't say I tested it, but this chunk of code is how my Puppeteer class worked. This class derives from the actor class so that the update and post render functions update.

 

BaseActor.h

 

// Temp Actor class until the offical one gets improved.

#if !defined(BASEACTOR_H)

#define BASEACTOR_H

#pragma once

#include "Leadwerks.h"

 

namespace Leadwerks

{

class BaseActor : public Actor

{

BaseActor();

virtual ~BaseActor();

 

virtual void Attach();

virtual void Detach();

 

// Hooks that are not working with actors in 4.2

virtual void UpdateWorld() {};

virtual void UpdatePhysics() {};

virtual void PostRender(Leadwerks::Context* context) {};

 

protected:

static void PostRenderHook(Entity* entity);

static void UpdatePhysicsHook(Entity* entity);

static void UpdateWorldHook(Entity* entity);

};

}

#endif

 

BaseActor.cpp

 

// Temp Actor class until the offical one gets improved.

#include "BaseActor.h"

 

namespace Leadwerks

{

BaseActor::BaseActor() : Actor() {};

 

BaseActor::~BaseActor(){};

 

void BaseActor::Attach()

{

Actor::Attach();

entity->AddHook(Entity::PostRenderHook, (void*)PostRenderHook);

entity->AddHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook);

entity->AddHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook);

}

 

void BaseActor::Detach()

{

entity->RemoveHook(Entity::PostRenderHook, (void*)PostRenderHook);

entity->RemoveHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook);

entity->RemoveHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook);

Actor::Detach();

}

 

void BaseActor::PostRenderHook(Entity* entity)

{

BaseActor* script = (BaseActor*)entity->GetUserData();

Leadwerks::Context* context = Leadwerks::Context::GetCurrent();

if (script != nullptr)

{

script->PostRender(context);

}

}

 

void BaseActor::UpdatePhysicsHook(Entity* entity)

{

BaseActor* script = (BaseActor*)entity->GetUserData();

 

if (script != nullptr)

{

script->UpdatePhysics();

}

}

 

void BaseActor::UpdateWorldHook(Entity* entity)

{

BaseActor* script = (BaseActor*)entity->GetUserData();

 

if (script != nullptr)

{

script->UpdateWorld();

}

}

}

 

You may need to static cast your Actors based off this when you go to attach the actor to the entity with Entity->SetActor().

  • Upvote 1

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

Seem to be getting crashes when I clear the world. I thought it was because the hooks were not being detached before the actor was, but I disabled my additional hooks and I'm getting the same crash.

 

ActorCrash.PNG

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

Still no dice. I got my custom Actor Class to work tho. There seems to be an issue with Detach. When CUSTOM_ACTOR is defined, everything works like expected. (Fully custom class based on hooks) vs the class derived from the stock Actor Class.

 

Header:

 


// Temp Actor class until the offical one gets improved.

#if !defined(BASEACTOR_H)

#define BASEACTOR_H

#pragma once

#include "Leadwerks.h"

#define CUSTOM_ACTOR

namespace Leadwerks

{

#ifdef CUSTOM_ACTOR

class BaseActor : public Object

{

public:

Entity* entity;

BaseActor() {};

virtual ~BaseActor();

virtual void Attach();

void RemoveHooks();

virtual void Detach();

void Shutdown()

{

Detach();

};

virtual void Collision(Entity* pEntity, float* position, float* normal, float speed) {};

virtual void UpdateWorld() {};

virtual void UpdatePhysics() {};

virtual void UpdateMatrix() {};

virtual void PostRender(Context* context) {};

virtual void Draw() {};

virtual void DrawEach(Camera* camera) {};

protected:

static void CollisionHook(Entity* entity0, Entity* entity1, float* position, float* normal, float speed);

static void DrawHook(Entity* entity);

static void DrawEachHook(Entity* entity);

static void PostRenderHook(Entity* entity);

static void UpdateMatrixHook(Entity* entity);

static void UpdatePhysicsHook(Entity* entity);

static void UpdateWorldHook(Entity* entity);

};

inline void AttachEntityToActor(Entity* entity, BaseActor* actor)

{

actor->entity = entity;

actor->Attach();

}

inline void DetachEntityFromActor(Entity* entity)

{

if (entity->GetUserData() != NULL)

{

BaseActor* actor = (BaseActor*)entity->GetUserData();

actor->RemoveHooks();

delete actor;

}

}

bool DetachAllActors();

#else

class BaseActor : public Actor

{

public:

BaseActor();

virtual ~BaseActor();

virtual void Attach();

virtual void Detach();

void AddHooks();

void RemoveHooks();

// Hooks that are not working with actors in 4.2

virtual void UpdateWorld() {};

virtual void UpdatePhysics() {};

virtual void PostRender(Leadwerks::Context* context) {};

protected:

static void PostRenderHook(Entity* entity);

static void UpdatePhysicsHook(Entity* entity);

static void UpdateWorldHook(Entity* entity);

};

#endif

}

#endif

 

CPP:

 


// Temp Actor class until the offical one gets improved.

#include "BaseActor.h"

std::vector<Leadwerks::BaseActor*> vActors;

namespace Leadwerks

{

#ifdef CUSTOM_ACTOR

bool DetachAllActors()

{

if (vActors.size() <= 0)

return false;

// Come back to this later...

for (auto actor : vActors) {

actor->Shutdown();

}

vActors.clear();

return true;

}

void BaseActor::Attach()

{

if (entity == nullptr) { return; }

entity->SetUserData((void*)this);

entity->AddHook(Entity::CollisionHook, (void*)CollisionHook);

entity->AddHook(Entity::DrawHook, (void*)DrawHook);

entity->AddHook(Entity::DrawEachHook, (void*)DrawEachHook);

entity->AddHook(Entity::PostRenderHook, (void*)PostRenderHook);

entity->AddHook(Entity::UpdateMatrixHook, (void*)UpdateMatrixHook);

entity->AddHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook);

entity->AddHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook);

vActors.push_back((BaseActor*)this);

}

void BaseActor::RemoveHooks()

{

if (entity == nullptr) { return; }

entity->RemoveHook(Entity::CollisionHook, (void*)CollisionHook);

entity->RemoveHook(Entity::DrawHook, (void*)DrawHook);

entity->RemoveHook(Entity::DrawEachHook, (void*)DrawEachHook);

entity->RemoveHook(Entity::PostRenderHook, (void*)PostRenderHook);

entity->RemoveHook(Entity::UpdateMatrixHook, (void*)UpdateMatrixHook);

entity->RemoveHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook);

entity->RemoveHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook);

entity->SetUserData(NULL);

}

BaseActor::~BaseActor()

{

//RemoveHooks();

}

void BaseActor::Detach()

{

System::Print("Puppeteer: Detach() was called.");

RemoveHooks();

delete this;

}

void BaseActor::CollisionHook(Entity* entity0, Entity* entity1, float* position, float* normal, float speed)

{

BaseActor* actor = (BaseActor*)entity0->GetUserData();

if (actor->entity == nullptr) { return; }

if (actor != NULL)

{

actor->Collision(entity1, position, normal, speed);

}

}

void BaseActor::DrawHook(Entity* entity)

{

BaseActor* actor = (BaseActor*)entity->GetUserData();

if (actor->entity == nullptr) { return; }

if (actor != NULL)

{

//actor->Draw(WORLD->);

}

}

void BaseActor::DrawEachHook(Entity* entity)

{

BaseActor* actor = (BaseActor*)entity->GetUserData();

if (actor->entity == nullptr) { return; }

if (actor != NULL)

{

//actor->DrawEach();

}

}

void BaseActor::PostRenderHook(Entity* entity)

{

BaseActor* actor = (BaseActor*)entity->GetUserData();

if (actor->entity == nullptr) { return; }

if (actor != NULL)

{

actor->PostRender(Leadwerks::Context::GetCurrent());

}

}

void BaseActor::UpdateMatrixHook(Entity* entity)

{

BaseActor* actor = (BaseActor*)entity->GetUserData();

if (actor->entity == nullptr) { return; }

if (actor != NULL)

{

actor->UpdateMatrix();

}

}

void BaseActor::UpdatePhysicsHook(Entity* entity)

{

BaseActor* actor = (BaseActor*)entity->GetUserData();

if (actor->entity == nullptr) { return; }

if (actor != NULL)

{

actor->UpdatePhysics();

}

}

void BaseActor::UpdateWorldHook(Entity* entity)

{

BaseActor* actor = (BaseActor*)entity->GetUserData();

if (actor->entity == nullptr) { return; }

if (actor != NULL)

{

actor->UpdateWorld();

}

}

#else

BaseActor::BaseActor() : Actor() {};

BaseActor::~BaseActor() {};

void BaseActor::Attach()

{

AddHooks();

}

void BaseActor::Detach()

{

RemoveHooks();

}

void BaseActor::AddHooks()

{

entity->AddHook(Entity::PostRenderHook, (void*)PostRenderHook);

entity->AddHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook);

entity->AddHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook);

}

void BaseActor::RemoveHooks()

{

entity->RemoveHook(Entity::PostRenderHook, (void*)PostRenderHook);

entity->RemoveHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook);

entity->RemoveHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook);

}

void BaseActor::PostRenderHook(Entity* entity)

{

BaseActor* script = (BaseActor*)entity->GetUserData();

Leadwerks::Context* context = Leadwerks::Context::GetCurrent();

if (script != nullptr)

{

script->PostRender(context);

}

}

void BaseActor::UpdatePhysicsHook(Entity* entity)

{

BaseActor* script = (BaseActor*)entity->GetActor();

if (script != nullptr)

{

script->UpdatePhysics();

}

}

void BaseActor::UpdateWorldHook(Entity* entity)

{

BaseActor* script = (BaseActor*)entity->GetActor();

if (script != nullptr)

{

script->UpdateWorld();

}

}

#endif

}

 

Only gotcha with mine is that I need to call this command before clearing/releasing the world.

Leadwerks::DetachAllActors();

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

  • 4 weeks later...

A new function is being added to this class:

  • virtual void EndAnimation(const int sequence)

 

This will be called when a one-shot PlayAnimation call reaches the end of the sequence.

 

Support for UpdateWorld, UpdatePhysics, and PostRender calls is being added as well.

  • Upvote 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

  • 3 weeks later...
  • 1 month later...

Assigning an actor to an entity during or after level load causes crashing.

 

CPP:

#pragma once

#include "ActorFactory.h"

/*

#include

#include

#include

*/

 

#include "../../Game/SimpleActor.h"

namespace Leadwerks

{

void ActorFactory::AssignEntityToActor(Entity* entity, string actorname)

{

if (actorname == "actor_test")

{

SimpleActor* a = new SimpleActor;

if (entity != NULL)

{

entity->SetActor(a);

}

}

}

 

/*

Actor* TestCreate(vector parameters)

{

Actor* b = new Actor;

return b;

}

*/

 

}

 

Header:

#pragma once

#include "Leadwerks.h"

 

namespace Leadwerks

{

class Actor;

class Entity;

 

class ActorFactory : public Object//lua

{

public:

//static void AssignNameToActor(string pName, Actor* actorclass);

static void AssignEntityToActor(Entity* entity, string actorname);//lua

 

private:

ActorFactory() {};

~ActorFactory() {};

};

}

 

What I was trying to do was a system in which I'd register all my actors to a map, but this simple function is causing issues...

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

  • Josh unpinned this topic

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...