Compare commits
247 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
076960c41d | ||
|
|
2898a6f5b0 | ||
|
|
f1a36c495d | ||
|
|
31388612bb | ||
|
|
5b529bd97d | ||
|
|
d93d69d059 | ||
|
|
82459a6e4c | ||
|
|
5b4d6d915a | ||
|
|
ea044a2357 | ||
|
|
b6c3220797 | ||
|
|
15051a4eb7 | ||
|
|
ef25a932b5 | ||
|
|
d7e60cfe96 | ||
|
|
a27039d7c5 | ||
|
|
18eec6c570 | ||
|
|
699375f1a7 | ||
|
|
c8aa609ab1 | ||
|
|
6a96ce497c | ||
|
|
fb217221b7 | ||
|
|
9238a59a00 | ||
|
|
f1b4aaad76 | ||
|
|
b32ee08b65 | ||
|
|
b33bfcab57 | ||
|
|
6744a58043 | ||
|
|
32273eece9 | ||
|
|
d43c48207c | ||
|
|
d714ac0f35 | ||
|
|
dd46e32bee | ||
|
|
1782f18f26 | ||
|
|
84b2b63ba9 | ||
|
|
4ab59bf7e8 | ||
|
|
d546228089 | ||
|
|
9937d35579 | ||
|
|
1063ffcd58 | ||
|
|
e4c11140e0 | ||
|
|
9b853aef7e | ||
|
|
26ad1507eb | ||
|
|
3fbb1bd33d | ||
|
|
2c4d0faf64 | ||
|
|
0ac0934622 | ||
|
|
0311862b65 | ||
|
|
89209dc7ba | ||
|
|
e47142a3e4 | ||
|
|
5c2311d7b5 | ||
|
|
9647cac48b | ||
|
|
03d785f016 | ||
|
|
f1be4f7cef | ||
|
|
cbf11abcf5 | ||
|
|
3d630483f6 | ||
|
|
c432077328 | ||
|
|
39cf28c91e | ||
|
|
4e0817b761 | ||
|
|
8ed6a53cf4 | ||
|
|
534c35c76f | ||
|
|
28bbb255c5 | ||
|
|
e18dbd292f | ||
|
|
102ccc530b | ||
|
|
31c8a2e598 | ||
|
|
a37bdd9d7a | ||
|
|
6e8f14c5da | ||
|
|
bf75c04a8c | ||
|
|
2dfcb683fc | ||
|
|
f1c403f94c | ||
|
|
114adab73f | ||
|
|
0e750bda89 | ||
|
|
8079c47832 | ||
|
|
29b35a6932 | ||
|
|
ef6e7ac0dc | ||
|
|
0c784d4462 | ||
|
|
954e2110f1 | ||
|
|
3d9cda2990 | ||
|
|
6ac1ff8386 | ||
|
|
7791cd9f29 | ||
|
|
a487d31c48 | ||
|
|
edce52bb17 | ||
|
|
d0c5ef1a1d | ||
|
|
98797e15f8 | ||
|
|
216fa230b6 | ||
|
|
616532e78b | ||
|
|
a87aebe12b | ||
|
|
7fc10b4e56 | ||
|
|
bd6b4362bc | ||
|
|
ca645e2026 | ||
|
|
066b2998ac | ||
|
|
510b577f49 | ||
|
|
67d7865a20 | ||
|
|
ef0fde5847 | ||
|
|
1b2d2985f5 | ||
|
|
07871123cb | ||
|
|
5f1b9dc65b | ||
|
|
c6a2d916a8 | ||
|
|
7ed37d0bbb | ||
|
|
f58e09cfc3 | ||
|
|
bd77025ed0 | ||
|
|
dd3cc823c0 | ||
|
|
da995b99c8 | ||
|
|
1b2abced1e | ||
|
|
38484415f1 | ||
|
|
cf9612c5b1 | ||
|
|
7f92311f12 | ||
|
|
4ac7d1cfc9 | ||
|
|
cff63d71cc | ||
|
|
4a3d15e7d3 | ||
|
|
d19ba4f979 | ||
|
|
ae426f7f17 | ||
|
|
8b2511f995 | ||
|
|
d338a98c9b | ||
|
|
bb43bbe1b8 | ||
|
|
52776186d3 | ||
|
|
b23d418f23 | ||
|
|
baac971deb | ||
|
|
24be72b10a | ||
|
|
269533eb03 | ||
|
|
7846a667a2 | ||
|
|
0dcd383dbb | ||
|
|
2b06fe32de | ||
|
|
1d5f578e86 | ||
|
|
6149907576 | ||
|
|
d8d904b6ba | ||
|
|
1e570e17fd | ||
|
|
d62f241a16 | ||
|
|
5d0eb4a597 | ||
|
|
dabd9c01a6 | ||
|
|
aed98dd648 | ||
|
|
59505b0664 | ||
|
|
9e94006d2b | ||
|
|
82771d43da | ||
|
|
65c8ab79af | ||
|
|
68ffe1d6b4 | ||
|
|
90a60e8d87 | ||
|
|
56e12c2647 | ||
|
|
7d66a19ab2 | ||
|
|
bf6fb0f8b6 | ||
|
|
ded6fd2e03 | ||
|
|
c2e50822f1 | ||
|
|
24a4281a3d | ||
|
|
c5dca4dc37 | ||
|
|
edc4d43f97 | ||
|
|
a7cbbf2830 | ||
|
|
68ae15594f | ||
|
|
79908a12a5 | ||
|
|
fad8b4033b | ||
|
|
efc4b8bae7 | ||
|
|
6e92674bba | ||
|
|
ee852f7f3d | ||
|
|
bb0da25682 | ||
|
|
1b89eaa695 | ||
|
|
89ea32a4b3 | ||
|
|
4c76e9e493 | ||
|
|
3b148b76c4 | ||
|
|
9e87dca9ce | ||
|
|
5e1483e111 | ||
|
|
c7621b31e0 | ||
|
|
596e4a484c | ||
|
|
a5bf5d99c7 | ||
|
|
8b6991822f | ||
|
|
7ee76a129e | ||
|
|
a75bcc260f | ||
|
|
f1903de9ab | ||
|
|
40da75eeeb | ||
|
|
7efa69a20d | ||
|
|
706821861b | ||
|
|
0e78c7d889 | ||
|
|
7a5568b513 | ||
|
|
ebedefb6a7 | ||
|
|
552fe0ee04 | ||
|
|
2c48590a4a | ||
|
|
1949946cdd | ||
|
|
dcbd6d0fe3 | ||
|
|
ffc79ccdf4 | ||
|
|
7e341b34cf | ||
|
|
1051f0cdd3 | ||
|
|
aef5f65f75 | ||
|
|
5a0f7c06f0 | ||
|
|
0f14e303b2 | ||
|
|
22a859b3e1 | ||
|
|
e36e33aa9a | ||
|
|
f30e178e87 | ||
|
|
9f09773636 | ||
|
|
73e0498287 | ||
|
|
13c0fb414d | ||
|
|
7c123e1c0a | ||
|
|
219c9a97cd | ||
|
|
20ade88fd9 | ||
|
|
6005eb51d3 | ||
|
|
8d69094cf2 | ||
|
|
5034adca8e | ||
|
|
81b69749d9 | ||
|
|
89971b2d77 | ||
|
|
43e9d6e7fc | ||
|
|
2c2ed94eea | ||
|
|
120af20237 | ||
|
|
422331dec2 | ||
|
|
9e05e6883a | ||
|
|
73c927fdaf | ||
|
|
5e3472c256 | ||
|
|
732e94899c | ||
|
|
ea97133e94 | ||
|
|
e1550fbff9 | ||
|
|
780b95fba7 | ||
|
|
a2f28c4c86 | ||
|
|
9c5f05f224 | ||
|
|
e607b99191 | ||
|
|
e1813870a2 | ||
|
|
ec9748ecd7 | ||
|
|
7140d2b4ff | ||
|
|
8c620be479 | ||
|
|
10b8c862e7 | ||
|
|
dc3c993962 | ||
|
|
db0ec40948 | ||
|
|
f650f0485b | ||
|
|
156bf8c5cc | ||
|
|
87f58d890e | ||
|
|
c91812c65e | ||
|
|
db21f342b5 | ||
|
|
adb90b4f42 | ||
|
|
112718d1ac | ||
|
|
aaf553f8ba | ||
|
|
db8ec0fbfd | ||
|
|
1ac0337863 | ||
|
|
be725f52f2 | ||
|
|
55a2403b88 | ||
|
|
54e5787472 | ||
|
|
8aef2aaff9 | ||
|
|
ced74170c5 | ||
|
|
000a1d564e | ||
|
|
d9237f83d2 | ||
|
|
5a801e642c | ||
|
|
01000b9d13 | ||
|
|
d20847b4e3 | ||
|
|
c7a1c10ff0 | ||
|
|
5077b1b7f8 | ||
|
|
8f72f1711d | ||
|
|
7af703b5fc | ||
|
|
178ad898b9 | ||
|
|
63578ced2d | ||
|
|
5971e4f2d6 | ||
|
|
67a1406e1b | ||
|
|
bcf3e9751a | ||
|
|
636736f567 | ||
|
|
b7ee13c0eb | ||
|
|
d289c5431d | ||
|
|
63712edc6d | ||
|
|
f59a7e931f | ||
|
|
8aa41a1bf8 | ||
|
|
05096355be | ||
|
|
c5563c204c |
@@ -1,59 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Directory containing the files
|
||||
input_directory="Resources"
|
||||
|
||||
# Output C++ header file for variable declarations
|
||||
output_header="Nuake/src/Resource/StaticResources.h"
|
||||
|
||||
# Output C++ source file for data storage
|
||||
output_source="Nuake/src/Resource/StaticResources.cpp"
|
||||
|
||||
# Remove existing header and source files (if any)
|
||||
rm -f "$output_header" "$output_source"
|
||||
|
||||
# Create the C++ header file with an initial guard
|
||||
echo "#ifndef FILES_DATA_H" >> "$output_header"
|
||||
echo "#define FILES_DATA_H" >> "$output_header"
|
||||
|
||||
echo "#include <string> " >> "$output_header"
|
||||
|
||||
echo "namespace Nuake { " >> "$output_header"
|
||||
echo " namespace StaticResources { " >> "$output_header"
|
||||
|
||||
# Create the C++ source file
|
||||
echo "#include \"StaticResources.h\"" >> "$output_source"
|
||||
|
||||
echo "namespace Nuake { " >> "$output_source"
|
||||
echo " namespace StaticResources { " >> "$output_source"
|
||||
# Use find to search for files in the directory and its subdirectories
|
||||
find "$input_directory" -type f -print0 | while IFS= read -r -d $'\0' file_path; do
|
||||
# Get the relative path of the file within the input_directory
|
||||
relative_path="${file_path/}"
|
||||
|
||||
# Sanitize the relative path to make it suitable for C++ variable names
|
||||
sanitized_path="${relative_path//[^[:alnum:]_]/_}"
|
||||
|
||||
# Generate C++ variable declarations for file path and size
|
||||
echo "extern const std::string ${sanitized_path}_path;" >> "$output_header"
|
||||
echo "extern unsigned int ${sanitized_path}_len;" >> "$output_header"
|
||||
echo "extern unsigned char ${sanitized_path}[];" >> "$output_header"
|
||||
|
||||
# Append C++ code to the source file for storing file data
|
||||
echo -e "\n// Data for file: ${sanitized_path}_path" >> "$output_source"
|
||||
echo "const std::string ${sanitized_path}_path = R\"(${relative_path})\";" >> "$output_source"
|
||||
|
||||
xxd -i "$file_path" | sed -e 's/^/ /' >> "$output_source"
|
||||
done
|
||||
|
||||
echo " }" >> "$output_source"
|
||||
echo "}">> "$output_source"
|
||||
|
||||
echo " }" >> "$output_header"
|
||||
echo "}">> "$output_header"
|
||||
|
||||
# Close the header file guard
|
||||
echo "#endif // FILES_DATA_H" >> "$output_header"
|
||||
|
||||
echo "Header file '$output_header' generated with variable declarations."
|
||||
echo "Source file '$output_source' generated with file data."
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -864,3 +864,4 @@ Nuake/dependencies/glad/glad.vcxproj.filters
|
||||
*.csproj
|
||||
*.filters
|
||||
cloc.exe
|
||||
Nuake/src/Modules/Modules.cpp
|
||||
27
.gitmodules
vendored
27
.gitmodules
vendored
@@ -1,15 +1,6 @@
|
||||
[submodule "Nuake/dependencies/glfw"]
|
||||
path = Nuake/dependencies/glfw
|
||||
url = https://github.com/glfw/glfw.git
|
||||
[submodule "Nuake/dependencies/assimp"]
|
||||
path = Nuake/dependencies/assimp
|
||||
url = https://github.com/assimp/assimp.git
|
||||
[submodule "Nuake/dependencies/bullet3"]
|
||||
path = Nuake/dependencies/bullet3
|
||||
url = https://github.com/bulletphysics/bullet3.git
|
||||
[submodule "Nuake/dependencies/glew"]
|
||||
path = Nuake/dependencies/glew
|
||||
url = https://github.com/nigels-com/glew.git
|
||||
[submodule "Nuake/dependencies/JoltPhysics"]
|
||||
path = Nuake/dependencies/JoltPhysics
|
||||
url = https://github.com/antopilo/JoltPhysics.git
|
||||
@@ -22,3 +13,21 @@
|
||||
[submodule "Nuake/dependencies/recastnavigation"]
|
||||
path = Nuake/dependencies/recastnavigation
|
||||
url = https://github.com/antopilo/recastnavigation.git
|
||||
[submodule "Nuake/dependencies/tracy"]
|
||||
path = Nuake/dependencies/tracy
|
||||
url = https://github.com/wolfpld/tracy.git
|
||||
[submodule "Nuake/dependencies/msdf-atlas-gen"]
|
||||
path = Nuake/dependencies/msdf-atlas-gen
|
||||
url = https://github.com/antopilo/msdf-atlas-gen.git
|
||||
[submodule "Nuake/dependencies/yoga"]
|
||||
path = Nuake/dependencies/yoga
|
||||
url = https://github.com/facebook/yoga.git
|
||||
[submodule "Nuake/dependencies/freetype"]
|
||||
path = Nuake/dependencies/freetype
|
||||
url = https://github.com/freetype/freetype.git
|
||||
[submodule "Nuake/dependencies/entt"]
|
||||
path = Nuake/dependencies/entt
|
||||
url = https://github.com/skypjack/entt.git
|
||||
[submodule "Nuake/dependencies/glfw"]
|
||||
path = Nuake/dependencies/glfw
|
||||
url = https://github.com/antopilo/glfw.git
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: 3.7
|
||||
#install:
|
||||
#- requirements: docs/requirements.txt
|
||||
@@ -5,23 +5,19 @@
|
||||
#include <src/Core/Input.h>
|
||||
#include <src/Scene/Scene.h>
|
||||
#include <src/Scene/Entities/Entity.h>
|
||||
#include <src/Scene/Components/Components.h>
|
||||
#include <src/Scene/Components.h>
|
||||
|
||||
#include "src/Windows/EditorInterface.h"
|
||||
|
||||
#include <src/Scene/Components/QuakeMap.h>
|
||||
#include <src/Vendors/imgui/imgui.h>
|
||||
#include <src/Vendors/imgui/ImGuizmo.h>
|
||||
#include <src/Physics/PhysicsManager.h>
|
||||
#include "src/Scene/Components/BoxCollider.h"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <src/Vendors/glm/trigonometric.hpp>
|
||||
#include <src/Scripting/ScriptingEngine.h>
|
||||
#include <src/Resource/FGD/FGDFile.h>
|
||||
#include <src/Rendering/Shaders/ShaderManager.h>
|
||||
#include <src/Rendering/Renderer.h>
|
||||
#include <src/Scene/Components/BSPBrushComponent.h>
|
||||
|
||||
#include "src/Actions/EditorSelection.h"
|
||||
#include "src/Misc/GizmoDrawer.h"
|
||||
@@ -98,6 +94,13 @@ LaunchSettings ParseLaunchSettings(const std::vector<std::string>& arguments)
|
||||
launchSettings.monitor = stoi(arguments[i + 1]);
|
||||
}
|
||||
}
|
||||
else if (argumentSize == 2 && Nuake::FileSystem::FileExists(arg))
|
||||
{
|
||||
if (Nuake::String::EndsWith(arg, ".project"))
|
||||
{
|
||||
launchSettings.projectPath = arg;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
@@ -116,11 +119,12 @@ Nuake::Application* Nuake::CreateApplication(int argc, char** argv)
|
||||
ApplicationSpecification specification
|
||||
{
|
||||
.Name = "Editor",
|
||||
.WindowWidth = 1100,
|
||||
.WindowHeight = 630,
|
||||
.WindowWidth = static_cast<uint32_t>(launchSettings.resolution.x),
|
||||
.WindowHeight = static_cast<uint32_t>(launchSettings.resolution.y),
|
||||
.VSync = true
|
||||
};
|
||||
|
||||
|
||||
#ifdef NK_DEBUG
|
||||
specification.Name += "(DEBUG BUILD)";
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
struct LaunchSettings
|
||||
{
|
||||
int32_t monitor = 1;
|
||||
Nuake::Vector2 resolution = { 1920, 1080 };
|
||||
Nuake::Vector2 resolution = { 1100, 630 };
|
||||
std::string windowTitle = "Nuake Editor ";
|
||||
std::string projectPath;
|
||||
};
|
||||
|
||||
BIN
Editor/SourceSansPro-Regular.ttf
Normal file
BIN
Editor/SourceSansPro-Regular.ttf
Normal file
Binary file not shown.
@@ -41,7 +41,6 @@ public:
|
||||
EditorSelection(const Nuake::Entity& entity)
|
||||
{
|
||||
Type = EditorSelectionType::Entity;
|
||||
Nuake::Engine::GetCurrentScene()->m_SceneRenderer->mOutlineEntityID = (uint32_t)entity.GetHandle();
|
||||
Entity = entity;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include "Commands.h"
|
||||
|
||||
#include <Engine.h>
|
||||
#include "src/Core/FileSystem.h"
|
||||
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace NuakeEditor
|
||||
{
|
||||
@@ -39,6 +42,12 @@ namespace NuakeEditor
|
||||
{
|
||||
const std::string& cleanProjectName = String::Sanitize(mProject->Name);
|
||||
const std::string& gameConfigFolderPath = mProject->TrenchbroomPath + "/../games/" + cleanProjectName + "/";
|
||||
|
||||
if (!FileSystem::DirectoryExists(gameConfigFolderPath))
|
||||
{
|
||||
FileSystem::MakeDirectory(gameConfigFolderPath, true);
|
||||
}
|
||||
|
||||
const std::string& gameConfigFilePath = gameConfigFolderPath + "GameConfig.cfg";
|
||||
FileSystem::BeginWriteFile(gameConfigFilePath, true);
|
||||
|
||||
@@ -56,7 +65,7 @@ namespace NuakeEditor
|
||||
"packageformat": { "extension": ".zip", "format": "zip" }
|
||||
},
|
||||
"textures": {
|
||||
"root": "textures",
|
||||
"root": "Textures",
|
||||
"extensions": [ ".jpg", ".png", ".tga" ]
|
||||
},
|
||||
"entities": {
|
||||
@@ -69,8 +78,8 @@ namespace NuakeEditor
|
||||
"name": "Trigger",
|
||||
"attribs": [ "transparent" ],
|
||||
"match": "classname",
|
||||
"pattern": "trigger_*",
|
||||
"texture": "trigger"
|
||||
"pattern": "Trigger*",
|
||||
"texture": "trigger.png"
|
||||
}
|
||||
],
|
||||
"brushface": [
|
||||
@@ -135,7 +144,7 @@ namespace NuakeEditor
|
||||
// Copy Icon.png
|
||||
if (FileSystem::FileExists("icon.png"))
|
||||
{
|
||||
std::filesystem::copy_file(FileSystem::RelativeToAbsolute("icon.png"), gameConfigFolderPath + "Icon.png");
|
||||
std::filesystem::copy_file(FileSystem::RelativeToAbsolute("icon.png"), gameConfigFolderPath + "Icon.png", std::filesystem::copy_options::overwrite_existing);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/AudioEmitterComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
|
||||
class AudioEmitterPanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
AudioEmitterPanel() = default;
|
||||
~AudioEmitterPanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<AudioEmitterComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<AudioEmitterComponent>();
|
||||
BeginComponentTable(AUDIO EMITTER, AudioEmitterComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Audio File");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.FilePath;
|
||||
ImGui::Button(component.FilePath.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_AudioFile"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
component.FilePath = path;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.FilePath, "");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Playing");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
UI::ToggleButton("##Player", &component.IsPlaying);
|
||||
//ImGui::Checkbox("##Playing", &component.IsPlaying);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.IsPlaying, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Loop");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##Loop", &component.Loop);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Loop, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Volume");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##Volume", &component.Volume, 0.001f, 0.0f, 2.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Volume, 1.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Playback Speed");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##PlaybackSpeed", &component.PlaybackSpeed, 0.01f, 0.0001f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.PlaybackSpeed, 1.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Pan");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##Pan", &component.Pan, 0.01f, -1.0f, 1.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Pan, 0.0f);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Spatialized");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##Spatialized", &component.Spatialized);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Spatialized, false);
|
||||
}
|
||||
|
||||
if (component.Spatialized)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Min Distance");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##minDistance", &component.MinDistance, 0.001f, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.MinDistance, 1.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Max Distance");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##maxDistance", &component.MaxDistance, 0.001f, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.MaxDistance, 10.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Attenuation Factor");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##attenuationFactor", &component.AttenuationFactor, 0.001f, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.AttenuationFactor, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,24 +1,25 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/BoneComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
class BonePanel : ComponentPanel
|
||||
class BonePanel
|
||||
{
|
||||
public:
|
||||
BonePanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<BoneComponent>())
|
||||
|
||||
Nuake::BoneComponent* componentPtr = componentInstance.try_cast<Nuake::BoneComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<BoneComponent>();
|
||||
}
|
||||
Nuake::BoneComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(BONE, BoneComponent);
|
||||
{
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/BoxCollider.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
#include <src/Scene/Components/CameraComponent.h>
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
class CameraPanel : ComponentPanel {
|
||||
class CameraPanel {
|
||||
|
||||
public:
|
||||
CameraPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::CameraComponent>())
|
||||
using namespace Nuake;
|
||||
|
||||
Nuake::CameraComponent* componentPtr = componentInstance.try_cast<Nuake::CameraComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::CameraComponent>();
|
||||
}
|
||||
Nuake::CameraComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(CAMERA, Nuake::CameraComponent);
|
||||
{
|
||||
{
|
||||
|
||||
@@ -3,48 +3,47 @@
|
||||
|
||||
#include <src/Scene/Components/CapsuleColliderComponent.h>
|
||||
|
||||
class CapsuleColliderPanel : ComponentPanel
|
||||
class CapsuleColliderPanel
|
||||
{
|
||||
public:
|
||||
CapsuleColliderPanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<CapsuleColliderComponent>())
|
||||
|
||||
Nuake::CapsuleColliderComponent* componentPtr = componentInstance.try_cast<Nuake::CapsuleColliderComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& [Capsule, Radius, Height, IsTrigger] = entity.GetComponent<CapsuleColliderComponent>();
|
||||
Nuake::CapsuleColliderComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(CAPSULE COLLIDER, CapsuleColliderComponent)
|
||||
{
|
||||
{
|
||||
ImGui::Text("Radius");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Radius", &Radius, 0.01f, 0.001f);
|
||||
Radius = std::max(Radius, 0.001f);
|
||||
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f);
|
||||
component.Radius = std::max(component.Radius, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(Radius, 0.5f)
|
||||
ComponentTableReset(component.Radius, 0.5f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Height");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Height", &Height, 0.01f, 0.001f);
|
||||
Height = std::max(Height, 0.001f);
|
||||
ImGui::DragFloat("##Height", &component.Height, 0.01f, 0.001f);
|
||||
component.Height = std::max(component.Height, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(Height, 1.0f)
|
||||
ComponentTableReset(component.Height, 1.0f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Is Trigger");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##isTrigger", &IsTrigger);
|
||||
ImGui::Checkbox("##isTrigger", &component.IsTrigger);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(IsTrigger, false);
|
||||
ComponentTableReset(component.IsTrigger, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable()
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
#include <src/Scene/Components/CharacterControllerComponent.h>
|
||||
#include <src/Core/FileSystem.h>
|
||||
|
||||
class CharacterControllerPanel : ComponentPanel {
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
class CharacterControllerPanel
|
||||
{
|
||||
public:
|
||||
CharacterControllerPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::CharacterControllerComponent>())
|
||||
return;
|
||||
using namespace Nuake;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::CharacterControllerComponent>();
|
||||
|
||||
Nuake::CharacterControllerComponent* componentPtr = componentInstance.try_cast<Nuake::CharacterControllerComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Nuake::CharacterControllerComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(CHARACTER CONTROLLER, Nuake::CharacterControllerComponent);
|
||||
{
|
||||
{
|
||||
@@ -50,7 +52,7 @@ public:
|
||||
{
|
||||
ImGui::Text("Stick to floor step down");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##StickToFloorStepDown", &component.StickToFloorStepDown.y, -10.0f, 0.01, 0.0f);
|
||||
ImGui::DragFloat("##StickToFloorStepDown", &component.StickToFloorStepDown.y, -10.0f, 0.01f, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.StickToFloorStepDown.y, -0.5f);
|
||||
}
|
||||
@@ -58,7 +60,7 @@ public:
|
||||
{
|
||||
ImGui::Text("Step down extra");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##StepDownExtra", &component.StepDownExtra.y, -10.0f, 0.01, 0.0f);
|
||||
ImGui::DragFloat("##StepDownExtra", &component.StepDownExtra.y, -10.0f, 0.01f, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.StepDownExtra.y, 0.0f);
|
||||
}
|
||||
@@ -66,7 +68,7 @@ public:
|
||||
{
|
||||
ImGui::Text("Step up");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##StepUp", &component.SteppingStepUp.y, 0.0f, 0.01, 10.0f);
|
||||
ImGui::DragFloat("##StepUp", &component.SteppingStepUp.y, 0.0f, 0.01f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.SteppingStepUp.y, 0.4f);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ ImGui::Text(##name);
|
||||
bool removed = false; \
|
||||
bool headerOpened = ImGui::CollapsingHeader(#name, ImGuiTreeNodeFlags_DefaultOpen); \
|
||||
ImGui::PopStyleVar(); \
|
||||
if (#name != "TRANSFORM" && ImGui::BeginPopupContextItem()) \
|
||||
if (strcmp(#name, "TRANSFORM") != 0 && ImGui::BeginPopupContextItem()) \
|
||||
{ \
|
||||
if (ImGui::Selectable("Remove")) { removed = true; } \
|
||||
ImGui::EndPopup(); \
|
||||
@@ -42,7 +42,7 @@ ImGui::Text(##name);
|
||||
{ \
|
||||
delete boldFont; \
|
||||
ImGui::PopStyleVar(); \
|
||||
ImGui::Indent(); \
|
||||
ImGui::Indent(); \
|
||||
if (ImGui::BeginTable(#name, 3, ImGuiTableFlags_SizingStretchProp)) \
|
||||
{ \
|
||||
ImGui::TableSetupColumn("name", 0, 0.25f); \
|
||||
@@ -93,5 +93,7 @@ ImGui::Text(##name);
|
||||
|
||||
class ComponentPanel {
|
||||
public:
|
||||
virtual void Draw(Nuake::Entity entity) = 0;
|
||||
};
|
||||
virtual void Draw(Nuake::Entity entity);
|
||||
};
|
||||
|
||||
inline void ComponentPanel::Draw(Nuake::Entity entity) {}
|
||||
|
||||
@@ -3,48 +3,47 @@
|
||||
|
||||
#include <src/Scene/Components/CylinderColliderComponent.h>
|
||||
|
||||
class CylinderColliderPanel : ComponentPanel
|
||||
class CylinderColliderPanel
|
||||
{
|
||||
public:
|
||||
CylinderColliderPanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<CylinderColliderComponent>())
|
||||
|
||||
Nuake::CylinderColliderComponent* componentPtr = componentInstance.try_cast<Nuake::CylinderColliderComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& [Cylinder, Radius, Height, IsTrigger] = entity.GetComponent<CylinderColliderComponent>();
|
||||
Nuake::CylinderColliderComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(CYLINDER COLLIDER, CylinderColliderComponent)
|
||||
{
|
||||
{
|
||||
ImGui::Text("Radius");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Radius", &Radius, 0.01f, 0.001f);
|
||||
Radius = std::max(Radius, 0.001f);
|
||||
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f);
|
||||
component.Radius = std::max(component.Radius, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(Radius, 0.5f)
|
||||
ComponentTableReset(component.Radius, 0.5f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Height");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Height", &Height, 0.01f, 0.0001f);
|
||||
Height = std::max(Height, 0.001f);
|
||||
ImGui::DragFloat("##Height", &component.Height, 0.01f, 0.0001f);
|
||||
component.Height = std::max(component.Height, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(Height, 1.0f)
|
||||
ComponentTableReset(component.Height, 1.0f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Is Trigger");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##isTrigger", &IsTrigger);
|
||||
ImGui::Checkbox("##isTrigger", &component.IsTrigger);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(IsTrigger, false);
|
||||
ComponentTableReset(component.IsTrigger, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable()
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
#include "ComponentPanel.h"
|
||||
#include "src/Scene/Components/LightComponent.h"
|
||||
|
||||
class LightPanel :ComponentPanel {
|
||||
|
||||
class LightPanel
|
||||
{
|
||||
public:
|
||||
LightPanel() { }
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::LightComponent>())
|
||||
return;
|
||||
|
||||
Nuake::LightComponent& component = entity.GetComponent<Nuake::LightComponent>();
|
||||
Nuake::LightComponent* componentPtr = componentInstance.try_cast<Nuake::LightComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Nuake::LightComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(LIGHT, Nuake::LightComponent);
|
||||
{
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#include "MaterialEditor.h"
|
||||
#include <imgui/imgui.h>
|
||||
#include <src/Resource/FontAwesome5.h>
|
||||
#include <src/Vendors/imgui/imgui_internal.h>
|
||||
#include "../Misc/InterfaceFonts.h"
|
||||
#include <src/Resource/FontAwesome5.h>
|
||||
#include <src/Resource/ResourceManager.h>
|
||||
#include <src/FileSystem/FileDialog.h>
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <src/Vendors/imgui/imgui_internal.h>
|
||||
|
||||
|
||||
void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
{
|
||||
|
||||
@@ -9,23 +9,25 @@
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
#include <src/Core/String.h>
|
||||
|
||||
class MeshColliderPanel : ComponentPanel {
|
||||
private:
|
||||
Scope<ModelResourceInspector> _modelInspector;
|
||||
bool _expanded = false;
|
||||
class MeshColliderPanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
MeshColliderPanel()
|
||||
{
|
||||
CreateScope<ModelResourceInspector>();
|
||||
}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
if (!entity.HasComponent<MeshColliderComponent>())
|
||||
|
||||
Nuake::MeshColliderComponent* componentPtr = componentInstance.try_cast<Nuake::MeshColliderComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
|
||||
MeshColliderComponent& component = entity.GetComponent<MeshColliderComponent>();
|
||||
}
|
||||
Nuake::MeshColliderComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(MESH, MeshColliderComponent);
|
||||
{
|
||||
ImGui::Text("Model");
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <src/Scene/Components/ModelComponent.h>
|
||||
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
#include <src/Resource/ResourceManager.h>
|
||||
|
||||
#include <src/Core/String.h>
|
||||
#include <src/Resource/ModelLoader.h>
|
||||
|
||||
@@ -24,13 +26,17 @@ public:
|
||||
CreateScope<ModelResourceInspector>();
|
||||
}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
if (!entity.HasComponent<ModelComponent>())
|
||||
|
||||
Nuake::ModelComponent* componentPtr = componentInstance.try_cast<Nuake::ModelComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
|
||||
ModelComponent& component = entity.GetComponent<ModelComponent>();
|
||||
}
|
||||
Nuake::ModelComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(MESH, ModelComponent);
|
||||
{
|
||||
ImGui::Text("Model");
|
||||
|
||||
@@ -3,24 +3,25 @@
|
||||
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
#include <src/Scene/Components/NavMeshVolumeComponent.h>
|
||||
#include "src/AI/NavManager.h"
|
||||
#include "src/Scene/Components/QuakeMap.h"
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/AI/RecastConfig.h>
|
||||
|
||||
class NavMeshVolumePanel : ComponentPanel {
|
||||
|
||||
class NavMeshVolumePanel
|
||||
{
|
||||
public:
|
||||
NavMeshVolumePanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<NavMeshVolumeComponent>())
|
||||
|
||||
Nuake::NavMeshVolumeComponent* componentPtr = componentInstance.try_cast<Nuake::NavMeshVolumeComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& component = entity.GetComponent<NavMeshVolumeComponent>();
|
||||
Nuake::NavMeshVolumeComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(NAVMESH VOLUME, NavMeshVolumeComponent);
|
||||
{
|
||||
{
|
||||
@@ -384,4 +385,4 @@ public:
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,16 +1,57 @@
|
||||
#include "NetScriptPanel.h"
|
||||
|
||||
#include "../Windows/FileSystemUI.h"
|
||||
#include <src/Scene/Components/NetScriptComponent.h>
|
||||
#include <src/Core/FileSystem.h>
|
||||
|
||||
#include <src/FileSystem/FileDialog.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Scripting/ScriptingEngineNet.h>
|
||||
#include <src/Scene/Components/NetScriptComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
void NetScriptPanel::Draw(Nuake::Entity entity)
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::NetScriptComponent>())
|
||||
return;
|
||||
const std::string NET_TEMPLATE_SCRIPT_FIRST = R"(using Nuake.Net;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::NetScriptComponent>();
|
||||
namespace NuakeShowcase
|
||||
{
|
||||
class )";
|
||||
|
||||
const std::string NET_TEMPLATE_SCRIPT_SECOND = R"( : Entity
|
||||
{
|
||||
public override void OnInit()
|
||||
{
|
||||
// Called once at the start of the game
|
||||
}
|
||||
|
||||
|
||||
public override void OnUpdate(float dt)
|
||||
{
|
||||
// Called every frame
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate(float dt)
|
||||
{
|
||||
// Called every fixed update
|
||||
}
|
||||
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
// Called at the end of the game fixed update
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
void NetScriptPanel::Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
Nuake::NetScriptComponent* componentPtr = componentInstance.try_cast<Nuake::NetScriptComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Nuake::NetScriptComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(.NETSCRIPT, Nuake::NetScriptComponent);
|
||||
{
|
||||
{
|
||||
@@ -130,6 +171,11 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
|
||||
{
|
||||
if (!field.Value.has_value())
|
||||
{
|
||||
if (!field.DefaultValue.has_value())
|
||||
{
|
||||
field.DefaultValue = 0.0f;
|
||||
}
|
||||
|
||||
field.Value = field.DefaultValue;
|
||||
}
|
||||
|
||||
@@ -143,6 +189,11 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
|
||||
{
|
||||
if (!field.Value.has_value())
|
||||
{
|
||||
if (!field.DefaultValue.has_value())
|
||||
{
|
||||
field.DefaultValue = 0.0;
|
||||
}
|
||||
|
||||
field.Value = field.DefaultValue;
|
||||
}
|
||||
|
||||
@@ -156,13 +207,22 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
|
||||
{
|
||||
if (!field.Value.has_value())
|
||||
{
|
||||
if (!field.DefaultValue.has_value())
|
||||
{
|
||||
field.DefaultValue = false;
|
||||
}
|
||||
|
||||
field.Value = field.DefaultValue;
|
||||
}
|
||||
|
||||
bool currentValue = std::any_cast<bool>(field.Value);
|
||||
const std::string sliderName = "##" + field.Name + "slider";
|
||||
ImGui::Checkbox(sliderName.c_str(), ¤tValue);
|
||||
field.Value = currentValue;
|
||||
auto typeName = field.Value.type().name();
|
||||
if (typeName == std::string("bool"))
|
||||
{
|
||||
bool currentValue = std::any_cast<bool>(field.Value);
|
||||
const std::string sliderName = "##" + field.Name + "slider";
|
||||
ImGui::Checkbox(sliderName.c_str(), ¤tValue);
|
||||
field.Value = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (field.Type == Nuake::NetScriptExposedVarType::String)
|
||||
@@ -188,6 +248,11 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
|
||||
{
|
||||
if (!field.Value.has_value())
|
||||
{
|
||||
if (!field.DefaultValue.has_value())
|
||||
{
|
||||
field.DefaultValue = Nuake::Vector2(0, 0);
|
||||
}
|
||||
|
||||
field.Value = field.DefaultValue;
|
||||
}
|
||||
|
||||
@@ -203,6 +268,11 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
|
||||
{
|
||||
if (!field.Value.has_value())
|
||||
{
|
||||
if (!field.DefaultValue.has_value())
|
||||
{
|
||||
field.DefaultValue = Nuake::Vector3(0, 0, 0);
|
||||
}
|
||||
|
||||
field.Value = field.DefaultValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,45 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
|
||||
const std::string NET_TEMPLATE_SCRIPT_FIRST = R"(using Nuake.Net;
|
||||
|
||||
namespace NuakeShowcase
|
||||
class NetScriptPanel
|
||||
{
|
||||
class )";
|
||||
|
||||
const std::string NET_TEMPLATE_SCRIPT_SECOND = R"( : Entity
|
||||
{
|
||||
public override void OnInit()
|
||||
{
|
||||
// Called once at the start of the game
|
||||
}
|
||||
|
||||
|
||||
public override void OnUpdate(float dt)
|
||||
{
|
||||
// Called every frame
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate(float dt)
|
||||
{
|
||||
// Called every fixed update
|
||||
}
|
||||
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
// Called at the end of the game fixed update
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
class NetScriptPanel : ComponentPanel {
|
||||
|
||||
public:
|
||||
NetScriptPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override;
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance);
|
||||
};
|
||||
@@ -1,155 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/ParticleEmitterComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
#include "MaterialEditor.h"
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
|
||||
class ParticleEmitterPanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
Scope<ModelResourceInspector> _modelInspector;
|
||||
|
||||
ParticleEmitterPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::ParticleEmitterComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::ParticleEmitterComponent>();
|
||||
BeginComponentTable(PARTICLE EMITTER, Nuake::ParticleEmitterComponent);
|
||||
{
|
||||
|
||||
{
|
||||
ImGui::Text("Particle Material");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string label = "Empty";
|
||||
if (component.ParticleMaterial && !component.ParticleMaterial->Path.empty())
|
||||
{
|
||||
label = component.ParticleMaterial->Path;
|
||||
}
|
||||
|
||||
if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Material"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
|
||||
fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
|
||||
Ref<Nuake::Material> material = Nuake::ResourceLoader::LoadMaterial(fullPath);
|
||||
component.ParticleMaterial = material;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
//std::string childId = "materialEditorParticle";
|
||||
//ImGui::BeginChild(childId.c_str(), ImVec2(0, 0), false);
|
||||
//{
|
||||
// MaterialEditor editor;
|
||||
// editor.Draw(component.ParticleMaterial);
|
||||
//}
|
||||
//ImGui::EndChild();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
//ComponentTableReset(component.ParticleColor, Nuake::Vector4(1, 1, 1, 1));
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Amount");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleAmount", &component.Amount, 0.1f, 0.0f, 500.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Amount, 10.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Particle Scale");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGuiHelper::DrawVec3("##particleSize", &component.ParticleScale);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.ParticleScale, Nuake::Vector3(0.1, 0.1, 0.1));
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Particle Scale Random");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##particleSizeRandom", &component.ScaleRandomness, 0.01f, 0.0f);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.ScaleRandomness, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Global Space");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##globalSpace", &component.GlobalSpace);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.GlobalSpace, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Rate");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleRate", &component.Rate, 0.1f, 0.0f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Rate, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Life");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleLife", &component.Life, 0.1f, 0.0f, 100.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Life, 5.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Gravity");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGuiHelper::DrawVec3("Gravity", &component.Gravity);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Gravity, Nuake::Vector3(0, -1, 0));
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Gravity Random");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##GravityRandom", &component.GravityRandom, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.GravityRandom, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Radius");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##ParticleRadius", &component.Radius, 0.01f, 0.0f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Radius, 1.0f);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,79 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
#include <src/Scene/Components/QuakeMap.h>
|
||||
#include "src/Scene/Systems/QuakeMapBuilder.h"
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/AI/NavManager.h>
|
||||
#include <src/UI/ImUI.h>
|
||||
|
||||
class QuakeMapPanel : ComponentPanel {
|
||||
|
||||
public:
|
||||
QuakeMapPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<Nuake::QuakeMapComponent>())
|
||||
return;
|
||||
|
||||
Nuake::QuakeMapComponent& component = entity.GetComponent<Nuake::QuakeMapComponent>();
|
||||
BeginComponentTable(QUAKEMAP, Nuake::QuakeMapComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Map");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.Path;
|
||||
ImGui::Button(component.Path.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Map"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
|
||||
component.Path = path;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Path, "");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Collision");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##Collison", &component.HasCollisions);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.HasCollisions, true);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Auto Rebuild");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##AutoRebuild", &component.AutoRebuild);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.AutoRebuild, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Build");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (UI::SecondaryButton("Build Geometry"))
|
||||
{
|
||||
Nuake::QuakeMapBuilder builder;
|
||||
builder.BuildQuakeMap(entity, component.HasCollisions);
|
||||
}
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,62 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
#include <src/Scene/Components/RigidbodyComponent.h>
|
||||
#include <src/Core/FileSystem.h>
|
||||
|
||||
class RigidbodyPanel : ComponentPanel {
|
||||
|
||||
public:
|
||||
RigidbodyPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::RigidBodyComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::RigidBodyComponent>();
|
||||
BeginComponentTable(RIGIDBODY, Nuake::RigidBodyComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Mass");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##Mass", &component.Mass, 0.01f, 0.1f);
|
||||
component.Mass = std::max(component.Mass, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Mass, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Lock X axis");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##lockx", &component.LockX);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.LockX, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Lock Y axis");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##locky", &component.LockY);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.LockY, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Lock Z axis");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##lockz", &component.LockZ);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.LockZ, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,114 +0,0 @@
|
||||
#include "ScriptPanel.h"
|
||||
#include "../Windows/FileSystemUI.h"
|
||||
#include <src/Scene/Components/WrenScriptComponent.h>
|
||||
#include <src/Core/FileSystem.h>
|
||||
|
||||
void ScriptPanel::Draw(Nuake::Entity entity)
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::WrenScriptComponent>())
|
||||
return;
|
||||
|
||||
Nuake::WrenScriptComponent& component = entity.GetComponent<Nuake::WrenScriptComponent>();
|
||||
BeginComponentTable(SCRIPT, Nuake::WrenScriptComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Script");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.Script;
|
||||
ImGui::Button( path.empty() ? "Create New" : component.Script.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Script"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
|
||||
std::string fullPath = std::string(file, 512);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(std::move(fullPath));
|
||||
|
||||
component.LoadScript(path);
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
component.Script = path;
|
||||
|
||||
// Double click on file
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
|
||||
{
|
||||
if(!component.Script.empty())
|
||||
{
|
||||
if (component.mWrenScript)
|
||||
{
|
||||
Nuake::OS::OpenIn(component.mWrenScript->GetFile()->GetAbsolutePath());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Turn into command (Undo/Redo)
|
||||
|
||||
std::string pathCreation = Nuake::FileDialog::SaveFile("*.wren");
|
||||
|
||||
if (!pathCreation.empty())
|
||||
{
|
||||
if (!Nuake::String::EndsWith(pathCreation, ".wren"))
|
||||
{
|
||||
pathCreation += ".wren";
|
||||
}
|
||||
|
||||
std::string fileName = Nuake::String::ToUpper(Nuake::FileSystem::GetFileNameFromPath(pathCreation));
|
||||
fileName = Nuake::String::RemoveWhiteSpace(fileName);
|
||||
|
||||
if(!Nuake::String::IsDigit(fileName[0]))
|
||||
{
|
||||
Nuake::FileSystem::BeginWriteFile(pathCreation);
|
||||
Nuake::FileSystem::WriteLine(TEMPLATE_SCRIPT_FIRST + fileName + TEMPLATE_SCRIPT_SECOND);
|
||||
Nuake::FileSystem::EndWriteFile();
|
||||
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(pathCreation);
|
||||
Nuake::FileSystem::Scan();
|
||||
Nuake::FileSystemUI::m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
|
||||
component.LoadScript(path);
|
||||
component.Script = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
Nuake::Logger::Log("Cannot create script files that starts with a number.","fileSystem", Nuake::CRITICAL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Script, "");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Module");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Here we create a dropdown for every modules
|
||||
auto& wrenScript = component.mWrenScript;
|
||||
if (wrenScript)
|
||||
{
|
||||
auto modules = wrenScript->GetModules();
|
||||
|
||||
std::vector<const char*> modulesC;
|
||||
|
||||
for (auto& m : modules)
|
||||
{
|
||||
modulesC.push_back(m.c_str());
|
||||
}
|
||||
static int currentModule = (int)component.mModule;
|
||||
ImGui::Combo("##WrenModule", ¤tModule, &modulesC[0], modules.size());
|
||||
component.mModule = currentModule;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
//ComponentTableReset(component.Class, "");
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
|
||||
const std::string TEMPLATE_SCRIPT_FIRST = R"(import "Nuake:Engine" for Engine
|
||||
import "Nuake:ScriptableEntity" for ScriptableEntity
|
||||
import "Nuake:Input" for Input
|
||||
import "Nuake:Math" for Vector3, Math
|
||||
import "Nuake:Scene" for Scene
|
||||
|
||||
class )";
|
||||
|
||||
const std::string TEMPLATE_SCRIPT_SECOND = R"( is ScriptableEntity {
|
||||
construct new() {
|
||||
}
|
||||
|
||||
// Called when the scene gets initialized
|
||||
init() {
|
||||
// Engine.Log("Hello World!")
|
||||
}
|
||||
|
||||
// Called every update
|
||||
update(ts) {
|
||||
}
|
||||
|
||||
// Called 90 times per second
|
||||
fixedUpdate(ts) {
|
||||
}
|
||||
|
||||
// Called on shutdown
|
||||
exit() {
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
class ScriptPanel : ComponentPanel {
|
||||
|
||||
public:
|
||||
ScriptPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override;
|
||||
};
|
||||
132
Editor/src/ComponentsPanel/SkinnedMeshPanel.h
Normal file
132
Editor/src/ComponentsPanel/SkinnedMeshPanel.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#pragma once
|
||||
#include <src/Core/Core.h>
|
||||
#include "ComponentPanel.h"
|
||||
#include "ModelResourceInspector.h"
|
||||
#include "../Misc/PopupHelper.h"
|
||||
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
#include <src/Scene/Components/SkinnedModelComponent.h>
|
||||
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
#include <src/Resource/ResourceManager.h>
|
||||
|
||||
#include <src/Core/String.h>
|
||||
#include <src/Resource/ModelLoader.h>
|
||||
|
||||
class SkinnedMeshPanel : ComponentPanel
|
||||
{
|
||||
private:
|
||||
Scope<ModelResourceInspector> _modelInspector;
|
||||
bool _expanded = false;
|
||||
|
||||
std::string _importedPathMesh;
|
||||
public:
|
||||
SkinnedMeshPanel()
|
||||
{
|
||||
CreateScope<ModelResourceInspector>();
|
||||
}
|
||||
|
||||
void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
Nuake::SkinnedModelComponent* componentPtr = componentInstance.try_cast<Nuake::SkinnedModelComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Nuake::SkinnedModelComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(SKINNED MESH, SkinnedModelComponent);
|
||||
{
|
||||
ImGui::Text("Model");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string label = "None";
|
||||
|
||||
const bool isModelNone = component.ModelResource == nullptr;
|
||||
if (!isModelNone)
|
||||
{
|
||||
label = std::to_string(component.ModelResource->ID);
|
||||
}
|
||||
|
||||
if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
|
||||
{
|
||||
if (!isModelNone)
|
||||
{
|
||||
if (!_expanded)
|
||||
{
|
||||
//_modelInspector = CreateScope<ModelResourceInspector>(component.ModelResource);
|
||||
}
|
||||
|
||||
_expanded = !_expanded;
|
||||
}
|
||||
}
|
||||
|
||||
if (_expanded)
|
||||
{
|
||||
//_modelInspector->Draw();
|
||||
}
|
||||
|
||||
bool shouldConvert = false;
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Model"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
|
||||
if (Nuake::String::EndsWith(fullPath, ".mesh"))
|
||||
{
|
||||
//component.ModelPath = fullPath;
|
||||
//component.ModelResource = ResourceLoader::LoadModel(fullPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert to .Model
|
||||
Ref<Nuake::File> resourceFile = FileSystem::GetFile(fullPath);
|
||||
component.ModelPath = resourceFile;
|
||||
component.LoadModel((entt::entity)entity.GetHandle(), entity.GetScene());
|
||||
|
||||
_importedPathMesh = fullPath;
|
||||
|
||||
auto loader = ModelLoader();
|
||||
auto modelResource = loader.LoadModel(fullPath);
|
||||
shouldConvert = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
|
||||
//if (PopupHelper::DefineConfirmationDialog("##ConvertAsset", "Convert Asset"))
|
||||
//{
|
||||
// // Convert to disk
|
||||
// auto loader = ModelLoader();
|
||||
// Ref<Model> modelResource = loader.LoadModel(_importedPathMesh);
|
||||
// json serializedData = modelResource->SerializeData();
|
||||
|
||||
// const std::string exportedMeshPath = _importedPathMesh + ".mesh";
|
||||
// FileSystem::BeginWriteFile(exportedMeshPath);
|
||||
// FileSystem::WriteLine(serializedData.dump());
|
||||
// FileSystem::EndWriteFile();
|
||||
|
||||
// ResourceManager::RegisterResource(modelResource);
|
||||
|
||||
// // Update component
|
||||
// component.ModelPath = exportedMeshPath;
|
||||
// component.ModelResource = modelResource;
|
||||
//}
|
||||
|
||||
//if (shouldConvert)
|
||||
//{
|
||||
// PopupHelper::OpenPopup("##ConvertAsset");
|
||||
//}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
//ComponentTableReset(component.ModelPath, "");
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,172 +0,0 @@
|
||||
#pragma once
|
||||
#include <src/Core/Core.h>
|
||||
#include "ComponentPanel.h"
|
||||
#include "ModelResourceInspector.h"
|
||||
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
#include <src/Scene/Components/SkinnedModelComponent.h>
|
||||
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
#include <src/Core/String.h>
|
||||
|
||||
class SkinnedModelPanel : ComponentPanel
|
||||
{
|
||||
private:
|
||||
Scope<ModelResourceInspector> m_ModelInspector;
|
||||
bool m_Expanded = false;
|
||||
std::string m_QueuedModelPath;
|
||||
|
||||
public:
|
||||
SkinnedModelPanel()
|
||||
{
|
||||
CreateScope<ModelResourceInspector>();
|
||||
}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
using namespace Nuake;
|
||||
if (!entity.HasComponent<SkinnedModelComponent>())
|
||||
return;
|
||||
|
||||
SkinnedModelComponent& component = entity.GetComponent<SkinnedModelComponent>();
|
||||
BeginComponentTable(SKINNED MESH, SkinnedModelComponent);
|
||||
{
|
||||
ImGui::Text("Model");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string label = "None";
|
||||
|
||||
const bool isModelNone = component.ModelResource == nullptr;
|
||||
if (!isModelNone)
|
||||
{
|
||||
label = std::to_string(component.ModelResource->ID);
|
||||
}
|
||||
|
||||
if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
|
||||
{
|
||||
}
|
||||
|
||||
if (m_Expanded)
|
||||
{
|
||||
m_ModelInspector->Draw();
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Model"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
|
||||
if (Nuake::String::EndsWith(fullPath, ".model"))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_QueuedModelPath = fullPath;
|
||||
ImGui::OpenPopup("Create Skeleton");
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal("Create Skeleton", NULL, ImGuiWindowFlags_AlwaysAutoResize))
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
ImGui::Text("Would you like to create the skeleton structure in the scene tree?");
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("OK", ImVec2(120, 0)))
|
||||
{
|
||||
component.ModelPath = m_QueuedModelPath;
|
||||
component.LoadModel();
|
||||
|
||||
Scene* scene = entity.GetScene();
|
||||
scene->CreateSkeleton(entity);
|
||||
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SetItemDefaultFocus();
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel", ImVec2(120, 0)))
|
||||
{
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.ModelPath, "");
|
||||
|
||||
if (component.ModelResource)
|
||||
{
|
||||
auto& model = component.ModelResource;
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
{
|
||||
ImGui::Text("Playing");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##playing", &model->IsPlaying);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(model->IsPlaying, true);
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
|
||||
if(model->GetCurrentAnimation())
|
||||
{
|
||||
ImGui::Text("Animation");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
uint32_t animIndex = model->GetCurrentAnimationIndex();
|
||||
uint32_t oldAnimIndex = animIndex;
|
||||
auto animations = model->GetAnimations();
|
||||
if (ImGui::BeginCombo("Type", model->GetCurrentAnimation()->GetName().c_str()))
|
||||
{
|
||||
for (int n = 0; n < model->GetAnimationsCount(); n++)
|
||||
{
|
||||
bool is_selected = (animIndex == n);
|
||||
std::string animName = animations[n]->GetName();
|
||||
|
||||
if (animName.empty())
|
||||
{
|
||||
animName = "Empty";
|
||||
}
|
||||
|
||||
if (ImGui::Selectable(animName.c_str(), is_selected))
|
||||
{
|
||||
animIndex = n;
|
||||
}
|
||||
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (animIndex != oldAnimIndex)
|
||||
{
|
||||
model->PlayAnimation(animIndex);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
|
||||
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetAnimId";
|
||||
if (ImGui::Button(resetLabel.c_str()))
|
||||
{
|
||||
model->PlayAnimation(0);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
#include <src/Scene/Components/SphereCollider.h>
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
class SphereColliderPanel : ComponentPanel {
|
||||
public:
|
||||
SphereColliderPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::SphereColliderComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::SphereColliderComponent>();
|
||||
BeginComponentTable(SPHERE COLLIDER, Nuake::SphereColliderComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Size");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f);
|
||||
|
||||
component.Radius = std::max(component.Radius, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Radius, 0.5f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Is Trigger");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##isTrigger", &component.IsTrigger);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.IsTrigger, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/SpriteComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
|
||||
class SpritePanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
SpritePanel() = default;
|
||||
~SpritePanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::SpriteComponent>())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::SpriteComponent>();
|
||||
BeginComponentTable(SPRITE, Nuake::SpriteComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Sprite");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.SpritePath;
|
||||
ImGui::Button(path.empty() ? "Drag image" : component.SpritePath.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Image"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
|
||||
std::string fullPath = std::string(file, 512);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(std::move(fullPath));
|
||||
component.SpritePath = path;
|
||||
|
||||
component.LoadSprite();
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.LockYRotation, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Billboard");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##billboard", &component.Billboard);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Billboard, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Lock Y rotation");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##lockYRotation", &component.LockYRotation);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.LockYRotation, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Position Based");
|
||||
if (ImGui::BeginItemTooltip())
|
||||
{
|
||||
ImGui::Text("Orientation is based on the position of the camera or the orientation of the camera.");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##positionbased", &component.PositionFacing);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.LockYRotation, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -27,14 +27,14 @@ public:
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
Vector3 position = component.GetLocalPosition();
|
||||
ImGuiHelper::DrawVec3("Translation", &position);
|
||||
ImGuiHelper::DrawVec3("Translation##" + std::to_string(entity.GetHandle()), &position);
|
||||
if (position != component.GetLocalPosition())
|
||||
component.SetLocalPosition(position);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
|
||||
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetTranslation";
|
||||
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetTranslation" + std::to_string(entity.GetHandle());
|
||||
if (ImGui::Button(resetLabel.c_str()))
|
||||
component.SetLocalPosition(Vector3(0, 0, 0));
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
Vector3 eulerDegreesOld = glm::degrees(glm::eulerAngles(currentRotation));
|
||||
|
||||
// Draw the ImGui widget for rotation
|
||||
ImGuiHelper::DrawVec3("Rotation", &eulerDegreesOld);
|
||||
ImGuiHelper::DrawVec3("Rotation##" + std::to_string(entity.GetHandle()), &eulerDegreesOld);
|
||||
|
||||
// Calculate the delta in Euler angles
|
||||
Vector3 eulerDelta = eulerDegreesOld - glm::degrees(glm::eulerAngles(currentRotation));
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
|
||||
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetRotation";
|
||||
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetRotation" + std::to_string(entity.GetHandle());
|
||||
if (ImGui::Button(resetLabel.c_str()))
|
||||
{
|
||||
component.SetLocalRotation(Quat(1, 0, 0, 0));
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
Vector3 localScale = component.GetLocalScale();
|
||||
ImGuiHelper::DrawVec3("Scale", &localScale);
|
||||
ImGuiHelper::DrawVec3("Scale##" + std::to_string(entity.GetHandle()), &localScale);
|
||||
|
||||
if (localScale != component.GetLocalScale())
|
||||
component.SetLocalScale(localScale);
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
|
||||
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetScale";
|
||||
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetScale" + std::to_string(entity.GetHandle());
|
||||
if (ImGui::Button(resetLabel.c_str()))
|
||||
component.SetLocalScale(Vector3(1, 1, 1));
|
||||
|
||||
|
||||
@@ -7,11 +7,15 @@
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include "src/UI/NuakeUI.h"
|
||||
#include "src/UI/UIInputManager.h"
|
||||
|
||||
|
||||
|
||||
void EditorApplication::OnInit()
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
|
||||
Engine::Init();
|
||||
m_Window = Engine::GetCurrentWindow();
|
||||
m_Window->SetSize({ m_Specification.WindowWidth, m_Specification.WindowHeight });
|
||||
@@ -45,6 +49,39 @@ void EditorApplication::OnInit()
|
||||
}
|
||||
}
|
||||
|
||||
m_Window->SetOnWindowFocusedCallback([&](Window& window, bool focused)
|
||||
{
|
||||
if (!focused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& layer : m_LayerStack)
|
||||
{
|
||||
layer->OnWindowFocused();
|
||||
}
|
||||
});
|
||||
|
||||
m_Window->SetOnWindowClosedCallback([](Window& window)
|
||||
{
|
||||
if (Engine::GetProject())
|
||||
{
|
||||
Engine::GetProject()->Save();
|
||||
}
|
||||
|
||||
if (Engine::GetCurrentScene())
|
||||
{
|
||||
Engine::GetCurrentScene()->Save();
|
||||
}
|
||||
});
|
||||
|
||||
m_Window->SetOnDragNDropCallback([&](Window& window, const std::vector<std::string>& paths) {
|
||||
for (auto& layer : m_LayerStack)
|
||||
{
|
||||
layer->OnDragNDrop(paths);
|
||||
}
|
||||
});
|
||||
|
||||
PushLayer(CreateScope<EditorLayer>());
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,15 @@
|
||||
|
||||
using namespace NuakeEditor;
|
||||
|
||||
class DragNDropModule : public Nuake::IApplicationModule
|
||||
{
|
||||
public:
|
||||
void OnInit() override
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class EditorApplication : public Nuake::Application
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -53,14 +53,18 @@ void EditorLayer::OnUpdate()
|
||||
m_GizmoDrawer->DrawNavMesh(currentScene, true);
|
||||
}
|
||||
|
||||
if (m_EditorInterface->ShouldDrawCollision())
|
||||
if (m_EditorInterface->ShouldDrawGizmos())
|
||||
{
|
||||
m_GizmoDrawer->DrawGizmos(currentScene, false);
|
||||
}
|
||||
|
||||
|
||||
if (m_EditorInterface->ShouldDrawShapes())
|
||||
{
|
||||
m_GizmoDrawer->DrawShapes(currentScene, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sceneFramebuffer->Unbind();
|
||||
}
|
||||
|
||||
@@ -75,4 +79,14 @@ void EditorLayer::OnUpdate()
|
||||
void EditorLayer::OnDetach()
|
||||
{
|
||||
delete m_EditorInterface;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorLayer::OnWindowFocused()
|
||||
{
|
||||
m_EditorInterface->OnWindowFocused();
|
||||
}
|
||||
|
||||
void EditorLayer::OnDragNDrop(const std::vector<std::string>& paths)
|
||||
{
|
||||
m_EditorInterface->OnDragNDrop(paths);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ public:
|
||||
virtual void OnUpdate() override;
|
||||
virtual void OnDetach() override;
|
||||
|
||||
virtual void OnWindowFocused() override;
|
||||
virtual void OnDragNDrop(const std::vector<std::string>& paths) override;
|
||||
|
||||
private:
|
||||
CommandBuffer mCommandBuffer;
|
||||
Nuake::EditorInterface* m_EditorInterface;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <src/Scene/Components/SphereCollider.h>
|
||||
#include <src/Scene/Components/CharacterControllerComponent.h>
|
||||
#include <src/Scene/Components/BoxCollider.h>
|
||||
#include "src/Scene/Components/RigidbodyComponent.h"
|
||||
|
||||
#include <src/Resource/ModelLoader.h>
|
||||
#include <src/Rendering/RenderList.h>
|
||||
@@ -22,7 +23,9 @@
|
||||
#include <src/Scene/Components/ParticleEmitterComponent.h>
|
||||
#include <src/Scene/Components/BoneComponent.h>
|
||||
#include <src/Scene/Components/AudioEmitterComponent.h>
|
||||
#include <src/Scene/Components/ParentComponent.h>
|
||||
#include <DetourDebugDraw.h>
|
||||
#include <src/Scene/Components/BSPBrushComponent.h>
|
||||
|
||||
|
||||
GizmoDrawer::GizmoDrawer(EditorInterface* editor)
|
||||
@@ -141,6 +144,11 @@ bool GizmoDrawer::IsEntityInSelection(Nuake::Entity entity)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_Editor->Selection.Entity.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using namespace Nuake;
|
||||
const Nuake::Entity selectedEntity = m_Editor->Selection.Entity;
|
||||
|
||||
@@ -182,10 +190,10 @@ void GizmoDrawer::DrawAxis(Ref<Scene> scene, bool occluded)
|
||||
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
|
||||
{
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform1f("u_Opacity", occluded ? 0.1f : 0.5f);
|
||||
m_LineShader->SetUniformVec4("u_Color", {0.0f, 0.0f, 0.0f, 0.0f});
|
||||
m_LineShader->SetUniform("u_View", scene->m_EditorCamera->GetTransform());
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform("u_Opacity", occluded ? 0.1f : 0.5f);
|
||||
m_LineShader->SetUniform("u_Color", {0.0f, 0.0f, 0.0f, 0.0f});
|
||||
m_AxisLineBuffer->Bind();
|
||||
glLineWidth(1.0f);
|
||||
Nuake::RenderCommand::DrawLines(0, 6);
|
||||
@@ -211,29 +219,11 @@ void GizmoDrawer::DrawNavMesh(Ref<Scene> scene, bool occluded)
|
||||
}
|
||||
}
|
||||
|
||||
void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
void GizmoDrawer::DrawShapes(Ref<Scene> scene, bool occluded)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
|
||||
|
||||
glLineWidth(3.0f);
|
||||
auto boxColliderView = scene->m_Registry.view<TransformComponent, BoxColliderComponent>();
|
||||
for (auto e : boxColliderView)
|
||||
{
|
||||
auto [transform, box] = scene->m_Registry.get<TransformComponent, BoxColliderComponent>(e);
|
||||
|
||||
const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation());
|
||||
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
|
||||
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform1f("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, box.Size));
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_BoxBuffer->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 26);
|
||||
}
|
||||
glLineWidth(2.0f);
|
||||
|
||||
auto navMeshVolumeView = scene->m_Registry.view<TransformComponent, NavMeshVolumeComponent>();
|
||||
for (auto e : navMeshVolumeView)
|
||||
@@ -249,9 +239,26 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
|
||||
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform1f("u_Opacity", 0.9f);
|
||||
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, volume.VolumeSize));
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform("u_Opacity", 0.9f);
|
||||
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, volume.VolumeSize));
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_BoxBuffer->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 26);
|
||||
}
|
||||
|
||||
auto boxColliderView = scene->m_Registry.view<TransformComponent, BoxColliderComponent>();
|
||||
for (auto e : boxColliderView)
|
||||
{
|
||||
auto [transform, box] = scene->m_Registry.get<TransformComponent, BoxColliderComponent>(e);
|
||||
|
||||
const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation());
|
||||
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
|
||||
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, box.Size));
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_BoxBuffer->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 26);
|
||||
@@ -262,9 +269,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
{
|
||||
auto [transform, sphere] = scene->m_Registry.get<TransformComponent, SphereColliderComponent>(e);
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform1f("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(sphere.Radius)));
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(sphere.Radius)));
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_CircleBuffer->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 128);
|
||||
@@ -283,14 +290,14 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
|
||||
Vector3 globalPosition = Vector3(transform.GetGlobalTransform()[3]);
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform1f("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MaxDistance)));
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MaxDistance)));
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_CircleBuffer->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 128);
|
||||
|
||||
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MinDistance)));
|
||||
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MinDistance)));
|
||||
Nuake::RenderCommand::DrawLines(0, 128);
|
||||
}
|
||||
|
||||
@@ -311,9 +318,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
|
||||
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform1f("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_CapsuleGizmo[entityId]->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 264);
|
||||
@@ -336,9 +343,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
|
||||
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform1f("u_Opacity", 1.0f);
|
||||
m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform("u_Opacity", 1.0f);
|
||||
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_CylinderGizmo[entityId]->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 264);
|
||||
@@ -369,23 +376,52 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
gizmoPosition = glm::translate(gizmoPosition, { 0, -cylinderLength / 2.0, 0 });
|
||||
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform1f("u_Opacity", 1.0f);
|
||||
m_LineShader->SetUniformMat4f("u_View", gizmoPosition);
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform("u_Opacity", 1.0f);
|
||||
m_LineShader->SetUniform("u_View", gizmoPosition);
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_CylinderGizmo[entityId]->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 264);
|
||||
}
|
||||
}
|
||||
|
||||
auto bspView = scene->m_Registry.view<TransformComponent, BSPBrushComponent>();
|
||||
for (auto e : bspView)
|
||||
{
|
||||
auto [transform, brush] = scene->m_Registry.get<TransformComponent, BSPBrushComponent>(e);
|
||||
|
||||
if (brush.target.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto bspView2 = scene->m_Registry.view<TransformComponent, BSPBrushComponent>();
|
||||
for (auto e2 : bspView2)
|
||||
{
|
||||
auto [transform2, brush2] = scene->m_Registry.get<TransformComponent, BSPBrushComponent>(e2);
|
||||
if (brush2.TargetName.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (brush.target == brush2.TargetName)
|
||||
{
|
||||
Vector3 from = transform.GetGlobalTransform()[3];
|
||||
Vector3 to = transform2.GetGlobalTransform()[3];
|
||||
|
||||
scene->m_SceneRenderer->DrawDebugLine(from, to, Color(1, 0, 0, 1), 0.f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto particleView = scene->m_Registry.view<TransformComponent, ParticleEmitterComponent>();
|
||||
for (auto e : particleView)
|
||||
{
|
||||
auto [transform, particle] = scene->m_Registry.get<TransformComponent, ParticleEmitterComponent>(e);
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform1f("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(particle.Radius)));
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform("u_Opacity", 1.f);
|
||||
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(particle.Radius)));
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_CircleBuffer->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 128);
|
||||
@@ -414,8 +450,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
|
||||
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
|
||||
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
meshes[mesh.SubMesh]->Bind();
|
||||
@@ -423,11 +459,42 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
auto camView = scene->m_Registry.view<TransformComponent, CameraComponent>();
|
||||
for (auto e : camView)
|
||||
{
|
||||
auto [transform, camera] = scene->m_Registry.get<TransformComponent, CameraComponent>(e);
|
||||
const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation());
|
||||
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
|
||||
|
||||
m_LineShader->Bind();
|
||||
m_LineShader->SetUniform("u_Opacity", 1.f);
|
||||
const float aspectRatio = camera.CameraInstance->AspectRatio;
|
||||
const float fov = camera.CameraInstance->Fov;
|
||||
Matrix4 clampedPerspective = glm::perspectiveFov(glm::radians(fov), 9.0f * aspectRatio, 9.0f, 0.05f, 3.0f);
|
||||
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix * glm::inverse(clampedPerspective));
|
||||
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
m_BoxBuffer->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 26);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
auto camView = scene->m_Registry.view<TransformComponent, CameraComponent>();
|
||||
|
||||
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
|
||||
|
||||
glLineWidth(3.0f);
|
||||
|
||||
auto flatShader = ShaderManager::GetShader("Resources/Shaders/flat.shader");
|
||||
flatShader->Bind();
|
||||
flatShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
|
||||
flatShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
flatShader->SetUniform4f("u_Color", 0.5f, 0.5f, 0.5f, 1.0f);
|
||||
flatShader->SetUniform("u_View", scene->m_EditorCamera->GetTransform());
|
||||
flatShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
flatShader->SetUniform("u_Color", 0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
|
||||
RenderCommand::Enable(RendererEnum::FACE_CULL);
|
||||
@@ -438,9 +505,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
|
||||
auto gizmoShader = ShaderManager::GetShader("Resources/Shaders/gizmo.shader");
|
||||
gizmoShader->Bind();
|
||||
gizmoShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
|
||||
gizmoShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
gizmoShader->SetUniform1f("u_Opacity", occluded ? 0.1f : 1.f);
|
||||
gizmoShader->SetUniform("u_View", scene->m_EditorCamera->GetTransform());
|
||||
gizmoShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
gizmoShader->SetUniform("u_Opacity", occluded ? 0.1f : 1.f);
|
||||
RenderCommand::Disable(RendererEnum::FACE_CULL);
|
||||
|
||||
const Vector3& cameraPosition = scene->m_EditorCamera->GetTranslation();
|
||||
@@ -448,11 +515,10 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
const Vector3 gizmoSize = Vector3(Engine::GetProject()->Settings.GizmoSize);
|
||||
|
||||
// Camera
|
||||
auto camView = scene->m_Registry.view<TransformComponent, CameraComponent>();
|
||||
for (auto e : camView)
|
||||
{
|
||||
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/camera.png").get());
|
||||
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/camera.png").get());
|
||||
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
auto [transform, camera] = scene->m_Registry.get<TransformComponent, CameraComponent>(e);
|
||||
|
||||
auto initialTransform = transform.GetGlobalTransform();
|
||||
@@ -470,6 +536,7 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
}
|
||||
|
||||
// Lights
|
||||
auto lightView = scene->m_Registry.view<TransformComponent, LightComponent>();
|
||||
for (auto e : lightView)
|
||||
{
|
||||
auto [transform, light] = scene->m_Registry.get<TransformComponent, LightComponent>(e);
|
||||
@@ -491,8 +558,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
texturePath = "Resources/Gizmos/light.png";
|
||||
}
|
||||
|
||||
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture(texturePath).get());
|
||||
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture(texturePath).get());
|
||||
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
|
||||
auto initialTransform = transform.GetGlobalTransform();
|
||||
Matrix4 particleTransform = initialTransform;
|
||||
@@ -512,8 +579,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
auto characterControllerView = scene->m_Registry.view<TransformComponent, CharacterControllerComponent>();
|
||||
for (auto e : characterControllerView)
|
||||
{
|
||||
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/player.png").get());
|
||||
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/player.png").get());
|
||||
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
auto [transform, characterControllerComponent] = scene->m_Registry.get<TransformComponent, CharacterControllerComponent>(e);
|
||||
|
||||
auto initialTransform = transform.GetGlobalTransform();
|
||||
@@ -535,8 +602,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
auto boneView = scene->m_Registry.view<TransformComponent, BoneComponent>();
|
||||
for (auto e : boneView)
|
||||
{
|
||||
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/bone.png").get());
|
||||
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/bone.png").get());
|
||||
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
auto [transform, boneComponent] = scene->m_Registry.get<TransformComponent, BoneComponent>(e);
|
||||
|
||||
auto initialTransform = transform.GetGlobalTransform();
|
||||
@@ -557,8 +624,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
auto audioView = scene->m_Registry.view<TransformComponent, AudioEmitterComponent>();
|
||||
for (auto e : audioView)
|
||||
{
|
||||
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/sound_emitter.png").get());
|
||||
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/sound_emitter.png").get());
|
||||
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
auto [transformComponent, audioEmitterComponent] = scene->m_Registry.get<TransformComponent, AudioEmitterComponent>(e);
|
||||
|
||||
auto initialTransform = transformComponent.GetGlobalTransform();
|
||||
@@ -578,8 +645,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
auto rigidbodyView = scene->m_Registry.view<TransformComponent, RigidBodyComponent>();
|
||||
for (auto e : rigidbodyView)
|
||||
{
|
||||
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/rigidbody.png").get());
|
||||
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/rigidbody.png").get());
|
||||
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
auto [transformComponent, rigidbodyComponent] = scene->m_Registry.get<TransformComponent, RigidBodyComponent>(e);
|
||||
|
||||
auto initialTransform = transformComponent.GetGlobalTransform();
|
||||
@@ -599,8 +666,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
|
||||
auto particleEmitterView = scene->m_Registry.view<TransformComponent, ParticleEmitterComponent>();
|
||||
for (auto e : particleEmitterView)
|
||||
{
|
||||
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/particles.png").get());
|
||||
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/particles.png").get());
|
||||
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
|
||||
auto [transformComponent, particleEmitter] = scene->m_Registry.get<TransformComponent, ParticleEmitterComponent>(e);
|
||||
|
||||
auto initialTransform = transformComponent.GetGlobalTransform();
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
GizmoDrawer() = default;
|
||||
~GizmoDrawer() = default;
|
||||
|
||||
void DrawShapes(Ref<Scene> scene, bool occluded);
|
||||
void DrawGizmos(Ref<Scene> scene, bool occluded);
|
||||
void DrawAxis(Ref<Scene> scene, bool occluded);
|
||||
void DrawNavMesh(Ref<Scene> scene, bool occluded);
|
||||
|
||||
@@ -6,7 +6,7 @@ void ImGuiTextSTD(const std::string& label, std::string& value)
|
||||
{
|
||||
char buffer[256];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
std::strncpy(buffer, value.c_str(), sizeof(buffer));
|
||||
strncpy_s(buffer, value.c_str(), sizeof(buffer));
|
||||
if (ImGui::InputText(label.c_str(), buffer, sizeof(buffer)))
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ void ImGuiTextMultiline(const std::string& label, std::string& value)
|
||||
{
|
||||
char buffer[256];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
std::strncpy(buffer, value.c_str(), sizeof(buffer));
|
||||
strncpy_s(buffer, value.c_str(), sizeof(buffer));
|
||||
if (ImGui::InputTextMultiline(label.c_str(), buffer, sizeof(buffer)))
|
||||
{
|
||||
value = std::string(buffer);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
void PopupHelper::OpenPopup(const std::string& id)
|
||||
{
|
||||
ImGui::TextWrapped(id.c_str());
|
||||
|
||||
ImGui::OpenPopup(id.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
#include "ThumbnailManager.h"
|
||||
|
||||
#include <src/Vendors/glm/ext/matrix_clip_space.hpp>
|
||||
#include <src/FileSystem/FileTypes.h>
|
||||
#include <src/FileSystem/File.h>
|
||||
|
||||
#include <src/Scene/Components/CameraComponent.h>
|
||||
#include <src/Scene/Components/ModelComponent.h>
|
||||
|
||||
#include <src/Rendering/SceneRenderer.h>
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include <src/Resource/Prefab.h>
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
|
||||
#include <src/Vendors/glm/ext/matrix_clip_space.hpp>
|
||||
#include <glad/glad.h>
|
||||
#include <Tracy.hpp>
|
||||
|
||||
|
||||
ThumbnailManager::ThumbnailManager()
|
||||
@@ -39,6 +48,8 @@ bool ThumbnailManager::IsThumbnailLoaded(const std::string& path) const
|
||||
|
||||
Ref<Nuake::Texture> ThumbnailManager::GetThumbnail(const std::string& path)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
if (IsThumbnailLoaded(path))
|
||||
{
|
||||
return m_Thumbnails[path];
|
||||
@@ -71,6 +82,9 @@ void ThumbnailManager::MarkThumbnailAsDirty(const std::string & path)
|
||||
|
||||
Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path, Ref<Nuake::Texture> texture)
|
||||
{
|
||||
ZoneScopedN("GenerateThumbnail");
|
||||
ZoneText(path.c_str(), path.size());
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
const Matrix4 ortho = glm::orthoLH(-0.6f, 0.6f, -0.6f, 0.6f, -100.0f, 100.0f);
|
||||
@@ -80,26 +94,26 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
|
||||
auto file = FileSystem::GetFile(path);
|
||||
if (file->GetFileType() == FileType::Prefab)
|
||||
{
|
||||
Ref<Scene> scene = Scene::New();
|
||||
auto cam = scene->CreateEntity("Camera");
|
||||
TransformComponent& camTransform = cam.GetComponent<TransformComponent>();
|
||||
camTransform.SetLocalPosition({ 0.0f, 0.0f, 2.0f });
|
||||
|
||||
auto& previewLight = scene->CreateEntity("_directionalLight").AddComponent<LightComponent>();
|
||||
previewLight.SetCastShadows(false);
|
||||
previewLight.Type = LightType::Directional;
|
||||
|
||||
scene->GetEnvironment()->CurrentSkyType = SkyType::ProceduralSky;
|
||||
scene->GetEnvironment()->ProceduralSkybox->SunDirection = { 0.58f, 0.34f, -0.74f };
|
||||
auto& camComponent = cam.AddComponent<CameraComponent>();
|
||||
camComponent.CameraInstance->Fov = 45.0f;
|
||||
camComponent.CameraInstance->AspectRatio = 1.0f;
|
||||
m_ShadedFramebuffer->SetTexture(texture);
|
||||
|
||||
Ref<Prefab> prefab = Prefab::InstanceInScene(path, scene);
|
||||
|
||||
scene->Update(0.01f);
|
||||
scene->Draw(*m_ShadedFramebuffer.get());
|
||||
//Ref<Scene> scene = Scene::New();
|
||||
//auto cam = scene->CreateEntity("Camera");
|
||||
//TransformComponent& camTransform = cam.GetComponent<TransformComponent>();
|
||||
//camTransform.SetLocalPosition({ 0.0f, 0.0f, 2.0f });
|
||||
//
|
||||
//auto& previewLight = scene->CreateEntity("_directionalLight").AddComponent<LightComponent>();
|
||||
//previewLight.SetCastShadows(false);
|
||||
//previewLight.Type = LightType::Directional;
|
||||
//
|
||||
//scene->GetEnvironment()->CurrentSkyType = SkyType::ProceduralSky;
|
||||
//scene->GetEnvironment()->ProceduralSkybox->SunDirection = { 0.58f, 0.34f, -0.74f };
|
||||
//auto& camComponent = cam.AddComponent<CameraComponent>();
|
||||
//camComponent.CameraInstance->Fov = 45.0f;
|
||||
//camComponent.CameraInstance->AspectRatio = 1.0f;
|
||||
//m_ShadedFramebuffer->SetTexture(texture);
|
||||
//
|
||||
//Ref<Prefab> prefab = Prefab::InstanceInScene(path, scene.get());
|
||||
//
|
||||
//scene->Update(0.01f);
|
||||
//scene->Draw(*m_ShadedFramebuffer.get());
|
||||
|
||||
// Gbuffer pass
|
||||
//m_Framebuffer->Bind();
|
||||
@@ -113,9 +127,9 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
|
||||
// shader->Bind();
|
||||
//
|
||||
// auto cam = Engine::GetCurrentScene()->GetCurrentCamera();
|
||||
// shader->SetUniformMat4f("u_View", view);
|
||||
// shader->SetUniformMat4f("u_Projection", ortho);
|
||||
// shader->SetUniformMat4f("u_Model", Matrix4(1.0f));
|
||||
// shader->SetUniform("u_View", view);
|
||||
// shader->SetUniform("u_Projection", ortho);
|
||||
// shader->SetUniform("u_Model", Matrix4(1.0f));
|
||||
// Renderer::SphereMesh->Draw(shader, true);
|
||||
//}
|
||||
//m_Framebuffer->Unbind();
|
||||
@@ -129,15 +143,15 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
|
||||
// RenderCommand::Disable(RendererEnum::FACE_CULL);
|
||||
// auto shader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
|
||||
// shader->Bind();
|
||||
// shader->SetUniformVec3("u_EyePosition", Vector3(1, 0, 0));
|
||||
// shader->SetUniform1i("LightCount", 0);
|
||||
// shader->SetUniform("u_EyePosition", Vector3(1, 0, 0));
|
||||
// shader->SetUniform("LightCount", 0);
|
||||
// auto dir = Engine::GetCurrentScene()->GetEnvironment()->ProceduralSkybox->GetSunDirection();
|
||||
// shader->SetUniform3f("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
|
||||
// shader->SetUniform3f("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
|
||||
// shader->SetUniform1i("u_DirectionalLight.Shadow", 0);
|
||||
// shader->SetUniform1i("u_DisableSSAO", 1);
|
||||
// shader->SetUniformMat4f("u_View", view);
|
||||
// shader->SetUniformMat4f("u_Projection", ortho);
|
||||
// shader->SetUniform("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
|
||||
// shader->SetUniform("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
|
||||
// shader->SetUniform("u_DirectionalLight.Shadow", 0);
|
||||
// shader->SetUniform("u_DisableSSAO", 1);
|
||||
// shader->SetUniform("u_View", view);
|
||||
// shader->SetUniform("u_Projection", ortho);
|
||||
//
|
||||
// m_Framebuffer->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(5);
|
||||
// m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->Bind(6);
|
||||
@@ -145,11 +159,11 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
|
||||
// m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT2)->Bind(8);
|
||||
// m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT4)->Bind(10);
|
||||
//
|
||||
// shader->SetUniform1i("m_Depth", 5);
|
||||
// shader->SetUniform1i("m_Albedo", 6);
|
||||
// shader->SetUniform1i("m_Normal", 7);
|
||||
// shader->SetUniform1i("m_Material", 8);
|
||||
// shader->SetUniform1i("m_Emissive", 10);
|
||||
// shader->SetUniform("m_Depth", 5);
|
||||
// shader->SetUniform("m_Albedo", 6);
|
||||
// shader->SetUniform("m_Normal", 7);
|
||||
// shader->SetUniform("m_Material", 8);
|
||||
// shader->SetUniform("m_Emissive", 10);
|
||||
//
|
||||
// Renderer::DrawQuad(Matrix4());
|
||||
//}
|
||||
@@ -178,12 +192,8 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
|
||||
|
||||
m_ShadedFramebuffer->SetTexture(texture);
|
||||
|
||||
ModelComponent& modelComp = scene->CreateEntity("Mesh").AddComponent<ModelComponent>();
|
||||
modelComp.ModelResource = ResourceLoader::LoadModel(file->GetRelativePath());
|
||||
|
||||
AABB aabb = modelComp.ModelResource->GetMeshes()[0]->GetAABB();
|
||||
Vector3 middlePoint = aabb.Max / 2.0f;
|
||||
|
||||
//ModelComponent& modelComp = scene->CreateEntity("Mesh").AddComponent<ModelComponent>();
|
||||
//modelComp.ModelResource = ResourceLoader::LoadModel(file->GetRelativePath());
|
||||
scene->Update(0.01f);
|
||||
scene->Draw(*m_ShadedFramebuffer.get());
|
||||
}
|
||||
@@ -201,9 +211,9 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
|
||||
shader->Bind();
|
||||
|
||||
auto cam = Engine::GetCurrentScene()->GetCurrentCamera();
|
||||
shader->SetUniformMat4f("u_View", view);
|
||||
shader->SetUniformMat4f("u_Projection", ortho);
|
||||
shader->SetUniformMat4f("u_Model", Matrix4(1.0f));
|
||||
shader->SetUniform("u_View", view);
|
||||
shader->SetUniform("u_Projection", ortho);
|
||||
shader->SetUniform("u_Model", Matrix4(1.0f));
|
||||
Ref<Material> material = ResourceLoader::LoadMaterial(path);
|
||||
material->Bind(shader);
|
||||
Renderer::SphereMesh->Draw(shader, false);
|
||||
@@ -219,15 +229,15 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
|
||||
RenderCommand::Disable(RendererEnum::FACE_CULL);
|
||||
auto shader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
|
||||
shader->Bind();
|
||||
shader->SetUniformVec3("u_EyePosition", Vector3(1, 0, 0));
|
||||
shader->SetUniform1i("LightCount", 0);
|
||||
shader->SetUniform("u_EyePosition", Vector3(1, 0, 0));
|
||||
shader->SetUniform("LightCount", 0);
|
||||
auto dir = Engine::GetCurrentScene()->GetEnvironment()->ProceduralSkybox->GetSunDirection();
|
||||
shader->SetUniform3f("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
|
||||
shader->SetUniform3f("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
|
||||
shader->SetUniform1i("u_DirectionalLight.Shadow", 0);
|
||||
shader->SetUniform1i("u_DisableSSAO", 1);
|
||||
shader->SetUniformMat4f("u_View", view);
|
||||
shader->SetUniformMat4f("u_Projection", ortho);
|
||||
shader->SetUniform("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
|
||||
shader->SetUniform("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
|
||||
shader->SetUniform("u_DirectionalLight.Shadow", 0);
|
||||
shader->SetUniform("u_DisableSSAO", 1);
|
||||
shader->SetUniform("u_View", view);
|
||||
shader->SetUniform("u_Projection", ortho);
|
||||
|
||||
m_Framebuffer->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(5);
|
||||
m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->Bind(6);
|
||||
@@ -235,11 +245,11 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
|
||||
m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT2)->Bind(8);
|
||||
m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT4)->Bind(10);
|
||||
|
||||
shader->SetUniform1i("m_Depth", 5);
|
||||
shader->SetUniform1i("m_Albedo", 6);
|
||||
shader->SetUniform1i("m_Normal", 7);
|
||||
shader->SetUniform1i("m_Material", 8);
|
||||
shader->SetUniform1i("m_Emissive", 10);
|
||||
shader->SetUniform("m_Depth", 5);
|
||||
shader->SetUniform("m_Albedo", 6);
|
||||
shader->SetUniform("m_Normal", 7);
|
||||
shader->SetUniform("m_Material", 8);
|
||||
shader->SetUniform("m_Emissive", 10);
|
||||
|
||||
Renderer::DrawQuad(Matrix4());
|
||||
}
|
||||
|
||||
@@ -5,22 +5,22 @@
|
||||
|
||||
void ScriptingContext::Initialize()
|
||||
{
|
||||
m_Modules =
|
||||
modules =
|
||||
{
|
||||
CreateRef<EditorNetAPI>()
|
||||
};
|
||||
|
||||
for (auto& m : m_Modules)
|
||||
for (auto& m : modules)
|
||||
{
|
||||
m->RegisterMethods();
|
||||
}
|
||||
|
||||
// Load Nuake assembly DLL
|
||||
/*auto m_LoadContext2 = Nuake::ScriptingEngineNet::Get().GetHostInstance()->CreateAssemblyLoadContext("NuakeEditorContext");
|
||||
m_NuakeAssembly = Nuake::ScriptingEngineNet::Get().ReloadEngineAPI(m_LoadContext2);
|
||||
m_EditorAssembly = m_LoadContext2.LoadAssembly("EditorNet.dll");
|
||||
/*auto loadContext2 = Nuake::ScriptingEngineNet::Get().GetHostInstance()->CreateAssemblyLoadContext("NuakeEditorContext");
|
||||
nuakeAssembly = Nuake::ScriptingEngineNet::Get().ReloadEngineAPI(loadContext2);
|
||||
m_EditorAssembly = loadContext2.LoadAssembly("EditorNet.dll");
|
||||
|
||||
for (const auto& netModule : m_Modules)
|
||||
for (const auto& netModule : modules)
|
||||
{
|
||||
for (const auto& [methodName, methodPtr] : netModule->GetMethods())
|
||||
{
|
||||
|
||||
@@ -13,13 +13,13 @@ namespace Coral
|
||||
class ScriptingContext
|
||||
{
|
||||
private:
|
||||
Coral::HostInstance* m_HostInstance;
|
||||
Coral::AssemblyLoadContext m_LoadContext;
|
||||
Coral::HostInstance* hostInstance;
|
||||
Coral::AssemblyLoadContext loadContext;
|
||||
|
||||
std::unordered_map<std::string, Coral::AssemblyLoadContext*> m_LoadedAssemblies;
|
||||
std::vector<Ref<Nuake::NetAPIModule>> m_Modules;
|
||||
std::unordered_map<std::string, Coral::AssemblyLoadContext*> loadedAssemblies;
|
||||
std::vector<Ref<Nuake::NetAPIModule>> modules;
|
||||
|
||||
Coral::ManagedAssembly m_NuakeAssembly; // Nuake DLL
|
||||
Coral::ManagedAssembly nuakeAssembly; // Nuake DLL
|
||||
Coral::ManagedAssembly m_EditorAssembly; // Editor DLL
|
||||
public:
|
||||
static ScriptingContext& Get()
|
||||
|
||||
2
Editor/src/UIComponents/EntityTree.h
Normal file
2
Editor/src/UIComponents/EntityTree.h
Normal file
@@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
|
||||
@@ -10,27 +10,27 @@ public:
|
||||
float dummyVolume = 1.0f;
|
||||
void Draw()
|
||||
{
|
||||
constexpr int numBus = 6;
|
||||
if(ImGui::Begin("Audio mixer"))
|
||||
{
|
||||
for (int i = 0; i < numBus; i++)
|
||||
{
|
||||
const std::string busName = "Bus " + std::to_string(i);
|
||||
//ImGui::BeginTable(busName.c_str(), 1, 0, ImVec2(300, ImGui::GetContentRegionAvail().y));
|
||||
//
|
||||
//ImGui::TableSetupColumn(busName.c_str(), 0, 1.0f);
|
||||
//ImGui::TableNextColumn ();
|
||||
//ImGui::TableHeader(busName.c_str());
|
||||
//ImGui::TableNextColumn();
|
||||
//
|
||||
//const float height = ImGui::GetContentRegionAvail().y - 50;
|
||||
//const std::string id = "##Volume" + std::to_string(i);
|
||||
//ImGui::VSliderFloat(id.c_str(), ImVec2(50, height), &dummyVolume, -60.0f, 6.0f, "%.3dB", ImGuiSliderFlags_Logarithmic);
|
||||
//ImGui::TableNextColumn();
|
||||
//ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
//constexpr int numBus = 6;
|
||||
//if(ImGui::Begin("Audio mixer"))
|
||||
//{
|
||||
// for (int i = 0; i < numBus; i++)
|
||||
// {
|
||||
// const std::string busName = "Bus " + std::to_string(i);
|
||||
// //ImGui::BeginTable(busName.c_str(), 1, 0, ImVec2(300, ImGui::GetContentRegionAvail().y));
|
||||
// //
|
||||
// //ImGui::TableSetupColumn(busName.c_str(), 0, 1.0f);
|
||||
// //ImGui::TableNextColumn ();
|
||||
// //ImGui::TableHeader(busName.c_str());
|
||||
// //ImGui::TableNextColumn();
|
||||
// //
|
||||
// //const float height = ImGui::GetContentRegionAvail().y - 50;
|
||||
// //const std::string id = "##Volume" + std::to_string(i);
|
||||
// //ImGui::VSliderFloat(id.c_str(), ImVec2(50, height), &dummyVolume, -60.0f, 6.0f, "%.3dB", ImGuiSliderFlags_Logarithmic);
|
||||
// //ImGui::TableNextColumn();
|
||||
// //ImGui::EndTable();
|
||||
// }
|
||||
//}
|
||||
|
||||
ImGui::End();
|
||||
//ImGui::End();
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
#include "src/Vendors/imgui/imgui.h"
|
||||
|
||||
#include <src/Vendors/imgui/ImGuizmo.h>
|
||||
#include "src/Core/FileSystem.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
#include "../Actions/EditorSelection.h"
|
||||
#include "EditorSelectionPanel.h"
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <src/Scripting/ScriptingEngineNet.h>
|
||||
#include "ProjectSettings/ProjectSettingsWindow.h"
|
||||
#include "PrefabEditor/PrefabEditorWindow.h"
|
||||
|
||||
|
||||
using namespace NuakeEditor;
|
||||
@@ -30,14 +31,20 @@ namespace Nuake
|
||||
class EditorInterface
|
||||
{
|
||||
private:
|
||||
bool m_TitleBarHovered = false;
|
||||
std::vector<CompilationError> errors;
|
||||
std::vector<Ref<PrefabEditorWindow>> prefabEditors;
|
||||
Ref<Scene> SceneSnapshot;
|
||||
static NuakeEditor::CommandBuffer* mCommandBuffer;
|
||||
|
||||
std::string searchQuery = "";
|
||||
bool isControllingCamera = false;
|
||||
bool m_DrawGrid = false;
|
||||
bool m_DrawAxis = true;
|
||||
bool m_ShowImGuiDemo = false;
|
||||
bool m_DebugCollisions = true;
|
||||
bool m_DrawShapes = true;
|
||||
bool m_DrawGizmos = true;
|
||||
bool m_DrawCamPreview = false;
|
||||
bool m_DrawNavMesh = true;
|
||||
bool m_ShowOverlay = true;
|
||||
bool m_IsHoveringViewport = false;
|
||||
@@ -68,39 +75,54 @@ namespace Nuake
|
||||
|
||||
AudioWindow* _audioWindow;
|
||||
FileSystemUI* filesystem;
|
||||
bool isNewProject = false;
|
||||
static EditorSelection Selection;
|
||||
EditorSelectionPanel SelectionPanel;
|
||||
EditorSelectionPanel* SelectionPanel;
|
||||
TrenchbroomConfiguratorWindow m_TrenchhbroomConfigurator;
|
||||
MapImporterWindow m_MapImporter;
|
||||
|
||||
ProjectSettingsWindow* m_ProjectSettingsWindow;
|
||||
|
||||
Ref<Texture> NuakeTexture;
|
||||
Ref<Texture> CloseIconTexture;
|
||||
Ref<Texture> MaximizeTexture;
|
||||
Ref<Texture> RestoreTexture;
|
||||
Ref<Texture> MinimizeTexture;
|
||||
EditorInterface(CommandBuffer& commandBuffer);
|
||||
|
||||
static ImFont* bigIconFont;
|
||||
void BuildFonts();
|
||||
void DrawTitlebar(float& outHeight);
|
||||
void Init();
|
||||
|
||||
void Draw();
|
||||
void Update(float ts);
|
||||
void DrawMenuBar();
|
||||
bool BeginMenubar(const ImRect& barRectangle);
|
||||
void EndMenubar();
|
||||
|
||||
void SetStatusMessage(const std::string& msg, const Color& color = Color(0.08f, 0.08f, 0.08f, 1.0f)) { m_StatusMessage = msg; m_StatusBarColor = color; }
|
||||
void DrawViewport();
|
||||
void DrawStatusBar();
|
||||
void DrawMenuBars();
|
||||
void DrawEntityTree(Entity ent);
|
||||
void DrawEntityTree(Entity ent, bool drawChildrens = true);
|
||||
void DrawSceneTree();
|
||||
void DrawLogger();
|
||||
void DrawProjectSettings();
|
||||
bool EntityContainsItself(Entity ent1, Entity ent2);
|
||||
void Overlay();
|
||||
|
||||
void OpenPrefabWindow(const std::string& prefabPath);
|
||||
bool ShouldDrawAxis() const { return m_DrawAxis; }
|
||||
bool ShouldDrawCollision() const { return m_DebugCollisions; }
|
||||
bool ShouldDrawShapes() const { return m_DrawShapes; }
|
||||
bool ShouldDrawGizmos() const { return m_DrawGizmos; }
|
||||
bool ShouldDrawNavMesh() const { return m_DrawNavMesh; }
|
||||
bool LoadProject(const std::string& projectPath);
|
||||
|
||||
public:
|
||||
std::string GetEntityTypeName(const Entity& entity) const;
|
||||
static void PushCommand(ICommand&& command);
|
||||
|
||||
public:
|
||||
void OnWindowFocused();
|
||||
void OnDragNDrop(const std::vector<std::string>& paths);
|
||||
};
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,61 +2,49 @@
|
||||
#include "../Actions/EditorSelection.h"
|
||||
#include "src/Scene/Entities/Entity.h"
|
||||
|
||||
#include "src/Core/FileSystem.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Resource/Project.h>
|
||||
|
||||
#include "../ComponentsPanel/TransformPanel.h"
|
||||
#include "../ComponentsPanel/LightPanel.h"
|
||||
#include "../ComponentsPanel/ScriptPanel.h"
|
||||
#include "../ComponentsPanel/MeshPanel.h"
|
||||
#include "../ComponentsPanel/QuakeMapPanel.h"
|
||||
#include "../ComponentsPanel/SkinnedMeshPanel.h"
|
||||
#include "../ComponentsPanel/CameraPanel.h"
|
||||
#include "../ComponentsPanel/RigidbodyPanel.h"
|
||||
#include "../ComponentsPanel/BoxColliderPanel.h"
|
||||
#include "../ComponentsPanel/CapsuleColliderPanel.h"
|
||||
#include "../ComponentsPanel/CylinderColliderPanel.h"
|
||||
#include "../ComponentsPanel/SphereColliderPanel.h"
|
||||
#include "../ComponentsPanel/MeshColliderPanel.h"
|
||||
#include "../ComponentsPanel/CharacterControllerPanel.h"
|
||||
#include "../ComponentsPanel/SpritePanel.h"
|
||||
#include "../ComponentsPanel/ParticleEmitterPanel.h"
|
||||
#include "../ComponentsPanel/SkinnedModelPanel.h"
|
||||
#include "../ComponentsPanel/BonePanel.h"
|
||||
#include "../ComponentsPanel/AudioEmitterPanel.h"
|
||||
#include "../ComponentsPanel/NetScriptPanel.h"
|
||||
#include "../ComponentsPanel/NavMeshVolumePanel.h"
|
||||
|
||||
#include <src/Resource/Prefab.h>
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class Scene;
|
||||
}
|
||||
|
||||
class EditorSelectionPanel
|
||||
{
|
||||
using DrawComponentTypeFn = std::function<void(Nuake::Entity& entity, entt::meta_any& componentInstance)>;
|
||||
using DrawFieldTypeFn = std::function<void(entt::meta_data& fieldMeta, entt::meta_any& componentInstance)>;
|
||||
|
||||
private:
|
||||
TransformPanel mTransformPanel;
|
||||
LightPanel mLightPanel;
|
||||
ScriptPanel mScriptPanel;
|
||||
NetScriptPanel mNetScriptPanel;
|
||||
MeshPanel mMeshPanel;
|
||||
SkinnedModelPanel mSkinnedModelPanel;
|
||||
QuakeMapPanel mQuakeMapPanel;
|
||||
CameraPanel mCameraPanel;
|
||||
RigidbodyPanel mRigidbodyPanel;
|
||||
BoxColliderPanel mBoxColliderPanel;
|
||||
SphereColliderPanel mSphereColliderPanel;
|
||||
MeshColliderPanel mMeshColliderPanel;
|
||||
CapsuleColliderPanel mCapsuleColliderPanel;
|
||||
CylinderColliderPanel mCylinderColliderPanel;
|
||||
SpritePanel mSpritePanel;
|
||||
CharacterControllerPanel mCharacterControllerPanel;
|
||||
ParticleEmitterPanel mParticleEmitterPanel;
|
||||
BonePanel mBonePanel;
|
||||
AudioEmitterPanel mAudioEmitterPanel;
|
||||
NavMeshVolumePanel mNavMeshVolumePanel;
|
||||
MeshPanel meshPanel;
|
||||
SkinnedMeshPanel skinnedMeshPanel;
|
||||
EditorSelection* selection = nullptr;
|
||||
|
||||
Ref<Nuake::File> currentFile;
|
||||
Ref<Nuake::Resource> selectedResource;
|
||||
|
||||
Ref<Nuake::Scene> virtualScene;
|
||||
public:
|
||||
EditorSelectionPanel();
|
||||
EditorSelectionPanel(EditorSelection& selection);
|
||||
|
||||
void Draw(EditorSelection selection);
|
||||
void Draw(EditorSelection selection, const std::string& id = "");
|
||||
|
||||
void DrawNone();
|
||||
void DrawEntity(Nuake::Entity entity);
|
||||
@@ -64,11 +52,48 @@ public:
|
||||
|
||||
void DrawFile(Ref<Nuake::File> file);
|
||||
void DrawResource(Nuake::Resource resource);
|
||||
void DrawPrefabPanel(Ref<Nuake::Prefab> prefab);
|
||||
|
||||
template<class T, auto Func>
|
||||
void RegisterComponentDrawer()
|
||||
{
|
||||
const auto t = entt::type_id<T>();
|
||||
ComponentTypeDrawers[t.hash()] = std::bind(Func, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
template<class T, auto Func, class O>
|
||||
void RegisterComponentDrawer(O* o)
|
||||
{
|
||||
ComponentTypeDrawers[entt::type_id<T>().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
template<class T, auto Func, class O>
|
||||
void RegisterTypeDrawer(O* o)
|
||||
{
|
||||
FieldTypeDrawers[entt::type_id<T>().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Drawing functions for each component (for writing very specific inspectors for specific components)
|
||||
std::unordered_map<entt::id_type, DrawComponentTypeFn> ComponentTypeDrawers;
|
||||
|
||||
// List of functions to call for each component field type that needs to be drawn
|
||||
std::unordered_map<entt::id_type, DrawFieldTypeFn> FieldTypeDrawers;
|
||||
|
||||
private:
|
||||
void ResolveFile(Ref<Nuake::File> file);
|
||||
void DrawMaterialPanel(Ref<Nuake::Material> material);
|
||||
void DrawProjectPanel(Ref<Nuake::Project> project);
|
||||
void DrawWrenScriptPanel(Ref<Nuake::WrenScript> wrenFile);
|
||||
void DrawNetScriptPanel(Ref<Nuake::File> file);
|
||||
|
||||
void DrawComponent(Nuake::Entity& entity, entt::meta_any& component);
|
||||
void DrawComponentContent(entt::meta_any& component);
|
||||
|
||||
void DrawFieldTypeFloat(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeBool(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeVector2(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeVector3(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeString(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeResourceFile(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeDynamicItemList(entt::meta_data& field, entt::meta_any& component);
|
||||
};
|
||||
@@ -12,15 +12,19 @@
|
||||
|
||||
#include <src/Rendering/Textures/Material.h>
|
||||
#include "../Misc/PopupHelper.h"
|
||||
|
||||
#include <src/FileSystem/FileDialog.h>
|
||||
#include <src/FileSystem/Directory.h>
|
||||
#include <src/FileSystem/File.h>
|
||||
#include "src/Scene/Systems/WadConverter.h"
|
||||
#include "../Misc/ThumbnailManager.h"
|
||||
|
||||
#include <Tracy.hpp>
|
||||
#include <src/Resource/SkyResource.h>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
Ref<Directory> FileSystemUI::m_CurrentDirectory;
|
||||
|
||||
// TODO: add filetree in same panel
|
||||
void FileSystemUI::Draw()
|
||||
{
|
||||
|
||||
@@ -64,6 +68,8 @@ namespace Nuake
|
||||
|
||||
void FileSystemUI::DrawDirectory(Ref<Directory> directory, uint32_t drawId)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
ImGui::PushFont(FontManager::GetFont(Icons));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
|
||||
const char* icon = ICON_FA_FOLDER;
|
||||
@@ -226,6 +232,8 @@ namespace Nuake
|
||||
|
||||
void FileSystemUI::DrawFile(Ref<File> file, uint32_t drawId)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
ImGui::PushFont(EditorInterface::bigIconFont);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, {0.f, 0.f});
|
||||
@@ -254,6 +262,8 @@ namespace Nuake
|
||||
OS::OpenTrenchbroomMap(file->GetAbsolutePath());
|
||||
break;
|
||||
case FileType::NetScript:
|
||||
case FileType::UI:
|
||||
case FileType::CSS:
|
||||
OS::OpenIn(file->GetAbsolutePath());
|
||||
break;
|
||||
case FileType::Scene:
|
||||
@@ -262,8 +272,10 @@ namespace Nuake
|
||||
case FileType::Solution:
|
||||
OS::OpenIn(file->GetAbsolutePath());
|
||||
break;
|
||||
case FileType::Prefab:
|
||||
this->Editor->OpenPrefabWindow(file->GetRelativePath());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Editor->Selection = EditorSelection(file);
|
||||
@@ -313,6 +325,18 @@ namespace Nuake
|
||||
{
|
||||
dragType = "_AudioFile";
|
||||
}
|
||||
else if (fileExtension == ".html")
|
||||
{
|
||||
dragType = "_UIFile";
|
||||
}
|
||||
else if (fileExtension == ".sky")
|
||||
{
|
||||
dragType = "_SkyFile";
|
||||
}
|
||||
else if (fileExtension == ".env")
|
||||
{
|
||||
dragType = "_EnvFile";
|
||||
}
|
||||
|
||||
ImGui::SetDragDropPayload(dragType.c_str(), (void*)(pathBuffer), sizeof(pathBuffer));
|
||||
ImGui::Text(file->GetName().c_str());
|
||||
@@ -373,17 +397,34 @@ namespace Nuake
|
||||
textureImage = image;
|
||||
}
|
||||
}
|
||||
else if (fileType == FileType::Solution)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture("Resources/Images/sln_icon.png");
|
||||
}
|
||||
else if (fileType == FileType::Map)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture("Resources/Images/trenchbroom_icon.png");
|
||||
}
|
||||
else if (fileType == FileType::Env)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture("Resources/Images/env_file_icon.png");
|
||||
}
|
||||
|
||||
ImGui::SetCursorPos(prevCursor);
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(textureImage->GetID()), ImVec2(100, 100), ImVec2(0, 1), ImVec2(1, 0));
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
auto imguiStyle = ImGui::GetStyle();
|
||||
auto& imguiStyle = ImGui::GetStyle();
|
||||
|
||||
ImVec2 startOffset = ImVec2(imguiStyle.CellPadding.x / 2.0f, 0);
|
||||
ImVec2 offsetEnd = ImVec2(startOffset.x, imguiStyle.CellPadding.y / 2.0f);
|
||||
ImU32 rectColor = IM_COL32(255, 255, 255, 16);
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(prevScreenPos + ImVec2(0, 100) - startOffset, prevScreenPos + ImVec2(100, 150) + offsetEnd, rectColor, 1.0f);
|
||||
|
||||
ImU32 rectColor2 = UI::PrimaryCol;
|
||||
Color fileTypeColor = GetColorByFileType(file->GetFileType());
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(prevScreenPos + ImVec2(0, 100) - startOffset, prevScreenPos + ImVec2(100, 101) + offsetEnd, IM_COL32(fileTypeColor.r * 255.f, fileTypeColor.g * 255.f, fileTypeColor.b * 255.f, fileTypeColor.a * 255.f), 0.0f);
|
||||
|
||||
std::string visibleName = file->GetName();
|
||||
const uint32_t MAX_CHAR_NAME = 32;
|
||||
if (file->GetName().size() >= MAX_CHAR_NAME)
|
||||
@@ -552,7 +593,7 @@ namespace Nuake
|
||||
}
|
||||
|
||||
scene->Path = FileSystem::AbsoluteToRelative(projectPath);
|
||||
Engine::LoadScene(scene);
|
||||
Engine::SetCurrentScene(scene);
|
||||
}
|
||||
|
||||
// Rename Popup
|
||||
@@ -646,36 +687,50 @@ namespace Nuake
|
||||
RefreshFileBrowser();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Wren Script"))
|
||||
{
|
||||
std::string path = FileDialog::SaveFile("*.wren");
|
||||
|
||||
if (!String::EndsWith(path, ".wren"))
|
||||
{
|
||||
path += ".wren";
|
||||
}
|
||||
|
||||
if (!path.empty())
|
||||
{
|
||||
std::string fileName = String::ToUpper(FileSystem::GetFileNameFromPath(path));
|
||||
fileName = String::RemoveWhiteSpace(fileName);
|
||||
|
||||
if(!String::IsDigit(fileName[0]))
|
||||
{
|
||||
|
||||
FileSystem::BeginWriteFile(path, true);
|
||||
FileSystem::WriteLine(TEMPLATE_SCRIPT_FIRST + fileName + TEMPLATE_SCRIPT_SECOND);
|
||||
FileSystem::EndWriteFile();
|
||||
|
||||
RefreshFileBrowser();
|
||||
if (ImGui::MenuItem("Sky"))
|
||||
{
|
||||
const std::string path = FileDialog::SaveFile("*.sky");
|
||||
if (!path.empty())
|
||||
{
|
||||
std::string finalPath = path;
|
||||
if (!String::EndsWith(path, ".sky"))
|
||||
{
|
||||
finalPath = path + ".sky";
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Log("Cannot create script files that starts with a number.", "filesystem", CRITICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<SkyResource> sky = CreateRef<SkyResource>(FileSystem::AbsoluteToRelative(finalPath));
|
||||
sky->IsEmbedded = false;
|
||||
auto jsonData = sky->Serialize();
|
||||
|
||||
FileSystem::BeginWriteFile(finalPath, true);
|
||||
FileSystem::WriteLine(jsonData.dump(4));
|
||||
FileSystem::EndWriteFile();
|
||||
|
||||
RefreshFileBrowser();
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("Environment"))
|
||||
{
|
||||
const std::string path = FileDialog::SaveFile("*.env");
|
||||
if (!path.empty())
|
||||
{
|
||||
std::string finalPath = path;
|
||||
if (!String::EndsWith(path, ".env"))
|
||||
{
|
||||
finalPath = path + ".env";
|
||||
}
|
||||
|
||||
Ref<Environment> env = CreateRef<Environment>(FileSystem::AbsoluteToRelative(finalPath));
|
||||
env->IsEmbedded = false;
|
||||
auto jsonData = env->Serialize();
|
||||
|
||||
FileSystem::BeginWriteFile(finalPath, true);
|
||||
FileSystem::WriteLine(jsonData.dump(4));
|
||||
FileSystem::EndWriteFile();
|
||||
|
||||
RefreshFileBrowser();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -687,8 +742,79 @@ namespace Nuake
|
||||
|
||||
void FileSystemUI::RefreshFileBrowser()
|
||||
{
|
||||
Scan();
|
||||
}
|
||||
|
||||
Color FileSystemUI::GetColorByFileType(FileType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
{
|
||||
case Nuake::FileType::Unknown:
|
||||
break;
|
||||
case Nuake::FileType::Image:
|
||||
break;
|
||||
case Nuake::FileType::Material:
|
||||
break;
|
||||
case Nuake::FileType::Mesh:
|
||||
break;
|
||||
case Nuake::FileType::Script:
|
||||
return { 1.0, 0.0, 0.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::NetScript:
|
||||
return { 1.0, 0.0, 0.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::Project:
|
||||
return Engine::GetProject()->Settings.PrimaryColor;
|
||||
break;
|
||||
case Nuake::FileType::Prefab:
|
||||
break;
|
||||
case Nuake::FileType::Scene:
|
||||
return { 0, 1.0f, 1.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::Wad:
|
||||
break;
|
||||
case Nuake::FileType::Map:
|
||||
return { 0.0, 1.0, 0.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::Assembly:
|
||||
break;
|
||||
case Nuake::FileType::Solution:
|
||||
break;
|
||||
case Nuake::FileType::Audio:
|
||||
return { 0.0, 0.0, 1.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::UI:
|
||||
return { 1.0, 1.0, 0.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::CSS:
|
||||
return { 1.0, 0.0, 1.0, 1.0 };
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Color(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void FileSystemUI::Scan()
|
||||
{
|
||||
if (!m_CurrentDirectory)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string previousPath = m_CurrentDirectory->FullPath;
|
||||
|
||||
FileSystem::Scan();
|
||||
m_CurrentDirectory = FileSystem::RootDirectory;
|
||||
|
||||
if (FileSystem::DirectoryExists(previousPath, true))
|
||||
{
|
||||
m_CurrentDirectory = FileSystem::GetDirectory(FileSystem::AbsoluteToRelative(previousPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CurrentDirectory = FileSystem::RootDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
float h = 200;
|
||||
@@ -888,6 +1014,11 @@ namespace Nuake
|
||||
{
|
||||
for (Ref<Directory>& d : m_CurrentDirectory->Directories)
|
||||
{
|
||||
if (d->GetName() == "bin" || d->GetName() == ".vs" || d->GetName() == "obj")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(String::Sanitize(d->Name).find(String::Sanitize(m_SearchKeyword)) != std::string::npos)
|
||||
{
|
||||
if (i + 1 % amount != 0)
|
||||
@@ -907,6 +1038,11 @@ namespace Nuake
|
||||
{
|
||||
if(m_SearchKeyword.empty() || f->GetName().find(String::Sanitize(m_SearchKeyword)) != std::string::npos)
|
||||
{
|
||||
if (f->GetFileType() == FileType::Unknown || f->GetFileType() == FileType::Assembly)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i + 1 % amount != 0 || i == 1)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
@@ -915,7 +1051,7 @@ namespace Nuake
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
}
|
||||
|
||||
|
||||
DrawFile(f, i);
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Scene/Entities/Entity.h>
|
||||
#include "EditorInterface.h"
|
||||
|
||||
@@ -32,5 +32,9 @@ namespace Nuake {
|
||||
bool DeletePopup();
|
||||
void DrawContextMenu();
|
||||
void RefreshFileBrowser();
|
||||
|
||||
Color GetColorByFileType(FileType fileType);
|
||||
|
||||
void Scan();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
#include "MapImporterWindow.h"
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
#include "../Misc/InterfaceFonts.h"
|
||||
#include <src/UI/ImUI.h>
|
||||
#include <src/Core/Logger.h>
|
||||
#include <regex>
|
||||
#include <src/Threading/JobSystem.h>
|
||||
|
||||
#include <Engine.h>
|
||||
#include <src/Core/Logger.h>
|
||||
#include <src/FileSystem/File.h>
|
||||
#include <src/Threading/JobSystem.h>
|
||||
#include <src/UI/ImUI.h>
|
||||
#include <src/FileSystem/FileDialog.h>
|
||||
#include <src/Core/String.h>
|
||||
#include <src/Resource/Project.h>
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
void MapImporterWindow::Draw()
|
||||
{
|
||||
@@ -227,7 +240,7 @@ std::vector<std::string> MapImporterWindow::ScanUsedWads()
|
||||
|
||||
std::string MapImporterWindow::GetTransformedWadPath(const std::string& path)
|
||||
{
|
||||
const std::string& baseTextureDir = "/textures/";
|
||||
const std::string& baseTextureDir = "/Textures/";
|
||||
|
||||
using namespace Nuake;
|
||||
if (m_WadToMaterialMap.find(path) != m_WadToMaterialMap.end())
|
||||
@@ -272,7 +285,7 @@ std::string MapImporterWindow::GetTransformedWadPath(const std::string& path)
|
||||
|
||||
if (entry.is_regular_file() && stem == upperInput)
|
||||
{
|
||||
std::filesystem::path relativePath = std::filesystem::relative(entry.path(), FileSystem::Root + "/textures/");
|
||||
std::filesystem::path relativePath = std::filesystem::relative(entry.path(), FileSystem::Root + "/Textures/");
|
||||
std::filesystem::path pathWithoutExtension = relativePath;
|
||||
pathWithoutExtension = pathWithoutExtension.parent_path(); // Remove the file name
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <atomic>
|
||||
|
||||
class MapImporterWindow
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
#include <src/Rendering/Textures/TextureManager.h>
|
||||
#include <src/Rendering/Textures/Texture.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/FileSystem/FileDialog.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/UI/ImUI.h>
|
||||
#include <src/Core/Logger.h>
|
||||
#include <src/Resource/Project.h>
|
||||
@@ -52,7 +53,7 @@ namespace Nuake
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.1, 0.1, 0.1, 0.2f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.1f, 0.1f, 0.1f, 0.2f));
|
||||
ImGui::BeginChild("TemplateContainer", { ImGui::GetContentRegionAvail().x - 64.0f, ImGui::GetContentRegionAvail().y }, true, ImGuiChildFlags_AlwaysUseWindowPadding);
|
||||
{
|
||||
ImGui::Dummy({ 4, 4 });
|
||||
@@ -93,7 +94,7 @@ namespace Nuake
|
||||
if (showTitleEmptyWarning && projectTitle.empty())
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored({ 1.0, 0.1, 0.1, 1.0 }, ICON_FA_EXCLAMATION_TRIANGLE);
|
||||
ImGui::TextColored({ 1.0f, 0.1f, 0.1f, 1.0f }, ICON_FA_EXCLAMATION_TRIANGLE);
|
||||
|
||||
Nuake::UI::Tooltip("Title required");
|
||||
}
|
||||
@@ -138,28 +139,26 @@ namespace Nuake
|
||||
ImGui::InputText("##Location", &location); ImGui::SameLine();
|
||||
if (ImGui::Button((ICON_FA_FOLDER + std::string("##folderOpen")).c_str()))
|
||||
{
|
||||
std::string folderPath = Nuake::FileDialog::SaveFile("Project File\0*.project");
|
||||
std::string folderPath = Nuake::FileDialog::OpenFolder();
|
||||
folderPath = Nuake::String::ReplaceSlash(folderPath);
|
||||
|
||||
|
||||
if (!folderPath.empty())
|
||||
{
|
||||
auto splits = Nuake::String::Split(folderPath, '/');
|
||||
projectFileName = splits[splits.size() - 1];
|
||||
if (!Nuake::String::EndsWith(projectFileName, ".project"))
|
||||
{
|
||||
projectFileName += ".project";
|
||||
}
|
||||
|
||||
|
||||
location = "";
|
||||
|
||||
for (int i = 0; i < splits.size() - 1; i++)
|
||||
for (int i = 0; i < splits.size(); i++)
|
||||
{
|
||||
location += splits[i] + "/";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
projectFileName = Nuake::String::RemoveWhiteSpace(projectTitle) + ".project";
|
||||
|
||||
finalLocation = location;
|
||||
static std::string projectParentPath = location;
|
||||
projectParentPath = location;
|
||||
@@ -193,7 +192,12 @@ namespace Nuake
|
||||
|
||||
ImGui::Dummy({ 1, ImGui::GetContentRegionAvail().y - 42 });
|
||||
|
||||
ImGui::Dummy({ ImGui::GetContentRegionAvail().x - 130, 38 }); ImGui::SameLine();
|
||||
ImGui::Dummy({ ImGui::GetContentRegionAvail().x - 230 - 16, 38}); ImGui::SameLine();
|
||||
if (Nuake::UI::SecondaryButton("Cancel", { 100, 38 }))
|
||||
{
|
||||
m_Editor->isCreatingNewProject = false;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (Nuake::UI::PrimaryButton((ICON_FA_PLUS + std::string(" Create")).c_str(), Nuake::Vector2{ 120, 38 }, Nuake::Color(primaryColor.x, primaryColor.y, primaryColor.z, primaryColor.w)))
|
||||
{
|
||||
if (projectTitle.empty())
|
||||
@@ -230,7 +234,7 @@ namespace Nuake
|
||||
Nuake::FileSystem::SetRootDirectory(projectParentPath);
|
||||
auto project = Nuake::Project::New(projectTitle, description, finalLocation);
|
||||
Nuake::Engine::LoadProject(project);
|
||||
Nuake::Engine::LoadScene(Nuake::Scene::New());
|
||||
Nuake::Engine::SetCurrentScene(Nuake::Scene::New());
|
||||
project->Settings.PrimaryColor = Nuake::Color(primaryColor.x, primaryColor.y, primaryColor.z, primaryColor.w);
|
||||
project->Save();
|
||||
|
||||
@@ -239,7 +243,7 @@ namespace Nuake
|
||||
window->Maximize();
|
||||
|
||||
m_Editor->filesystem->m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
|
||||
|
||||
m_Editor->isNewProject = true;
|
||||
m_HasCreatedProject = true;
|
||||
}
|
||||
}
|
||||
@@ -263,7 +267,6 @@ namespace Nuake
|
||||
void NewProjectWindow::DrawProjectTemplate(uint32_t i, const std::string& title, const std::string& description)
|
||||
{
|
||||
opened = true;
|
||||
ImGui::ShowDemoWindow(&opened);
|
||||
ImGui::Dummy({ 4, 4 });
|
||||
ImGui::SameLine();
|
||||
opened = true;
|
||||
|
||||
919
Editor/src/Windows/PrefabEditor/PrefabEditorWindow.cpp
Normal file
919
Editor/src/Windows/PrefabEditor/PrefabEditorWindow.cpp
Normal file
@@ -0,0 +1,919 @@
|
||||
#include "PrefabEditorWindow.h"
|
||||
|
||||
#include <src/Core/Input.h>
|
||||
#include <src/Rendering/Buffers/FrameBuffer.h>
|
||||
#include <src/Rendering/SceneRenderer.h>
|
||||
#include <src/Resource/Prefab.h>
|
||||
#include <src/Scene/Scene.h>
|
||||
#include <src/Scene/EditorCamera.h>
|
||||
#include <src/Scene/Entities/Entity.h>
|
||||
#include <src/Rendering/Textures/Texture.h>
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/imgui_internal.h>
|
||||
#include <src/Scene/Components/SpriteComponent.h>
|
||||
#include <src/Scene/Components/ParticleEmitterComponent.h>
|
||||
#include <src/Scene/Components/RigidbodyComponent.h>
|
||||
#include <src/Scene/Components/BoxCollider.h>
|
||||
#include <src/Scene/Components/SphereCollider.h>
|
||||
#include <src/Scene/Components/AudioEmitterComponent.h>
|
||||
#include <src/Scene/Components/PrefabComponent.h>
|
||||
#include <src/Scene/Components/BSPBrushComponent.h>
|
||||
#include <src/Scene/Components/NetScriptComponent.h>
|
||||
#include <src/FileSystem/FileDialog.h>
|
||||
#include <imgui/ImGuizmo.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
PrefabEditorWindow::PrefabEditorWindow(Ref<Prefab> inPrefab) :
|
||||
prefab(inPrefab),
|
||||
SelectionPanel(CreateScope<EditorSelectionPanel>(Selection))
|
||||
{
|
||||
const Vector2 defaultSize = Vector2{ 640, 360 };
|
||||
viewportFramebuffer = CreateRef<FrameBuffer>(true, defaultSize);
|
||||
viewportFramebuffer->SetTexture(CreateRef<Texture>(defaultSize, GL_RGB, GL_RGB16F, GL_FLOAT));
|
||||
|
||||
virtualScene = CreateRef<Scene>();
|
||||
virtualScene->GetEnvironment()->CurrentSkyType = SkyType::ProceduralSky;
|
||||
virtualScene->GetEnvironment()->ProceduralSkybox->SunDirection = { 0.58f, 0.34f, -0.74f };
|
||||
|
||||
prefab = Prefab::InstanceInScene(inPrefab->Path, virtualScene.get());
|
||||
prefab->Path = inPrefab->Path;
|
||||
|
||||
Ref<Texture> outputTexture = CreateRef<Texture>(defaultSize, GL_RGB);
|
||||
outputTexture->SetParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
outputTexture->SetParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
auto& previewLight = virtualScene->CreateEntity("_directionalLight").AddComponent<LightComponent>();
|
||||
previewLight.Type = LightType::Directional;
|
||||
previewLight.SetCastShadows(true);
|
||||
previewLight.SyncDirectionWithSky = true;
|
||||
previewLight.Strength = 5.5f;
|
||||
}
|
||||
|
||||
void PrefabEditorWindow::Update(float ts)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PrefabEditorWindow::Draw()
|
||||
{
|
||||
RenderScene();
|
||||
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
|
||||
ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
|
||||
ImGuiID dockspace_id = ImGui::GetID(prefab->Path.c_str());
|
||||
ImVec2 dockspace_size;
|
||||
if (!isInitialized)
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(1280, 720));
|
||||
}
|
||||
|
||||
if(ImGui::Begin(prefab->Path.c_str(), 0, window_flags))
|
||||
{
|
||||
dockspace_size = ImGui::GetContentRegionAvail();
|
||||
ImGui::DockSpace(dockspace_id, dockspace_size, dockspace_flags);
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("File"))
|
||||
{
|
||||
if(ImGui::MenuItem("Save", "Ctrl+S"))
|
||||
{
|
||||
Save();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
// Programmatically dock windows using DockBuilder API
|
||||
if (!isInitialized)
|
||||
{
|
||||
isInitialized = true;
|
||||
|
||||
// Create dock layout for the embedded dockspace
|
||||
ImGui::DockBuilderRemoveNode(dockspace_id); // Clear any existing layout
|
||||
ImGui::DockBuilderAddNode(dockspace_id, dockspace_flags | ImGuiDockNodeFlags_DockSpace);
|
||||
ImGui::DockBuilderSetNodeSize(dockspace_id, dockspace_size);
|
||||
|
||||
// Split the dockspace into two areas: left and right
|
||||
ImGuiID dock_left_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.25f, nullptr, &dockspace_id);
|
||||
ImGuiID dock_r_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Right, 0.66f, nullptr, &dockspace_id);
|
||||
|
||||
// Dock windows into the created nodes
|
||||
ImGui::DockBuilderDockWindow(std::string("Prefab Hierarchy## " + prefab->Path).c_str(), dock_left_id);
|
||||
ImGui::DockBuilderDockWindow(std::string("Viewport##" + prefab->Path).c_str(), dockspace_id);
|
||||
ImGui::DockBuilderDockWindow(std::string("Properties##" + prefab->Path).c_str(), dock_r_id);
|
||||
// Commit the dock layout
|
||||
ImGui::DockBuilderFinish(dockspace_id);
|
||||
}
|
||||
|
||||
if (ImGui::Begin(std::string("Prefab Hierarchy## " + prefab->Path).c_str()))
|
||||
{
|
||||
Ref<Scene> scene = virtualScene;
|
||||
std::string searchQuery = "";
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 8, 8 });
|
||||
ImGui::InputTextWithHint("##search", "Search entity", &searchQuery, 0, 0, 0);
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (UI::PrimaryButton("Add Entity", { ImGui::GetContentRegionAvail().x, 0 }))
|
||||
{
|
||||
ImGui::OpenPopup("create_entity_popup");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("create_entity_popup"))
|
||||
{
|
||||
Nuake::Entity entity;
|
||||
if (ImGui::MenuItem("Empty"))
|
||||
{
|
||||
entity = scene->CreateEntity("Empty");
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("3D"))
|
||||
{
|
||||
if (ImGui::MenuItem("Camera"))
|
||||
{
|
||||
entity = scene->CreateEntity("Camera");
|
||||
entity.AddComponent<CameraComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Model"))
|
||||
{
|
||||
entity = scene->CreateEntity("Model");
|
||||
entity.AddComponent<ModelComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Skinned Model"))
|
||||
{
|
||||
entity = scene->CreateEntity("Skinned Model");
|
||||
entity.AddComponent<SkinnedModelComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Sprite"))
|
||||
{
|
||||
entity = scene->CreateEntity("Sprite");
|
||||
entity.AddComponent<SpriteComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Particle Emitter"))
|
||||
{
|
||||
entity = scene->CreateEntity("Particle Emitter");
|
||||
entity.AddComponent<ParticleEmitterComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Light"))
|
||||
{
|
||||
entity = scene->CreateEntity("Light");
|
||||
entity.AddComponent<LightComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Quake Map"))
|
||||
{
|
||||
entity = scene->CreateEntity("Quake Map");
|
||||
entity.AddComponent<QuakeMapComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("NavMesh Volume"))
|
||||
{
|
||||
entity = scene->CreateEntity("NavMesh Volume");
|
||||
entity.AddComponent<NavMeshVolumeComponent>();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Physics"))
|
||||
{
|
||||
if (ImGui::MenuItem("Character Controller"))
|
||||
{
|
||||
entity = scene->CreateEntity("Character Controller");
|
||||
entity.AddComponent<CharacterControllerComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Rigid Body"))
|
||||
{
|
||||
entity = scene->CreateEntity("Rigid Body");
|
||||
entity.AddComponent<RigidBodyComponent>();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Colliders"))
|
||||
{
|
||||
if (ImGui::MenuItem("Box Collider"))
|
||||
{
|
||||
entity = scene->CreateEntity("Box Collider");
|
||||
entity.AddComponent<BoxColliderComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Sphere Collider"))
|
||||
{
|
||||
entity = scene->CreateEntity("Sphere Collider");
|
||||
entity.AddComponent<SphereColliderComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Capsule Collider"))
|
||||
{
|
||||
entity = scene->CreateEntity("Capsule Collider");
|
||||
entity.AddComponent<CapsuleColliderComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Cylinder Collider"))
|
||||
{
|
||||
entity = scene->CreateEntity("Cylinder Collider");
|
||||
entity.AddComponent<CylinderColliderComponent>();
|
||||
}
|
||||
if (ImGui::MenuItem("Mesh Collider"))
|
||||
{
|
||||
entity = scene->CreateEntity("Mesh Collider");
|
||||
entity.AddComponent<MeshColliderComponent>();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Audio"))
|
||||
{
|
||||
if (ImGui::MenuItem("Audio Emitter"))
|
||||
{
|
||||
entity = scene->CreateEntity("Audio Emitter");
|
||||
entity.AddComponent<AudioEmitterComponent>();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (entity.IsValid())
|
||||
{
|
||||
if (Selection.Type == EditorSelectionType::Entity && Selection.Entity.IsValid())
|
||||
{
|
||||
Selection.Entity.AddChild(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& camera = virtualScene->m_EditorCamera;
|
||||
Vector3 newEntityPos = camera->Translation + camera->Direction;
|
||||
entity.GetComponent<TransformComponent>().SetLocalPosition(newEntityPos);
|
||||
}
|
||||
|
||||
Selection = EditorSelection(entity);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Draw a tree of entities.
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(26.f / 255.0f, 26.f / 255.0f, 26.f / 255.0f, 1));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 4, 4 });
|
||||
if (ImGui::BeginChild("Scene tree", ImGui::GetContentRegionAvail(), false))
|
||||
{
|
||||
if (ImGui::BeginTable("entity_table", 4, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingStretchProp))
|
||||
{
|
||||
ImGui::TableSetupColumn(" Label", ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("Script", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("Visibility ", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0));
|
||||
std::vector<Nuake::Entity> entities = scene->GetAllEntities();
|
||||
|
||||
ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanFullWidth;
|
||||
std::string name = prefab->Root.GetComponent<NameComponent>().Name;
|
||||
// If selected add selected flag.
|
||||
if (Selection.Type == EditorSelectionType::Entity && Selection.Entity == prefab->Root)
|
||||
base_flags |= ImGuiTreeNodeFlags_Selected;
|
||||
|
||||
DrawEntityTree(prefab->Root);
|
||||
|
||||
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
|
||||
if (QueueDeletion.GetHandle() != -1)
|
||||
{
|
||||
virtualScene->DestroyEntity(QueueDeletion);
|
||||
|
||||
// Clear Selection
|
||||
Selection = EditorSelection();
|
||||
|
||||
QueueDeletion = Nuake::Entity{ (entt::entity)-1, scene.get() };
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
SelectionPanel->Draw(Selection, prefab->Path);
|
||||
|
||||
DrawViewportWindow();
|
||||
}
|
||||
|
||||
void PrefabEditorWindow::DrawViewportWindow()
|
||||
{
|
||||
|
||||
//viewportFramebuffer->Bind();
|
||||
////RenderCommand::SetClearColor(Color(1, 0, 0, 1));
|
||||
//viewportFramebuffer->Clear();
|
||||
//viewportFramebuffer->Unbind();
|
||||
|
||||
//RenderScene();
|
||||
|
||||
if (ImGui::Begin(std::string("Viewport##" + prefab->Path).c_str()))
|
||||
{
|
||||
DrawOverlay();
|
||||
|
||||
ImGuizmo::BeginFrame();
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
|
||||
ImVec2 regionAvail = ImGui::GetContentRegionAvail();
|
||||
Vector2 viewportPanelSize = glm::vec2(regionAvail.x, regionAvail.y);
|
||||
|
||||
if (viewportFramebuffer->GetSize() != viewportPanelSize)
|
||||
viewportFramebuffer->QueueResize(viewportPanelSize);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));\
|
||||
viewportFramebuffer->QueueResize(viewportPanelSize);
|
||||
ImGui::Image((void*)viewportFramebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->GetID(), regionAvail, ImVec2(0, 1), ImVec2(1, 0));
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
const Vector2& mousePos = Input::GetMousePosition();
|
||||
|
||||
ImVec2 imagePos = ImGui::GetWindowPos() + ImGui::GetCursorPos();
|
||||
|
||||
const ImVec2& windowPos = ImGui::GetWindowPos();
|
||||
const auto windowPosNuake = Vector2(windowPos.x, windowPos.y);
|
||||
const ImVec2& windowSize = ImGui::GetWindowSize();
|
||||
const bool isInsideWidth = mousePos.x > windowPos.x && mousePos.x < windowPos.x + windowSize.x;
|
||||
const bool isInsideHeight = mousePos.y > windowPos.y && mousePos.y < windowPos.y + windowSize.y;
|
||||
isHoveringViewport = isInsideWidth && isInsideHeight;
|
||||
|
||||
ImGuizmo::SetDrawlist();
|
||||
ImGuizmo::AllowAxisFlip(true);
|
||||
ImGuizmo::SetRect(imagePos.x, imagePos.y + 0.0f, viewportPanelSize.x, viewportPanelSize.y);
|
||||
|
||||
auto& editorCam = virtualScene->m_EditorCamera;
|
||||
isControllingCamera = editorCam->Update(Engine::GetTimestep(), isHoveringViewport);
|
||||
|
||||
|
||||
if (Selection.Type == EditorSelectionType::Entity && !Engine::IsPlayMode())
|
||||
{
|
||||
if (!Selection.Entity.IsValid())
|
||||
{
|
||||
Selection = EditorSelection();
|
||||
}
|
||||
else
|
||||
{
|
||||
TransformComponent& tc = Selection.Entity.GetComponent<TransformComponent>();
|
||||
Matrix4 transform = tc.GetGlobalTransform();
|
||||
const auto& editorCam = virtualScene->GetCurrentCamera();
|
||||
Matrix4 cameraView = editorCam->GetTransform();
|
||||
Matrix4 cameraProjection = editorCam->GetPerspective();
|
||||
static Vector3 camPreviousPos = virtualScene->m_EditorCamera->Translation;
|
||||
static Vector3 camNewPos = Vector3(0, 0, 0);
|
||||
|
||||
Vector3 camDelta = camNewPos - camPreviousPos;
|
||||
Vector3 previousGlobalPos = transform[3];
|
||||
|
||||
// Imguizmo calculates the delta from the gizmo,
|
||||
ImGuizmo::Manipulate(
|
||||
glm::value_ptr(cameraView),
|
||||
glm::value_ptr(cameraProjection),
|
||||
CurrentOperation, CurrentMode,
|
||||
glm::value_ptr(transform), NULL,
|
||||
UseSnapping ? &CurrentSnapping.x : NULL
|
||||
);
|
||||
|
||||
if (ImGuizmo::IsUsing())
|
||||
{
|
||||
// Since imguizmo returns a transform in global space and we want the local transform,
|
||||
// we need to multiply by the inverse of the parent's global transform in order to revert
|
||||
// the changes from the parent transform.
|
||||
Matrix4 localTransform = Matrix4(transform);
|
||||
|
||||
Vector3 newGlobalPos = transform[3];
|
||||
if (ImGui::IsKeyDown(ImGuiKey_LeftShift))
|
||||
{
|
||||
Vector3 positionDelta = newGlobalPos - previousGlobalPos;
|
||||
virtualScene->m_EditorCamera->Translation += positionDelta;
|
||||
camNewPos = virtualScene->m_EditorCamera->Translation;
|
||||
}
|
||||
|
||||
ParentComponent& parent = Selection.Entity.GetComponent<ParentComponent>();
|
||||
if (parent.HasParent)
|
||||
{
|
||||
const auto& parentTransformComponent = parent.Parent.GetComponent<TransformComponent>();
|
||||
const Matrix4& parentTransform = parentTransformComponent.GetGlobalTransform();
|
||||
localTransform = glm::inverse(parentTransform) * localTransform;
|
||||
}
|
||||
|
||||
// Decompose local transform
|
||||
float decomposedPosition[3];
|
||||
float decomposedEuler[3];
|
||||
float decomposedScale[3];
|
||||
ImGuizmo::DecomposeMatrixToComponents(glm::value_ptr(localTransform), decomposedPosition, decomposedEuler, decomposedScale);
|
||||
|
||||
const auto& localPosition = Vector3(decomposedPosition[0], decomposedPosition[1], decomposedPosition[2]);
|
||||
const auto& localScale = Vector3(decomposedScale[0], decomposedScale[1], decomposedScale[2]);
|
||||
|
||||
localTransform[0] /= localScale.x;
|
||||
localTransform[1] /= localScale.y;
|
||||
localTransform[2] /= localScale.z;
|
||||
const auto& rotationMatrix = Matrix3(localTransform);
|
||||
const Quat& localRotation = glm::normalize(Quat(rotationMatrix));
|
||||
|
||||
const Matrix4& rotationMatrix4 = glm::mat4_cast(localRotation);
|
||||
const Matrix4& scaleMatrix = glm::scale(Matrix4(1.0f), localScale);
|
||||
const Matrix4& translationMatrix = glm::translate(Matrix4(1.0f), localPosition);
|
||||
const Matrix4& newLocalTransform = translationMatrix * rotationMatrix4 * scaleMatrix;
|
||||
|
||||
tc.Translation = localPosition;
|
||||
|
||||
if (CurrentOperation != ImGuizmo::SCALE)
|
||||
{
|
||||
tc.Rotation = localRotation;
|
||||
}
|
||||
|
||||
tc.Scale = localScale;
|
||||
tc.LocalTransform = newLocalTransform;
|
||||
tc.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsWindowHovered() && isHoveringViewport && !isViewportFocused && ImGui::GetIO().WantCaptureMouse)
|
||||
{
|
||||
ImGui::FocusWindow(ImGui::GetCurrentWindow());
|
||||
}
|
||||
|
||||
isViewportFocused = ImGui::IsWindowFocused();
|
||||
|
||||
|
||||
if (ImGui::GetIO().WantCaptureMouse && isHoveringViewport && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && isViewportFocused)
|
||||
{
|
||||
auto& gbuffer = virtualScene->m_SceneRenderer->GetGBuffer();
|
||||
auto pixelPos = (Input::GetMousePosition() - windowPosNuake);
|
||||
pixelPos.y = gbuffer.GetSize().y - pixelPos.y; // imgui coords are inverted on the Y axi
|
||||
|
||||
gbuffer.Bind();
|
||||
if (const int result = gbuffer.ReadPixel(3, pixelPos); result > 0)
|
||||
{
|
||||
auto ent = Nuake::Entity{ (entt::entity)(result - 1), virtualScene.get() };
|
||||
if (ent.IsValid())
|
||||
{
|
||||
Selection = EditorSelection(ent);
|
||||
virtualScene->m_SceneRenderer->mOutlineEntityID = (uint32_t)ent.GetHandle();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Selection = EditorSelection(); // None
|
||||
}
|
||||
|
||||
gbuffer.Unbind();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void PrefabEditorWindow::DrawOverlay()
|
||||
{
|
||||
if (Engine::GetGameState() == GameState::Playing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME-VIEWPORT: Select a default viewport
|
||||
const float DISTANCE = 10.0f;
|
||||
int corner = 0;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
|
||||
|
||||
window_flags |= ImGuiWindowFlags_NoMove;
|
||||
ImGuiViewport* viewport = ImGui::GetWindowViewport();
|
||||
ImVec2 work_area_pos = ImGui::GetCurrentWindow()->Pos; // Instead of using viewport->Pos we use GetWorkPos() to avoid menu bars, if any!
|
||||
ImVec2 work_area_size = ImGui::GetCurrentWindow()->Size;
|
||||
ImVec2 window_pos = ImVec2((corner & 1) ? (work_area_pos.x + work_area_size.x - DISTANCE) : (work_area_pos.x + DISTANCE), (corner & 2) ? (work_area_pos.y + work_area_size.y - DISTANCE) : (work_area_pos.y + DISTANCE));
|
||||
ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
|
||||
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 32.0f);
|
||||
if (ImGui::Begin("ActionBar2", 0, window_flags))
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 100);
|
||||
|
||||
bool selectedMode = CurrentOperation == ImGuizmo::OPERATION::TRANSLATE;
|
||||
if (selectedMode)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button(ICON_FA_ARROWS_ALT , ImVec2(30, 28)) || (ImGui::Shortcut(ImGuiKey_W, 0, ImGuiInputFlags_RouteGlobalLow) && !ImGui::IsAnyItemActive() && !isControllingCamera))
|
||||
{
|
||||
CurrentOperation = ImGuizmo::OPERATION::TRANSLATE;
|
||||
}
|
||||
|
||||
|
||||
UI::Tooltip("Translate");
|
||||
if (selectedMode)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
selectedMode = CurrentOperation == ImGuizmo::OPERATION::ROTATE;
|
||||
if (selectedMode)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button(ICON_FA_SYNC_ALT, ImVec2(30, 28)) || (ImGui::Shortcut(ImGuiKey_E, 0, ImGuiInputFlags_RouteGlobalLow) && !ImGui::IsAnyItemActive() && !isControllingCamera))
|
||||
{
|
||||
CurrentOperation = ImGuizmo::OPERATION::ROTATE;
|
||||
}
|
||||
|
||||
UI::Tooltip("Rotate");
|
||||
|
||||
if (selectedMode)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
selectedMode = CurrentOperation == ImGuizmo::OPERATION::SCALE;
|
||||
if (selectedMode)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button(ICON_FA_EXPAND_ALT, ImVec2(30, 28)) || (ImGui::Shortcut(ImGuiKey_R, 0, ImGuiInputFlags_RouteGlobalLow) && !ImGui::IsAnyItemActive() && !isControllingCamera))
|
||||
{
|
||||
CurrentOperation = ImGuizmo::OPERATION::SCALE;
|
||||
}
|
||||
|
||||
UI::Tooltip("Scale");
|
||||
|
||||
if (selectedMode)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
selectedMode = CurrentMode == ImGuizmo::MODE::WORLD;
|
||||
if (selectedMode)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button(ICON_FA_GLOBE, ImVec2(30, 28)))
|
||||
{
|
||||
CurrentMode = ImGuizmo::MODE::WORLD;
|
||||
}
|
||||
|
||||
UI::Tooltip("Global Transformation");
|
||||
|
||||
if (selectedMode)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
selectedMode = CurrentMode == ImGuizmo::MODE::LOCAL;
|
||||
if (selectedMode)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button(ICON_FA_CUBE, ImVec2(30, 28)))
|
||||
{
|
||||
CurrentMode = ImGuizmo::MODE::LOCAL;
|
||||
}
|
||||
|
||||
UI::Tooltip("Local Transformation");
|
||||
|
||||
if (selectedMode)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(75);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 6, 6 });
|
||||
ImGui::DragFloat("##snapping", &CurrentSnapping.x, 0.01f, 0.0f, 100.0f);
|
||||
CurrentSnapping = { CurrentSnapping.x, CurrentSnapping.x, CurrentSnapping.z };
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
UI::Tooltip("Snapping");
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::End();
|
||||
|
||||
int corner2 = 1;
|
||||
work_area_pos = ImGui::GetCurrentWindow()->Pos; // Instead of using viewport->Pos we use GetWorkPos() to avoid menu bars, if any!
|
||||
work_area_size = ImGui::GetCurrentWindow()->Size;
|
||||
window_pos = ImVec2((corner2 & 1) ? (work_area_pos.x + work_area_size.x - DISTANCE) : (work_area_pos.x + DISTANCE), (corner2 & 2) ? (work_area_pos.y + work_area_size.y - DISTANCE) : (work_area_pos.y + DISTANCE));
|
||||
window_pos_pivot = ImVec2((corner2 & 1) ? 1.0f : 0.0f, (corner2 & 2) ? 1.0f : 0.0f);
|
||||
ImGui::SetNextWindowPos(window_pos + ImVec2(0, 40), ImGuiCond_Always, window_pos_pivot);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 32.0f);
|
||||
ImGui::SetNextWindowSize(ImVec2(16, ImGui::GetContentRegionAvail().y - DISTANCE * 2.0 - 40.0));
|
||||
if (ImGui::Begin("Controls2", 0, window_flags))
|
||||
{
|
||||
const auto& editorCam = virtualScene->m_EditorCamera;
|
||||
const float camSpeed = editorCam->Speed;
|
||||
|
||||
const float maxSpeed = 50.0f;
|
||||
const float minSpeed = 0.05f;
|
||||
const float normalizedSpeed = glm::clamp((camSpeed / maxSpeed), 0.0f, 1.0f);
|
||||
|
||||
ImVec2 start = ImGui::GetWindowPos() - ImVec2(0.0, 4.0);
|
||||
ImVec2 end = start + ImGui::GetWindowSize() - ImVec2(0, 16.0);
|
||||
ImVec2 startOffset = ImVec2(start.x, end.y - (normalizedSpeed * (ImGui::GetWindowHeight() - 20.0)));
|
||||
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(startOffset + ImVec2(0, 10.0), end + ImVec2(0.0, 20.0), IM_COL32(255, 255, 255, 180), 8.0f, ImDrawFlags_RoundCornersAll);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 100);
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void PrefabEditorWindow::RenderScene()
|
||||
{
|
||||
virtualScene->Update(Engine::GetTimestep());
|
||||
|
||||
Ref<SceneRenderer> sceneRenderer = virtualScene->m_SceneRenderer;
|
||||
Ref<EditorCamera> editorCam = virtualScene->m_EditorCamera;
|
||||
editorCam->OnWindowResize(viewportFramebuffer->GetSize().x, viewportFramebuffer->GetSize().y);
|
||||
virtualScene->Draw(*viewportFramebuffer.get());
|
||||
|
||||
sceneRenderer->BeginRenderScene(editorCam->GetPerspective(), editorCam->GetTransform(), editorCam->Translation);
|
||||
sceneRenderer->RenderScene(*virtualScene, *viewportFramebuffer.get(), true);
|
||||
|
||||
}
|
||||
|
||||
void PrefabEditorWindow::DrawEntityTree(Nuake::Entity e)
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{ 0.0f, 0.0f });
|
||||
|
||||
ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_FramePadding | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAllColumns;
|
||||
|
||||
NameComponent& nameComponent = e.GetComponent<NameComponent>();
|
||||
std::string name = nameComponent.Name;
|
||||
|
||||
ParentComponent& parent = e.GetComponent<ParentComponent>();
|
||||
|
||||
if (Selection.Type == EditorSelectionType::Entity && Selection.Entity == e)
|
||||
base_flags |= ImGuiTreeNodeFlags_Selected;
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Write in normal font.
|
||||
// ImGui::PushFont(normalFont);
|
||||
|
||||
// If has no childrens draw tree node leaf
|
||||
if (parent.Children.size() <= 0)
|
||||
{
|
||||
base_flags |= ImGuiTreeNodeFlags_Leaf;
|
||||
}
|
||||
|
||||
if (nameComponent.IsPrefab && e.HasComponent<PrefabComponent>())
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0, 255, 0, 255));
|
||||
}
|
||||
else if (e.HasComponent<BSPBrushComponent>())
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 120));
|
||||
}
|
||||
|
||||
//if (!m_IsRenaming && m_ShouldUnfoldEntityTree && Selection.Type == EditorSelectionType::Entity && e.GetScene()->EntityIsParent(Selection.Entity, e))
|
||||
//{
|
||||
// ImGui::SetNextItemOpen(true);
|
||||
//}
|
||||
|
||||
auto cursorPos = ImGui::GetCursorPos();
|
||||
ImGui::SetNextItemAllowOverlap();
|
||||
bool open = ImGui::TreeNodeEx(name.c_str(), base_flags);
|
||||
|
||||
if (isRenaming)
|
||||
{
|
||||
if (Selection.Type == EditorSelectionType::Entity && Selection.Entity == e)
|
||||
{
|
||||
ImGui::SetCursorPosY(cursorPos.y);
|
||||
ImGui::Indent();
|
||||
ImGui::InputText("##renamingEntity", &name);
|
||||
ImGui::Unindent();
|
||||
if (Input::IsKeyDown(Key::ENTER))
|
||||
{
|
||||
nameComponent.Name = name;
|
||||
isRenaming = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isDragging = false;
|
||||
if (nameComponent.IsPrefab && e.HasComponent<PrefabComponent>() || e.HasComponent<BSPBrushComponent>())
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
else if (!isRenaming && ImGui::BeginDragDropSource())
|
||||
{
|
||||
ImGui::SetDragDropPayload("ENTITYPrefab", (void*)&e, sizeof(Nuake::Entity));
|
||||
ImGui::Text(name.c_str());
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITYPrefab"))
|
||||
{
|
||||
Nuake::Entity payload_entity = *(const Nuake::Entity*)payload->Data;
|
||||
|
||||
// Check if entity is already parent.
|
||||
ParentComponent& parentPayload = payload_entity.GetComponent<ParentComponent>();
|
||||
if (!payload_entity.EntityContainsItself(payload_entity, e) && parentPayload.Parent != e && std::count(parent.Children.begin(), parent.Children.end(), payload_entity) == 0)
|
||||
{
|
||||
if (parentPayload.HasParent)
|
||||
{
|
||||
// Erase remove idiom.
|
||||
ParentComponent& childOfParent = parentPayload.Parent.GetComponent<ParentComponent>();
|
||||
childOfParent.Children.erase(std::remove(childOfParent.Children.begin(), childOfParent.Children.end(), payload_entity), childOfParent.Children.end());
|
||||
}
|
||||
|
||||
parentPayload.Parent = e;
|
||||
parentPayload.HasParent = true;
|
||||
parent.Children.push_back(payload_entity);
|
||||
}
|
||||
}
|
||||
else if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_NetScript"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
|
||||
std::string fullPath = std::string(file, 512);
|
||||
std::string path = Nuake::FileSystem::AbsoluteToRelative(std::move(fullPath));
|
||||
|
||||
if (e.HasComponent<NetScriptComponent>())
|
||||
{
|
||||
e.GetComponent<NetScriptComponent>().ScriptPath = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
e.AddComponent<NetScriptComponent>().ScriptPath = path;
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
|
||||
if (!isDragging && ImGui::IsItemHovered() && ImGui::IsMouseReleased(0))
|
||||
{
|
||||
// We selected another another that we werent renaming
|
||||
if (Selection.Entity != e)
|
||||
{
|
||||
isRenaming = false;
|
||||
}
|
||||
|
||||
Selection = EditorSelection(e);
|
||||
}
|
||||
|
||||
if (!isDragging && (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) || Input::IsKeyPressed(Key::F2))
|
||||
{
|
||||
isRenaming = true;
|
||||
}
|
||||
|
||||
if (!isRenaming && Selection.Type == EditorSelectionType::Entity && Input::IsKeyPressed(Key::DELETE_KEY))
|
||||
{
|
||||
QueueDeletion = Selection.Entity;
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
{
|
||||
Selection = EditorSelection(e);
|
||||
|
||||
Nuake::Entity entity = Selection.Entity;
|
||||
if (entity.HasComponent<CameraComponent>())
|
||||
{
|
||||
// Moves the editor camera to the camera position and direction.
|
||||
if (ImGui::Selectable("Focus camera"))
|
||||
{
|
||||
Ref<EditorCamera> editorCam = virtualScene->m_EditorCamera;
|
||||
Vector3 camDirection = entity.GetComponent<CameraComponent>().CameraInstance->GetDirection();
|
||||
camDirection.z *= -1.0f;
|
||||
editorCam->SetTransform(glm::inverse(entity.GetComponent<TransformComponent>().GetGlobalTransform()));
|
||||
}
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
if (ImGui::Selectable("Remove"))
|
||||
{
|
||||
QueueDeletion = e;
|
||||
}
|
||||
|
||||
if (entity.GetComponent<ParentComponent>().HasParent && ImGui::Selectable("Move to root"))
|
||||
{
|
||||
auto& parentComp = Selection.Entity.GetComponent<ParentComponent>();
|
||||
if (parentComp.HasParent)
|
||||
{
|
||||
auto& parentParentComp = parentComp.Parent.GetComponent<ParentComponent>();
|
||||
parentParentComp.RemoveChildren(entity);
|
||||
parentComp.HasParent = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Selectable("Save entity as a new prefab"))
|
||||
{
|
||||
Ref<Prefab> newPrefab = Prefab::CreatePrefabFromEntity(Selection.Entity);
|
||||
std::string savePath = Nuake::FileDialog::SaveFile("*.prefab");
|
||||
if (!String::EndsWith(savePath, ".prefab"))
|
||||
{
|
||||
savePath += ".prefab";
|
||||
}
|
||||
|
||||
if (!savePath.empty())
|
||||
{
|
||||
newPrefab->SaveAs(savePath);
|
||||
Selection.Entity.AddComponent<PrefabComponent>().PrefabInstance = newPrefab;
|
||||
}
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::TextColored(ImVec4(0.5, 0.5, 0.5, 1.0), "");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
bool hasScript = e.HasComponent<NetScriptComponent>();
|
||||
if (hasScript)
|
||||
{
|
||||
std::string scrollIcon = std::string(ICON_FA_SCROLL) + "##" + name;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
|
||||
if (ImGui::Button(scrollIcon.c_str(), { 40, 0 }))
|
||||
{
|
||||
auto& scriptComponent = e.GetComponent<NetScriptComponent>();
|
||||
if (!scriptComponent.ScriptPath.empty() && FileSystem::FileExists(scriptComponent.ScriptPath))
|
||||
{
|
||||
OS::OpenIn(FileSystem::RelativeToAbsolute(scriptComponent.ScriptPath));
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
bool& isVisible = e.GetComponent<VisibilityComponent>().Visible;
|
||||
std::string visibilityIcon = isVisible ? ICON_FA_EYE : ICON_FA_EYE_SLASH;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
|
||||
if (ImGui::Button(visibilityIcon.c_str(), { 40, 0 }))
|
||||
{
|
||||
isVisible = !isVisible;
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
if (open)
|
||||
{
|
||||
// Caching list to prevent deletion while iterating.
|
||||
std::vector<Nuake::Entity> childrens = parent.Children;
|
||||
for (auto& c : childrens)
|
||||
DrawEntityTree(c);
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
//ImGui::PopFont();
|
||||
}
|
||||
|
||||
void PrefabEditorWindow::Save()
|
||||
{
|
||||
Ref<Prefab> newPrefab = Prefab::CreatePrefabFromEntity(prefab->Root);
|
||||
newPrefab->Path = prefab->Path;
|
||||
newPrefab->SaveAs(newPrefab->Path);
|
||||
}
|
||||
53
Editor/src/Windows/PrefabEditor/PrefabEditorWindow.h
Normal file
53
Editor/src/Windows/PrefabEditor/PrefabEditorWindow.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
|
||||
#include "../EditorSelectionPanel.h"
|
||||
#include <src/Vendors/imgui/ImGuizmo.h>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class Prefab;
|
||||
class Scene;
|
||||
class FrameBuffer;
|
||||
class Texture;
|
||||
class Entity;
|
||||
}
|
||||
|
||||
class PrefabEditorWindow
|
||||
{
|
||||
public:
|
||||
PrefabEditorWindow(Ref<Nuake::Prefab> prefab);
|
||||
~PrefabEditorWindow() {
|
||||
ASSERT(false);
|
||||
};
|
||||
|
||||
void Update(float ts);
|
||||
void Draw();
|
||||
|
||||
private:
|
||||
Ref<Nuake::Prefab> prefab;
|
||||
Ref<Nuake::Scene> virtualScene;
|
||||
Ref<Nuake::FrameBuffer> viewportFramebuffer;
|
||||
Ref<Nuake::Texture> viewportTexture;
|
||||
|
||||
bool isViewportFocused;
|
||||
bool isHoveringViewport;
|
||||
bool isRenaming;
|
||||
bool isInitialized = false;
|
||||
|
||||
Scope<EditorSelectionPanel> SelectionPanel;
|
||||
EditorSelection Selection;
|
||||
Nuake::Entity QueueDeletion;
|
||||
ImGuizmo::OPERATION CurrentOperation = ImGuizmo::TRANSLATE;
|
||||
ImGuizmo::MODE CurrentMode = ImGuizmo::WORLD;
|
||||
bool UseSnapping = true;
|
||||
Nuake::Vector3 CurrentSnapping = Nuake::Vector3{ 0.0f, 0.0f, 0.0f };
|
||||
bool isControllingCamera = false;
|
||||
private:
|
||||
void DrawViewportWindow();
|
||||
void DrawOverlay();
|
||||
void RenderScene();
|
||||
void DrawEntityTree(Nuake::Entity e);
|
||||
void Save();
|
||||
};
|
||||
@@ -1,9 +1,12 @@
|
||||
#include "ProjectInterface.h"
|
||||
#include <src/Vendors/imgui/imgui.h>
|
||||
|
||||
#include "Engine.h"
|
||||
#include "src/Core/FileSystem.h"
|
||||
#include <src/FileSystem/FileDialog.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Scripting/ScriptingEngineNet.h>
|
||||
#include <src/Scripting/ScriptingEngineNet.h>
|
||||
|
||||
#include <src/Vendors/imgui/imgui.h>
|
||||
//#include "ImGuiTextHelper.h"
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "ProjectSettingsWindow.h"
|
||||
#include <imgui/imgui.h>
|
||||
#include "../../Misc/InterfaceFonts.h"
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/FileSystem/FileDialog.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include "../EditorInterface.h"
|
||||
#include "../../Commands/Commands/Commands.h"
|
||||
#include <src/Audio/AudioManager.h>
|
||||
@@ -14,23 +15,24 @@ ProjectSettingsCategoryWindowGeneral::ProjectSettingsCategoryWindowGeneral(Ref<N
|
||||
|
||||
void ProjectSettingsCategoryWindowGeneral::Draw()
|
||||
{
|
||||
using namespace Nuake;
|
||||
//ImGui::InputText("Project Name", &m_Project->Name);
|
||||
//ImGui::InputTextMultiline("Project Description", &m_Project->Description);
|
||||
ImGui::InputText("Project Name", &m_Project->Name);
|
||||
|
||||
if (ImGui::Button("Locate"))
|
||||
{
|
||||
const std::string& locationPath = Nuake::FileDialog::OpenFile("TrenchBroom (.exe)\0TrenchBroom.exe\0");
|
||||
ImGui::InputTextMultiline("Project Description", &m_Project->Description);
|
||||
|
||||
if (ImGui::Button("Locate"))
|
||||
{
|
||||
const std::string& locationPath = Nuake::FileDialog::OpenFile("TrenchBroom (.exe)\0TrenchBroom.exe\0");
|
||||
|
||||
if (!locationPath.empty())
|
||||
{
|
||||
m_Project->TrenchbroomPath = locationPath;
|
||||
}
|
||||
}
|
||||
if (!locationPath.empty())
|
||||
{
|
||||
m_Project->TrenchbroomPath = locationPath;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::ColorEdit4("Primary Color", &m_Project->Settings.PrimaryColor.r);
|
||||
|
||||
//ImGui::InputText("Trenchbroom Path", &m_Project->TrenchbroomPath);
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("Trenchbroom Path", &m_Project->TrenchbroomPath);
|
||||
|
||||
ImGui::ColorEdit4("Primary Color", &m_Project->Settings.PrimaryColor.r);
|
||||
}
|
||||
|
||||
ProjectSettingsWindow::ProjectSettingsWindow()
|
||||
@@ -63,7 +65,7 @@ void ProjectSettingsWindow::Draw()
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints({600, 300}, {1280, 720});
|
||||
ImGui::SetNextWindowSizeConstraints({800, 400}, {1280, 720});
|
||||
if (ImGui::Begin("Project Settings", &m_DisplayWindow, ImGuiWindowFlags_NoDocking))
|
||||
{
|
||||
ImVec4* colors = ImGui::GetStyle().Colors;
|
||||
@@ -121,7 +123,7 @@ ProjectSettingsCategoryWindowViewport::ProjectSettingsCategoryWindowViewport(Ref
|
||||
|
||||
void ProjectSettingsCategoryWindowViewport::Draw()
|
||||
{
|
||||
ImGui::DragFloat("Outline Radius", &m_Project->Settings.OutlineRadius, 0.1f, 1.0f, 10.0f);
|
||||
ImGui::DragFloat("Outline Radius", &m_Project->Settings.OutlineRadius, 0.1f, 1.0f, 90.0f);
|
||||
ImGui::DragFloat("Gizmo Size", &m_Project->Settings.GizmoSize, 0.01f, 0.05f, 0.5f);
|
||||
ImGui::Separator();
|
||||
ImGui::Checkbox("Smooth Camera", &m_Project->Settings.SmoothCamera);
|
||||
@@ -182,11 +184,11 @@ void ProjectSettingsCategoryPhysics::Draw()
|
||||
Engine::SetPhysicsStep(Engine::GetProject()->Settings.PhysicsStep);
|
||||
}
|
||||
|
||||
ImGui::DragInt("Maximum SubSteps", &Engine::GetProject()->Settings.MaxPhysicsSubStep, 1.0f, 8.0f, 128);
|
||||
ImGui::DragInt("Maximum SubSteps", &Engine::GetProject()->Settings.MaxPhysicsSubStep, 1, 8, 128);
|
||||
|
||||
ImGui::DragInt("Maximum Bodies", &Engine::GetProject()->Settings.MaxPhysicsBodies, 1.0f, 256.0f, 8000);
|
||||
ImGui::DragInt("Maximum Body Pair", &Engine::GetProject()->Settings.MaxPhysicsBodyPair, 1.0f, 256.0f, 4096.0f);
|
||||
ImGui::DragInt("Maximum Contact Constraint", &Engine::GetProject()->Settings.MaxPhysicsContactConstraints, 1.0f, 256.0f, 4096.0f);
|
||||
ImGui::DragInt("Maximum Bodies", &Engine::GetProject()->Settings.MaxPhysicsBodies, 1.0f, 256, 8000);
|
||||
ImGui::DragInt("Maximum Body Pair", &Engine::GetProject()->Settings.MaxPhysicsBodyPair, 1.0f, 256, 4096);
|
||||
ImGui::DragInt("Maximum Contact Constraint", &Engine::GetProject()->Settings.MaxPhysicsContactConstraints, 1.0f, 256, 4096);
|
||||
}
|
||||
|
||||
ProjectSettingsCategoryAudio::ProjectSettingsCategoryAudio(Ref<Nuake::Project> project) :
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#include "TrenchbroomConfiguratorWindow.h"
|
||||
|
||||
#include <Engine.h>
|
||||
#include <src/Resource/Project.h>
|
||||
#include <src/UI/ImUI.h>
|
||||
#include <src/Core/OS.h>
|
||||
#include <src/Rendering/Textures/TextureManager.h>
|
||||
#include <src/Resource/Prefab.h>
|
||||
|
||||
|
||||
void TrenchbroomConfiguratorWindow::Update()
|
||||
{
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ void UIDemoWindow::Draw()
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
UI::BeginWindow("UI Demo");
|
||||
{
|
||||
UI::PrimaryButton("Primary Button");
|
||||
UI::SecondaryButton("Secondary Button");
|
||||
UI::FloatSlider("Float slider", floatSlider);
|
||||
UI::CheckBox("Checkbox", checkbox);
|
||||
}
|
||||
UI::EndWindow();
|
||||
//UI::BeginWindow("UI Demo");
|
||||
//{
|
||||
// UI::PrimaryButton("Primary Button");
|
||||
// UI::SecondaryButton("Secondary Button");
|
||||
// UI::FloatSlider("Float slider", floatSlider);
|
||||
// UI::CheckBox("Checkbox", checkbox);
|
||||
//}
|
||||
//UI::EndWindow();
|
||||
}
|
||||
@@ -5,7 +5,8 @@
|
||||
#include "../Misc/InterfaceFonts.h"
|
||||
|
||||
#include <Engine.h>
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/FileSystem/FileDialog.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Resource/Project.h>
|
||||
#include <src/Core/Logger.h>
|
||||
#include <src/Rendering/Textures/TextureManager.h>
|
||||
@@ -80,6 +81,11 @@ namespace Nuake
|
||||
|
||||
ParseRecentFile();
|
||||
|
||||
if (_Projects.size() > 0)
|
||||
{
|
||||
SelectedProject = 0;
|
||||
}
|
||||
|
||||
// Load Nuake logo
|
||||
_NuakeLogo = TextureManager::Get()->GetTexture(NUAKE_LOGO_PATH);
|
||||
}
|
||||
@@ -109,8 +115,41 @@ namespace Nuake
|
||||
Engine::GetCurrentWindow()->SetTitle("Nuake Engine - Editing " + project->Name);
|
||||
}
|
||||
|
||||
void WelcomeWindow::ImportProject(const std::string& file)
|
||||
{
|
||||
if (file != "" && String::EndsWith(file, ".project"))
|
||||
{
|
||||
// Prevent importing the same project twice in the list
|
||||
bool alreadyContainsProject = false;
|
||||
for (auto& p : _Projects)
|
||||
{
|
||||
if (p.Path == file)
|
||||
{
|
||||
alreadyContainsProject = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyContainsProject)
|
||||
{
|
||||
_Projects.push_back(ProjectPreview(file));
|
||||
SaveRecentFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WelcomeWindow::Draw()
|
||||
{
|
||||
if (!queuedRemovalPath.empty())
|
||||
{
|
||||
std::erase_if(_Projects, [&](ProjectPreview preview)
|
||||
{
|
||||
return preview.Path == queuedRemovalPath;
|
||||
});
|
||||
|
||||
queuedRemovalPath = "";
|
||||
SaveRecentFile();
|
||||
}
|
||||
|
||||
// Make viewport fullscreen
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
@@ -144,6 +183,7 @@ namespace Nuake
|
||||
|
||||
DrawRightControls();
|
||||
ImGui::SameLine();
|
||||
|
||||
DrawRecentProjectsSection();
|
||||
|
||||
ImGui::End();
|
||||
@@ -157,36 +197,30 @@ namespace Nuake
|
||||
ImVec2 projectsWindowSize = ImGui::GetContentRegionAvail();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 0));
|
||||
ImGui::BeginChild("Projects", projectsWindowSize, false);
|
||||
ImGui::BeginChild("Projects", projectsWindowSize);
|
||||
{
|
||||
//ImGui::Dummy({ 4, 4 });
|
||||
//ImGui::SameLine();
|
||||
//{
|
||||
// auto font = UIFont(Bold);
|
||||
// ImGui::Text("Recent Projects");
|
||||
//}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
for (uint32_t i = 0; i < std::size(_Projects); i++)
|
||||
{
|
||||
DrawProjectItem(i);
|
||||
}
|
||||
|
||||
const float itemHeight = 100.0f;
|
||||
ImGui::Dummy({ 1, 4 });
|
||||
ImGui::SameLine();
|
||||
const float itemHeight = 60.0f;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::Button("Import an existing project", ImVec2(ImGui::GetContentRegionAvail().x, itemHeight)))
|
||||
if (UI::SecondaryButton("Import or Drag a Project", Vector2(ImGui::GetContentRegionAvail().x - 8, itemHeight)))
|
||||
{
|
||||
const std::string path = FileDialog::OpenFile("Project file(.project)\0*.project\0");
|
||||
if (path != "" && String::EndsWith(path, ".project"))
|
||||
{
|
||||
// Prevent importing the same project twice in the list
|
||||
bool alreadyContainsProject = false;
|
||||
for (auto& p : _Projects)
|
||||
{
|
||||
if (p.Path == path)
|
||||
{
|
||||
alreadyContainsProject = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyContainsProject)
|
||||
{
|
||||
_Projects.push_back(ProjectPreview(path));
|
||||
}
|
||||
}
|
||||
ImportProject(path);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
@@ -195,8 +229,10 @@ namespace Nuake
|
||||
|
||||
void WelcomeWindow::DrawProjectItem(const uint32_t itemIndex)
|
||||
{
|
||||
ImGui::Dummy({ 4, 4 });
|
||||
ImGui::SameLine();
|
||||
const ProjectPreview& project = _Projects[itemIndex];
|
||||
const uint32_t itemHeight = 120;
|
||||
const uint32_t itemHeight = 56;
|
||||
const float cursorYStart = ImGui::GetCursorPosY();
|
||||
|
||||
const std::string selectableName = "##" + std::to_string(itemIndex);
|
||||
@@ -210,7 +246,24 @@ namespace Nuake
|
||||
draw_list->ChannelsSetCurrent(1);
|
||||
|
||||
//ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0, 0, 0, 0));
|
||||
bool result = ImGui::Selectable(selectableName.c_str(), SelectedProject == itemIndex, ImGuiSelectableFlags_AllowOverlap | ImGuiSelectableFlags_AllowDoubleClick, ImVec2(ImGui::GetContentRegionAvail().x, itemHeight));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.25, 0.25, 0.5, 0.0));
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.25, 0.25, 0.5, 0.0));
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.25, 0.25, 0.5, 0.0));
|
||||
bool result = ImGui::Selectable(selectableName.c_str(), SelectedProject == itemIndex, ImGuiSelectableFlags_AllowOverlap | ImGuiSelectableFlags_AllowDoubleClick, ImVec2(ImGui::GetContentRegionAvail().x - 12, itemHeight));
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
if (ImGui::BeginPopupContextWindow(selectableName.c_str()))
|
||||
{
|
||||
if (ImGui::MenuItem("Remove from list"))
|
||||
{
|
||||
queuedRemovalPath = _Projects[itemIndex].Path;
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
|
||||
if (result)
|
||||
{
|
||||
SelectedProject = itemIndex;
|
||||
@@ -220,12 +273,23 @@ namespace Nuake
|
||||
{
|
||||
SaveRecentFile();
|
||||
|
||||
queuedProjectPath = _Projects[SelectedProject].Path;
|
||||
queuedProjectPath = _Projects[itemIndex].Path;
|
||||
}
|
||||
|
||||
//ImGui::PopStyleColor();
|
||||
|
||||
draw_list->ChannelsMerge();
|
||||
ImU32 color = IM_COL32(63, 63, 66, 128);
|
||||
if (isSelected)
|
||||
{
|
||||
color = IM_COL32(63, 69, 79, 255);
|
||||
}
|
||||
else if (ImGui::IsItemHovered())
|
||||
{
|
||||
color = IM_COL32(20, 20, 20, 128);
|
||||
}
|
||||
|
||||
if (isSelected && ImGui::IsKeyPressed(ImGuiKey_Delete))
|
||||
{
|
||||
queuedRemovalPath = _Projects[SelectedProject].Path;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
@@ -233,33 +297,62 @@ namespace Nuake
|
||||
}
|
||||
//ImGui::PopStyleColor();
|
||||
|
||||
const ImVec2 padding = ImVec2(25.0f, 20.0f);
|
||||
const ImVec2 iconSize = ImVec2(100, 100);
|
||||
ImGui::SetCursorPos(ImVec2(padding.x / 2.0, padding.y / 2.0) + ImVec2(0, cursorYStart));
|
||||
draw_list->ChannelsSetCurrent(0);
|
||||
ImVec2 p_min = ImGui::GetItemRectMin();
|
||||
ImVec2 p_max = ImGui::GetItemRectMax();
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(p_min, p_max, color, 4.0f);
|
||||
|
||||
draw_list->ChannelsMerge();
|
||||
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
const ImVec2 padding = ImVec2(16.0f, 0.0f);
|
||||
const ImVec2 iconSize = ImVec2(54, 54.0f);
|
||||
ImGui::SetCursorPos(ImVec2(padding.x / 2.0, padding.y / 2.0) + ImVec2(4, cursorYStart));
|
||||
|
||||
if (project.ProjectIcon)
|
||||
{
|
||||
ImGui::Image((ImTextureID)project.ProjectIcon->GetID(), iconSize, ImVec2(0, 1), ImVec2(1, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Image((void*)Nuake::TextureManager::Get()->GetTexture("Resources/Images/cube.png")->GetID(), iconSize, ImVec2(0, 1), ImVec2(1, 0));
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(padding.x + iconSize.x + padding.x);
|
||||
ImGui::SetCursorPosX(padding.x + iconSize.x);
|
||||
|
||||
ImGui::SetCursorPosX(padding.x + iconSize.x + padding.x);
|
||||
ImGui::SetCursorPosY(cursorYStart + padding.y);
|
||||
ImGui::SetCursorPosY(cursorYStart + 8.0f);
|
||||
{
|
||||
UIFont boldfont = UIFont(Fonts::LargeBold);
|
||||
ImGui::Text(project.Name.c_str());
|
||||
UIFont boldfont = UIFont(Fonts::Normal);
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ImGui::TextColored(ImVec4(119.0f / 255.0f, 187.0f / 255.0f, 1, 255.0f), project.Name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text(project.Name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SetCursorPosY(cursorYStart + padding.y + 34.f);
|
||||
ImGui::SetCursorPosY(cursorYStart + 28.f);
|
||||
{
|
||||
ImGui::SetCursorPosX(padding.x + iconSize.x + padding.x);
|
||||
UIFont boldfont = UIFont(Fonts::Bold);
|
||||
ImGui::Text(project.Description.c_str());
|
||||
ImGui::SetCursorPosX(padding.x + iconSize.x);
|
||||
UIFont boldfont = UIFont(Fonts::Normal);
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ImGui::TextColored(ImVec4(119.0f / 255.0f, 187.0f / 255.0f, 1, 255.0f), (ICON_FA_INFO_CIRCLE + std::string(" ") + project.Description).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::TextColored(ImVec4(1, 1, 1, 0.4), (ICON_FA_INFO_CIRCLE + std::string(" ") + project.Description).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SetCursorPosY(cursorYStart + itemHeight + 32.0f);
|
||||
ImGui::SetCursorPosY(cursorYStart + itemHeight + 4.0f);
|
||||
ImGui::Dummy({ 4, 2 });
|
||||
}
|
||||
|
||||
void WelcomeWindow::DrawRightControls()
|
||||
@@ -275,56 +368,17 @@ namespace Nuake
|
||||
const ImVec2 buttonSize = ImVec2(ImGui::GetContentRegionAvail().x, buttonHeight);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.14f, 0.5f));
|
||||
const std::string buttonLabel = std::string(ICON_FA_FOLDER_PLUS) + " New Game Project...";
|
||||
const std::string buttonLabel = std::string(ICON_FA_FOLDER_PLUS) + " New Project...";
|
||||
if (Nuake::UI::PrimaryButton(buttonLabel.c_str(), { buttonSize.x, buttonSize.y }))
|
||||
{
|
||||
_Editor->isCreatingNewProject = true;
|
||||
//
|
||||
|
||||
//std::string selectedProject = FileDialog::SaveFile("Project file\0*.project");
|
||||
//
|
||||
//if (!selectedProject.empty())
|
||||
//{
|
||||
// if(!String::EndsWith(selectedProject, ".project"))
|
||||
// selectedProject += ".project";
|
||||
//
|
||||
// auto backslashSplits = String::Split(selectedProject, '\\');
|
||||
// auto fileName = backslashSplits[backslashSplits.size() - 1];
|
||||
|
||||
// std::string finalPath = String::Split(selectedProject, '.')[0];
|
||||
|
||||
// if (String::EndsWith(fileName, ".project"))
|
||||
// {
|
||||
// // We need to create a folder
|
||||
// if (const auto& dirPath = finalPath;
|
||||
// !std::filesystem::create_directory(dirPath))
|
||||
// {
|
||||
// // Should we continue?
|
||||
// Logger::Log("Failed creating project directory: " + dirPath);
|
||||
// }
|
||||
|
||||
// finalPath += "\\" + fileName;
|
||||
// }
|
||||
|
||||
// auto project = Project::New(String::Split(fileName, '.')[0], "no description", finalPath);
|
||||
// Engine::LoadProject(project);
|
||||
// Engine::LoadScene(Scene::New());
|
||||
// project->Save();
|
||||
|
||||
// auto projectPreview = ProjectPreview();
|
||||
// projectPreview.Name = project->Name;
|
||||
// projectPreview.Description = project->Description;
|
||||
// projectPreview.Path = project->FullPath;
|
||||
// projectPreview.ProjectIcon = nullptr;
|
||||
// _Projects.push_back(projectPreview);
|
||||
//}
|
||||
}
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.16f, 0.5f));
|
||||
const std::string buttonLabelOpen = std::string(ICON_FA_FOLDER_OPEN) + " Load Selected Project";
|
||||
const std::string buttonLabelOpen = std::string(ICON_FA_FOLDER_OPEN) + " Load Project";
|
||||
|
||||
bool hasProjectSelected = false;
|
||||
if (SelectedProject < std::size(_Projects) && SelectedProject >= 0)
|
||||
@@ -355,10 +409,10 @@ namespace Nuake
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.09f, 0.5f));
|
||||
const std::string buttonLabelDoc = std::string(ICON_FA_EXTERNAL_LINK_SQUARE_ALT) + " Documentation";
|
||||
const std::string buttonLabelDoc = std::string(ICON_FA_EXTERNAL_LINK_SQUARE_ALT) + " Documentation";
|
||||
if (Nuake::UI::SecondaryButton(buttonLabelDoc, { buttonSize.x, buttonSize.y }))
|
||||
{
|
||||
OS::OpenURL("https://nuake.readthedocs.io/en/latest/index.html");
|
||||
OS::OpenURL("https://docs.readthedocs.io/en/latest/index.html");
|
||||
}
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Nuake
|
||||
int32_t SelectedProject = -1;
|
||||
std::vector<ProjectPreview> _Projects;
|
||||
std::string queuedProjectPath;
|
||||
std::string queuedRemovalPath;
|
||||
|
||||
public:
|
||||
WelcomeWindow(Nuake::EditorInterface* editor);
|
||||
~WelcomeWindow() = default;
|
||||
@@ -50,6 +52,9 @@ namespace Nuake
|
||||
|
||||
bool IsProjectQueued() const { return !queuedProjectPath.empty(); };
|
||||
void LoadQueuedProject();
|
||||
|
||||
void ImportProject(const std::string& file);
|
||||
|
||||
private:
|
||||
void DrawRecentProjectsSection();
|
||||
void DrawProjectItem(const uint32_t projectPreview);
|
||||
|
||||
5
Editor/test.html
Normal file
5
Editor/test.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<div>
|
||||
<div class="main">
|
||||
<p>Hello</p>
|
||||
</div>
|
||||
</div>
|
||||
268
Nuake/Engine.cpp
268
Nuake/Engine.cpp
@@ -1,63 +1,125 @@
|
||||
#include "Engine.h"
|
||||
|
||||
#include "src/Scene/Scene.h"
|
||||
#include "src/Resource/Project.h"
|
||||
#include "src/Physics/PhysicsManager.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "src/AI/NavManager.h"
|
||||
#include "src/Audio/AudioManager.h"
|
||||
#include "src/Core/FileSystem.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include "src/Core/Input.h"
|
||||
#include "src/Rendering/Renderer.h"
|
||||
#include "src/Rendering/Renderer2D.h"
|
||||
#include "src/Scripting/ScriptingEngine.h"
|
||||
#include "src/Scripting/ScriptingEngineNet.h"
|
||||
#include "src/Threading/JobSystem.h"
|
||||
#include "src/Core/RegisterCoreTypes.h"
|
||||
#include "src/Modules/Modules.h"
|
||||
#include "src/Subsystems/EngineSubsystemScriptable.h"
|
||||
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <imgui/imgui_impl_glfw.h>
|
||||
#include <imgui/imgui_impl_opengl3.h>
|
||||
#include <Tracy.hpp>
|
||||
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
Ref<Project> Engine::currentProject;
|
||||
Ref<Window> Engine::currentWindow;
|
||||
std::string Engine::queuedScene = "";
|
||||
|
||||
Ref<Project> Engine::s_CurrentProject;
|
||||
Ref<Window> Engine::s_CurrentWindow;
|
||||
GameState Engine::gameState = GameState::Stopped;
|
||||
|
||||
GameState Engine::s_GameState = GameState::Stopped;
|
||||
|
||||
float Engine::s_LastFrameTime = 0.0f;
|
||||
float Engine::s_FixedUpdateRate = 1.0f / 90.0f;
|
||||
float Engine::s_FixedUpdateDifference = 0.f;
|
||||
float Engine::s_Time = 0.f;
|
||||
Timestep Engine::s_TimeStep = 0.f;
|
||||
float Engine::s_TimeScale = 1.0f;
|
||||
float Engine::lastFrameTime = 0.0f;
|
||||
float Engine::fixedUpdateRate = 1.0f / 90.0f;
|
||||
float Engine::fixedUpdateDifference = 0.f;
|
||||
float Engine::time = 0.f;
|
||||
Timestep Engine::timeStep = 0.f;
|
||||
float Engine::timeScale = 1.0f;
|
||||
|
||||
void Engine::Init()
|
||||
{
|
||||
//Window::Get()->OnWindowSetScene().AddStatic(&Engine::OnWindowSetScene);
|
||||
|
||||
ScriptingEngineNet::Get().OnGameAssemblyLoaded().AddStatic(&Engine::OnScriptingEngineGameAssemblyLoaded);
|
||||
|
||||
AudioManager::Get().Initialize();
|
||||
PhysicsManager::Get().Init();
|
||||
NavManager::Get().Initialize();
|
||||
|
||||
// Creates the window
|
||||
s_CurrentWindow = Window::Get();
|
||||
currentWindow = Window::Get();
|
||||
|
||||
Input::Init();
|
||||
Renderer2D::Init();
|
||||
Logger::Log("Engine initialized");
|
||||
|
||||
RegisterCoreTypes::RegisterCoreComponents();
|
||||
|
||||
Modules::StartupModules();
|
||||
|
||||
InitializeCoreSubsystems();
|
||||
}
|
||||
|
||||
void Engine::Tick()
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
JobSystem::Get().Update();
|
||||
|
||||
s_Time = static_cast<float>(glfwGetTime());
|
||||
s_TimeStep = s_Time - s_LastFrameTime;
|
||||
s_LastFrameTime = s_Time;
|
||||
time = static_cast<float>(glfwGetTime());
|
||||
timeStep = time - lastFrameTime;
|
||||
lastFrameTime = time;
|
||||
|
||||
if (Engine::IsPlayMode())
|
||||
{
|
||||
if (!queuedScene.empty())
|
||||
{
|
||||
Ref<Scene> nextScene = Scene::New();
|
||||
if (FileSystem::FileExists(queuedScene))
|
||||
{
|
||||
const std::string& fileContent = FileSystem::ReadFile(queuedScene);
|
||||
nextScene->Path = queuedScene;
|
||||
nextScene->Deserialize(json::parse(fileContent));
|
||||
|
||||
// Uninit current scene
|
||||
GetCurrentScene()->OnExit();
|
||||
|
||||
// Set new scene
|
||||
SetCurrentScene(nextScene);
|
||||
|
||||
// Init new scene
|
||||
PhysicsManager::Get().ReInit();
|
||||
GetCurrentScene()->OnInit();
|
||||
|
||||
queuedScene = "";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
float scaledTimeStep = timeStep * timeScale;
|
||||
|
||||
// Tick all subsystems
|
||||
if (Engine::IsPlayMode())
|
||||
{
|
||||
for (auto subsystem : subsystems)
|
||||
{
|
||||
if (subsystem == nullptr)
|
||||
continue;
|
||||
|
||||
if (subsystem->CanEverTick())
|
||||
{
|
||||
subsystem->Tick(scaledTimeStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dont update if no scene is loaded.
|
||||
if (s_CurrentWindow->GetScene())
|
||||
if (currentWindow->GetScene())
|
||||
{
|
||||
float scaledTimeStep = s_TimeStep * s_TimeScale;
|
||||
s_CurrentWindow->Update(scaledTimeStep);
|
||||
currentWindow->Update(scaledTimeStep);
|
||||
|
||||
// Play mode update all the entities, Editor does not.
|
||||
if (!Engine::IsPlayMode())
|
||||
@@ -65,32 +127,33 @@ namespace Nuake
|
||||
GetCurrentScene()->EditorUpdate(scaledTimeStep);
|
||||
}
|
||||
|
||||
s_FixedUpdateDifference += s_TimeStep;
|
||||
fixedUpdateDifference += timeStep;
|
||||
|
||||
// Fixed update
|
||||
while (s_FixedUpdateDifference >= s_FixedUpdateRate)
|
||||
while (fixedUpdateDifference >= fixedUpdateRate)
|
||||
{
|
||||
s_CurrentWindow->FixedUpdate(s_FixedUpdateRate * s_TimeScale);
|
||||
currentWindow->FixedUpdate(fixedUpdateRate * timeScale);
|
||||
|
||||
s_FixedUpdateDifference -= s_FixedUpdateRate;
|
||||
fixedUpdateDifference -= fixedUpdateRate;
|
||||
}
|
||||
|
||||
Input::Update();
|
||||
AudioManager::Get().AudioUpdate();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Engine::EnterPlayMode()
|
||||
{
|
||||
s_LastFrameTime = (float)glfwGetTime(); // Reset timestep timer.
|
||||
lastFrameTime = (float)glfwGetTime(); // Reset timestep timer.
|
||||
|
||||
// Dont trigger init if already in player mode.
|
||||
if (GetGameState() == GameState::Playing)
|
||||
if (GetGameState() == GameState::Playing || GetGameState() == GameState::Loading)
|
||||
{
|
||||
Logger::Log("Cannot enter play mode if is already in play mode.", "engine", WARNING);
|
||||
Logger::Log("Cannot enter play mode if is already in play mode or is loading.", "engine", WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
SetGameState(GameState::Loading);
|
||||
|
||||
PhysicsManager::Get().ReInit();
|
||||
|
||||
@@ -108,22 +171,28 @@ namespace Nuake
|
||||
void Engine::ExitPlayMode()
|
||||
{
|
||||
// Dont trigger exit if already not in play mode.
|
||||
if (s_GameState != GameState::Stopped)
|
||||
if (gameState != GameState::Stopped)
|
||||
{
|
||||
GetCurrentScene()->OnExit();
|
||||
Input::ShowMouse();
|
||||
s_GameState = GameState::Stopped;
|
||||
gameState = GameState::Stopped;
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::Draw()
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
RenderCommand::Clear();
|
||||
|
||||
// Start imgui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
{
|
||||
ZoneScopedN("ImGui New Frame");
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
// Draw scene
|
||||
Window::Get()->Draw();
|
||||
@@ -131,6 +200,7 @@ namespace Nuake
|
||||
|
||||
void Engine::EndDraw()
|
||||
{
|
||||
ZoneScoped;
|
||||
Window::Get()->EndDraw();
|
||||
}
|
||||
|
||||
@@ -141,34 +211,146 @@ namespace Nuake
|
||||
|
||||
Ref<Scene> Engine::GetCurrentScene()
|
||||
{
|
||||
if (s_CurrentWindow)
|
||||
if (currentWindow)
|
||||
{
|
||||
return s_CurrentWindow->GetScene();
|
||||
return currentWindow->GetScene();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Engine::LoadScene(Ref<Scene> scene)
|
||||
bool Engine::SetCurrentScene(Ref<Scene> scene)
|
||||
{
|
||||
return s_CurrentWindow->SetScene(scene);
|
||||
return currentWindow->SetScene(scene);
|
||||
}
|
||||
|
||||
bool Engine::QueueSceneSwitch(const std::string& scenePath)
|
||||
{
|
||||
if (!IsPlayMode())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
queuedScene = scenePath;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Ref<Project> Engine::GetProject()
|
||||
{
|
||||
return s_CurrentProject;
|
||||
return currentProject;
|
||||
}
|
||||
|
||||
Ref<EngineSubsystemScriptable> Engine::GetScriptedSubsystem(const std::string& subsystemName)
|
||||
{
|
||||
if (scriptedSubsystemMap.contains(subsystemName))
|
||||
{
|
||||
return scriptedSubsystemMap[subsystemName];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Ref<EngineSubsystemScriptable> Engine::GetScriptedSubsystem(const int subsystemId)
|
||||
{
|
||||
if (subsystemId >= subsystems.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return std::reinterpret_pointer_cast<EngineSubsystemScriptable>(subsystems[subsystemId]);
|
||||
}
|
||||
|
||||
void Engine::OnWindowSetScene(Ref<Scene> oldScene, Ref<Scene> newScene)
|
||||
{
|
||||
// Inform the subsystems that we are going to destroy/swap out the old scene
|
||||
for (auto subsystem : subsystems)
|
||||
{
|
||||
if (subsystem == nullptr)
|
||||
continue;
|
||||
|
||||
subsystem->OnScenePreDestroy(oldScene);
|
||||
}
|
||||
|
||||
// Hook into when the internal pieces of the scene are just about to be ready and when the scene is finally
|
||||
// ready to present (ie, all initialized and loaded).
|
||||
if (newScene != nullptr)
|
||||
{
|
||||
newScene->OnPreInitialize().AddStatic(&Engine::OnScenePreInitialize, newScene);
|
||||
newScene->OnPostInitialize().AddStatic(&Engine::OnScenePostInitialize, newScene);
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::InitializeCoreSubsystems()
|
||||
{
|
||||
}
|
||||
|
||||
void Engine::OnScriptingEngineGameAssemblyLoaded()
|
||||
{
|
||||
if (!Engine::IsPlayMode() && Engine::GetGameState() != GameState::Loading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
subsystems.clear();
|
||||
scriptedSubsystemMap.clear();
|
||||
|
||||
const Coral::ManagedAssembly& gameAssembly = ScriptingEngineNet::Get().GetGameAssembly();
|
||||
|
||||
const auto scriptTypeEngineSubsystem = gameAssembly.GetType("Nuake.Net.EngineSubsystem");
|
||||
|
||||
const auto& types = gameAssembly.GetTypes();
|
||||
for (const auto& type : types)
|
||||
{
|
||||
// Initialize all subsystems
|
||||
if (type->IsSubclassOf(scriptTypeEngineSubsystem))
|
||||
{
|
||||
const std::string typeName = std::string(type->GetFullName());
|
||||
Logger::Log("Creating Scripted Subsystem " + typeName);
|
||||
|
||||
Coral::ManagedObject scriptedSubsystem = type->CreateInstance();
|
||||
scriptedSubsystem.SetPropertyValue("EngineSubsystemID", subsystems.size());
|
||||
Ref<EngineSubsystemScriptable> subsystemScript = CreateRef<EngineSubsystemScriptable>(scriptedSubsystem);
|
||||
subsystems.push_back(subsystemScript);
|
||||
|
||||
scriptedSubsystemMap[typeName] = subsystemScript;
|
||||
|
||||
subsystemScript->Initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::OnScenePreInitialize(Ref<Scene> scene)
|
||||
{
|
||||
for (auto subsystem : subsystems)
|
||||
{
|
||||
if (subsystem == nullptr)
|
||||
continue;
|
||||
|
||||
subsystem->OnScenePreInitialize(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::OnScenePostInitialize(Ref<Scene> scene)
|
||||
{
|
||||
for (auto subsystem : subsystems)
|
||||
{
|
||||
if (subsystem == nullptr)
|
||||
continue;
|
||||
|
||||
subsystem->OnScenePostInitialize(scene);
|
||||
}
|
||||
}
|
||||
|
||||
bool Engine::LoadProject(Ref<Project> project)
|
||||
{
|
||||
s_CurrentProject = project;
|
||||
currentProject = project;
|
||||
|
||||
if (!Engine::LoadScene(s_CurrentProject->DefaultScene))
|
||||
if (!Engine::SetCurrentScene(currentProject->DefaultScene))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FileSystem::SetRootDirectory(FileSystem::GetParentPath(project->FullPath));
|
||||
ScriptingEngineNet::Get().Initialize();
|
||||
ScriptingEngineNet::Get().LoadProjectAssembly(project);
|
||||
|
||||
return true;
|
||||
@@ -176,6 +358,6 @@ namespace Nuake
|
||||
|
||||
Ref<Window> Engine::GetCurrentWindow()
|
||||
{
|
||||
return s_CurrentWindow;
|
||||
return currentWindow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Window.h"
|
||||
#include "src/Scene/Scene.h"
|
||||
#include "src/Resource/Project.h"
|
||||
#include "src/Core/Logger.h"
|
||||
|
||||
/* TODOS:
|
||||
|
||||
*/
|
||||
#include "src/Window.h"
|
||||
|
||||
// Welcome to the Nuake source code.
|
||||
namespace Nuake
|
||||
{
|
||||
class Project;
|
||||
class Scene;
|
||||
class EngineSubsystem;
|
||||
class EngineSubsystemScriptable;
|
||||
|
||||
enum GameState
|
||||
{
|
||||
Loading,
|
||||
Playing,
|
||||
Paused,
|
||||
Stopped
|
||||
@@ -21,19 +22,6 @@ namespace Nuake
|
||||
|
||||
class Engine
|
||||
{
|
||||
private:
|
||||
static Ref<Window> s_CurrentWindow;
|
||||
static Ref<Project> s_CurrentProject;
|
||||
static Ref<Scene> s_CurrentScene;
|
||||
|
||||
static GameState s_GameState;
|
||||
|
||||
static float s_LastFrameTime;
|
||||
static float s_FixedUpdateRate;
|
||||
static float s_FixedUpdateDifference;
|
||||
static float s_Time;
|
||||
static Timestep s_TimeStep;
|
||||
static float s_TimeScale;
|
||||
public:
|
||||
static void Init(); // Initialize the engine.
|
||||
static void Tick(); // Updates everything, called every frame.
|
||||
@@ -46,23 +34,57 @@ namespace Nuake
|
||||
static void Draw(); // Start new frame
|
||||
static void EndDraw(); // Swap buffer
|
||||
|
||||
static void SetGameState(GameState gameState) { s_GameState = gameState; }
|
||||
static GameState GetGameState() { return s_GameState; }
|
||||
static bool IsPlayMode() { return s_GameState == GameState::Playing; }
|
||||
static void SetGameState(GameState state) { gameState = state; }
|
||||
static GameState GetGameState() { return gameState; }
|
||||
static bool IsPlayMode() { return gameState == GameState::Playing; }
|
||||
|
||||
static inline float GetTime() { return s_Time; }
|
||||
static inline Timestep GetTimestep() { return s_TimeStep; }
|
||||
static inline void SetPhysicsStep(int amount) { s_FixedUpdateRate = 1.0f / static_cast<float>(amount); }
|
||||
static inline void SetTimeScale(float timeScale) { s_TimeScale = timeScale; }
|
||||
static inline float GetTimeScale() { return s_TimeScale; }
|
||||
static inline float GetTime() { return time; }
|
||||
static inline Timestep GetTimestep() { return timeStep; }
|
||||
static inline void SetPhysicsStep(int amount) { fixedUpdateRate = 1.0f / static_cast<float>(amount); }
|
||||
static inline float GetFixedTimeStep() { return fixedUpdateRate; }
|
||||
static inline void SetTimeScale(float timeScale) { timeScale = timeScale; }
|
||||
static inline float GetTimeScale() { return timeScale; }
|
||||
|
||||
static Ref<Window> GetCurrentWindow();
|
||||
|
||||
static bool LoadScene(Ref<Scene> scene);
|
||||
static bool SetCurrentScene(Ref<Scene> scene);
|
||||
static bool QueueSceneSwitch(const std::string& scene);
|
||||
static Ref<Scene> GetCurrentScene();
|
||||
|
||||
static bool LoadProject(Ref<Project> project);
|
||||
static Ref<Project> GetProject();
|
||||
|
||||
static Ref<EngineSubsystemScriptable> GetScriptedSubsystem(const std::string& subsystemName);
|
||||
static Ref<EngineSubsystemScriptable> GetScriptedSubsystem(const int subsystemId);
|
||||
|
||||
protected:
|
||||
static void OnWindowSetScene(Ref<Scene> oldScene, Ref<Scene> newScene);
|
||||
static void InitializeCoreSubsystems();
|
||||
|
||||
static void OnScriptingEngineUninitialize();
|
||||
static void OnScriptingEngineGameAssemblyLoaded();
|
||||
|
||||
static void OnScenePreInitialize(Ref<Scene> scene);
|
||||
static void OnScenePostInitialize(Ref<Scene> scene);
|
||||
|
||||
private:
|
||||
static Ref<Window> currentWindow;
|
||||
static Ref<Project> currentProject;
|
||||
static Ref<Scene> currentScene;
|
||||
static std::string queuedScene;
|
||||
|
||||
static inline std::vector<Ref<EngineSubsystem>> subsystems;
|
||||
static inline std::unordered_map<std::string, Ref<EngineSubsystemScriptable>> scriptedSubsystemMap;
|
||||
|
||||
static GameState gameState;
|
||||
|
||||
static float lastFrameTime;
|
||||
static float fixedUpdateRate;
|
||||
static float fixedUpdateDifference;
|
||||
static float time;
|
||||
static Timestep timeStep;
|
||||
static float timeScale;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Submodule Nuake/dependencies/Coral updated: 8bbf4998da...a1a9620d97
Submodule Nuake/dependencies/assimp updated: 9519a62dd2...97257a3bcc
@@ -11,12 +11,15 @@ project 'assimp'
|
||||
warnings 'Off'
|
||||
optimize 'Speed'
|
||||
|
||||
cppdialect "C++20"
|
||||
|
||||
includedirs {
|
||||
'build/',
|
||||
'build/assimp',
|
||||
'assimp/',
|
||||
'assimp/contrib/irrXML/',
|
||||
'assimp/contrib/unzip/',
|
||||
'assimp/contrib/utf8cpp/source',
|
||||
'assimp/contrib/zlib/',
|
||||
'assimp/contrib/rapidjson/include/',
|
||||
'assimp/code',
|
||||
@@ -32,6 +35,7 @@ project 'assimp'
|
||||
'assimp/code/Common/**',
|
||||
'assimp/code/PostProcessing/**',
|
||||
'assimp/code/Material/**',
|
||||
'assimp/code/Geometry/**',
|
||||
'assimp/code/CApi/**',
|
||||
-- Importers
|
||||
'assimp/code/AssetLib/Collada/**',
|
||||
@@ -99,7 +103,8 @@ project 'assimp'
|
||||
'ASSIMP_BUILD_NO_X_IMPORTER',
|
||||
'ASSIMP_BUILD_NO_X3D_IMPORTER',
|
||||
'ASSIMP_BUILD_NO_XGL_IMPORTER',
|
||||
'ASSIMP_BUILD_NO_IQM_IMPORTER'
|
||||
'ASSIMP_BUILD_NO_IQM_IMPORTER',
|
||||
'ASSIMP_BUILD_NO_USD_IMPORTER'
|
||||
}
|
||||
-- Exporters
|
||||
defines {
|
||||
@@ -119,6 +124,13 @@ project 'assimp'
|
||||
'ASSIMP_BUILD_NO_3MF_EXPORTER',
|
||||
'ASSIMP_BUILD_NO_ASSJSON_EXPORTER'
|
||||
}
|
||||
|
||||
-- When building any Visual Studio solution
|
||||
filter { "system:windows", "action:vs*"}
|
||||
flags
|
||||
{
|
||||
"MultiProcessorCompile",
|
||||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
runtime "Debug"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1
Nuake/dependencies/entt
Submodule
1
Nuake/dependencies/entt
Submodule
Submodule Nuake/dependencies/entt added at 156bc470ce
1
Nuake/dependencies/freetype
Submodule
1
Nuake/dependencies/freetype
Submodule
Submodule Nuake/dependencies/freetype added at ba47af32ba
91
Nuake/dependencies/freetype_p5.lua
Normal file
91
Nuake/dependencies/freetype_p5.lua
Normal file
@@ -0,0 +1,91 @@
|
||||
group "Dependencies"
|
||||
project "Freetype"
|
||||
location "freetype"
|
||||
kind "StaticLib"
|
||||
staticruntime "on"
|
||||
language "C"
|
||||
|
||||
targetdir ("freetype/bin/" .. outputdir .. "/%{prj.name}")
|
||||
objdir ("freetype/bin-obj/" .. outputdir .. "/%{prj.name}")
|
||||
|
||||
includedirs {
|
||||
'freetype/include/',
|
||||
'freetype/',
|
||||
"freetype/include/config/"
|
||||
}
|
||||
defines { "FT2_BUILD_LIBRARY" }
|
||||
|
||||
files {
|
||||
"freetype/src/autofit/autofit.c",
|
||||
"freetype/src/base/ftbase.c",
|
||||
"freetype/src/base/ftbbox.c",
|
||||
"freetype/src/base/ftbdf.c",
|
||||
"freetype/src/base/ftbitmap.c",
|
||||
"freetype/src/base/ftcid.c",
|
||||
"freetype/src/base/ftfstype.c",
|
||||
"freetype/src/base/ftgasp.c",
|
||||
"freetype/src/base/ftglyph.c",
|
||||
"freetype/src/base/ftgxval.c",
|
||||
"freetype/src/base/ftinit.c",
|
||||
"freetype/src/base/ftmm.c",
|
||||
"freetype/src/base/ftotval.c",
|
||||
"freetype/src/base/ftpatent.c",
|
||||
"freetype/src/base/ftpfr.c",
|
||||
"freetype/src/base/ftstroke.c",
|
||||
"freetype/src/base/ftsynth.c",
|
||||
"freetype/src/base/ftsystem.c",
|
||||
"freetype/src/base/fttype1.c",
|
||||
"freetype/src/base/ftwinfnt.c",
|
||||
"freetype/src/bdf/bdf.c",
|
||||
"freetype/src/cache/ftcache.c",
|
||||
"freetype/src/cff/cff.c",
|
||||
"freetype/src/cid/type1cid.c",
|
||||
"freetype/src/gzip/ftgzip.c",
|
||||
"freetype/src/lzw/ftlzw.c",
|
||||
"freetype/src/pcf/pcf.c",
|
||||
"freetype/src/pfr/pfr.c",
|
||||
"freetype/src/psaux/psaux.c",
|
||||
"freetype/src/pshinter/pshinter.c",
|
||||
"freetype/src/psnames/psmodule.c",
|
||||
"freetype/src/raster/raster.c",
|
||||
"freetype/src/sfnt/sfnt.c",
|
||||
"freetype/src/smooth/smooth.c",
|
||||
"freetype/src/truetype/truetype.c",
|
||||
"freetype/src/type1/type1.c",
|
||||
"freetype/src/type42/type42.c",
|
||||
"freetype/src/winfonts/winfnt.c",
|
||||
"freetype/src/winfonts/winfnt.c",
|
||||
"freetype/src/sdf/sdf.c"
|
||||
}
|
||||
|
||||
|
||||
filter "system:windows"
|
||||
systemversion "latest"
|
||||
|
||||
-- warning C4244: 'function': conversion from '__int64' to 'const unsigned int', possible loss of data
|
||||
-- warning C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead
|
||||
-- warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead.
|
||||
-- warning C4267: '=': conversion from 'size_t' to 'FT_Int', possible loss of data
|
||||
-- warning C4312: 'type cast': conversion from 'unsigned long' to 'void *' of greater size
|
||||
disablewarnings { "4996", "4267", "4244", "4312" }
|
||||
|
||||
defines
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
files { "freetype/src/base/ftdebug.c" }
|
||||
runtime "Debug"
|
||||
symbols "on"
|
||||
|
||||
filter "configurations:Release"
|
||||
files { "freetype/src/base/ftdebug.c" }
|
||||
runtime "Release"
|
||||
optimize "on"
|
||||
|
||||
filter "configurations:Dist"
|
||||
files { "freetype/src/base/ftdebug.c" }
|
||||
runtime "Release"
|
||||
optimize "on"
|
||||
group ""
|
||||
Submodule Nuake/dependencies/glfw updated: 114776a246...026a148d7d
@@ -10,14 +10,19 @@ project "GLFW"
|
||||
files
|
||||
{
|
||||
"glfw/include/GLFW/glfw3.h",
|
||||
--"glfw/include/GLFW/glfw3native.h",
|
||||
"glfw/include/GLFW/glfw3native.h",
|
||||
"glfw/src/glfw_config.h",
|
||||
"glfw/src/context.c",
|
||||
"glfw/src/init.c",
|
||||
"glfw/src/input.c",
|
||||
"glfw/src/monitor.c",
|
||||
"glfw/src/vulkan.c",
|
||||
"glfw/src/window.c"
|
||||
"glfw/src/window.c",
|
||||
"glfw/src/platform.c",
|
||||
"glfw/src/null_init.c",
|
||||
"glfw/src/null_joystick.c",
|
||||
"glfw/src/null_monitor.c",
|
||||
"glfw/src/null_window.c",
|
||||
"glfw/src/vulkan.c"
|
||||
}
|
||||
|
||||
filter "system:windows"
|
||||
@@ -31,6 +36,7 @@ project "GLFW"
|
||||
"glfw/src/win32_time.c",
|
||||
"glfw/src/win32_thread.c",
|
||||
"glfw/src/win32_window.c",
|
||||
"glfw/src/win32_module.c",
|
||||
"glfw/src/wgl_context.c",
|
||||
"glfw/src/egl_context.c",
|
||||
"glfw/src/osmesa_context.c"
|
||||
@@ -40,6 +46,8 @@ project "GLFW"
|
||||
{
|
||||
"_GLFW_WIN32",
|
||||
}
|
||||
|
||||
disablewarnings { "4996" }
|
||||
|
||||
|
||||
filter "system:linux"
|
||||
@@ -54,6 +62,7 @@ project "GLFW"
|
||||
"glfw/src/xkb_unicode.c",
|
||||
"glfw/src/posix_time.c",
|
||||
"glfw/src/posix_thread.c",
|
||||
"glfw/src/posix_module.c",
|
||||
"glfw/src/glx_context.c",
|
||||
"glfw/src/egl_context.c",
|
||||
"glfw/src/osmesa_context.c",
|
||||
@@ -72,4 +81,4 @@ project "GLFW"
|
||||
|
||||
filter "configurations:Release"
|
||||
runtime "Release"
|
||||
optimize "on"
|
||||
optimize "on"
|
||||
|
||||
@@ -36,6 +36,14 @@ project 'JoltPhysics'
|
||||
prebuildcommands {
|
||||
"cp %{prj.location}./Jolt.cpp %{prj.location}/"
|
||||
}
|
||||
|
||||
-- When building any Visual Studio solution
|
||||
filter { "system:windows", "action:vs*"}
|
||||
flags
|
||||
{
|
||||
"MultiProcessorCompile",
|
||||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
cppdialect "C++17"
|
||||
runtime "Debug"
|
||||
|
||||
1
Nuake/dependencies/msdf-atlas-gen
Submodule
1
Nuake/dependencies/msdf-atlas-gen
Submodule
Submodule Nuake/dependencies/msdf-atlas-gen added at 7116b6255d
86
Nuake/dependencies/msdf-atlas-gen_p5.lua
Normal file
86
Nuake/dependencies/msdf-atlas-gen_p5.lua
Normal file
@@ -0,0 +1,86 @@
|
||||
project '*'
|
||||
includedirs {
|
||||
'yoga/yoga/'
|
||||
}
|
||||
|
||||
group "Dependencies"
|
||||
|
||||
project 'msdf-gen'
|
||||
kind "StaticLib"
|
||||
staticruntime "on"
|
||||
warnings 'Off'
|
||||
optimize 'Speed'
|
||||
cppdialect "C++20"
|
||||
|
||||
includedirs {
|
||||
'msdf-atlas-gen/include',
|
||||
'freetype/include'
|
||||
}
|
||||
|
||||
files {
|
||||
'msdf-atlas-gen/msdfgen/*.h',
|
||||
'msdf-atlas-gen/msdfgen/*.cpp',
|
||||
'msdf-atlas-gen/msdfgen/*.hpp',
|
||||
'msdf-atlas-gen/msdfgen/Core/*.h',
|
||||
'msdf-atlas-gen/msdfgen/Core/*.hpp',
|
||||
'msdf-atlas-gen/msdfgen/Core/*.cpp',
|
||||
'msdf-atlas-gen/msdfgen/lib/*.cpp',
|
||||
'msdf-atlas-gen/msdfgen/ext/*.h',
|
||||
'msdf-atlas-gen/msdfgen/ext/*.cpp'
|
||||
}
|
||||
|
||||
defines {
|
||||
|
||||
}
|
||||
|
||||
-- When building any Visual Studio solution
|
||||
filter { "system:windows", "action:vs*"}
|
||||
flags
|
||||
{
|
||||
"MultiProcessorCompile",
|
||||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
runtime "Debug"
|
||||
symbols "on"
|
||||
|
||||
filter "configurations:Release"
|
||||
runtime "Release"
|
||||
optimize "on"
|
||||
|
||||
project 'msdf-atlas-gen'
|
||||
kind "StaticLib"
|
||||
staticruntime "on"
|
||||
warnings 'Off'
|
||||
optimize 'Speed'
|
||||
cppdialect "C++20"
|
||||
|
||||
includedirs {
|
||||
'msdf-atlas-gen/include',
|
||||
'msdf-atlas-gen/msdfgen',
|
||||
'msdf-atlas-gen/msdfgen/include'
|
||||
}
|
||||
|
||||
files {
|
||||
'msdf-atlas-gen/msdf-atlas-gen/*.h',
|
||||
'msdf-atlas-gen/msdf-atlas-gen/*.cpp',
|
||||
'msdf-atlas-gen/msdf-atlas-gen/*.hpp',
|
||||
}
|
||||
|
||||
links {
|
||||
'msdf-gen'
|
||||
}
|
||||
|
||||
defines {
|
||||
|
||||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
runtime "Debug"
|
||||
symbols "on"
|
||||
|
||||
filter "configurations:Release"
|
||||
runtime "Release"
|
||||
optimize "on"
|
||||
|
||||
group ""
|
||||
@@ -67,7 +67,6 @@ project "Detour"
|
||||
defines {"DEBUG"}
|
||||
symbols "On"
|
||||
postbuildcommands {}
|
||||
flags {"staticruntime"} -- this is what worked for me
|
||||
|
||||
-- linux library cflags and libs
|
||||
filter {"system:linux", "toolset:gcc"}
|
||||
|
||||
1
Nuake/dependencies/tracy
Submodule
1
Nuake/dependencies/tracy
Submodule
Submodule Nuake/dependencies/tracy added at 5d542dc09f
30
Nuake/dependencies/tracy_p5.lua
Normal file
30
Nuake/dependencies/tracy_p5.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
group "Dependencies"
|
||||
project 'Tracy'
|
||||
location "tracy"
|
||||
|
||||
kind "StaticLib"
|
||||
staticruntime "on"
|
||||
warnings 'Off'
|
||||
|
||||
includedirs {
|
||||
"tracy/public/tracy"
|
||||
}
|
||||
|
||||
files {
|
||||
"tracy/public/tracy/Tracy.hpp",
|
||||
"tracy/public/TracyClient.cpp"
|
||||
}
|
||||
|
||||
defines {
|
||||
"TRACY_ENABLE",
|
||||
"TRACY_ON_DEMAND",
|
||||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
runtime "Debug"
|
||||
symbols "on"
|
||||
|
||||
filter "configurations:Release"
|
||||
runtime "Release"
|
||||
optimize "on"
|
||||
group ""
|
||||
1
Nuake/dependencies/vma
Submodule
1
Nuake/dependencies/vma
Submodule
Submodule Nuake/dependencies/vma added at 5a53a19894
1
Nuake/dependencies/yoga
Submodule
1
Nuake/dependencies/yoga
Submodule
Submodule Nuake/dependencies/yoga added at dc4ab5ad57
43
Nuake/dependencies/yoga_p5.lua
Normal file
43
Nuake/dependencies/yoga_p5.lua
Normal file
@@ -0,0 +1,43 @@
|
||||
project '*'
|
||||
includedirs {
|
||||
'yoga/yoga/'
|
||||
}
|
||||
|
||||
group "Dependencies"
|
||||
|
||||
project 'yoga'
|
||||
kind "StaticLib"
|
||||
staticruntime "on"
|
||||
warnings 'Off'
|
||||
optimize 'Speed'
|
||||
cppdialect "C++20"
|
||||
|
||||
includedirs {
|
||||
'yoga/'
|
||||
}
|
||||
files {
|
||||
'yoga/yoga/*.cpp',
|
||||
'yoga/yoga/*.h',
|
||||
'yoga/yoga/**/*.cpp',
|
||||
'yoga/yoga/**/*.h',
|
||||
}
|
||||
|
||||
defines {
|
||||
}
|
||||
|
||||
-- When building any Visual Studio solution
|
||||
filter { "system:windows", "action:vs*"}
|
||||
flags
|
||||
{
|
||||
"MultiProcessorCompile",
|
||||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
runtime "Debug"
|
||||
symbols "on"
|
||||
|
||||
filter "configurations:Release"
|
||||
runtime "Release"
|
||||
optimize "on"
|
||||
|
||||
group ""
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <Tracy.hpp>
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
Application::Application(const ApplicationSpecification& appSpecification)
|
||||
@@ -33,8 +35,11 @@ namespace Nuake {
|
||||
{
|
||||
while (!m_Window->ShouldClose())
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
for (auto& layer : m_LayerStack)
|
||||
{
|
||||
ZoneScopedN("Layer Update");
|
||||
layer->OnUpdate();
|
||||
}
|
||||
|
||||
@@ -42,9 +47,12 @@ namespace Nuake {
|
||||
{
|
||||
for (auto& layer : m_LayerStack)
|
||||
{
|
||||
ZoneScopedN("Layer Draw");
|
||||
layer->OnDraw();
|
||||
}
|
||||
}
|
||||
|
||||
FrameMark;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,4 +63,4 @@ namespace Nuake {
|
||||
layer->OnDetach();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace Nuake {
|
||||
|
||||
virtual void OnDraw() {};
|
||||
|
||||
virtual void OnWindowFocused() {};
|
||||
virtual void OnDragNDrop(const std::vector<std::string>&) {};
|
||||
// TODO: OnEvent
|
||||
|
||||
inline const std::string& GetName() const { return m_Name; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "AudioManager.h"
|
||||
#include "src/Core/Logger.h"
|
||||
#include "src/Core/FileSystem.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
#include <soloud.h>
|
||||
#include "soloud_speech.h"
|
||||
@@ -11,8 +11,7 @@
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
AudioManager::AudioManager() :
|
||||
m_AudioThreadRunning(true)
|
||||
AudioManager::AudioManager()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -20,9 +19,6 @@ namespace Nuake {
|
||||
{
|
||||
Deinitialize();
|
||||
|
||||
m_AudioThreadRunning = false;
|
||||
m_AudioThread.join();
|
||||
|
||||
m_Soloud->deinit();
|
||||
}
|
||||
|
||||
@@ -32,20 +28,11 @@ namespace Nuake {
|
||||
|
||||
// TODO: Sample rate, back end, buffer size, flags.
|
||||
#ifdef NK_WIN
|
||||
m_Soloud->init();
|
||||
m_Soloud->init(SoLoud::Soloud::LEFT_HANDED_3D);
|
||||
#else
|
||||
m_Soloud->init(SoLoud::Soloud::CLIP_ROUNDOFF, SoLoud::Soloud::ALSA);
|
||||
#endif
|
||||
|
||||
if (m_AudioThread.joinable())
|
||||
{
|
||||
m_AudioThreadRunning = false;
|
||||
m_AudioThread.join();
|
||||
}
|
||||
|
||||
m_AudioThreadRunning = true;
|
||||
m_AudioThread = std::thread(&AudioManager::AudioThreadLoop, this);
|
||||
|
||||
Logger::Log("Audio manager initialized", "audio", VERBOSE);
|
||||
}
|
||||
|
||||
@@ -68,6 +55,7 @@ namespace Nuake {
|
||||
m_ListenerUp.x, m_ListenerUp.y, m_ListenerUp.z
|
||||
);
|
||||
|
||||
|
||||
m_Soloud->update3dAudio();
|
||||
}
|
||||
}
|
||||
@@ -79,9 +67,6 @@ namespace Nuake {
|
||||
|
||||
void AudioManager::QueueWavAudio(const AudioRequest& request)
|
||||
{
|
||||
// Acquire mutex lock and push to queue
|
||||
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
|
||||
|
||||
// Check if file exists and load
|
||||
const bool fileExists = FileSystem::FileExists(request.audioFile, true);
|
||||
if (fileExists && !IsWavLoaded(request.audioFile))
|
||||
@@ -94,9 +79,6 @@ namespace Nuake {
|
||||
|
||||
void AudioManager::UpdateVoice(const AudioRequest& request)
|
||||
{
|
||||
// Acquire mutex lock
|
||||
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
|
||||
|
||||
auto& audioClip = m_ActiveClips[request.audioFile];
|
||||
if (IsVoiceActive(request.audioFile))
|
||||
{
|
||||
@@ -125,8 +107,6 @@ namespace Nuake {
|
||||
|
||||
void AudioManager::StopVoice(const std::string& filePath)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
|
||||
|
||||
if (!IsVoiceActive(filePath))
|
||||
{
|
||||
return; // We can't stop a voice that isn't active.
|
||||
@@ -153,7 +133,7 @@ namespace Nuake {
|
||||
|
||||
void AudioManager::LoadWavAudio(const std::string& filePath)
|
||||
{
|
||||
const bool STREAMING = true;
|
||||
const bool STREAMING = false;
|
||||
if (STREAMING)
|
||||
{
|
||||
Ref<SoLoud::WavStream> wavStream = CreateRef<SoLoud::WavStream>();
|
||||
@@ -166,44 +146,42 @@ namespace Nuake {
|
||||
wav->load(filePath.c_str());
|
||||
m_WavSamples[filePath] = wav;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AudioManager::AudioThreadLoop()
|
||||
void AudioManager::AudioUpdate()
|
||||
{
|
||||
while(m_AudioThreadRunning)
|
||||
// Check if we have audio queued
|
||||
if (m_Soloud->getGlobalVolume() != m_GlobalVolume)
|
||||
{
|
||||
// Acquire mutex lock
|
||||
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
|
||||
m_Soloud->setGlobalVolume(m_GlobalVolume);
|
||||
}
|
||||
|
||||
// Check if we have audio queued
|
||||
while (!m_AudioQueue.empty())
|
||||
while (!m_AudioQueue.empty())
|
||||
{
|
||||
AudioRequest& audioRequest = m_AudioQueue.front();
|
||||
Ref<SoLoud::AudioSource> audio = m_WavSamples[audioRequest.audioFile];
|
||||
|
||||
SoLoud::handle handle;
|
||||
if (!audioRequest.spatialized)
|
||||
{
|
||||
AudioRequest& audioRequest = m_AudioQueue.front();
|
||||
Ref<SoLoud::AudioSource> audio = m_WavSamples[audioRequest.audioFile];
|
||||
|
||||
SoLoud::handle soloudHandle;
|
||||
if (!audioRequest.spatialized)
|
||||
{
|
||||
soloudHandle = m_Soloud->play(*audio);
|
||||
m_Soloud->setVolume(soloudHandle, audioRequest.volume);
|
||||
m_Soloud->setPan(soloudHandle, audioRequest.pan);
|
||||
}
|
||||
else
|
||||
{
|
||||
const Vector3& position = audioRequest.position;
|
||||
soloudHandle = m_Soloud->play3d(*audio, position.x, position.y, position.z);
|
||||
m_Soloud->set3dSourceMinMaxDistance(soloudHandle, audioRequest.MinDistance, audioRequest.MaxDistance);
|
||||
m_Soloud->set3dSourceAttenuation(soloudHandle, SoLoud::AudioSource::ATTENUATION_MODELS::EXPONENTIAL_DISTANCE, audioRequest.AttenuationFactor);
|
||||
}
|
||||
|
||||
m_Soloud->setRelativePlaySpeed(soloudHandle, audioRequest.speed);
|
||||
m_Soloud->setLooping(soloudHandle, audioRequest.Loop);
|
||||
|
||||
m_ActiveClips[audioRequest.audioFile] = soloudHandle;
|
||||
|
||||
m_AudioQueue.pop();
|
||||
handle = m_Soloud->play(*audio);
|
||||
m_Soloud->setVolume(handle, audioRequest.volume);
|
||||
m_Soloud->setPan(handle, audioRequest.pan);
|
||||
}
|
||||
else
|
||||
{
|
||||
const Vector3& position = audioRequest.position;
|
||||
handle = m_Soloud->play3d(*audio, position.x, position.y, position.z);
|
||||
m_Soloud->set3dSourceMinMaxDistance(handle, audioRequest.MinDistance, audioRequest.MaxDistance);
|
||||
m_Soloud->set3dSourceAttenuation(handle, SoLoud::AudioSource::ATTENUATION_MODELS::EXPONENTIAL_DISTANCE, audioRequest.AttenuationFactor);
|
||||
}
|
||||
|
||||
m_Soloud->setRelativePlaySpeed(handle, audioRequest.speed);
|
||||
m_Soloud->setLooping(handle, audioRequest.Loop);
|
||||
|
||||
m_ActiveClips[audioRequest.audioFile] = handle;
|
||||
|
||||
m_AudioQueue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,10 +39,7 @@ namespace Nuake
|
||||
|
||||
Ref<SoLoud::Soloud> m_Soloud;
|
||||
|
||||
bool m_AudioThreadRunning;
|
||||
std::thread m_AudioThread;
|
||||
std::mutex m_AudioQueueMutex;
|
||||
std::atomic<bool> m_AudioQueued = { false };
|
||||
bool m_AudioQueued = false;
|
||||
std::queue<AudioRequest> m_AudioQueue;
|
||||
|
||||
Vector3 m_ListenerPosition;
|
||||
@@ -87,8 +84,9 @@ namespace Nuake
|
||||
bool IsVoiceActive(const std::string & voice) const;
|
||||
void LoadWavAudio(const std::string& filePath);
|
||||
|
||||
void AudioUpdate();
|
||||
|
||||
private:
|
||||
void AudioThreadLoop();
|
||||
|
||||
void CleanupInactiveVoices();
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
#define ASSERT(x) if (!(x)) assert(false)
|
||||
|
||||
|
||||
@@ -1,404 +0,0 @@
|
||||
#include "FileSystem.h"
|
||||
|
||||
#include "Engine.h"
|
||||
#include "OS.h"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#ifdef NK_WIN
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
|
||||
#include "GLFW/glfw3native.h"
|
||||
#include <commdlg.h>
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NK_LINUX
|
||||
#include "gtk/gtk.h"
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <ShlObj.h>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::string FileDialog::OpenFile(const char* filter)
|
||||
{
|
||||
std::string filePath;
|
||||
#ifdef NK_WIN
|
||||
OPENFILENAMEA ofn;
|
||||
CHAR szFile[260] = { 0 };
|
||||
ZeroMemory(&ofn, sizeof(OPENFILENAME));
|
||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||
ofn.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.nMaxFile = sizeof(szFile);
|
||||
ofn.lpstrFilter = filter;
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
|
||||
if (GetOpenFileNameA(&ofn) == TRUE)
|
||||
{
|
||||
filePath = std::string(ofn.lpstrFile);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NK_LINUX
|
||||
GtkWidget *dialog;
|
||||
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
||||
gint res;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new("Open File",
|
||||
NULL,
|
||||
action,
|
||||
"_Cancel",
|
||||
GTK_RESPONSE_CANCEL,
|
||||
"_Open",
|
||||
GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
|
||||
if (filter) {
|
||||
GtkFileFilter *file_filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(file_filter, "Filter Name");
|
||||
gtk_file_filter_add_pattern(file_filter, filter);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), file_filter);
|
||||
}
|
||||
|
||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
|
||||
if (res == GTK_RESPONSE_ACCEPT) {
|
||||
char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
filePath = filename;
|
||||
g_free(filename);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
#endif
|
||||
return filePath;
|
||||
}
|
||||
|
||||
std::string FileDialog::SaveFile(const char* filter)
|
||||
{
|
||||
#ifdef NK_WIN
|
||||
OPENFILENAMEA ofn;
|
||||
CHAR szFile[260] = { 0 };
|
||||
ZeroMemory(&ofn, sizeof(OPENFILENAME));
|
||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||
ofn.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.nMaxFile = sizeof(szFile);
|
||||
ofn.lpstrFilter = filter;
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
|
||||
if (GetSaveFileNameA(&ofn) == TRUE)
|
||||
{
|
||||
return ofn.lpstrFile;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NK_LINUX
|
||||
GtkWidget *dialog;
|
||||
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE;
|
||||
gint res;
|
||||
|
||||
gtk_init(NULL, NULL);
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new("Save File",
|
||||
NULL,
|
||||
action,
|
||||
"_Cancel",
|
||||
GTK_RESPONSE_CANCEL,
|
||||
"_Save",
|
||||
GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
GtkFileFilter *file_filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(file_filter, filter);
|
||||
gtk_file_filter_add_pattern(file_filter, "*.*"); // You can customize this pattern
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), file_filter);
|
||||
|
||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
if (res == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
char *filename;
|
||||
GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
|
||||
filename = gtk_file_chooser_get_filename(chooser);
|
||||
std::string result(filename);
|
||||
g_free(filename);
|
||||
gtk_widget_destroy(dialog);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_destroy(dialog);
|
||||
return std::string();
|
||||
}
|
||||
#endif
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string FileDialog::OpenFolder()
|
||||
{
|
||||
std::string folderPath;
|
||||
|
||||
#ifdef NK_WIN
|
||||
BROWSEINFOA bi;
|
||||
CHAR szFolder[260] = { 0 };
|
||||
ZeroMemory(&bi, sizeof(BROWSEINFO));
|
||||
bi.lpszTitle = "Select a Folder";
|
||||
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
|
||||
bi.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
|
||||
bi.pszDisplayName = szFolder;
|
||||
LPITEMIDLIST pidl = SHBrowseForFolderA(&bi);
|
||||
if (pidl != NULL)
|
||||
{
|
||||
SHGetPathFromIDListA(pidl, szFolder);
|
||||
folderPath = std::string(szFolder);
|
||||
CoTaskMemFree(pidl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NK_LINUX
|
||||
GtkWidget* dialog;
|
||||
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
|
||||
gint res;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new("Select Folder",
|
||||
NULL,
|
||||
action,
|
||||
"_Cancel",
|
||||
GTK_RESPONSE_CANCEL,
|
||||
"_Select",
|
||||
GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
|
||||
if (res == GTK_RESPONSE_ACCEPT) {
|
||||
char* foldername = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
folderPath = foldername;
|
||||
g_free(foldername);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
#endif
|
||||
|
||||
return folderPath;
|
||||
}
|
||||
|
||||
std::string FileSystem::Root = "";
|
||||
|
||||
Ref<Directory> FileSystem::RootDirectory;
|
||||
|
||||
void FileSystem::ScanDirectory(Ref<Directory> directory)
|
||||
{
|
||||
for (const auto& entry : std::filesystem::directory_iterator(directory->FullPath))
|
||||
{
|
||||
if (entry.is_directory())
|
||||
{
|
||||
Ref<Directory> newDir = CreateRef<Directory>();
|
||||
newDir->FullPath = entry.path().string();
|
||||
newDir->Name = entry.path().filename().string();
|
||||
|
||||
newDir->Parent = directory;
|
||||
ScanDirectory(newDir);
|
||||
directory->Directories.push_back(newDir);
|
||||
}
|
||||
else if (entry.is_regular_file())
|
||||
{
|
||||
std::filesystem::path currentPath = entry.path();
|
||||
std::string absolutePath = currentPath.string();
|
||||
std::string name = currentPath.filename().string();
|
||||
std::string extension = currentPath.extension().string();
|
||||
Ref<File> newFile = CreateRef<File>(directory, absolutePath, name, extension);
|
||||
directory->Files.push_back(newFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSystem::DirectoryExists(const std::string& path, bool absolute)
|
||||
{
|
||||
const std::string& finalPath = absolute ? path : Root + path;
|
||||
|
||||
return std::filesystem::exists(finalPath) && std::filesystem::is_directory(finalPath);
|
||||
}
|
||||
|
||||
bool FileSystem::MakeDirectory(const std::string& path, bool absolute)
|
||||
{
|
||||
return std::filesystem::create_directories(absolute ? path : FileSystem::Root + path);
|
||||
}
|
||||
|
||||
bool FileSystem::FileExists(const std::string& path, bool absolute)
|
||||
{
|
||||
std::string fullPath = absolute ? path : FileSystem::Root + path;
|
||||
return std::filesystem::exists(fullPath);
|
||||
}
|
||||
|
||||
void FileSystem::SetRootDirectory(const std::string path)
|
||||
{
|
||||
Root = path;
|
||||
Scan();
|
||||
}
|
||||
|
||||
void FileSystem::Scan()
|
||||
{
|
||||
RootDirectory = CreateRef<Directory>(Root);
|
||||
ScanDirectory(RootDirectory);
|
||||
}
|
||||
|
||||
std::string FileSystem::AbsoluteToRelative(const std::string& path)
|
||||
{
|
||||
const fs::path rootPath(Root);
|
||||
const fs::path absolutePath(path);
|
||||
return fs::relative(absolutePath, rootPath).generic_string();
|
||||
}
|
||||
|
||||
std::string FileSystem::RelativeToAbsolute(const std::string& path)
|
||||
{
|
||||
return Root + path;
|
||||
}
|
||||
|
||||
std::string FileSystem::GetParentPath(const std::string& fullPath)
|
||||
{
|
||||
std::filesystem::path pathObj(fullPath);
|
||||
auto returnvalue = pathObj.parent_path().string();
|
||||
return returnvalue + "/";
|
||||
}
|
||||
|
||||
std::string FileSystem::ReadFile(const std::string& path, bool absolute)
|
||||
{
|
||||
std::string finalPath = path;
|
||||
if (!absolute)
|
||||
finalPath = Root + path;
|
||||
|
||||
std::ifstream myReadFile(finalPath, std::ios::in | std::ios::binary);
|
||||
std::string fileContent = "";
|
||||
std::string allFile = "";
|
||||
|
||||
char bom[3];
|
||||
myReadFile.read(bom, 3);
|
||||
|
||||
// Check for UTF-8 BOM (EF BB BF)
|
||||
if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF)
|
||||
{
|
||||
myReadFile.seekg(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
myReadFile.seekg(0);
|
||||
}
|
||||
|
||||
// Use a while loop together with the getline() function to read the file line by line
|
||||
while (getline(myReadFile, fileContent))
|
||||
{
|
||||
allFile.append(fileContent + "\n");
|
||||
}
|
||||
|
||||
// Close the file
|
||||
myReadFile.close();
|
||||
return allFile;
|
||||
}
|
||||
|
||||
std::ofstream FileSystem::fileWriter;
|
||||
bool FileSystem::BeginWriteFile(const std::string path, bool absolute)
|
||||
{
|
||||
fileWriter = std::ofstream();
|
||||
fileWriter.open(absolute ? path : FileSystem::Root + path);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileSystem::WriteLine(const std::string line)
|
||||
{
|
||||
fileWriter << line.c_str();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileSystem::EndWriteFile()
|
||||
{
|
||||
fileWriter.close();
|
||||
}
|
||||
|
||||
uintmax_t FileSystem::DeleteFileFromPath(const std::string& path)
|
||||
{
|
||||
return std::remove(path.c_str());
|
||||
}
|
||||
|
||||
uintmax_t FileSystem::DeleteFolder(const std::string& path)
|
||||
{
|
||||
return std::filesystem::remove_all(path.c_str());
|
||||
}
|
||||
|
||||
std::string FileSystem::GetConfigFolderPath()
|
||||
{
|
||||
std::string subFolderPath = OS::GetConfigFolderPath().append("/Nuake/");
|
||||
if (!DirectoryExists(subFolderPath, true))
|
||||
{
|
||||
MakeDirectory(subFolderPath);
|
||||
}
|
||||
|
||||
return subFolderPath;
|
||||
}
|
||||
|
||||
Ref<Directory> FileSystem::GetFileTree()
|
||||
{
|
||||
return RootDirectory;
|
||||
}
|
||||
|
||||
Ref<File> FileSystem::GetFile(const std::string& path)
|
||||
{
|
||||
// Note, Might be broken on other platforms.
|
||||
auto splits = String::Split(path, '/');
|
||||
|
||||
int currentDepth = -1;
|
||||
std::string currentDirName = ".";
|
||||
Ref<Directory> currentDirComparator = RootDirectory;
|
||||
while (currentDirName == currentDirComparator->Name)
|
||||
{
|
||||
currentDepth++;
|
||||
currentDirName = splits[currentDepth];
|
||||
|
||||
// Find next directory
|
||||
for (auto& d : currentDirComparator->Directories)
|
||||
{
|
||||
if (d->Name == currentDirName)
|
||||
{
|
||||
currentDirComparator = d;
|
||||
}
|
||||
}
|
||||
|
||||
// Find in files if can't find in directories.
|
||||
for (auto& f : currentDirComparator->Files)
|
||||
{
|
||||
if (f->GetName() == currentDirName)
|
||||
{
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string FileSystem::GetFileNameFromPath(const std::string& path)
|
||||
{
|
||||
const auto& split = String::Split(path, '/');
|
||||
return String::Split(split[split.size() - 1], '.')[0];
|
||||
}
|
||||
|
||||
|
||||
Directory::Directory(const std::string& path)
|
||||
{
|
||||
Files = std::vector<Ref<File>>();
|
||||
Directories = std::vector<Ref<Directory>>();
|
||||
Name = FileSystem::AbsoluteToRelative(path);
|
||||
FullPath = path;
|
||||
}
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
#pragma once
|
||||
#include "Core.h"
|
||||
#include "String.h"
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class FileDialog
|
||||
{
|
||||
public:
|
||||
static std::string OpenFile(const char* filter);
|
||||
static std::string SaveFile(const char* filter);
|
||||
static std::string OpenFolder();
|
||||
};
|
||||
|
||||
class Directory;
|
||||
class File;
|
||||
|
||||
class FileSystem
|
||||
{
|
||||
public:
|
||||
static std::string Root;
|
||||
|
||||
static Ref<Directory> RootDirectory;
|
||||
|
||||
static void SetRootDirectory(const std::string path);
|
||||
|
||||
static void Scan();
|
||||
static std::string AbsoluteToRelative(const std::string& path);
|
||||
static std::string RelativeToAbsolute(const std::string& path);
|
||||
static std::string GetParentPath(const std::string& fullPath);
|
||||
static Ref<Directory> GetFileTree();
|
||||
static Ref<File> GetFile(const std::string& path);
|
||||
static std::string GetFileNameFromPath(const std::string& path);
|
||||
static void ScanDirectory(Ref<Directory> directory);
|
||||
static void GetDirectories();
|
||||
|
||||
static bool MakeDirectory(const std::string& path, bool absolute = false);
|
||||
static bool DirectoryExists(const std::string& path, bool absolute = false);
|
||||
static bool FileExists(const std::string& path, bool absolute = false);
|
||||
|
||||
static std::string ReadFile(const std::string& path, bool absolute = false);
|
||||
|
||||
static std::ofstream fileWriter;
|
||||
static bool BeginWriteFile(const std::string path, bool absolute = false);
|
||||
static bool WriteLine(const std::string line);
|
||||
static void EndWriteFile();
|
||||
static uintmax_t DeleteFileFromPath(const std::string& path);
|
||||
static uintmax_t DeleteFolder(const std::string& path);
|
||||
static std::string GetConfigFolderPath();
|
||||
};
|
||||
|
||||
enum class FileType
|
||||
{
|
||||
Unkown,
|
||||
Image,
|
||||
Material,
|
||||
Mesh,
|
||||
Script,
|
||||
NetScript,
|
||||
Project,
|
||||
Prefab,
|
||||
Scene,
|
||||
Wad,
|
||||
Map,
|
||||
Assembly,
|
||||
Solution,
|
||||
Audio
|
||||
};
|
||||
|
||||
class File
|
||||
{
|
||||
private:
|
||||
std::string Type;
|
||||
std::string Name;
|
||||
std::string RelativePath;
|
||||
std::string AbsolutePath;
|
||||
Ref<Directory> Parent;
|
||||
public:
|
||||
|
||||
std::string GetExtension() const { return Type; }
|
||||
std::string GetName() const { return Name; }
|
||||
std::string GetRelativePath() const { return RelativePath; }
|
||||
std::string GetAbsolutePath() const { return AbsolutePath; }
|
||||
Ref<Directory> GetParent() const { return Parent; }
|
||||
FileType GetFileType() const
|
||||
{
|
||||
std::string ext = GetExtension();
|
||||
if (ext == ".png" || ext == ".jpg")
|
||||
{
|
||||
return FileType::Image;
|
||||
}
|
||||
if (ext == ".ogg" || ext == ".wav")
|
||||
{
|
||||
return FileType::Audio;
|
||||
}
|
||||
if (ext == ".material")
|
||||
{
|
||||
return FileType::Material;
|
||||
}
|
||||
|
||||
if (ext == ".scene")
|
||||
{
|
||||
return FileType::Scene;
|
||||
}
|
||||
|
||||
if (ext == ".project")
|
||||
{
|
||||
return FileType::Project;
|
||||
}
|
||||
|
||||
if (ext == ".script")
|
||||
{
|
||||
return FileType::Script;
|
||||
}
|
||||
|
||||
if (ext == ".prefab")
|
||||
{
|
||||
return FileType::Prefab;
|
||||
}
|
||||
|
||||
if (ext == ".wad")
|
||||
{
|
||||
return FileType::Wad;
|
||||
}
|
||||
|
||||
if (ext == ".map")
|
||||
{
|
||||
return FileType::Map;
|
||||
}
|
||||
|
||||
if (ext == ".dll")
|
||||
{
|
||||
return FileType::Assembly;
|
||||
}
|
||||
|
||||
if (ext == ".cs")
|
||||
{
|
||||
return FileType::NetScript;
|
||||
}
|
||||
|
||||
if (ext == ".sln")
|
||||
{
|
||||
return FileType::Solution;
|
||||
}
|
||||
|
||||
if (ext == ".mesh")
|
||||
{
|
||||
return FileType::Mesh;
|
||||
}
|
||||
|
||||
return FileType::Unkown;
|
||||
}
|
||||
|
||||
std::string GetFileTypeAsString() const
|
||||
{
|
||||
std::string ext = GetExtension();
|
||||
if (ext == ".png" || ext == "jpg")
|
||||
{
|
||||
return "Image";
|
||||
}
|
||||
|
||||
if (ext == ".material")
|
||||
{
|
||||
return "Material";
|
||||
}
|
||||
|
||||
if (ext == ".scene")
|
||||
{
|
||||
return "Scene";
|
||||
}
|
||||
|
||||
if (ext == ".project")
|
||||
{
|
||||
return "Project";
|
||||
}
|
||||
|
||||
if (ext == ".script")
|
||||
{
|
||||
return "Script";
|
||||
}
|
||||
|
||||
if (ext == ".prefab")
|
||||
{
|
||||
return "Prefab";
|
||||
}
|
||||
|
||||
if (ext == ".wad")
|
||||
{
|
||||
return "Wad";
|
||||
}
|
||||
|
||||
if (ext == ".map")
|
||||
{
|
||||
return "Map";
|
||||
}
|
||||
|
||||
if (ext == ".map")
|
||||
{
|
||||
return "Assembly";
|
||||
}
|
||||
|
||||
if (ext == ".cs")
|
||||
{
|
||||
return "C# Script";
|
||||
}
|
||||
|
||||
return "File";
|
||||
}
|
||||
|
||||
std::string Read()
|
||||
{
|
||||
return FileSystem::ReadFile(AbsolutePath, true);
|
||||
}
|
||||
|
||||
bool IsValid()
|
||||
{
|
||||
return FileSystem::FileExists(AbsolutePath, true);
|
||||
}
|
||||
|
||||
File(Ref<Directory> parentDir, const std::string& absolutePath, const std::string& name, const std::string& type)
|
||||
{
|
||||
AbsolutePath = absolutePath;
|
||||
Parent = parentDir;
|
||||
RelativePath = FileSystem::AbsoluteToRelative(absolutePath);
|
||||
Name = name;
|
||||
Type = type;
|
||||
}
|
||||
};
|
||||
|
||||
class Directory
|
||||
{
|
||||
public:
|
||||
std::string Name;
|
||||
std::string FullPath;
|
||||
Ref<Directory> Parent;
|
||||
std::vector<Ref<Directory>> Directories;
|
||||
std::vector<Ref<File>> Files;
|
||||
|
||||
Directory(const std::string& path);
|
||||
Directory() = default;
|
||||
~Directory() = default;
|
||||
};
|
||||
}
|
||||
@@ -3,15 +3,21 @@
|
||||
|
||||
#include <imgui/imgui_impl_glfw.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <Tracy.hpp>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
Input* Input::s_Instance;
|
||||
Vector2 Input::s_ViewportPos = Vector2(0,0);
|
||||
Vector2 Input::s_ViewportSize = Vector2(0, 0);
|
||||
|
||||
std::map<int, bool> Input::m_Keys = std::map<int, bool>();
|
||||
bool Input::m_MouseButtons[5] = { false, false, false, false, false };
|
||||
float Input::XScroll = 0.0f;
|
||||
float Input::YScroll = 0.0f;
|
||||
|
||||
|
||||
Vector2 Input::ViewportPosition = Vector2(0, 0);;
|
||||
Vector2 Input::ViewportSize = Vector2(0, 0);
|
||||
void Input::ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
XScroll = (float)xoffset;
|
||||
@@ -74,6 +80,7 @@ namespace Nuake
|
||||
{
|
||||
auto window = Window::Get()->GetHandle();
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouse;
|
||||
}
|
||||
|
||||
bool Input::IsMouseHidden()
|
||||
@@ -86,6 +93,7 @@ namespace Nuake
|
||||
{
|
||||
auto window = Window::Get()->GetHandle();
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
|
||||
}
|
||||
|
||||
// Action
|
||||
@@ -149,14 +157,108 @@ namespace Nuake
|
||||
return Vector2(xpos, ypos);
|
||||
}
|
||||
|
||||
void Input::SetEditorViewportSize(const Vector2& position, const Vector2& size)
|
||||
{
|
||||
s_ViewportPos = position;
|
||||
s_ViewportSize = size;
|
||||
}
|
||||
|
||||
Vector2 Input::GetEditorViewportMousePosition()
|
||||
{
|
||||
if (s_ViewportPos == s_ViewportSize)
|
||||
{
|
||||
return GetMousePosition();
|
||||
}
|
||||
|
||||
auto window = Window::Get()->GetHandle();
|
||||
|
||||
double xpos, ypos;
|
||||
glfwGetCursorPos(window, &xpos, &ypos);
|
||||
|
||||
Vector2 absolutePosition = { xpos, ypos };
|
||||
Vector2 offset = absolutePosition - ViewportPosition;
|
||||
|
||||
return Vector2(xpos , ypos);
|
||||
}
|
||||
|
||||
void Input::SetMousePosition(const Vector2& position)
|
||||
{
|
||||
auto window = Window::Get()->GetHandle();
|
||||
glfwSetCursorPos(window, position.x, position.y);
|
||||
}
|
||||
|
||||
float Input::GetViewportMouseY()
|
||||
{
|
||||
return glm::clamp(GetMouseY() - ViewportPosition.y, 0.0f, ViewportSize.y);
|
||||
}
|
||||
|
||||
float Input::GetViewportMouseX()
|
||||
{
|
||||
return glm::clamp(GetMouseX() - ViewportPosition.x, 0.0f, ViewportSize.x);
|
||||
}
|
||||
|
||||
Vector2 Input::GetViewportMousePosition()
|
||||
{
|
||||
return glm::clamp(GetMousePosition() - ViewportPosition, { 0, 0 }, ViewportSize);
|
||||
}
|
||||
|
||||
Vector2 Input::GetViewportSize()
|
||||
{
|
||||
return ViewportSize;
|
||||
}
|
||||
|
||||
void Input::SetViewportDimensions(const Vector2& pos, const Vector2& size)
|
||||
{
|
||||
ViewportPosition = pos;
|
||||
ViewportSize = size;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
bool Input::IsControllerPresent(int id)
|
||||
{
|
||||
if (id > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return glfwJoystickPresent(GLFW_JOYSTICK_1 + id);
|
||||
}
|
||||
|
||||
std::string Input::GetControllerName(int id)
|
||||
{
|
||||
if (IsControllerPresent(id))
|
||||
{
|
||||
return glfwGetJoystickName(id);
|
||||
}
|
||||
|
||||
return "Controller Disconnected";
|
||||
}
|
||||
|
||||
bool Input::IsControllerButtonPressed(int id, ControllerInput input)
|
||||
{
|
||||
GLFWgamepadstate state;
|
||||
if (glfwGetGamepadState(GLFW_JOYSTICK_1 + id, &state))
|
||||
{
|
||||
if (state.buttons[static_cast<int>(input)])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float Input::GetControllerAxis(int id, ControllerAxis axis)
|
||||
{
|
||||
GLFWgamepadstate state;
|
||||
if (glfwGetGamepadState(GLFW_JOYSTICK_1 + id, &state))
|
||||
{
|
||||
return state.axes[static_cast<int>(axis)];
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool Input::Init()
|
||||
{
|
||||
//auto window = Application::Get().GetWindow()->GetNative();
|
||||
@@ -167,6 +269,8 @@ namespace Nuake
|
||||
|
||||
void Input::Update()
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
// Reset all input to false.
|
||||
for (auto& k : m_Keys)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "src/Core/Maths.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
@@ -65,7 +66,7 @@ namespace Nuake
|
||||
TAB = 258,
|
||||
BACKSPACE = 259,
|
||||
INSERT = 260,
|
||||
DELETE = 261,
|
||||
DELETE_KEY = 261,
|
||||
RIGHT = 262,
|
||||
LEFT = 263,
|
||||
DOWN = 264,
|
||||
@@ -132,11 +133,43 @@ namespace Nuake
|
||||
MENU = 348
|
||||
};
|
||||
|
||||
enum class ControllerInput
|
||||
{
|
||||
A = 0,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
LEFT_BUMPER,
|
||||
RIGHT_BUMPER,
|
||||
BACK,
|
||||
START,
|
||||
GUIDE,
|
||||
LEFT_THUMB,
|
||||
RIGHT_THUMB,
|
||||
DPAD_UP,
|
||||
DPAD_RIGHT,
|
||||
DPAD_DOWN,
|
||||
DPAD_LEFT
|
||||
};
|
||||
|
||||
enum class ControllerAxis
|
||||
{
|
||||
LEFT_X = 0,
|
||||
LEFT_Y,
|
||||
RIGHT_X,
|
||||
RIGHT_Y,
|
||||
LEFT_TRIGGER,
|
||||
RIGHT_TRIGGER
|
||||
};
|
||||
|
||||
class Input
|
||||
{
|
||||
private:
|
||||
static bool m_MouseButtons[5];
|
||||
static std::map<int, bool> m_Keys;
|
||||
static Vector2 ViewportPosition;
|
||||
static Vector2 ViewportSize;
|
||||
|
||||
public:
|
||||
static bool IsKeyPressed(Key keycode);
|
||||
static bool IsKeyDown(Key keycode);
|
||||
@@ -153,11 +186,29 @@ namespace Nuake
|
||||
static bool IsMouseButtonDown(int button);
|
||||
static bool IsMouseButtonReleased(int button);
|
||||
|
||||
// Get mouse position relative to window
|
||||
static float GetMouseX();
|
||||
static float GetMouseY();
|
||||
static Vector2 GetMousePosition();
|
||||
|
||||
static void SetEditorViewportSize(const Vector2& position, const Vector2& size);
|
||||
static Vector2 GetEditorViewportMousePosition();
|
||||
static void SetMousePosition(const Vector2& position);
|
||||
|
||||
// Get mouse position relative to viewport
|
||||
static float GetViewportMouseY();
|
||||
static float GetViewportMouseX();
|
||||
static Vector2 GetViewportMousePosition();
|
||||
static Vector2 GetViewportSize();
|
||||
static void SetViewportDimensions(const Vector2& pos, const Vector2& size);
|
||||
|
||||
// Controller
|
||||
static bool IsControllerPresent(int id);
|
||||
static std::string GetControllerName(int id);
|
||||
|
||||
static bool IsControllerButtonPressed(int id, ControllerInput input);
|
||||
static float GetControllerAxis(int id, ControllerAxis axis);
|
||||
|
||||
static bool Init();
|
||||
static void Update();
|
||||
|
||||
@@ -165,5 +216,7 @@ namespace Nuake
|
||||
|
||||
private:
|
||||
static Input* s_Instance;
|
||||
static Vector2 s_ViewportPos;
|
||||
static Vector2 s_ViewportSize;
|
||||
};
|
||||
}
|
||||
|
||||
134
Nuake/src/Core/MulticastDelegate.h
Normal file
134
Nuake/src/Core/MulticastDelegate.h
Normal file
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#define DECLARE_MULTICAST_DELEGATE(multicastDelegateName, ...) typedef MulticastDelegate<__VA_ARGS__> multicastDelegateName;
|
||||
|
||||
struct DelegateHandle
|
||||
{
|
||||
size_t id = InvalidHandle;
|
||||
|
||||
static inline size_t InvalidHandle = static_cast<size_t>(-1);
|
||||
|
||||
bool IsValid() const { return id != InvalidHandle; }
|
||||
void Reset() { id = InvalidHandle; }
|
||||
|
||||
// Comparison operators for convenience
|
||||
bool operator==(const DelegateHandle& other) const { return id == other.id; }
|
||||
bool operator!=(const DelegateHandle& other) const { return id != other.id; }
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
class MulticastDelegate
|
||||
{
|
||||
public:
|
||||
// Add a callable with bound variables (supports no arguments as well)
|
||||
template<typename Callable, typename... BoundArgs>
|
||||
DelegateHandle AddStatic(Callable&& func, BoundArgs&&... boundArgs)
|
||||
{
|
||||
size_t id = GetNextID();
|
||||
auto boundFunction = [=](Args... args) {
|
||||
if constexpr (sizeof...(Args) > 0)
|
||||
{
|
||||
func(boundArgs..., std::forward<Args>(args)...);
|
||||
}
|
||||
else
|
||||
{
|
||||
func(boundArgs...);
|
||||
}
|
||||
};
|
||||
SetDelegate(id, boundFunction);
|
||||
return DelegateHandle{ id };
|
||||
}
|
||||
|
||||
template<typename Obj, typename Callable, typename... BoundArgs>
|
||||
DelegateHandle AddRaw(Obj* object, Callable&& func, BoundArgs&&... boundArgs)
|
||||
{
|
||||
size_t id = GetNextID();
|
||||
auto boundFunction = [=](Args... args) {
|
||||
if constexpr (sizeof...(Args) > 0)
|
||||
{
|
||||
(object->*func)(boundArgs..., std::forward<Args>(args)...);
|
||||
}
|
||||
else
|
||||
{
|
||||
(object->*func)(boundArgs...);
|
||||
}
|
||||
};
|
||||
SetDelegate(id, boundFunction);
|
||||
return DelegateHandle{ id };
|
||||
}
|
||||
|
||||
// Remove a callable using the token returned by Add()
|
||||
void Remove(DelegateHandle& handle)
|
||||
{
|
||||
ASSERT(handle.IsValid());
|
||||
|
||||
if (handle.IsValid() && handle.id < delegates.size())
|
||||
{
|
||||
delegates[handle.id].active = false;
|
||||
|
||||
// Mark this slot as reusable
|
||||
freeIDs.push_back(handle.id);
|
||||
}
|
||||
|
||||
// Invalidate the handle
|
||||
handle.Reset();
|
||||
}
|
||||
|
||||
// Clear all delegates
|
||||
void Clear()
|
||||
{
|
||||
delegates.clear();
|
||||
freeIDs.clear();
|
||||
nextID = 0;
|
||||
}
|
||||
|
||||
// Invoke all callables
|
||||
void Broadcast(Args... args)
|
||||
{
|
||||
for (auto& delegate : delegates)
|
||||
{
|
||||
if (delegate.active)
|
||||
{
|
||||
delegate.function(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct Delegate
|
||||
{
|
||||
bool active = false;
|
||||
std::function<void(Args...)> function;
|
||||
};
|
||||
|
||||
// A vector of delegates with active state
|
||||
std::vector<Delegate> delegates;
|
||||
// List of reusable slots
|
||||
std::vector<size_t> freeIDs;
|
||||
size_t nextID = 0;
|
||||
|
||||
// Get the next available ID, either by reusing a free slot or by creating a new one
|
||||
size_t GetNextID()
|
||||
{
|
||||
if (!freeIDs.empty())
|
||||
{
|
||||
size_t id = freeIDs.back();
|
||||
freeIDs.pop_back();
|
||||
return id;
|
||||
}
|
||||
|
||||
return nextID++;
|
||||
}
|
||||
|
||||
// Set the delegate in the vector, makes the array larger if necessary
|
||||
void SetDelegate(size_t id, const std::function<void(Args...)>& func)
|
||||
{
|
||||
if (id >= delegates.size())
|
||||
delegates.resize(id + 1);
|
||||
|
||||
delegates[id] = { true, func };
|
||||
}
|
||||
};
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "OS.h"
|
||||
|
||||
#include "src/Window.h"
|
||||
#include "Engine.h"
|
||||
#include "src/Resource/Project.h"
|
||||
#include "src/Window.h"
|
||||
#include "src/Core/String.h"
|
||||
|
||||
#ifdef NK_WIN
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
@@ -18,13 +20,17 @@
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#include "src/FileSystem/File.h"
|
||||
#include "src/FileSystem/Directory.h"
|
||||
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "GLFW/glfw3native.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <imgui/imgui.h>
|
||||
#include <Subprocess.hpp>
|
||||
#include <codecvt>
|
||||
#include <filesystem>
|
||||
#include <Subprocess.hpp>
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "FileSystem.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
|
||||
5
Nuake/src/Core/Object/ClassDB.cpp
Normal file
5
Nuake/src/Core/Object/ClassDB.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "ClassDB.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
}
|
||||
14
Nuake/src/Core/Object/ClassDB.h
Normal file
14
Nuake/src/Core/Object/ClassDB.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class ClassDB
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
static void RegisterComponent(T klass)
|
||||
{
|
||||
T::InternalInitializeClass();
|
||||
}
|
||||
};
|
||||
}
|
||||
173
Nuake/src/Core/Object/Object.h
Normal file
173
Nuake/src/Core/Object/Object.h
Normal file
@@ -0,0 +1,173 @@
|
||||
#pragma once
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
#define NK_HASHED_STATIC_STR(name) inline static constexpr entt::hashed_string name = entt::hashed_string(#name);
|
||||
|
||||
#define NK_ENUM_BITWISE_IMPL(enumClassName) \
|
||||
inline enumClassName operator|(enumClassName lhs, enumClassName rhs) \
|
||||
{ \
|
||||
return static_cast<enumClassName>(ToUnderlying(lhs) | ToUnderlying(rhs)); \
|
||||
} \
|
||||
\
|
||||
inline enumClassName operator&(enumClassName lhs, enumClassName rhs) \
|
||||
{ \
|
||||
return static_cast<enumClassName>(ToUnderlying(lhs) & ToUnderlying(rhs)); \
|
||||
}
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
struct HashedFnName
|
||||
{
|
||||
NK_HASHED_STATIC_STR(GetComponentName)
|
||||
NK_HASHED_STATIC_STR(AddToEntity)
|
||||
NK_HASHED_STATIC_STR(RemoveFromEntity)
|
||||
NK_HASHED_STATIC_STR(ActionName)
|
||||
};
|
||||
|
||||
struct HashedFieldPropName
|
||||
{
|
||||
NK_HASHED_STATIC_STR(FloatStep)
|
||||
NK_HASHED_STATIC_STR(FloatMin)
|
||||
NK_HASHED_STATIC_STR(FloatMax)
|
||||
|
||||
NK_HASHED_STATIC_STR(ResourceFileType)
|
||||
};
|
||||
|
||||
struct HashedName
|
||||
{
|
||||
NK_HASHED_STATIC_STR(DisplayName)
|
||||
};
|
||||
|
||||
enum class ComponentTypeTrait : uint16_t
|
||||
{
|
||||
None = 0,
|
||||
// Exposes the component to be added via the inspector
|
||||
InspectorExposed = 1 << 0,
|
||||
};
|
||||
|
||||
enum class ComponentFuncTrait : uint16_t
|
||||
{
|
||||
None = 0,
|
||||
// Exposes the component to be added via the inspector
|
||||
Action = 1 << 0,
|
||||
};
|
||||
|
||||
enum class ComponentFieldTrait : uint16_t
|
||||
{
|
||||
None = 0,
|
||||
// Stops field from showing up in the editor inspector
|
||||
Internal = 1 << 0,
|
||||
// Marks the field as temporary (ie, do not serialize)
|
||||
Transient = 1 << 1,
|
||||
};
|
||||
|
||||
template <typename Enum>
|
||||
constexpr std::underlying_type_t<Enum> ToUnderlying(Enum e)
|
||||
{
|
||||
return static_cast<std::underlying_type_t<Enum>>(e);
|
||||
}
|
||||
|
||||
NK_ENUM_BITWISE_IMPL(ComponentTypeTrait);
|
||||
NK_ENUM_BITWISE_IMPL(ComponentFuncTrait);
|
||||
NK_ENUM_BITWISE_IMPL(ComponentFieldTrait);
|
||||
}
|
||||
|
||||
#define NUAKECOMPONENT(klass, componentName) \
|
||||
public: \
|
||||
static std::string ClassName() \
|
||||
{ \
|
||||
static std::string className = #klass; \
|
||||
return className; \
|
||||
} \
|
||||
\
|
||||
static std::string ComponentName() \
|
||||
{ \
|
||||
static std::string name = componentName; \
|
||||
return name; \
|
||||
} \
|
||||
\
|
||||
static void AddToEntity(entt::entity entity, entt::registry* enttRegistry) \
|
||||
{ \
|
||||
enttRegistry->emplace_or_replace<klass>(entity); \
|
||||
} \
|
||||
\
|
||||
static void RemoveFromEntity(entt::entity entity, entt::registry* enttRegistry) \
|
||||
{ \
|
||||
enttRegistry->erase<klass>(entity); \
|
||||
} \
|
||||
\
|
||||
\
|
||||
static void (*GetInitializeComponentClass())() \
|
||||
{ \
|
||||
return &klass::InitializeComponentClass; \
|
||||
} \
|
||||
\
|
||||
inline static auto ComponentFactory = entt::meta<klass>(); \
|
||||
static void InternalInitializeClass() \
|
||||
{ \
|
||||
static bool initialized = false; \
|
||||
if (initialized) \
|
||||
return; \
|
||||
\
|
||||
ComponentFactory.type(entt::hashed_string(#klass)) \
|
||||
.traits(ComponentTypeTrait::InspectorExposed); \
|
||||
ComponentFactory.func<&klass::ComponentName>(HashedFnName::GetComponentName); \
|
||||
ComponentFactory.func<&klass::AddToEntity>(HashedFnName::AddToEntity); \
|
||||
ComponentFactory.func<&klass::RemoveFromEntity>(HashedFnName::RemoveFromEntity); \
|
||||
\
|
||||
if (klass::GetInitializeComponentClass() != Component::GetInitializeComponentClass()) \
|
||||
{ \
|
||||
GetInitializeComponentClass()(); \
|
||||
} \
|
||||
\
|
||||
initialized = true; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
template<auto Data> \
|
||||
static auto BindComponentField(const char* varName, const char* displayName) \
|
||||
{ \
|
||||
return ComponentFactory \
|
||||
.data<Data>(entt::hashed_string(varName)) \
|
||||
.prop(HashedName::DisplayName, displayName); \
|
||||
} \
|
||||
\
|
||||
template<auto Getter, auto Setter> \
|
||||
static auto BindComponentProperty(const char* varName, const char* displayName) \
|
||||
{ \
|
||||
return ComponentFactory \
|
||||
.data<Getter, Setter>(entt::hashed_string(varName)) \
|
||||
.prop(HashedName::DisplayName, displayName); \
|
||||
} \
|
||||
\
|
||||
static auto FieldFloatLimits(float stepSize, float min, float max) \
|
||||
{ \
|
||||
return ComponentFactory \
|
||||
.prop(HashedFieldPropName::FloatStep, stepSize) \
|
||||
.prop(HashedFieldPropName::FloatMin, min) \
|
||||
.prop(HashedFieldPropName::FloatMax, max); \
|
||||
} \
|
||||
\
|
||||
static auto ResourceFileRestriction(const char* fileType) \
|
||||
{ \
|
||||
return ComponentFactory \
|
||||
.prop(HashedFieldPropName::ResourceFileType, fileType); \
|
||||
} \
|
||||
\
|
||||
template <typename... Enums> \
|
||||
static auto SetFlags(Enums... enums) \
|
||||
{ \
|
||||
static_assert((std::is_enum_v<Enums> && ...), "All arguments must be of enum class type"); \
|
||||
return ComponentFactory.traits((enums | ...)); \
|
||||
} \
|
||||
\
|
||||
template<auto Func> \
|
||||
static void BindAction(const char* funcName, const char* actionName) \
|
||||
{ \
|
||||
ComponentFactory \
|
||||
.func<Func>(entt::hashed_string(funcName)) \
|
||||
.prop(HashedName::DisplayName, actionName); \
|
||||
SetFlags(ComponentFuncTrait::Action); \
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user