#include "ObjectUtils.h"
#include "Utils/RangeFor.h"
#include <CasualCore.h>
#include <Graphics/Object.h>
#include <Graphics/Level.h>
namespace bne
{
#if !defined(BNE_OBJECT_CROSSOVER)
void RemoveObjectFromLevel(CasualCore::Level* a_level, RKTransformObject* a_obj) {
if (a_level == nullptr || a_obj == nullptr) {
return;
}
// Copy list locally before iteration - may not be necessary but AKL recommeneds it
RKList<RKTransformObject*, 8> children = a_obj->GetChildren();
for (RKTransformObject* child : children) {
RemoveObjectFromLevel(a_level, child);
}
a_level->RemoveObject(a_obj);
}
RKTransformObject* CreateObjectFromFriendlyRKIName(const char* a_pFriendlyRKIName) {
const char* c_noLevel = nullptr;
const bool c_doNotAddToLevel = false;
return CasualCore::Game::GetInstance()->GetScene()->CreateObjectFromFriendlyRKIName(a_pFriendlyRKIName, c_noLevel, c_doNotAddToLevel);
}
void DestroyObject(RKTransformObject* a_pObject) {
if (a_pObject != nullptr) {
// Copy list locally before iteration - may not be necessary but AKL recommeneds it
//RKList<RKTransformObject*, 8> children = a_pObject->GetChildren();
//for (RKTransformObject* child : children) {
// DestroyObject(child);
//}
RKObjectFactory::GetInstance().DestroyObject(a_pObject, true);
}
}
#endif // !defined(BNE_OBJECT_CROSSOVER)
#if defined(BNE_OBJECT_INTERFACE)
namespace object
{
CasualCore::Level *GetLevelContainingObject(RKTransformObject *pObject)
{
/*
// Iterate through levels in scene till we find the object
const RKList<CasualCore::Level*> levelList = SCENE->GetLevelList();
for(size_t l = 0; l < levelList.Size(); l++)
{
CasualCore::Level *pLevel = levelList.GetAt(l);
ssize_t objectIndex = pLevel->GetBaseList().FirstIndexOf(pObject);
if(objectIndex != -1)
{
return pLevel;
}
}
return NULL;
*/
return pObject->Internal_GetLevel();
}
static void RemoveObjectTreeFromLevel(RKTransformObject *pObject, CasualCore::Level *pLevel)
{
// Process children
for(size_t c = 0; c < pObject->GetChildren().Size(); c++)
{
RKTransformObject *pChildObject = pObject->GetChildren().GetAt(c);
RemoveObjectTreeFromLevel(pChildObject, pLevel);
}
// Remove this actual object from the level
bool bRemoved = pLevel->RemoveObject(pObject, false);
RKASSERT(bRemoved, "Failed to remove object [%s] from level [%s]", pObject->GetName().GetString(), pLevel->GetLevelName().GetString());
}
static void AddObjectTreeToLevel(RKTransformObject *pObject, CasualCore::Level *pLevel)
{
// Process children
for(size_t c = 0; c < pObject->GetChildren().Size(); c++)
{
RKTransformObject *pChildObject = pObject->GetChildren().GetAt(c);
AddObjectTreeToLevel(pChildObject, pLevel);
}
// Add this actual object to level
pLevel->AddObject(pObject);
}
static void DestroyObjectTree(RKTransformObject *pObject, CasualCore::Level *pSpecifiedObjectLevel = NULL)
{
// Get level containing object
CasualCore::Level *pLevel = NULL;
if(pSpecifiedObjectLevel)
{
pLevel = pSpecifiedObjectLevel;
}
else
{
pLevel = GetLevelContainingObject(pObject);
}
RKASSERT(pLevel, "Trying to destroy object [%s] which is not in a level", pObject->GetName().GetString());
// Process children
while(pObject && pObject->GetChildren().Size() > 0)
{
RKTransformObject *pChildObject = pObject->GetChildren().GetAt(0);
if(pChildObject)
{
DestroyObjectTree(pChildObject, pLevel);
}
else
{
pObject->GetChildren().EraseAt(0);
}
}
// Destroy this actual object
bool bRemoved = pLevel->RemoveObject(pObject, true);
RKASSERT(bRemoved, "Failed to remove object [%s] from level [%s]", pObject->GetName().GetString(), pLevel->GetLevelName().GetString());
}
// BNE OBJECT INTERFACE
CasualCore::Object *CreateFromTemplate(const char *pFriendlyRKIName, CasualCore::Level *pLevel)
{
RKASSERT(pFriendlyRKIName, "Trying to create an object from RKI without an object name");
RKASSERT(pLevel, "Trying create an object [%s] from RKI without a level. Currently this is not supported", pFriendlyRKIName);
return SCENE->CreateObjectFromFriendlyRKIName(pFriendlyRKIName, pLevel->GetLevelName().GetString(), true);
}
RKTransformObject *CreateFromType(const char *pObjectTypeName, CasualCore::Level *pLevel)
{
RKASSERT(pObjectTypeName, "Trying to create an object from TYPE without a type name");
RKASSERT(pLevel, "Trying create an object from TYPE [%s] without a level. Currently this is not supported", pObjectTypeName);
return SCENE->AddObject(pObjectTypeName, NULL, NULL, pLevel->GetLevelName().GetString());
}
CasualCore::Object *CreateFromTemplate(const char *pFriendlyRKIName, RKTransformObject *pParent)
{
RKASSERT(pFriendlyRKIName, "Trying to create an object from RKI without an object name");
RKASSERT(pParent, "Trying create an object [%s] from RKI with a NULL parent.", pFriendlyRKIName);
CasualCore::Level *pParentLevel = GetLevelContainingObject(pParent);
RKASSERT(pParentLevel, "Cannot create object [%s] with parent [%s] as parent does not have a level", pFriendlyRKIName, pParent->GetName().GetString());
CasualCore::Object *pObject = SCENE->CreateObjectFromFriendlyRKIName(pFriendlyRKIName, pParentLevel->GetLevelName().GetString(), true);
if(pObject)
{
bne::object::AttachToParent(pObject, pParent);
}
return pObject;
}
RKTransformObject *CreateFromType(const char *pObjectTypeName, RKTransformObject *pParent)
{
RKASSERT(pObjectTypeName, "Trying to create an object from TYPE without a type name");
RKASSERT(pParent, "Trying create an object from TYPE [%s] with a NULL parent.", pObjectTypeName);
CasualCore::Level *pParentLevel = GetLevelContainingObject(pParent);
RKASSERT(pParentLevel, "Cannot create object from type [%s] with parent [%s] as parent does not have a level", pObjectTypeName, pParent->GetName().GetString());
RKTransformObject *pObject = SCENE->AddObject(pObjectTypeName, NULL, NULL, pParentLevel->GetLevelName().GetString());
if(pObject)
{
bne::object::AttachToParent(pObject, pParent);
}
return pObject;
}
void Destroy(RKTransformObject *pObject)
{
if(!pObject)
{
return;
}
// Destroy object and all it's children
DestroyObjectTree(pObject);
}
void AttachToLevel(RKTransformObject *pObject, CasualCore::Level *pLevel)
{
RKASSERT(pObject && pLevel, "NULL pointer when trying to attach an object to a level");
// SetParent to NULL
pObject->SetParent(NULL);
// If object level == requested level then exit here
CasualCore::Level *pObjectLevel = GetLevelContainingObject(pObject);
if(pObjectLevel == pLevel)
{
return;
}
// Remove from existing level
if(pObjectLevel)
{
RemoveObjectTreeFromLevel(pObject, pObjectLevel);
}
// Add object and its children to requested level
AddObjectTreeToLevel(pObject, pLevel);
}
void AttachToParent(RKTransformObject *pObject, RKTransformObject *pParentObject, int refIndex, bool refIndexIsBone)
{
RKASSERT(pObject && pParentObject, "NULL pointer when trying to attach an object to a parent");
// SetParent to parent object
pObject->SetParent(pParentObject, refIndex, refIndexIsBone);
// If object level == parentObject level then exit here
CasualCore::Level *pObjectLevel = GetLevelContainingObject(pObject);
CasualCore::Level *pParentLevel = GetLevelContainingObject(pParentObject);
if(pObjectLevel == pParentLevel)
{
return;
}
// Remove from existing level
if(pObjectLevel)
{
RemoveObjectTreeFromLevel(pObject, pObjectLevel);
}
// Add object and its children to the parent level
AddObjectTreeToLevel(pObject, pParentLevel);
}
}
#endif // defined(BNE_OBJECT_INTERFACE)
} // namespace bne