diff --git a/include/NovelRT.Interop/Ecs/Audio/NrtEcsAudio.h b/include/NovelRT.Interop/Ecs/Audio/NrtEcsAudio.h index 9cbe747c1..5cad7fc0a 100644 --- a/include/NovelRT.Interop/Ecs/Audio/NrtEcsAudio.h +++ b/include/NovelRT.Interop/Ecs/Audio/NrtEcsAudio.h @@ -7,5 +7,6 @@ #include "NrtAudioEmitterComponent.h" #include "NrtAudioEmitterStateComponent.h" #include "NrtAudioSystem.h" +#include "NrtEcsAudioComponents.h" #endif // NOVELRT_INTEROP_ECS_AUDIO_H diff --git a/include/NovelRT.Interop/Ecs/Audio/NrtEcsAudioComponents.h b/include/NovelRT.Interop/Ecs/Audio/NrtEcsAudioComponents.h new file mode 100644 index 000000000..f096187d4 --- /dev/null +++ b/include/NovelRT.Interop/Ecs/Audio/NrtEcsAudioComponents.h @@ -0,0 +1,21 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_INTEROP_ECS_AUDIO_ECSAUDIOCOMPONENTS_H +#define NOVELRT_INTEROP_ECS_AUDIO_ECSAUDIOCOMPONENTS_H + +#include "../../NrtTypedefs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + NrtAtom Nrt_Components_GetAudioEmitterComponentId(); + NrtAtom Nrt_Components_GetAudioEmitterStateComponentId(); + +#ifdef __cplusplus +} +#endif + +#endif // NOVELRT_INTEROP_ECS_AUDIO_ECSAUDIOCOMPONENTS_H diff --git a/include/NovelRT.Interop/Ecs/Graphics/NrtDefaultRenderingSystem.h b/include/NovelRT.Interop/Ecs/Graphics/NrtDefaultRenderingSystem.h index b6b0bb5fa..2fc6b5732 100644 --- a/include/NovelRT.Interop/Ecs/Graphics/NrtDefaultRenderingSystem.h +++ b/include/NovelRT.Interop/Ecs/Graphics/NrtDefaultRenderingSystem.h @@ -1,8 +1,8 @@ // Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root // for more information. -#ifndef NOVELRT_INTEROP_ECS_GRAPHICS_NRTDEFAULTRENDERINGSYSTEM_H -#define NOVELRT_INTEROP_ECS_GRAPHICS_NRTDEFAULTRENDERINGSYSTEM_H +#ifndef NOVELRT_INTEROP_ECS_GRAPHICS_DEFAULTRENDERINGSYSTEM_H +#define NOVELRT_INTEROP_ECS_GRAPHICS_DEFAULTRENDERINGSYSTEM_H #include "../../NrtTypedefs.h" @@ -16,10 +16,40 @@ extern "C" NrtResult Nrt_DefaultRenderingSystem_ForceVertexTextureFutureResolution(NrtDefaultRenderingSystemHandle system); - // TODO: Implement GetOrLoadTexture, CreateSpriteEntity and CreateSpriteEntityOutsideOfSystem + NrtResult Nrt_DefaultRenderingSystem_GetOrLoadTexture(NrtDefaultRenderingSystemHandle system, + const char* textureName, + NrtFutureResultOfTextureInfoHandle* outputTextureFuture); + + NrtResult Nrt_DefaultRenderingSystem_GetExistingTextureById(NrtDefaultRenderingSystemHandle system, + NrtAtom id, + NrtTextureInfoHandle* outputTexture); + + NrtResult Nrt_DefaultRenderingSystem_GetExistingTextureByName(NrtDefaultRenderingSystemHandle system, + const char* name, + NrtTextureInfoHandle* outputTexture); + + // Even after calling a DeleteTexture method, TextureInfo_Destroy still + // needs to be called by the user once done with it! + + NrtResult Nrt_DefaultRenderingSystem_DeleteTextureByHandle(NrtDefaultRenderingSystemHandle system, + NrtTextureInfoHandle texture); + + NrtResult Nrt_DefaultRenderingSystem_DeleteTextureByName(NrtDefaultRenderingSystemHandle system, const char* name); + + NrtResult Nrt_DefaultRenderingSystem_DeleteTextureById(NrtDefaultRenderingSystemHandle system, NrtAtom id); + + NrtResult Nrt_DefaultRenderingSystem_CreateSpriteEntity(NrtDefaultRenderingSystemHandle system, + NrtTextureInfoHandle texture, + NrtCatalogueHandle catalogue, + NrtEntityId* outputEntityId); + + NrtResult Nrt_DefaultRenderingSystem_CreateSpriteEntityOutsideOfSystem(NrtDefaultRenderingSystemHandle system, + NrtTextureInfoHandle texture, + NrtSystemSchedulerHandle scheduler, + NrtEntityId* outputEntityId); #ifdef __cplusplus } #endif -#endif // NOVELRT_INTEROP_ECS_GRAPHICS_NRTDEFAULTRENDERINGSYSTEM_H +#endif // NOVELRT_INTEROP_ECS_GRAPHICS_DEFAULTRENDERINGSYSTEM_H diff --git a/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphics.h b/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphics.h index 3a2239ed1..60f0e115c 100644 --- a/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphics.h +++ b/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphics.h @@ -4,5 +4,7 @@ #define NOVELRT_INTEROP_ECS_GRAPHICS_NRTECSGRAPHICS_H #include "NrtDefaultRenderingSystem.h" +#include "NrtEcsGraphicsComponents.h" +#include "NrtTextureInfo.h" #endif // NOVELRT_INTEROP_ECS_GRAPHICS_NRTECSGRAPHICS_H diff --git a/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsComponents.h b/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsComponents.h new file mode 100644 index 000000000..9370193cf --- /dev/null +++ b/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsComponents.h @@ -0,0 +1,21 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_INTEROP_ECS_GRAPHICS_ECSGRAPHICSCOMPONENTS_H +#define NOVELRT_INTEROP_ECS_GRAPHICS_ECSGRAPHICSCOMPONENTS_H + +#include "../../NrtTypedefs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + NrtAtom Nrt_Components_GetRenderComponentTypeId(); + +#ifdef __cplusplus +} +#endif + + +#endif // NOVELRT_INTEROP_ECS_GRAPHICS_ECSGRAPHICSCOMPONENTS_H diff --git a/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsTypedefs.h b/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsTypedefs.h index 8ef1ffd87..51407ed02 100644 --- a/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsTypedefs.h +++ b/include/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsTypedefs.h @@ -10,6 +10,17 @@ extern "C" typedef struct NrtDefaultRenderingSystem* NrtDefaultRenderingSystemHandle; + // Component types + + typedef struct { + NrtAtom vertexDataId; + NrtAtom textureId; + NrtAtom pipelineId; + NrtAtom primitiveInfoId; + bool requiresCustomRendering; + bool markedForDeletion; + } NrtRenderComponent; + #ifdef __cplusplus } #endif diff --git a/include/NovelRT.Interop/Ecs/Graphics/NrtTextureInfo.h b/include/NovelRT.Interop/Ecs/Graphics/NrtTextureInfo.h new file mode 100644 index 000000000..c4799e622 --- /dev/null +++ b/include/NovelRT.Interop/Ecs/Graphics/NrtTextureInfo.h @@ -0,0 +1,30 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_INTEROP_ECS_GRAPHICS_TEXTUREINFO_H +#define NOVELRT_INTEROP_ECS_GRAPHICS_TEXTUREINFO_H + +#include "../../NrtTypedefs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + NrtResult Nrt_TextureInfo_Destroy(NrtTextureInfoHandle texture); + + char* Nrt_TextureInfo_GetTextureName(NrtTextureInfoHandle texture); + + uint32_t Nrt_TextureInfo_GetTextureWidth(NrtTextureInfoHandle texture); + + uint32_t Nrt_TextureInfo_GetTextureHeight(NrtTextureInfoHandle texture); + + NrtAtom Nrt_TextureInfo_GetEcsId(NrtTextureInfoHandle texture); + + NrtBool Nrt_TextureInfo_Equals(NrtTextureInfoHandle lhs, NrtTextureInfoHandle rhs); + +#ifdef __cplusplus +} +#endif + +#endif // NOVELRT_INTEROP_ECS_GRAPHICS_TEXTUREINFO_H diff --git a/include/NovelRT.Interop/Ecs/Input/NrtEcsInput.h b/include/NovelRT.Interop/Ecs/Input/NrtEcsInput.h new file mode 100644 index 000000000..86d439145 --- /dev/null +++ b/include/NovelRT.Interop/Ecs/Input/NrtEcsInput.h @@ -0,0 +1,10 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_INTEROP_ECS_INPUT_ECSINPUT_H +#define NOVELRT_INTEROP_ECS_INPUT_ECSINPUT_H + +#include "NrtEcsInputComponents.h" +#include "NrtEcsInputTypedefs.h" + +#endif // NOVELRT_INTEROP_ECS_INPUT_ECSINPUT_H diff --git a/include/NovelRT.Interop/Ecs/Input/NrtEcsInputComponents.h b/include/NovelRT.Interop/Ecs/Input/NrtEcsInputComponents.h new file mode 100644 index 000000000..21e309e20 --- /dev/null +++ b/include/NovelRT.Interop/Ecs/Input/NrtEcsInputComponents.h @@ -0,0 +1,20 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_INTEROP_ECS_INPUT_ECSINPUTCOMPONENTS_H +#define NOVELRT_INTEROP_ECS_INPUT_ECSINPUTCOMPONENTS_H + +#include "../../NrtTypedefs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + NrtAtom Nrt_Components_GetInputEventComponentTypeId(); + +#ifdef __cplusplus +} +#endif + +#endif // NOVELRT_INTEROP_ECS_INPUT_ECSINPUTCOMPONENTS_H diff --git a/include/NovelRT.Interop/Ecs/Input/NrtEcsInputTypedefs.h b/include/NovelRT.Interop/Ecs/Input/NrtEcsInputTypedefs.h new file mode 100644 index 000000000..c2ecd7346 --- /dev/null +++ b/include/NovelRT.Interop/Ecs/Input/NrtEcsInputTypedefs.h @@ -0,0 +1,34 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_INTEROP_ECS_INPUT_NRTECSINPUTTYPEDEFS_H +#define NOVELRT_INTEROP_ECS_INPUT_NRTECSINPUTTYPEDEFS_H + +#include "../../NrtTypedefs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + // Components + // Note that int32_t is used instead of NrtKeyState, as, in C, + // enums are *not* guaranteed to be exactly the size of an int. + // Even though it is in 99.99% of the cases due to system ABI, + // we better enforce the size given by the C++ NovelRT API. + // See KeyState definition: + // enum class KeyState : int32_t <--- + + typedef struct { + NrtAtom actionId; + // Uses the NrtKeyState enum. + int32_t state; + float mousePositionX; + float mousePositionY; + } NrtInputEventComponent; + +#ifdef __cplusplus +} +#endif + +#endif // NOVELRT_INTEROP_ECS_INPUT_NRTECSINPUTTYPEDEFS_H diff --git a/include/NovelRT.Interop/Ecs/NrtEcs.h b/include/NovelRT.Interop/Ecs/NrtEcs.h index 0b0e3d8e3..d4dfe1cc1 100644 --- a/include/NovelRT.Interop/Ecs/NrtEcs.h +++ b/include/NovelRT.Interop/Ecs/NrtEcs.h @@ -9,6 +9,7 @@ #include "NrtComponentCache.h" #include "NrtConfigurator.h" #include "NrtEntityCache.h" +#include "NrtEcsComponents.h" #include "NrtEntityIdVector.h" #include "NrtSparseSetMemoryContainer.h" #include "NrtSystemScheduler.h" diff --git a/include/NovelRT.Interop/Ecs/NrtEcsComponents.h b/include/NovelRT.Interop/Ecs/NrtEcsComponents.h new file mode 100644 index 000000000..2e69ef5e9 --- /dev/null +++ b/include/NovelRT.Interop/Ecs/NrtEcsComponents.h @@ -0,0 +1,23 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_INTEROP_ECS_ECSCOMPONENTS_H +#define NOVELRT_INTEROP_ECS_ECSCOMPONENTS_H + +#include "../NrtTypedefs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + NrtAtom Nrt_Components_GetTransformComponentTypeId(); + NrtAtom Nrt_Components_GetEntityGraphComponentTypeId(); + NrtAtom Nrt_Components_LinkedEntityListNodeComponentTypeId(); + +#ifdef __cplusplus +} +#endif + + +#endif // NOVELRT_INTEROP_ECS_ECSCOMPONENTS_H diff --git a/include/NovelRT.Interop/Ecs/NrtEcsTypedefs.h b/include/NovelRT.Interop/Ecs/NrtEcsTypedefs.h index 80d9395cd..d09e4e0a0 100644 --- a/include/NovelRT.Interop/Ecs/NrtEcsTypedefs.h +++ b/include/NovelRT.Interop/Ecs/NrtEcsTypedefs.h @@ -34,6 +34,34 @@ extern "C" typedef NrtAtom NrtEntityId; typedef NrtAtom NrtComponentTypeId; + // Default components, equivalents in C structs + // When a component is modified in DefaultComponentTypes.h, + // it must also be updated there. + + // Note that we do not use the NrtBool type, + // as it doesn't have the same as a standard C/C++ bool. + + typedef struct + { + NrtGeoVector3F positionAndLayer; + NrtGeoVector2F scale; + float rotationInRadians; + } NrtTransformComponent; + + typedef struct + { + bool isValid; + NrtEntityId parent; + NrtEntityId childrenStartNode; + } NrtEntityGraphComponent; + + typedef struct + { + bool isValid; + NrtEntityId parent; + NrtEntityId childrenStartNode; + } NrtLinkedEntityListNodeComponent; + #ifdef __cplusplus } #endif diff --git a/include/NovelRT.Interop/Graphics/NrtGraphicsTypedefs.h b/include/NovelRT.Interop/Graphics/NrtGraphicsTypedefs.h index 457709074..d4c39cf6d 100644 --- a/include/NovelRT.Interop/Graphics/NrtGraphicsTypedefs.h +++ b/include/NovelRT.Interop/Graphics/NrtGraphicsTypedefs.h @@ -18,6 +18,8 @@ extern "C" typedef struct NrtGraphicsProvider* NrtGraphicsProviderHandle; + typedef struct NrtTextureInfo* NrtTextureInfoHandle; + #ifdef __cplusplus } #endif diff --git a/include/NovelRT.Interop/NrtTypedefs.h b/include/NovelRT.Interop/NrtTypedefs.h index ce4ed8062..813ee0a4b 100644 --- a/include/NovelRT.Interop/NrtTypedefs.h +++ b/include/NovelRT.Interop/NrtTypedefs.h @@ -71,6 +71,7 @@ extern "C" #include "Audio/NrtAudioTypedefs.h" #include "Ecs/Audio/NrtEcsAudioTypedefs.h" #include "Ecs/Graphics/NrtEcsGraphicsTypedefs.h" +#include "Ecs/Input/NrtEcsInputTypedefs.h" #include "Ecs/NrtEcsTypedefs.h" #include "Graphics/NrtGraphicsTypedefs.h" #include "Input/NrtInputTypedefs.h" @@ -78,6 +79,7 @@ extern "C" #include "ResourceManagement/NrtResourceManagementTypedefs.h" #include "SceneGraph/NrtSceneGraphTypedefs.h" #include "Windowing/NrtWindowingTypedefs.h" +#include "Threading/NrtThreadingTypedefs.h" // clang-format on diff --git a/include/NovelRT.Interop/Threading/NrtFutureResult.h b/include/NovelRT.Interop/Threading/NrtFutureResult.h new file mode 100644 index 000000000..17a32ef2c --- /dev/null +++ b/include/NovelRT.Interop/Threading/NrtFutureResult.h @@ -0,0 +1,24 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_INTEROP_THREADING_FUTURERESULT_H +#define NOVELRT_INTEROP_THREADING_FUTURERESULT_H + +#include "../NrtTypedefs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + // FutureResult + NrtResult Nrt_FutureResultOfTextureInfo_Destroy(NrtFutureResultOfTextureInfoHandle handle); + + NrtBool Nrt_FutureResultOfTextureInfo_TryGetValue(NrtFutureResultOfTextureInfoHandle handle, + NrtTextureInfoHandle* outValue); + +#ifdef __cplusplus +} +#endif + +#endif // NOVELRT_INTEROP_THREADING_FUTURERESULT_H diff --git a/include/NovelRT.Interop/Threading/NrtThreadingTypedefs.h b/include/NovelRT.Interop/Threading/NrtThreadingTypedefs.h new file mode 100644 index 000000000..d8e769824 --- /dev/null +++ b/include/NovelRT.Interop/Threading/NrtThreadingTypedefs.h @@ -0,0 +1,18 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#ifndef NOVELRT_INTEROP_THREADING_THREADINGTYPEDEFS_H +#define NOVELRT_INTEROP_THREADING_THREADINGTYPEDEFS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct NrtFutureResultOfTextureInfo* NrtFutureResultOfTextureInfoHandle; + +#ifdef __cplusplus +} +#endif + +#endif // NOVELRT_INTEROP_THREADING_THREADINGTYPEDEFS_H diff --git a/src/NovelRT.Interop/CMakeLists.txt b/src/NovelRT.Interop/CMakeLists.txt index ad1625d0a..bfc319355 100644 --- a/src/NovelRT.Interop/CMakeLists.txt +++ b/src/NovelRT.Interop/CMakeLists.txt @@ -8,6 +8,7 @@ set(INTEROP_SOURCES Ecs/NrtConfigurator.cpp Ecs/NrtComponentBufferMemoryContainer.cpp Ecs/NrtComponentCache.cpp + Ecs/NrtEcsComponents.cpp Ecs/NrtEntityCache.cpp Ecs/NrtEntityIdVector.cpp Ecs/NrtSparseSetMemoryContainer.cpp @@ -17,8 +18,13 @@ set(INTEROP_SOURCES Ecs/Audio/NrtAudioSystem.cpp Ecs/Audio/NrtAudioEmitterComponent.cpp Ecs/Audio/NrtAudioEmitterStateComponent.cpp + Ecs/Audio/NrtEcsAudioComponents.cpp Ecs/Graphics/NrtDefaultRenderingSystem.cpp + Ecs/Graphics/NrtTextureInfo.cpp + Ecs/Graphics/NrtEcsGraphicsComponents.cpp + + Ecs/Input/NrtEcsInputComponents.cpp Graphics/NrtRGBAColour.cpp Graphics/NrtGraphicsProvider.cpp @@ -43,7 +49,7 @@ set(INTEROP_SOURCES ResourceManagement/NrtTextureMetadata.cpp ResourceManagement/NrtResourceLoader.cpp ResourceManagement/NrtUint8Vector.cpp - ResourceManagement/NrtInt16Vector.cpp + ResourceManagement/NrtInt16Vector.cpp ResourceManagement/NrtUuidFilePathMap.cpp PluginManagement/NrtDefaultPluginSelector.cpp @@ -61,14 +67,15 @@ set(INTEROP_SOURCES SceneGraph/NrtSceneNodeBreadthFirstIterator.cpp SceneGraph/NrtSceneNodeDepthFirstIterator.cpp + Threading/NrtFutureResult.cpp + Timing/NrtStepTimer.cpp Timing/NrtTimestamp.cpp Utilities/NrtMisc.cpp Utilities/NrtEvent.cpp - Windowing/NrtIWindowingDevice.cpp -) + Windowing/NrtIWindowingDevice.cpp) add_library(Interop SHARED ${INTEROP_SOURCES}) add_dependencies(Interop Engine) diff --git a/src/NovelRT.Interop/Ecs/Audio/NrtEcsAudioComponents.cpp b/src/NovelRT.Interop/Ecs/Audio/NrtEcsAudioComponents.cpp new file mode 100644 index 000000000..06e89a9a2 --- /dev/null +++ b/src/NovelRT.Interop/Ecs/Audio/NrtEcsAudioComponents.cpp @@ -0,0 +1,18 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#include +#include + +using namespace NovelRT::Ecs; +using namespace NovelRT::Ecs::Audio; + +NrtAtom Nrt_Components_GetAudioEmitterComponentId() +{ + return GetComponentTypeId(); +} + +NrtAtom Nrt_Components_GetAudioEmitterStateComponentId() +{ + return GetComponentTypeId(); +} \ No newline at end of file diff --git a/src/NovelRT.Interop/Ecs/Graphics/NrtDefaultRenderingSystem.cpp b/src/NovelRT.Interop/Ecs/Graphics/NrtDefaultRenderingSystem.cpp index ae1e7c7b0..91d428d3c 100644 --- a/src/NovelRT.Interop/Ecs/Graphics/NrtDefaultRenderingSystem.cpp +++ b/src/NovelRT.Interop/Ecs/Graphics/NrtDefaultRenderingSystem.cpp @@ -1,13 +1,15 @@ // Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root // for more information. +#include "../../LifetimeExtender.h" #include #include #include -#include using namespace NovelRT::Ecs; using namespace NovelRT::Ecs::Graphics; +using namespace NovelRT::Threading; +using namespace NovelRT::Interop; NrtResult Nrt_DefaultRenderingSystem_FindInScheduler(NrtSystemSchedulerHandle scheduler, NrtDefaultRenderingSystemHandle* outputResult) @@ -50,3 +52,253 @@ NrtResult Nrt_DefaultRenderingSystem_ForceVertexTextureFutureResolution(NrtDefau reinterpret_cast(system)->ForceVertexTextureFutureResolution(); return NRT_SUCCESS; } +NrtResult Nrt_DefaultRenderingSystem_GetOrLoadTexture(NrtDefaultRenderingSystemHandle system, + const char* textureName, + NrtFutureResultOfTextureInfoHandle* outputTextureFuture) +{ + if (system == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + if (textureName == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + + auto* rendering = reinterpret_cast(system); + FutureResult&& future = rendering->GetOrLoadTexture(std::string(textureName)); + // Let's move the FutureResult to the C land. + *outputTextureFuture = + reinterpret_cast(new FutureResult{std::move(future)}); + + return NRT_SUCCESS; +} + +NrtResult Nrt_DefaultRenderingSystem_GetExistingTextureById(NrtDefaultRenderingSystemHandle system, + NrtAtom id, + NrtTextureInfoHandle* outputTexture) +{ + if (system == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + if (outputTexture == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + + auto* rendering = reinterpret_cast(system); + ConcurrentSharedPtr texture(nullptr); + try + { + texture = rendering->GetExistingTexture(id); + } + catch (const std::out_of_range&) + { + return NRT_FAILURE_KEY_NOT_FOUND; + } + + *outputTexture = reinterpret_cast(texture.get()); + ConcurrentLifetime::KeepAlive(std::move(texture)); + + return NRT_SUCCESS; +} + +NrtResult Nrt_DefaultRenderingSystem_GetExistingTextureByName(NrtDefaultRenderingSystemHandle system, + const char* name, + NrtTextureInfoHandle* outputTexture) +{ + if (system == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + if (name == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + if (outputTexture == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + + auto* rendering = reinterpret_cast(system); + ConcurrentSharedPtr texture(nullptr); + try + { + texture = rendering->GetExistingTexture(std::string(name)); + } + catch (const NovelRT::Exceptions::KeyNotFoundException&) + { + return NRT_FAILURE_KEY_NOT_FOUND; + } + + *outputTexture = reinterpret_cast(texture.get()); + ConcurrentLifetime::KeepAlive(std::move(texture)); + + return NRT_SUCCESS; +} +NrtResult Nrt_DefaultRenderingSystem_DeleteTextureByHandle(NrtDefaultRenderingSystemHandle system, + NrtTextureInfoHandle texture) +{ + if (system == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + if (texture == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + + auto* cppTexture = reinterpret_cast(texture); + ConcurrentSharedPtr sharedTexture = ConcurrentLifetime::Find(cppTexture); + if (sharedTexture == nullptr) + { + Nrt_setErrMsgIsAlreadyDeletedOrRemovedInternal(); + return NRT_FAILURE_ALREADY_DELETED_OR_REMOVED; + } + + auto* rendering = reinterpret_cast(system); + rendering->DeleteTexture(sharedTexture); + + return NRT_SUCCESS; +} + +NrtResult Nrt_DefaultRenderingSystem_DeleteTextureByName(NrtDefaultRenderingSystemHandle system, const char* name) +{ + if (system == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + if (name == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + + auto* rendering = reinterpret_cast(system); + try + { + rendering->DeleteTexture(std::string(name)); + } + catch (const NovelRT::Exceptions::KeyNotFoundException&) + { + return NRT_FAILURE_KEY_NOT_FOUND; + } + + return NRT_SUCCESS; +} + +NrtResult Nrt_DefaultRenderingSystem_DeleteTextureById(NrtDefaultRenderingSystemHandle system, NrtAtom id) +{ + if (system == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + + auto* rendering = reinterpret_cast(system); + try + { + rendering->DeleteTexture(id); + } + catch (const NovelRT::Exceptions::KeyNotFoundException&) + { + return NRT_FAILURE_KEY_NOT_FOUND; + } + + return NRT_SUCCESS; +} +NrtResult Nrt_DefaultRenderingSystem_CreateSpriteEntity(NrtDefaultRenderingSystemHandle system, + NrtTextureInfoHandle texture, + NrtCatalogueHandle catalogue, + NrtEntityId* outputEntityId) +{ + if (system == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + if (texture == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + if (catalogue == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + if (outputEntityId == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + + auto* rendering = reinterpret_cast(system); + auto* cppTexture = reinterpret_cast(texture); + auto* cppCatalogue = reinterpret_cast(catalogue); + + ConcurrentSharedPtr sharedTexture = ConcurrentLifetime::Find(cppTexture); + if (sharedTexture == nullptr) + { + Nrt_setErrMsgIsAlreadyDeletedOrRemovedInternal(); + return NRT_FAILURE_ALREADY_DELETED_OR_REMOVED; + } + + NrtAtom id = rendering->CreateSpriteEntity(sharedTexture, *cppCatalogue); + *outputEntityId = id; + + return NRT_SUCCESS; +} +NrtResult Nrt_DefaultRenderingSystem_CreateSpriteEntityOutsideOfSystem(NrtDefaultRenderingSystemHandle system, + NrtTextureInfoHandle texture, + NrtSystemSchedulerHandle scheduler, + NrtEntityId* outputEntityId) +{ + if (system == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + if (texture == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + if (scheduler == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + if (outputEntityId == nullptr) + { + Nrt_setErrMsgIsNullArgumentProvidedInternal(); + return NRT_FAILURE_NULL_ARGUMENT_PROVIDED; + } + + auto* rendering = reinterpret_cast(system); + auto* cppTexture = reinterpret_cast(texture); + auto* cppScheduler = reinterpret_cast(scheduler); + + ConcurrentSharedPtr sharedTexture = ConcurrentLifetime::Find(cppTexture); + if (sharedTexture == nullptr) + { + Nrt_setErrMsgIsAlreadyDeletedOrRemovedInternal(); + return NRT_FAILURE_ALREADY_DELETED_OR_REMOVED; + } + + NrtAtom id = rendering->CreateSpriteEntityOutsideOfSystem(sharedTexture, *cppScheduler); + *outputEntityId = id; + + return NRT_SUCCESS; +} diff --git a/src/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsComponents.cpp b/src/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsComponents.cpp new file mode 100644 index 000000000..97037854a --- /dev/null +++ b/src/NovelRT.Interop/Ecs/Graphics/NrtEcsGraphicsComponents.cpp @@ -0,0 +1,13 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#include +#include + +using namespace NovelRT::Ecs; +using namespace NovelRT::Ecs::Graphics; + +NrtAtom Nrt_Components_GetRenderComponentTypeId() +{ + return GetComponentTypeId(); +} diff --git a/src/NovelRT.Interop/Ecs/Graphics/NrtTextureInfo.cpp b/src/NovelRT.Interop/Ecs/Graphics/NrtTextureInfo.cpp new file mode 100644 index 000000000..82edca52c --- /dev/null +++ b/src/NovelRT.Interop/Ecs/Graphics/NrtTextureInfo.cpp @@ -0,0 +1,55 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#include "../../LifetimeExtender.h" +#include +#include +#include + +using namespace NovelRT::Ecs::Graphics; +using namespace NovelRT::Interop; + +// TextureInfo is a "shared" object. Its lifetime is managed by ConcurrentLifetime (LifetimeExtender.h), +// which can provide a ConcurrentSharedPtr for the TextureInfo. + +NrtResult Nrt_TextureInfo_Destroy(NrtTextureInfoHandle texture) +{ + if (texture == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + + if (!ConcurrentLifetime::Release(reinterpret_cast(texture))) + { + Nrt_setErrMsgIsAlreadyDeletedOrRemovedInternal(); + return NRT_FAILURE_ALREADY_DELETED_OR_REMOVED; + } + + return NRT_SUCCESS; +} + +char* Nrt_TextureInfo_GetTextureName(NrtTextureInfoHandle texture) +{ + return reinterpret_cast(texture)->textureName.data(); +} + +uint32_t Nrt_TextureInfo_GetTextureWidth(NrtTextureInfoHandle texture) +{ + return reinterpret_cast(texture)->width; +} + +uint32_t Nrt_TextureInfo_GetTextureHeight(NrtTextureInfoHandle texture) +{ + return reinterpret_cast(texture)->height; +} + +NrtAtom Nrt_TextureInfo_GetEcsId(NrtTextureInfoHandle texture) +{ + return reinterpret_cast(texture)->ecsId; +} + +NrtBool Nrt_TextureInfo_Equals(NrtTextureInfoHandle lhs, NrtTextureInfoHandle rhs) +{ + return *reinterpret_cast(lhs) == *reinterpret_cast(rhs); +} diff --git a/src/NovelRT.Interop/Ecs/Input/NrtEcsInputComponents.cpp b/src/NovelRT.Interop/Ecs/Input/NrtEcsInputComponents.cpp new file mode 100644 index 000000000..dc3590175 --- /dev/null +++ b/src/NovelRT.Interop/Ecs/Input/NrtEcsInputComponents.cpp @@ -0,0 +1,13 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#include +#include + +using namespace NovelRT::Ecs; +using namespace NovelRT::Ecs::Input; + +NrtAtom Nrt_Components_GetInputEventComponentTypeId() +{ + return GetComponentTypeId(); +} diff --git a/src/NovelRT.Interop/Ecs/NrtEcsComponents.cpp b/src/NovelRT.Interop/Ecs/NrtEcsComponents.cpp new file mode 100644 index 000000000..8818dfebd --- /dev/null +++ b/src/NovelRT.Interop/Ecs/NrtEcsComponents.cpp @@ -0,0 +1,20 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#include +#include + +using namespace NovelRT::Ecs; + +NrtAtom Nrt_Components_GetTransformComponentTypeId() +{ + return GetComponentTypeId(); +} +NrtAtom Nrt_Components_GetEntityGraphComponentTypeId() +{ + return GetComponentTypeId(); +} +NrtAtom Nrt_Components_LinkedEntityListNodeComponentTypeId() +{ + return GetComponentTypeId(); +} diff --git a/src/NovelRT.Interop/LifetimeExtender.h b/src/NovelRT.Interop/LifetimeExtender.h index ce85c74cc..f2bb9a406 100644 --- a/src/NovelRT.Interop/LifetimeExtender.h +++ b/src/NovelRT.Interop/LifetimeExtender.h @@ -3,55 +3,69 @@ #ifndef NOVELRT_INTEROP_LIFETIMEEXTENDER_H #define NOVELRT_INTEROP_LIFETIMEEXTENDER_H #include +#include #include -/* - * Extends the lifetime of objects contained in a shared_ptr. - * This lets the API consumer take ownership of an object without double indirection. - */ -namespace NovelRT::Interop::Lifetime + +// Unfortunately need to include Threading.h for ConcurrentLifetime, as +// the other solution requires include order madness. +// Another solution could be to create ConcurrentLifetimeExtender.h, +// but that's maybe too much, who knows? +#include + +namespace NovelRT::Interop { - template[[nodiscard]] std::vector>& AliveObjects() noexcept + /* + * Extends the lifetime of objects contained in a shared_ptr-like structure. + * By default, this stores instances of shared_ptr, but can be configured to some + * other pointer type using the template argument P. + * This lets the API consumer take ownership of an object without double indirection. + * + * This class uses an unordered_map internally, which map pointers to their shared_ptr. + */ + template typename P = std::shared_ptr> class PtrLifetime { - static std::vector> aliveObjects{}; + public: + PtrLifetime() = delete; - return aliveObjects; - } + template [[nodiscard]] static std::unordered_map>& AliveObjects() noexcept + { + static std::unordered_map> aliveObjects{}; - template void KeepAlive(std::shared_ptr&& object) noexcept - { - AliveObjects().emplace_back(std::move(object)); - } + return aliveObjects; + } - template void KeepAlive(const std::shared_ptr& object) noexcept - { - AliveObjects().emplace_back(object); - } + // KeepAlive does nothing if the pointer already exists. + template static void KeepAlive(P&& object) noexcept + { + AliveObjects().insert({object.get(), std::move(object)}); + } - template[[nodiscard]] std::shared_ptr Find(T* object) noexcept - { - for (auto& aliveObject : AliveObjects()) + template static void KeepAlive(P& object) noexcept { - if (aliveObject.get() == object) - { - return aliveObject; - } + AliveObjects().insert({object.get(), object}); } - return nullptr; - } - template bool Release(T* object) noexcept - { - auto& aliveObjects = AliveObjects(); - for (auto it = aliveObjects.begin(); it != aliveObjects.end(); ++it) + template [[nodiscard]] static P Find(T* object) noexcept { - if ((*it).get() == object) + auto& alive = AliveObjects(); + if (auto finding = alive.find(object); finding != alive.end()) + { + return finding->second; + } + else { - aliveObjects.erase(it); - return true; + return nullptr; } } - return false; - } + + template static bool Release(T* object) noexcept + { + return AliveObjects().erase(object) == 1; + } + }; + + using Lifetime = PtrLifetime<>; + using ConcurrentLifetime = PtrLifetime; } #endif // NOVELRT_INTEROP_LIFETIMEEXTENDER_H diff --git a/src/NovelRT.Interop/Threading/NrtFutureResult.cpp b/src/NovelRT.Interop/Threading/NrtFutureResult.cpp new file mode 100644 index 000000000..847c587fa --- /dev/null +++ b/src/NovelRT.Interop/Threading/NrtFutureResult.cpp @@ -0,0 +1,78 @@ +// Copyright © Matt Jones and Contributors. Licensed under the MIT Licence (MIT). See LICENCE.md in the repository root +// for more information. + +#include "../LifetimeExtender.h" +#include "NovelRT.Interop/NrtErrorHandling.h" +#include +#include +#include + +using namespace NovelRT::Threading; + +/* + * FutureResults are implemented in a similar fashion to Events, but in a much simpler way. + * An NrtFutureResultOfXHandle is simply a pointer to a C++ FutureResult, copied to the heap. + * Until the NrtFutureResult is destroyed, it holds a reference to the ConcurrentSharedPtr, + * keeping it alive. + * Once the value is requested, a "global" reference to X is added using the Lifetime system + * (see LifetimeExtender.h). It is the user's responsibility to remove this reference by calling + * the Destroy method on the instance of X, which usually calls Lifetime::Release. + * + * Each NrtFutureResultOfX requires two functions (NrtFutureResultOfXHandle = FRH for conciseness): + * - NrtResult Destroy(FRH future) + * Destroys the future result, removing one reference count. + * - NrtBool TryGetValue(FRH future, XHandle* outValue) + * If the value exists: + * If outValue is not null: + * Write the value handle to outValue + * Add a ref count using ConcurrentLifetime (see LifetimeExtender.h) + * Return true. + * If it doesn't exist: Return false. + * + * You can use the GenericFutureResult methods to implement those functions. + * */ + +template NrtResult GenericFutureResultDestroy(void* handle) +{ + if (handle == nullptr) + { + Nrt_setErrMsgIsNullInstanceProvidedInternal(); + return NRT_FAILURE_NULL_INSTANCE_PROVIDED; + } + + delete reinterpret_cast*>(handle); + return NRT_SUCCESS; +} + +template NrtBool GenericFutureResultTryGetValue(void* handle, XHandle* outValue) +{ + auto future = reinterpret_cast*>(handle); + + if (future->IsValueCreated()) + { + if (outValue != nullptr) + { + ConcurrentSharedPtr sharedPtr = future->GetBackingConcurrentSharedPtr(); + + *outValue = reinterpret_cast(sharedPtr.get()); + NovelRT::Interop::ConcurrentLifetime::KeepAlive(std::move(sharedPtr)); + } + return true; + } + else + { + return false; + } +} + +using TextureInfo = NovelRT::Ecs::Graphics::TextureInfo; + +NrtResult Nrt_FutureResultOfTextureInfo_Destroy(NrtFutureResultOfTextureInfoHandle handle) +{ + return GenericFutureResultDestroy(handle); +} +NrtBool Nrt_FutureResultOfTextureInfo_TryGetValue(NrtFutureResultOfTextureInfoHandle handle, + NrtTextureInfoHandle* outValue) +{ + return GenericFutureResultTryGetValue(handle, outValue); +}