diff --git a/Deer/Include/Deer/Enviroment.h b/Deer/Include/Deer/Enviroment.h index b221bcf..e7fb3dc 100755 --- a/Deer/Include/Deer/Enviroment.h +++ b/Deer/Include/Deer/Enviroment.h @@ -165,11 +165,8 @@ namespace Deer { }; namespace EnvironmentManager { - uint16_t createEnvironment(const std::string& name); - uint16_t getEnvironmentId(const std::string& name); - + uint16_t createEnvironment(); Environment& getEnvironment(uint16_t); - const std::string& getEnvironmentName(uint16_t); void clearAllEnvironments(); } diff --git a/Deer/src/Deer/Core/Application.cpp b/Deer/src/Deer/Core/Application.cpp index 92325fd..1ac2ec5 100644 --- a/Deer/src/Deer/Core/Application.cpp +++ b/Deer/src/Deer/Core/Application.cpp @@ -2,15 +2,6 @@ #include #include -#ifdef DEER_RENDER -#include "DeerRender/Render/RenderCommand.h" -#include "DeerRender/Render/RenderUtils.h" -#include "DeerRender/Render/Render.h" - -#include "DeerRender/ImGui/ImGuiLayer.h" -#include "imgui.h" -#endif - namespace Deer { namespace Application { // Implemented in DeerRender/Application diff --git a/Deer/src/Deer/Scene/EnvironmentManager.cpp b/Deer/src/Deer/Scene/EnvironmentManager.cpp index 410b23c..d219386 100644 --- a/Deer/src/Deer/Scene/EnvironmentManager.cpp +++ b/Deer/src/Deer/Scene/EnvironmentManager.cpp @@ -6,45 +6,35 @@ namespace Deer { namespace EnvironmentManager { struct EnvironmentContainer { Environment* env_data = nullptr; - std::string env_name; }; - std::unordered_map environment_name_id; EnvironmentContainer environments[MAX_ENVIRONMENT_COUNT]{}; uint16_t maxEnvironmentId = 1; } - uint16_t EnvironmentManager::createEnvironment(const std::string& name) { + uint16_t EnvironmentManager::createEnvironment() { + if (maxEnvironmentId >= MAX_ENVIRONMENT_COUNT) { + DEER_CORE_ERROR("Max environment count"); + return 0; + } + uint16_t envId = maxEnvironmentId; maxEnvironmentId++; environments[envId].env_data = new Environment(); - environments[envId].env_name = name; - - environment_name_id[name] = envId; return envId; } - uint16_t EnvironmentManager::getEnvironmentId(const std::string& name) { - return environment_name_id[name]; - } - Environment& EnvironmentManager::getEnvironment(uint16_t id) { + DEER_CORE_ASSERT(id >= 0 && id < MAX_ENVIRONMENT_COUNT, "Invalid environment id {0}", id); + if (id == 0) return Scene::environment; return *environments[id].env_data; } - const std::string& EnvironmentManager::getEnvironmentName(uint16_t id) { - const static std::string main_env_name("Main Environment"); - if (id == 0) - return main_env_name; - - return environments[id].env_name; - } - void EnvironmentManager::clearAllEnvironments() { for (int i = 1; i < maxEnvironmentId; i++) { delete environments[i].env_data; @@ -52,11 +42,6 @@ namespace Deer { } environments[0].env_data = &Scene::environment; - environments[0].env_name = "Main Environment"; - - environment_name_id.clear(); - environment_name_id["Main Environment"] = 0; - maxEnvironmentId = 1; } } \ No newline at end of file diff --git a/Deer/vendor/angelScript/Build.lua b/Deer/vendor/angelScript/Build.lua index 635bbcb..155e4b6 100755 --- a/Deer/vendor/angelScript/Build.lua +++ b/Deer/vendor/angelScript/Build.lua @@ -21,6 +21,7 @@ project "angelScript" defines { "ANGELSCRIPT_EXPORT", + "AS_ENABLE_METADATA", "_LIB"} filter "system:linux" diff --git a/Deer/vendor/angelScript/include/scriptdictionary.h b/Deer/vendor/angelScript/include/scriptdictionary.h new file mode 100644 index 0000000..062bb15 --- /dev/null +++ b/Deer/vendor/angelScript/include/scriptdictionary.h @@ -0,0 +1,240 @@ +#ifndef SCRIPTDICTIONARY_H +#define SCRIPTDICTIONARY_H + +// The dictionary class relies on the script string object, thus the script +// string type must be registered with the engine before registering the +// dictionary type + +#ifndef ANGELSCRIPT_H +// Avoid having to inform include path if header is already include before +#include +#endif + +// By default the CScriptDictionary use the std::string for the keys. +// If the application uses a custom string type, then this typedef +// can be changed accordingly. +#include +typedef std::string dictKey_t; + +// Forward declare CScriptDictValue so we can typedef the internal map type +BEGIN_AS_NAMESPACE +class CScriptDictValue; +END_AS_NAMESPACE + +// C++11 introduced the std::unordered_map which is a hash map which is +// is generally more performatic for lookups than the std::map which is a +// binary tree. +// TODO: memory: The map allocator should use the asAllocMem and asFreeMem +#if AS_CAN_USE_CPP11 +#include +typedef std::unordered_map dictMap_t; +#else +#include +typedef std::map dictMap_t; +#endif + + +#ifdef _MSC_VER +// Turn off annoying warnings about truncated symbol names +#pragma warning (disable:4786) +#endif + + + + +// Sometimes it may be desired to use the same method names as used by C++ STL. +// This may for example reduce time when converting code from script to C++ or +// back. +// +// 0 = off +// 1 = on + +#ifndef AS_USE_STLNAMES +#define AS_USE_STLNAMES 0 +#endif + + +BEGIN_AS_NAMESPACE + +class CScriptArray; +class CScriptDictionary; + +class CScriptDictValue +{ +public: + // This class must not be declared as local variable in C++, because it needs + // to receive the script engine pointer in all operations. The engine pointer + // is not kept as member in order to keep the size down + CScriptDictValue(); + CScriptDictValue(asIScriptEngine *engine, void *value, int typeId); + + // Destructor must not be called without first calling FreeValue, otherwise a memory leak will occur + ~CScriptDictValue(); + + // Replace the stored value + void Set(asIScriptEngine *engine, void *value, int typeId); + void Set(asIScriptEngine *engine, const asINT64 &value); + void Set(asIScriptEngine *engine, const double &value); + void Set(asIScriptEngine *engine, CScriptDictValue &value); + + // Gets the stored value. Returns false if the value isn't compatible with the informed typeId + bool Get(asIScriptEngine *engine, void *value, int typeId) const; + bool Get(asIScriptEngine *engine, asINT64 &value) const; + bool Get(asIScriptEngine *engine, double &value) const; + + // Returns the address of the stored value for inspection + const void *GetAddressOfValue() const; + + // Returns the type id of the stored value + int GetTypeId() const; + + // Free the stored value + void FreeValue(asIScriptEngine *engine); + + // GC callback + void EnumReferences(asIScriptEngine *engine); + +protected: + friend class CScriptDictionary; + + union + { + asINT64 m_valueInt; + double m_valueFlt; + void *m_valueObj; + }; + int m_typeId; +}; + +class CScriptDictionary +{ +public: + // Factory functions + static CScriptDictionary *Create(asIScriptEngine *engine); + + // Called from the script to instantiate a dictionary from an initialization list + static CScriptDictionary *Create(asBYTE *buffer); + + // Reference counting + void AddRef() const; + void Release() const; + + // Reassign the dictionary + CScriptDictionary &operator =(const CScriptDictionary &other); + + // Sets a key/value pair + void Set(const dictKey_t &key, void *value, int typeId); + void Set(const dictKey_t &key, const asINT64 &value); + void Set(const dictKey_t &key, const double &value); + + // Gets the stored value. Returns false if the value isn't compatible with the informed typeId + bool Get(const dictKey_t &key, void *value, int typeId) const; + bool Get(const dictKey_t &key, asINT64 &value) const; + bool Get(const dictKey_t &key, double &value) const; + + // Index accessors. If the dictionary is not const it inserts the value if it doesn't already exist + // If the dictionary is const then a script exception is set if it doesn't exist and a null pointer is returned + CScriptDictValue *operator[](const dictKey_t &key); + const CScriptDictValue *operator[](const dictKey_t &key) const; + + // Returns the type id of the stored value, or negative if it doesn't exist + int GetTypeId(const dictKey_t &key) const; + + // Returns true if the key is set + bool Exists(const dictKey_t &key) const; + + // Returns true if there are no key/value pairs in the dictionary + bool IsEmpty() const; + + // Returns the number of key/value pairs in the dictionary + asUINT GetSize() const; + + // Deletes the key + bool Delete(const dictKey_t &key); + + // Deletes all keys + void DeleteAll(); + + // Get an array of all keys + CScriptArray *GetKeys() const; + + // STL style iterator + class CIterator + { + public: + void operator++(); // Pre-increment + void operator++(int); // Post-increment + + // This is needed to support C++11 range-for + CIterator &operator*(); + + bool operator==(const CIterator &other) const; + bool operator!=(const CIterator &other) const; + + // Accessors + const dictKey_t &GetKey() const; + int GetTypeId() const; + bool GetValue(asINT64 &value) const; + bool GetValue(double &value) const; + bool GetValue(void *value, int typeId) const; + const void * GetAddressOfValue() const; + + protected: + friend class CScriptDictionary; + + CIterator(); + CIterator(const CScriptDictionary &dict, + dictMap_t::const_iterator it); + + CIterator &operator=(const CIterator &) {return *this;} // Not used + + dictMap_t::const_iterator m_it; + const CScriptDictionary &m_dict; + }; + + CIterator begin() const; + CIterator end() const; + CIterator find(const dictKey_t &key) const; + + // Garbage collections behaviours + int GetRefCount(); + void SetGCFlag(); + bool GetGCFlag(); + void EnumReferences(asIScriptEngine *engine); + void ReleaseAllReferences(asIScriptEngine *engine); + +protected: + // Since the dictionary uses the asAllocMem and asFreeMem functions to allocate memory + // the constructors are made protected so that the application cannot allocate it + // manually in a different way + CScriptDictionary(asIScriptEngine *engine); + CScriptDictionary(asBYTE *buffer); + + // We don't want anyone to call the destructor directly, it should be called through the Release method + virtual ~CScriptDictionary(); + + // Cache the object types needed + void Init(asIScriptEngine *engine); + + // Our properties + asIScriptEngine *engine; + mutable int refCount; + mutable bool gcFlag; + dictMap_t dict; +}; + +// This function will determine the configuration of the engine +// and use one of the two functions below to register the dictionary object +void RegisterScriptDictionary(asIScriptEngine *engine); + +// Call this function to register the math functions +// using native calling conventions +void RegisterScriptDictionary_Native(asIScriptEngine *engine); + +// Use this one instead if native calling conventions +// are not supported on the target platform +void RegisterScriptDictionary_Generic(asIScriptEngine *engine); + +END_AS_NAMESPACE + +#endif diff --git a/Deer/vendor/angelScript/src/scriptdictionary.cpp b/Deer/vendor/angelScript/src/scriptdictionary.cpp new file mode 100644 index 0000000..35342d6 --- /dev/null +++ b/Deer/vendor/angelScript/src/scriptdictionary.cpp @@ -0,0 +1,1299 @@ +#include +#include +#include "scriptdictionary.h" +#include "scriptarray.h" + +BEGIN_AS_NAMESPACE + +using namespace std; + +//------------------------------------------------------------------------ +// Object types are cached as user data to avoid costly runtime lookups + +// We just define a number here that we assume nobody else is using for +// object type user data. The add-ons have reserved the numbers 1000 +// through 1999 for this purpose, so we should be fine. +const asPWORD DICTIONARY_CACHE = 1003; + +// This cache holds the object type of the dictionary type and array type +// so it isn't necessary to look this up each time the dictionary or array +// is created. +struct SDictionaryCache +{ + asITypeInfo *dictType; + asITypeInfo *arrayType; + asITypeInfo *keyType; + + // This is called from RegisterScriptDictionary + static void Setup(asIScriptEngine *engine) + { + SDictionaryCache *cache = reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + if( cache == 0 ) + { + cache = new SDictionaryCache; + engine->SetUserData(cache, DICTIONARY_CACHE); + engine->SetEngineUserDataCleanupCallback(SDictionaryCache::Cleanup, DICTIONARY_CACHE); + + cache->dictType = engine->GetTypeInfoByName("dictionary"); + cache->arrayType = engine->GetTypeInfoByDecl("array"); + cache->keyType = engine->GetTypeInfoByDecl("string"); + } + } + + // This is called from the engine when shutting down + static void Cleanup(asIScriptEngine *engine) + { + SDictionaryCache *cache = reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + if( cache ) + delete cache; + } +}; + +//-------------------------------------------------------------------------- +// CScriptDictionary implementation + +CScriptDictionary *CScriptDictionary::Create(asIScriptEngine *engine) +{ + // Use the custom memory routine from AngelScript to allow application to better control how much memory is used + CScriptDictionary *obj = (CScriptDictionary*)asAllocMem(sizeof(CScriptDictionary)); + new(obj) CScriptDictionary(engine); + return obj; +} + +CScriptDictionary *CScriptDictionary::Create(asBYTE *buffer) +{ + // Use the custom memory routine from AngelScript to allow application to better control how much memory is used + CScriptDictionary *obj = (CScriptDictionary*)asAllocMem(sizeof(CScriptDictionary)); + new(obj) CScriptDictionary(buffer); + return obj; +} + +CScriptDictionary::CScriptDictionary(asIScriptEngine *engine) +{ + Init(engine); +} + +void CScriptDictionary::Init(asIScriptEngine *e) +{ + // We start with one reference + refCount = 1; + gcFlag = false; + + // Keep a reference to the engine for as long as we live + // We don't increment the reference counter, because the + // engine will hold a pointer to the object in the GC. + engine = e; + + // The dictionary object type is cached to avoid dynamically parsing it each time + SDictionaryCache *cache = reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + + // Notify the garbage collector of this object + engine->NotifyGarbageCollectorOfNewObject(this, cache->dictType); +} + +CScriptDictionary::CScriptDictionary(asBYTE *buffer) +{ + // This constructor will always be called from a script + // so we can get the engine from the active context + asIScriptContext *ctx = asGetActiveContext(); + Init(ctx->GetEngine()); + + // Determine if the dictionary key type is registered as reference type or value type + SDictionaryCache& cache = *reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + bool keyAsRef = cache.keyType->GetFlags() & asOBJ_REF ? true : false; + + // Initialize the dictionary from the buffer + asUINT length = *(asUINT*)buffer; + buffer += 4; + + while( length-- ) + { + // Align the buffer pointer on a 4 byte boundary in + // case previous value was smaller than 4 bytes + if( asPWORD(buffer) & 0x3 ) + buffer += 4 - (asPWORD(buffer) & 0x3); + + // Get the name value pair from the buffer and insert it in the dictionary + dictKey_t name; + if (keyAsRef) + { + name = **(dictKey_t**)buffer; + buffer += sizeof(dictKey_t*); + } + else + { + name = *(dictKey_t*)buffer; + buffer += sizeof(dictKey_t); + } + + // Get the type id of the value + int typeId = *(int*)buffer; + buffer += sizeof(int); + + // Depending on the type id, the value will inline in the buffer or a pointer + void *ref = (void*)buffer; + + if( typeId >= asTYPEID_INT8 && typeId <= asTYPEID_DOUBLE ) + { + // Convert primitive values to either int64 or double, so we can use the overloaded Set methods + asINT64 i64; + double d; + switch( typeId ) + { + case asTYPEID_INT8: i64 = *(char*) ref; break; + case asTYPEID_INT16: i64 = *(short*) ref; break; + case asTYPEID_INT32: i64 = *(int*) ref; break; + case asTYPEID_INT64: i64 = *(asINT64*) ref; break; + case asTYPEID_UINT8: i64 = *(unsigned char*) ref; break; + case asTYPEID_UINT16: i64 = *(unsigned short*)ref; break; + case asTYPEID_UINT32: i64 = *(unsigned int*) ref; break; + case asTYPEID_UINT64: i64 = *(asINT64*) ref; break; + case asTYPEID_FLOAT: d = *(float*) ref; break; + case asTYPEID_DOUBLE: d = *(double*) ref; break; + } + + if( typeId >= asTYPEID_FLOAT ) + Set(name, d); + else + Set(name, i64); + } + else + { + if( (typeId & asTYPEID_MASK_OBJECT) && + !(typeId & asTYPEID_OBJHANDLE) && + (engine->GetTypeInfoById(typeId)->GetFlags() & asOBJ_REF) ) + { + // Dereference the pointer to get the reference to the actual object + ref = *(void**)ref; + } + + Set(name, ref, typeId); + } + + // Advance the buffer pointer with the size of the value + if( typeId & asTYPEID_MASK_OBJECT ) + { + asITypeInfo *ti = engine->GetTypeInfoById(typeId); + if( ti->GetFlags() & asOBJ_VALUE ) + buffer += ti->GetSize(); + else + buffer += sizeof(void*); + } + else if( typeId == 0 ) + { + // null pointer + buffer += sizeof(void*); + } + else + { + buffer += engine->GetSizeOfPrimitiveType(typeId); + } + } +} + +CScriptDictionary::~CScriptDictionary() +{ + // Delete all keys and values + DeleteAll(); +} + +void CScriptDictionary::AddRef() const +{ + // We need to clear the GC flag + gcFlag = false; + asAtomicInc(refCount); +} + +void CScriptDictionary::Release() const +{ + // We need to clear the GC flag + gcFlag = false; + if( asAtomicDec(refCount) == 0 ) + { + this->~CScriptDictionary(); + asFreeMem(const_cast(this)); + } +} + +int CScriptDictionary::GetRefCount() +{ + return refCount; +} + +void CScriptDictionary::SetGCFlag() +{ + gcFlag = true; +} + +bool CScriptDictionary::GetGCFlag() +{ + return gcFlag; +} + +void CScriptDictionary::EnumReferences(asIScriptEngine *inEngine) +{ + // TODO: If garbage collection can be done from a separate thread, then this method must be + // protected so that it doesn't get lost during the iteration if the dictionary is modified + + // Call the gc enum callback for each of the objects + dictMap_t::iterator it; + for( it = dict.begin(); it != dict.end(); it++ ) + { + if (it->second.m_typeId & asTYPEID_MASK_OBJECT) + { + asITypeInfo *subType = engine->GetTypeInfoById(it->second.m_typeId); + if ((subType->GetFlags() & asOBJ_VALUE) && (subType->GetFlags() & asOBJ_GC)) + { + // For value types we need to forward the enum callback + // to the object so it can decide what to do + engine->ForwardGCEnumReferences(it->second.m_valueObj, subType); + } + else + { + // For others, simply notify the GC about the reference + inEngine->GCEnumCallback(it->second.m_valueObj); + } + } + } +} + +void CScriptDictionary::ReleaseAllReferences(asIScriptEngine * /*engine*/) +{ + // We're being told to release all references in + // order to break circular references for dead objects + DeleteAll(); +} + +CScriptDictionary &CScriptDictionary::operator =(const CScriptDictionary &other) +{ + // Clear everything we had before + DeleteAll(); + + // Do a shallow copy of the dictionary + dictMap_t::const_iterator it; + for( it = other.dict.begin(); it != other.dict.end(); it++ ) + { + if( it->second.m_typeId & asTYPEID_OBJHANDLE ) + Set(it->first, (void*)&it->second.m_valueObj, it->second.m_typeId); + else if( it->second.m_typeId & asTYPEID_MASK_OBJECT ) + Set(it->first, (void*)it->second.m_valueObj, it->second.m_typeId); + else + Set(it->first, (void*)&it->second.m_valueInt, it->second.m_typeId); + } + + return *this; +} + +CScriptDictValue *CScriptDictionary::operator[](const dictKey_t &key) +{ + // Return the existing value if it exists, else insert an empty value + return &dict[key]; +} + +const CScriptDictValue *CScriptDictionary::operator[](const dictKey_t &key) const +{ + // Return the existing value if it exists + dictMap_t::const_iterator it; + it = dict.find(key); + if( it != dict.end() ) + return &it->second; + + // Else raise an exception + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Invalid access to non-existing value"); + + return 0; +} + +void CScriptDictionary::Set(const dictKey_t &key, void *value, int typeId) +{ + dictMap_t::iterator it; + it = dict.find(key); + if( it == dict.end() ) + it = dict.insert(dictMap_t::value_type(key, CScriptDictValue())).first; + + it->second.Set(engine, value, typeId); +} + +// This overloaded method is implemented so that all integer and +// unsigned integers types will be stored in the dictionary as int64 +// through implicit conversions. This simplifies the management of the +// numeric types when the script retrieves the stored value using a +// different type. +void CScriptDictionary::Set(const dictKey_t &key, const asINT64 &value) +{ + Set(key, const_cast(&value), asTYPEID_INT64); +} + +// This overloaded method is implemented so that all floating point types +// will be stored in the dictionary as double through implicit conversions. +// This simplifies the management of the numeric types when the script +// retrieves the stored value using a different type. +void CScriptDictionary::Set(const dictKey_t &key, const double &value) +{ + Set(key, const_cast(&value), asTYPEID_DOUBLE); +} + +// Returns true if the value was successfully retrieved +bool CScriptDictionary::Get(const dictKey_t &key, void *value, int typeId) const +{ + dictMap_t::const_iterator it; + it = dict.find(key); + if( it != dict.end() ) + return it->second.Get(engine, value, typeId); + + // AngelScript has already initialized the value with a default value, + // so we don't have to do anything if we don't find the element, or if + // the element is incompatible with the requested type. + + return false; +} + +// Returns the type id of the stored value +int CScriptDictionary::GetTypeId(const dictKey_t &key) const +{ + dictMap_t::const_iterator it; + it = dict.find(key); + if( it != dict.end() ) + return it->second.m_typeId; + + return -1; +} + +bool CScriptDictionary::Get(const dictKey_t &key, asINT64 &value) const +{ + return Get(key, &value, asTYPEID_INT64); +} + +bool CScriptDictionary::Get(const dictKey_t &key, double &value) const +{ + return Get(key, &value, asTYPEID_DOUBLE); +} + +bool CScriptDictionary::Exists(const dictKey_t &key) const +{ + dictMap_t::const_iterator it; + it = dict.find(key); + if( it != dict.end() ) + return true; + + return false; +} + +bool CScriptDictionary::IsEmpty() const +{ + if( dict.size() == 0 ) + return true; + + return false; +} + +asUINT CScriptDictionary::GetSize() const +{ + return asUINT(dict.size()); +} + +bool CScriptDictionary::Delete(const dictKey_t &key) +{ + dictMap_t::iterator it; + it = dict.find(key); + if( it != dict.end() ) + { + it->second.FreeValue(engine); + dict.erase(it); + return true; + } + + return false; +} + +void CScriptDictionary::DeleteAll() +{ + dictMap_t::iterator it; + for( it = dict.begin(); it != dict.end(); it++ ) + it->second.FreeValue(engine); + + dict.clear(); +} + +CScriptArray* CScriptDictionary::GetKeys() const +{ + // Retrieve the object type for the array from the cache + SDictionaryCache *cache = reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + asITypeInfo *ti = cache->arrayType; + + // Create the array object + CScriptArray *array = CScriptArray::Create(ti, asUINT(dict.size())); + long current = -1; + dictMap_t::const_iterator it; + for( it = dict.begin(); it != dict.end(); it++ ) + { + current++; + *(dictKey_t*)array->At(current) = it->first; + } + + return array; +} + +//-------------------------------------------------------------------------- +// Generic wrappers + +void ScriptDictionaryFactory_Generic(asIScriptGeneric *gen) +{ + *(CScriptDictionary**)gen->GetAddressOfReturnLocation() = CScriptDictionary::Create(gen->GetEngine()); +} + +void ScriptDictionaryListFactory_Generic(asIScriptGeneric *gen) +{ + asBYTE *buffer = (asBYTE*)gen->GetArgAddress(0); + *(CScriptDictionary**)gen->GetAddressOfReturnLocation() = CScriptDictionary::Create(buffer); +} + +void ScriptDictionaryAddRef_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dict->AddRef(); +} + +void ScriptDictionaryRelease_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dict->Release(); +} + +void ScriptDictionaryAssign_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + CScriptDictionary *other = *(CScriptDictionary**)gen->GetAddressOfArg(0); + *dict = *other; + *(CScriptDictionary**)gen->GetAddressOfReturnLocation() = dict; +} + +void ScriptDictionarySet_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + int typeId = gen->GetArgTypeId(1); + dict->Set(*key, ref, typeId); +} + +void ScriptDictionarySetInt_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + dict->Set(*key, *(asINT64*)ref); +} + +void ScriptDictionarySetFlt_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + dict->Set(*key, *(double*)ref); +} + +void ScriptDictionaryGet_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + int typeId = gen->GetArgTypeId(1); + *(bool*)gen->GetAddressOfReturnLocation() = dict->Get(*key, ref, typeId); +} + +void ScriptDictionaryGetInt_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + *(bool*)gen->GetAddressOfReturnLocation() = dict->Get(*key, *(asINT64*)ref); +} + +void ScriptDictionaryGetFlt_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + *(bool*)gen->GetAddressOfReturnLocation() = dict->Get(*key, *(double*)ref); +} + +void ScriptDictionaryExists_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + bool ret = dict->Exists(*key); + *(bool*)gen->GetAddressOfReturnLocation() = ret; +} + +void ScriptDictionaryIsEmpty_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + bool ret = dict->IsEmpty(); + *(bool*)gen->GetAddressOfReturnLocation() = ret; +} + +void ScriptDictionaryGetSize_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + asUINT ret = dict->GetSize(); + *(asUINT*)gen->GetAddressOfReturnLocation() = ret; +} + +void ScriptDictionaryDelete_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + *(bool*)gen->GetAddressOfReturnLocation() = dict->Delete(*key); +} + +void ScriptDictionaryDeleteAll_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dict->DeleteAll(); +} + +static void ScriptDictionaryGetRefCount_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + *(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount(); +} + +static void ScriptDictionarySetGCFlag_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + self->SetGCFlag(); +} + +static void ScriptDictionaryGetGCFlag_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + *(bool*)gen->GetAddressOfReturnLocation() = self->GetGCFlag(); +} + +static void ScriptDictionaryEnumReferences_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); + self->EnumReferences(engine); +} + +static void ScriptDictionaryReleaseAllReferences_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); + self->ReleaseAllReferences(engine); +} + +static void CScriptDictionaryGetKeys_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + *(CScriptArray**)gen->GetAddressOfReturnLocation() = self->GetKeys(); +} + +static void CScriptDictionary_opIndex_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = self->operator[](*key); +} + +static void CScriptDictionary_opIndex_const_Generic(asIScriptGeneric *gen) +{ + const CScriptDictionary *self = (const CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + *(const CScriptDictValue**)gen->GetAddressOfReturnLocation() = self->operator[](*key); +} + + +//------------------------------------------------------------------------- +// CScriptDictValue + +CScriptDictValue::CScriptDictValue() +{ + m_valueObj = 0; + m_typeId = 0; +} + +CScriptDictValue::CScriptDictValue(asIScriptEngine *engine, void *value, int typeId) +{ + m_valueObj = 0; + m_typeId = 0; + Set(engine, value, typeId); +} + +CScriptDictValue::~CScriptDictValue() +{ + if (m_valueObj && m_typeId) + { + asIScriptContext *ctx = asGetActiveContext(); + if (ctx) + FreeValue(ctx->GetEngine()); + else + { + // Must not hold an object when destroyed, as then the object will never be freed + assert((m_typeId & asTYPEID_MASK_OBJECT) == 0); + } + } +} + +void CScriptDictValue::FreeValue(asIScriptEngine *engine) +{ + // If it is a handle or a ref counted object, call release + if( m_typeId & asTYPEID_MASK_OBJECT ) + { + // Let the engine release the object + engine->ReleaseScriptObject(m_valueObj, engine->GetTypeInfoById(m_typeId)); + m_valueObj = 0; + m_typeId = 0; + } + + // For primitives, there's nothing to do +} + +void CScriptDictValue::EnumReferences(asIScriptEngine *inEngine) +{ + // If we're holding a reference, we'll notify the garbage collector of it + if (m_valueObj) + inEngine->GCEnumCallback(m_valueObj); + + // The object type itself is also garbage collected + if (m_typeId) + inEngine->GCEnumCallback(inEngine->GetTypeInfoById(m_typeId)); +} + +void CScriptDictValue::Set(asIScriptEngine *engine, void *value, int typeId) +{ + FreeValue(engine); + + m_typeId = typeId; + if( typeId & asTYPEID_OBJHANDLE ) + { + // We're receiving a reference to the handle, so we need to dereference it + m_valueObj = *(void**)value; + engine->AddRefScriptObject(m_valueObj, engine->GetTypeInfoById(typeId)); + } + else if( typeId & asTYPEID_MASK_OBJECT ) + { + // Create a copy of the object + m_valueObj = engine->CreateScriptObjectCopy(value, engine->GetTypeInfoById(typeId)); + if( m_valueObj == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Cannot create copy of object"); + } + } + else + { + // Copy the primitive value + // We receive a pointer to the value. + int size = engine->GetSizeOfPrimitiveType(typeId); + memcpy(&m_valueInt, value, size); + } +} + +void CScriptDictValue::Set(asIScriptEngine *engine, CScriptDictValue &value) +{ + if( value.m_typeId & asTYPEID_OBJHANDLE ) + Set(engine, (void*)&value.m_valueObj, value.m_typeId); + else if( value.m_typeId & asTYPEID_MASK_OBJECT ) + Set(engine, (void*)value.m_valueObj, value.m_typeId); + else + Set(engine, (void*)&value.m_valueInt, value.m_typeId); +} + +// This overloaded method is implemented so that all integer and +// unsigned integers types will be stored in the dictionary as int64 +// through implicit conversions. This simplifies the management of the +// numeric types when the script retrieves the stored value using a +// different type. +void CScriptDictValue::Set(asIScriptEngine *engine, const asINT64 &value) +{ + Set(engine, const_cast(&value), asTYPEID_INT64); +} + +// This overloaded method is implemented so that all floating point types +// will be stored in the dictionary as double through implicit conversions. +// This simplifies the management of the numeric types when the script +// retrieves the stored value using a different type. +void CScriptDictValue::Set(asIScriptEngine *engine, const double &value) +{ + Set(engine, const_cast(&value), asTYPEID_DOUBLE); +} + +bool CScriptDictValue::Get(asIScriptEngine *engine, void *value, int typeId) const +{ + // Return the value + if( typeId & asTYPEID_OBJHANDLE ) + { + // A handle can be retrieved if the stored type is a handle of same or compatible type + // or if the stored type is an object that implements the interface that the handle refer to. + if( (m_typeId & asTYPEID_MASK_OBJECT) ) + { + // Don't allow the get if the stored handle is to a const, but the desired handle is not + if( (m_typeId & asTYPEID_HANDLETOCONST) && !(typeId & asTYPEID_HANDLETOCONST) ) + return false; + + // RefCastObject will increment the refcount if successful + engine->RefCastObject(m_valueObj, engine->GetTypeInfoById(m_typeId), engine->GetTypeInfoById(typeId), reinterpret_cast(value)); + + return true; + } + } + else if( typeId & asTYPEID_MASK_OBJECT ) + { + // Verify that the copy can be made + bool isCompatible = false; + + // Allow a handle to be value assigned if the wanted type is not a handle + if( (m_typeId & ~(asTYPEID_OBJHANDLE | asTYPEID_HANDLETOCONST) ) == typeId && m_valueObj != 0 ) + isCompatible = true; + + // Copy the object into the given reference + if( isCompatible ) + { + engine->AssignScriptObject(value, m_valueObj, engine->GetTypeInfoById(typeId)); + + return true; + } + } + else + { + if( m_typeId == typeId ) + { + int size = engine->GetSizeOfPrimitiveType(typeId); + memcpy(value, &m_valueInt, size); + return true; + } + + // We know all numbers are stored as either int64 or double, since we register overloaded functions for those + // Only bool and enums needs to be treated separately + if( typeId == asTYPEID_DOUBLE ) + { + if( m_typeId == asTYPEID_INT64 ) + *(double*)value = double(m_valueInt); + else if (m_typeId == asTYPEID_BOOL) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + char localValue; + memcpy(&localValue, &m_valueInt, sizeof(char)); + *(double*)value = localValue ? 1.0 : 0.0; + } + else if (m_typeId > asTYPEID_DOUBLE && (m_typeId & asTYPEID_MASK_OBJECT) == 0) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + int localValue; + memcpy(&localValue, &m_valueInt, sizeof(int)); + *(double*)value = double(localValue); // enums are 32bit + } + else + { + // The stored type is an object + // TODO: Check if the object has a conversion operator to a primitive value + *(double*)value = 0; + return false; + } + return true; + } + else if( typeId == asTYPEID_INT64 ) + { + if( m_typeId == asTYPEID_DOUBLE ) + *(asINT64*)value = asINT64(m_valueFlt); + else if (m_typeId == asTYPEID_BOOL) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + char localValue; + memcpy(&localValue, &m_valueInt, sizeof(char)); + *(asINT64*)value = localValue ? 1 : 0; + } + else if (m_typeId > asTYPEID_DOUBLE && (m_typeId & asTYPEID_MASK_OBJECT) == 0) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + int localValue; + memcpy(&localValue, &m_valueInt, sizeof(int)); + *(asINT64*)value = localValue; // enums are 32bit + } + else + { + // The stored type is an object + // TODO: Check if the object has a conversion operator to a primitive value + *(asINT64*)value = 0; + return false; + } + return true; + } + else if( typeId > asTYPEID_DOUBLE && (m_typeId & asTYPEID_MASK_OBJECT) == 0 ) + { + // The desired type is an enum. These are always 32bit integers + if( m_typeId == asTYPEID_DOUBLE ) + *(int*)value = int(m_valueFlt); + else if( m_typeId == asTYPEID_INT64 ) + *(int*)value = int(m_valueInt); + else if (m_typeId == asTYPEID_BOOL) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + char localValue; + memcpy(&localValue, &m_valueInt, sizeof(char)); + *(int*)value = localValue ? 1 : 0; + } + else if (m_typeId > asTYPEID_DOUBLE && (m_typeId & asTYPEID_MASK_OBJECT) == 0) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + int localValue; + memcpy(&localValue, &m_valueInt, sizeof(int)); + *(int*)value = localValue; // enums are 32bit + } + else + { + // The stored type is an object + // TODO: Check if the object has a conversion operator to a primitive value + *(int*)value = 0; + return false; + } + return true; + } + else if( typeId == asTYPEID_BOOL ) + { + if (m_typeId & asTYPEID_OBJHANDLE) + { + // TODO: Check if the object has a conversion operator to a primitive value + *(bool*)value = m_valueObj ? true : false; + } + else if( m_typeId & asTYPEID_MASK_OBJECT ) + { + // TODO: Check if the object has a conversion operator to a primitive value + *(bool*)value = true; + } + else + { + // Compare only the bytes that were actually set + asQWORD zero = 0; + int size = engine->GetSizeOfPrimitiveType(m_typeId); + *(bool*)value = memcmp(&m_valueInt, &zero, size) == 0 ? false : true; + } + return true; + } + } + + // It was not possible to retrieve the value using the desired typeId + return false; +} + +const void * CScriptDictValue::GetAddressOfValue() const +{ + if( (m_typeId & asTYPEID_MASK_OBJECT) && !(m_typeId & asTYPEID_OBJHANDLE) ) + { + // Return the address to the object directly + return m_valueObj; + } + + // Return the address of the primitive or the pointer to the object + return reinterpret_cast(&m_valueObj); +} + +bool CScriptDictValue::Get(asIScriptEngine *engine, asINT64 &value) const +{ + return Get(engine, &value, asTYPEID_INT64); +} + +bool CScriptDictValue::Get(asIScriptEngine *engine, double &value) const +{ + return Get(engine, &value, asTYPEID_DOUBLE); +} + +int CScriptDictValue::GetTypeId() const +{ + return m_typeId; +} + +static void CScriptDictValue_Construct(void *mem) +{ + new(mem) CScriptDictValue(); +} + +static void CScriptDictValue_Destruct(CScriptDictValue *obj) +{ + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + { + asIScriptEngine *engine = ctx->GetEngine(); + obj->FreeValue(engine); + } + obj->~CScriptDictValue(); +} + +static CScriptDictValue &CScriptDictValue_opAssign(void *ref, int typeId, CScriptDictValue *obj) +{ + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + { + asIScriptEngine *engine = ctx->GetEngine(); + obj->Set(engine, ref, typeId); + } + return *obj; +} + +static CScriptDictValue &CScriptDictValue_opAssign(const CScriptDictValue &other, CScriptDictValue *obj) +{ + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + { + asIScriptEngine *engine = ctx->GetEngine(); + obj->Set(engine, const_cast(other)); + } + + return *obj; +} + +static CScriptDictValue &CScriptDictValue_opAssign(double val, CScriptDictValue *obj) +{ + return CScriptDictValue_opAssign(&val, asTYPEID_DOUBLE, obj); +} + +static CScriptDictValue &CScriptDictValue_opAssign(asINT64 val, CScriptDictValue *obj) +{ + return CScriptDictValue_opAssign(&val, asTYPEID_INT64, obj); +} + +static void CScriptDictValue_opCast(void *ref, int typeId, CScriptDictValue *obj) +{ + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + { + asIScriptEngine *engine = ctx->GetEngine(); + obj->Get(engine, ref, typeId); + } +} + +static asINT64 CScriptDictValue_opConvInt(CScriptDictValue *obj) +{ + asINT64 value; + CScriptDictValue_opCast(&value, asTYPEID_INT64, obj); + return value; +} + +static double CScriptDictValue_opConvDouble(CScriptDictValue *obj) +{ + double value; + CScriptDictValue_opCast(&value, asTYPEID_DOUBLE, obj); + return value; +} + +//------------------------------------------------------------------- +// generic wrapper for CScriptDictValue + +static void CScriptDictValue_opConvDouble_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + double value; + self->Get(gen->GetEngine(), value); + *(double*)gen->GetAddressOfReturnLocation() = value; +} + +static void CScriptDictValue_opConvInt_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + asINT64 value; + self->Get(gen->GetEngine(), value); + *(asINT64*)gen->GetAddressOfReturnLocation() = value; +} + +static void CScriptDictValue_opCast_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + self->Get(gen->GetEngine(), gen->GetArgAddress(0), gen->GetArgTypeId(0)); +} + +static void CScriptDictValue_opAssign_int64_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = &CScriptDictValue_opAssign((asINT64)gen->GetArgQWord(0), self); +} + +static void CScriptDictValue_opAssign_double_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = &CScriptDictValue_opAssign(gen->GetArgDouble(0), self); +} + +static void CScriptDictValue_opAssign_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = &CScriptDictValue_opAssign(gen->GetArgAddress(0), gen->GetArgTypeId(0), self); +} + +static void CScriptDictValue_opCopyAssign_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = &CScriptDictValue_opAssign(*reinterpret_cast(gen->GetArgAddress(0)), self); +} + +static void CScriptDictValue_Construct_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + CScriptDictValue_Construct(self); +} + +static void CScriptDictValue_Destruct_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + CScriptDictValue_Destruct(self); +} + +static void CScriptDictValue_EnumReferences_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + self->EnumReferences(gen->GetEngine()); +} + +static void CScriptDictValue_FreeValue_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + self->FreeValue(gen->GetEngine()); +} + +//-------------------------------------------------------------------------- +// Register the type + +void RegisterScriptDictionary(asIScriptEngine *engine) +{ + if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) + RegisterScriptDictionary_Generic(engine); + else + RegisterScriptDictionary_Native(engine); +} + +void RegisterScriptDictionary_Native(asIScriptEngine *engine) +{ + int r; + + // The array type must be available + assert( engine->GetTypeInfoByDecl("array") ); + +#if AS_CAN_USE_CPP11 + // With C++11 it is possible to use asGetTypeTraits to automatically determine the correct flags that represents the C++ class + r = engine->RegisterObjectType("dictionaryValue", sizeof(CScriptDictValue), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits()); assert( r >= 0 ); +#else + r = engine->RegisterObjectType("dictionaryValue", sizeof(CScriptDictValue), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CD); assert( r >= 0 ); +#endif + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(CScriptDictValue_Construct), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(CScriptDictValue_Destruct), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptDictValue, EnumReferences), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptDictValue, FreeValue), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(const dictionaryValue &in)", asFUNCTIONPR(CScriptDictValue_opAssign, (const CScriptDictValue &, CScriptDictValue *), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opHndlAssign(const ?&in)", asFUNCTIONPR(CScriptDictValue_opAssign, (void *, int, CScriptDictValue*), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opHndlAssign(const dictionaryValue &in)", asFUNCTIONPR(CScriptDictValue_opAssign, (const CScriptDictValue &, CScriptDictValue *), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(const ?&in)", asFUNCTIONPR(CScriptDictValue_opAssign, (void *, int, CScriptDictValue*), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(double)", asFUNCTIONPR(CScriptDictValue_opAssign, (double, CScriptDictValue*), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(int64)", asFUNCTIONPR(CScriptDictValue_opAssign, (asINT64, CScriptDictValue*), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "void opCast(?&out)", asFUNCTIONPR(CScriptDictValue_opCast, (void *, int, CScriptDictValue*), void), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "void opConv(?&out)", asFUNCTIONPR(CScriptDictValue_opCast, (void *, int, CScriptDictValue*), void), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "int64 opConv()", asFUNCTIONPR(CScriptDictValue_opConvInt, (CScriptDictValue*), asINT64), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "double opConv()", asFUNCTIONPR(CScriptDictValue_opConvDouble, (CScriptDictValue*), double), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + r = engine->RegisterObjectType("dictionary", sizeof(CScriptDictionary), asOBJ_REF | asOBJ_GC); assert( r >= 0 ); + // Use the generic interface to construct the object since we need the engine pointer, we could also have retrieved the engine pointer from the active context + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_FACTORY, "dictionary@ f()", asFUNCTION(ScriptDictionaryFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_LIST_FACTORY, "dictionary @f(int &in) {repeat {string, ?}}", asFUNCTION(ScriptDictionaryListFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptDictionary,AddRef), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptDictionary,Release), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "dictionary &opAssign(const dictionary &in)", asMETHODPR(CScriptDictionary, operator=, (const CScriptDictionary &), CScriptDictionary&), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const ?&in)", asMETHODPR(CScriptDictionary,Set,(const dictKey_t&,void*,int),void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, ?&out) const", asMETHODPR(CScriptDictionary,Get,(const dictKey_t&,void*,int) const,bool), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const int64&in)", asMETHODPR(CScriptDictionary,Set,(const dictKey_t&,const asINT64&),void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, int64&out) const", asMETHODPR(CScriptDictionary,Get,(const dictKey_t&,asINT64&) const,bool), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const double&in)", asMETHODPR(CScriptDictionary,Set,(const dictKey_t&,const double&),void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, double&out) const", asMETHODPR(CScriptDictionary,Get,(const dictKey_t&,double&) const,bool), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "bool exists(const string &in) const", asMETHOD(CScriptDictionary,Exists), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool isEmpty() const", asMETHOD(CScriptDictionary, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "uint getSize() const", asMETHOD(CScriptDictionary, GetSize), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool delete(const string &in)", asMETHOD(CScriptDictionary,Delete), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "void deleteAll()", asMETHOD(CScriptDictionary,DeleteAll), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "array @getKeys() const", asMETHOD(CScriptDictionary,GetKeys), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "dictionaryValue &opIndex(const string &in)", asMETHODPR(CScriptDictionary, operator[], (const dictKey_t &), CScriptDictValue*), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "const dictionaryValue &opIndex(const string &in) const", asMETHODPR(CScriptDictionary, operator[], (const dictKey_t &) const, const CScriptDictValue*), asCALL_THISCALL); assert( r >= 0 ); + + // Register GC behaviours + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(CScriptDictionary,GetRefCount), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_SETGCFLAG, "void f()", asMETHOD(CScriptDictionary,SetGCFlag), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(CScriptDictionary,GetGCFlag), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptDictionary,EnumReferences), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptDictionary,ReleaseAllReferences), asCALL_THISCALL); assert( r >= 0 ); + +#if AS_USE_STLNAMES == 1 + // Same as isEmpty + r = engine->RegisterObjectMethod("dictionary", "bool empty() const", asMETHOD(CScriptDictionary, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); + // Same as getSize + r = engine->RegisterObjectMethod("dictionary", "uint size() const", asMETHOD(CScriptDictionary, GetSize), asCALL_THISCALL); assert( r >= 0 ); + // Same as delete + r = engine->RegisterObjectMethod("dictionary", "void erase(const string &in)", asMETHOD(CScriptDictionary,Delete), asCALL_THISCALL); assert( r >= 0 ); + // Same as deleteAll + r = engine->RegisterObjectMethod("dictionary", "void clear()", asMETHOD(CScriptDictionary,DeleteAll), asCALL_THISCALL); assert( r >= 0 ); +#endif + + // Cache some things the dictionary will need at runtime + SDictionaryCache::Setup(engine); +} + +void RegisterScriptDictionary_Generic(asIScriptEngine *engine) +{ + int r; + + // Register the cleanup callback for the object type cache + engine->SetEngineUserDataCleanupCallback(SDictionaryCache::Cleanup, DICTIONARY_CACHE); + +#if AS_CAN_USE_CPP11 + // With C++11 it is possible to use asGetTypeTraits to automatically determine the correct flags that represents the C++ class + r = engine->RegisterObjectType("dictionaryValue", sizeof(CScriptDictValue), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits()); assert( r >= 0 ); +#else + r = engine->RegisterObjectType("dictionaryValue", sizeof(CScriptDictValue), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CD); assert( r >= 0 ); +#endif + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(CScriptDictValue_Construct_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(CScriptDictValue_Destruct_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(CScriptDictValue_EnumReferences_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(CScriptDictValue_FreeValue_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(const dictionaryValue &in)", asFUNCTION(CScriptDictValue_opCopyAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opHndlAssign(const ?&in)", asFUNCTION(CScriptDictValue_opAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opHndlAssign(const dictionaryValue &in)", asFUNCTION(CScriptDictValue_opCopyAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(const ?&in)", asFUNCTION(CScriptDictValue_opAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(double)", asFUNCTION(CScriptDictValue_opAssign_double_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(int64)", asFUNCTION(CScriptDictValue_opAssign_int64_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "void opCast(?&out)", asFUNCTION(CScriptDictValue_opCast_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "void opConv(?&out)", asFUNCTION(CScriptDictValue_opCast_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "int64 opConv()", asFUNCTION(CScriptDictValue_opConvInt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "double opConv()", asFUNCTION(CScriptDictValue_opConvDouble_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectType("dictionary", sizeof(CScriptDictionary), asOBJ_REF | asOBJ_GC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_FACTORY, "dictionary@ f()", asFUNCTION(ScriptDictionaryFactory_Generic), asCALL_GENERIC); assert( r>= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_LIST_FACTORY, "dictionary @f(int &in) {repeat {string, ?}}", asFUNCTION(ScriptDictionaryListFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptDictionaryAddRef_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptDictionaryRelease_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "dictionary &opAssign(const dictionary &in)", asFUNCTION(ScriptDictionaryAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const ?&in)", asFUNCTION(ScriptDictionarySet_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, ?&out) const", asFUNCTION(ScriptDictionaryGet_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const int64&in)", asFUNCTION(ScriptDictionarySetInt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, int64&out) const", asFUNCTION(ScriptDictionaryGetInt_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const double&in)", asFUNCTION(ScriptDictionarySetFlt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, double&out) const", asFUNCTION(ScriptDictionaryGetFlt_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "bool exists(const string &in) const", asFUNCTION(ScriptDictionaryExists_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool isEmpty() const", asFUNCTION(ScriptDictionaryIsEmpty_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "uint getSize() const", asFUNCTION(ScriptDictionaryGetSize_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool delete(const string &in)", asFUNCTION(ScriptDictionaryDelete_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "void deleteAll()", asFUNCTION(ScriptDictionaryDeleteAll_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "array @getKeys() const", asFUNCTION(CScriptDictionaryGetKeys_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "dictionaryValue &opIndex(const string &in)", asFUNCTION(CScriptDictionary_opIndex_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "const dictionaryValue &opIndex(const string &in) const", asFUNCTION(CScriptDictionary_opIndex_const_Generic), asCALL_GENERIC); assert( r >= 0 ); + + // Register GC behaviours + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptDictionaryGetRefCount_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptDictionarySetGCFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptDictionaryGetGCFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptDictionaryEnumReferences_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptDictionaryReleaseAllReferences_Generic), asCALL_GENERIC); assert( r >= 0 ); + + // Cache some things the dictionary will need at runtime + SDictionaryCache::Setup(engine); +} + +//------------------------------------------------------------------ +// Iterator implementation + +CScriptDictionary::CIterator CScriptDictionary::begin() const +{ + return CIterator(*this, dict.begin()); +} + +CScriptDictionary::CIterator CScriptDictionary::end() const +{ + return CIterator(*this, dict.end()); +} + +CScriptDictionary::CIterator CScriptDictionary::find(const dictKey_t &key) const +{ + return CIterator(*this, dict.find(key)); +} + +CScriptDictionary::CIterator::CIterator( + const CScriptDictionary &dict, + dictMap_t::const_iterator it) + : m_it(it), m_dict(dict) +{} + +void CScriptDictionary::CIterator::operator++() +{ + ++m_it; +} + +void CScriptDictionary::CIterator::operator++(int) +{ + ++m_it; + + // Normally the post increment would return a copy of the object with the original state, + // but it is rarely used so we skip this extra copy to avoid unnecessary overhead +} + +CScriptDictionary::CIterator &CScriptDictionary::CIterator::operator*() +{ + return *this; +} + +bool CScriptDictionary::CIterator::operator==(const CIterator &other) const +{ + return m_it == other.m_it; +} + +bool CScriptDictionary::CIterator::operator!=(const CIterator &other) const +{ + return m_it != other.m_it; +} + +const dictKey_t &CScriptDictionary::CIterator::GetKey() const +{ + return m_it->first; +} + +int CScriptDictionary::CIterator::GetTypeId() const +{ + return m_it->second.m_typeId; +} + +bool CScriptDictionary::CIterator::GetValue(asINT64 &value) const +{ + return m_it->second.Get(m_dict.engine, &value, asTYPEID_INT64); +} + +bool CScriptDictionary::CIterator::GetValue(double &value) const +{ + return m_it->second.Get(m_dict.engine, &value, asTYPEID_DOUBLE); +} + +bool CScriptDictionary::CIterator::GetValue(void *value, int typeId) const +{ + return m_it->second.Get(m_dict.engine, value, typeId); +} + +const void *CScriptDictionary::CIterator::GetAddressOfValue() const +{ + return m_it->second.GetAddressOfValue(); +} + +END_AS_NAMESPACE + + diff --git a/DeerStudio/Build.lua b/DeerStudio/Build.lua index d465328..6c6faa4 100755 --- a/DeerStudio/Build.lua +++ b/DeerStudio/Build.lua @@ -28,7 +28,8 @@ project "DeerStudio" "ImGui", "angelScript" } - defines { "DEER_RENDER" } + defines { "DEER_RENDER", + "AS_ENABLE_METADATA" } targetdir ("../bin/" .. OutputDir .. "/%{prj.name}") objdir ("../bin/int/" .. OutputDir .. "/%{prj.name}") diff --git a/DeerStudio/imgui.ini b/DeerStudio/imgui.ini index 15b403c..e9ae88e 100644 --- a/DeerStudio/imgui.ini +++ b/DeerStudio/imgui.ini @@ -1,6 +1,6 @@ [Window][DockSpace Demo] Pos=0,0 -Size=1920,1011 +Size=1741,1159 Collapsed=0 [Window][Debug##Default] @@ -9,53 +9,53 @@ Size=400,400 Collapsed=0 [Window][Terrain Editor] -Pos=1587,24 -Size=333,745 +Pos=1315,24 +Size=426,893 Collapsed=0 DockId=0x00000006,1 [Window][Viewport] -Pos=294,24 -Size=1291,745 +Pos=361,24 +Size=952,893 Collapsed=0 DockId=0x00000005,1 [Window][ViewportPannel] -Pos=294,24 -Size=1291,745 +Pos=361,24 +Size=952,893 Collapsed=0 DockId=0x00000005,0 [Window][ShaderExplorer] -Pos=0,771 -Size=1920,240 +Pos=0,919 +Size=1741,240 Collapsed=0 DockId=0x00000004,1 [Window][TreePannel] Pos=0,24 -Size=292,745 +Size=359,893 Collapsed=0 DockId=0x00000001,0 [Window][MeshExplorer] -Pos=0,771 -Size=1920,240 +Pos=0,919 +Size=1741,240 Collapsed=0 DockId=0x00000004,0 [Window][PropertiesPannel] -Pos=1587,24 -Size=333,745 +Pos=1315,24 +Size=426,893 Collapsed=0 DockId=0x00000006,0 [Docking][Data] -DockSpace ID=0xA1672E74 Window=0x4647B76E Pos=0,24 Size=1920,987 Split=Y Selected=0x34A4C10F +DockSpace ID=0xA1672E74 Window=0x4647B76E Pos=0,24 Size=1741,1135 Split=Y Selected=0x34A4C10F DockNode ID=0x00000003 Parent=0xA1672E74 SizeRef=1280,454 Split=X - DockNode ID=0x00000001 Parent=0x00000003 SizeRef=292,696 Selected=0xE45B9F93 - DockNode ID=0x00000002 Parent=0x00000003 SizeRef=986,696 Split=X Selected=0x34A4C10F - DockNode ID=0x00000005 Parent=0x00000002 SizeRef=651,454 CentralNode=1 Selected=0x34A4C10F - DockNode ID=0x00000006 Parent=0x00000002 SizeRef=333,454 Selected=0xA35A27E3 + DockNode ID=0x00000001 Parent=0x00000003 SizeRef=359,696 Selected=0xE45B9F93 + DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1380,696 Split=X Selected=0x34A4C10F + DockNode ID=0x00000005 Parent=0x00000002 SizeRef=952,454 CentralNode=1 Selected=0x34A4C10F + DockNode ID=0x00000006 Parent=0x00000002 SizeRef=426,454 Selected=0x2A2C795E DockNode ID=0x00000004 Parent=0xA1672E74 SizeRef=1280,240 Selected=0xD962995A diff --git a/DeerStudio/src/DeerStudio/EditorEngine/EditorEngine.cpp b/DeerStudio/src/DeerStudio/EditorEngine/EditorEngine.cpp index 509dcff..2e0d034 100644 --- a/DeerStudio/src/DeerStudio/EditorEngine/EditorEngine.cpp +++ b/DeerStudio/src/DeerStudio/EditorEngine/EditorEngine.cpp @@ -11,6 +11,8 @@ #include "angelscript.h" #include "scriptbuilder.h" #include "scriptstdstring.h" +#include "scriptarray.h" +#include "scriptdictionary.h" void extract_angelScript(); @@ -34,6 +36,8 @@ namespace Deer { scriptEngine = asCreateScriptEngine(); RegisterStdString(scriptEngine); + RegisterScriptArray(scriptEngine, true); + RegisterScriptDictionary(scriptEngine); AS_RET_CHECK(scriptEngine->SetMessageCallback(asFUNCTION(Deer::EditorEngine::errorCallback), 0, asCALL_CDECL)); diff --git a/roe/Editor/mesh_explorer.as b/roe/Editor/MeshExplorer/MeshExplorer.as similarity index 100% rename from roe/Editor/mesh_explorer.as rename to roe/Editor/MeshExplorer/MeshExplorer.as diff --git a/roe/Editor/MeshExplorer/MeshPreviewRender.as b/roe/Editor/MeshExplorer/MeshPreviewRender.as new file mode 100644 index 0000000..4ff8ef8 --- /dev/null +++ b/roe/Editor/MeshExplorer/MeshPreviewRender.as @@ -0,0 +1,14 @@ +dictionary meshFrameBuffer; + +FrameBuffer getMeshFrameBuffer(string mesh) { + if (meshFrameBuffer.exists(mesh)) + return cast(meshFrameBuffer[mesh]); +} + +FrameBuffer generateMeshFrameBuffer(string mesh) { + FrameBuffer fb = Engine::createRGBA8FrameBuffer(mesh, 64, 64); + + + + return fb; +} \ No newline at end of file diff --git a/roe/Editor/as.predefined b/roe/Editor/as.predefined index b234fbe..fcb8346 100644 --- a/roe/Editor/as.predefined +++ b/roe/Editor/as.predefined @@ -506,3 +506,63 @@ namespace UI { int sliderInt(string&in, int value, int min, int max); float slider(string&in, float value, float min, float max); } + +class array { + T& opIndex(uint index); + const T& opIndex(uint index) const; + T[]& opAssign(const T[]&in); + void insertAt(uint index, const T&in value); + void insertAt(uint index, const T[]&inout arr); + void insertLast(const T&in value); + void removeAt(uint index); + void removeLast(); + void removeRange(uint start, uint count); + uint length() const; + void reserve(uint length); + void resize(uint length); + void sortAsc(); + void sortAsc(uint startAt, uint count); + void sortDesc(); + void sortDesc(uint startAt, uint count); + void reverse(); + int find(const T&in value) const; + int find(uint startAt, const T&in value) const; + int findByRef(const T&in value) const; + int findByRef(uint startAt, const T&in value) const; + bool opEquals(const T[]&in) const; + bool isEmpty() const; + //void sort(T[]::less&in, uint startAt = 0, uint count = uint ( - 1 )); + funcdef bool less(const T&in, const T&in); +} + +class dictionaryValue { + ~dictionaryValue(); + dictionaryValue(); + dictionaryValue& opAssign(const dictionaryValue&in); + dictionaryValue& opHndlAssign(const ?&in); + dictionaryValue& opHndlAssign(const dictionaryValue&in); + dictionaryValue& opAssign(const ?&in); + dictionaryValue& opAssign(double); + dictionaryValue& opAssign(int64); + void opCast(?&out); + void opConv(?&out); + int64 opConv(); + double opConv(); +} +class dictionary { + dictionary& opAssign(const dictionary&in); + void set(const string&in, const ?&in); + bool get(const string&in, ?&out) const; + void set(const string&in, const int64&in); + bool get(const string&in, int64&out) const; + void set(const string&in, const double&in); + bool get(const string&in, double&out) const; + bool exists(const string&in) const; + bool isEmpty() const; + uint getSize() const; + bool delete(const string&in); + void deleteAll(); + string[]@ getKeys() const; + dictionaryValue& opIndex(const string&in); + const dictionaryValue& opIndex(const string&in) const; +} \ No newline at end of file diff --git a/roe/tmp/voxel_texture_atlas.png b/roe/tmp/voxel_texture_atlas.png index ae08728..5cb7ad7 100644 Binary files a/roe/tmp/voxel_texture_atlas.png and b/roe/tmp/voxel_texture_atlas.png differ