Newer
Older
Import / projects / Gameloft / bne_lib / code / Utils / ObjectUtils.cpp
#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