Cleaned
This commit is contained in:
		| @@ -1,47 +0,0 @@ | ||||
| name: build-linux-glfw-x64 | ||||
| on: | ||||
|   # ON tag | ||||
|   push: | ||||
|     tags: | ||||
|       - 'v*' | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|  | ||||
|       - name: Install Dependencies | ||||
|         run: | | ||||
|           mkdir release | ||||
|           sudo apt-get update | ||||
|           sudo apt-get install -y \ | ||||
|             build-essential \ | ||||
|             cmake \ | ||||
|             xorg-dev \ | ||||
|             libglu1-mesa-dev \ | ||||
|             libglfw3-dev \ | ||||
|             libx11-dev \ | ||||
|             libxkbcommon-dev \ | ||||
|             python3-pil | ||||
|  | ||||
|  | ||||
|       - name: Build Linux GLFW x64 | ||||
|         run: | | ||||
|           if [ -d "build" ]; then | ||||
|             rm -rf build | ||||
|           fi | ||||
|           mkdir build | ||||
|           mkdir release/linux-glfw-x64 | ||||
|           cd build | ||||
|           cmake .. | ||||
|           make | ||||
|           cd .. | ||||
|           cp build/src/Dawn release/linux-glfw-x64/Dawn | ||||
|           cp build/dawn.tar release/linux-glfw-x64/dawn.tar | ||||
|  | ||||
|       # - name: Release   | ||||
|       #   uses: akkuman/gitea-release-action@v1 | ||||
|       #   with: | ||||
|       #     files: |- | ||||
|       #       release/ | ||||
							
								
								
									
										0
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -7,37 +7,4 @@ cmake_minimum_required(VERSION 3.13) | ||||
| set(CMAKE_C_STANDARD 99) | ||||
| set(CMAKE_C_STANDARD_REQUIRED ON) | ||||
| set(CMAKE_CXX_STANDARD 20) | ||||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||
|  | ||||
| # Variable Caches | ||||
| set(DAWN_CACHE_TARGET "dawn-target") | ||||
| set(DAWN_TARGET_NAME "Dawn") | ||||
|  | ||||
| # Set Common Build Variables | ||||
| set(DAWN_ROOT_DIR "${CMAKE_SOURCE_DIR}") | ||||
| set(DAWN_BUILD_DIR "${CMAKE_BINARY_DIR}") | ||||
| set(DAWN_SOURCES_DIR "${DAWN_ROOT_DIR}/src") | ||||
| set(DAWN_TOOLS_DIR "${DAWN_ROOT_DIR}/tools") | ||||
| set(DAWN_ASSETS_SOURCE_DIR "${DAWN_ROOT_DIR}/assets") | ||||
| set(DAWN_ASSETS_BUILD_DIR "${DAWN_BUILD_DIR}/assets") | ||||
| set(DAWN_GENERATED_DIR "${DAWN_BUILD_DIR}/generated") | ||||
| set(DAWN_TEMP_DIR "${DAWN_BUILD_DIR}/temp") | ||||
|  | ||||
| # Options | ||||
| option(DAWN_ENABLE_PHYSICS "Enable Physics" OFF) | ||||
| option(DAWN_DEBUG_SHADERS "Enable Debug Shaders" ON) | ||||
|  | ||||
| # Initialize Project First. | ||||
| project(Dawn | ||||
|   VERSION 1.0.0 | ||||
|   LANGUAGES C CXX | ||||
| ) | ||||
|  | ||||
| # Add tools | ||||
| add_subdirectory(tools) | ||||
|  | ||||
| # Add Libraries | ||||
| add_subdirectory(lib) | ||||
|  | ||||
| # Add Project Files | ||||
| add_subdirectory(src) | ||||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||
| @@ -1,8 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "Shader.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
| @@ -1,259 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "display/shader/ShaderStage.hpp" | ||||
| #include "display/shader/IShader.hpp" | ||||
| #include "assert/assert.hpp" | ||||
| #include "assert/assertgl.hpp" | ||||
| #include "display/Color.hpp" | ||||
| #include "display/Texture.hpp" | ||||
|  | ||||
| #include "ShaderParameter.hpp" | ||||
| #include "ShaderStructure.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   typedef GLuint shadertexturebinding_t; | ||||
|  | ||||
|   enum class ShaderOpenGLVariant { | ||||
|     GLSL_330_CORE | ||||
|   }; | ||||
|  | ||||
|   template<typename T> | ||||
|   class Shader : public IShader<T> { | ||||
|     private: | ||||
|       std::vector<std::shared_ptr<ShaderStage>> stages; | ||||
|       std::vector<struct ShaderParameter> parameters; | ||||
|       std::vector<struct IShaderStructure> structures; | ||||
|       enum ShaderOpenGLVariant variant; | ||||
|  | ||||
|       GLuint shaderProgram = -1; | ||||
|  | ||||
|     protected: | ||||
|       /** | ||||
|        * Overridable function to get the stages for the shader. | ||||
|        *  | ||||
|        * @param variant The variant of the shader to use. | ||||
|        * @param rel The relative data to use. | ||||
|        * @param stages The stages to add to. | ||||
|        * @param parameters The parameters to add to. | ||||
|        * @param structures The structures to add to. | ||||
|        */ | ||||
|       virtual void getStages( | ||||
|         const enum ShaderOpenGLVariant variant, | ||||
|         const T *rel, | ||||
|         std::vector<std::shared_ptr<ShaderStage>> &stages, | ||||
|         std::vector<struct ShaderParameter> ¶meters, | ||||
|         std::vector<struct IShaderStructure> &structures | ||||
|       ) = 0; | ||||
|  | ||||
|     public: | ||||
|       /** | ||||
|        * Initializes the shader, this needs to be called before the shader can | ||||
|        * be used. | ||||
|        */ | ||||
|       void init() override { | ||||
|         // Determine which kind of OpenGL shader to use. | ||||
|         variant = ShaderOpenGLVariant::GLSL_330_CORE; | ||||
|  | ||||
|         // Now get the stages | ||||
|         T dummy; | ||||
|         this->getStages( | ||||
|           variant, | ||||
|           &dummy, | ||||
|           stages, | ||||
|           parameters, | ||||
|           structures | ||||
|         ); | ||||
|  | ||||
|         // Create the shader program | ||||
|         shaderProgram = glCreateProgram(); | ||||
|         assertNoGLError(); | ||||
|  | ||||
|         // Attach all the stages | ||||
|         for(auto stage : stages) { | ||||
|           glAttachShader(shaderProgram, stage->id); | ||||
|           assertNoGLError(); | ||||
|         } | ||||
|  | ||||
|         // Link and verify the program | ||||
|         glLinkProgram(shaderProgram); | ||||
|         assertNoGLError(); | ||||
|  | ||||
|         GLint status; | ||||
|         glGetProgramiv(shaderProgram, GL_LINK_STATUS, &status); | ||||
|         assertNoGLError(); | ||||
|         assertTrue(status == GL_TRUE, "Failed to link shader program."); | ||||
|  | ||||
|         std::vector<std::string> uniformNames; | ||||
|         GLint numUniforms = 0; | ||||
|  | ||||
|         // Get the number of active uniforms | ||||
|         glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &numUniforms); | ||||
|         assertNoGLError(); | ||||
|  | ||||
|         // Iterate through each uniform | ||||
|         // for (GLint i = 0; i < numUniforms; ++i) { | ||||
|         //   char name[256]; | ||||
|         //   GLsizei length; | ||||
|         //   GLint size; | ||||
|         //   GLenum type; | ||||
|  | ||||
|         //   // Get the uniform name | ||||
|         //   glGetActiveUniform(shaderProgram, i, sizeof(name), &length, &size, &type, name); | ||||
|         //   assertNoGLError(); | ||||
|         //   std::cout << "Uniform: " << i << ":" << name << std::endl; | ||||
|         //   // uniformNames.push_back(std::string(name)); | ||||
|         // } | ||||
|  | ||||
|         // Map parameters correctly. | ||||
|         std::for_each( | ||||
|           parameters.begin(), | ||||
|           parameters.end(), | ||||
|           [&](struct ShaderParameter ¶m) { | ||||
|             // Correct offset | ||||
|             param.offset = param.offset - (size_t)(&dummy); | ||||
|             param.location = glGetUniformLocation( | ||||
|               shaderProgram, | ||||
|               param.name.c_str() | ||||
|             ); | ||||
|             assertNoGLError(); | ||||
|             assertTrue( | ||||
|               param.location != -1, | ||||
|               "Failed to get location for parameter %s.", | ||||
|               param.name.c_str() | ||||
|             ); | ||||
|           } | ||||
|         ); | ||||
|  | ||||
|         // Map structures | ||||
|         std::for_each( | ||||
|           structures.begin(), | ||||
|           structures.end(), | ||||
|           [&](struct IShaderStructure &structure) { | ||||
|             structure.offset = structure.offset - (size_t)(&dummy); | ||||
|             structure.location = glGetUniformBlockIndex( | ||||
|               shaderProgram, | ||||
|               structure.structureName.c_str() | ||||
|             ); | ||||
|             assertNoGLError(); | ||||
|             assertTrue( | ||||
|               structure.location != -1, | ||||
|               "Failed to get location for structure %s.", | ||||
|               structure.structureName.c_str() | ||||
|             ); | ||||
|  | ||||
|             // Create the buffer | ||||
|             glGenBuffers(1, &structure.buffer); | ||||
|           } | ||||
|         ); | ||||
|  | ||||
|         this->bind(); | ||||
|       } | ||||
|  | ||||
|       /** | ||||
|        * Binds the shader as the current one, does not upload any data, somewhat | ||||
|        * relies on something else uploading the data. | ||||
|        */ | ||||
|       void bind() override { | ||||
|         glUseProgram(shaderProgram); | ||||
|         assertNoGLError(); | ||||
|       } | ||||
|  | ||||
|       /** | ||||
|        * Uploads the data to the GPU. | ||||
|        */ | ||||
|       void upload() override { | ||||
|         switch(this->variant) { | ||||
|           case ShaderOpenGLVariant::GLSL_330_CORE: | ||||
|             for(auto param : parameters) { | ||||
|               void *value = (void*)( | ||||
|                 ((size_t)&this->data) + param.offset | ||||
|               ); | ||||
|  | ||||
|               switch(param.type) { | ||||
|                 case ShaderParameterType::MAT4: { | ||||
|                   glm::mat4 *matrix = (glm::mat4 *)value; | ||||
|                   if(param.count != 1) { | ||||
|                     assertUnreachable("I haven't implemented multiple mat4s"); | ||||
|                   } | ||||
|                   glUniformMatrix4fv( | ||||
|                     param.location, 1, GL_FALSE, glm::value_ptr(*matrix) | ||||
|                   ); | ||||
|                   break; | ||||
|                 } | ||||
|                  | ||||
|                 case ShaderParameterType::COLOR: { | ||||
|                   auto color = (Color *)value; | ||||
|                   glUniform4fv( | ||||
|                     param.location, | ||||
|                     param.count, | ||||
|                     (GLfloat*)value | ||||
|                   ); | ||||
|                   break; | ||||
|                 } | ||||
|  | ||||
|                 case ShaderParameterType::BOOLEAN: { | ||||
|                   glUniform1iv(param.location, param.count, (GLint*)value); | ||||
|                   break; | ||||
|                 } | ||||
|  | ||||
|                 case ShaderParameterType::TEXTURE: { | ||||
|                   glUniform1iv(param.location, param.count, (GLint*)value); | ||||
|                   break; | ||||
|                 } | ||||
|  | ||||
|                 default: { | ||||
|                   assertUnreachable("Unsupported ShaderParameterType"); | ||||
|                 } | ||||
|               } | ||||
|  | ||||
|               assertNoGLError(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|           default: | ||||
|             assertUnreachable("Unsupported ShaderOpenGLVariant"); | ||||
|         } | ||||
|  | ||||
|         // Upload structures | ||||
|         for(auto structure : structures) { | ||||
|           switch(structure.structureType) { | ||||
|             case ShaderOpenGLStructureType::STD140: { | ||||
|               // Upload the data | ||||
|               glBindBuffer(GL_UNIFORM_BUFFER, structure.buffer); | ||||
|               assertNoGLError(); | ||||
|               glBindBufferBase(GL_UNIFORM_BUFFER, structure.location, structure.buffer);  | ||||
|               assertNoGLError(); | ||||
|               glBufferData( | ||||
|                 GL_UNIFORM_BUFFER, | ||||
|                 structure.size * structure.count, | ||||
|                 (void*)((size_t)&this->data + (size_t)structure.offset), | ||||
|                 GL_STATIC_DRAW | ||||
|               ); | ||||
|               assertNoGLError(); | ||||
|               break; | ||||
|             } | ||||
|  | ||||
|             default: | ||||
|               assertUnreachable("Unsupported ShaderOpenGLStructureType"); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       ~Shader() { | ||||
|         // Delete the structures | ||||
|         for(auto structure : structures) { | ||||
|           assertTrue(structure.buffer != -1, "Invalid buffer."); | ||||
|           glDeleteBuffers(1, &structure.buffer); | ||||
|           assertNoGLError(); | ||||
|         } | ||||
|  | ||||
|         // Delete the shader program | ||||
|         glDeleteProgram(shaderProgram); | ||||
|         assertNoGLError(); | ||||
|       } | ||||
|   }; | ||||
| } | ||||
| @@ -1,20 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "ShaderParameter.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| ShaderParameter::ShaderParameter(  | ||||
|   const std::string &name, | ||||
|   const void *offset, | ||||
|   const enum ShaderParameterType type, | ||||
|   const size_t count | ||||
| ) { | ||||
|   this->name = name; | ||||
|   this->offset = (size_t)offset; | ||||
|   this->type = type; | ||||
|   this->count = count; | ||||
| } | ||||
| @@ -1,33 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "display/shader/IShader.hpp" | ||||
| #include "dawnopengl.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   struct ShaderParameter { | ||||
|     std::string name; | ||||
|     size_t offset; | ||||
|     enum ShaderParameterType type; | ||||
|     size_t count; | ||||
|     GLint location = -1; | ||||
|  | ||||
|     /** | ||||
|      * Construct a new shader parameter. | ||||
|      *  | ||||
|      * @param name Name of the parameter within the shader. | ||||
|      * @param offset Offset, relative to the structure of the data. | ||||
|      * @param type Type of the parameter. | ||||
|      * @param count How many elements in the array (if multiple). | ||||
|      */ | ||||
|     ShaderParameter( | ||||
|       const std::string &name, | ||||
|       const void *offset, | ||||
|       const enum ShaderParameterType type, | ||||
|       const size_t count = 1 | ||||
|     ); | ||||
|   }; | ||||
| } | ||||
| @@ -1,74 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "assert/assertgl.hpp" | ||||
| #include "assert/assert.hpp" | ||||
| #include "ShaderStage.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| ShaderStage::ShaderStage( | ||||
|   const enum ShaderStageType type, | ||||
|   const std::string source | ||||
| ) : IShaderStage(type) { | ||||
|   // Get OpenGL Shader Type | ||||
|   GLenum shaderType; | ||||
|   switch(this->type) { | ||||
|     case ShaderStageType::VERTEX: | ||||
|       shaderType = GL_VERTEX_SHADER; | ||||
|       break; | ||||
|  | ||||
|     case ShaderStageType::FRAGMENT: | ||||
|       shaderType = GL_FRAGMENT_SHADER; | ||||
|       break; | ||||
|  | ||||
|     // case ShaderStageType::COMPUTE: | ||||
|     //   shaderType = GL_COMPUTE; | ||||
|     //   break; | ||||
|  | ||||
|     default: | ||||
|       assertUnreachable("Unknown ShaderStageType"); | ||||
|   } | ||||
|  | ||||
|   // Initialize the shader | ||||
|   this->id = glCreateShader(shaderType); | ||||
|   assertNoGLError(); | ||||
|  | ||||
|   // Compile the shader | ||||
|   auto cSource = source.c_str(); | ||||
|   glShaderSource(this->id, 1, &cSource, NULL); | ||||
|   assertNoGLError(); | ||||
|   glCompileShader(this->id); | ||||
|   assertNoGLError(); | ||||
|    | ||||
|   // glShaderBinary(1, &this->id, GL_SHADER_BINARY_FORMAT_SPIR_V, source.data(), source.size()); | ||||
|   // assertNoGLError(); | ||||
|   // glSpecializeShader(this->id, "main", 0, NULL, NULL); | ||||
|   // assertNoGLError(); | ||||
|  | ||||
|   // Validate | ||||
|   GLint status; | ||||
|   glGetShaderiv(this->id, GL_COMPILE_STATUS, &status); | ||||
|   assertNoGLError(); | ||||
|  | ||||
|   if(!status) { | ||||
|     // Failed to compile | ||||
|     GLint logLength; | ||||
|     glGetShaderiv(this->id, GL_INFO_LOG_LENGTH, &logLength); | ||||
|     assertNoGLError(); | ||||
|  | ||||
|     GLchar *log = new GLchar[logLength]; | ||||
|     glGetShaderInfoLog(this->id, logLength, NULL, log); | ||||
|     assertNoGLError(); | ||||
|     assertUnreachable("Failed to compile shader stage %i:\n%s", type, log); | ||||
|   } | ||||
| } | ||||
|  | ||||
| ShaderStage::~ShaderStage() { | ||||
|   if(this->id != -1) { | ||||
|     glDeleteShader(this->id); | ||||
|     assertNoGLError(); | ||||
|   } | ||||
| } | ||||
| @@ -1,28 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "dawnopengl.hpp" | ||||
| #include "display/shader/IShaderStage.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class ShaderStage : public IShaderStage { | ||||
|     public: | ||||
|       GLuint id = -1; | ||||
|  | ||||
|       /** | ||||
|        * Constructs a new ShaderStage. | ||||
|        *  | ||||
|        * @param type The type of shader this is. | ||||
|        * @param source The source code to compile. | ||||
|        */ | ||||
|       ShaderStage(const enum ShaderStageType type, const std::string source); | ||||
|  | ||||
|       /** | ||||
|        * Disposes of the shader stage. | ||||
|        */ | ||||
|       ~ShaderStage(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,96 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma ocne | ||||
| #include "display/shader/ShaderParameter.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   enum class ShaderOpenGLStructureType { | ||||
|     STD140 | ||||
|   }; | ||||
|  | ||||
|   struct IShaderStructure { | ||||
|     std::string structureName; | ||||
|     size_t offset; | ||||
|     enum ShaderOpenGLStructureType structureType; | ||||
|     size_t size; | ||||
|     size_t count; | ||||
|     std::vector<struct ShaderParameter> parameters; | ||||
|     GLint location = -1; | ||||
|     GLuint buffer = -1; | ||||
|   }; | ||||
|    | ||||
|   template<typename T> | ||||
|   struct ShaderStructure final : public IShaderStructure { | ||||
|     public: | ||||
|       /** | ||||
|        * Constructs a new shader structure. Shader structures allow for larger | ||||
|        * amounts/volumes of data to be passed to the shader in a single call. | ||||
|        * Ideally I wouldn't really need this as I wanted the entire shader to | ||||
|        * basically be a single large structure, but OpenGL doesn't support that | ||||
|        * so I have to do this instead. | ||||
|        *  | ||||
|        * @param structureName Structure name within the shader. | ||||
|        * @param offset Offset, within the data structure, that this structure | ||||
|        *               starts at. | ||||
|        * @param structureType The type of structure data format to use. | ||||
|        * @param getParameters A callback that, when invoked, will populate the | ||||
|        *                      parameters vector with the parameters for this | ||||
|        *                      structure. | ||||
|        * @param count The number of structures to create. | ||||
|        */ | ||||
|       ShaderStructure( | ||||
|         const std::string &structureName, | ||||
|         const void *offset, | ||||
|         const enum ShaderOpenGLStructureType structureType, | ||||
|         std::function< | ||||
|           void(const T&, std::vector<struct ShaderParameter>&) | ||||
|         > getParameters, | ||||
|         size_t count = 1 | ||||
|       ) { | ||||
|         this->structureName = structureName; | ||||
|         this->offset = (size_t)offset; | ||||
|         this->structureType = structureType; | ||||
|         this->size = sizeof(T); | ||||
|         this->count = count; | ||||
|         this->parameters = std::vector<struct ShaderParameter>(); | ||||
|  | ||||
|         T dummy; | ||||
|         getParameters(dummy, this->parameters); | ||||
|  | ||||
|         // Update offsets. | ||||
|         auto itParams = this->parameters.begin(); | ||||
|         while(itParams != this->parameters.end()) { | ||||
|           struct ShaderParameter ¶m = *itParams; | ||||
|           param.offset -= (size_t)(&dummy); | ||||
|  | ||||
|           // Check for non-aligned OpenGL structures. | ||||
|           if(param.offset % sizeof(glm::vec4) != 0) { | ||||
|             assertUnreachable( | ||||
|               "%s%s%s", | ||||
|               "Non-aligned OpenGL structure detected on param ", | ||||
|               param.name.c_str(), | ||||
|               "!\nEnsure you have padded correctly." | ||||
|             ); | ||||
|           } | ||||
|  | ||||
|           if( | ||||
|             itParams == (this->parameters.end() - 1) && | ||||
|             count > 1 && | ||||
|             (sizeof(T) % sizeof(glm::vec4)) != 0 | ||||
|           ) { | ||||
|             assertUnreachable( | ||||
|               "%s%s%s", | ||||
|               "Non-aligned OpenGL structure detected on last element in array structure on param ", | ||||
|               param.name.c_str(), | ||||
|               "!\nEnsure you have padded correctly." | ||||
|             ); | ||||
|           } | ||||
|  | ||||
|           ++itParams; | ||||
|         } | ||||
|       } | ||||
|   }; | ||||
| } | ||||
| @@ -1,230 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "display/shader/SimpleTexturedShader.hpp" | ||||
|  | ||||
| #include <fstream> | ||||
| #include "slang.h" | ||||
| #include "slang-gfx.h" | ||||
| using namespace slang; | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void SimpleTexturedShader::getStages( | ||||
|   const enum ShaderOpenGLVariant variant, | ||||
|   const struct SimpleTexturedShaderData *rel, | ||||
|   std::vector<std::shared_ptr<ShaderStage>> &stages, | ||||
|   std::vector<struct ShaderParameter> ¶meters, | ||||
|   std::vector<struct IShaderStructure> &structures | ||||
| ) { | ||||
|   // Stages | ||||
|   std::shared_ptr<ShaderStage> vertex; | ||||
|   std::shared_ptr<ShaderStage> fragment; | ||||
|  | ||||
|   std::string shader = R"( | ||||
|     cbuffer Uniforms { | ||||
|       float4x4 u_Projection; | ||||
|       float4x4 u_View; | ||||
|       float4x4 u_Model; | ||||
|       float4 u_Color; | ||||
|       bool u_HasTexture; | ||||
|       uniform Sampler2D u_Texture; | ||||
|     }; | ||||
|  | ||||
|     struct AssembledVertex { | ||||
|       float3 position : POSITION; | ||||
|       float2 texcoord : TEXCOORD; | ||||
|     }; | ||||
|  | ||||
|     struct Fragment { | ||||
|       float4 color; | ||||
|     }; | ||||
|  | ||||
|     struct VertexStageOutput { | ||||
|       float2 uv : UV; | ||||
|       float4 sv_position : SV_Position; | ||||
|     }; | ||||
|  | ||||
|     [shader("vertex")] | ||||
|     VertexStageOutput vertexMain( | ||||
|       AssembledVertex assembledVertex | ||||
|     ) { | ||||
|       VertexStageOutput output; | ||||
|  | ||||
|       float3 position = assembledVertex.position; | ||||
|  | ||||
|       output.uv = assembledVertex.texcoord; | ||||
|  | ||||
|       output.sv_position = mul( | ||||
|         float4(position, 1.0), | ||||
|         mul(u_Model, mul(u_View, u_Projection)) | ||||
|       ); | ||||
|  | ||||
|       return output; | ||||
|     } | ||||
|  | ||||
|     [shader("fragment")] | ||||
|     Fragment fragmentMain( | ||||
|       float2 uv: UV | ||||
|     ) : SV_Target { | ||||
|       Fragment output; | ||||
|       if(u_HasTexture) { | ||||
|         output.color = u_Texture.Sample(uv) * u_Color; | ||||
|       } else { | ||||
|         output.color = u_Color; | ||||
|       } | ||||
|       return output; | ||||
|     } | ||||
|   )"; | ||||
|   Slang::ComPtr<IGlobalSession> globalSession; | ||||
|   createGlobalSession(globalSession.writeRef()); | ||||
|  | ||||
|   SessionDesc sessionDesc; | ||||
|  | ||||
|   TargetDesc targetDesc; | ||||
|   targetDesc.format = SLANG_GLSL; | ||||
|   targetDesc.profile = globalSession->findProfile("glsl_330"); | ||||
|   sessionDesc.targets = &targetDesc; | ||||
|   sessionDesc.targetCount = 1; | ||||
|  | ||||
|   Slang::ComPtr<IBlob> diagnostics; | ||||
|   const char* searchPaths[] = { "/home/yourwishes/htdocs/Dawn/assets/shaders/" }; | ||||
|   sessionDesc.searchPaths = searchPaths; | ||||
|   sessionDesc.searchPathCount = 1; | ||||
|  | ||||
|   Slang::ComPtr<ISession> session; | ||||
|   globalSession->createSession(sessionDesc, session.writeRef()); | ||||
|   auto module = session->loadModuleFromSourceString( | ||||
|     "hello-world.slang", | ||||
|     "hello-world.slang", | ||||
|     shader.c_str(), | ||||
|     diagnostics.writeRef() | ||||
|   ); | ||||
|   if(diagnostics) { | ||||
|     assertUnreachable("Failed to load module %s", (const char*) diagnostics->getBufferPointer()); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   Slang::ComPtr<IEntryPoint> vertexEntryPoint; | ||||
|   Slang::ComPtr<IEntryPoint> fragEntryPoint; | ||||
|   module->findEntryPointByName("vertexMain", vertexEntryPoint.writeRef()); | ||||
|   module->findEntryPointByName("fragmentMain", fragEntryPoint.writeRef()); | ||||
|  | ||||
|   IComponentType* components[] = { module, vertexEntryPoint, fragEntryPoint }; | ||||
|   Slang::ComPtr<IComponentType> program; | ||||
|   session->createCompositeComponentType( | ||||
|     components, | ||||
|     sizeof(components) / sizeof(components[0]), | ||||
|     program.writeRef() | ||||
|   ); | ||||
|  | ||||
|   Slang::ComPtr<IComponentType> linkedProgram; | ||||
|   auto result = program->link(linkedProgram.writeRef(), diagnostics.writeRef()); | ||||
|   std::cout << "Result: " << result << std::endl; | ||||
|   if(diagnostics) { | ||||
|     assertUnreachable("%s\n", (const char*) diagnostics->getBufferPointer()); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   int entryPointIndex = 0; | ||||
|   int targetIndex = 0; // only one target | ||||
|   Slang::ComPtr<IBlob> vertexBlob; | ||||
|   result = linkedProgram->getEntryPointCode( | ||||
|     entryPointIndex, | ||||
|     targetIndex, | ||||
|     vertexBlob.writeRef(), | ||||
|     diagnostics.writeRef() | ||||
|   ); | ||||
|   if(diagnostics) { | ||||
|     assertUnreachable("%s\n", (const char*) diagnostics->getBufferPointer()); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   slang::ProgramLayout* layout = program->getLayout(); | ||||
|   unsigned parameterCount = layout->getParameterCount(); | ||||
|   for(unsigned pp = 0; pp < parameterCount; pp++) { | ||||
|     slang::VariableLayoutReflection* parameter = layout->getParameterByIndex(pp); | ||||
|     std::cout << "Parameter: " << parameter->getName() << std::endl; | ||||
|      | ||||
|     auto layout = parameter->getTypeLayout(); | ||||
|     auto fields = layout->getFieldCount(); | ||||
|     for(unsigned ff = 0; ff < fields; ff++) { | ||||
|       slang::VariableLayoutReflection* field = layout->getFieldByIndex(ff); | ||||
|       std::string fieldName = field->getName(); | ||||
|       std::cout << "Field: " << fieldName << std::endl; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   std::string vertexString = (const char*)vertexBlob->getBufferPointer(); | ||||
|  | ||||
|   entryPointIndex = 1; | ||||
|   Slang::ComPtr<IBlob> fragmentBlob; | ||||
|   result = linkedProgram->getEntryPointCode( | ||||
|     entryPointIndex, | ||||
|     targetIndex, | ||||
|     fragmentBlob.writeRef(), | ||||
|     diagnostics.writeRef() | ||||
|   ); | ||||
|   if(diagnostics) { | ||||
|     assertUnreachable("%s\n", (const char*) diagnostics->getBufferPointer()); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   std::string fragmentString = (const char*)fragmentBlob->getBufferPointer(); | ||||
|  | ||||
|   vertex = std::make_shared<ShaderStage>( | ||||
|     ShaderStageType::VERTEX, vertexString | ||||
|   ); | ||||
|   stages.push_back(vertex); | ||||
|  | ||||
|   fragment = std::make_shared<ShaderStage>( | ||||
|     ShaderStageType::FRAGMENT, fragmentString | ||||
|   ); | ||||
|   stages.push_back(fragment); | ||||
|  | ||||
|   structures.push_back(ShaderStructure<struct SimpleTexturedShaderDataSub>( | ||||
|     "block_SLANG_ParameterGroup_Uniforms_std140_0", | ||||
|     &rel->data, | ||||
|     ShaderOpenGLStructureType::STD140, | ||||
|     [](const SimpleTexturedShaderDataSub &data, std::vector<struct ShaderParameter> ¶meters) { | ||||
|       parameters.push_back(ShaderParameter( | ||||
|         "u_Projection_0", | ||||
|         &data.projection, | ||||
|         ShaderParameterType::MAT4 | ||||
|       )); | ||||
|  | ||||
|       parameters.push_back(ShaderParameter( | ||||
|         "u_View_0", | ||||
|         &data.view, | ||||
|         ShaderParameterType::MAT4 | ||||
|       )); | ||||
|  | ||||
|       parameters.push_back(ShaderParameter( | ||||
|         "u_Model_0", | ||||
|         &data.model, | ||||
|         ShaderParameterType::MAT4 | ||||
|       )); | ||||
|  | ||||
|       parameters.push_back(ShaderParameter( | ||||
|         "u_Color_0", | ||||
|         &data.color, | ||||
|         ShaderParameterType::COLOR | ||||
|       )); | ||||
|  | ||||
|       parameters.push_back(ShaderParameter( | ||||
|         "u_HasTexture_0", | ||||
|         &data.hasTexture, | ||||
|         ShaderParameterType::BOOLEAN | ||||
|       )); | ||||
|     } | ||||
|   )); | ||||
|  | ||||
|   // Parameters | ||||
|   parameters.push_back(ShaderParameter( | ||||
|     "Uniforms_u_Texture_0", | ||||
|     &rel->texture, | ||||
|     ShaderParameterType::TEXTURE | ||||
|   )); | ||||
| } | ||||
| @@ -1,34 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "display/shader/Shader.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   struct SimpleTexturedShaderDataSub { | ||||
|     glm::mat4 projection; | ||||
|     glm::mat4 view; | ||||
|     glm::mat4 model; | ||||
|     struct Color color = COLOR_WHITE; | ||||
|  | ||||
|     bool hasTexture = false; | ||||
|   }; | ||||
|  | ||||
|   struct SimpleTexturedShaderData { | ||||
|     struct SimpleTexturedShaderDataSub data; | ||||
|     shadertexturebinding_t texture = 0; | ||||
|   }; | ||||
|  | ||||
|   class SimpleTexturedShader : public Shader<SimpleTexturedShaderData> { | ||||
|     protected: | ||||
|       void getStages( | ||||
|         const enum ShaderOpenGLVariant variant, | ||||
|         const struct SimpleTexturedShaderData *rel, | ||||
|         std::vector<std::shared_ptr<ShaderStage>> &stages, | ||||
|         std::vector<struct ShaderParameter> ¶meters, | ||||
|         std::vector<struct IShaderStructure> &structures | ||||
|       ) override; | ||||
|   }; | ||||
| } | ||||
| @@ -1,194 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "display/shader/UIShader.hpp" | ||||
| #include "util/Macro.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void UIShader::getStages( | ||||
|   const enum ShaderOpenGLVariant variant, | ||||
|   const struct UIShaderData *rel, | ||||
|   std::vector<std::shared_ptr<ShaderStage>> &stages, | ||||
|   std::vector<struct ShaderParameter> ¶meters, | ||||
|   std::vector<struct IShaderStructure> &structures | ||||
| ) { | ||||
|   // Stages | ||||
|   std::shared_ptr<ShaderStage> vertex; | ||||
|   std::shared_ptr<ShaderStage> fragment; | ||||
|  | ||||
|   switch(variant) { | ||||
|     case ShaderOpenGLVariant::GLSL_330_CORE: | ||||
|       vertex = std::make_shared<ShaderStage>( | ||||
|         ShaderStageType::VERTEX, | ||||
|         "#version 330 core\n" | ||||
|         "layout (location = 0) in vec3 aPos;\n" | ||||
|         "layout (location = 1) in vec2 aTexCoord;\n" | ||||
|         "uniform mat4 u_Projection;\n" | ||||
|         "uniform mat4 u_View;\n" | ||||
|         "uniform mat4 u_Model;\n" | ||||
|         "struct UIShaderQuad {\n" | ||||
|           "vec4 quad;\n" | ||||
|           "vec4 uv;\n" | ||||
|           "vec4 color;\n" | ||||
|           "vec4 style;\n" | ||||
|         "};\n" | ||||
|         "layout (std140) uniform ub_Quad {\n" | ||||
|           "UIShaderQuad quads[" MACRO_STRINGIFY(UI_SHADER_QUAD_COUNT) "];\n" | ||||
|         "};\n" | ||||
|         "out vec2 v_TextCoord;\n" | ||||
|         "out vec4 v_Color;\n" | ||||
|         "out vec4 v_Style;\n" | ||||
|         "void main() {\n" | ||||
|           "vec4 pos;\n" | ||||
|           "vec2 coord;\n" | ||||
|           "int index = int(aPos.z);\n" | ||||
|           "int quadIndex = index / 4;\n" | ||||
|           "int vertexIndex = index % 4;\n" | ||||
|           "UIShaderQuad quad = quads[quadIndex];\n" | ||||
|           "if(vertexIndex == 0) {\n" | ||||
|             "pos.x = quad.quad.x;\n" | ||||
|             "pos.y = quad.quad.y;\n" | ||||
|             "coord.x = quad.uv.x;\n" | ||||
|             "coord.y = quad.uv.y;\n" | ||||
|           "} else if(vertexIndex == 1) {\n" | ||||
|             "pos.x = quad.quad.z;\n" | ||||
|             "pos.y = quad.quad.y;\n" | ||||
|             "coord.x = quad.uv.z;\n" | ||||
|             "coord.y = quad.uv.y;\n" | ||||
|           "} else if(vertexIndex == 2) {\n" | ||||
|             "pos.y = quad.quad.w;\n" | ||||
|             "pos.x = quad.quad.x;\n" | ||||
|             "coord.x = quad.uv.x;\n" | ||||
|             "coord.y = quad.uv.w;\n" | ||||
|           "} else if(vertexIndex == 3) {\n" | ||||
|             "pos.x = quad.quad.z;\n" | ||||
|             "pos.y = quad.quad.w;\n" | ||||
|             "coord.x = quad.uv.z;\n" | ||||
|             "coord.y = quad.uv.w;\n" | ||||
|           "}\n" | ||||
|           "pos.z = 0;\n" | ||||
|           "pos.w = 1;\n" | ||||
|           "gl_Position = u_Projection * u_View * u_Model * pos;\n" | ||||
|           "v_TextCoord = coord;\n" | ||||
|           "v_Color = quad.color;\n" | ||||
|           "v_Style = quad.style;\n" | ||||
|         "}" | ||||
|       ); | ||||
|        | ||||
|       fragment = std::make_shared<ShaderStage>( | ||||
|         ShaderStageType::FRAGMENT, | ||||
|         "#version 330 core\n" | ||||
|         "in vec2 v_TextCoord;\n" | ||||
|         "in vec4 v_Color;\n" | ||||
|         "in vec4 v_Style;\n" | ||||
|         "uniform sampler2D u_Texture[" MACRO_STRINGIFY(UI_SHADER_TEXTURE_COUNT) "];\n" | ||||
|         "out vec4 o_Color;\n"  | ||||
|         "void main() {\n" | ||||
|           "vec4 texColor = vec4(1, 1, 1, 1);\n" | ||||
|           "int vStyle = int(round(v_Style[0]));\n" | ||||
|           "int vTextInd = int(round(v_Style[1]));\n" | ||||
|           "switch(vTextInd) {\n" | ||||
|             "case -1:\n" | ||||
|               "texColor = vec4(1, 1, 1, 1);\n" | ||||
|               "break;\n" | ||||
|             "case 0:\n" | ||||
|               "texColor = texture(u_Texture[0], v_TextCoord);\n" | ||||
|               "break;\n" | ||||
|             "case 1:\n" | ||||
|               "texColor = texture(u_Texture[1], v_TextCoord);\n" | ||||
|               "break;\n" | ||||
|             "case 2:\n" | ||||
|               "texColor = texture(u_Texture[2], v_TextCoord);\n" | ||||
|               "break;\n" | ||||
|             "case 3:\n" | ||||
|               "texColor = texture(u_Texture[3], v_TextCoord);\n" | ||||
|               "break;\n" | ||||
|             "case 4:\n" | ||||
|               "texColor = texture(u_Texture[4], v_TextCoord);\n" | ||||
|               "break;\n" | ||||
|             "case 5:\n" | ||||
|               "texColor = texture(u_Texture[5], v_TextCoord);\n" | ||||
|               "break;\n" | ||||
|           "}\n" | ||||
|           "switch(vStyle) {\n" | ||||
|             "case 0:\n" | ||||
|               "o_Color = texColor * v_Color;\n" | ||||
|               "break;\n" | ||||
|             "case 1:\n" | ||||
|               "o_Color.rgb = v_Color.rgb;\n" | ||||
|               "o_Color.a = texColor.r * v_Color.a;\n" | ||||
|               "break;\n" | ||||
|           "}\n" | ||||
|         "}\n" | ||||
|       ); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       assertUnreachable("Unsupported ShaderOpenGLVariant"); | ||||
|   } | ||||
|  | ||||
|   // Add stages | ||||
|   stages.push_back(vertex); | ||||
|   stages.push_back(fragment); | ||||
|  | ||||
|   // Parameters | ||||
|   parameters.push_back(ShaderParameter( | ||||
|     "u_Projection", | ||||
|     &rel->projection, | ||||
|     ShaderParameterType::MAT4 | ||||
|   )); | ||||
|  | ||||
|   parameters.push_back(ShaderParameter( | ||||
|     "u_View", | ||||
|     &rel->view, | ||||
|     ShaderParameterType::MAT4 | ||||
|   )); | ||||
|  | ||||
|   parameters.push_back(ShaderParameter( | ||||
|     "u_Model", | ||||
|     &rel->model, | ||||
|     ShaderParameterType::MAT4 | ||||
|   )); | ||||
|  | ||||
|   parameters.push_back(ShaderParameter( | ||||
|     "u_Texture", | ||||
|     &rel->textures, | ||||
|     ShaderParameterType::TEXTURE, | ||||
|     UI_SHADER_TEXTURE_COUNT | ||||
|   )); | ||||
|    | ||||
|   structures.push_back(ShaderStructure<struct UIShaderQuad>( | ||||
|     "ub_Quad", | ||||
|     &rel->quads, | ||||
|     ShaderOpenGLStructureType::STD140, | ||||
|     [&](const struct UIShaderQuad &rel, std::vector<struct ShaderParameter> ¶meters) { | ||||
|       parameters.push_back(ShaderParameter( | ||||
|         "quad", | ||||
|         &rel.quad, | ||||
|         ShaderParameterType::VEC4 | ||||
|       )); | ||||
|  | ||||
|       parameters.push_back(ShaderParameter( | ||||
|         "uv", | ||||
|         &rel.uv, | ||||
|         ShaderParameterType::VEC4 | ||||
|       )); | ||||
|  | ||||
|       parameters.push_back(ShaderParameter( | ||||
|         "color", | ||||
|         &rel.color, | ||||
|         ShaderParameterType::COLOR | ||||
|       )); | ||||
|  | ||||
|       parameters.push_back(ShaderParameter( | ||||
|         "style", | ||||
|         &rel.style, | ||||
|         ShaderParameterType::VEC4 | ||||
|       )); | ||||
|     }, | ||||
|     UI_SHADER_QUAD_COUNT | ||||
|   )); | ||||
| } | ||||
| @@ -1,43 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "display/shader/Shader.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   #define UI_SHADER_QUAD_COUNT 1024 | ||||
|   #define UI_SHADER_TEXTURE_COUNT 16 | ||||
|  | ||||
|   enum class UIShaderQuadStyle { | ||||
|     TEXTURED = 0, | ||||
|     FONT = 1 | ||||
|   }; | ||||
|  | ||||
|   struct UIShaderQuad { | ||||
|     glm::vec4 quad; | ||||
|     glm::vec4 uv; | ||||
|     struct Color color; | ||||
|     glm::vec4 style; | ||||
|   }; | ||||
|    | ||||
|   struct UIShaderData { | ||||
|     glm::mat4 projection; | ||||
|     glm::mat4 view; | ||||
|     glm::mat4 model; | ||||
|     shadertexturebinding_t textures[UI_SHADER_TEXTURE_COUNT]; | ||||
|     struct UIShaderQuad quads[UI_SHADER_QUAD_COUNT]; | ||||
|   }; | ||||
|  | ||||
|   class UIShader : public Shader<UIShaderData> { | ||||
|     protected: | ||||
|       void getStages( | ||||
|         const enum ShaderOpenGLVariant variant, | ||||
|         const struct UIShaderData *rel, | ||||
|         std::vector<std::shared_ptr<ShaderStage>> &stages, | ||||
|         std::vector<struct ShaderParameter> ¶meters, | ||||
|         std::vector<struct IShaderStructure> &structures | ||||
|       ) override; | ||||
|   }; | ||||
| } | ||||
| @@ -1,9 +0,0 @@ | ||||
| # Copyright (c) 2023 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     UICanvas.cpp | ||||
| ) | ||||
| @@ -1,144 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "UICanvas.hpp" | ||||
| #include "display/pass/RenderPass.hpp" | ||||
| #include "display/mesh/QuadMesh.hpp" | ||||
| #include "ui/UIElement.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void UICanvas::onInit() { | ||||
|   mesh = std::make_shared<Mesh>(); | ||||
|   mesh->createBuffers( | ||||
|     QUAD_VERTICE_COUNT * UI_SHADER_QUAD_COUNT, | ||||
|     QUAD_INDICE_COUNT * UI_SHADER_QUAD_COUNT | ||||
|   ); | ||||
|  | ||||
|   for(int32_t i = 0; i < UI_SHADER_QUAD_COUNT; i++) { | ||||
|     QuadMesh::bufferWithIndex( | ||||
|       mesh, | ||||
|       glm::vec4(0, 0, 1, 1), | ||||
|       glm::vec4(0, 0, 1, 1), | ||||
|       i * QUAD_VERTICE_COUNT, | ||||
|       i * QUAD_INDICE_COUNT, | ||||
|       i * QUAD_VERTICE_COUNT | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void UICanvas::onDispose() { | ||||
|   mesh = nullptr; | ||||
| } | ||||
|  | ||||
| std::vector<std::shared_ptr<IRenderPass>> UICanvas::getPasses( | ||||
| struct RenderPassContext &ctx | ||||
| ) { | ||||
|   if(this->elements.empty()) return {}; | ||||
|  | ||||
|   glm::mat4 projection; | ||||
|   glm::mat4 view; | ||||
|    | ||||
|   // Setup the projection and views | ||||
|   data.projection = glm::ortho( | ||||
|     0.0f, ctx.renderTarget->getWidth(), | ||||
|     ctx.renderTarget->getHeight(), 0.0f, | ||||
|     0.0f, 1.0f | ||||
|   ); | ||||
|   data.view = glm::mat4(1.0f); | ||||
|   data.model = glm::mat4(1.0f); | ||||
|  | ||||
|   // Reset the passes | ||||
|   this->passes.clear(); | ||||
|   this->textureBindings.clear(); | ||||
|   this->textures.clear(); | ||||
|   quadCount = 0; | ||||
|   nextBinding = 0; | ||||
|  | ||||
|   // Alignment root | ||||
|   const glm::vec2 rootPosition = { 0, 0 }; | ||||
|   const glm::vec2 rootSize = { | ||||
|     ctx.renderTarget->getWidth(), | ||||
|     ctx.renderTarget->getHeight() | ||||
|   }; | ||||
|   const float_t rootScale = 1.0f; | ||||
|  | ||||
|   // Get the quads for each component | ||||
|   auto itComponents = elements.begin(); | ||||
|   auto self = std::ref(*this); | ||||
|   while(itComponents != elements.end()) { | ||||
|     auto component = *itComponents; | ||||
|     component->updateAlignment(rootPosition, rootSize, rootScale); | ||||
|     component->getQuads(self); | ||||
|     ++itComponents; | ||||
|   } | ||||
|  | ||||
|   // Flush the remaining quads | ||||
|   flushPass(); | ||||
|   return passes; | ||||
| } | ||||
|  | ||||
| void UICanvas::addQuad( | ||||
|   const glm::vec4 quad, | ||||
|   const glm::vec4 uvs, | ||||
|   const struct Color color, | ||||
|   const enum UIShaderQuadStyle style, | ||||
|   const std::shared_ptr<Texture> text | ||||
| ) { | ||||
|   glm::vec4 styleData; | ||||
|   styleData[0] = (float_t)style; | ||||
|  | ||||
|   if(text == nullptr) { | ||||
|     styleData[1] = -1; | ||||
|   } else { | ||||
|     shadertexturebinding_t texture; | ||||
|     auto bindingIt = textureBindings.find(text); | ||||
|     if(bindingIt == textureBindings.end()) { | ||||
|       if(nextBinding >= UI_SHADER_TEXTURE_COUNT) { | ||||
|         flushPass(); | ||||
|       } | ||||
|       textureBindings[text] = nextBinding; | ||||
|       textures[nextBinding] = text; | ||||
|       data.textures[nextBinding] = nextBinding; | ||||
|       texture = nextBinding++; | ||||
|     } else { | ||||
|       texture = bindingIt->second; | ||||
|     } | ||||
|     styleData[1] = (float_t)texture; | ||||
|   } | ||||
|  | ||||
|   data.quads[quadCount] = { | ||||
|     quad, | ||||
|     uvs, | ||||
|     color, | ||||
|     styleData | ||||
|   }; | ||||
|   quadCount++; | ||||
|   if(quadCount == UI_SHADER_QUAD_COUNT) flushPass(); | ||||
| } | ||||
|  | ||||
| void UICanvas::flushPass() { | ||||
|   if(quadCount == 0) return; | ||||
|  | ||||
|   auto pass = createRenderPass<UIShader, UIShaderData>( | ||||
|     std::ref(*this), | ||||
|     data, | ||||
|     textures, | ||||
|     mesh, | ||||
|     MeshDrawMode::TRIANGLES, | ||||
|     0, | ||||
|     quadCount * QUAD_INDICE_COUNT | ||||
|   ); | ||||
|   passes.push_back(pass); | ||||
|  | ||||
|   quadCount = 0; | ||||
|   nextBinding = 0; | ||||
|   textures.clear(); | ||||
|   textureBindings.clear(); | ||||
| } | ||||
|  | ||||
| void UICanvas::addElement(const std::shared_ptr<UIElement> element) { | ||||
|   elements.push_back(element); | ||||
| } | ||||
| @@ -1,73 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "scene/SceneItem.hpp" | ||||
| #include "component/display/IRenderableComponent.hpp" | ||||
| #include "display/shader/UIShader.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class UIElement; | ||||
|  | ||||
|   class UICanvas : | ||||
|     public SceneComponent, | ||||
|     public IRenderableComponent | ||||
|   { | ||||
|     private: | ||||
|       std::shared_ptr<Mesh> mesh; | ||||
|       UIShaderData data; | ||||
|       std::vector<std::shared_ptr<UIElement>> elements; | ||||
|  | ||||
|       size_t quadCount = 0; | ||||
|       shadertexturebinding_t nextBinding = 0; | ||||
|       std::unordered_map< | ||||
|         shadertexturebinding_t, std::shared_ptr<Texture> | ||||
|       > textures; | ||||
|       std::map< | ||||
|         std::shared_ptr<Texture>, shadertexturebinding_t | ||||
|       > textureBindings; | ||||
|        | ||||
|       std::vector<std::shared_ptr<IRenderPass>> passes; | ||||
|        | ||||
|     protected: | ||||
|       virtual void onInit() override; | ||||
|       virtual void onDispose() override; | ||||
|  | ||||
|       /** | ||||
|        * Flushes all pending quads to the render pass. This doesn't actually | ||||
|        * render anything, it just flushes the data buffer to a new pass. | ||||
|        */ | ||||
|       void flushPass(); | ||||
|  | ||||
|     public: | ||||
|       std::vector<std::shared_ptr<IRenderPass>> getPasses( | ||||
|         struct RenderPassContext &ctx | ||||
|       ) override; | ||||
|  | ||||
|       /** | ||||
|        * Adds a quad to the canvas and performs a flush if necessary. | ||||
|        *  | ||||
|        * @param quad The quad to add. | ||||
|        * @param uvs The UVs to use for the quad. | ||||
|        * @param color The color to use for the quad. | ||||
|        * @param style Style that the quad should be rendered in. | ||||
|        * @param texture The texture to use for the quad, can be null. | ||||
|        */ | ||||
|       void addQuad( | ||||
|         const glm::vec4 quad, | ||||
|         const glm::vec4 uvs, | ||||
|         const struct Color color, | ||||
|         const enum UIShaderQuadStyle style, | ||||
|         const std::shared_ptr<Texture> texture = nullptr | ||||
|       ); | ||||
|  | ||||
|       /** | ||||
|        * Adds a component to the canvas. | ||||
|        *  | ||||
|        * @param component The component to add. | ||||
|        */ | ||||
|       void addElement(const std::shared_ptr<UIElement> component); | ||||
|   }; | ||||
| } | ||||
| @@ -1,16 +0,0 @@ | ||||
| # Copyright (c) 2023 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     UIAlignableElement.cpp | ||||
|     UISubAlignableElement.cpp | ||||
|     UIElement.cpp | ||||
|     UIMenu.cpp | ||||
| ) | ||||
|  | ||||
| # Subdirs | ||||
| add_subdirectory(container) | ||||
| add_subdirectory(elements) | ||||
| @@ -1,247 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "UIAlignableElement.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| UIAlignableElement::UIAlignableElement() { | ||||
|   alignUnit[0] = UIAlignmentUnit::SCALE; | ||||
|   alignUnit[1] = UIAlignmentUnit::SCALE; | ||||
|   alignUnit[2] = UIAlignmentUnit::SCALE; | ||||
|   alignUnit[3] = UIAlignmentUnit::SCALE; | ||||
|  | ||||
|   eventAlignmentUpdated = [&](const glm::vec2 p, const glm::vec2 s) { | ||||
|   }; | ||||
| } | ||||
|  | ||||
| void UIAlignableElement::updateSelfAlignment( | ||||
|   const glm::vec2 pPos, | ||||
|   const glm::vec2 pSize, | ||||
|   const float_t canvasScale | ||||
| ) { | ||||
|   auto valueAxis = [&]( | ||||
|     const enum UIAlignmentUnit unit, | ||||
|     const float_t alignment, | ||||
|     const float_t parentSize, | ||||
|     const float_t ratioSize, | ||||
|     const float_t contentSize | ||||
|   ) { | ||||
|     if(alignment == UI_ALIGN_SIZE_AUTO) return contentSize; | ||||
|  | ||||
|     switch(unit) { | ||||
|       case UIAlignmentUnit::PIXEL: | ||||
|         return alignment; | ||||
|  | ||||
|       case UIAlignmentUnit::SCALE: | ||||
|         return canvasScale * alignment; | ||||
|  | ||||
|       case UIAlignmentUnit::PERCENT: | ||||
|         return parentSize * (alignment / 100.0f); | ||||
|  | ||||
|       case UIAlignmentUnit::RATIO: | ||||
|         return (alignment / 100.0f) * ratioSize; | ||||
|        | ||||
|       default: | ||||
|         assertUnreachable("Invalid UIAlignmentType"); | ||||
|         return 0.0f; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   auto alignAxis = [&]( | ||||
|     const enum UIAlignmentType type, | ||||
|     const enum UIAlignmentUnit unit0, | ||||
|     const enum UIAlignmentUnit unit1, | ||||
|     const float_t alignment0, | ||||
|     const float_t alignment1, | ||||
|     const float_t parentSize, | ||||
|     const float_t ratioSize, | ||||
|     const float_t contentSize, | ||||
|     float_t &outPosition, | ||||
|     float_t &outSize | ||||
|   ) { | ||||
|     switch(type) { | ||||
|       case UIAlignmentType::START: | ||||
|         outPosition = valueAxis( | ||||
|           unit0, | ||||
|           alignment0, | ||||
|           parentSize, | ||||
|           ratioSize, | ||||
|           contentSize | ||||
|         ); | ||||
|         outSize = valueAxis( | ||||
|           unit1, | ||||
|           alignment1, | ||||
|           parentSize, | ||||
|           ratioSize, | ||||
|           contentSize | ||||
|         ); | ||||
|         break; | ||||
|  | ||||
|       case UIAlignmentType::MIDDLE: | ||||
|         outSize = valueAxis( | ||||
|           unit1, | ||||
|           alignment1, | ||||
|           parentSize, | ||||
|           ratioSize, | ||||
|           contentSize | ||||
|         ); | ||||
|         outPosition = (parentSize / 2.0f) - (contentSize / 2.0f) + valueAxis( | ||||
|           unit0, | ||||
|           alignment0, | ||||
|           parentSize, | ||||
|           ratioSize, | ||||
|           contentSize | ||||
|         ); | ||||
|         break; | ||||
|  | ||||
|       case UIAlignmentType::END: | ||||
|         outSize = valueAxis( | ||||
|           unit0, | ||||
|           alignment0, | ||||
|           parentSize, | ||||
|           ratioSize, | ||||
|           contentSize | ||||
|         ); | ||||
|         outPosition = parentSize - outSize - valueAxis( | ||||
|           unit1, | ||||
|           alignment1, | ||||
|           parentSize, | ||||
|           ratioSize, | ||||
|           contentSize | ||||
|         ); | ||||
|         break; | ||||
|  | ||||
|       case UIAlignmentType::STRETCH: | ||||
|         outPosition = valueAxis( | ||||
|           unit0, | ||||
|           alignment0, | ||||
|           parentSize, | ||||
|           ratioSize, | ||||
|           contentSize | ||||
|         ); | ||||
|         outSize = parentSize - (outPosition + valueAxis( | ||||
|           unit1, | ||||
|           alignment1, | ||||
|           parentSize, | ||||
|           ratioSize, | ||||
|           contentSize | ||||
|         )); | ||||
|         break; | ||||
|  | ||||
|       default: | ||||
|         assertUnreachable("Invalid UIAlignmentType"); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   bool_t heightFirst = ( | ||||
|     alignUnit[0] == UIAlignmentUnit::RATIO || | ||||
|     alignUnit[2] == UIAlignmentUnit::RATIO | ||||
|   ); | ||||
|  | ||||
|   if(heightFirst) { | ||||
|     // Align height first, this will define size.y which we can use as the ratio | ||||
|     // for the width/X axis alignment. | ||||
|     alignAxis( | ||||
|       alignY, | ||||
|       alignUnit[1], | ||||
|       alignUnit[3], | ||||
|       align[1], | ||||
|       align[3], | ||||
|       pSize.y, | ||||
|       0, | ||||
|       this->getContentHeight(), | ||||
|       position.y, | ||||
|       size.y | ||||
|     ); | ||||
|     alignAxis( | ||||
|       alignX, | ||||
|       alignUnit[0], | ||||
|       alignUnit[2], | ||||
|       align[0], | ||||
|       align[2], | ||||
|       pSize.x, | ||||
|       size.y, | ||||
|       this->getContentWidth(), | ||||
|       position.x, | ||||
|       size.x | ||||
|     ); | ||||
|   } else { | ||||
|     alignAxis( | ||||
|       alignX, | ||||
|       alignUnit[0], | ||||
|       alignUnit[2], | ||||
|       align[0], | ||||
|       align[2], | ||||
|       pSize.x, | ||||
|       0, | ||||
|       this->getContentWidth(), | ||||
|       position.x, | ||||
|       size.x | ||||
|     ); | ||||
|     alignAxis( | ||||
|       alignY, | ||||
|       alignUnit[1], | ||||
|       alignUnit[3], | ||||
|       align[1], | ||||
|       align[3], | ||||
|       pSize.y, | ||||
|       size.x, | ||||
|       this->getContentHeight(), | ||||
|       position.y, | ||||
|       size.y | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   this->position += pPos; | ||||
|   this->eventAlignmentUpdated(position, size); | ||||
| } | ||||
|  | ||||
| bool_t UIAlignableElement::hasExplicitWidth() { | ||||
|   if(size.x == 0.0f) return false; | ||||
|   if( | ||||
|     (alignX == UIAlignmentType::STRETCH) || | ||||
|     (alignX == UIAlignmentType::END) | ||||
|   ) { | ||||
|     return align[0] != UI_ALIGN_SIZE_AUTO; | ||||
|   } | ||||
|   return align[2] != UI_ALIGN_SIZE_AUTO; | ||||
| } | ||||
|  | ||||
| bool_t UIAlignableElement::hasExplicitHeight() { | ||||
|   if(size.y == 0.0f) return false; | ||||
|   if( | ||||
|     (alignY == UIAlignmentType::STRETCH) || | ||||
|     (alignY == UIAlignmentType::END) | ||||
|   ) { | ||||
|     return align[1] != UI_ALIGN_SIZE_AUTO; | ||||
|   } | ||||
|   return align[3] != UI_ALIGN_SIZE_AUTO; | ||||
| } | ||||
|  | ||||
| float_t UIAlignableElement::getWidth() { | ||||
|   if(hasExplicitWidth()) return size.x; | ||||
|   return getContentWidth(); | ||||
| } | ||||
|  | ||||
| float_t UIAlignableElement::getHeight() { | ||||
|   if(hasExplicitHeight()) return size.y; | ||||
|   return getContentHeight(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void UIAlignableElement::updateAlignment( | ||||
|   const glm::vec2 pPos, | ||||
|   const glm::vec2 pSize, | ||||
|   const float_t canvasScale | ||||
| ) { | ||||
|   this->updateSelfAlignment(pPos, pSize, canvasScale); | ||||
|  | ||||
|   // Now update children alignment | ||||
|   auto children = getChildren(); | ||||
|   for(auto &c : children) { | ||||
|     c->updateAlignment(this->position, this->size, canvasScale); | ||||
|   } | ||||
| } | ||||
| @@ -1,83 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "ui/UIElement.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   #define UI_ALIGN_SIZE_AUTO -1.0f | ||||
|  | ||||
|   enum class UIAlignmentType { | ||||
|     START, | ||||
|     MIDDLE, | ||||
|     END, | ||||
|     STRETCH | ||||
|   }; | ||||
|  | ||||
|   enum class UIAlignmentUnit { | ||||
|     PIXEL, | ||||
|     SCALE, | ||||
|     PERCENT, | ||||
|     RATIO | ||||
|   }; | ||||
|  | ||||
|   class UIAlignableElement : public UIElement { | ||||
|     protected: | ||||
|       glm::vec2 position; | ||||
|       glm::vec2 size; | ||||
|        | ||||
|       /** | ||||
|        * Updates the alignment of this element ONLY. | ||||
|        *  | ||||
|        * @param parentPosition The position of the parent. | ||||
|        * @param parentSize The size of the parent. | ||||
|        * @param canvasScale The scale of the canvas. | ||||
|        */ | ||||
|       virtual void updateSelfAlignment( | ||||
|         const glm::vec2 parentPosition, | ||||
|         const glm::vec2 parentSize, | ||||
|         const float_t canvasScale | ||||
|       ); | ||||
|  | ||||
|       /** | ||||
|        * Returns true only if the width of this component is explicitly set. | ||||
|        *  | ||||
|        * @return True if the width of this component is explicitly set. | ||||
|        */ | ||||
|       bool_t hasExplicitWidth(); | ||||
|  | ||||
|       /** | ||||
|        * Returns true only if the height of this component is explicitly set. | ||||
|        *  | ||||
|        * @return True if the height of this component is explicitly set. | ||||
|        */ | ||||
|       bool_t hasExplicitHeight(); | ||||
|  | ||||
|     public: | ||||
|       // Primary alignment controls | ||||
|       glm::vec4 align = glm::vec4(0, 0, 0, 0); | ||||
|       enum UIAlignmentType alignX = UIAlignmentType::STRETCH; | ||||
|       enum UIAlignmentType alignY = UIAlignmentType::STRETCH; | ||||
|       enum UIAlignmentUnit alignUnit[4]; | ||||
|        | ||||
|       std::function< | ||||
|         void(const glm::vec2, const glm::vec2) | ||||
|       > eventAlignmentUpdated; | ||||
|  | ||||
|       /** | ||||
|        * Constructor for the UIAlignableElement. | ||||
|        */ | ||||
|       UIAlignableElement(); | ||||
|  | ||||
|       float_t getWidth() override; | ||||
|       float_t getHeight() override; | ||||
|  | ||||
|       void updateAlignment( | ||||
|         const glm::vec2 parentPosition, | ||||
|         const glm::vec2 parentSize, | ||||
|         const float_t canvasScale | ||||
|       ) override; | ||||
|   }; | ||||
| } | ||||
| @@ -1,53 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "UIElement.hpp" | ||||
| #include "assert/assert.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| std::vector<std::shared_ptr<UIElement>> UIElement::getChildren() { | ||||
|   return {}; | ||||
| } | ||||
|  | ||||
| void UIElement::getSelfQuads(UICanvas &ctx) { | ||||
|   //Do nothing | ||||
| } | ||||
|  | ||||
| float_t UIElement::getContentWidth() { | ||||
|   return 0.0f; | ||||
| } | ||||
|  | ||||
| float_t UIElement::getContentHeight() { | ||||
|   return 0.0f; | ||||
| } | ||||
|  | ||||
| float_t UIElement::getWidth() { | ||||
|   return this->getContentWidth(); | ||||
| } | ||||
|  | ||||
| float_t UIElement::getHeight() { | ||||
|   return this->getContentHeight(); | ||||
| } | ||||
|  | ||||
| void UIElement::getQuads(UICanvas &ctx) { | ||||
|   this->getSelfQuads(ctx); | ||||
|  | ||||
|   auto children = getChildren(); | ||||
|   for(auto &c : children) { | ||||
|     c->getQuads(ctx); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void UIElement::updateAlignment( | ||||
|   const glm::vec2 parentPosition, | ||||
|   const glm::vec2 parentSize, | ||||
|   const float_t canvasScale | ||||
| ) { | ||||
|   auto children = getChildren(); | ||||
|   for(auto &c : children) { | ||||
|     c->updateAlignment(parentPosition, parentSize, canvasScale); | ||||
|   } | ||||
| } | ||||
| @@ -1,80 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "display/shader/UIShader.hpp" | ||||
| #include "component/ui/UICanvas.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class UIElement { | ||||
|     protected: | ||||
|       /** | ||||
|        * Virtual method overridden by the UIElement to get the quads for the | ||||
|        * component. | ||||
|        *  | ||||
|        * @param alignment The alignment of this component. | ||||
|        * @param ctx The canvas to add the quads to. | ||||
|        */ | ||||
|       virtual void getSelfQuads(UICanvas &ctx); | ||||
|  | ||||
|     public: | ||||
|       /** | ||||
|        * Overrided method by the UI Element that requests the minimum  | ||||
|        * width of the content. | ||||
|        *  | ||||
|        * @return The minimum width of the content. | ||||
|        */ | ||||
|       virtual float_t getContentWidth(); | ||||
|  | ||||
|       /** | ||||
|        * Overrided method by the UI Element that requests the minimum  | ||||
|        * height of the content. | ||||
|        *  | ||||
|        * @return The minimum height of the content. | ||||
|        */ | ||||
|       virtual float_t getContentHeight(); | ||||
|  | ||||
|       /** | ||||
|        * Returns the width of this component. | ||||
|        *  | ||||
|        * @return The width of this component. | ||||
|        */ | ||||
|       virtual float_t getWidth(); | ||||
|  | ||||
|       /** | ||||
|        * Returns the height of this component. | ||||
|        *  | ||||
|        * @return The height of this component. | ||||
|        */ | ||||
|       virtual float_t getHeight(); | ||||
|  | ||||
|       /** | ||||
|        * Virtual method overridden by the UIElement to get the children of | ||||
|        * this component. | ||||
|        */ | ||||
|       virtual std::vector<std::shared_ptr<UIElement>> getChildren(); | ||||
|  | ||||
|       /** | ||||
|        * Method called by the UICanvas to get the quads for this component. | ||||
|        *  | ||||
|        * @param ctx The canvas to add the quads to. | ||||
|        */ | ||||
|       void getQuads(UICanvas &ctx); | ||||
|  | ||||
|       /** | ||||
|        * Updates the alignment of this component based on the parent. Typically | ||||
|        * left to the UIAlignableElement to implement, default implementation | ||||
|        * does nothing but invoke children. | ||||
|        *  | ||||
|        * @param parentPosition The position of the parent. | ||||
|        * @param parentSize The size of the parent. | ||||
|        */ | ||||
|       virtual void updateAlignment( | ||||
|         const glm::vec2 parentPosition, | ||||
|         const glm::vec2 parentSize, | ||||
|         const float_t canvasScale | ||||
|       ); | ||||
|   }; | ||||
| } | ||||
| @@ -1,50 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "UIMenu.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void UIMenu::setPosition(int32_t x, int32_t y) { | ||||
|   assertTrue(x >= 0, "X position must be greater than or equal to 0."); | ||||
|   assertTrue(y >= 0, "Y position must be greater than or equal to 0."); | ||||
|   assertTrue(x < columns, "X must be less than the number of columns."); | ||||
|   assertTrue(y < rows, "Y must be less than the number of rows."); | ||||
|  | ||||
|   if(this->x == x && this->y == y) return; | ||||
|  | ||||
|   this->x = x; | ||||
|   this->y = y; | ||||
|  | ||||
|   eventPositionChanged.emit(x, y); | ||||
| } | ||||
|  | ||||
| void UIMenu::setSize(int32_t columns, int32_t rows) { | ||||
|   assertTrue(columns > 0, "Columns must be greater than 0."); | ||||
|   assertTrue(rows > 0, "Rows must be greater than 0."); | ||||
|   assertTrue(columns > x, "Columns must be greater than current x position."); | ||||
|   assertTrue(rows > y, "Rows must be greater than current y position."); | ||||
|  | ||||
|   if(this->columns == columns && this->rows == rows) return; | ||||
|  | ||||
|   this->columns = columns; | ||||
|   this->rows = rows; | ||||
| } | ||||
|  | ||||
| int32_t UIMenu::getX() { | ||||
|   return x; | ||||
| } | ||||
|  | ||||
| int32_t UIMenu::getY() { | ||||
|   return y; | ||||
| } | ||||
|  | ||||
| int32_t UIMenu::getColumns() { | ||||
|   return columns; | ||||
| } | ||||
|  | ||||
| int32_t UIMenu::getRows() { | ||||
|   return rows; | ||||
| } | ||||
| @@ -1,64 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "ui/UIElement.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class UIMenu final : public UIElement { | ||||
|     private: | ||||
|       int32_t x = 0; | ||||
|       int32_t y = 0; | ||||
|       int32_t columns = 1; | ||||
|       int32_t rows = 1; | ||||
|  | ||||
|     public: | ||||
|       Event<int32_t, int32_t> eventPositionChanged; | ||||
|  | ||||
|       /** | ||||
|        * Sets the position of this menu. | ||||
|        *  | ||||
|        * @param x The x position of this menu. | ||||
|        * @param y The y position of this menu. | ||||
|        */ | ||||
|       void setPosition(int32_t x, int32_t y); | ||||
|  | ||||
|       /** | ||||
|        * Sets the size of this menu. | ||||
|        *  | ||||
|        * @param columns The number of columns in this menu. | ||||
|        * @param rows The number of rows in this menu. | ||||
|        */ | ||||
|       void setSize(int32_t columns, int32_t rows); | ||||
|  | ||||
|       /** | ||||
|        * Gets the x position of this menu. | ||||
|        *  | ||||
|        * @return The x position of this menu. | ||||
|        */ | ||||
|       int32_t getX(); | ||||
|  | ||||
|       /** | ||||
|        * Gets the y position of this menu. | ||||
|        *  | ||||
|        * @return The y position of this menu. | ||||
|        */ | ||||
|       int32_t getY(); | ||||
|  | ||||
|       /** | ||||
|        * Gets the number of columns in this menu. | ||||
|        *  | ||||
|        * @return The number of columns in this menu. | ||||
|        */ | ||||
|       int32_t getColumns(); | ||||
|  | ||||
|       /** | ||||
|        * Gets the number of rows in this menu. | ||||
|        *  | ||||
|        * @return The number of rows in this menu. | ||||
|        */ | ||||
|       int32_t getRows(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,68 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "UISubAlignableElement.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void UISubAlignableElement::updateAlignment( | ||||
|   const glm::vec2 parentPosition, | ||||
|   const glm::vec2 parentSize, | ||||
|   const float_t canvasScale | ||||
| ) { | ||||
|   UIAlignableElement::updateAlignment(parentPosition, parentSize, canvasScale); | ||||
|    | ||||
|   switch(this->subAlignX) { | ||||
|     case UISubAlignment::START: | ||||
|       this->subAlignedPosition.x = this->position.x; | ||||
|       break; | ||||
|      | ||||
|     case UISubAlignment::MIDDLE: | ||||
|       this->subAlignedPosition.x = ( | ||||
|         this->position.x + | ||||
|         (this->size.x / 2.0f) - | ||||
|         (this->getContentWidth() / 2.0f) | ||||
|       ); | ||||
|       break; | ||||
|  | ||||
|     case UISubAlignment::END: | ||||
|       this->subAlignedPosition.x = ( | ||||
|         this->position.x + | ||||
|         this->size.x - | ||||
|         this->getContentWidth() | ||||
|       ); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       assertUnreachable("Unknown UISubAlignment!"); | ||||
|   } | ||||
|  | ||||
|   switch(this->subAlignY) { | ||||
|     case UISubAlignment::START: | ||||
|       this->subAlignedPosition.y = this->position.y; | ||||
|       break; | ||||
|      | ||||
|     case UISubAlignment::MIDDLE: | ||||
|       this->subAlignedPosition.y = ( | ||||
|         this->position.y + | ||||
|         (this->size.y / 2.0f) - | ||||
|         (this->getContentHeight() / 2.0f) | ||||
|       ); | ||||
|       break; | ||||
|  | ||||
|     case UISubAlignment::END: | ||||
|       this->subAlignedPosition.y = ( | ||||
|         this->position.y + | ||||
|         this->size.y - | ||||
|         this->getContentHeight() | ||||
|       ); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       assertUnreachable("Unknown UISubAlignment!"); | ||||
|   } | ||||
|  | ||||
|   this->eventSubAlignmentUpdated.emit(this->subAlignedPosition); | ||||
| } | ||||
| @@ -1,32 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "ui/UIAlignableElement.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   enum class UISubAlignment { | ||||
|     START, | ||||
|     MIDDLE, | ||||
|     END | ||||
|   }; | ||||
|  | ||||
|   class UISubAlignableElement : public UIAlignableElement { | ||||
|     protected: | ||||
|       glm::vec2 subAlignedPosition; | ||||
|  | ||||
|     public: | ||||
|       Event<glm::vec2> eventSubAlignmentUpdated; | ||||
|  | ||||
|       enum UISubAlignment subAlignX = UISubAlignment::START; | ||||
|       enum UISubAlignment subAlignY = UISubAlignment::START; | ||||
|  | ||||
|       void updateAlignment( | ||||
|         const glm::vec2 parentPosition, | ||||
|         const glm::vec2 parentSize, | ||||
|         const float_t canvasScale | ||||
|       ) override; | ||||
|   }; | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| # Copyright (c) 2023 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     UIColumnContainer.cpp | ||||
|     UIContainer.cpp | ||||
|     UIPaddingContainer.cpp | ||||
|     UIRowContainer.cpp | ||||
| ) | ||||
| @@ -1,36 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "assert/assert.hpp" | ||||
| #include "UIColumnContainer.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void UIColumnContainer::updateAlignment( | ||||
|   const glm::vec2 parentPosition, | ||||
|   const glm::vec2 parentSize, | ||||
|   const float_t canvasScale | ||||
| ) { | ||||
|   this->updateSelfAlignment(parentPosition, parentSize, canvasScale); | ||||
|  | ||||
|   // Now we have our dimensions, divide evenly | ||||
|   auto children = this->getChildren(); | ||||
|  | ||||
|   float_t x = 0.0f; | ||||
|   float_t xPiece = this->size.x / (float_t)children.size(); | ||||
|    | ||||
|   // Update all children | ||||
|   for(auto &child : children) { | ||||
|     child->updateAlignment( | ||||
|       this->position + glm::vec2(x, 0), | ||||
|       glm::vec2( | ||||
|         xPiece, | ||||
|         this->size.y | ||||
|       ), | ||||
|       canvasScale | ||||
|     ); | ||||
|     x += xPiece; | ||||
|   } | ||||
| } | ||||
| @@ -1,18 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "ui/container/UIContainer.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class UIColumnContainer final : public UIContainer { | ||||
|     public: | ||||
|       void updateAlignment( | ||||
|         const glm::vec2 parentPosition, | ||||
|         const glm::vec2 parentSize, | ||||
|         const float_t canvasScale | ||||
|       ) override; | ||||
|   }; | ||||
| } | ||||
| @@ -1,47 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "assert/assert.hpp" | ||||
| #include "UIContainer.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| std::vector<std::shared_ptr<UIElement>> UIContainer::getChildren() { | ||||
|   return this->children; | ||||
| } | ||||
|  | ||||
| float_t UIContainer::getContentWidth() { | ||||
|   float_t width = 0; | ||||
|   auto children = this->getChildren(); | ||||
|   for(auto child : children) { | ||||
|     width = Math::max(width, child->getWidth()); | ||||
|   } | ||||
|   return width; | ||||
| } | ||||
|  | ||||
| float_t UIContainer::getContentHeight() { | ||||
|   float_t height = 0; | ||||
|   auto children = this->getChildren(); | ||||
|   for(auto child : children) { | ||||
|     height = Math::max(height, child->getHeight()); | ||||
|   } | ||||
|   return height; | ||||
| } | ||||
|  | ||||
| void UIContainer::appendChild(std::shared_ptr<UIElement> child) { | ||||
|   assertNotNull(child, "Cannot append a null child!"); | ||||
|   this->children.push_back(child); | ||||
| } | ||||
|  | ||||
| void UIContainer::removeChild(std::shared_ptr<UIElement> child) { | ||||
|   assertNotNull(child, "Cannot remove a null child!"); | ||||
|   auto it = std::find(this->children.begin(), this->children.end(), child); | ||||
|   if(it == this->children.end()) return; | ||||
|   this->children.erase(it); | ||||
| } | ||||
|  | ||||
| void UIContainer::clearChildren() { | ||||
|   this->children.clear(); | ||||
| } | ||||
| @@ -1,39 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "ui/UIAlignableElement.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class UIContainer : public UIAlignableElement { | ||||
|     private: | ||||
|       std::vector<std::shared_ptr<UIElement>> children; | ||||
|  | ||||
|     public: | ||||
|       std::vector<std::shared_ptr<UIElement>> getChildren() override; | ||||
|  | ||||
|       float_t getContentWidth() override; | ||||
|       float_t getContentHeight() override; | ||||
|        | ||||
|       /** | ||||
|        * Appends a child to this container. | ||||
|        *  | ||||
|        * @param child Child to append. | ||||
|        */ | ||||
|       void appendChild(std::shared_ptr<UIElement> child); | ||||
|  | ||||
|       /** | ||||
|        * Removes a child from this container. | ||||
|        *  | ||||
|        * @param child Child to remove. | ||||
|        */ | ||||
|       void removeChild(std::shared_ptr<UIElement> child); | ||||
|  | ||||
|       /** | ||||
|        * Removes all children from this container. | ||||
|        */ | ||||
|       void clearChildren(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,38 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "UIPaddingContainer.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| float_t UIPaddingContainer::getContentWidth() { | ||||
|   float_t width = 0.0f; | ||||
|   for(auto &child : getChildren()) { | ||||
|     width = Math::max(width, child->getWidth()); | ||||
|   } | ||||
|   return width + padding.x + padding.z; | ||||
| } | ||||
|  | ||||
| float_t UIPaddingContainer::getContentHeight() { | ||||
|   float_t height = 0.0f; | ||||
|   for(auto &child : getChildren()) { | ||||
|     height = Math::max(height, child->getHeight()); | ||||
|   } | ||||
|   return height + padding.y + padding.w; | ||||
| } | ||||
|  | ||||
| void UIPaddingContainer::updateAlignment( | ||||
|   const glm::vec2 parentPosition, | ||||
|   const glm::vec2 parentSize, | ||||
|   const float_t canvasScale | ||||
| ) { | ||||
|   glm::vec2 childPosition = parentPosition + glm::vec2(padding.x, padding.y); | ||||
|   glm::vec2 childSize = parentSize - glm::vec2(padding.x + padding.z, padding.y + padding.w); | ||||
|  | ||||
|   auto children = getChildren(); | ||||
|   for(auto &child : children) { | ||||
|     child->updateAlignment(childPosition, childSize, canvasScale); | ||||
|   } | ||||
| } | ||||
| @@ -1,22 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "ui/container/UIContainer.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class UIPaddingContainer final : public UIContainer { | ||||
|     public: | ||||
|       glm::vec4 padding = { 0, 0, 0, 0 }; | ||||
|  | ||||
|       float_t getContentWidth() override; | ||||
|       float_t getContentHeight() override; | ||||
|       void updateAlignment( | ||||
|         const glm::vec2 parentPosition, | ||||
|         const glm::vec2 parentSize, | ||||
|         const float_t canvasScale | ||||
|       ) override; | ||||
|   }; | ||||
| } | ||||
| @@ -1,51 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "UIRowContainer.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| float_t UIRowContainer::getContentWidth() { | ||||
|   float_t width = 0.0f; | ||||
|   for(auto &child : this->getChildren()) { | ||||
|     width = Math::max(width, child->getWidth()); | ||||
|   } | ||||
|   return width; | ||||
| } | ||||
|  | ||||
| float_t UIRowContainer::getContentHeight() { | ||||
|   float_t height = 0.0f; | ||||
|   for(auto &child : this->getChildren()) { | ||||
|     height += child->getHeight(); | ||||
|   } | ||||
|   return height; | ||||
| } | ||||
|  | ||||
| void UIRowContainer::updateAlignment( | ||||
|   const glm::vec2 parentPosition, | ||||
|   const glm::vec2 parentSize, | ||||
|   const float_t canvasScale | ||||
| ) { | ||||
|   this->updateSelfAlignment(parentPosition, parentSize, canvasScale); | ||||
|  | ||||
|   // Now we have our dimensions, divide evenly | ||||
|   auto children = this->getChildren(); | ||||
|  | ||||
|   float_t y = 0.0f; | ||||
|   float_t yPiece = this->size.y / (float_t)children.size(); | ||||
|    | ||||
|   // Update all children | ||||
|   for(auto &child : children) { | ||||
|     child->updateAlignment( | ||||
|       this->position + glm::vec2(0, y), | ||||
|       glm::vec2( | ||||
|         this->size.x, | ||||
|         yPiece | ||||
|       ), | ||||
|       canvasScale | ||||
|     ); | ||||
|     y += yPiece; | ||||
|   } | ||||
| } | ||||
| @@ -1,20 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "ui/container/UIContainer.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class UIRowContainer final : public UIContainer { | ||||
|     public: | ||||
|       float_t getContentWidth() override; | ||||
|       float_t getContentHeight() override; | ||||
|       void updateAlignment( | ||||
|         const glm::vec2 parentPosition, | ||||
|         const glm::vec2 parentSize, | ||||
|         const float_t canvasScale | ||||
|       ) override; | ||||
|   }; | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| # Copyright (c) 2023 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     UILabel.cpp | ||||
|     UIRectangle.cpp | ||||
| ) | ||||
| @@ -1,175 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "UILabel.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void UILabel::getSelfQuads(UICanvas &ctx) { | ||||
|   std::vector<struct UIShaderQuad> quads; | ||||
|   if(this->texture == nullptr || this->text.empty()) return; | ||||
|  | ||||
|   glm::vec4 quad; | ||||
|   glm::vec2 pos = glm::vec2(0, this->texture->fontSize); | ||||
|   bool_t lastCharWasSpace = false; | ||||
|  | ||||
|   for(size_t i = 0; i < text.size(); i++) { | ||||
|     wchar_t c = text[i]; | ||||
|     auto info = texture->getCharacterData(c); | ||||
|  | ||||
|     // Newline(s) | ||||
|     if(c == L'\n') { | ||||
|       pos.x = 0; | ||||
|       pos.y += this->texture->fontSize; | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     // Spaces | ||||
|     if(c == L' ') { | ||||
|       pos.x += info.advance.x; | ||||
|       lastCharWasSpace = true; | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     // Word Wrap | ||||
|     if(wordWrap) { | ||||
|       if(lastCharWasSpace) { | ||||
|         // Scan ahead to next space | ||||
|         float_t wordWidth = pos.x;// Start at current position and scan ahead. | ||||
|         for(size_t j = i; j < text.size(); j++) { | ||||
|           wchar_t c2 = text[j]; | ||||
|           if(c2 == L' ' || c2 == L'\n') { | ||||
|             break;// If we hit another space, we are OK. | ||||
|           } | ||||
|  | ||||
|           // Will this character fit on the row? If not the whole word will wrap. | ||||
|           auto info2 = texture->getCharacterData(c); | ||||
|           wordWidth += info.advance.x; | ||||
|           if(wordWidth > size.x) { | ||||
|             pos.x = 0; | ||||
|             pos.y += this->texture->fontSize; | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         lastCharWasSpace = false; | ||||
|       } | ||||
|     // } else if(pos.x + info.size.x > subAlignedPosition.x + size.x) { | ||||
|     //   // Not word wrap, but instead just overflow characters. | ||||
|     //   pos.x = 0; | ||||
|     //   pos.y += this->texture->fontSize; | ||||
|     } | ||||
|  | ||||
|     ctx.addQuad( | ||||
|       { | ||||
|         subAlignedPosition.x + pos.x + info.offset.x, | ||||
|         subAlignedPosition.y + pos.y + info.offset.y, | ||||
|         subAlignedPosition.x + pos.x + info.size.x + info.offset.x, | ||||
|         subAlignedPosition.y + pos.y + info.size.y + info.offset.y | ||||
|       }, | ||||
|       { | ||||
|         info.quad.x, | ||||
|         info.quad.y, | ||||
|         info.quad.z, | ||||
|         info.quad.w | ||||
|       }, | ||||
|       this->color, | ||||
|       UIShaderQuadStyle::FONT, | ||||
|       texture->texture | ||||
|     ); | ||||
|     pos += info.advance; | ||||
|   } | ||||
| } | ||||
|  | ||||
| float_t UILabel::getContentWidth() { | ||||
|   if(this->texture == nullptr || this->text.empty()) return 0.0f; | ||||
|  | ||||
|   float_t lineWidth = 0.0f; | ||||
|   float_t width = 0.0f; | ||||
|   for(wchar_t c : text) { | ||||
|     if(c == L'\n') { | ||||
|       width = Math::max<float_t>(width, lineWidth); | ||||
|       lineWidth = 0.0f; | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     auto info = texture->getCharacterData(c); | ||||
|     lineWidth += info.advance.x; | ||||
|     if( | ||||
|       this->hasExplicitWidth() && | ||||
|       lineWidth >= size.x | ||||
|     ) return size.x; | ||||
|   } | ||||
|   width = Math::max<float_t>(width, lineWidth); | ||||
|   return width; | ||||
| } | ||||
|  | ||||
| float_t UILabel::getContentHeight() { | ||||
|   if(this->texture == nullptr || this->text.empty()) return 0.0f; | ||||
|  | ||||
|   float_t height = this->texture->fontSize; | ||||
|   float_t lineWidth = 0.0f; | ||||
|   bool_t lastCharWasSpace = false; | ||||
|  | ||||
|   for(wchar_t c : text) { | ||||
|     if(c == L'\n') { | ||||
|       height += this->texture->fontSize; | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     auto info = texture->getCharacterData(c); | ||||
|  | ||||
|     if(c == L' ') { | ||||
|       lineWidth += info.advance.x; | ||||
|       lastCharWasSpace = true; | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     if(wordWrap) { | ||||
|       if(lastCharWasSpace) { | ||||
|         // Scan ahead to next space | ||||
|         float_t wordWidth = lineWidth;// Start at current position and scan ahead. | ||||
|         for(size_t j = 0; j < text.size(); j++) { | ||||
|           wchar_t c2 = text[j]; | ||||
|           if(c2 == L' ' || c2 == L'\n') { | ||||
|             break;// If we hit another space, we are OK. | ||||
|           } | ||||
|  | ||||
|           // Will this character fit on the row? If not the whole word will wrap. | ||||
|           auto info2 = texture->getCharacterData(c); | ||||
|           wordWidth += info.advance.x; | ||||
|           if(wordWidth > size.x) { | ||||
|             height += this->texture->fontSize; | ||||
|             lineWidth = 0.0f; | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         lastCharWasSpace = false; | ||||
|       } | ||||
|     // } else if(lineWidth + info.size.x > size.x) { | ||||
|     //   height += this->texture->fontSize; | ||||
|     //   lineWidth = 0.0f; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return height; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<TrueTypeTexture> UILabel::getFont() { | ||||
|   return this->texture; | ||||
| } | ||||
|  | ||||
| std::wstring UILabel::getText() { | ||||
|   return this->text; | ||||
| } | ||||
|  | ||||
| void UILabel::setFont(std::shared_ptr<TrueTypeTexture> texture) { | ||||
|   this->texture = texture; | ||||
| } | ||||
|  | ||||
| void UILabel::setText(const std::wstring &text) { | ||||
|   this->text = text; | ||||
| } | ||||
| @@ -1,54 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "ui/UISubAlignableElement.hpp" | ||||
| #include "display/font/TrueTypeTexture.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class UILabel final : public UISubAlignableElement { | ||||
|     private: | ||||
|       std::shared_ptr<TrueTypeTexture> texture = nullptr; | ||||
|       std::wstring text = L"Hello World"; | ||||
|  | ||||
|     protected: | ||||
|       void getSelfQuads(UICanvas &ctx) override; | ||||
|  | ||||
|     public: | ||||
|       bool_t wordWrap = true; | ||||
|       struct Color color = COLOR_WHITE; | ||||
|  | ||||
|       float_t getContentWidth() override; | ||||
|       float_t getContentHeight() override; | ||||
|  | ||||
|       /** | ||||
|        * Returns the font used for this label. | ||||
|        *  | ||||
|        * @return The font used for this label. | ||||
|        */ | ||||
|       std::shared_ptr<TrueTypeTexture> getFont(); | ||||
|  | ||||
|       /** | ||||
|        * Returns the text used for this label. | ||||
|        *  | ||||
|        * @return The text used for this label. | ||||
|        */ | ||||
|       std::wstring getText(); | ||||
|  | ||||
|       /** | ||||
|        * Sets the font to use for this label. | ||||
|        *  | ||||
|        * @param texture TrueType texture to use for this label. | ||||
|        */ | ||||
|       void setFont(std::shared_ptr<TrueTypeTexture> texture); | ||||
|  | ||||
|       /** | ||||
|        * Sets the text to use for this label. | ||||
|        *  | ||||
|        * @param text The text to use for this label. | ||||
|        */ | ||||
|       void setText(const std::wstring &text); | ||||
|   }; | ||||
| } | ||||
| @@ -1,19 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "UIRectangle.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void UIRectangle::getSelfQuads(UICanvas &ctx) { | ||||
|   std::vector<struct UIShaderQuad> quads; | ||||
|   ctx.addQuad( | ||||
|     glm::vec4(position, position + size), | ||||
|     uv, | ||||
|     color, | ||||
|     UIShaderQuadStyle::TEXTURED, | ||||
|     texture | ||||
|   ); | ||||
| } | ||||
| @@ -1,19 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "ui/UIAlignableElement.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class UIRectangle final : public UIAlignableElement { | ||||
|     protected: | ||||
|       void getSelfQuads(UICanvas &ctx) override; | ||||
|  | ||||
|     public: | ||||
|       struct Color color = COLOR_WHITE; | ||||
|       std::shared_ptr<Texture> texture = nullptr; | ||||
|       glm::vec4 uv = glm::vec4(0,0,1,1); | ||||
|   }; | ||||
| } | ||||
| @@ -1,42 +0,0 @@ | ||||
| { | ||||
|   "main_menu": { | ||||
|     "new_game": "New Game", | ||||
|     "load_game": "Load Game", | ||||
|     "options": "Options", | ||||
|     "exit": "Exit" | ||||
|   }, | ||||
|   "tiles": { | ||||
|     "water": { | ||||
|       "interact": "A refreshing body of water." | ||||
|     }, | ||||
|     "lamp": { | ||||
|       "interact": "An electric lamp.\nA real lightbulb idea." | ||||
|     }, | ||||
|     "rail": { | ||||
|       "interact": "Train tracks.\n...Better not cross them." | ||||
|     } | ||||
|   }, | ||||
|   "entities": { | ||||
|     "sign": { | ||||
|       "name": "Sign" | ||||
|     } | ||||
|   }, | ||||
|   "maps": { | ||||
|     "testmap": { | ||||
|       "bob": "Hello, I am Bob.", | ||||
|       "sign": "This is a sign.", | ||||
|       "sign2": { | ||||
|         "1": "This is another sign.", | ||||
|         "2": "It has two lines." | ||||
|       } | ||||
|     }, | ||||
|     "train_station": { | ||||
|       "stair_sign": { | ||||
|         "0": "Stairs slippery when wet.\n\n<- West to Town.\n-> East to lakefront." | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   "battle": { | ||||
|     "start": "Battle Start!" | ||||
|   } | ||||
| } | ||||
| @@ -1,8 +0,0 @@ | ||||
| { | ||||
|   "name": "Test Map", | ||||
|   "layers": [ | ||||
|     { | ||||
|  | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| @@ -1,8 +0,0 @@ | ||||
| { | ||||
|   "assets": { | ||||
|     "simpleTexturedShader": { | ||||
|       "type": "shader", | ||||
|       "path": "shaders/simple-textured.shader" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1,26 +0,0 @@ | ||||
| { | ||||
|   "name": "Rosa", | ||||
|    | ||||
|   "assets": { | ||||
|     "rosa": { | ||||
|       "type": "texture", | ||||
|       "path": "rosa.texture" | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   "components": { | ||||
|     "mesh": { | ||||
|       "type": "QuadMesh" | ||||
|     }, | ||||
|     "material": { | ||||
|       "type": "SimpleTexturedMaterial", | ||||
|       "texture": "rosa" | ||||
|     }, | ||||
|     "meshRenderer": { | ||||
|       "type": "MeshRenderer" | ||||
|     }, | ||||
|     "entity": { | ||||
|       "type": "RPGEntity" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1,29 +0,0 @@ | ||||
| { | ||||
|   "name": "Rosa", | ||||
|    | ||||
|   "assets": { | ||||
|     "rosa": { | ||||
|       "type": "texture", | ||||
|       "path": "rosa.texture" | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   "components": { | ||||
|     "mesh": { | ||||
|       "type": "QuadMesh" | ||||
|     }, | ||||
|     "material": { | ||||
|       "type": "SimpleTexturedMaterial", | ||||
|       "texture": "rosa" | ||||
|     }, | ||||
|     "meshRenderer": { | ||||
|       "type": "MeshRenderer" | ||||
|     }, | ||||
|     "entity": { | ||||
|       "type": "RPGEntity" | ||||
|     }, | ||||
|     "player": { | ||||
|       "type": "RPGPlayer" | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/rosa.png
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/rosa.png
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.5 KiB | 
| @@ -1,47 +0,0 @@ | ||||
| { | ||||
|   "name": "Test RPG Scene", | ||||
|    | ||||
|   "assets": { | ||||
|     "rosa": { | ||||
|       "type": "prefab", | ||||
|       "path": "prefabs/rosa.json" | ||||
|     }, | ||||
|     "npc": { | ||||
|       "type": "prefab", | ||||
|       "path": "prefabs/npc.json" | ||||
|     }, | ||||
|     "rosatext": { | ||||
|       "type": "texture", | ||||
|       "path": "rosa.texture" | ||||
|     }, | ||||
|     "simpleTexturedShader": { | ||||
|       "type": "shader", | ||||
|       "path": "shaders/simple-textured.slang" | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   "items": { | ||||
|     "camera": { | ||||
|       "components": { | ||||
|         "camera": { | ||||
|           "type": "camera" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     "rosa": { | ||||
|       "prefab": "rosa", | ||||
|       "position": [ 0, 0, 0 ], | ||||
|       "components": { | ||||
|         "player": { | ||||
|           "camera": "camera" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     "npc": { | ||||
|       "prefab": "npc", | ||||
|       "position": [ 32, 0, 0 ] | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1,53 +0,0 @@ | ||||
| uniform float4x4 projection; | ||||
| uniform float4x4 view; | ||||
| uniform float4x4 model; | ||||
| uniform float4 color; | ||||
| uniform bool hasTexture; | ||||
| uniform Sampler2D texture; | ||||
|  | ||||
| struct AssembledVertex { | ||||
|   float3 position : POSITION; | ||||
|   float2 texcoord : TEXCOORD; | ||||
| }; | ||||
|  | ||||
| struct Fragment { | ||||
|   float4 color; | ||||
| }; | ||||
|  | ||||
| struct VertexStageOutput { | ||||
|   float2 uv : UV; | ||||
|   float4 sv_position : SV_Position; | ||||
| }; | ||||
|  | ||||
| [shader("vertex")] | ||||
| VertexStageOutput vertexMain( | ||||
|   AssembledVertex assembledVertex | ||||
| ) { | ||||
|   VertexStageOutput output; | ||||
|  | ||||
|   float3 position = assembledVertex.position; | ||||
|  | ||||
|   output.uv = assembledVertex.texcoord; | ||||
|  | ||||
|   output.sv_position = mul( | ||||
|     float4(position, 1.0), | ||||
|     mul(model, mul(view, projection)) | ||||
|   ); | ||||
|  | ||||
|   return output; | ||||
| } | ||||
|  | ||||
| [shader("fragment")] | ||||
| Fragment fragmentMain( | ||||
|   float2 uv: UV | ||||
| ) : SV_Target { | ||||
|   Fragment output; | ||||
|    | ||||
|   if (hasTexture) { | ||||
|     output.color = texture.Sample(uv) * color; | ||||
|   } else { | ||||
|     output.color = color; | ||||
|   } | ||||
|    | ||||
|   return output; | ||||
| } | ||||
| @@ -1,74 +0,0 @@ | ||||
| # Copyright (c) 2021 Dominic Msters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| include(FetchContent) | ||||
|  | ||||
| # GLFW | ||||
| FetchContent_Declare(glfw URL https://github.com/glfw/glfw/releases/download/3.4/glfw-3.4.zip) | ||||
| FetchContent_MakeAvailable(glfw) | ||||
|  | ||||
| add_subdirectory(glad) | ||||
|  | ||||
| # GLM | ||||
| FetchContent_Declare( | ||||
|   glm | ||||
|   GIT_REPOSITORY  https://github.com/g-truc/glm | ||||
|   GIT_TAG         0af55ccecd98d4e5a8d1fad7de25ba429d60e863 | ||||
| ) | ||||
| FetchContent_MakeAvailable(glm) | ||||
|  | ||||
| # FreeType | ||||
| FetchContent_Declare( | ||||
|   freetype | ||||
|   GIT_REPOSITORY  https://gitlab.freedesktop.org/freetype/freetype | ||||
|   GIT_TAG         VER-2-13-3 | ||||
| ) | ||||
| FetchContent_MakeAvailable(freetype) | ||||
|  | ||||
| #LibArchive | ||||
| FetchContent_Declare( | ||||
|   libarchive | ||||
|   GIT_REPOSITORY https://github.com/libarchive/libarchive | ||||
|   GIT_TAG        v3.7.6 | ||||
| ) | ||||
| FetchContent_MakeAvailable(libarchive) | ||||
|  | ||||
| # JSON | ||||
| FetchContent_Declare( | ||||
|   json | ||||
|   URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz | ||||
| ) | ||||
| FetchContent_MakeAvailable(json) | ||||
|  | ||||
| # JOLT Physics | ||||
| if(DAWN_ENABLE_PHYSICS) | ||||
|   FetchContent_Declare( | ||||
|     JoltPhysics | ||||
|     GIT_REPOSITORY "https://github.com/jrouwe/JoltPhysics" | ||||
|     GIT_TAG "v5.2.0" | ||||
|     SOURCE_SUBDIR "Build" | ||||
|   ) | ||||
|   FetchContent_MakeAvailable(JoltPhysics) | ||||
| endif() | ||||
|  | ||||
| # SLANG | ||||
| set(SLANG_ENABLE_GFX ON CACHE BOOL "Enable GFX" FORCE) | ||||
| FetchContent_Declare( | ||||
|   slang | ||||
|   GIT_REPOSITORY https://github.com/shader-slang/slang | ||||
|   GIT_TAG v2024.17 | ||||
| ) | ||||
| FetchContent_MakeAvailable(slang) | ||||
|  | ||||
|  | ||||
| # OpenAL | ||||
| # if(DAWN_TARGET_OPENAL) | ||||
| #   set(LIBTYPE "STATIC") | ||||
| #   add_subdirectory(openal-soft) | ||||
|  | ||||
| #   set(BUILD_TESTS OFF CACHE BOOL "Build tests" FORCE) | ||||
| #   set(BUILD_EXAMPLES OFF CACHE BOOL "Build examples" FORCE)  | ||||
| #   add_subdirectory(AudioFile) | ||||
| # endif() | ||||
| @@ -1,12 +0,0 @@ | ||||
| cmake_minimum_required(VERSION 3.11) | ||||
| project(glad) | ||||
| set(CMAKE_C_STANDARD 99) | ||||
| set(CMAKE_C_STANDARD_REQUIRED ON) | ||||
|  | ||||
| add_library(${PROJECT_NAME} | ||||
|   src/glad.c | ||||
| ) | ||||
| target_include_directories(${PROJECT_NAME} | ||||
|   PUBLIC | ||||
|     ${CMAKE_CURRENT_SOURCE_DIR}/include | ||||
| ) | ||||
| @@ -1,311 +0,0 @@ | ||||
| #ifndef __khrplatform_h_ | ||||
| #define __khrplatform_h_ | ||||
|  | ||||
| /* | ||||
| ** Copyright (c) 2008-2018 The Khronos Group Inc. | ||||
| ** | ||||
| ** Permission is hereby granted, free of charge, to any person obtaining a | ||||
| ** copy of this software and/or associated documentation files (the | ||||
| ** "Materials"), to deal in the Materials without restriction, including | ||||
| ** without limitation the rights to use, copy, modify, merge, publish, | ||||
| ** distribute, sublicense, and/or sell copies of the Materials, and to | ||||
| ** permit persons to whom the Materials are furnished to do so, subject to | ||||
| ** the following conditions: | ||||
| ** | ||||
| ** The above copyright notice and this permission notice shall be included | ||||
| ** in all copies or substantial portions of the Materials. | ||||
| ** | ||||
| ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
| ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
| ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
| ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
| ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
| ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
| ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. | ||||
| */ | ||||
|  | ||||
| /* Khronos platform-specific types and definitions. | ||||
|  * | ||||
|  * The master copy of khrplatform.h is maintained in the Khronos EGL | ||||
|  * Registry repository at https://github.com/KhronosGroup/EGL-Registry | ||||
|  * The last semantic modification to khrplatform.h was at commit ID: | ||||
|  *      67a3e0864c2d75ea5287b9f3d2eb74a745936692 | ||||
|  * | ||||
|  * Adopters may modify this file to suit their platform. Adopters are | ||||
|  * encouraged to submit platform specific modifications to the Khronos | ||||
|  * group so that they can be included in future versions of this file. | ||||
|  * Please submit changes by filing pull requests or issues on | ||||
|  * the EGL Registry repository linked above. | ||||
|  * | ||||
|  * | ||||
|  * See the Implementer's Guidelines for information about where this file | ||||
|  * should be located on your system and for more details of its use: | ||||
|  *    http://www.khronos.org/registry/implementers_guide.pdf | ||||
|  * | ||||
|  * This file should be included as | ||||
|  *        #include <KHR/khrplatform.h> | ||||
|  * by Khronos client API header files that use its types and defines. | ||||
|  * | ||||
|  * The types in khrplatform.h should only be used to define API-specific types. | ||||
|  * | ||||
|  * Types defined in khrplatform.h: | ||||
|  *    khronos_int8_t              signed   8  bit | ||||
|  *    khronos_uint8_t             unsigned 8  bit | ||||
|  *    khronos_int16_t             signed   16 bit | ||||
|  *    khronos_uint16_t            unsigned 16 bit | ||||
|  *    khronos_int32_t             signed   32 bit | ||||
|  *    khronos_uint32_t            unsigned 32 bit | ||||
|  *    khronos_int64_t             signed   64 bit | ||||
|  *    khronos_uint64_t            unsigned 64 bit | ||||
|  *    khronos_intptr_t            signed   same number of bits as a pointer | ||||
|  *    khronos_uintptr_t           unsigned same number of bits as a pointer | ||||
|  *    khronos_ssize_t             signed   size | ||||
|  *    khronos_usize_t             unsigned size | ||||
|  *    khronos_float_t             signed   32 bit floating point | ||||
|  *    khronos_time_ns_t           unsigned 64 bit time in nanoseconds | ||||
|  *    khronos_utime_nanoseconds_t unsigned time interval or absolute time in | ||||
|  *                                         nanoseconds | ||||
|  *    khronos_stime_nanoseconds_t signed time interval in nanoseconds | ||||
|  *    khronos_boolean_enum_t      enumerated boolean type. This should | ||||
|  *      only be used as a base type when a client API's boolean type is | ||||
|  *      an enum. Client APIs which use an integer or other type for | ||||
|  *      booleans cannot use this as the base type for their boolean. | ||||
|  * | ||||
|  * Tokens defined in khrplatform.h: | ||||
|  * | ||||
|  *    KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. | ||||
|  * | ||||
|  *    KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. | ||||
|  *    KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. | ||||
|  * | ||||
|  * Calling convention macros defined in this file: | ||||
|  *    KHRONOS_APICALL | ||||
|  *    KHRONOS_APIENTRY | ||||
|  *    KHRONOS_APIATTRIBUTES | ||||
|  * | ||||
|  * These may be used in function prototypes as: | ||||
|  * | ||||
|  *      KHRONOS_APICALL void KHRONOS_APIENTRY funcname( | ||||
|  *                                  int arg1, | ||||
|  *                                  int arg2) KHRONOS_APIATTRIBUTES; | ||||
|  */ | ||||
|  | ||||
| #if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) | ||||
| #   define KHRONOS_STATIC 1 | ||||
| #endif | ||||
|  | ||||
| /*------------------------------------------------------------------------- | ||||
|  * Definition of KHRONOS_APICALL | ||||
|  *------------------------------------------------------------------------- | ||||
|  * This precedes the return type of the function in the function prototype. | ||||
|  */ | ||||
| #if defined(KHRONOS_STATIC) | ||||
|     /* If the preprocessor constant KHRONOS_STATIC is defined, make the | ||||
|      * header compatible with static linking. */ | ||||
| #   define KHRONOS_APICALL | ||||
| #elif defined(_WIN32) | ||||
| #   define KHRONOS_APICALL __declspec(dllimport) | ||||
| #elif defined (__SYMBIAN32__) | ||||
| #   define KHRONOS_APICALL IMPORT_C | ||||
| #elif defined(__ANDROID__) | ||||
| #   define KHRONOS_APICALL __attribute__((visibility("default"))) | ||||
| #else | ||||
| #   define KHRONOS_APICALL | ||||
| #endif | ||||
|  | ||||
| /*------------------------------------------------------------------------- | ||||
|  * Definition of KHRONOS_APIENTRY | ||||
|  *------------------------------------------------------------------------- | ||||
|  * This follows the return type of the function  and precedes the function | ||||
|  * name in the function prototype. | ||||
|  */ | ||||
| #if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) | ||||
|     /* Win32 but not WinCE */ | ||||
| #   define KHRONOS_APIENTRY __stdcall | ||||
| #else | ||||
| #   define KHRONOS_APIENTRY | ||||
| #endif | ||||
|  | ||||
| /*------------------------------------------------------------------------- | ||||
|  * Definition of KHRONOS_APIATTRIBUTES | ||||
|  *------------------------------------------------------------------------- | ||||
|  * This follows the closing parenthesis of the function prototype arguments. | ||||
|  */ | ||||
| #if defined (__ARMCC_2__) | ||||
| #define KHRONOS_APIATTRIBUTES __softfp | ||||
| #else | ||||
| #define KHRONOS_APIATTRIBUTES | ||||
| #endif | ||||
|  | ||||
| /*------------------------------------------------------------------------- | ||||
|  * basic type definitions | ||||
|  *-----------------------------------------------------------------------*/ | ||||
| #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Using <stdint.h> | ||||
|  */ | ||||
| #include <stdint.h> | ||||
| typedef int32_t                 khronos_int32_t; | ||||
| typedef uint32_t                khronos_uint32_t; | ||||
| typedef int64_t                 khronos_int64_t; | ||||
| typedef uint64_t                khronos_uint64_t; | ||||
| #define KHRONOS_SUPPORT_INT64   1 | ||||
| #define KHRONOS_SUPPORT_FLOAT   1 | ||||
| /* | ||||
|  * To support platform where unsigned long cannot be used interchangeably with | ||||
|  * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. | ||||
|  * Ideally, we could just use (u)intptr_t everywhere, but this could result in | ||||
|  * ABI breakage if khronos_uintptr_t is changed from unsigned long to | ||||
|  * unsigned long long or similar (this results in different C++ name mangling). | ||||
|  * To avoid changes for existing platforms, we restrict usage of intptr_t to | ||||
|  * platforms where the size of a pointer is larger than the size of long. | ||||
|  */ | ||||
| #if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) | ||||
| #if __SIZEOF_POINTER__ > __SIZEOF_LONG__ | ||||
| #define KHRONOS_USE_INTPTR_T | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #elif defined(__VMS ) || defined(__sgi) | ||||
|  | ||||
| /* | ||||
|  * Using <inttypes.h> | ||||
|  */ | ||||
| #include <inttypes.h> | ||||
| typedef int32_t                 khronos_int32_t; | ||||
| typedef uint32_t                khronos_uint32_t; | ||||
| typedef int64_t                 khronos_int64_t; | ||||
| typedef uint64_t                khronos_uint64_t; | ||||
| #define KHRONOS_SUPPORT_INT64   1 | ||||
| #define KHRONOS_SUPPORT_FLOAT   1 | ||||
|  | ||||
| #elif defined(_WIN32) && !defined(__SCITECH_SNAP__) | ||||
|  | ||||
| /* | ||||
|  * Win32 | ||||
|  */ | ||||
| typedef __int32                 khronos_int32_t; | ||||
| typedef unsigned __int32        khronos_uint32_t; | ||||
| typedef __int64                 khronos_int64_t; | ||||
| typedef unsigned __int64        khronos_uint64_t; | ||||
| #define KHRONOS_SUPPORT_INT64   1 | ||||
| #define KHRONOS_SUPPORT_FLOAT   1 | ||||
|  | ||||
| #elif defined(__sun__) || defined(__digital__) | ||||
|  | ||||
| /* | ||||
|  * Sun or Digital | ||||
|  */ | ||||
| typedef int                     khronos_int32_t; | ||||
| typedef unsigned int            khronos_uint32_t; | ||||
| #if defined(__arch64__) || defined(_LP64) | ||||
| typedef long int                khronos_int64_t; | ||||
| typedef unsigned long int       khronos_uint64_t; | ||||
| #else | ||||
| typedef long long int           khronos_int64_t; | ||||
| typedef unsigned long long int  khronos_uint64_t; | ||||
| #endif /* __arch64__ */ | ||||
| #define KHRONOS_SUPPORT_INT64   1 | ||||
| #define KHRONOS_SUPPORT_FLOAT   1 | ||||
|  | ||||
| #elif 0 | ||||
|  | ||||
| /* | ||||
|  * Hypothetical platform with no float or int64 support | ||||
|  */ | ||||
| typedef int                     khronos_int32_t; | ||||
| typedef unsigned int            khronos_uint32_t; | ||||
| #define KHRONOS_SUPPORT_INT64   0 | ||||
| #define KHRONOS_SUPPORT_FLOAT   0 | ||||
|  | ||||
| #else | ||||
|  | ||||
| /* | ||||
|  * Generic fallback | ||||
|  */ | ||||
| #include <stdint.h> | ||||
| typedef int32_t                 khronos_int32_t; | ||||
| typedef uint32_t                khronos_uint32_t; | ||||
| typedef int64_t                 khronos_int64_t; | ||||
| typedef uint64_t                khronos_uint64_t; | ||||
| #define KHRONOS_SUPPORT_INT64   1 | ||||
| #define KHRONOS_SUPPORT_FLOAT   1 | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Types that are (so far) the same on all platforms | ||||
|  */ | ||||
| typedef signed   char          khronos_int8_t; | ||||
| typedef unsigned char          khronos_uint8_t; | ||||
| typedef signed   short int     khronos_int16_t; | ||||
| typedef unsigned short int     khronos_uint16_t; | ||||
|  | ||||
| /* | ||||
|  * Types that differ between LLP64 and LP64 architectures - in LLP64, | ||||
|  * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears | ||||
|  * to be the only LLP64 architecture in current use. | ||||
|  */ | ||||
| #ifdef KHRONOS_USE_INTPTR_T | ||||
| typedef intptr_t               khronos_intptr_t; | ||||
| typedef uintptr_t              khronos_uintptr_t; | ||||
| #elif defined(_WIN64) | ||||
| typedef signed   long long int khronos_intptr_t; | ||||
| typedef unsigned long long int khronos_uintptr_t; | ||||
| #else | ||||
| typedef signed   long  int     khronos_intptr_t; | ||||
| typedef unsigned long  int     khronos_uintptr_t; | ||||
| #endif | ||||
|  | ||||
| #if defined(_WIN64) | ||||
| typedef signed   long long int khronos_ssize_t; | ||||
| typedef unsigned long long int khronos_usize_t; | ||||
| #else | ||||
| typedef signed   long  int     khronos_ssize_t; | ||||
| typedef unsigned long  int     khronos_usize_t; | ||||
| #endif | ||||
|  | ||||
| #if KHRONOS_SUPPORT_FLOAT | ||||
| /* | ||||
|  * Float type | ||||
|  */ | ||||
| typedef          float         khronos_float_t; | ||||
| #endif | ||||
|  | ||||
| #if KHRONOS_SUPPORT_INT64 | ||||
| /* Time types | ||||
|  * | ||||
|  * These types can be used to represent a time interval in nanoseconds or | ||||
|  * an absolute Unadjusted System Time.  Unadjusted System Time is the number | ||||
|  * of nanoseconds since some arbitrary system event (e.g. since the last | ||||
|  * time the system booted).  The Unadjusted System Time is an unsigned | ||||
|  * 64 bit value that wraps back to 0 every 584 years.  Time intervals | ||||
|  * may be either signed or unsigned. | ||||
|  */ | ||||
| typedef khronos_uint64_t       khronos_utime_nanoseconds_t; | ||||
| typedef khronos_int64_t        khronos_stime_nanoseconds_t; | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Dummy value used to pad enum types to 32 bits. | ||||
|  */ | ||||
| #ifndef KHRONOS_MAX_ENUM | ||||
| #define KHRONOS_MAX_ENUM 0x7FFFFFFF | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Enumerated boolean type | ||||
|  * | ||||
|  * Values other than zero should be considered to be true.  Therefore | ||||
|  * comparisons should not be made against KHRONOS_TRUE. | ||||
|  */ | ||||
| typedef enum { | ||||
|     KHRONOS_FALSE = 0, | ||||
|     KHRONOS_TRUE  = 1, | ||||
|     KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM | ||||
| } khronos_boolean_enum_t; | ||||
|  | ||||
| #endif /* __khrplatform_h_ */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1833
									
								
								lib/glad/src/glad.c
									
									
									
									
									
								
							
							
						
						
									
										1833
									
								
								lib/glad/src/glad.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,34 +0,0 @@ | ||||
| # Copyright (c) 2022 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| # Build Project | ||||
| add_executable(${DAWN_TARGET_NAME}) | ||||
|  | ||||
| # Validate game project includes the target name | ||||
| if(NOT DEFINED DAWN_TARGET_NAME) | ||||
|   message(FATAL_ERROR "You need to define a target name") | ||||
| endif() | ||||
|  | ||||
| # Add in base library | ||||
| add_subdirectory(dawn) | ||||
| add_subdirectory(dawnrpg) | ||||
|  | ||||
| if(DAWN_ENABLE_PHYSICS) | ||||
|   add_subdirectory(dawnphysics) | ||||
| endif() | ||||
|  | ||||
| # Host Libraries | ||||
| target_link_libraries(${DAWN_TARGET_NAME} | ||||
|   PUBLIC | ||||
|     ${DAWN_BUILD_HOST_LIBS} | ||||
| ) | ||||
|  | ||||
| # Compile support targets | ||||
| add_subdirectory(dawnglfw) | ||||
| add_subdirectory(dawnopengl) | ||||
| add_subdirectory(dawnlinux) | ||||
|  | ||||
| # Compress the game assets. | ||||
| add_dependencies(${DAWN_TARGET_NAME} dawnassets) | ||||
| @@ -1,48 +0,0 @@ | ||||
| # Copyright (c) 2022 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| # Libraries | ||||
| target_link_libraries(${DAWN_TARGET_NAME} | ||||
|   PUBLIC | ||||
|     archive_static | ||||
|     glm::glm | ||||
|     nlohmann_json::nlohmann_json | ||||
|     freetype | ||||
|     slang | ||||
| ) | ||||
|  | ||||
| # Includes | ||||
| target_include_directories(${DAWN_TARGET_NAME} | ||||
|   PUBLIC | ||||
|     ${CMAKE_CURRENT_LIST_DIR} | ||||
| ) | ||||
|  | ||||
| # Definitions | ||||
| target_compile_definitions(${DAWN_TARGET_NAME} | ||||
|   PUBLIC | ||||
|     DAWN_DEBUG_SHADERS=$<BOOL:${DAWN_DEBUG_SHADERS}> | ||||
| ) | ||||
|  | ||||
| # Subdirs | ||||
| add_subdirectory(assert) | ||||
| add_subdirectory(asset) | ||||
| add_subdirectory(audio) | ||||
| add_subdirectory(component) | ||||
| add_subdirectory(display) | ||||
| add_subdirectory(environment) | ||||
| add_subdirectory(game) | ||||
| add_subdirectory(locale) | ||||
| add_subdirectory(save) | ||||
| add_subdirectory(scene) | ||||
| add_subdirectory(settings) | ||||
| add_subdirectory(time) | ||||
| add_subdirectory(util) | ||||
|  | ||||
|  | ||||
| # Assets | ||||
| tool_copy(en en.json) | ||||
| tool_copy(simpleTexturedShader shaders/simple-textured.slang) | ||||
|  | ||||
| add_dependencies(${DAWN_TARGET_NAME} dawnassets) | ||||
| @@ -1,9 +0,0 @@ | ||||
| # Copyright (c) 2022 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     assert.cpp | ||||
| ) | ||||
| @@ -1,35 +0,0 @@ | ||||
| /** | ||||
|  * Copyright (c) 2022 Dominic Masters | ||||
|  *  | ||||
|  * This software is released under the MIT License. | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #include "assert.hpp" | ||||
|  | ||||
| void assertTrueImplement( | ||||
|   const char *file, | ||||
|   const int32_t line, | ||||
|   const char *func, | ||||
|   const bool_t result, | ||||
|   const char *message, | ||||
|   ... | ||||
| ) { | ||||
|   if(result) return; | ||||
|  | ||||
|   // Print file info. | ||||
|   fprintf( | ||||
|     stderr, | ||||
|     "Assert failed in %s:%i :: %s\n", | ||||
|     file, | ||||
|     line, | ||||
|     func | ||||
|   ); | ||||
|  | ||||
|   va_list argptr; | ||||
|   va_start(argptr, message); | ||||
|   vfprintf(stderr, message, argptr); | ||||
|   va_end(argptr); | ||||
|   fprintf(stderr, "\n"); | ||||
|   throw std::runtime_error("Assert failed."); | ||||
| } | ||||
| @@ -1,126 +0,0 @@ | ||||
| /** | ||||
|  * Copyright (c) 2022 Dominic Masters | ||||
|  *  | ||||
|  * This software is released under the MIT License. | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
| #include "util/Flag.hpp" | ||||
|  | ||||
| /** | ||||
|  * Asserts that a given statement must evaluate to true or the assertion fails | ||||
|  * and the game will close semi-gracefully. | ||||
|  *  | ||||
|  * @param file String filename of the file that has the assertion. | ||||
|  * @param line Integer line number within the file that the assertion is on. | ||||
|  * @param func Called function that has the assertion. | ||||
|  * @param result The statement that must equate to true. | ||||
|  * @param message Message (sprintf format) to send to the stdout. | ||||
|  * @param ... Varargs of the sprintf arguments. | ||||
|  */ | ||||
| void assertTrueImplement( | ||||
|   const char *file, | ||||
|   const int32_t line, | ||||
|   const char *func, | ||||
|   const bool_t result, | ||||
|   const char *message, | ||||
|   ... | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * Asserts that a statement must be true in order for the assertion to not cause | ||||
|  * an error. Basically this is a throw statement in disguise. | ||||
|  *  | ||||
|  * @param statement Statement of the assertion. | ||||
|  * @param message Message (sprintf format) to send to the logger. | ||||
|  * @param args Optional TParam args for the sprintf message to accept. | ||||
|  */ | ||||
| #define assertTrue(...) assertTrueImplement( \ | ||||
|   __FILE__, __LINE__, __func__, __VA_ARGS__  \ | ||||
| ) | ||||
|  | ||||
| /** | ||||
|  * Asserts that a statement must be false in order for the assertion to not | ||||
|  * cause an error. | ||||
|  *  | ||||
|  * @param statement Statement of the assertion. | ||||
|  * @param message Message (sprintf format) to send to the logger. | ||||
|  * @param args Optional TParam args for the sprintf message to accept. | ||||
|  */ | ||||
| #define assertFalse(x, ...) assertTrue(!(x), __VA_ARGS__) | ||||
|  | ||||
| /** | ||||
|  * Asserts that a specified piece of code should be entirely unreachable. | ||||
|  * @param message Message (sprintf format) to send to the logger. | ||||
|  * @param args Optional TParam args for the sprintf message to accept. | ||||
|  */ | ||||
| #define assertUnreachable(...) assertTrue(false, __VA_ARGS__) | ||||
|  | ||||
| /** | ||||
|  * Asserts that a given pointer is not null. | ||||
|  * @param x Pointer to check. | ||||
|  * @param message Message (sprintf format) to send to the logger. | ||||
|  * @param args Optional TParam args for the sprintf message to accept. | ||||
|  */ | ||||
| #define assertNotNull(x, ...) assertTrue(x != nullptr, __VA_ARGS__) | ||||
|  | ||||
| /** | ||||
|  * Asserts that a given pointer is null. | ||||
|  * @param x Pointer to check. | ||||
|  * @param message Message (sprintf format) to send to the logger. | ||||
|  * @param args Optional TParam args for the sprintf message to accept. | ||||
|  */ | ||||
| #define assertNull(x, ...) assertTrue(x == nullptr, __VA_ARGS__) | ||||
|  | ||||
| /** | ||||
|  * Asserts that a given map has a specific key. | ||||
|  * @param map Map to check. | ||||
|  * @param key Key to check for. | ||||
|  * @param message Message (sprintf format) to send to the logger. | ||||
|  * @param args Optional TParam args for the sprintf message to accept. | ||||
|  */ | ||||
| #define assertMapHasKey(map, key, ...) assertTrue( \ | ||||
|   map.find(key) != map.end(), __VA_ARGS__ \ | ||||
| ) | ||||
|  | ||||
| /** | ||||
|  * Asserts that a given map does not have a specific key. | ||||
|  * @param map Map to check. | ||||
|  * @param key Key to check for. | ||||
|  * @param message Message (sprintf format) to send to the logger. | ||||
|  * @param args Optional TParam args for the sprintf message to accept. | ||||
|  */ | ||||
| #define assertMapNotHasKey(map, key, ...) assertTrue( \ | ||||
|   map.find(key) == map.end(), __VA_ARGS__ \ | ||||
| ) | ||||
|  | ||||
| /** | ||||
|  * Asserts that a given value has a specific flag turned off. | ||||
|  *  | ||||
|  * @param value Value to check. | ||||
|  * @param flag Flag to check for. | ||||
|  * @param message Message (sprintf format) to send to the logger. | ||||
|  * @param args Optional TParam args for the sprintf message to accept. | ||||
|  */ | ||||
| #define assertFlagOff(value, flag, ...) assertTrue( \ | ||||
|   Flag::isOff(value, flag), __VA_ARGS__ \ | ||||
| ) | ||||
|  | ||||
| /** | ||||
|  * Asserts that a given value has a specific flag turned on. | ||||
|  *  | ||||
|  * @param value Value to check. | ||||
|  * @param flag Flag to check for. | ||||
|  * @param message Message (sprintf format) to send to the logger. | ||||
|  * @param args Optional TParam args for the sprintf message to accept. | ||||
|  */ | ||||
| #define assertFlagOn(value, flag, ...) assertTrue( \ | ||||
|   Flag::isOn(value, flag), __VA_ARGS__ \ | ||||
| ) | ||||
|  | ||||
| /** | ||||
|  * Asserts that the current code is deprecated and should not be used anymore. | ||||
|  * @deprecated | ||||
|  */ | ||||
| #define assertDeprecated(...) assertUnreachable(__VA_ARGS__) | ||||
| @@ -1,230 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "assert/assert.hpp" | ||||
| #include "AssetDataLoader.hpp" | ||||
| #include "util/Math.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| ssize_t assetDataLoaderArchiveRead( | ||||
|   struct archive *archive, | ||||
|   void *d, | ||||
|   const void **buffer | ||||
| ) { | ||||
|   assertNotNull(archive, "Archive is NULL!"); | ||||
|   assertNotNull(d, "Data is NULL!"); | ||||
|   assertNotNull(buffer, "Buffer is NULL!"); | ||||
|   AssetDataLoader *loader = (AssetDataLoader*)d; | ||||
|  | ||||
|   *buffer = loader->buffer; | ||||
|   size_t read = fread( | ||||
|     loader->buffer, 1, ASSET_LOADER_BUFFER_SIZE, loader->assetArchiveFile | ||||
|   ); | ||||
|   if(ferror(loader->assetArchiveFile)) return ARCHIVE_FATAL; | ||||
|   return read; | ||||
| } | ||||
|  | ||||
| int64_t assetDataLoaderArchiveSeek( | ||||
|   struct archive *archive, | ||||
|   void *d, | ||||
|   int64_t offset, | ||||
|   int32_t whence | ||||
| ) { | ||||
|   assertNotNull(archive, "Archive is NULL!"); | ||||
|   assertNotNull(d, "Data is NULL!"); | ||||
|   assertTrue(offset > 0, "Offset must be greater than 0!"); | ||||
|   AssetDataLoader *loader = (AssetDataLoader*)d; | ||||
|   int32_t ret = fseek(loader->assetArchiveFile, offset, whence); | ||||
|   assertTrue(ret == 0, "Failed to seek!"); | ||||
|   return ftell(loader->assetArchiveFile); | ||||
| } | ||||
|  | ||||
| int32_t assetDataLoaderArchiveOpen(struct archive *a, void *d) { | ||||
|   assertNotNull(a, "Archive is NULL!"); | ||||
|   assertNotNull(d, "Data is NULL!"); | ||||
|   AssetDataLoader *loader = (AssetDataLoader*)d; | ||||
|  | ||||
|   int32_t ret = fseek(loader->assetArchiveFile, 0, SEEK_SET); | ||||
|   assertTrue(ret == 0, "Failed to seek to start of file!"); | ||||
|   return ARCHIVE_OK; | ||||
| } | ||||
|  | ||||
| int32_t assetDataLoaderArchiveClose(struct archive *a, void *d) { | ||||
|   assertNotNull(a, "Archive is NULL!"); | ||||
|   assertNotNull(d, "Data is NULL!"); | ||||
|   return assetDataLoaderArchiveOpen(a, d); | ||||
| } | ||||
|  | ||||
| // // // // // // // // // // // // // // // // // // // // // // // // // // // | ||||
|  | ||||
| AssetDataLoader::AssetDataLoader(const std::string &fileName) : | ||||
|   fileName(fileName) | ||||
| { | ||||
|   assertTrue( | ||||
|     fileName.size() > 0, | ||||
|     "IAssetDataLoader::IAssetDataLoader: fileName must be greater than 0" | ||||
|   ); | ||||
| } | ||||
|  | ||||
| size_t AssetDataLoader::getSize() { | ||||
|   assertTrue(this->assetArchiveEntry != nullptr, "Entry is NULL!"); | ||||
|   assertTrue( | ||||
|     archive_entry_size_is_set(assetArchiveEntry), | ||||
|     "Entry size is not set!" | ||||
|   ); | ||||
|   return archive_entry_size(assetArchiveEntry); | ||||
| } | ||||
|  | ||||
| size_t AssetDataLoader::getPosition() { | ||||
|   assertNotNull(this->assetArchiveFile, "File is not open!"); | ||||
|   return this->position; | ||||
| } | ||||
|  | ||||
| std::string AssetDataLoader::getEntireContentsAsString() { | ||||
|   if(!this->isOpen()) { | ||||
|     this->open(); | ||||
|   } else { | ||||
|     this->rewind(); | ||||
|   } | ||||
|  | ||||
|   std::string buffer; | ||||
|   buffer.resize(this->getSize()); | ||||
|   this->read((uint8_t*)buffer.data(), buffer.size()); | ||||
|   this->close(); | ||||
|   return buffer; | ||||
| } | ||||
|  | ||||
| bool_t AssetDataLoader::isOpen() { | ||||
|   return this->assetArchive != nullptr; | ||||
| } | ||||
|  | ||||
| void AssetDataLoader::open() { | ||||
|   assertNull(this->assetArchiveFile, "File is already open"); | ||||
|   assertNull(this->assetArchive, "Archive is already open"); | ||||
|   assertNull(this->assetArchiveEntry, "Entry is already open"); | ||||
|  | ||||
|   this->assetArchiveFile = this->openAssetArchiveFile(); | ||||
|   assertNotNull(this->assetArchiveFile, "Failed to open archive file!"); | ||||
|  | ||||
|   // Open archive reader | ||||
|   assetArchive = archive_read_new(); | ||||
|   assertNotNull(assetArchive, "Failed to create archive reader"); | ||||
|  | ||||
|   // Set up the reader | ||||
|   archive_read_support_format_tar(assetArchive); | ||||
|  | ||||
|   // Open reader | ||||
|   archive_read_set_open_callback(assetArchive, &assetDataLoaderArchiveOpen); | ||||
|   archive_read_set_read_callback(assetArchive, &assetDataLoaderArchiveRead); | ||||
|   archive_read_set_seek_callback(assetArchive, &assetDataLoaderArchiveSeek); | ||||
|   archive_read_set_close_callback(assetArchive, &assetDataLoaderArchiveClose); | ||||
|   archive_read_set_callback_data(assetArchive, this); | ||||
|  | ||||
|   int32_t ret =  archive_read_open1(assetArchive); | ||||
|   assertTrue(ret == ARCHIVE_OK, "Failed to open archive!"); | ||||
|   position = 0; | ||||
|  | ||||
|   // Iterate over each file to find the one for this asset loader. | ||||
|   while(archive_read_next_header(assetArchive, &assetArchiveEntry)==ARCHIVE_OK){ | ||||
|     const char_t *headerFile = (char_t*)archive_entry_pathname( | ||||
|       assetArchiveEntry | ||||
|     ); | ||||
|     if(std::string(headerFile) == this->fileName) return; | ||||
|     int32_t ret = archive_read_data_skip(assetArchive); | ||||
|     assertTrue(ret == ARCHIVE_OK, "Failed to skip data!"); | ||||
|   } | ||||
|  | ||||
|   assertUnreachable("Failed to find file!"); | ||||
| } | ||||
|  | ||||
| int32_t AssetDataLoader::close() { | ||||
|   assertNotNull(this->assetArchiveFile, "File is NULL"); | ||||
|   assertNotNull(this->assetArchive, "Archive is NULL!"); | ||||
|   assertNotNull(this->assetArchiveEntry, "Entry is NULL!"); | ||||
|    | ||||
|   // Close the archive | ||||
|   int32_t ret = archive_read_free(this->assetArchive); | ||||
|   assertTrue(ret == ARCHIVE_OK, "Failed to close archive!"); | ||||
|  | ||||
|   this->assetArchive = nullptr; | ||||
|   this->assetArchiveEntry = nullptr; | ||||
|  | ||||
|   // Close the file | ||||
|   int32_t res = fclose(this->assetArchiveFile); | ||||
|   this->assetArchiveFile = nullptr; | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| size_t AssetDataLoader::read(uint8_t *buffer, const size_t &size) { | ||||
|   assertNotNull(buffer, "Buffer is NULL!"); | ||||
|   assertTrue(size > 0, "Size must be greater than 0!"); | ||||
|   assertNotNull(this->assetArchive, "Archive is NULL!"); | ||||
|   assertNotNull(this->assetArchiveEntry, "Entry is NULL!"); | ||||
|  | ||||
|   ssize_t read = archive_read_data(this->assetArchive, buffer, size); | ||||
|   this->position += read; | ||||
|    | ||||
|   if(read == ARCHIVE_FATAL) { | ||||
|     assertUnreachable(archive_error_string(this->assetArchive)); | ||||
|   } | ||||
|    | ||||
|   assertTrue(read != ARCHIVE_RETRY, "Failed to read data (RETRY)!"); | ||||
|   assertTrue(read != ARCHIVE_WARN, "Failed to read data (WARN)!"); | ||||
|  | ||||
|   return read; | ||||
| } | ||||
|  | ||||
| size_t AssetDataLoader::readUntil( | ||||
|   uint8_t *buffer, | ||||
|   const size_t maxSize, | ||||
|   const char_t delimiter | ||||
| ) { | ||||
|   size_t totalRead = this->read(buffer, maxSize); | ||||
|   size_t i = 0; | ||||
|   while(i < totalRead) { | ||||
|     if(buffer[i] == delimiter) break; | ||||
|     i++; | ||||
|   } | ||||
|   buffer[i++] = '\0'; | ||||
|   return i; | ||||
| } | ||||
|  | ||||
| size_t AssetDataLoader::skip(const size_t &n) { | ||||
|   assertTrue(n >= 0, "Byte count must be greater than 0."); | ||||
|   assertTrue(n < (this->getSize() - this->position), "Cannot skip past EOF!"); | ||||
|  | ||||
|   uint8_t dumpBuffer[ASSET_LOADER_BUFFER_SIZE]; | ||||
|   size_t skipped = 0; | ||||
|   size_t n2, n3, n4; | ||||
|   n4 = n; | ||||
|   while(n4 != 0) { | ||||
|     n2 = Math::min<size_t>(n4, ASSET_LOADER_BUFFER_SIZE); | ||||
|     n3 = this->read(dumpBuffer, n2); | ||||
|     assertTrue(n3 == n2, "Failed to skip bytes!"); | ||||
|     n4 -= n3; | ||||
|   } | ||||
|  | ||||
|   return skipped; | ||||
| } | ||||
|  | ||||
| size_t AssetDataLoader::setPosition(const size_t position) { | ||||
|   assertTrue(position >= 0, "Position must be greater than or equal to 0"); | ||||
|   this->rewind(); | ||||
|   return this->skip(position); | ||||
| } | ||||
|  | ||||
| void AssetDataLoader::rewind() { | ||||
|   assertTrue(this->isOpen(), "Asset is not open!"); | ||||
|   if(this->position == 0) return; | ||||
|  | ||||
|   // TODO: See if I can optimize this | ||||
|   this->close(); | ||||
|   this->open(); | ||||
| } | ||||
|  | ||||
| AssetDataLoader::~AssetDataLoader() { | ||||
|   if(this->assetArchiveFile != nullptr) this->close(); | ||||
| } | ||||
| @@ -1,180 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "dawn.hpp" | ||||
|  | ||||
| extern "C" { | ||||
|   #include <archive.h> | ||||
|   #include <archive_entry.h> | ||||
| } | ||||
|  | ||||
| #define ASSET_LOADER_BUFFER_SIZE 32768 | ||||
|  | ||||
| /** | ||||
|  * Method invoked by the libarchive internals to read bytes from the archive | ||||
|  * file pointer. | ||||
|  *  | ||||
|  * @param archive Archive requesting the read.  | ||||
|  * @param data Data pointer passed to the archive. | ||||
|  * @param buffer Pointer to where the buffer pointer should be stored. | ||||
|  * @return Count of bytes read. | ||||
|  */ | ||||
| ssize_t assetDataLoaderArchiveRead( | ||||
|   struct archive *archive, | ||||
|   void *data, | ||||
|   const void **buffer | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * Method invoked by the libarchive internals to seek the archive file pointer. | ||||
|  *  | ||||
|  * @param archive Archive requesting the seek. | ||||
|  * @param data Data pointer passed to the archive. | ||||
|  * @param offset Offset to seek to. | ||||
|  * @param whence Whence to seek from. | ||||
|  * @return The new offset. | ||||
|  */ | ||||
| int64_t assetDataLoaderArchiveSeek( | ||||
|   struct archive *archive, | ||||
|   void *data, | ||||
|   int64_t offset, | ||||
|   int32_t whence | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * Method invoked by the libarchive internals to open the archive file pointer. | ||||
|  *  | ||||
|  * @param archive Archive requesting the open. | ||||
|  * @param data Data pointer passed to the archive. | ||||
|  * @return 0 if success, otherwise for failure. | ||||
|  */ | ||||
| int32_t assetDataLoaderArchiveOpen(struct archive *a, void *data); | ||||
|  | ||||
| /** | ||||
|  * Method invoked by the libarchive internals to close the archive file pointer. | ||||
|  *  | ||||
|  * @param archive Archive requesting the close. | ||||
|  * @param data Data pointer passed to the archive. | ||||
|  * @return 0 if success, otherwise for failure. | ||||
|  */ | ||||
| int32_t assetDataLoaderArchiveClose(struct archive *a, void *data); | ||||
|  | ||||
| namespace Dawn { | ||||
|   class AssetDataLoader { | ||||
|     protected: | ||||
|       struct archive *assetArchive = nullptr; | ||||
|       struct archive_entry *assetArchiveEntry = nullptr; | ||||
|       size_t position; | ||||
|       std::string fileName; | ||||
|  | ||||
|     public: | ||||
|       uint8_t buffer[ASSET_LOADER_BUFFER_SIZE]; | ||||
|       FILE *assetArchiveFile = nullptr; | ||||
|  | ||||
|       /** | ||||
|        * Unimplemented method intended to be implemented by the platform that | ||||
|        * will be used to request a File pointer to the asset. | ||||
|        *  | ||||
|        * @return Pointer to the opened asset archive. | ||||
|        */ | ||||
|       FILE * openAssetArchiveFile(); | ||||
|        | ||||
|       /** | ||||
|        * Create a new asset loader. Asset Loaders can be used to load data from | ||||
|        * a file in a myriad of ways. | ||||
|        *  | ||||
|        * @param fileName File name of the asset that is to be loaded. | ||||
|        */ | ||||
|       AssetDataLoader(const std::string &filename); | ||||
|        | ||||
|       /** | ||||
|        * Get the size of the asset. | ||||
|        * @return The size of the asset in bytes. | ||||
|        */ | ||||
|       size_t getSize(); | ||||
|  | ||||
|       /** | ||||
|        * Returns the current position of the read head. | ||||
|        *  | ||||
|        * @return The current read head position. | ||||
|        */ | ||||
|       size_t getPosition(); | ||||
|  | ||||
|       /** | ||||
|        * Get the entire contents of the asset as a string. | ||||
|        *  | ||||
|        * @return The entire contents of the asset as a string. | ||||
|        */ | ||||
|       std::string getEntireContentsAsString(); | ||||
|  | ||||
|       /** | ||||
|        * Check if the asset is open. | ||||
|        *  | ||||
|        * @return True if the asset is open, otherwise false. | ||||
|        */ | ||||
|       bool_t isOpen(); | ||||
|  | ||||
|       /** | ||||
|        * Platform-centric method to open a file buffer to an asset. | ||||
|        */ | ||||
|       void open(); | ||||
|  | ||||
|       /** | ||||
|        * Closes the previously ppened asset. | ||||
|        * @return 0 if successful, otherwise false. | ||||
|        */ | ||||
|       int32_t close(); | ||||
|  | ||||
|       /** | ||||
|        * Read bytes from buffer. | ||||
|        * @param buffer Pointer to a ubyte array to buffer data into. | ||||
|        * @param size Length of the data buffer (How many bytes to read). | ||||
|        * @return The count of bytes read. | ||||
|        */ | ||||
|       size_t read(uint8_t *buffer, const size_t &size); | ||||
|  | ||||
|       /** | ||||
|        * Reads bytes from the buffer until a given delimiter is found. Returned | ||||
|        * position will be the index of the delimiter within the buffer. | ||||
|        *  | ||||
|        * @param buffer Buffer to read into. | ||||
|        * @param maxSize Maximum size of the buffer. | ||||
|        * @param delimiter Delimiter to read until. | ||||
|        * @return The count of bytes read (including null terminator) | ||||
|        */ | ||||
|       size_t readUntil( | ||||
|         uint8_t *buffer, | ||||
|         const size_t maxSize, | ||||
|         const char_t delimiter | ||||
|       ); | ||||
|  | ||||
|       /** | ||||
|        * Skips the read head forward to a given position. | ||||
|        *  | ||||
|        * @param n Count of bytes to progress the read head by. | ||||
|        * @return Count of bytes progressed. | ||||
|        */ | ||||
|       size_t skip(const size_t &n); | ||||
|  | ||||
|       /** | ||||
|        * Rewind the read head to the beginning of the file. | ||||
|        */ | ||||
|       void rewind(); | ||||
|  | ||||
|       /** | ||||
|        * Sets the absolute position of the read head within the buffer of the | ||||
|        * file. | ||||
|        *  | ||||
|        * @param absolutePosition Absolute position to set the read head to. | ||||
|        */ | ||||
|       size_t setPosition(const size_t absolutePosition); | ||||
|  | ||||
|       /** | ||||
|        * Cleanup the asset loader. | ||||
|        */ | ||||
|       virtual ~AssetDataLoader(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,42 +0,0 @@ | ||||
| // Copyright (c) 2022 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "AssetLoader.hpp" | ||||
| #include "assert/assert.hpp" | ||||
| #include "asset/AssetManager.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| const std::string AssetLoader::ASSET_TYPE = "unknown"; | ||||
|  | ||||
| AssetLoader::AssetLoader( | ||||
|   const std::shared_ptr<AssetManager> assetManager, | ||||
|   const std::string name | ||||
| ) : | ||||
|   assetManager(assetManager), | ||||
|   name(name) | ||||
| { | ||||
|   assertNotNull(assetManager, "AssetManager cannot be null"); | ||||
|   assertTrue(name.size() > 0, "Name cannot be empty"); | ||||
|  | ||||
|   std::cout << "Loading: " << name << std::endl; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<AssetManager> AssetLoader::getAssetManager() { | ||||
|   auto am = this->assetManager.lock(); | ||||
|   assertNotNull(am, "AssetManager is null"); | ||||
|   return am; | ||||
| } | ||||
|  | ||||
| void AssetLoader::loadImmediately() { | ||||
|   while(!this->loaded) { | ||||
|     this->getAssetManager()->update(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| AssetLoader::~AssetLoader() { | ||||
|   this->loaded = false; | ||||
|   std::cout << "Unloading: " << name << std::endl; | ||||
| } | ||||
| @@ -1,71 +0,0 @@ | ||||
| // Copyright (c) 2022 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "dawn.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class AssetManager; | ||||
|  | ||||
|   class AssetLoader { | ||||
|     private: | ||||
|       std::weak_ptr<AssetManager> assetManager; | ||||
|  | ||||
|     public: | ||||
|       std::string typetest; | ||||
|       const static std::string ASSET_TYPE; | ||||
|  | ||||
|       const std::string name; | ||||
|       bool_t loaded = false; | ||||
|  | ||||
|       /** | ||||
|        * Create an abstract Asset object. | ||||
|        *  | ||||
|        * @param name Name of the asset. | ||||
|        */ | ||||
|       AssetLoader( | ||||
|         const std::shared_ptr<AssetManager> assetManager, | ||||
|         const std::string name | ||||
|       ); | ||||
|  | ||||
|       /** | ||||
|        * Virtual function that will be called by the asset manager on a  | ||||
|        * synchronous basis. This will only trigger if the blocks are false and | ||||
|        * the loaded is also false. | ||||
|        */ | ||||
|       virtual void updateSync() = 0; | ||||
|  | ||||
|       /** | ||||
|        * Virtual function called by the asset manager asynchronously every tick. | ||||
|        * This will only trigger if blocks are false and the loaded state is also | ||||
|        * false. | ||||
|        */ | ||||
|       virtual void updateAsync() = 0; | ||||
|  | ||||
|       /** | ||||
|        * Returns the asset type. | ||||
|        *  | ||||
|        * @return The asset type. | ||||
|        */ | ||||
|       virtual std::string getAssetType() const = 0; | ||||
|  | ||||
|       /** | ||||
|        * Returns the asset manager. | ||||
|        *  | ||||
|        * @return The asset manager. | ||||
|        */ | ||||
|       std::shared_ptr<AssetManager> getAssetManager(); | ||||
|  | ||||
|       /** | ||||
|        * Load the asset immediately, this is blocking on the main thread. | ||||
|        */ | ||||
|       void loadImmediately(); | ||||
|        | ||||
|       /** | ||||
|        * Dispose the asset item. | ||||
|        */ | ||||
|       virtual ~AssetLoader(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,77 +0,0 @@ | ||||
| // Copyright (c) 2022 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "AssetManager.hpp" | ||||
| #include "assert/assert.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void AssetManager::init(const std::shared_ptr<Game> &game) { | ||||
|   assertNotNull(game, "Game is NULL?"); | ||||
|   this->game = game; | ||||
| } | ||||
|  | ||||
| void AssetManager::update() { | ||||
|   auto copyPendingAssets = pendingAssetLoaders; | ||||
|   auto itPending = copyPendingAssets.begin(); | ||||
|   while(itPending != copyPendingAssets.end()) { | ||||
|     auto loader = *itPending; | ||||
|      | ||||
|     loader->updateSync(); | ||||
|     loader->updateAsync(); | ||||
|     loader->updateSync(); | ||||
|  | ||||
|     if(!loader->loaded) { | ||||
|       ++itPending; | ||||
|       continue; | ||||
|     } | ||||
|      | ||||
|     finishedAssetLoaders.push_back(loader); | ||||
|     auto it = std::find( | ||||
|       pendingAssetLoaders.begin(), | ||||
|       pendingAssetLoaders.end(), | ||||
|       loader | ||||
|     ); | ||||
|     assertTrue(it != pendingAssetLoaders.end(), "Loader not found?"); | ||||
|     pendingAssetLoaders.erase(it); | ||||
|     ++itPending; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void AssetManager::remove(const std::shared_ptr<AssetLoader> loader) { | ||||
|   for( | ||||
|     auto it = pendingAssetLoaders.begin(); | ||||
|     it != pendingAssetLoaders.end(); | ||||
|     it++ | ||||
|   ) { | ||||
|     if(*it != loader) continue; | ||||
|     pendingAssetLoaders.erase(it); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   for( | ||||
|     auto it = finishedAssetLoaders.begin(); | ||||
|     it != finishedAssetLoaders.end(); | ||||
|     it++ | ||||
|   ) { | ||||
|     if(it->lock() != loader) continue; | ||||
|     finishedAssetLoaders.erase(it); | ||||
|     return; | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool_t AssetManager::isEverythingLoaded() { | ||||
|   return pendingAssetLoaders.size() == 0; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<Game> AssetManager::getGame() { | ||||
|   auto g = game.lock(); | ||||
|   assertNotNull(g, "Game is NULL?"); | ||||
|   return g; | ||||
| } | ||||
|  | ||||
| AssetManager::~AssetManager() { | ||||
|    | ||||
| } | ||||
| @@ -1,114 +0,0 @@ | ||||
| // Copyright (c) 2022 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "dawn.hpp" | ||||
| #include "asset/AssetLoader.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class Game; | ||||
|  | ||||
|   class AssetManager final : public std::enable_shared_from_this<AssetManager> { | ||||
|     private: | ||||
|       std::weak_ptr<Game> game; | ||||
|       std::vector<std::shared_ptr<AssetLoader>> pendingAssetLoaders; | ||||
|       std::vector<std::weak_ptr<AssetLoader>> finishedAssetLoaders; | ||||
|  | ||||
|       /** | ||||
|        * Returns an existing asset loader if it exists. | ||||
|        *  | ||||
|        * @param filename The filename of the asset to get. | ||||
|        * @return The asset loader if it exists, otherwise nullptr. | ||||
|        */ | ||||
|       template<class T> | ||||
|       std::shared_ptr<T> getExisting(const std::string &filename) { | ||||
|         for(auto &loader : pendingAssetLoaders) { | ||||
|           if(loader->name != filename) continue; | ||||
|           if(loader->getAssetType() != T::ASSET_TYPE) continue; | ||||
|           return std::static_pointer_cast<T>(loader); | ||||
|         } | ||||
|  | ||||
|         for(auto &wLoader : finishedAssetLoaders) { | ||||
|           auto loader = wLoader.lock(); | ||||
|           if(!loader) continue; | ||||
|           if(loader->name != filename) continue; | ||||
|           if(loader->getAssetType() != T::ASSET_TYPE) continue; | ||||
|           return std::static_pointer_cast<T>(loader); | ||||
|         } | ||||
|          | ||||
|         return nullptr; | ||||
|       } | ||||
|  | ||||
|       /** | ||||
|        * Removes an existing asset loader if it exists. | ||||
|        *  | ||||
|        * @param filename The filename of the asset to remove. | ||||
|        */ | ||||
|       void removeExisting(const std::string &filename); | ||||
|  | ||||
|     public: | ||||
|       /** | ||||
|        * Initializes this asset manager so it can begin accepting assets. | ||||
|        *  | ||||
|        * @param game Game context that this asset manager is attached to. | ||||
|        */ | ||||
|       void init(const std::shared_ptr<Game> &game); | ||||
|  | ||||
|       /** | ||||
|        * Updates the asset manager. | ||||
|        */ | ||||
|       void update(); | ||||
|  | ||||
|       /** | ||||
|        * Returns whether the asset manager has loaded all of the currently | ||||
|        * managed assets. | ||||
|        *  | ||||
|        * @return True if all assets have been loaded. | ||||
|        */ | ||||
|       bool_t isEverythingLoaded(); | ||||
|  | ||||
|       /** | ||||
|        * Returns the asset loader for the given asset. | ||||
|        *  | ||||
|        * @param filename The filename of the asset to get. | ||||
|        * @return The asset loader for the given asset. | ||||
|        */ | ||||
|       template<class T> | ||||
|       std::shared_ptr<T> get(const std::string &filename) { | ||||
|         auto existing = this->getExisting<T>(filename); | ||||
|         if(existing) return existing; | ||||
|  | ||||
|         std::shared_ptr<T> loader = std::make_shared<T>( | ||||
|           shared_from_this(), | ||||
|           filename | ||||
|         ); | ||||
|         pendingAssetLoaders.push_back( | ||||
|           std::static_pointer_cast<AssetLoader>(loader) | ||||
|         ); | ||||
|         return loader; | ||||
|       } | ||||
|  | ||||
|       /** | ||||
|        * Returns the game context that this asset manager is attached to. | ||||
|        *  | ||||
|        * @return The game context. | ||||
|        */ | ||||
|       std::shared_ptr<Game> getGame(); | ||||
|  | ||||
|       /** | ||||
|        * Removes the given asset loader from the asset manager, assumes that | ||||
|        * nothing else needs to access it and any dangling shared_ptrs will have | ||||
|        * to remain in memory. | ||||
|        *  | ||||
|        * @param loader The asset loader to remove. | ||||
|        */ | ||||
|       void remove(const std::shared_ptr<AssetLoader> loader); | ||||
|  | ||||
|       /** | ||||
|        * Dispose the asset manager, and all attached assets. | ||||
|        */ | ||||
|       ~AssetManager(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,15 +0,0 @@ | ||||
| # Copyright (c) 2022 Dominic Msters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| # Sources | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     AssetLoader.cpp | ||||
|     AssetDataLoader.cpp | ||||
|     AssetManager.cpp | ||||
| ) | ||||
|  | ||||
| # Subdirs | ||||
| add_subdirectory(loader) | ||||
| @@ -1,17 +0,0 @@ | ||||
| # Copyright (c) 2022 Dominic Msters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| # Sources | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     TextureLoader.cpp | ||||
|     JSONLoader.cpp | ||||
|     TrueTypeLoader.cpp | ||||
|     ShaderLoader.cpp | ||||
|     StringLoader.cpp | ||||
| ) | ||||
|  | ||||
| # Subdirs | ||||
| add_subdirectory(scene) | ||||
| @@ -1,43 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "JSONLoader.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| const std::string JSONLoader::ASSET_TYPE = "json"; | ||||
|  | ||||
| JSONLoader::JSONLoader( | ||||
|   const std::shared_ptr<AssetManager> assetManager, | ||||
|   const std::string name | ||||
| ) : | ||||
|   AssetLoader(assetManager, name), | ||||
|   loader(name), | ||||
|   state(JSONLoaderState::INITIAL) | ||||
| { | ||||
|   this->typetest = this->getAssetType(); | ||||
| } | ||||
|  | ||||
| void JSONLoader::updateAsync() { | ||||
|   if(this->state != JSONLoaderState::INITIAL) return; | ||||
|    | ||||
|   this->state = JSONLoaderState::LOADING_JSON; | ||||
|   std::string jsonContents = loader.getEntireContentsAsString(); | ||||
|   this->data = json::parse(jsonContents); | ||||
|   this->state = JSONLoaderState::DONE; | ||||
|   this->loaded = true; | ||||
| } | ||||
|  | ||||
| void JSONLoader::updateSync() { | ||||
| } | ||||
|  | ||||
| std::string JSONLoader::getAssetType() const { | ||||
|   return JSONLoader::ASSET_TYPE; | ||||
| } | ||||
|  | ||||
| JSONLoader::~JSONLoader() { | ||||
|    | ||||
| } | ||||
|  | ||||
| @@ -1,37 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "asset/AssetLoader.hpp" | ||||
| #include "asset/AssetDataLoader.hpp" | ||||
|  | ||||
|  | ||||
| namespace Dawn { | ||||
|   enum class JSONLoaderState { | ||||
|     INITIAL, | ||||
|     LOADING_JSON, | ||||
|     DONE | ||||
|   }; | ||||
|  | ||||
|   class JSONLoader : public AssetLoader { | ||||
|     protected: | ||||
|       AssetDataLoader loader; | ||||
|       enum JSONLoaderState state; | ||||
|  | ||||
|     public: | ||||
|       const static std::string ASSET_TYPE; | ||||
|  | ||||
|       json data; | ||||
|  | ||||
|       JSONLoader( | ||||
|         const std::shared_ptr<AssetManager> assetManager, | ||||
|         const std::string name | ||||
|       ); | ||||
|       void updateSync() override; | ||||
|       void updateAsync() override; | ||||
|       std::string getAssetType() const override; | ||||
|       ~JSONLoader(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,60 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "ShaderLoader.hpp" | ||||
| #include "assert/assert.hpp" | ||||
| #include "asset/AssetManager.hpp" | ||||
| #include "game/Game.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| const std::string ShaderLoader::ASSET_TYPE = "shader"; | ||||
|  | ||||
| ShaderLoader::ShaderLoader( | ||||
|   const std::shared_ptr<AssetManager> assetManager, | ||||
|   const std::string name | ||||
| ) : | ||||
|   AssetLoader(assetManager, name), | ||||
|   state(ShaderLoaderState::INITIAL), | ||||
|   shader(std::make_shared<ShaderProgram>()) | ||||
| { | ||||
| } | ||||
|  | ||||
| void ShaderLoader::updateAsync() { | ||||
| } | ||||
|  | ||||
| void ShaderLoader::updateSync() { | ||||
|   if(state != ShaderLoaderState::INITIAL) return; | ||||
|   this->state = ShaderLoaderState::LOADING; | ||||
|   assertFalse(loaded, "ShaderLoader already loaded."); | ||||
|  | ||||
|   // Shorthand. | ||||
|   auto sm = this->getAssetManager()->getGame()->shaderManager; | ||||
|  | ||||
|   // Load the shader string | ||||
|   Slang::ComPtr<IBlob> diagnostics; | ||||
|   auto module = sm->session->loadModule( | ||||
|     this->name.c_str(), | ||||
|     diagnostics.writeRef() | ||||
|   ); | ||||
|   shader->init(module, sm->session); | ||||
|  | ||||
|   // Finished loading. | ||||
|   this->state = ShaderLoaderState::LOADED; | ||||
|   this->loaded = true; | ||||
| } | ||||
|  | ||||
| std::string ShaderLoader::getAssetType() const { | ||||
|   return ShaderLoader::ASSET_TYPE; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<ShaderProgram> ShaderLoader::getShader() { | ||||
|   assertNotNull(shader, "ShaderLoader shader is null."); | ||||
|   return shader; | ||||
| } | ||||
|  | ||||
| ShaderLoader::~ShaderLoader() { | ||||
|   shader = nullptr; | ||||
| } | ||||
| @@ -1,44 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "asset/AssetLoader.hpp" | ||||
| #include "asset/AssetDataLoader.hpp" | ||||
| #include "display/shader/ShaderManager.hpp" | ||||
| #include "display/shader/ShaderProgram.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   enum class ShaderLoaderState { | ||||
|     INITIAL, | ||||
|     LOADING, | ||||
|     LOADED | ||||
|   }; | ||||
|  | ||||
|   class ShaderLoader : public AssetLoader { | ||||
|     protected: | ||||
|       enum ShaderLoaderState state; | ||||
|       std::shared_ptr<ShaderProgram> shader; | ||||
|  | ||||
|     public: | ||||
|       const static std::string ASSET_TYPE; | ||||
|  | ||||
|       ShaderLoader( | ||||
|         const std::shared_ptr<AssetManager> assetManager, | ||||
|         const std::string name | ||||
|       ); | ||||
|       void updateSync() override; | ||||
|       void updateAsync() override; | ||||
|       std::string getAssetType() const override; | ||||
|        | ||||
|       /** | ||||
|        * Retreives the shader program for this loader. | ||||
|        *  | ||||
|        * @return The shader program that this loader is managing. | ||||
|        */ | ||||
|       std::shared_ptr<ShaderProgram> getShader(); | ||||
|  | ||||
|       ~ShaderLoader(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,38 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "StringLoader.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| const std::string StringLoader::ASSET_TYPE = "string"; | ||||
|  | ||||
| StringLoader::StringLoader( | ||||
|   const std::shared_ptr<AssetManager> assetManager, | ||||
|   const std::string name | ||||
| ) : | ||||
|   AssetLoader(assetManager, name), | ||||
|   loader(name), | ||||
|   state(StringLoaderState::INITIAL) | ||||
| { | ||||
| } | ||||
|  | ||||
| void StringLoader::updateSync() { | ||||
| } | ||||
|  | ||||
| void StringLoader::updateAsync() { | ||||
|   if(this->state != StringLoaderState::INITIAL) return; | ||||
|   this->state = StringLoaderState::LOADING_STRING; | ||||
|   this->data = this->loader.getEntireContentsAsString(); | ||||
|   this->state = StringLoaderState::DONE; | ||||
|   this->loaded = true; | ||||
| } | ||||
|  | ||||
| std::string StringLoader::getAssetType() const { | ||||
|   return StringLoader::ASSET_TYPE; | ||||
| } | ||||
|  | ||||
| StringLoader::~StringLoader() { | ||||
| } | ||||
| @@ -1,36 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "asset/AssetLoader.hpp" | ||||
| #include "asset/AssetDataLoader.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   enum class StringLoaderState { | ||||
|     INITIAL, | ||||
|     LOADING_STRING, | ||||
|     DONE | ||||
|   }; | ||||
|  | ||||
|   class StringLoader : public AssetLoader { | ||||
|     protected: | ||||
|       AssetDataLoader loader; | ||||
|       enum StringLoaderState state; | ||||
|  | ||||
|     public: | ||||
|       const static std::string ASSET_TYPE; | ||||
|  | ||||
|       std::string data; | ||||
|  | ||||
|       StringLoader( | ||||
|         const std::shared_ptr<AssetManager> assetManager, | ||||
|         const std::string name | ||||
|       ); | ||||
|       void updateSync() override; | ||||
|       void updateAsync() override; | ||||
|       std::string getAssetType() const override; | ||||
|       ~StringLoader(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,157 +0,0 @@ | ||||
| // Copyright (c) 2022 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "TextureLoader.hpp" | ||||
| #include "assert/assert.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| const std::string TextureLoader::ASSET_TYPE = "texture"; | ||||
|  | ||||
| TextureLoader::TextureLoader( | ||||
|   const std::shared_ptr<AssetManager> assetManager, | ||||
|   const std::string name | ||||
| ) : | ||||
|   AssetLoader(assetManager, name), | ||||
|   loader(name), | ||||
|   state(TextureLoaderLoadState::INITIAL) | ||||
| { | ||||
|   this->typetest = this->getAssetType(); | ||||
|   texture = std::make_shared<Texture>(); | ||||
| } | ||||
|  | ||||
| void TextureLoader::updateAsync() { | ||||
|   if(this->state != TextureLoaderLoadState::INITIAL) return; | ||||
|   this->state = TextureLoaderLoadState::ASYNC_LOADING; | ||||
|   this->loader.open(); | ||||
|  | ||||
|   // Read in the header. | ||||
|   uint8_t buffer[TEXTURE_LOADER_HEADER_SIZE]; | ||||
|   size_t pos = 0; | ||||
|    | ||||
|   // Read Version | ||||
|   pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|'); | ||||
|   std::string version = std::string((char*)buffer); | ||||
|   assertTrue(version == "DT_2.00", "Invalid Texture Version!"); | ||||
|  | ||||
|   // Read Texture Width | ||||
|   this->loader.setPosition(pos); | ||||
|   pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|'); | ||||
|   width = std::stoi(std::string((char*)buffer)); | ||||
|   assertTrue(width > 0, "Invalid Texture Width!"); | ||||
|  | ||||
|   // Read Texture Height | ||||
|   this->loader.setPosition(pos); | ||||
|   pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|'); | ||||
|   height = std::stoi(std::string((char*)buffer)); | ||||
|   assertTrue(height > 0, "Invalid Texture Height!"); | ||||
|  | ||||
|   // Texture Format (RGBA, RGB, etc) | ||||
|   this->loader.setPosition(pos); | ||||
|   pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|'); | ||||
|   int32_t iFormat = std::stoi(std::string((char*)buffer)); | ||||
|   switch(iFormat) { | ||||
|     case 1: format = TextureFormat::R; break; | ||||
|     case 2: format = TextureFormat::RG; break; | ||||
|     case 3: format = TextureFormat::RGB; break; | ||||
|     case 4: format = TextureFormat::RGBA; break; | ||||
|     default: assertUnreachable("Invalid Texture Format %i!", iFormat); | ||||
|   } | ||||
|  | ||||
|   // Wrap X | ||||
|   this->loader.setPosition(pos); | ||||
|   pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|'); | ||||
|   int32_t iWrapX = std::stoi(std::string((char*)buffer)); | ||||
|   switch(iWrapX) { | ||||
|     case 0: wrapX = TextureWrapMode::REPEAT; break; | ||||
|     case 1: wrapX = TextureWrapMode::MIRRORED_REPEAT; break; | ||||
|     case 2: wrapX = TextureWrapMode::CLAMP_TO_EDGE; break; | ||||
|     case 3: wrapX = TextureWrapMode::CLAMP_TO_BORDER; break; | ||||
|     default: assertUnreachable("Invalid Texture Wrap X %i!", iWrapX); | ||||
|   } | ||||
|  | ||||
|   // Wrap Y | ||||
|   this->loader.setPosition(pos); | ||||
|   pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|'); | ||||
|   int32_t iWrapY = std::stoi(std::string((char*)buffer)); | ||||
|   switch(iWrapY) { | ||||
|     case 0: wrapY = TextureWrapMode::REPEAT; break; | ||||
|     case 1: wrapY = TextureWrapMode::MIRRORED_REPEAT; break; | ||||
|     case 2: wrapY = TextureWrapMode::CLAMP_TO_EDGE; break; | ||||
|     case 3: wrapY = TextureWrapMode::CLAMP_TO_BORDER; break; | ||||
|     default: assertUnreachable("Invalid Texture Wrap Y %i!", iWrapY); | ||||
|   } | ||||
|  | ||||
|   // Filter Min | ||||
|   this->loader.setPosition(pos); | ||||
|   pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|'); | ||||
|   int32_t iFilterMin = std::stoi(std::string((char*)buffer)); | ||||
|   switch(iFilterMin) { | ||||
|     case 0: filterMin = TextureFilterMode::NEAREST; break; | ||||
|     case 1: filterMin = TextureFilterMode::LINEAR; break; | ||||
|     default: assertUnreachable("Invalid Texture Filter Min %i!", iFilterMin); | ||||
|   } | ||||
|  | ||||
|   // Filter Mag | ||||
|   this->loader.setPosition(pos); | ||||
|   pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|'); | ||||
|   int32_t iFilterMag = std::stoi(std::string((char*)buffer)); | ||||
|   switch(iFilterMag) { | ||||
|     case 0: filterMag = TextureFilterMode::NEAREST; break; | ||||
|     case 1: filterMag = TextureFilterMode::LINEAR; break; | ||||
|     default: assertUnreachable("Invalid Texture Filter Mag %i!", iFilterMag); | ||||
|   } | ||||
|  | ||||
|   // Data begins here. This part is done synchronously directly to the GPU. | ||||
|   this->loader.setPosition(pos); | ||||
|   size_t bufferSize = width * height * iFormat; | ||||
|   data = new uint8_t[bufferSize]; | ||||
|   assertNotNull(data, "Failed to allocate texture data!"); | ||||
|   this->loader.read(data, bufferSize); | ||||
|  | ||||
|   // Handoff to sync to buffer to GPU. | ||||
|   this->state = TextureLoaderLoadState::ASYNC_DONE; | ||||
| } | ||||
|  | ||||
| void TextureLoader::updateSync() { | ||||
|   if(this->state != TextureLoaderLoadState::ASYNC_DONE) return; | ||||
|   this->state = TextureLoaderLoadState::SYNC_LOADING; | ||||
|  | ||||
|   assertNotNull(this->texture, "Texture is null!"); | ||||
|   assertNotNull(this->data, "Texture data is null!"); | ||||
|  | ||||
|   // Setup Texture | ||||
|   this->texture->setSize( | ||||
|     this->width, | ||||
|     this->height, | ||||
|     this->format, | ||||
|     TextureDataFormat::UNSIGNED_BYTE | ||||
|   ); | ||||
|   this->texture->buffer(this->data); | ||||
|  | ||||
|   // Free data buffer | ||||
|   delete[] this->data; | ||||
|   this->data = nullptr; | ||||
|  | ||||
|   // Hand off and call done | ||||
|   this->state = TextureLoaderLoadState::SYNC_DONE; | ||||
|   this->loaded = true; | ||||
| } | ||||
|  | ||||
| std::string TextureLoader::getAssetType() const { | ||||
|   return TextureLoader::ASSET_TYPE; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<Texture> TextureLoader::getTexture() { | ||||
|   return this->texture; | ||||
| } | ||||
|  | ||||
| TextureLoader::~TextureLoader() { | ||||
|   if(this->data != nullptr) { | ||||
|     delete[] this->data; | ||||
|     this->data = nullptr; | ||||
|   } | ||||
|   this->texture = nullptr; | ||||
| } | ||||
| @@ -1,55 +0,0 @@ | ||||
| // Copyright (c) 2022 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "asset/AssetLoader.hpp" | ||||
| #include "asset/AssetDataLoader.hpp" | ||||
| #include "display/Texture.hpp" | ||||
|  | ||||
| #define TEXTURE_LOADER_HEADER_SIZE 256 | ||||
|  | ||||
| namespace Dawn { | ||||
|   enum class TextureLoaderLoadState { | ||||
|     INITIAL, | ||||
|     ASYNC_LOADING, | ||||
|     ASYNC_DONE, | ||||
|     SYNC_LOADING, | ||||
|     SYNC_DONE | ||||
|   }; | ||||
|  | ||||
|   class TextureLoader : public AssetLoader { | ||||
|     protected: | ||||
|       AssetDataLoader loader; | ||||
|       enum TextureLoaderLoadState state; | ||||
|       uint8_t *data = nullptr; | ||||
|       int32_t width = -1, height = -1; | ||||
|       enum TextureFormat format; | ||||
|       enum TextureWrapMode wrapX; | ||||
|       enum TextureWrapMode wrapY; | ||||
|       enum TextureFilterMode filterMin; | ||||
|       enum TextureFilterMode filterMag; | ||||
|       std::shared_ptr<Texture> texture; | ||||
|  | ||||
|     public: | ||||
|       const static std::string ASSET_TYPE; | ||||
|  | ||||
|       TextureLoader( | ||||
|         const std::shared_ptr<AssetManager> assetManager, | ||||
|         const std::string name | ||||
|       ); | ||||
|  | ||||
|       void updateSync() override; | ||||
|       void updateAsync() override; | ||||
|       std::string getAssetType() const override; | ||||
|  | ||||
|       /** | ||||
|        * Get the texture asset. | ||||
|        *  | ||||
|        * @return Texture asset. | ||||
|        */ | ||||
|       std::shared_ptr<Texture> getTexture(); | ||||
|       ~TextureLoader(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,107 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "TrueTypeLoader.hpp" | ||||
| #include "assert/assert.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| const std::string TrueTypeLoader::ASSET_TYPE = "ttf"; | ||||
|  | ||||
| TrueTypeLoader::TrueTypeLoader( | ||||
|   const std::shared_ptr<AssetManager> assetManager, | ||||
|   const std::string name | ||||
| ) : | ||||
|   AssetLoader(assetManager, name), | ||||
|   loader(name) | ||||
| { | ||||
|   this->typetest = this->getAssetType(); | ||||
|   // Init the font. | ||||
|   auto ret = FT_Init_FreeType(&fontLibrary); | ||||
|   assertTrue(ret == 0, "Failed to initialize FreeType library."); | ||||
| } | ||||
|  | ||||
| void TrueTypeLoader::updateSync() { | ||||
|   if(state != TrueTypeLoaderState::ASYNC_DONE) return; | ||||
|   state = TrueTypeLoaderState::SYNC_LOADING; | ||||
|  | ||||
|   // Init all the textures. | ||||
|   auto it = textures.begin(); | ||||
|   while(it != textures.end()) { | ||||
|     auto texture = it->second.lock(); | ||||
|  | ||||
|     if(texture) { | ||||
|       texture->setFace(face); | ||||
|       it++; | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     it = textures.erase(it); | ||||
|   } | ||||
|  | ||||
|   // Done | ||||
|   state = TrueTypeLoaderState::SYNC_DONE; | ||||
|   this->loaded = true; | ||||
| } | ||||
|  | ||||
| void TrueTypeLoader::updateAsync() { | ||||
|   if(state != TrueTypeLoaderState::INITIAL) return; | ||||
|   state = TrueTypeLoaderState::ASYNC_LOADING; | ||||
|  | ||||
|   // Load the data. | ||||
|   this->loader.open(); | ||||
|   size_t size = loader.getSize(); | ||||
|   buffer = new uint8_t[size]; | ||||
|  | ||||
|   // Read the data. | ||||
|   size_t readSize = loader.read(buffer, size); | ||||
|   assertTrue(readSize == size, "Failed to read all data from TrueTypeLoader."); | ||||
|  | ||||
|   // Init the font. | ||||
|   auto ret = FT_New_Memory_Face(fontLibrary, buffer, size, 0, &face); | ||||
|   assertTrue(ret == 0, "Failed to load font face."); | ||||
|  | ||||
|   // Now close the asset loader | ||||
|   loader.close(); | ||||
|   state = TrueTypeLoaderState::ASYNC_DONE; | ||||
| } | ||||
|  | ||||
| std::string TrueTypeLoader::getAssetType() const { | ||||
|   return TrueTypeLoader::ASSET_TYPE; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<TrueTypeTexture> TrueTypeLoader::getTexture( | ||||
|   const uint32_t fontSize | ||||
| ) { | ||||
|   // Check if we have the texture already and it hasn't gone stale. | ||||
|   auto it = textures.find(fontSize); | ||||
|   if(it != textures.end()) { | ||||
|     if(!it->second.expired()) return it->second.lock(); | ||||
|     textures.erase(it); | ||||
|   } | ||||
|  | ||||
|   // Create the texture. | ||||
|   auto texture = std::make_shared<TrueTypeTexture>(fontSize); | ||||
|   textures[fontSize] = texture; | ||||
|   if(this->loaded) texture->setFace(face); | ||||
|   return texture; | ||||
| } | ||||
|  | ||||
| TrueTypeLoader::~TrueTypeLoader() { | ||||
|   if( | ||||
|     this->state == TrueTypeLoaderState::SYNC_DONE || | ||||
|     this->state == TrueTypeLoaderState::SYNC_LOADING || | ||||
|     this->state == TrueTypeLoaderState::ASYNC_DONE | ||||
|   ) { | ||||
|     FT_Done_Face(face); | ||||
|   } | ||||
|  | ||||
|   FT_Done_FreeType(fontLibrary); | ||||
|  | ||||
|   if(buffer != nullptr) { | ||||
|     delete[] buffer; | ||||
|     buffer = nullptr; | ||||
|   } | ||||
| } | ||||
| @@ -1,53 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "asset/AssetLoader.hpp" | ||||
| #include "asset/AssetDataLoader.hpp" | ||||
| #include "display/font/TrueTypeTexture.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   enum class TrueTypeLoaderState { | ||||
|     INITIAL, | ||||
|     ASYNC_LOADING, | ||||
|     ASYNC_DONE, | ||||
|     SYNC_LOADING, | ||||
|     SYNC_DONE | ||||
|   }; | ||||
|  | ||||
|   class TrueTypeLoader : public AssetLoader { | ||||
|     protected: | ||||
|       FT_Library fontLibrary; | ||||
|       FT_Face face; | ||||
|       AssetDataLoader loader; | ||||
|       std::unordered_map<uint32_t, std::weak_ptr<TrueTypeTexture>> textures; | ||||
|       enum TrueTypeLoaderState state = TrueTypeLoaderState::INITIAL; | ||||
|       uint8_t *buffer = nullptr; | ||||
|  | ||||
|     public: | ||||
|       const static std::string ASSET_TYPE; | ||||
|  | ||||
|       TrueTypeLoader( | ||||
|         const std::shared_ptr<AssetManager> assetManager, | ||||
|         const std::string name | ||||
|       ); | ||||
|  | ||||
|       void updateSync() override; | ||||
|       void updateAsync() override; | ||||
|       std::string getAssetType() const override; | ||||
|  | ||||
|       /** | ||||
|        * Returns the texture for the given font size. | ||||
|        *  | ||||
|        * @param fontSize Font size to get the texture for. | ||||
|        * @return Texture for the given character. | ||||
|        */ | ||||
|       std::shared_ptr<TrueTypeTexture> getTexture( | ||||
|         const uint32_t fontSize | ||||
|       ); | ||||
|  | ||||
|       ~TrueTypeLoader(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,13 +0,0 @@ | ||||
| # Copyright (c) 2025 Dominic Msters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| # Sources | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     SceneLoader.cpp | ||||
|     LoaderForSceneItems.cpp | ||||
|     PrefabLoader.cpp | ||||
|     SceneLoadContext.cpp | ||||
| ) | ||||
| @@ -1,76 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "LoaderForSceneItems.hpp" | ||||
| #include "asset/loader/TextureLoader.hpp" | ||||
| #include "asset/loader/scene/PrefabLoader.hpp" | ||||
| #include "asset/loader/ShaderLoader.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| LoaderForSceneItems::LoaderForSceneItems( | ||||
|   const std::shared_ptr<AssetManager> assetManager, | ||||
|   const std::string name | ||||
| ) : | ||||
|   AssetLoader(assetManager, name), | ||||
|   ctx(std::make_shared<SceneLoadContext>()) | ||||
| { | ||||
| } | ||||
|  | ||||
| void LoaderForSceneItems::setupDependencies() { | ||||
|   assertNotNull(this->jsonLoader, "JSON Loader is NULL?"); | ||||
|   assertNotNull(ctx, "SceneLoadContext is NULL?"); | ||||
|   assertTrue(this->jsonLoader->loaded, "JSON loader not loaded?"); | ||||
|    | ||||
|   // Begin loading dependencies. | ||||
|   auto &data = this->jsonLoader->data; | ||||
|   if(data.contains("assets")) { | ||||
|     for(auto &asset : data["assets"].items()) { | ||||
|       auto &assetName = asset.key(); | ||||
|       auto &assetData = asset.value(); | ||||
|       assertTrue(assetData.contains("type"), "Asset missing type"); | ||||
|       assertTrue(assetData.contains("path"), "Asset missing path"); | ||||
|       auto type = assetData["type"].get<std::string>(); | ||||
|       auto path = assetData["path"].get<std::string>(); | ||||
|  | ||||
|       // Is this asset already named? | ||||
|       if(ctx->assets.find(assetName) != ctx->assets.end()) { | ||||
|         // Check if path and type already the same. | ||||
|         auto &existing = ctx->assets[assetName]; | ||||
|         assertTrue( | ||||
|           existing->name == path && existing->getAssetType() == type, | ||||
|           "Asset already exists with different path or type: %s", | ||||
|           assetName.c_str() | ||||
|         ); | ||||
|         continue; | ||||
|       } | ||||
|  | ||||
|       std::shared_ptr<AssetLoader> loader; | ||||
|       if(type == "texture") { | ||||
|         loader = getAssetManager()->get<TextureLoader>(path); | ||||
|  | ||||
|       } else if(type == "json") { | ||||
|         loader = getAssetManager()->get<JSONLoader>(path); | ||||
|  | ||||
|       } else if(type == "prefab") { | ||||
|         auto prefabLoader = getAssetManager()->get<PrefabLoader>(path); | ||||
|         prefabLoader->ctx->parent = ctx; | ||||
|         loader = prefabLoader; | ||||
|  | ||||
|       } else if(type == "shader") { | ||||
|         loader = getAssetManager()->get<ShaderLoader>(path); | ||||
|  | ||||
|       } else { | ||||
|         assertUnreachable("Unknown asset type: %s", type.c_str()); | ||||
|       } | ||||
|  | ||||
|       ctx->assets[assetName] = loader; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| LoaderForSceneItems::~LoaderForSceneItems() { | ||||
|   jsonLoader = nullptr; | ||||
| } | ||||
| @@ -1,39 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "asset/loader/JSONLoader.hpp" | ||||
| #include "SceneLoadContext.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class LoaderForSceneitems; | ||||
|  | ||||
|   class LoaderForSceneItems : | ||||
|     public AssetLoader, | ||||
|     public std::enable_shared_from_this<LoaderForSceneItems> | ||||
|   { | ||||
|     protected: | ||||
|       std::shared_ptr<JSONLoader> jsonLoader; | ||||
|  | ||||
|       /** | ||||
|        * Loads the dependencies into the context for the data available in | ||||
|        * the jsonLoader. | ||||
|        */ | ||||
|       void setupDependencies(); | ||||
|  | ||||
|     public: | ||||
|       const std::shared_ptr<SceneLoadContext> ctx; | ||||
|  | ||||
|       LoaderForSceneItems( | ||||
|         const std::shared_ptr<AssetManager> assetManager, | ||||
|         const std::string name | ||||
|       ); | ||||
|  | ||||
|       ~LoaderForSceneItems(); | ||||
|  | ||||
|       friend class SceneLoader; | ||||
|       friend class PrefabLoader; | ||||
|   }; | ||||
| } | ||||
| @@ -1,69 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "PrefabLoader.hpp" | ||||
| #include "SceneLoader.hpp" | ||||
| #include "game/Game.hpp" | ||||
| #include "assert/assert.hpp" | ||||
| #include "asset/loader/TextureLoader.hpp" | ||||
| #include "scene/Scene.hpp" | ||||
| #include "component/SceneComponentRegistry.hpp" | ||||
| #include "util/JSON.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| const std::string PrefabLoader::ASSET_TYPE = "prefab"; | ||||
|  | ||||
| PrefabLoader::PrefabLoader( | ||||
|   const std::shared_ptr<AssetManager> assetManager, | ||||
|   const std::string name | ||||
| ) : | ||||
|   LoaderForSceneItems(assetManager, name) | ||||
| { | ||||
|   this->typetest = this->getAssetType(); | ||||
| } | ||||
|  | ||||
| void PrefabLoader::updateSync() { | ||||
|   switch(this->state) { | ||||
|     case PrefabLoaderState::INITIAL: | ||||
|       jsonLoader = getAssetManager()->get<JSONLoader>(this->name); | ||||
|       this->state = PrefabLoaderState::LOADING_JSON; | ||||
|       break; | ||||
|      | ||||
|     case PrefabLoaderState::LOADING_JSON: | ||||
|       assertNotNull(this->jsonLoader, "JSON Loader is NULL?"); | ||||
|       if(!this->jsonLoader->loaded) return; | ||||
|       this->state = PrefabLoaderState::LOADING_DEPENDENCIES; | ||||
|       this->ctx->data = this->jsonLoader->data; | ||||
|       this->setupDependencies(); | ||||
|       break; | ||||
|  | ||||
|     case PrefabLoaderState::LOADING_DEPENDENCIES: | ||||
|       assertTrue(this->jsonLoader->loaded, "JSON loader not loaded?"); | ||||
|  | ||||
|       // Check if all dependencies are loaded. | ||||
|       for(auto &asset : ctx->assets) { | ||||
|         if(!asset.second->loaded) return; | ||||
|       } | ||||
|  | ||||
|       this->state = PrefabLoaderState::DEPENDENCIES_LOADED; | ||||
|       this->loaded = true; | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void PrefabLoader::updateAsync() { | ||||
| } | ||||
|  | ||||
| std::string PrefabLoader::getAssetType() const { | ||||
|   return PrefabLoader::ASSET_TYPE; | ||||
| } | ||||
|  | ||||
| PrefabLoader::~PrefabLoader() { | ||||
|  | ||||
| } | ||||
| @@ -1,39 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "LoaderForSceneItems.hpp" | ||||
| #include "scene/Scene.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|    | ||||
|   enum class PrefabLoaderState { | ||||
|     INITIAL, | ||||
|     LOADING_JSON, | ||||
|     LOADING_DEPENDENCIES, | ||||
|     DEPENDENCIES_LOADED, | ||||
|     DONE | ||||
|   }; | ||||
|  | ||||
|   class PrefabLoader : public LoaderForSceneItems { | ||||
|     protected: | ||||
|       PrefabLoaderState state = PrefabLoaderState::INITIAL; | ||||
|       std::shared_ptr<SceneItem> item; | ||||
|  | ||||
|     public: | ||||
|       const static std::string ASSET_TYPE; | ||||
|  | ||||
|       PrefabLoader( | ||||
|         const std::shared_ptr<AssetManager> assetManager, | ||||
|         const std::string name | ||||
|       ); | ||||
|        | ||||
|       void updateSync() override; | ||||
|       void updateAsync() override; | ||||
|       std::string getAssetType() const override; | ||||
|  | ||||
|       ~PrefabLoader(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,18 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "SceneLoadContext.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| std::shared_ptr<SceneItem> SceneLoadContext::getItem(const std::string &j) { | ||||
|   auto it = items.find(j); | ||||
|   if(it == items.end()) { | ||||
|     auto parent = this->parent.lock(); | ||||
|     assertNotNull(parent, "Couldn't find item."); | ||||
|     return parent->getItem(j); | ||||
|   } | ||||
|   return it->second; | ||||
| } | ||||
| @@ -1,85 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "dawn.hpp" | ||||
| #include "assert/assert.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class Scene; | ||||
|   class SceneItem; | ||||
|   class SceneComponent; | ||||
|   class AssetLoader; | ||||
|   class SceneLoadContext; | ||||
|  | ||||
|   class PrefabLoader; | ||||
|   class LoaderForSceneItems; | ||||
|   class SceneLoader; | ||||
|  | ||||
|   class SceneLoadContext { | ||||
|     private: | ||||
|       std::weak_ptr<SceneLoadContext> parent; | ||||
|       std::unordered_map<std::string, std::shared_ptr<SceneItem>> items; | ||||
|       std::unordered_map<std::string, std::shared_ptr<SceneComponent>> components; | ||||
|       std::unordered_map<std::string, std::shared_ptr<AssetLoader>> assets; | ||||
|       std::shared_ptr<Scene> currentScene; | ||||
|       std::shared_ptr<SceneItem> currentItem; | ||||
|       std::shared_ptr<SceneComponent> currentComponent; | ||||
|  | ||||
|     public: | ||||
|       json data; | ||||
|  | ||||
|       /** | ||||
|        * Gets an asset from the context. | ||||
|        *  | ||||
|        * @param j Name of the asset to get. | ||||
|        * @return Asset from the context. | ||||
|        */ | ||||
|       template<class T> | ||||
|       std::shared_ptr<T> getAsset(const std::string &j) const { | ||||
|         auto it = assets.find(j); | ||||
|         if(it == assets.end()) { | ||||
|           auto parent = this->parent.lock(); | ||||
|           assertNotNull(parent, "Couldn't find asset %s", j.c_str()); | ||||
|           return parent->getAsset<T>(j); | ||||
|         } | ||||
|         auto asset = std::dynamic_pointer_cast<T>(it->second); | ||||
|         assertNotNull(asset, "Asset is not of the correct type."); | ||||
|         return asset; | ||||
|       } | ||||
|  | ||||
|       /** | ||||
|        * Gets an item from the context. | ||||
|        *  | ||||
|        * @param j Name of the item to get. | ||||
|        * @return Item from the context. | ||||
|        */ | ||||
|       std::shared_ptr<SceneItem> getItem(const std::string &j); | ||||
|  | ||||
|       /** | ||||
|        * Gets a component from the context. | ||||
|        *  | ||||
|        * @param j Name of the component to get. | ||||
|        * @return Component from the context. | ||||
|        */ | ||||
|       template<class T> | ||||
|       std::shared_ptr<T> getComponent(const std::string &j) const { | ||||
|         auto it = components.find(j); | ||||
|         if(it == components.end()) { | ||||
|           auto parent = this->parent.lock(); | ||||
|           assertNotNull(parent, "Couldn't find component."); | ||||
|           return parent->getComponent<T>(j); | ||||
|         } | ||||
|         auto cmp = std::dynamic_pointer_cast<T>(it->second); | ||||
|         assertNotNull(cmp, "Component is not of the correct type."); | ||||
|         return cmp; | ||||
|       } | ||||
|  | ||||
|       friend class PrefabLoader; | ||||
|       friend class LoaderForSceneItems; | ||||
|       friend class SceneLoader; | ||||
|       friend class SceneItem; | ||||
|   }; | ||||
| } | ||||
| @@ -1,126 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "SceneLoader.hpp" | ||||
| #include "game/Game.hpp" | ||||
| #include "assert/assert.hpp" | ||||
| #include "scene/Scene.hpp" | ||||
| #include "util/JSON.hpp" | ||||
| #include "PrefabLoader.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| const std::string SceneLoader::ASSET_TYPE = "scene"; | ||||
|  | ||||
| SceneLoader::SceneLoader( | ||||
|   const std::shared_ptr<AssetManager> assetManager, | ||||
|   const std::string name | ||||
| ) : | ||||
|   LoaderForSceneItems(assetManager, name), | ||||
|   state(SceneLoaderState::INITIAL) | ||||
| { | ||||
|   this->typetest = this->getAssetType(); | ||||
| } | ||||
|  | ||||
| void SceneLoader::updateAsync() { | ||||
|   switch(this->state) { | ||||
|     case SceneLoaderState::INITIAL: | ||||
|       this->jsonLoader = getAssetManager()->get<JSONLoader>(this->name); | ||||
|       this->state = SceneLoaderState::LOADING_JSON; | ||||
|       break; | ||||
|      | ||||
|     case SceneLoaderState::LOADING_JSON: | ||||
|       assertNotNull(this->jsonLoader, "JSON Loader is NULL?"); | ||||
|       if(!this->jsonLoader->loaded) return; | ||||
|       this->ctx->data = this->jsonLoader->data; | ||||
|       this->setupDependencies(); | ||||
|       this->state = SceneLoaderState::LOADING_DEPENDENCIES; | ||||
|       break; | ||||
|  | ||||
|     case SceneLoaderState::LOADING_DEPENDENCIES: | ||||
|       assertTrue(this->jsonLoader->loaded, "JSON loader not loaded?"); | ||||
|       // Check if all dependencies are loaded. | ||||
|       for(auto &asset : ctx->assets) { | ||||
|         if(!asset.second->loaded) return; | ||||
|       } | ||||
|       ctx->currentScene = std::make_shared<Scene>( | ||||
|         this->getAssetManager()->getGame() | ||||
|       ); | ||||
|       this->state = SceneLoaderState::PENDING_STAGE; | ||||
|       break; | ||||
|      | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void SceneLoader::updateSync() { | ||||
|   if(this->state != SceneLoaderState::PENDING_STAGE) return; | ||||
|   assertNotNull(this->jsonLoader, "JSON Loader is NULL?"); | ||||
|   assertNotNull(ctx, "SceneLoadContext is NULL?"); | ||||
|   assertTrue(this->jsonLoader->loaded, "JSON loader not loaded?"); | ||||
|  | ||||
|   auto &data = this->jsonLoader->data; | ||||
|   if(data.contains("items")) { | ||||
|     // Create the scene items | ||||
|     for(auto &item : data["items"].items()) { | ||||
|       auto &itemName = item.key(); | ||||
|       auto &itemData = item.value(); | ||||
|       auto sceneItem = ctx->currentScene->createSceneItem(); | ||||
|       ctx->items[itemName] = sceneItem; | ||||
|     } | ||||
|  | ||||
|     // Add components to each scene item | ||||
|     for(auto &item : data["items"].items()) { | ||||
|       auto &itemName = item.key(); | ||||
|       auto &itemData = item.value(); | ||||
|       auto sceneItem = ctx->items[itemName]; | ||||
|       sceneItem->name = itemName; | ||||
|  | ||||
|       std::shared_ptr<SceneLoadContext> itemCtx; | ||||
|       if(itemData.contains("prefab")) { | ||||
|         auto prefabLoader = ctx->getAsset<PrefabLoader>( | ||||
|           itemData["prefab"].get<std::string>() | ||||
|         ); | ||||
|         assertNotNull(prefabLoader, "Prefab loader not found"); | ||||
|         assertTrue(prefabLoader->loaded, "Prefab loader not loaded"); | ||||
|         assertNotNull( | ||||
|           prefabLoader->jsonLoader, | ||||
|           "Prefab JSON loader not found" | ||||
|         ); | ||||
|         assertTrue( | ||||
|           prefabLoader->jsonLoader->loaded, | ||||
|           "Prefab JSON loader not loaded" | ||||
|         ); | ||||
|         itemCtx = prefabLoader->ctx; | ||||
|         itemCtx->data = json(prefabLoader->jsonLoader->data); | ||||
|         itemCtx->parent = this->ctx; | ||||
|         JSON::mergeObjectsRecursive(itemCtx->data, itemData); | ||||
|       } else { | ||||
|         itemCtx = this->ctx; | ||||
|         itemCtx->data = json(itemData); | ||||
|       } | ||||
|  | ||||
|       sceneItem->load(itemCtx); | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   this->jsonLoader = nullptr; | ||||
|   this->state = SceneLoaderState::DONE; | ||||
|   this->loaded = true; | ||||
| } | ||||
|  | ||||
| std::string SceneLoader::getAssetType() const { | ||||
|   return SceneLoader::ASSET_TYPE; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<Scene> SceneLoader::getScene() { | ||||
|   assertNotNull(ctx, "Context is NULL?"); | ||||
|   assertNotNull(ctx->currentScene, "Scene not loaded?"); | ||||
|   return ctx->currentScene; | ||||
| } | ||||
|  | ||||
| SceneLoader::~SceneLoader() { | ||||
| } | ||||
| @@ -1,44 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "LoaderForSceneItems.hpp" | ||||
| #include "scene/Scene.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   enum class SceneLoaderState { | ||||
|     INITIAL, | ||||
|     LOADING_JSON, | ||||
|     LOADING_DEPENDENCIES, | ||||
|     PENDING_STAGE, | ||||
|     DONE | ||||
|   }; | ||||
|  | ||||
|   class SceneLoader : public LoaderForSceneItems { | ||||
|     protected: | ||||
|       SceneLoaderState state; | ||||
|  | ||||
|     public: | ||||
|       const static std::string ASSET_TYPE; | ||||
|  | ||||
|       SceneLoader( | ||||
|         const std::shared_ptr<AssetManager> assetManager, | ||||
|         const std::string name | ||||
|       ); | ||||
|        | ||||
|       void updateSync() override; | ||||
|       void updateAsync() override; | ||||
|       std::string getAssetType() const override; | ||||
|  | ||||
|       /** | ||||
|        * Returns the Scene that was loaded, or nullptr if not loaded. | ||||
|        *  | ||||
|        * @return The loaded scene. | ||||
|        */ | ||||
|       std::shared_ptr<Scene> getScene(); | ||||
|  | ||||
|       ~SceneLoader(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| # Copyright (c) 2022 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| # Sources | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     IAudioManager.cpp | ||||
| ) | ||||
| @@ -1,14 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "IAudioManager.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| IAudioManager::IAudioManager() { | ||||
| } | ||||
|  | ||||
| IAudioManager::~IAudioManager() { | ||||
| } | ||||
| @@ -1,32 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "dawn.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class IAudioManager { | ||||
|     public: | ||||
|       /** | ||||
|        * Construct a new IAudioManager. | ||||
|        */ | ||||
|       IAudioManager(); | ||||
|        | ||||
|       /** | ||||
|        * Initializes the audio manager system. | ||||
|        */ | ||||
|       virtual void init() = 0; | ||||
|  | ||||
|       /** | ||||
|        * Ticks/Update the audio manager system. | ||||
|        */ | ||||
|       virtual void update() = 0; | ||||
|  | ||||
|       /** | ||||
|        * Deinitializes the audio manager system. | ||||
|        */ | ||||
|       virtual ~IAudioManager(); | ||||
|   }; | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| # Copyright (c) 2023 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     SceneComponentRegistry.cpp | ||||
| ) | ||||
|  | ||||
| # Subdirs | ||||
| add_subdirectory(display) | ||||
| @@ -1,33 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "SceneComponentRegistry.hpp" | ||||
|  | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| std::unordered_map< | ||||
|   std::string, | ||||
|   std::function<std::shared_ptr<SceneComponent>( | ||||
|     const std::shared_ptr<SceneItem> & | ||||
|   )> | ||||
| > SceneComponentRegistry::REGISTRY = { | ||||
|    | ||||
| }; | ||||
|  | ||||
| std::shared_ptr<SceneComponent> SceneComponentRegistry::createComponent( | ||||
|   const std::string &type, | ||||
|   const std::shared_ptr<SceneItem> &item | ||||
| ) { | ||||
|   auto typeLower = String::toLowercase(type); | ||||
|   assertMapHasKey( | ||||
|     SceneComponentRegistry::REGISTRY, | ||||
|     typeLower, | ||||
|     "Component type not registered: %s", | ||||
|     type.c_str() | ||||
|   ); | ||||
|  | ||||
|   return SceneComponentRegistry::REGISTRY[typeLower](item); | ||||
| } | ||||
| @@ -1,45 +0,0 @@ | ||||
| // Copyright (c) 2024 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "scene/Scene.hpp" | ||||
| #include "util/String.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class SceneComponentRegistry final { | ||||
|     private: | ||||
|      | ||||
|     public: | ||||
|       static std::unordered_map< | ||||
|         std::string, | ||||
|         std::function<std::shared_ptr<SceneComponent>( | ||||
|           const std::shared_ptr<SceneItem> & | ||||
|         )> | ||||
|       > REGISTRY; | ||||
|        | ||||
|       template<class T> | ||||
|       static void reg(const std::string name) { | ||||
|         auto nameLower = String::toLowercase(name); | ||||
|         SceneComponentRegistry::REGISTRY[nameLower] = []( | ||||
|           const std::shared_ptr<SceneItem> &item | ||||
|         ) { | ||||
|           return item->addComponent<T>(); | ||||
|         }; | ||||
|       } | ||||
|  | ||||
|       /** | ||||
|        * Creates a scene component by its type name. Type names are unique and | ||||
|        * must be registered in order to be constructed by their string name. | ||||
|        *  | ||||
|        * @param type Type name of the scene component to create. | ||||
|        * @param item Scene item that the component belongs to. | ||||
|        * @return The created scene component. | ||||
|        */ | ||||
|       static std::shared_ptr<SceneComponent> createComponent( | ||||
|         const std::string &type, | ||||
|         const std::shared_ptr<SceneItem> &item | ||||
|       ); | ||||
|   }; | ||||
| } | ||||
| @@ -1,14 +0,0 @@ | ||||
| # Copyright (c) 2023 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     Camera.cpp | ||||
|     MeshRenderer.cpp | ||||
| ) | ||||
|  | ||||
| # Subdirs | ||||
| add_subdirectory(material) | ||||
| add_subdirectory(mesh) | ||||
| @@ -1,143 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "assert/assert.hpp" | ||||
| #include "Camera.hpp" | ||||
| #include "game/Game.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void Camera::onInit() { | ||||
|   this->onResizeListener = this->getRenderTarget()->onResize.listen([&]( | ||||
|     float_t width, float_t height | ||||
|   ) { | ||||
|     this->onResize.emit(this->getRenderTarget(), width, height); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| void Camera::onDispose() { | ||||
|   renderTarget = nullptr; | ||||
| } | ||||
|  | ||||
| void Camera::load(std::shared_ptr<SceneLoadContext> ctx) { | ||||
|   SceneComponent::load(ctx); | ||||
|  | ||||
|   if(ctx->data.contains("fov")) { | ||||
|     this->fov = Math::deg2rad(ctx->data["fov"].get<float_t>()); | ||||
|   } | ||||
|  | ||||
|   if(ctx->data.contains("cameraType")) { | ||||
|     if( | ||||
|       ctx->data["cameraType"] == "orthogonal" || | ||||
|       ctx->data["cameraType"] == "orthographic" || | ||||
|       ctx->data["cameraType"] == "ortho" | ||||
|     ) { | ||||
|       this->type = CameraType::ORTHOGONAL; | ||||
|     } else if(ctx->data["cameraType"] == "perspective") { | ||||
|       this->type = CameraType::PERSPECTIVE; | ||||
|     } else { | ||||
|       assertUnreachable("Invalid Camera Type!"); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if(ctx->data.contains("orthoLeft")) { | ||||
|     this->orthoLeft = ctx->data["orthoLeft"].get<float_t>(); | ||||
|   } else if(ctx->data.contains("left")) { | ||||
|     this->orthoLeft = ctx->data["left"].get<float_t>(); | ||||
|   } | ||||
|  | ||||
|   if(ctx->data.contains("orthoRight")) { | ||||
|     this->orthoRight = ctx->data["orthoRight"].get<float_t>(); | ||||
|   } else if(ctx->data.contains("right")) { | ||||
|     this->orthoRight = ctx->data["right"].get<float_t>(); | ||||
|   } | ||||
|  | ||||
|   if(ctx->data.contains("orthoBottom")) { | ||||
|     this->orthoBottom = ctx->data["orthoBottom"].get<float_t>(); | ||||
|   } else if(ctx->data.contains("bottom")) { | ||||
|     this->orthoBottom = ctx->data["bottom"].get<float_t>(); | ||||
|   } | ||||
|  | ||||
|   if(ctx->data.contains("orthoTop")) { | ||||
|     this->orthoTop = ctx->data["orthoTop"].get<float_t>(); | ||||
|   } else if(ctx->data.contains("top")) { | ||||
|     this->orthoTop = ctx->data["top"].get<float_t>(); | ||||
|   } | ||||
|  | ||||
|   if(ctx->data.contains("clipNear")) { | ||||
|     this->clipNear = ctx->data["clipNear"].get<float_t>(); | ||||
|   } else if(ctx->data.contains("near")) { | ||||
|     this->clipNear = ctx->data["near"].get<float_t>(); | ||||
|   } else if(ctx->data.contains("zNear")) { | ||||
|     this->clipNear = ctx->data["zNear"].get<float_t>(); | ||||
|   } | ||||
|  | ||||
|   if(ctx->data.contains("clipFar")) { | ||||
|     this->clipFar = ctx->data["clipFar"].get<float_t>(); | ||||
|   } else if(ctx->data.contains("far")) { | ||||
|     this->clipFar = ctx->data["far"].get<float_t>(); | ||||
|   } else if(ctx->data.contains("zFar")) { | ||||
|     this->clipFar = ctx->data["zFar"].get<float_t>(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| std::shared_ptr<RenderTarget> Camera::getRenderTarget() { | ||||
|   if(this->renderTarget) return this->renderTarget; | ||||
|   return getGame()->renderHost->getBackBufferRenderTarget(); | ||||
| } | ||||
|  | ||||
| glm::mat4 Camera::getProjection() { | ||||
|   switch(this->type) { | ||||
|     case CameraType::ORTHOGONAL: | ||||
|       return glm::ortho( | ||||
|         (float_t)this->orthoLeft, | ||||
|         (float_t)this->orthoRight, | ||||
|         (float_t)this->orthoBottom, | ||||
|         (float_t)this->orthoTop, | ||||
|         (float_t)this->clipNear, | ||||
|         (float_t)this->clipFar | ||||
|       ); | ||||
|  | ||||
|     case CameraType::PERSPECTIVE: | ||||
|       return glm::perspective( | ||||
|         (float_t)this->fov, | ||||
|         this->getAspect(), | ||||
|         (float_t)this->clipNear, | ||||
|         (float_t)this->clipFar | ||||
|       ); | ||||
|   } | ||||
|  | ||||
|   assertUnreachable("Invalid Camera Type!"); | ||||
|   return glm::mat4(1.0f); | ||||
| } | ||||
|  | ||||
| float_t Camera::getAspect() { | ||||
|   auto rt = this->getRenderTarget(); | ||||
|   return rt->getWidth() / rt->getHeight(); | ||||
| } | ||||
|  | ||||
| float_t Camera::lookAtPixelPerfect( | ||||
|   const glm::vec3 &position, | ||||
|   const glm::vec3 &look, | ||||
|   const float_t &scale | ||||
| ) { | ||||
|   return this->getItem()->lookAtPixelPerfect( | ||||
|     position, | ||||
|     look, | ||||
|     this->getRenderTarget()->getHeight(), | ||||
|     this->fov, | ||||
|     scale | ||||
|   ); | ||||
| } | ||||
|  | ||||
| void Camera::setRenderTarget(const std::shared_ptr<RenderTarget> renderTarget) { | ||||
|   onResizeListener(); | ||||
|   this->renderTarget = renderTarget; | ||||
|   this->onResizeListener = this->getRenderTarget()->onResize.listen([&]( | ||||
|     float_t width, float_t height | ||||
|   ) { | ||||
|     this->onResize.emit(this->getRenderTarget(), width, height); | ||||
|   }); | ||||
| } | ||||
| @@ -1,82 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "scene/SceneItem.hpp" | ||||
| #include "display/RenderTarget.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   enum class CameraType { | ||||
|     PERSPECTIVE, | ||||
|     ORTHOGONAL | ||||
|   }; | ||||
|  | ||||
|   class Camera final : public SceneComponent { | ||||
|     private: | ||||
|       std::shared_ptr<RenderTarget> renderTarget; | ||||
|       std::function<void()> onResizeListener; | ||||
|  | ||||
|     public: | ||||
|       Event<std::shared_ptr<RenderTarget>, float_t, float_t> onResize; | ||||
|       float_t clipNear = 0.01f; | ||||
|       float_t clipFar = 1000.0f; | ||||
|       enum CameraType type = CameraType::PERSPECTIVE; | ||||
|  | ||||
|       float_t fov = 0.785398f; | ||||
|  | ||||
|       float_t orthoLeft = -1.0f; | ||||
|       float_t orthoRight = 1.0f; | ||||
|       float_t orthoBottom = -1.0f; | ||||
|       float_t orthoTop = 1.0f; | ||||
|  | ||||
|       void onInit() override; | ||||
|       void onDispose() override; | ||||
|       void load(std::shared_ptr<SceneLoadContext> ctx) override; | ||||
|  | ||||
|       /** | ||||
|        * Returns the aspect ratio that the camera is using. In future I may  | ||||
|        * allow you to specify a custom ratio for stylistic reasons but for now I | ||||
|        * just take the ratio of the specific frame buffer. | ||||
|        *  | ||||
|        * @return The aspect ratio as a ratio of w/h. | ||||
|        */ | ||||
|       float_t getAspect(); | ||||
|  | ||||
|       /** | ||||
|        * Returns the render target for this camera. | ||||
|        *  | ||||
|        * @return Render target. | ||||
|        */ | ||||
|       std::shared_ptr<RenderTarget> getRenderTarget(); | ||||
|  | ||||
|       /** | ||||
|        * Returns the projection matrix for this camera. | ||||
|        *  | ||||
|        * @return Projection matrix. | ||||
|        */ | ||||
|       glm::mat4 getProjection(); | ||||
|  | ||||
|       /** | ||||
|        * Shorthand for getItem()->lookAtPixelPerfect() | ||||
|        *  | ||||
|        * @param position Position to look from. | ||||
|        * @param look Position to look at. | ||||
|        * @param scale Scale to use. At scale 1 then the centerest pixel is 1:1. | ||||
|        * @return The Z distance that was calculated. | ||||
|        */ | ||||
|       float_t lookAtPixelPerfect( | ||||
|         const glm::vec3 &position, | ||||
|         const glm::vec3 &look, | ||||
|         const float_t &scale = 1.0f | ||||
|       ); | ||||
|  | ||||
|       /** | ||||
|        * Sets the render target for this camera. | ||||
|        *  | ||||
|        * @param renderTarget The render target to set. | ||||
|        */ | ||||
|       void setRenderTarget(const std::shared_ptr<RenderTarget> renderTarget); | ||||
|   }; | ||||
| } | ||||
| @@ -1,56 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "display/pass/RenderPass.hpp" | ||||
| #include "display/pass/RenderPassContext.hpp" | ||||
| #include "display/mesh/Mesh.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class IRenderableComponent { | ||||
|     public: | ||||
|       /** | ||||
|        * Retreive the list of render passes for this component. | ||||
|        *  | ||||
|        * @param ctx Context for the render pass. | ||||
|        * @return List of render passes. | ||||
|        */ | ||||
|       virtual std::vector<std::shared_ptr<RenderPass>> getPasses( | ||||
|         struct RenderPassContext &ctx | ||||
|       ) = 0; | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * Short-hand function to create a render pass. | ||||
|    *  | ||||
|    * @tparam S Shader type. | ||||
|    * @tparam D Shader's data type | ||||
|    * @param self Instance of the IRenderableComponent that is creating the pass. | ||||
|    * @param data Data to use for the render pass. | ||||
|    * @return Created render pass. | ||||
|    */ | ||||
|   // template<class S, typename D> | ||||
|   // std::shared_ptr<IRenderPass> createRenderPass( | ||||
|   //   SceneComponent &self, | ||||
|   //   const D data, | ||||
|   //   const std::unordered_map< | ||||
|   //     shadertexturebinding_t, std::shared_ptr<Texture> | ||||
|   //   > textures = {}, | ||||
|   //   const std::shared_ptr<Mesh> mesh = nullptr, | ||||
|   //   const enum MeshDrawMode drawMode = MeshDrawMode::TRIANGLES, | ||||
|   //   int32_t indiceStart = 0, | ||||
|   //   int32_t indiceCount = -1 | ||||
|   // ) { | ||||
|   //   return std::make_shared<RenderPass<S,D>>( | ||||
|   //     self, | ||||
|   //     data, | ||||
|   //     textures, | ||||
|   //     mesh, | ||||
|   //     drawMode, | ||||
|   //     indiceStart, | ||||
|   //     indiceCount | ||||
|   //   ); | ||||
|   // } | ||||
| } | ||||
| @@ -1,16 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "MeshRenderer.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void MeshRenderer::onInit() { | ||||
|  | ||||
| } | ||||
|  | ||||
| void MeshRenderer::onDispose() { | ||||
|   mesh = nullptr; | ||||
| } | ||||
| @@ -1,18 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "display/mesh/Mesh.hpp" | ||||
| #include "scene/SceneItem.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class MeshRenderer final : public SceneComponent { | ||||
|     public: | ||||
|       std::shared_ptr<Mesh> mesh; | ||||
|  | ||||
|       void onInit() override; | ||||
|       void onDispose() override; | ||||
|   }; | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| # Copyright (c) 2023 Dominic Masters | ||||
| #  | ||||
| # This software is released under the MIT License. | ||||
| # https://opensource.org/licenses/MIT | ||||
|  | ||||
| target_sources(${DAWN_TARGET_NAME} | ||||
|   PRIVATE | ||||
|     Material.cpp | ||||
|     SimpleTexturedMaterial.cpp | ||||
| ) | ||||
| @@ -1,16 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "Material.hpp" | ||||
| #include "game/Game.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void Material::onInit() { | ||||
|   this->initShaderPrograms(); | ||||
| } | ||||
|  | ||||
| void Material::onDispose() { | ||||
| } | ||||
| @@ -1,27 +0,0 @@ | ||||
| // Copyright (c) 2023 Dominic Masters | ||||
| //  | ||||
| // This software is released under the MIT License. | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #pragma once | ||||
| #include "scene/SceneComponent.hpp" | ||||
| #include "component/display/IRenderableComponent.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class Material : | ||||
|     public SceneComponent, | ||||
|     public IRenderableComponent | ||||
|   { | ||||
|     protected: | ||||
|       /** | ||||
|        * Load the shaders for this material. | ||||
|        */ | ||||
|       virtual void initShaderPrograms( | ||||
|          | ||||
|       ) = 0; | ||||
|  | ||||
|     public: | ||||
|       void onInit() override; | ||||
|       void onDispose() override; | ||||
|   }; | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user