├── resources
├── Materials
│ ├── Text.mat
│ ├── GUI
│ │ ├── Label.mat
│ │ └── Label.mat.meta
│ └── Text.mat.meta
└── Shaders
│ ├── VertexColor.shader
│ ├── FlatColor.shader
│ ├── Diffuse.shader
│ ├── Skybox.shader
│ ├── Font.shader
│ ├── Lambert.shader
│ └── Sprite.shader
├── docs
├── Logo.png
├── AssetManager.png
├── Text.md
├── Entity.md
└── AssetManager.md
├── tools
├── AssetManager
│ ├── Resources
│ │ ├── Delete.png
│ │ ├── Error.png
│ │ ├── Expand.png
│ │ ├── Folder.png
│ │ ├── Search.png
│ │ ├── Building.ico
│ │ ├── Collapse.png
│ │ ├── Correct.png
│ │ ├── JewelIcon.ico
│ │ ├── Settings.ico
│ │ └── Settings.png
│ ├── App.config
│ ├── Properties
│ │ ├── Settings.settings
│ │ ├── Settings.Designer.cs
│ │ └── AssemblyInfo.cs
│ ├── workspace_templates
│ │ ├── open_asset_manager.cmd
│ │ ├── update_metadata.cmd
│ │ ├── pack_assets.cmd
│ │ └── config.workspace
│ ├── Program.cs
│ ├── WorkspaceConfig.cs
│ ├── Settings.cs
│ ├── RichTextBoxStreamWriter.cs
│ └── FileCache.cs
├── CMakeLists.txt
├── FontEncoder
│ ├── main.cpp
│ ├── CMakeLists.txt
│ └── FontEncoder.h
├── MeshEncoder
│ ├── main.cpp
│ ├── CMakeLists.txt
│ └── MeshEncoder.h
├── SoundEncoder
│ ├── main.cpp
│ ├── CMakeLists.txt
│ └── SoundEncoder.h
├── TextureEncoder
│ ├── main.cpp
│ ├── CMakeLists.txt
│ └── TextureEncoder.h
└── MaterialEncoder
│ ├── main.cpp
│ ├── CMakeLists.txt
│ └── MaterialEncoder.h
├── .gitignore
├── gemcutter
├── Resource
│ ├── Resource.cpp
│ ├── Material.h
│ ├── Model.h
│ ├── ParticleBuffer.h
│ ├── Shareable.h
│ ├── ParticleFunctor.cpp
│ ├── ConfigTable.h
│ ├── Font.h
│ ├── ParticleFunctor.h
│ ├── Sound.h
│ ├── Material.cpp
│ ├── Model.cpp
│ ├── Resource.h
│ └── UniformBuffer.inl
├── Rendering
│ ├── Viewport.h
│ ├── Viewport.cpp
│ ├── Mesh.h
│ ├── Text.h
│ ├── Renderable.h
│ ├── Mesh.cpp
│ ├── Light.h
│ ├── Sprite.h
│ ├── Sprite.cpp
│ ├── Renderable.cpp
│ ├── Primitives.h
│ ├── RenderPass.h
│ ├── Light.cpp
│ ├── Text.cpp
│ └── ParticleEmitter.h
├── GUI
│ ├── Rectangle.h
│ ├── Widget.inl
│ ├── Rectangle.cpp
│ ├── Screen.h
│ ├── Image.h
│ ├── Screen.cpp
│ ├── Label.h
│ ├── Button.h
│ ├── Widget.h
│ ├── Image.cpp
│ ├── Label.cpp
│ └── Widget.cpp
├── Entity
│ ├── Hierarchy.inl
│ ├── Name.h
│ ├── Name.cpp
│ └── Hierarchy.h
├── Math
│ ├── Math.cpp
│ ├── Transform.h
│ ├── Quaternion.h
│ └── Transform.cpp
├── Application
│ ├── HierarchicalEvent.cpp
│ ├── Event.cpp
│ ├── Delegate.cpp
│ ├── Event.inl
│ ├── CmdArgs.h
│ ├── Timer.h
│ ├── Reflection.inl
│ ├── Reflection.cpp
│ ├── Reflection.h
│ ├── HierarchicalEvent.h
│ ├── Logging.h
│ ├── CmdArgs.cpp
│ ├── Timer.cpp
│ └── Event.h
├── Sound
│ ├── SoundSystem.h
│ ├── SoundListener.h
│ ├── SoundSource.h
│ ├── SoundListener.cpp
│ ├── SoundSource.cpp
│ └── SoundSystem.cpp
├── Utilities
│ ├── Random.h
│ ├── Identifier.h
│ ├── EnumFlags.h
│ ├── StdExt.h
│ ├── String.h
│ ├── Random.cpp
│ └── ScopeGuard.h
├── AI
│ └── ProbabilityMatrix.h
└── Input
│ ├── XboxGamePad.h
│ └── Input.h
├── tests
├── WeakPtr.cpp
├── CMakeLists.txt
├── main.cpp
├── FileSystem.cpp
├── Math.cpp
├── String.cpp
├── EnumFlags.cpp
└── Meta.cpp
├── .vscode
├── launch.json
├── cmake-variants.json
└── c_cpp_properties.json
├── .editorconfig
├── .gitmodules
├── LICENSE
├── CMakeLists.txt
├── external
└── CMakeLists.txt
└── README.md
/resources/Materials/Text.mat:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/Materials/GUI/Label.mat:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/docs/Logo.png
--------------------------------------------------------------------------------
/docs/AssetManager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/docs/AssetManager.png
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Delete.png
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Error.png
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Expand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Expand.png
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Folder.png
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Search.png
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Building.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Building.ico
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Collapse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Collapse.png
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Correct.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Correct.png
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/JewelIcon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/JewelIcon.ico
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Settings.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Settings.ico
--------------------------------------------------------------------------------
/tools/AssetManager/Resources/Settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EmilianC/Gemcutter/HEAD/tools/AssetManager/Resources/Settings.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Log_Output.txt
2 | *.opendb
3 | *.TMP
4 | *.VC.db
5 | *.pdb
6 | *.user
7 | .vscode/
8 |
9 | # Likely CMake build locations
10 | build/
11 | gen/
12 | generated/
13 |
--------------------------------------------------------------------------------
/resources/Materials/GUI/Label.mat.meta:
--------------------------------------------------------------------------------
1 | blend_mode=Linear
2 | cull_mode=None
3 | depth_mode=None
4 | shader=Engine/Shaders/Font.shader
5 | texture_bind_points=
6 | textures=
7 | version=2
8 |
--------------------------------------------------------------------------------
/resources/Materials/Text.mat.meta:
--------------------------------------------------------------------------------
1 | blend_mode=Linear
2 | cull_mode=Clockwise
3 | depth_mode=Normal
4 | shader=Engine/Shaders/font.shader
5 | texture_bind_points=
6 | textures=
7 | version=2
8 |
--------------------------------------------------------------------------------
/gemcutter/Resource/Resource.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023 Emilian Cioca
2 | #include "Resource.h"
3 |
4 | REFLECT(gem::ResourceBase)
5 | MEMBERS {
6 | REF_PRIVATE_MEMBER(path, readonly())
7 | }
8 | REF_END;
9 |
--------------------------------------------------------------------------------
/tools/AssetManager/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tools/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(CMAKE_FOLDER "${CMAKE_FOLDER}/tools")
2 | add_subdirectory(FontEncoder)
3 | add_subdirectory(MaterialEncoder)
4 | add_subdirectory(MeshEncoder)
5 | add_subdirectory(SoundEncoder)
6 | add_subdirectory(TextureEncoder)
7 |
8 | add_subdirectory(AssetManager)
9 |
--------------------------------------------------------------------------------
/tools/AssetManager/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/docs/Text.md:
--------------------------------------------------------------------------------
1 | # Text Resources
2 | Before rendering Text, you must generate and load a .font file containing the pre-rendered characters.
3 | By default, any .ttf can be converted to a .font using the AssetManager.
4 |
5 | ```cpp
6 | auto font = Load("Fonts/Arial.font");
7 | entity->Add("Hello World!", font);
8 | ```
--------------------------------------------------------------------------------
/gemcutter/Rendering/Viewport.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 |
4 | namespace gem
5 | {
6 | struct Viewport
7 | {
8 | void bind() const;
9 | float GetAspectRatio() const;
10 |
11 | unsigned x = 0;
12 | unsigned y = 0;
13 | unsigned width = 1;
14 | unsigned height = 1;
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/tools/FontEncoder/main.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "FontEncoder.h"
3 |
4 | #include
5 |
6 | int main()
7 | {
8 | gem::InitializeReflectionTables();
9 |
10 | auto encoder = FontEncoder();
11 |
12 | if (!gem::Encoder::RunEncoder(encoder))
13 | {
14 | return EXIT_FAILURE;
15 | }
16 |
17 | return EXIT_SUCCESS;
18 | }
19 |
--------------------------------------------------------------------------------
/tools/MeshEncoder/main.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "MeshEncoder.h"
3 |
4 | #include
5 |
6 | int main()
7 | {
8 | gem::InitializeReflectionTables();
9 |
10 | auto encoder = MeshEncoder();
11 |
12 | if (!gem::Encoder::RunEncoder(encoder))
13 | {
14 | return EXIT_FAILURE;
15 | }
16 |
17 | return EXIT_SUCCESS;
18 | }
19 |
--------------------------------------------------------------------------------
/tools/SoundEncoder/main.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Emilian Cioca
2 | #include "SoundEncoder.h"
3 |
4 | #include
5 |
6 | int main()
7 | {
8 | gem::InitializeReflectionTables();
9 |
10 | auto encoder = SoundEncoder();
11 |
12 | if (!gem::Encoder::RunEncoder(encoder))
13 | {
14 | return EXIT_FAILURE;
15 | }
16 |
17 | return EXIT_SUCCESS;
18 | }
19 |
--------------------------------------------------------------------------------
/tools/TextureEncoder/main.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Emilian Cioca
2 | #include "TextureEncoder.h"
3 |
4 | #include
5 |
6 | int main()
7 | {
8 | gem::InitializeReflectionTables();
9 |
10 | auto encoder = TextureEncoder();
11 |
12 | if (!gem::Encoder::RunEncoder(encoder))
13 | {
14 | return EXIT_FAILURE;
15 | }
16 |
17 | return EXIT_SUCCESS;
18 | }
19 |
--------------------------------------------------------------------------------
/resources/Shaders/VertexColor.shader:
--------------------------------------------------------------------------------
1 | Attributes
2 | {
3 | vec4 a_vert : 0;
4 | vec4 a_color : 1;
5 | }
6 |
7 | Vertex
8 | {
9 | out vec4 color;
10 |
11 | void main()
12 | {
13 | color = a_color;
14 | gl_Position = Gem_MVP * a_vert;
15 | }
16 | }
17 |
18 | Fragment
19 | {
20 | in vec4 color;
21 | out vec4 outColor;
22 |
23 | void main()
24 | {
25 | outColor = color;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tools/MaterialEncoder/main.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Emilian Cioca
2 | #include "MaterialEncoder.h"
3 |
4 | #include
5 |
6 | int main()
7 | {
8 | gem::InitializeReflectionTables();
9 |
10 | auto encoder = MaterialEncoder();
11 |
12 | if (!gem::Encoder::RunEncoder(encoder))
13 | {
14 | return EXIT_FAILURE;
15 | }
16 |
17 | return EXIT_SUCCESS;
18 | }
19 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Rectangle.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #pragma once
3 |
4 | namespace gem
5 | {
6 | struct vec2;
7 |
8 | struct Rectangle
9 | {
10 | float GetAspectRatio() const;
11 | bool Contains(float x, float y) const;
12 | bool Contains(const vec2& pos) const;
13 |
14 | float x = 0.0f;
15 | float y = 0.0f;
16 | float width = 1.0f;
17 | float height = 1.0f;
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/gemcutter/Entity/Hierarchy.inl:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Emilian Cioca
2 | namespace gem
3 | {
4 | template
5 | void Hierarchy::ForEachChild(this Self& self, bool recursive, Functor&& Func)
6 | {
7 | for (auto& entity : self.children)
8 | {
9 | Func(*entity);
10 |
11 | if (recursive)
12 | {
13 | entity->Get().ForEachChild(true, Func);
14 | }
15 | }
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Widget.inl:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | namespace gem
3 | {
4 | template
5 | T& Widget::CreateChild(Args&&... constructorParams)
6 | {
7 | static_assert(std::is_base_of_v, "Template argument must be a Widget.");
8 |
9 | auto entity = owner.Get().CreateChild();
10 | return entity->Add(std::forward(constructorParams)...);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/resources/Shaders/FlatColor.shader:
--------------------------------------------------------------------------------
1 | Attributes
2 | {
3 | vec4 a_vert : 0;
4 | }
5 |
6 | Uniforms
7 | {
8 | instance Material : 0
9 | {
10 | vec4 Color = (0.0, 0.0, 0.0, 1.0);
11 | }
12 | }
13 |
14 | Vertex
15 | {
16 | void main()
17 | {
18 | gl_Position = Gem_MVP * a_vert;
19 | }
20 | }
21 |
22 | Fragment
23 | {
24 | out vec4 outColor;
25 |
26 | void main()
27 | {
28 | outColor = Material.Color;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tools/MeshEncoder/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | list(APPEND mesh_encoder_files
2 | "main.cpp"
3 | "MeshEncoder.h"
4 | "MeshEncoder.cpp"
5 | )
6 |
7 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${mesh_encoder_files})
8 |
9 | add_executable(mesh_encoder ${mesh_encoder_files})
10 | sf_target_compile_warnings(mesh_encoder)
11 | sf_target_compile_warnings_as_errors(mesh_encoder OPTIONAL)
12 |
13 | target_link_libraries(mesh_encoder PRIVATE gemcutter)
14 |
--------------------------------------------------------------------------------
/gemcutter/Math/Math.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "Math.h"
3 |
4 | namespace gem
5 | {
6 | float SnapToGrid(float value, float step)
7 | {
8 | return std::floorf((value + (step / 2.0f)) / step) * step;
9 | }
10 |
11 | float EaseIn(float percent)
12 | {
13 | return 1.0f - cosf(percent * (M_PI / 2.0f));
14 | }
15 |
16 | float EaseOut(float percent)
17 | {
18 | return cosf((percent - 1.0f) * (M_PI / 2.0f));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tools/SoundEncoder/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | list(APPEND sound_encoder_files
2 | "main.cpp"
3 | "SoundEncoder.h"
4 | "SoundEncoder.cpp"
5 | )
6 |
7 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${sound_encoder_files})
8 |
9 | add_executable(sound_encoder ${sound_encoder_files})
10 | sf_target_compile_warnings(sound_encoder)
11 | sf_target_compile_warnings_as_errors(sound_encoder OPTIONAL)
12 |
13 | target_link_libraries(sound_encoder
14 | PRIVATE
15 | gemcutter
16 | )
17 |
--------------------------------------------------------------------------------
/tools/FontEncoder/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | list(APPEND font_encoder_files
2 | "main.cpp"
3 | "FontEncoder.h"
4 | "FontEncoder.cpp"
5 | )
6 |
7 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${font_encoder_files})
8 |
9 | add_executable(font_encoder ${font_encoder_files})
10 | sf_target_compile_warnings(font_encoder)
11 | sf_target_compile_warnings_as_errors(font_encoder OPTIONAL)
12 |
13 | target_link_libraries(font_encoder
14 | PRIVATE
15 | gemcutter
16 | freetype
17 | )
18 |
--------------------------------------------------------------------------------
/resources/Shaders/Diffuse.shader:
--------------------------------------------------------------------------------
1 | Attributes
2 | {
3 | vec4 a_vert : 0;
4 | vec2 a_uv : 1;
5 | }
6 |
7 | Vertex
8 | {
9 | out vec2 texcoord;
10 |
11 | void main()
12 | {
13 | gl_Position = Gem_MVP * a_vert;
14 | texcoord = a_uv;
15 | }
16 | }
17 |
18 | Samplers
19 | {
20 | sampler2D sTex : 0;
21 | }
22 |
23 | Fragment
24 | {
25 | in vec2 texcoord;
26 | out vec3 outColor;
27 |
28 | void main()
29 | {
30 | outColor = texture(sTex, texcoord).rgb;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tools/MaterialEncoder/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | list(APPEND material_encoder_files
2 | "main.cpp"
3 | "MaterialEncoder.h"
4 | "MaterialEncoder.cpp"
5 | )
6 |
7 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${material_encoder_files})
8 |
9 | add_executable(material_encoder ${material_encoder_files})
10 | sf_target_compile_warnings(material_encoder)
11 | sf_target_compile_warnings_as_errors(material_encoder OPTIONAL)
12 |
13 | target_link_libraries(material_encoder PRIVATE gemcutter)
14 |
--------------------------------------------------------------------------------
/tools/TextureEncoder/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | list(APPEND texture_encoder_files
2 | "main.cpp"
3 | "TextureEncoder.h"
4 | "TextureEncoder.cpp"
5 | )
6 |
7 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${texture_encoder_files})
8 |
9 | add_executable(texture_encoder ${texture_encoder_files})
10 | sf_target_compile_warnings(texture_encoder)
11 | sf_target_compile_warnings_as_errors(texture_encoder OPTIONAL)
12 |
13 | target_link_libraries(texture_encoder
14 | PRIVATE
15 | gemcutter
16 | soil2
17 | )
18 |
--------------------------------------------------------------------------------
/tests/WeakPtr.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace gem;
5 |
6 | TEST_CASE("WeakPtr")
7 | {
8 | std::shared_ptr shared = std::make_shared(1);
9 | std::weak_ptr weak = shared;
10 | std::weak_ptr weakNull;
11 | std::weak_ptr weakExpired = std::make_shared(1);
12 |
13 | SECTION("Null Checks")
14 | {
15 | CHECK(!IsPtrNull(weak));
16 | CHECK(IsPtrNull(weakNull));
17 | CHECK(!IsPtrNull(weakExpired));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | list(APPEND unit_test_files
2 | "Delegate.cpp"
3 | "EntityComponentSystem.cpp"
4 | "EnumFlags.cpp"
5 | "FileSystem.cpp"
6 | "Hierarchy.cpp"
7 | "main.cpp"
8 | "Math.cpp"
9 | "Meta.cpp"
10 | "String.cpp"
11 | "WeakPtr.cpp"
12 | )
13 |
14 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${unit_test_files})
15 |
16 | add_executable(unit_tests ${unit_test_files})
17 | sf_target_compile_warnings(unit_tests)
18 |
19 | target_link_libraries(unit_tests
20 | PRIVATE
21 | gemcutter
22 | catch
23 | )
24 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
3 | "version": "0.2.0",
4 | "configurations": [
5 | {
6 | "name": "Launch",
7 | "request": "launch",
8 | "type": "cppvsdbg",
9 | "program": "${command:cmake.launchTargetPath}",
10 | "args": [],
11 | "cwd": "${workspaceFolder}\\samples",
12 | "visualizerFile": "${workspaceFolder}\\gemcutter\\Gemcutter.natvis",
13 | "environment": []
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/resources/Shaders/Skybox.shader:
--------------------------------------------------------------------------------
1 | Attributes
2 | {
3 | vec3 a_vert : 0;
4 | }
5 |
6 | Vertex
7 | {
8 | out vec3 texcoord;
9 |
10 | void main()
11 | {
12 | texcoord = a_vert;
13 | // After the perspective divide, Z will be very close to 1.0
14 | gl_Position = (Gem_ViewProj * vec4(a_vert, 0.0)).xyww;
15 | gl_Position.w *= 1.0001;
16 | }
17 | }
18 |
19 | Samplers
20 | {
21 | samplerCube sTex : 0;
22 | }
23 |
24 | Fragment
25 | {
26 | in vec3 texcoord;
27 | out vec4 outColor;
28 |
29 | void main()
30 | {
31 | outColor = texture(sTex, texcoord);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tests/main.cpp:
--------------------------------------------------------------------------------
1 | #define CATCH_CONFIG_RUNNER
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | int main(int argc, char** argv)
10 | {
11 | gem::InitializeReflectionTables();
12 |
13 | const int result = Catch::Session().run(argc, argv);
14 | if (result != 0)
15 | {
16 | std::println("Press any key to continue...");
17 | std::cin.get();
18 | }
19 | else
20 | {
21 | std::this_thread::sleep_for(std::chrono::seconds(1));
22 | }
23 |
24 | return result;
25 | }
26 |
--------------------------------------------------------------------------------
/tools/AssetManager/workspace_templates/open_asset_manager.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | :: Prefer the Release version if it exists.
4 | if exist "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/asset_manager.exe" (
5 | start "" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/asset_manager.exe"
6 | goto :EOF
7 | )
8 |
9 | if exist "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/RelWithDebInfo/asset_manager.exe" (
10 | start "" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/RelWithDebInfo/asset_manager.exe"
11 | goto :EOF
12 | )
13 |
14 | start "" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/asset_manager.exe"
15 |
--------------------------------------------------------------------------------
/.vscode/cmake-variants.json:
--------------------------------------------------------------------------------
1 | {
2 | "buildType": {
3 | "default": "debug",
4 | "description": "The build type.",
5 | "choices": {
6 | "debug": {
7 | "short": "Debug",
8 | "long": "Optimizations disabled.",
9 | "buildType": "Debug"
10 | },
11 | "development": {
12 | "short": "Development",
13 | "long": "Optimizations enabled with development tools.",
14 | "buildType": "RelWithDebInfo"
15 | },
16 | "production": {
17 | "short": "Production",
18 | "long": "Optimizations enabled without development tools.",
19 | "buildType": "Release"
20 | }
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/tools/FontEncoder/FontEncoder.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include
4 |
5 | class FontEncoder final : public gem::Encoder
6 | {
7 | public:
8 | FontEncoder();
9 |
10 | gem::ConfigTable GetDefault() const override;
11 |
12 | bool Validate(const gem::ConfigTable& metadata, unsigned loadedVersion) const override;
13 |
14 | private:
15 | bool Convert(std::string_view source, std::string_view destination, const gem::ConfigTable& metadata) const override;
16 |
17 | bool Upgrade(gem::ConfigTable& metadata, unsigned loadedVersion) const override;
18 | };
19 |
--------------------------------------------------------------------------------
/tools/MeshEncoder/MeshEncoder.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include
4 |
5 | class MeshEncoder final : public gem::Encoder
6 | {
7 | public:
8 | MeshEncoder();
9 |
10 | gem::ConfigTable GetDefault() const override;
11 |
12 | bool Validate(const gem::ConfigTable& metadata, unsigned loadedVersion) const override;
13 |
14 | private:
15 | bool Convert(std::string_view source, std::string_view destination, const gem::ConfigTable& metadata) const override;
16 |
17 | bool Upgrade(gem::ConfigTable& metadata, unsigned loadedVersion) const override;
18 | };
19 |
--------------------------------------------------------------------------------
/tools/SoundEncoder/SoundEncoder.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Emilian Cioca
2 | #pragma once
3 | #include
4 |
5 | class SoundEncoder final : public gem::Encoder
6 | {
7 | public:
8 | SoundEncoder();
9 |
10 | gem::ConfigTable GetDefault() const override;
11 |
12 | bool Validate(const gem::ConfigTable& metadata, unsigned loadedVersion) const override;
13 |
14 | private:
15 | bool Convert(std::string_view source, std::string_view destination, const gem::ConfigTable& metadata) const override;
16 |
17 | bool Upgrade(gem::ConfigTable& metadata, unsigned loadedVersion) const override;
18 | };
19 |
--------------------------------------------------------------------------------
/tools/MaterialEncoder/MaterialEncoder.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Emilian Cioca
2 | #pragma once
3 | #include
4 |
5 | class MaterialEncoder final : public gem::Encoder
6 | {
7 | public:
8 | MaterialEncoder();
9 |
10 | gem::ConfigTable GetDefault() const override;
11 |
12 | bool Validate(const gem::ConfigTable& metadata, unsigned loadedVersion) const override;
13 |
14 | private:
15 | bool Convert(std::string_view source, std::string_view destination, const gem::ConfigTable& metadata) const override;
16 |
17 | bool Upgrade(gem::ConfigTable& metadata, unsigned loadedVersion) const override;
18 | };
19 |
--------------------------------------------------------------------------------
/tools/TextureEncoder/TextureEncoder.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Emilian Cioca
2 | #pragma once
3 | #include
4 |
5 | class TextureEncoder final : public gem::Encoder
6 | {
7 | public:
8 | TextureEncoder();
9 |
10 | gem::ConfigTable GetDefault() const override;
11 |
12 | bool Validate(const gem::ConfigTable& metadata, unsigned loadedVersion) const override;
13 |
14 | private:
15 | bool Convert(std::string_view source, std::string_view destination, const gem::ConfigTable& metadata) const override;
16 |
17 | bool Upgrade(gem::ConfigTable& metadata, unsigned loadedVersion) const override;
18 | };
19 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://EditorConfig.org
2 | root = true
3 |
4 | # Global
5 | [*]
6 | charset = utf-8
7 | indent_style = tab
8 | indent_size = 4
9 | tab_width = 4
10 |
11 | # c++, c#
12 | [*.{c,cs,cpp,h,inl}]
13 | curly_bracket_next_line=true
14 | indent_brace_style=Allman
15 | insert_final_newline=true
16 | trim_trailing_whitespace=true
17 |
18 | # MSBuild
19 | [*.{csproj,vcxproj}]
20 | indent_style = space
21 | indent_size = 2
22 |
23 | # Config files
24 | [*.{config,resx,xml,cache,workspace,natvis}]
25 | indent_style = space
26 | indent_size = 2
27 |
28 | # Batch files
29 | [*.cmd]
30 | indent_style = space
31 | indent_size = 4
32 |
--------------------------------------------------------------------------------
/gemcutter/Rendering/Viewport.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "Viewport.h"
3 | #include "gemcutter/Rendering/Rendering.h"
4 |
5 | #include
6 | #include
7 |
8 | namespace gem
9 | {
10 | void Viewport::bind() const
11 | {
12 | SetViewport(x, y, width, height);
13 | }
14 |
15 | float Viewport::GetAspectRatio() const
16 | {
17 | return static_cast(width) / static_cast(height);
18 | }
19 | }
20 |
21 | REFLECT(gem::Viewport)
22 | MEMBERS {
23 | REF_MEMBER(x)
24 | REF_MEMBER(y)
25 | REF_MEMBER(width, min(0u))
26 | REF_MEMBER(height, min(0u))
27 | }
28 | REF_END;
29 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Rectangle.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #include "Rectangle.h"
3 |
4 | #include
5 |
6 | namespace gem
7 | {
8 | float Rectangle::GetAspectRatio() const
9 | {
10 | return width / height;
11 | }
12 |
13 | bool Rectangle::Contains(float _x, float _y) const
14 | {
15 | return _x >= x &&
16 | _y >= y &&
17 | _x <= x + width &&
18 | _y <= y + height;
19 | }
20 |
21 | bool Rectangle::Contains(const vec2& pos) const
22 | {
23 | return Contains(pos.x, pos.y);
24 | }
25 | }
26 |
27 | REFLECT(gem::Rectangle)
28 | MEMBERS {
29 | REF_MEMBER(x)
30 | REF_MEMBER(y)
31 | REF_MEMBER(width)
32 | REF_MEMBER(height)
33 | }
34 | REF_END;
35 |
--------------------------------------------------------------------------------
/resources/Shaders/Font.shader:
--------------------------------------------------------------------------------
1 | Attributes
2 | {
3 | vec4 a_vert : 0;
4 | vec2 a_uv : 1;
5 | }
6 |
7 | Uniforms
8 | {
9 | instance Material : 0
10 | {
11 | vec3 Color = (1.0, 1.0, 1.0);
12 | }
13 | }
14 |
15 | Vertex
16 | {
17 | out vec2 texcoord;
18 |
19 | void main()
20 | {
21 | gl_Position = Gem_MVP * a_vert;
22 | texcoord = a_uv;
23 | }
24 | }
25 |
26 | Samplers
27 | {
28 | sampler2D sTex : 0;
29 | }
30 |
31 | Fragment
32 | {
33 | in vec2 texcoord;
34 |
35 | out vec4 outColor;
36 |
37 | void main()
38 | {
39 | outColor = vec4(Material.Color, texture(sTex, texcoord).r);
40 |
41 | #if defined(GEM_CUTOUT)
42 | if (outColor.a < 1.0)
43 | {
44 | discard;
45 | }
46 | #endif
47 | }
48 | }
--------------------------------------------------------------------------------
/gemcutter/Entity/Name.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Entity/Entity.h"
4 |
5 | #include
6 | #include
7 |
8 | namespace gem
9 | {
10 | // Searches the given entity's sub-tree for the first child with the specified name.
11 | Entity* FindChild(const Entity& root, std::string_view name);
12 |
13 | // Searches all Entities with a name component and returns the first one found with the specified name.
14 | Entity* FindEntity(std::string_view name);
15 |
16 | // Associates an entity with a name.
17 | class Name : public Component
18 | {
19 | public:
20 | Name(Entity& owner);
21 | Name(Entity& owner, std::string name);
22 |
23 | std::string name;
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Screen.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Application/Application.h"
4 | #include "gemcutter/Application/Event.h"
5 | #include "gemcutter/GUI/Widget.h"
6 |
7 | namespace gem
8 | {
9 | // A root UI widget which automatically resizes to the size of the application's screen.
10 | // This is intended to be the root widget for a standard UI setup.
11 | class Screen : public Widget
12 | {
13 | public:
14 | Screen(Entity& owner);
15 |
16 | private:
17 | // These inherited functions are hidden because they are not appropriate for a screen root.
18 | void SetTransform(vec2 position, vec2 size) = delete;
19 | void FitToParent() = delete;
20 |
21 | Listener onResize;
22 | };
23 | }
24 |
--------------------------------------------------------------------------------
/gemcutter/Math/Transform.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Math/Quaternion.h"
4 | #include "gemcutter/Math/Vector.h"
5 |
6 | namespace gem
7 | {
8 | // A pose in space - Position / Rotation / Scale.
9 | struct Transform
10 | {
11 | Transform() = default;
12 | Transform(const vec3& position);
13 | Transform(const vec3& position, const quat& rotation);
14 | Transform(const vec3& position, const quat& rotation, const vec3& scale);
15 |
16 | void LookAt(const vec3& pos, const vec3& target, const vec3& up = vec3::Up);
17 | void Rotate(const vec3& axis, float degrees);
18 | void RotateX(float degrees);
19 | void RotateY(float degrees);
20 | void RotateZ(float degrees);
21 |
22 | vec3 position;
23 | quat rotation;
24 | vec3 scale = vec3::One;
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Image.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/GUI/Widget.h"
4 | #include "gemcutter/Resource/Material.h"
5 | #include "gemcutter/Resource/Texture.h"
6 |
7 | namespace gem
8 | {
9 | class Sprite;
10 |
11 | // A widget containing a sprite scaled to fit within it.
12 | class Image : public Widget
13 | {
14 | public:
15 | Image(Entity& owner);
16 | Image(Entity& owner, Texture::Ptr texture);
17 | Image(Entity& owner, Material::Ptr material);
18 |
19 | Sprite& GetSprite();
20 | const Sprite& GetSprite() const;
21 |
22 | void SetTexture(Texture::Ptr texture);
23 | Texture::Ptr GetTexture() const;
24 |
25 | void SetMaterial(Material::Ptr material);
26 | Material& GetMaterial() const;
27 |
28 | private:
29 | void UpdateContent() override;
30 |
31 | Sprite* sprite = nullptr;
32 | };
33 | }
34 |
--------------------------------------------------------------------------------
/gemcutter/Rendering/Mesh.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Rendering/Renderable.h"
4 | #include "gemcutter/Resource/Model.h"
5 |
6 | namespace gem
7 | {
8 | // Causes an entity to render as a 3D mesh.
9 | // Can use loaded *.models as well as custom VertexArrays.
10 | class Mesh : public Renderable
11 | {
12 | public:
13 | Mesh(Entity& owner);
14 | Mesh(Entity& owner, Model::Ptr model);
15 | Mesh(Entity& owner, Model::Ptr model, Material::Ptr material);
16 | Mesh(Entity& owner, Material::Ptr material);
17 | Mesh(Entity& owner, VertexArray::Ptr array);
18 | Mesh(Entity& owner, VertexArray::Ptr array, Material::Ptr material);
19 |
20 | void SetModel(Model::Ptr model);
21 | Model* GetModel() const;
22 |
23 | private:
24 | Model::Ptr model;
25 |
26 | public:
27 | PRIVATE_MEMBER(Mesh, model);
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/gemcutter/Rendering/Text.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Rendering/Renderable.h"
4 | #include "gemcutter/Resource/Font.h"
5 |
6 | #include
7 |
8 | namespace gem
9 | {
10 | // Causes text to render at the entity's position.
11 | class Text : public Renderable
12 | {
13 | public:
14 | Text(Entity& owner);
15 | Text(Entity& owner, Font::Ptr font);
16 | Text(Entity& owner, std::string string);
17 | Text(Entity& owner, Material::Ptr material);
18 | Text(Entity& owner, Font::Ptr font, std::string string, Material::Ptr material);
19 |
20 | unsigned GetNumLines() const;
21 | float GetLineWidth(unsigned line) const;
22 |
23 | Font::Ptr font;
24 | std::string string;
25 | bool centeredX = false;
26 | bool centeredY = false;
27 | // Extra spacing between letters.
28 | float kerning = 0.0f;
29 | };
30 | }
31 |
--------------------------------------------------------------------------------
/gemcutter/Application/HierarchicalEvent.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023 Emilian Cioca
2 | #include "HierarchicalEvent.h"
3 | #include "gemcutter/Application/Application.h"
4 | #include "gemcutter/Input/Input.h"
5 |
6 | #include
7 |
8 | REFLECT_SIMPLE(gem::HierarchicalListener);
9 | REFLECT_SIMPLE(gem::HierarchicalListener);
10 | REFLECT_SIMPLE(gem::HierarchicalListener);
11 | REFLECT_SIMPLE(gem::HierarchicalListener);
12 | REFLECT_SIMPLE(gem::HierarchicalListener);
13 |
14 | REFLECT_SIMPLE(gem::HierarchicalDispatcher);
15 | REFLECT_SIMPLE(gem::HierarchicalDispatcher);
16 | REFLECT_SIMPLE(gem::HierarchicalDispatcher);
17 | REFLECT_SIMPLE(gem::HierarchicalDispatcher);
18 | REFLECT_SIMPLE(gem::HierarchicalDispatcher);
19 |
--------------------------------------------------------------------------------
/gemcutter/Sound/SoundSystem.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 |
4 | namespace gem
5 | {
6 | // Provides global control of audio playback.
7 | extern class SoundSystemSingleton SoundSystem;
8 | class SoundSystemSingleton
9 | {
10 | friend class ApplicationSingleton; // For Update().
11 | public:
12 | bool Init(unsigned bufferSize = 1024);
13 | bool IsLoaded() const;
14 | void Unload();
15 |
16 | // Sets the global volume level. Should be [0, ...]. Default is 1.0f.
17 | void SetGlobalVolume(float volume);
18 | float GetGlobalVolume() const;
19 |
20 | void Mute();
21 | bool IsMuted() const;
22 | void Unmute();
23 |
24 | private:
25 | // Called every frame in order to ensure that sounds play at the correct locations.
26 | void Update();
27 |
28 | bool muted = true;
29 | bool initialized = false;
30 | float globalVolume = 1.0f;
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/tools/AssetManager/workspace_templates/update_metadata.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | :: Prefer the Release version if it exists.
4 | if exist "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/asset_manager.exe" (
5 | title Updating Metadata [Release]
6 | call "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/asset_manager.exe" --update
7 | goto :end
8 | )
9 |
10 | if exist "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/RelWithDebInfo/asset_manager.exe" (
11 | title Updating Metadata [RelWithDebInfo]
12 | call "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/RelWithDebInfo/asset_manager.exe" --update
13 | goto :end
14 | )
15 |
16 | title Updating Metadata [Debug]
17 | call "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/asset_manager.exe" --update
18 |
19 | :end
20 | if errorlevel 1 (
21 | title Update failed!
22 | pause
23 | goto :eof
24 | )
25 |
26 | title Updating complete!
27 | echo Updating complete!
28 | goto :eof
29 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "external/scaffold"]
2 | path = external/scaffold
3 | url = https://github.com/EmilianC/scaffold.git
4 | branch = compile-options
5 | [submodule "samples"]
6 | path = samples
7 | url = https://github.com/EmilianC/Gemcutter-Samples.git
8 | [submodule "external/imgui"]
9 | path = external/imgui
10 | url = https://github.com/ocornut/imgui.git
11 | [submodule "external/soloud"]
12 | path = external/soloud
13 | url = https://github.com/EmilianC/soloud.git
14 | [submodule "external/loupe"]
15 | path = external/loupe
16 | url = https://github.com/EmilianC/Loupe.git
17 | [submodule "external/glew"]
18 | path = external/glew
19 | url = https://github.com/Perlmint/glew-cmake.git
20 | [submodule "external/freetype"]
21 | path = external/freetype
22 | url = https://github.com/EmilianC/freetype.git
23 | [submodule "external/soil2"]
24 | path = external/soil2
25 | url = https://github.com/SpartanJ/SOIL2.git
26 |
--------------------------------------------------------------------------------
/gemcutter/Sound/SoundListener.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Entity/Entity.h"
4 |
5 | namespace gem
6 | {
7 | // The Entity with this component marks the location at which sounds are heard from.
8 | // Only one SoundListener can be enabled at a given point in time.
9 | // Creating or enabling a SoundListener will disable the currently active one.
10 | // Disabling this component mutes all audio until a SoundListener becomes enabled again.
11 | class SoundListener : public Component
12 | {
13 | public:
14 | SoundListener(Entity& owner);
15 |
16 | // Gets the currently active SoundListener. There can only ever be one.
17 | static Entity::Ptr GetListener();
18 |
19 | private:
20 | void OnDisable() final override;
21 | void OnEnable() final override;
22 |
23 | // A pointer to the active listener.
24 | static Entity::WeakPtr listener;
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/tests/FileSystem.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace gem;
5 |
6 | TEST_CASE("FileSystem")
7 | {
8 | SECTION("Directories and Filenames")
9 | {
10 | CHECK(DirectoryExists("C:/"));
11 |
12 | CHECK(IsPathAbsolute("C:/"));
13 |
14 | CHECK_FALSE(IsPathRelative("C:/"));
15 |
16 | CHECK(IsPathRelative("./Folder1/Folder2/"));
17 |
18 | CHECK(IsPathRelative("/Folder1/Folder2/"));
19 |
20 | CHECK(ExtractDriveLetter("C:/user/test.txt") == 'C');
21 |
22 | CHECK(ExtractPath("C:/user/test.txt") == "C:/user/");
23 |
24 | CHECK(ExtractPath("./user/test.txt") == "./user/");
25 |
26 | CHECK(ExtractFile("C:/user/test2.txt") == "test2.txt");
27 |
28 | CHECK(ExtractFilename("C:/user/test3.txt") == "test3");
29 |
30 | CHECK(ExtractFileExtension("C:/user/test4.txt") == ".txt");
31 |
32 | CHECK(ExtractFileExtension("C:/user/test5.txt.zip") == ".zip");
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/gemcutter/Application/Event.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "Event.h"
3 |
4 | #include "gemcutter/Application/Logging.h"
5 |
6 | namespace gem
7 | {
8 | EventQueueSingleton EventQueue;
9 |
10 | void EventQueueSingleton::Push(std::unique_ptr e)
11 | {
12 | eventQueue.push(std::move(e));
13 | }
14 |
15 | void EventQueueSingleton::Dispatch(const EventBase& e) const
16 | {
17 | e.Raise();
18 | }
19 |
20 | void EventQueueSingleton::Dispatch()
21 | {
22 | ASSERT(!dispatching,
23 | "Call to Dispatch() cannot be executed because the event queue is already being dispatched higher in the call stack.\n"
24 | "Consider using Dispatch(const EventBase&) if an event must be processed here immediately.");
25 |
26 | dispatching = true;
27 | while (!eventQueue.empty())
28 | {
29 | eventQueue.front()->Raise();
30 | eventQueue.pop();
31 | }
32 | dispatching = false;
33 | }
34 |
35 | bool EventQueueSingleton::IsDispatching() const
36 | {
37 | return dispatching;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/gemcutter/Resource/Material.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Rendering/Rendering.h"
4 | #include "gemcutter/Resource/Resource.h"
5 | #include "gemcutter/Resource/Shader.h"
6 | #include "gemcutter/Resource/Texture.h"
7 |
8 | namespace gem
9 | {
10 | // When rendering an Entity, the Material specifies:
11 | // - Textures
12 | // - Blend / Cull / Depth modes
13 | // - The shader
14 | // - Static uniform buffers
15 | class Material : public Resource, public Shareable
16 | {
17 | public:
18 | static constexpr std::string_view Extension = ".material";
19 |
20 | Material() = default;
21 |
22 | bool Load(std::string_view filePath);
23 |
24 | BlendFunc blendMode = BlendFunc::None;
25 | DepthFunc depthMode = DepthFunc::Normal;
26 | CullFunc cullMode = CullFunc::Clockwise;
27 |
28 | // The shader used to render the entity.
29 | Shader::Ptr shader;
30 | // These textures will be bound whenever the material is used in rendering.
31 | TextureList textures;
32 | };
33 | }
34 |
--------------------------------------------------------------------------------
/tools/AssetManager/workspace_templates/pack_assets.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | if "%1" == "" goto :default
4 |
5 | title Packing Assets [%1]
6 | call "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/%1/asset_manager.exe" --pack
7 | goto :end
8 |
9 | :default
10 | :: Prefer the Release version if it exists.
11 | if exist "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/asset_manager.exe" (
12 | title Packing Assets [Release]
13 | call "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/asset_manager.exe" --pack
14 | goto :end
15 | )
16 |
17 | if exist "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/RelWithDebInfo/asset_manager.exe" (
18 | title Packing Assets [RelWithDebInfo]
19 | call "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/RelWithDebInfo/asset_manager.exe" --pack
20 | goto :end
21 | )
22 |
23 | title Packing Assets [Debug]
24 | call "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/asset_manager.exe" --pack
25 |
26 | :end
27 | if errorlevel 1 (
28 | title Packing failed!
29 | pause
30 | goto :eof
31 | )
32 |
33 | title Packing completed!
34 | echo Packing completed!
35 | goto :eof
36 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Screen.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #include "Screen.h"
3 | #include "gemcutter/Application/HierarchicalEvent.h"
4 | #include "gemcutter/Entity/Hierarchy.h"
5 | #include "gemcutter/Input/Input.h"
6 |
7 | namespace gem
8 | {
9 | Screen::Screen(Entity& _owner)
10 | : Widget(_owner)
11 | {
12 | owner.Require();
13 | ASSERT(owner.Get().IsRoot(), "A Screen widget must be a root.");
14 |
15 | owner.Require>();
16 | owner.Require>();
17 | owner.Require>();
18 | owner.Require>();
19 |
20 | top.offset = static_cast(Application.GetScreenHeight());
21 | right.offset = static_cast(Application.GetScreenWidth());
22 |
23 | onResize = [this](const Resize& e) {
24 | top.offset = static_cast(e.height);
25 | right.offset = static_cast(e.width);
26 | };
27 | }
28 | }
29 |
30 | REFLECT_COMPONENT(gem::Screen, gem::Widget) REF_END;
31 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Label.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/GUI/Widget.h"
4 | #include "gemcutter/Resource/Font.h"
5 | #include "gemcutter/Resource/Material.h"
6 |
7 | #include
8 | #include
9 |
10 | namespace gem
11 | {
12 | class Text;
13 |
14 | // A widget containing text scaled to fit within it.
15 | class Label : public Widget
16 | {
17 | public:
18 | Label(Entity& owner);
19 | Label(Entity& owner, Font::Ptr font, std::string_view string);
20 | Label(Entity& owner, Font::Ptr font, std::string_view string, Material::Ptr material);
21 |
22 | Text& GetText();
23 | const Text& GetText() const;
24 |
25 | void SetString(std::string_view string);
26 | const std::string& GetString() const;
27 |
28 | void SetFont(Font::Ptr font);
29 | Font::Ptr GetFont() const;
30 |
31 | void SetMaterial(Material::Ptr material);
32 | Material& GetMaterial() const;
33 |
34 | float textScale = 1.0f;
35 |
36 | private:
37 | void UpdateContent() override;
38 |
39 | float textWidth = 0.0f;
40 | Text* text = nullptr;
41 | };
42 | }
43 |
--------------------------------------------------------------------------------
/gemcutter/Utilities/Random.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 |
4 | namespace gem
5 | {
6 | struct vec3;
7 |
8 | void SeedRandomNumberGenerator();
9 | void SeedRandomNumberGenerator(unsigned seed);
10 |
11 | // Returns a random float in the range [min, max].
12 | float RandomRange(float min, float max);
13 | // Returns a random int in the range [min, max].
14 | int RandomRange(int min, int max);
15 |
16 | // Returns a random unit-length vector.
17 | vec3 RandomDirection();
18 | // Returns a random color with [0, 1] RGB values.
19 | vec3 RandomColor();
20 |
21 | // Returns true randomly given the [0, 1] probability.
22 | bool RandomBool(float probability);
23 |
24 | struct Range
25 | {
26 | Range() = default;
27 | Range(float min, float max);
28 |
29 | // Potential range is the 'value' +/- half the 'deviation'.
30 | [[nodiscard]] static Range Deviation(float value, float deviation);
31 |
32 | float Random() const;
33 | void Set(float min, float max);
34 |
35 | bool Contains(float value) const;
36 |
37 | float min = 0.0f;
38 | float max = 1.0f;
39 | };
40 | }
41 |
--------------------------------------------------------------------------------
/gemcutter/Application/Delegate.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #include "Delegate.h"
3 |
4 | namespace gem
5 | {
6 | namespace detail
7 | {
8 | DelegateBase::DelegateBase()
9 | : controlBlock(std::make_shared(this))
10 | {
11 | }
12 |
13 | DelegateBase::DelegateBase(DelegateBase&& other) noexcept
14 | : controlBlock(std::move(other.controlBlock))
15 | {
16 | controlBlock->delegate = this;
17 | }
18 |
19 | DelegateBase& DelegateBase::operator=(DelegateBase&& other) noexcept
20 | {
21 | controlBlock = std::move(other.controlBlock);
22 | controlBlock->delegate = this;
23 |
24 | return *this;
25 | }
26 | }
27 |
28 | DelegateHandle::DelegateHandle(std::weak_ptr blockPtr, detail::DelegateId handleId)
29 | : controlBlock(std::move(blockPtr))
30 | , id(handleId)
31 | {
32 | }
33 |
34 | DelegateHandle::~DelegateHandle()
35 | {
36 | Expire();
37 | }
38 |
39 | void DelegateHandle::Expire()
40 | {
41 | if (auto lock = controlBlock.lock())
42 | {
43 | lock->delegate->Unbind(*this);
44 | controlBlock.reset();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/resources/Shaders/Lambert.shader:
--------------------------------------------------------------------------------
1 | Attributes
2 | {
3 | vec4 a_vert : 0;
4 | vec2 a_uv : 1;
5 | vec3 a_normal : 2;
6 | }
7 |
8 | Samplers
9 | {
10 | sampler2D sTex : 0;
11 | }
12 |
13 | Uniforms
14 | {
15 | Light : 0
16 | {
17 | vec3 Color;
18 | vec3 Position;
19 | vec3 Direction;
20 | float AttenuationLinear;
21 | float AttenuationQuadratic;
22 | float Angle;
23 | uint Type;
24 | }
25 |
26 | static Ambient : 1
27 | {
28 | vec3 Color = (0.1, 0.1, 0.1);
29 | }
30 | }
31 |
32 | Vertex
33 | {
34 | out vec2 texcoord;
35 | out vec3 norm;
36 | out vec3 pos;
37 |
38 | void main()
39 | {
40 | pos = (Gem_Model * a_vert).xyz;
41 | gl_Position = Gem_ViewProj * vec4(pos, 1.0);
42 |
43 | texcoord = a_uv;
44 | norm = Gem_NormalToWorld * a_normal;
45 | }
46 | }
47 |
48 | Fragment
49 | {
50 | in vec2 texcoord;
51 | in vec3 norm;
52 | in vec3 pos;
53 |
54 | out vec3 outColor;
55 |
56 | void main()
57 | {
58 | vec3 normal = normalize(norm);
59 |
60 | vec3 lighting = Ambient.Color;
61 | lighting += compute_light(Light, normal, pos);
62 |
63 | outColor = texture(sTex, texcoord).rgb * lighting;
64 | }
65 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Emilian Cioca
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/tools/AssetManager/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AssetManager.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/gemcutter/Sound/SoundSource.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Entity/Entity.h"
4 | #include "gemcutter/Resource/Sound.h"
5 |
6 | namespace gem
7 | {
8 | // Plays 2D or 3D audio.
9 | class SoundSource : public Component
10 | {
11 | friend class SoundSystemSingleton; // For hSound.
12 | public:
13 | SoundSource(Entity& owner);
14 | SoundSource(Entity& owner, Sound::Ptr sound);
15 | ~SoundSource();
16 |
17 | void SetData(Sound::Ptr sound);
18 | Sound* GetData() const;
19 |
20 | void Play();
21 | void Stop();
22 | void Pause();
23 | void Resume();
24 | bool IsPlaying() const;
25 | bool IsPaused() const;
26 |
27 | // Sets the volume multiplier of this SoundSource instance.
28 | void SetSourceVolume(float volume);
29 | float GetSourceVolume() const;
30 |
31 | private:
32 | // Stops any playing sound when disabled.
33 | void OnDisable() final override;
34 |
35 | Sound::Ptr data;
36 |
37 | // A handle for the sound instance.
38 | unsigned hSound = 0;
39 | float volume = 1.0f;
40 |
41 | public:
42 | PRIVATE_MEMBER(SoundSource, data);
43 | PRIVATE_MEMBER(SoundSource, volume);
44 | };
45 | }
46 |
--------------------------------------------------------------------------------
/gemcutter/Resource/Model.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Math/Vector.h"
4 | #include "gemcutter/Resource/Resource.h"
5 | #include "gemcutter/Resource/VertexArray.h"
6 |
7 | namespace gem
8 | {
9 | // A 3D model resource. Can be attached to an Entity's Mesh component.
10 | //
11 | // Provides the following attributes and bindings:
12 | // Vertex : 0
13 | // UVs : 1
14 | // Normal : 2
15 | // Tangent : 3
16 | class Model : public Resource, public Shareable
17 | {
18 | public:
19 | static constexpr std::string_view Extension = ".model";
20 |
21 | // Loads pre-packed *.model resources.
22 | bool Load(std::string_view filePath);
23 |
24 | VertexArray::Ptr GetArray() const;
25 |
26 | // Returns the extents of each axis in local-space.
27 | const vec3& GetMinBounds() const;
28 | const vec3& GetMaxBounds() const;
29 |
30 | bool HasUVs() const;
31 | bool HasNormals() const;
32 | bool HasTangents() const;
33 |
34 | private:
35 | VertexArray::Ptr array;
36 |
37 | vec3 minBounds;
38 | vec3 maxBounds;
39 |
40 | bool hasUvs = false;
41 | bool hasNormals = false;
42 | bool hasTangents = false;
43 | };
44 | }
45 |
--------------------------------------------------------------------------------
/gemcutter/Rendering/Renderable.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Entity/Entity.h"
4 | #include "gemcutter/Resource/Material.h"
5 | #include "gemcutter/Resource/VertexArray.h"
6 |
7 | namespace gem
8 | {
9 | // Base class for all renderable components.
10 | class Renderable : public Component
11 | {
12 | public:
13 | Renderable(Entity& owner);
14 | Renderable(Entity& owner, Material::Ptr material);
15 | Renderable(Entity& owner, VertexArray::Ptr array);
16 | Renderable(Entity& owner, VertexArray::Ptr array, Material::Ptr material);
17 |
18 | void SetMaterial(Material::Ptr newMaterial);
19 | const Material& GetMaterial() const;
20 | Material& GetMaterial();
21 |
22 | // The set of definitions used to permute the shader.
23 | ShaderVariantControl variants;
24 |
25 | // Per-instance uniform data for the Material's shader.
26 | BufferList buffers;
27 |
28 | // Per-instance texture overrides for the Material.
29 | TextureList textures;
30 |
31 | // The main geometry data to be rendered.
32 | VertexArray::Ptr array;
33 |
34 | private:
35 | Material::Ptr material;
36 |
37 | public:
38 | PRIVATE_MEMBER(Renderable, material);
39 | };
40 | }
41 |
--------------------------------------------------------------------------------
/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "x64",
5 | "includePath": [
6 | "${workspaceFolder}/**",
7 | "${workspaceFolder}/external/catch/**",
8 | "${workspaceFolder}/external/dirent/**",
9 | "${workspaceFolder}/external/freetype/**",
10 | "${workspaceFolder}/external/glew/**",
11 | "${workspaceFolder}/external/imgui/**",
12 | "${workspaceFolder}/external/soloud/include/**",
13 | "${workspaceFolder}/external/soil/**"
14 | ],
15 | "defines": [
16 | "_DEBUG",
17 | "GEM_DEBUG",
18 | "GEM_DEV",
19 | "GEM_PRODUCTION",
20 | "WIN32_LEAN_AND_MEAN",
21 | "GLEW_STATIC",
22 | "NOMINMAX",
23 | "_CRT_SECURE_NO_WARNINGS",
24 | "IMGUI_ENABLED"
25 | ],
26 | "cStandard": "c11",
27 | "cppStandard": "c++23",
28 | "intelliSenseMode": "msvc-x64",
29 | "configurationProvider": "ms-vscode.cmake-tools"
30 | }
31 | ],
32 | "version": 4
33 | }
--------------------------------------------------------------------------------
/gemcutter/Rendering/Mesh.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "Mesh.h"
3 |
4 | namespace gem
5 | {
6 | Mesh::Mesh(Entity& _owner)
7 | : Renderable(_owner)
8 | {
9 | }
10 |
11 | Mesh::Mesh(Entity& _owner, Model::Ptr _model)
12 | : Renderable(_owner)
13 | {
14 | SetModel(std::move(_model));
15 | }
16 |
17 | Mesh::Mesh(Entity& _owner, Model::Ptr _model, Material::Ptr material)
18 | : Renderable(_owner, std::move(material))
19 | {
20 | SetModel(std::move(_model));
21 | }
22 |
23 | Mesh::Mesh(Entity& _owner, Material::Ptr material)
24 | : Renderable(_owner, std::move(material))
25 | {
26 | }
27 |
28 | Mesh::Mesh(Entity& _owner, VertexArray::Ptr _array)
29 | : Renderable(_owner, std::move(_array))
30 | {
31 | }
32 |
33 | Mesh::Mesh(Entity& _owner, VertexArray::Ptr _array, Material::Ptr material)
34 | : Renderable(_owner, std::move(_array), std::move(material))
35 | {
36 | }
37 |
38 | void Mesh::SetModel(Model::Ptr _model)
39 | {
40 | model = std::move(_model);
41 | array = model->GetArray();
42 | }
43 |
44 | Model* Mesh::GetModel() const
45 | {
46 | return model.get();
47 | }
48 | }
49 |
50 | REFLECT_COMPONENT(gem::Mesh, gem::Renderable)
51 | MEMBERS {
52 | REF_PRIVATE_MEMBER_EX(model, nullptr, &gem::Mesh::SetModel)
53 | }
54 | REF_END;
55 |
--------------------------------------------------------------------------------
/gemcutter/Sound/SoundListener.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "SoundListener.h"
3 | #include "gemcutter/Sound/SoundSystem.h"
4 |
5 | namespace gem
6 | {
7 | Entity::WeakPtr SoundListener::listener;
8 |
9 | SoundListener::SoundListener(Entity& _owner)
10 | : Component(_owner)
11 | {
12 | if (!IsEnabled())
13 | {
14 | // Do not change any existing state.
15 | return;
16 | }
17 |
18 | OnEnable();
19 | }
20 |
21 | Entity::Ptr SoundListener::GetListener()
22 | {
23 | return listener.lock();
24 | }
25 |
26 | void SoundListener::OnDisable()
27 | {
28 | Entity::Ptr listenerEntity = GetListener();
29 |
30 | // If we are in fact the currently active listener, we can be disabled.
31 | if (listenerEntity == owner)
32 | {
33 | listener.reset();
34 | SoundSystem.Mute();
35 | }
36 | }
37 |
38 | void SoundListener::OnEnable()
39 | {
40 | // If there is already an active listener, we must disable it
41 | // because we only support one active listener at a time.
42 | if (Entity::Ptr listenerEntity = GetListener())
43 | {
44 | listenerEntity->Disable();
45 | }
46 |
47 | listener = owner.GetWeakPtr();
48 | SoundSystem.Unmute();
49 | }
50 | }
51 |
52 | REFLECT_COMPONENT(gem::SoundListener, gem::ComponentBase) REF_END;
53 |
--------------------------------------------------------------------------------
/gemcutter/Rendering/Light.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Entity/Entity.h"
4 | #include "gemcutter/Math/Vector.h"
5 | #include "gemcutter/Resource/UniformBuffer.h"
6 |
7 | namespace gem
8 | {
9 | // Defaults to a point light.
10 | class Light : public Component
11 | {
12 | public:
13 | enum class Type : uint16_t
14 | {
15 | Point,
16 | Directional,
17 | Spot
18 | };
19 |
20 | Light(Entity& owner);
21 | Light(Entity& owner, const vec3& color);
22 | Light(Entity& owner, const vec3& color, Type type);
23 |
24 | Type type = Type::Point;
25 | // Defaults to a white light.
26 | UniformHandle color;
27 | // Defaults to zero.
28 | UniformHandle attenuationLinear;
29 | // Defaults to one.
30 | UniformHandle attenuationQuadratic;
31 | // Cone angle for spotlights, in degrees.
32 | float angle = 25.0f;
33 |
34 | // Keeps the internal buffer up to date with the light's transform.
35 | void Update();
36 |
37 | UniformBuffer::Ptr& GetBuffer();
38 |
39 | private:
40 | void CreateUniformBuffer();
41 |
42 | UniformHandle position;
43 | UniformHandle direction;
44 | UniformHandle cosAngle;
45 | UniformHandle typeHandle;
46 | UniformBuffer::Ptr lightBuffer;
47 | };
48 | }
49 |
--------------------------------------------------------------------------------
/docs/Entity.md:
--------------------------------------------------------------------------------
1 | # Dynamic Queries
2 | A query will only return active Components and Entities. Any Component or Tag can be part of a query.
3 |
4 | Queries are implemented in a LINQ-style fashion. This means that they are very efficient (zero dynamic allocations),
5 | but also that Components/Tags of the queried types should not be created or deleted during the loop.
6 |
7 | # Examples
8 | ```cpp
9 | class Player : public Component { /**/ };
10 | class Network : public Component { /**/ };
11 | class Friendly : public Tag {};
12 | class Enemy : public Tag {};
13 | class SquadLeader : public Tag {};
14 |
15 | // Process all Entities with a Player Component.
16 | for (Entity& e : With())
17 | {
18 | //...
19 | }
20 |
21 | // Using All<>() processes the Component directly.
22 | // This avoids the cost of calling Entity.Get<>().
23 | for (Player& p : All())
24 | {
25 | //...
26 | }
27 |
28 | // Process all enemy players.
29 | for (Entity& e : With())
30 | {
31 | //...
32 | }
33 |
34 | // Process all friendly players.
35 | for (Entity& e : With())
36 | {
37 | //...
38 | }
39 |
40 | // Process all friendly SquadLeaders on the network.
41 | for (Entity& e : With())
42 | {
43 | //...
44 | }
45 | ```
--------------------------------------------------------------------------------
/gemcutter/Entity/Name.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "Name.h"
3 | #include "gemcutter/Entity/Hierarchy.h"
4 |
5 | namespace gem
6 | {
7 | Entity* FindChild(const Entity& root, std::string_view name)
8 | {
9 | if (name.empty())
10 | {
11 | return nullptr;
12 | }
13 |
14 | auto& hierarchy = root.Get();
15 |
16 | for (auto& child : hierarchy.GetChildren())
17 | {
18 | auto* nameComp = child->Try();
19 | if (nameComp && nameComp->name == name)
20 | {
21 | return child.get();
22 | }
23 | }
24 |
25 | for (auto& child : hierarchy.GetChildren())
26 | {
27 | if (auto* result = FindChild(*child, name))
28 | {
29 | return result;
30 | }
31 | }
32 |
33 | return nullptr;
34 | }
35 |
36 | Entity* FindEntity(std::string_view name)
37 | {
38 | if (name.empty())
39 | {
40 | return nullptr;
41 | }
42 |
43 | for (auto& comp : All())
44 | {
45 | if (comp.name == name)
46 | {
47 | return &comp.owner;
48 | }
49 | }
50 |
51 | return nullptr;
52 | }
53 |
54 | Name::Name(Entity& _owner)
55 | : Component(_owner)
56 | {
57 | }
58 |
59 | Name::Name(Entity& _owner, std::string _name)
60 | : Component(_owner)
61 | , name(std::move(_name))
62 | {
63 | }
64 | }
65 |
66 | REFLECT_COMPONENT(gem::Name, gem::ComponentBase)
67 | MEMBERS {
68 | REF_MEMBER(name)
69 | }
70 | REF_END;
71 |
--------------------------------------------------------------------------------
/gemcutter/Rendering/Sprite.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Rendering/Renderable.h"
4 |
5 | namespace gem
6 | {
7 | enum class Alignment : uint16_t
8 | {
9 | BottomLeft,
10 | BottomCenter,
11 | LeftCenter,
12 | Center
13 | };
14 |
15 | // Causes an entity to render as a 2D textured sprite.
16 | // The desired textures should be set on the Material component.
17 | // Alignment and BillBoard options are supported by the default sprite shader.
18 | class Sprite : public Renderable
19 | {
20 | public:
21 | Sprite(Entity& owner);
22 | Sprite(Entity& owner, Material::Ptr material);
23 | Sprite(Entity& owner, Alignment pivot);
24 | Sprite(Entity& owner, Alignment pivot, bool billBoard, Material::Ptr material);
25 |
26 | // The sprite will render with the specified point on the entity's position.
27 | // Defines "GEM_SPRITE_CENTERED_X" and "GEM_SPRITE_CENTERED_Y" on the Material Component if needed.
28 | void SetAlignment(Alignment pivot);
29 | Alignment GetAlignment() const;
30 |
31 | // Causes the Sprite to face the camera.
32 | // Defines "GEM_SPRITE_BILLBOARD" on the Material Component if needed.
33 | void SetBillBoarded(bool state);
34 | bool GetBillBoarded() const;
35 |
36 | private:
37 | Alignment alignment = Alignment::BottomLeft;
38 | bool billBoarded = false;
39 |
40 | public:
41 | PRIVATE_MEMBER(Sprite, alignment);
42 | PRIVATE_MEMBER(Sprite, billBoarded);
43 | };
44 | }
45 |
--------------------------------------------------------------------------------
/gemcutter/Math/Quaternion.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 |
4 | namespace gem
5 | {
6 | struct vec3;
7 | struct mat3;
8 |
9 | struct quat
10 | {
11 | quat() = default;
12 | quat(float X, float Y, float Z, float W);
13 | quat(const vec3& right, const vec3& up, const vec3& forward);
14 | explicit quat(const mat3& rotation);
15 |
16 | bool operator==(const quat&) const;
17 | bool operator!=(const quat&) const;
18 |
19 | quat operator*(const quat&) const;
20 | vec3 operator*(const vec3&) const;
21 | quat& operator*=(const quat&);
22 |
23 | float operator[](unsigned index) const;
24 | float& operator[](unsigned index);
25 |
26 | void SetIdentity();
27 |
28 | void FromEuler(const vec3& degrees);
29 | vec3 GetEuler() const;
30 |
31 | void Conjugate();
32 | quat GetConjugate() const;
33 |
34 | void Normalize();
35 | quat GetNormalized() const;
36 |
37 | vec3 GetRight() const;
38 | vec3 GetUp() const;
39 | vec3 GetForward() const;
40 |
41 | void Rotate(const vec3& axis, float degrees);
42 | void Rotate(float X, float Y, float Z, float degrees);
43 | void RotateX(float degrees);
44 | void RotateY(float degrees);
45 | void RotateZ(float degrees);
46 |
47 | static const quat Identity;
48 |
49 | float x = 0.0f;
50 | float y = 0.0f;
51 | float z = 0.0f;
52 | float w = 1.0f;
53 | };
54 |
55 | [[nodiscard]] float Dot(const quat& p0, const quat& p1);
56 | [[nodiscard]] quat Slerp(const quat& p0, const quat& p1, float percent);
57 | }
58 |
--------------------------------------------------------------------------------
/gemcutter/AI/ProbabilityMatrix.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 |
4 | namespace gem
5 | {
6 | // Stores and manages a probability matrix of States vs Actions.
7 | class ProbabilityMatrix
8 | {
9 | public:
10 | ProbabilityMatrix(unsigned numStates, unsigned numActions);
11 | ProbabilityMatrix(const ProbabilityMatrix&);
12 | ProbabilityMatrix(ProbabilityMatrix&&) noexcept;
13 | ~ProbabilityMatrix();
14 |
15 | ProbabilityMatrix& operator=(const ProbabilityMatrix&);
16 | ProbabilityMatrix& operator=(ProbabilityMatrix&&) noexcept;
17 |
18 | // Re-initialize the matrix with uniform probabilities.
19 | void Reset();
20 |
21 | // Based on the given state, returns a random action with respect to the probabilities.
22 | int QueryAction(unsigned state) const;
23 |
24 | // Reinforces (positively or negatively) an action by the scalar, percentage.
25 | void ReinforceScale(unsigned state, unsigned action, float percentage);
26 |
27 | // Reinforces (positively or negatively) an action by the additive, value.
28 | void ReinforceLinear(unsigned state, unsigned action, float value);
29 |
30 | // Returns the probability of taking an action from a given state.
31 | float GetValue(unsigned state, unsigned action) const;
32 | int GetNumStates() const;
33 | int GetNumActions() const;
34 |
35 | private:
36 | unsigned numStates = 0;
37 | unsigned numActions = 0;
38 | float* data = nullptr;
39 |
40 | void Normalize();
41 | void SetValue(unsigned state, unsigned action, float value);
42 | };
43 | }
44 |
--------------------------------------------------------------------------------
/tools/AssetManager/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("AssetManager")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("AssetManager")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("6099e7ad-99a7-4eb4-b3c7-d35ee1184ba5")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/tools/AssetManager/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | using System;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Windows.Forms;
6 |
7 | namespace AssetManager
8 | {
9 | static class Program
10 | {
11 | [DllImport("kernel32")]
12 | private static extern bool AttachConsole(int dwProcessId);
13 | const int ATTACH_PARENT_PROCESS = -1;
14 |
15 | [STAThread]
16 | static void Main()
17 | {
18 | Application.EnableVisualStyles();
19 | Application.SetCompatibleTextRenderingDefault(false);
20 | var builder = new Manager();
21 |
22 | // If we have arguments, process them then exit.
23 | if (Environment.GetCommandLineArgs().Length > 1)
24 | {
25 | if (!AttachConsole(ATTACH_PARENT_PROCESS))
26 | throw new SystemException("Could not link output to the calling console window.");
27 |
28 | if (Environment.GetCommandLineArgs().Contains("--update", StringComparer.InvariantCultureIgnoreCase))
29 | {
30 | if (!builder.UpdateWorkspace())
31 | {
32 | Environment.ExitCode = 1;
33 | return;
34 | }
35 | }
36 |
37 | if (Environment.GetCommandLineArgs().Contains("--pack", StringComparer.InvariantCultureIgnoreCase))
38 | {
39 | if (!builder.PackWorkspace())
40 | Environment.ExitCode = 1;
41 |
42 | builder.SaveFileCache();
43 | }
44 | }
45 | else
46 | {
47 | // Otherwise we can start the UI normally and route output to the visual textBox.
48 | Console.SetOut(new RichTextBoxStreamWriter(builder.GetOutput()));
49 |
50 | Application.Run(builder);
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/gemcutter/Resource/ParticleBuffer.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Resource/VertexArray.h"
4 | #include "gemcutter/Utilities/EnumFlags.h"
5 |
6 | namespace gem
7 | {
8 | struct vec2;
9 | struct vec3;
10 |
11 | enum class ParticleAttributes : uint16_t
12 | {
13 | None = 0,
14 | Size = 1, // vec2
15 | Color = 2, // vec3
16 | Alpha = 4, // float
17 | Rotation = 8, // float
18 | AgeRatio = 16 // float (age / lifetime)
19 | };
20 |
21 | class ParticleBuffer
22 | {
23 | public:
24 | ParticleBuffer(unsigned maxParticles);
25 | ~ParticleBuffer();
26 |
27 | void Unload();
28 |
29 | void SetAttributes(EnumFlags attributes);
30 | // Uploads data to the GPU buffers.
31 | void Update(unsigned activeParticles);
32 |
33 | void Kill(unsigned index, unsigned last);
34 | bool IsAlive(unsigned index) const;
35 |
36 | EnumFlags GetAttributes() const;
37 | VertexArray::Ptr GetArray() const;
38 | unsigned GetMaxParticles() const;
39 |
40 | vec3* positions = nullptr;
41 | vec3* velocities = nullptr;
42 | float* ages = nullptr;
43 | float* lifetimes = nullptr;
44 | vec2* sizes = nullptr;
45 | vec3* colors = nullptr;
46 | float* alphas = nullptr;
47 | float* rotations = nullptr;
48 | float* ageRatios = nullptr;
49 |
50 | private:
51 | unsigned TotalBufferSize() const;
52 |
53 | EnumFlags attributes = ParticleAttributes::None;
54 | unsigned maxParticles = 0;
55 |
56 | VertexArray::Ptr array;
57 | VertexBuffer::Ptr buffer;
58 | };
59 | }
60 |
--------------------------------------------------------------------------------
/gemcutter/Utilities/Identifier.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Emilian Cioca
2 | #pragma once
3 | #include "Gemcutter/Application/Logging.h"
4 |
5 | #include
6 | #include
7 |
8 | namespace gem
9 | {
10 | // A base class for strongly-typed identifiers.
11 | // The intended usage is to derive from this structure:
12 | //
13 | // struct CustomId : public Identifier {};
14 | // CustomId id = GenerateUniqueId();
15 | //
16 | // Please note that you will need to specialize std::hash<>
17 | // if you wish to use your identifiers as keys in containers.
18 | template
19 | struct Identifier
20 | {
21 | static_assert(std::is_integral_v);
22 | using ValueType = T;
23 |
24 | ValueType GetValue() const { return value; }
25 | void Reset() { value = invalid; }
26 |
27 | [[nodiscard]] bool IsValid() const { return value != invalid; }
28 | [[nodiscard]] bool operator==(const Identifier&) const = default;
29 | [[nodiscard]] bool operator!=(const Identifier&) const = default;
30 |
31 | static constexpr ValueType invalid = std::numeric_limits::min();
32 |
33 | private:
34 | template friend IdType GenerateUniqueId();
35 | ValueType value = invalid;
36 | };
37 |
38 | template
39 | IdType GenerateUniqueId()
40 | {
41 | constinit static IdType::ValueType counter = IdType::invalid;
42 |
43 | ASSERT(counter != std::numeric_limits::max(),
44 | "The underlying identifier type ran out of unique values to generate.");
45 |
46 | IdType Id;
47 | Id.value = ++counter;
48 | return Id;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Button.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Application/Delegate.h"
4 | #include "gemcutter/GUI/Widget.h"
5 | #include "gemcutter/Resource/Sound.h"
6 | #include "gemcutter/Resource/Texture.h"
7 | #include "gemcutter/Resource/Font.h"
8 |
9 | #include
10 |
11 | namespace gem
12 | {
13 | class Image;
14 | class Label;
15 |
16 | // An interactable button with a label and automatically updating background image.
17 | class Button : public Widget
18 | {
19 | public:
20 | Button(Entity& owner);
21 | Button(Entity& owner, Font::Ptr font, std::string_view text);
22 | Button(Entity& owner, Texture::Ptr idle, Texture::Ptr hover, Texture::Ptr pressed);
23 | Button(Entity& owner, Font::Ptr font, std::string_view text, Texture::Ptr idle, Texture::Ptr hover, Texture::Ptr pressed);
24 |
25 | enum class State : uint16_t
26 | {
27 | Idle,
28 | Hover,
29 | Pressed
30 | };
31 |
32 | void Update();
33 |
34 | Image& GetImage();
35 | Label& GetLabel();
36 | const Image& GetImage() const;
37 | const Label& GetLabel() const;
38 | State GetState() const;
39 |
40 | Sound::Ptr pressedSound;
41 | Texture::Ptr idleTexture;
42 | Texture::Ptr hoverTexture;
43 | Texture::Ptr pressedTexture;
44 |
45 | Dispatcher onClick;
46 |
47 | private:
48 | void SetState(State);
49 | void SetTexture(State);
50 |
51 | void OnDisable() override;
52 | void OnEnable() override;
53 |
54 | State state = State::Idle;
55 | Image* image = nullptr;
56 | Label* label = nullptr;
57 |
58 | public:
59 | PRIVATE_MEMBER(Button, state);
60 | };
61 | }
62 |
--------------------------------------------------------------------------------
/gemcutter/Resource/Shareable.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include
4 |
5 | namespace gem
6 | {
7 | template
8 | class Shareable : public std::enable_shared_from_this
9 | {
10 | // Hide these functions from user code.
11 | using std::enable_shared_from_this::shared_from_this;
12 | using std::enable_shared_from_this::weak_from_this;
13 |
14 | protected:
15 | // A helper allowing private constructors to participate in the Shareable pattern.
16 | struct ShareableAlloc : public Derived
17 | {
18 | template
19 | ShareableAlloc(Args&&... args) : Derived(std::forward(args)...) {}
20 | };
21 |
22 | public:
23 | using Ptr = std::shared_ptr;
24 | using ConstPtr = std::shared_ptr;
25 | using WeakPtr = std::weak_ptr;
26 | using ConstWeakPtr = std::weak_ptr;
27 |
28 | Ptr GetPtr()
29 | {
30 | return shared_from_this();
31 | }
32 |
33 | ConstPtr GetPtr() const
34 | {
35 | return shared_from_this();
36 | }
37 |
38 | WeakPtr GetWeakPtr()
39 | {
40 | return weak_from_this();
41 | }
42 |
43 | ConstWeakPtr GetWeakPtr() const
44 | {
45 | return weak_from_this();
46 | }
47 |
48 | template
49 | static Ptr MakeNew(Args&&... params)
50 | {
51 | // If you have a compile error because the Derived class has an inaccessible private constructor,
52 | // declare "friend ShareableAlloc;" and MakeNew() will still be able to instantiate it.
53 | return std::make_shared(std::forward(params)...);
54 | }
55 | };
56 | }
57 |
--------------------------------------------------------------------------------
/gemcutter/Math/Transform.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "Transform.h"
3 | #include "gemcutter/Application/Logging.h"
4 | #include "gemcutter/Math/Math.h"
5 |
6 | #include
7 |
8 | namespace gem
9 | {
10 | Transform::Transform(const vec3& _position)
11 | : position(_position)
12 | {
13 | }
14 |
15 | Transform::Transform(const vec3& _position, const quat& _rotation)
16 | : position(_position)
17 | , rotation(_rotation)
18 | {
19 | }
20 |
21 | Transform::Transform(const vec3& _position, const quat& _rotation, const vec3& _scale)
22 | : position(_position)
23 | , rotation(_rotation)
24 | , scale(_scale)
25 | {
26 | }
27 |
28 | void Transform::LookAt(const vec3& pos, const vec3& target, const vec3& up)
29 | {
30 | ASSERT(Equals(Length(up), 1.0f), "'up' must be a normalized vector.");
31 | ASSERT(pos != target, "Transform cannot look at itself.");
32 |
33 | vec3 forward = Normalize(target - pos);
34 | vec3 right = Normalize(Cross(forward, up));
35 |
36 | rotation = quat(right, Cross(right, forward), -forward);
37 | position = pos;
38 | }
39 |
40 | void Transform::Rotate(const vec3& axis, float degrees)
41 | {
42 | rotation.Rotate(axis, degrees);
43 | }
44 |
45 | void Transform::RotateX(float degrees)
46 | {
47 | rotation.RotateX(degrees);
48 | }
49 |
50 | void Transform::RotateY(float degrees)
51 | {
52 | rotation.RotateY(degrees);
53 | }
54 |
55 | void Transform::RotateZ(float degrees)
56 | {
57 | rotation.RotateZ(degrees);
58 | }
59 | }
60 |
61 | REFLECT(gem::Transform)
62 | MEMBERS {
63 | REF_MEMBER(position)
64 | REF_MEMBER(rotation)
65 | REF_MEMBER(scale)
66 | }
67 | REF_END;
68 |
--------------------------------------------------------------------------------
/gemcutter/Application/Event.inl:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | namespace gem
3 | {
4 | template std::vector*> Event::listeners;
5 |
6 | template
7 | Listener::Listener()
8 | {
9 | EventObj::Subscribe(*this);
10 | }
11 |
12 | template
13 | Listener::Listener(std::function callback)
14 | : func(std::move(callback))
15 | {
16 | EventObj::Subscribe(*this);
17 | }
18 |
19 | template
20 | Listener::~Listener()
21 | {
22 | EventObj::Unsubscribe(*this);
23 | }
24 |
25 | template
26 | Listener& Listener::operator=(std::function callback)
27 | {
28 | func = std::move(callback);
29 | return *this;
30 | }
31 |
32 | template
33 | bool Event::HasListeners() const
34 | {
35 | return HasListenersStatic();
36 | }
37 |
38 | template
39 | bool Event::HasListenersStatic()
40 | {
41 | return !listeners.empty();
42 | }
43 |
44 | template
45 | void Event::Raise() const
46 | {
47 | for (unsigned i = 0; i < listeners.size(); ++i)
48 | {
49 | if (listeners[i]->func)
50 | {
51 | listeners[i]->func(*static_cast(this));
52 | }
53 | }
54 | }
55 |
56 | template
57 | void Event::Subscribe(Listener& listener)
58 | {
59 | listeners.push_back(&listener);
60 | }
61 |
62 | template
63 | void Event::Unsubscribe(Listener& listener)
64 | {
65 | listeners.erase(std::find(listeners.begin(), listeners.end(), &listener));
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Widget.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #pragma once
3 | #include "gemcutter/Entity/Entity.h"
4 | #include "gemcutter/Entity/Hierarchy.h"
5 | #include "gemcutter/GUI/Rectangle.h"
6 |
7 | namespace gem
8 | {
9 | struct Edge
10 | {
11 | // Percentage of total distance from a parent edge.
12 | float anchor = 0.0f;
13 | // Flat offset from the anchor.
14 | float offset = 0.0f;
15 | };
16 |
17 | // A generic UI element sized with respect to its parent widget.
18 | class Widget : public Component
19 | {
20 | public:
21 | Widget(Entity& owner);
22 |
23 | // Creates a new child widget of the given type.
24 | template
25 | T& CreateChild(Args&&... constructorParams);
26 |
27 | // Helper function which sets anchors to maintain the target size and position.
28 | // The given position should be relative to the bottom-left corner of the parent widget.
29 | // The parent widget's layout must be up to date.
30 | void SetTransform(vec2 position, vec2 size);
31 |
32 | // Sets the anchors to the full space available in the parent widget.
33 | // This is the default behaviour.
34 | void FitToParent();
35 |
36 | // Returns the current world-space dimensions of the widget.
37 | const Rectangle& GetAbsoluteBounds() const;
38 |
39 | // Called when the bounds of the widget are updated.
40 | // This is where specific widgets can adjust their content.
41 | virtual void UpdateContent() {}
42 |
43 | static void UpdateAll();
44 |
45 | Edge top;
46 | Edge bottom;
47 | Edge left;
48 | Edge right;
49 |
50 | private:
51 | void UpdateBounds(const Widget& parent);
52 |
53 | Rectangle absoluteBounds;
54 | };
55 | }
56 |
57 | #include "Widget.inl"
58 |
--------------------------------------------------------------------------------
/resources/Shaders/Sprite.shader:
--------------------------------------------------------------------------------
1 | Attributes
2 | {
3 | vec4 a_vert : 0;
4 | vec2 a_uv : 1;
5 | }
6 |
7 | Uniforms
8 | {
9 | instance Material : 0
10 | {
11 | float AlphaCutOff = 0.5;
12 | }
13 | }
14 |
15 | Vertex
16 | {
17 | out vec2 texcoord;
18 |
19 | void main()
20 | {
21 | texcoord = a_uv;
22 |
23 | #if defined(GEM_SPRITE_BILLBOARD)
24 | // Get the position of the sprite.
25 | vec4 vertex = Gem_Model[3].xyzw;
26 |
27 | // Calculate vertex offset from the center.
28 | vec2 offset = texcoord;
29 | #if defined(GEM_SPRITE_CENTERED_X)
30 | offset.x -= 0.5;
31 | #endif
32 | #if defined(GEM_SPRITE_CENTERED_Y)
33 | offset.y -= 0.5;
34 | #endif
35 |
36 | // Extract the scale from the basis vectors.
37 | vec2 scale = vec2(length(Gem_Model[0].xyz), length(Gem_Model[1].xyz));
38 |
39 | // Offset in view space to create perfect billboard.
40 | vertex = Gem_View * vertex;
41 | vertex.xy += offset * scale;
42 |
43 | // Project to screen.
44 | gl_Position = Gem_Proj * vertex;
45 | #else
46 | vec4 vertex = a_vert;
47 |
48 | // Offset in local-space.
49 | #if defined(GEM_SPRITE_CENTERED_X)
50 | vertex.x -= 0.5;
51 | #endif
52 | #if defined(GEM_SPRITE_CENTERED_Y)
53 | vertex.y -= 0.5;
54 | #endif
55 |
56 | // Transform and project to screen.
57 | gl_Position = Gem_MVP * vertex;
58 | #endif
59 | }
60 | }
61 |
62 | Samplers
63 | {
64 | sampler2D sTex : 0;
65 | }
66 |
67 | Fragment
68 | {
69 | in vec2 texcoord;
70 |
71 | out vec4 outColor;
72 |
73 | void main()
74 | {
75 | outColor = texture(sTex, texcoord).rgba;
76 |
77 | #if defined(GEM_CUTOUT)
78 | if (outColor.a <= Material.AlphaCutOff)
79 | {
80 | discard;
81 | }
82 | #endif
83 | }
84 | }
--------------------------------------------------------------------------------
/tools/AssetManager/WorkspaceConfig.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Xml.Serialization;
6 |
7 | namespace AssetManager
8 | {
9 | public class EncoderLink
10 | {
11 | public string extension;
12 | public string encoder;
13 | }
14 |
15 | // Manages the input and output of the workspace settings.
16 | public class WorkspaceConfig
17 | {
18 | public string outputDirectory = "../Assets";
19 | public string excludedExtensions = "";
20 |
21 | [System.NonSerialized()]
22 | private string[] _excludedExtensions = new string[0];
23 |
24 | public List encoders = new List();
25 |
26 | public bool IsExtensionExcluded(string extension)
27 | {
28 | return _excludedExtensions.Contains(extension);
29 | }
30 |
31 | public static WorkspaceConfig Load()
32 | {
33 | WorkspaceConfig config;
34 |
35 | try
36 | {
37 | using (var myFileStream = File.OpenRead("config.workspace"))
38 | {
39 | var mySerializer = new XmlSerializer(typeof(WorkspaceConfig));
40 | config = (WorkspaceConfig)mySerializer.Deserialize(myFileStream);
41 | }
42 |
43 | config._excludedExtensions = config.excludedExtensions.Split(';');
44 | }
45 | catch (System.Exception)
46 | {
47 | config = new WorkspaceConfig();
48 | }
49 |
50 | return config;
51 | }
52 |
53 | public void Save()
54 | {
55 | if (File.Exists("config.workspace"))
56 | File.Delete("config.workspace");
57 |
58 | var serializer = new XmlSerializer(typeof(WorkspaceConfig));
59 | using (var stream = File.OpenWrite("config.workspace"))
60 | {
61 | serializer.Serialize(stream, this);
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/gemcutter/Application/CmdArgs.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include
4 |
5 | /*
6 | Assists in reading command line arguments, especially in the format:
7 | -
8 |
9 | For example, if the command line arguments are:
10 | -width 10 -name MyGame -enableDebug 1 -speed 10.2
11 |
12 | Then we could retrieve these values with:
13 | GetCommandLineArg("-width", &int)
14 | GetCommandLineArg("-name", &string)
15 | GetCommandLineArg("-enableDebug", &bool)
16 | GetCommandLineArg("-speed", &float)
17 | */
18 |
19 | namespace gem
20 | {
21 | int GetArgc();
22 | char** GetArgv();
23 |
24 | // Returns true if the command line argument with the given name exists.
25 | bool HasCommandLineArg(const char* name);
26 | // Returns the index of an argument or -1 if the argument is not found.
27 | int FindCommandLineArg(const char* name);
28 | // Returns the directory in which the program's executable was run.
29 | const char* GetExecutablePath();
30 |
31 | // Gets the argument at the specified index.
32 | bool GetCommandLineArg(int index, bool& value);
33 | bool GetCommandLineArg(int index, double& value);
34 | bool GetCommandLineArg(int index, float& value);
35 | bool GetCommandLineArg(int index, int& value);
36 | bool GetCommandLineArg(int index, unsigned& value);
37 | bool GetCommandLineArg(int index, char& value);
38 | bool GetCommandLineArg(int index, const char*& value);
39 | bool GetCommandLineArg(int index, std::string& value);
40 |
41 | // Gets the argument value after the specified name.
42 | template
43 | bool GetCommandLineArg(const char* name, T& value)
44 | {
45 | int index = FindCommandLineArg(name);
46 | if (index == -1)
47 | {
48 | return false;
49 | }
50 |
51 | return GetCommandLineArg(index + 1, value);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/gemcutter/GUI/Image.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 Emilian Cioca
2 | #include "Image.h"
3 | #include "gemcutter/Rendering/Sprite.h"
4 |
5 | namespace gem
6 | {
7 | Image::Image(Entity& _owner)
8 | : Widget(_owner)
9 | {
10 | auto material = Material::MakeNew();
11 | material->depthMode = DepthFunc::None;
12 | material->shader = Load("Engine/Shaders/Sprite");
13 |
14 | sprite = &owner.Require();
15 | sprite->SetAlignment(Alignment::Center);
16 | sprite->SetMaterial(std::move(material));
17 | }
18 |
19 | Image::Image(Entity& _owner, Texture::Ptr texture)
20 | : Image(_owner)
21 | {
22 | sprite->GetMaterial().textures.Add(std::move(texture));
23 | }
24 |
25 | Image::Image(Entity& _owner, Material::Ptr material)
26 | : Widget(_owner)
27 | {
28 | sprite = &owner.Require();
29 | sprite->SetAlignment(Alignment::Center);
30 | sprite->SetMaterial(std::move(material));
31 | }
32 |
33 | Sprite& Image::GetSprite()
34 | {
35 | return *sprite;
36 | }
37 |
38 | const Sprite& Image::GetSprite() const
39 | {
40 | return *sprite;
41 | }
42 |
43 | void Image::SetTexture(Texture::Ptr texture)
44 | {
45 | sprite->GetMaterial().textures.Add(std::move(texture));
46 | }
47 |
48 | Texture::Ptr Image::GetTexture() const
49 | {
50 | std::span textureSlots = sprite->GetMaterial().textures.GetAll();
51 |
52 | return textureSlots.empty() ? nullptr : textureSlots[0].tex;
53 | }
54 |
55 | void Image::SetMaterial(Material::Ptr material)
56 | {
57 | sprite->SetMaterial(std::move(material));
58 | }
59 |
60 | Material& Image::GetMaterial() const
61 | {
62 | return sprite->GetMaterial();
63 | }
64 |
65 | void Image::UpdateContent()
66 | {
67 | const Rectangle& bounds = GetAbsoluteBounds();
68 |
69 | owner.scale.x = bounds.width;
70 | owner.scale.y = bounds.height;
71 | }
72 | }
73 |
74 | REFLECT_COMPONENT(gem::Image, gem::Widget) REF_END;
75 |
--------------------------------------------------------------------------------
/gemcutter/Resource/ParticleFunctor.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #include "ParticleFunctor.h"
3 | #include "gemcutter/Application/Logging.h"
4 | #include "gemcutter/Rendering/ParticleEmitter.h"
5 |
6 | namespace gem
7 | {
8 | void ParticleFunctor::Init(ParticleBuffer&, ParticleEmitter&, unsigned, unsigned)
9 | {
10 | // This function is defined here in order to avoid unused-variable warnings.
11 | }
12 |
13 | FunctorList::FunctorList(const FunctorList& other)
14 | : functors(other.functors)
15 | {
16 | }
17 |
18 | FunctorList& FunctorList::operator=(const FunctorList& other)
19 | {
20 | functors = other.functors;
21 | dirty = true;
22 |
23 | return *this;
24 | }
25 |
26 | void FunctorList::Add(std::shared_ptr functor)
27 | {
28 | functors.push_back(std::move(functor));
29 | dirty = true;
30 | }
31 |
32 | void FunctorList::Clear()
33 | {
34 | functors.clear();
35 | }
36 |
37 | RotationFunc::RotationFunc(float _rotationSpeed, Range _initialRotation)
38 | : rotationSpeed(_rotationSpeed)
39 | , initialRotation(_initialRotation)
40 | {
41 | }
42 |
43 | void RotationFunc::Init(ParticleBuffer& particles, ParticleEmitter&, unsigned startIndex, unsigned count)
44 | {
45 | ASSERT(startIndex + count <= particles.GetMaxParticles(), "Indices out of range.");
46 |
47 | for (unsigned i = startIndex, end = startIndex + count; i < end; ++i)
48 | {
49 | particles.rotations[i] = initialRotation.Random();
50 | }
51 | }
52 |
53 | void RotationFunc::Update(ParticleBuffer& particles, ParticleEmitter& emitter, float deltaTime)
54 | {
55 | float rotation = rotationSpeed * deltaTime;
56 | for (unsigned i = 0; i < emitter.GetNumAliveParticles(); ++i)
57 | {
58 | particles.rotations[i] += rotation;
59 | }
60 | }
61 |
62 | ParticleAttributes RotationFunc::GetRequirements() const
63 | {
64 | return ParticleAttributes::Rotation;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/gemcutter/Utilities/EnumFlags.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include
4 |
5 | namespace gem
6 | {
7 | // Allows you to easily use a strongly-typed enum as if it was a bit-field.
8 | template
9 | class EnumFlags
10 | {
11 | public:
12 | using PrimitiveType = std::underlying_type_t;
13 |
14 | EnumFlags() : value(PrimitiveType{}) {}
15 | EnumFlags(Enumeration val) : value(static_cast(val)) {}
16 | EnumFlags(PrimitiveType val) : value(val) {}
17 |
18 | void Clear()
19 | {
20 | value = PrimitiveType{};
21 | }
22 |
23 | [[nodiscard]]
24 | PrimitiveType Value() const
25 | {
26 | return value;
27 | }
28 |
29 | [[nodiscard]]
30 | bool Has(EnumFlags mask) const
31 | {
32 | return (value & mask.value) != PrimitiveType{};
33 | }
34 |
35 | [[nodiscard]]
36 | bool operator==(EnumFlags other) const
37 | {
38 | return value == other.value;
39 | }
40 |
41 | [[nodiscard]]
42 | bool operator!=(EnumFlags other) const
43 | {
44 | return value != other.value;
45 | }
46 |
47 | EnumFlags& operator|=(EnumFlags other)
48 | {
49 | value = value | other.value;
50 | return *this;
51 | }
52 |
53 | EnumFlags& operator&=(EnumFlags other)
54 | {
55 | value = value & other.value;
56 | return *this;
57 | }
58 |
59 | [[nodiscard]]
60 | EnumFlags operator|(EnumFlags other) const
61 | {
62 | return value | other.value;
63 | }
64 |
65 | [[nodiscard]]
66 | EnumFlags operator&(EnumFlags other) const
67 | {
68 | return value & other.value;
69 | }
70 |
71 | [[nodiscard]]
72 | explicit operator Enumeration() const
73 | {
74 | return static_cast(value);
75 | }
76 |
77 | [[nodiscard]]
78 | explicit operator PrimitiveType() const
79 | {
80 | return value;
81 | }
82 |
83 | private:
84 | PrimitiveType value;
85 | };
86 | }
87 |
--------------------------------------------------------------------------------
/gemcutter/Resource/ConfigTable.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Emilian Cioca
2 | #pragma once
3 | #include
4 | #include
5 | #include