Merge branch 'main' into SP3-1-Rendering

This commit is contained in:
Brandon Mak 2022-11-05 15:10:50 +08:00
commit 09f1b152e8
100 changed files with 8452 additions and 15802 deletions

View File

@ -0,0 +1,4 @@
Start in Fullscreen: false
Starting Scene ID: 94283040
Window Size: {x: 1920, y: 1080}
Window Title: SHADE Engine

Binary file not shown.

View File

@ -1,3 +0,0 @@
Name: Cube.003
ID: 71245919
Type: 4

View File

@ -1,3 +0,0 @@
Name: Cube.012
ID: 80365422
Type: 4

View File

@ -1,16 +1,16 @@
[Window][MainStatusBar] [Window][MainStatusBar]
Pos=0,1060 Pos=0,1007
Size=1920,20 Size=1920,20
Collapsed=0 Collapsed=0
[Window][SHEditorMenuBar] [Window][SHEditorMenuBar]
Pos=0,48 Pos=0,48
Size=1920,1012 Size=1920,959
Collapsed=0 Collapsed=0
[Window][Hierarchy Panel] [Window][Hierarchy Panel]
Pos=0,197 Pos=0,189
Size=308,863 Size=308,818
Collapsed=0 Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
@ -21,13 +21,13 @@ Collapsed=0
[Window][Inspector] [Window][Inspector]
Pos=1528,48 Pos=1528,48
Size=392,1012 Size=392,959
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000006,0
[Window][Profiler] [Window][Profiler]
Pos=0,48 Pos=0,48
Size=308,147 Size=308,139
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
@ -76,7 +76,7 @@ DockId=0x0000000B,0
[Window][ Viewport] [Window][ Viewport]
Pos=310,48 Pos=310,48
Size=1216,715 Size=1216,662
Collapsed=0 Collapsed=0
DockId=0x0000000B,0 DockId=0x0000000B,0
@ -93,13 +93,19 @@ Collapsed=0
DockId=0x0000000A,0 DockId=0x0000000A,0
[Window][ Asset Browser] [Window][ Asset Browser]
Pos=310,765 Pos=310,712
Size=1216,295 Size=1216,295
Collapsed=0 Collapsed=0
DockId=0x0000000C,0 DockId=0x0000000C,0
[Window][Material Inspector]
Pos=1528,48
Size=392,959
Collapsed=0
DockId=0x00000006,1
[Docking][Data] [Docking][Data]
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=0,71 Size=1920,959 Split=X
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881
@ -111,5 +117,5 @@ DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Spli
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6 DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532 DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xE7039252 DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xD3697FB6

View File

@ -0,0 +1,8 @@
- VertexShader: 39210065
FragmentShader: 46377769
SubPass: G-Buffer Write
Properties:
data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 58303057
data.alpha: 0
data.beta: {x: 1, y: 1, z: 1}

View File

@ -0,0 +1,3 @@
Name: BagMaterial
ID: 123745521
Type: 7

View File

@ -0,0 +1,8 @@
- VertexShader: 39210065
FragmentShader: 46377769
SubPass: G-Buffer Write
Properties:
data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 64651793
data.alpha: 0
data.beta: {x: 1, y: 1, z: 1}

View File

@ -0,0 +1,3 @@
Name: TestMat
ID: 126974645
Type: 7

View File

@ -0,0 +1,8 @@
- VertexShader: 39210065
FragmentShader: 46377769
SubPass: G-Buffer Write
Properties:
data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 0
data.alpha: 0
data.beta: {x: 1, y: 1, z: 1}

View File

@ -0,0 +1,3 @@
Name: WhiteMat
ID: 124370424
Type: 7

BIN
Assets/Models/racoon.fbx Normal file

Binary file not shown.

4993
Assets/Models/racoon.gltf Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
Name: racoon
ID: 77816045
Type: 4
Sub Assets:
Name: Bag
ID: 144838771
Type: 8
Name: Raccoon
ID: 149697411
Type: 8

229
Assets/Scenes/M2Scene.shade Normal file
View File

@ -0,0 +1,229 @@
- EID: 0
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Camera Component:
Position: {x: 0, y: 0, z: 0}
Pitch: 0
Yaw: 0
Roll: 0
Width: 1920
Height: 1080
Near: 0.00999999978
Far: 10000
Perspective: true
Light Component:
Position: {x: 0, y: 0, z: 0}
Type: Directional
Direction: {x: 1.79999995, y: 0, z: 1}
Color: {x: 0.951541841, y: 0.921719015, z: 0.553319454, w: 1}
Layer: 4294967295
Strength: 0
Scripts: ~
- EID: 1
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -1.440328, y: -4.41369677, z: -5}
Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 49.4798889, y: 0.5, z: 17.5}
Renderable Component:
Mesh: 149697411
Material: 126974645
RigidBody Component:
Type: Static
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Interpolate: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 0.00427246094, y: 0.000122070312, z: 0.00427246094}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Scripts: ~
- EID: 2
Name: Player
IsActive: true
NumberOfChildren: 3
Components:
Transform Component:
Translate: {x: -3.06177855, y: -2, z: -5}
Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 2, y: 2, z: 2}
Renderable Component:
Mesh: 149697411
Material: 126974645
RigidBody Component:
Type: Dynamic
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Interpolate: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 0.000244140625, y: 0.000244140625, z: 0.000244140625}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts: ~
- EID: 3
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -0.0094268322, y: 0, z: 0}
Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 1, y: 1, z: 1}
Scripts: ~
- EID: 4
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 0, z: 0}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
Scripts: ~
- EID: 9
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 0, z: 0}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
Renderable Component:
Mesh: 144838771
Material: 123745521
Scripts: ~
- EID: 5
Name: item
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: -2, z: -5}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 2, y: 2, z: 2}
Renderable Component:
Mesh: 144838771
Material: 126974645
RigidBody Component:
Type: Dynamic
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Interpolate: false
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: true
Freeze Rotation Y: true
Freeze Rotation Z: true
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 0.000244140625, y: 0.000244140625, z: 0.000244140625}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
- Is Trigger: true
Type: Box
Half Extents: {x: 0.00048828125, y: 0.00048828125, z: 0.00048828125}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts: ~
- EID: 6
Name: AI
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -8, y: -2, z: 2.5}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 2, y: 2, z: 2}
Renderable Component:
Mesh: 149697411
Material: 126974645
RigidBody Component:
Type: Dynamic
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Interpolate: false
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: true
Freeze Rotation Y: true
Freeze Rotation Z: true
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 0.000244140625, y: 0.000244140625, z: 0.000244140625}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts: ~
- EID: 7
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 3, y: -1, z: -1}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 5, y: 5, z: 5}
Renderable Component:
Mesh: 149697411
Material: 126974645
Scripts: ~
- EID: 8
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Light Component:
Position: {x: 0, y: 0, z: 0}
Type: Ambient
Direction: {x: 0, y: 0, z: 1}
Color: {x: 1, y: 1, z: 1, w: 1}
Layer: 4294967295
Strength: 0.25
Scripts: ~

View File

@ -0,0 +1,3 @@
Name: M2Scene
ID: 94283040
Type: 5

View File

@ -0,0 +1,72 @@
- EID: 0
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 0.304069757, z: 1.73034382}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
Camera Component:
Position: {x: 0, y: 0.304069757, z: 1.73034382}
Pitch: 0
Yaw: 0
Roll: 0
Width: 1200
Height: 1080
Near: 0.00999999978
Far: 10000
Perspective: true
Scripts: ~
- EID: 1
Name: Raccoon
IsActive: true
NumberOfChildren: 1
Components:
Transform Component:
Translate: {x: 0, y: 0, z: 0}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
Renderable Component:
Mesh: 149697411
Material: 126974645
Scripts: ~
- EID: 3
Name: Bag
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0.006237939, y: -0.000393368304, z: 0}
Rotate: {x: -0, y: 2.79945588, z: 0}
Scale: {x: 1.0000881, y: 1, z: 1.0000881}
Renderable Component:
Mesh: 144838771
Material: 123745521
Scripts: ~
- EID: 2
Name: DirectionalLight
IsActive: true
NumberOfChildren: 0
Components:
Light Component:
Position: {x: 0, y: 0, z: 0}
Type: Directional
Direction: {x: 0, y: 0, z: 1}
Color: {x: 1, y: 1, z: 1, w: 1}
Layer: 4294967295
Strength: 0
Scripts: ~
- EID: 4
Name: AmbientLight
IsActive: true
NumberOfChildren: 0
Components:
Light Component:
Position: {x: 0, y: 0, z: 0}
Type: Ambient
Direction: {x: 0, y: 0, z: 1}
Color: {x: 1, y: 1, z: 1, w: 1}
Layer: 4294967295
Strength: 0.600000024
Scripts: ~

View File

@ -0,0 +1,3 @@
Name: Scene2
ID: 87285316
Type: 5

View File

@ -43,7 +43,7 @@ void main()
{ {
position = In.vertPos; position = In.vertPos;
normals = In.normal; normals = In.normal;
albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) + MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha; albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) * MatProp.data[In2.materialIndex].color;
outEntityID = In2.eid; outEntityID = In2.eid;
lightLayerIndices = In2.lightLayerIndex; lightLayerIndices = In2.lightLayerIndex;

Binary file not shown.

View File

@ -7,7 +7,7 @@ echo "SHADE DEPENDENCIES (Default - All in 10 Seconds)"
echo "A - All" echo "A - All"
echo "B - VMA" echo "B - VMA"
echo "C - msdf" echo "C - msdf"
echo "D - assimp" echo "D - ModelCompiler"
echo "E - spdlog" echo "E - spdlog"
echo "F - reactphysics3d" echo "F - reactphysics3d"
echo "G - imgui" echo "G - imgui"
@ -29,7 +29,7 @@ set _e=%ERRORLEVEL%
if %_e%==1 goto VMA if %_e%==1 goto VMA
if %_e%==2 goto VMA if %_e%==2 goto VMA
if %_e%==3 goto MSDF if %_e%==3 goto MSDF
if %_e%==4 goto assimp if %_e%==4 goto ModelCompiler
if %_e%==5 goto spdlog if %_e%==5 goto spdlog
if %_e%==6 goto reactphysics3d if %_e%==6 goto reactphysics3d
if %_e%==7 goto imgui if %_e%==7 goto imgui
@ -53,12 +53,13 @@ if %_e%==2 (goto :done) else (goto :MSDF)
echo -----------------------MSDF---------------------------- echo -----------------------MSDF----------------------------
rmdir "Dependencies/msdf" /S /Q rmdir "Dependencies/msdf" /S /Q
git clone --recurse-submodules https://github.com/SHADE-DP/msdf-atlas-gen.git "Dependencies/msdf" git clone --recurse-submodules https://github.com/SHADE-DP/msdf-atlas-gen.git "Dependencies/msdf"
if %_e%==3 (goto :done) else (goto :assimp) if %_e%==3 (goto :done) else (goto :ModelCompiler)
:assimp :ModelCompiler
echo -----------------------assimp---------------------------- echo -----------------------ModelCompiler----------------------------
rmdir "Dependencies/assimp" /S /Q rmdir "Dependencies/ModelCompiler" /S /Q
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/assimp" git clone https://github.com/SHADE-DP/ModelCompiler.git "Dependencies/ModelCompiler"
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/ModelCompiler/Dependencies/assimp"
if %_e%==4 (goto :done) else (goto :spdlog) if %_e%==4 (goto :done) else (goto :spdlog)
@REM :ktx @REM :ktx

View File

@ -1,5 +1,5 @@
IncludeDir = {} IncludeDir = {}
IncludeDir["assimp"] = "%{wks.location}\\Dependencies\\assimp" IncludeDir["ModelCompiler"] = "%{wks.location}\\Dependencies\\ModelCompiler"
IncludeDir["imgui"] = "%{wks.location}\\Dependencies\\imgui" IncludeDir["imgui"] = "%{wks.location}\\Dependencies\\imgui"
IncludeDir["imguizmo"] = "%{wks.location}\\Dependencies\\imguizmo" IncludeDir["imguizmo"] = "%{wks.location}\\Dependencies\\imguizmo"
IncludeDir["imnodes"] = "%{wks.location}\\Dependencies\\imnodes" IncludeDir["imnodes"] = "%{wks.location}\\Dependencies\\imnodes"

View File

@ -41,6 +41,8 @@
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Scenes/SBMainScene.h"
#include "Serialization/Configurations/SHConfigurationManager.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "Tools/SHDebugDraw.h" #include "Tools/SHDebugDraw.h"
@ -60,8 +62,9 @@ namespace Sandbox
{ {
// Set working directory // Set working directory
SHFileUtilities::SetWorkDirToExecDir(); SHFileUtilities::SetWorkDirToExecDir();
WindowData wndData{};
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); auto& appConfig = SHConfigurationManager::LoadApplicationConfig(&wndData);
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
// Create Systems // Create Systems
SHSystemManager::CreateSystem<SHGraphicsSystem>(); SHSystemManager::CreateSystem<SHGraphicsSystem>();
@ -80,7 +83,11 @@ namespace Sandbox
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND()); sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
SHSystemManager::CreateSystem<SHEditor>(); SHSystemManager::CreateSystem<SHEditor>();
SHSystemManager::GetSystem<SHEditor>()->SetSDLWindow(sdlWindow); if(auto editor = SHSystemManager::GetSystem<SHEditor>())
{
editor->SetSDLWindow(sdlWindow);
editor->SetSHWindow(&window);
}
#endif #endif
// Create Routines // Create Routines
@ -128,7 +135,7 @@ namespace Sandbox
SHSystemManager::Init(); SHSystemManager::Init();
SHSceneManager::InitSceneManager<SBTestScene>("TestScene"); SHSceneManager::InitSceneManager<SBMainScene>(appConfig.startingSceneID);
SHFrameRateController::UpdateFRC(); SHFrameRateController::UpdateFRC();
@ -154,7 +161,7 @@ namespace Sandbox
editor->PollPicking(); editor->PollPicking();
static bool drawColliders = false; static bool drawColliders = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::SPACE)) if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
{ {
drawColliders = !drawColliders; drawColliders = !drawColliders;
SHSystemManager::GetSystem<SHPhysicsSystem>()->SetDrawColliders(drawColliders); SHSystemManager::GetSystem<SHPhysicsSystem>()->SetDrawColliders(drawColliders);

View File

@ -0,0 +1,62 @@
#include "SBpch.h"
#include "SBMainScene.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Scripting/SHScriptEngine.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Physics/Components/SHRigidBodyComponent.h"
#include "Physics/Components/SHColliderComponent.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
#include "Assets/SHAssetManager.h"
#include "Camera/SHCameraComponent.h"
#include "Resource/SHResourceManager.h"
#include "Serialization/SHSerialization.h"
using namespace SHADE;
namespace Sandbox
{
void SBMainScene::WindowFocusFunc([[maybe_unused]] void* window, int focused)
{
if (focused)
{
}
else
{
}
}
void SBMainScene::Load()
{
}
void SBMainScene::Init()
{
sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID);
}
void SBMainScene::Update(float dt)
{
}
void SBMainScene::Render()
{
}
void SBMainScene::Unload()
{
}
void SBMainScene::Free()
{
//SHSerialization::SerializeScene("resources/scenes/Scene01.SHADE");
}
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "Scene/SHScene.h"
#include "Scene/SHSceneManager.h"
namespace Sandbox
{
class SBMainScene : public SHADE::SHScene
{
private:
EntityID camera;
EntityID testObj;
std::vector<EntityID> stressTestObjects;
public:
virtual void Load();
virtual void Init();
virtual void Update(float dt);
virtual void Render();
virtual void Free();
virtual void Unload();
//TODO: Change to new window DO IT IN CPP TOO
void WindowFocusFunc(void* window, int focused);
SBMainScene(void) = default;
};
}

View File

@ -53,7 +53,7 @@ namespace Sandbox
switch (asset.type) switch (asset.type)
{ {
case AssetType::MESH: case AssetType::MESH:
if (asset.name == "Cube.012") if (asset.name == "Raccoon")
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id)); handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
break; break;
case AssetType::TEXTURE: case AssetType::TEXTURE:
@ -65,58 +65,20 @@ namespace Sandbox
SHResourceManager::FinaliseChanges(); SHResourceManager::FinaliseChanges();
// Create Materials // Create Materials
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance(); auto baseRaccoonMat = graphicsSystem->AddOrGetBaseMaterialInstance();
auto customMat = graphicsSystem->AddMaterialInstanceCopy(matInst); auto baseRaccoonMatInstant = graphicsSystem->AddMaterialInstanceCopy(baseRaccoonMat);
customMat->SetProperty("data.color", SHVec4(0.0f, 1.0f, 1.0f, 1.0f)); baseRaccoonMatInstant->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
customMat->SetProperty("data.textureIndex", 0); baseRaccoonMatInstant->SetProperty("data.textureIndex", 0);
customMat->SetProperty("data.alpha", 0.1f); baseRaccoonMatInstant->SetProperty("data.alpha", 0.1f);
// Create Stress Test Objects auto baseFloorMatInstant = graphicsSystem->AddMaterialInstanceCopy(baseRaccoonMat);
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One; baseFloorMatInstant->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
constexpr int NUM_ROWS = 3; baseFloorMatInstant->SetProperty("data.textureIndex", 0);
constexpr int NUM_COLS = 1; baseFloorMatInstant->SetProperty("data.alpha", 0.1f);
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
for (int y = 0; y < NUM_ROWS; ++y) auto dummy = SHEntityManager::CreateEntity<>();
for (int x = 0; x < NUM_COLS; ++x)
{
auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>();
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
//renderable.Mesh = handles.front(); auto floor = SHEntityManager::CreateEntity<SHTransformComponent,SHRenderable, SHRigidBodyComponent, SHColliderComponent>();
renderable.SetMesh(CUBE_MESH);
renderable.SetMaterial(customMat);
if (y == 50)
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f));
//Set initial positions
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) });
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
transform.SetWorldScale(TEST_OBJ_SCALE);
collider.AddBoundingBox(SHVec3::One, SHVec3::Zero);
stressTestObjects.emplace_back(entity);
}
auto raccoonSpin = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
renderable.SetMesh(handles.front());
renderable.SetMaterial(customMat);
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
transform.SetWorldPosition({ -3.0f, -1.0f, -1.0f });
transform.SetLocalScale({ 5.0f, 5.0f, 5.0f });
auto floor = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>();
auto& floorRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(floor); auto& floorRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(floor);
auto& floorTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(floor); auto& floorTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(floor);
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor); auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
@ -125,7 +87,7 @@ namespace Sandbox
floorRenderable.SetMesh(CUBE_MESH); floorRenderable.SetMesh(CUBE_MESH);
floorRenderable.SetMaterial(graphicsSystem->GetDefaultMaterialInstance()); floorRenderable.SetMaterial(graphicsSystem->GetDefaultMaterialInstance());
floorTransform.SetWorldScale({ 7.5f, 0.5f, 7.5 }); floorTransform.SetWorldScale({ 17.5f, 0.5f, 17.5f });
floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f }); floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f });
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
@ -138,17 +100,97 @@ namespace Sandbox
//testObjRenderable.Mesh = CUBE_MESH; //testObjRenderable.Mesh = CUBE_MESH;
//testObjRenderable.SetMaterial(matInst); //testObjRenderable.SetMaterial(matInst);
//raccoon =======================================================================================================================
auto racoon = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>(MAX_EID, "Player");
auto& racoonRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(racoon);
auto& racoonTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoon);
auto& racoonRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(racoon);
auto& racoonCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(racoon);
racoonRenderable.SetMesh(handles.front());
racoonRenderable.SetMaterial(baseRaccoonMatInstant);
racoonTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f });
racoonCollider.AddBoundingBox();
racoonCollider.GetCollider(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f));
racoonCollider.GetCollider(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
auto racoonItemLocation = SHEntityManager::CreateEntity<SHTransformComponent>();
auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoonItemLocation);
SHSceneManager::GetCurrentSceneGraph().SetParent(racoonItemLocation, racoon);
auto racoonCamera = SHEntityManager::CreateEntity<SHTransformComponent>();
SHSceneManager::GetCurrentSceneGraph().SetParent(racoonCamera, racoon);
//================================================================================================================================
//item ===========================================================================================================================
auto item = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>(MAX_EID, "item");
auto& itemRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(item);
auto& itemTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(item);
auto& itemRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(item);
auto& itemCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(item);
itemRenderable.SetMesh(handles.front());
itemRenderable.SetMaterial(baseRaccoonMatInstant);
itemTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
itemTransform.SetWorldPosition({ 0.0f, -2.0f, -5.0f });
itemCollider.AddBoundingBox();
itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f));
itemCollider.GetCollider(1).SetIsTrigger(true);
itemCollider.GetCollider(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
itemCollider.GetCollider(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
itemCollider.GetCollider(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
itemCollider.GetCollider(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f));
itemRigidBody.SetInterpolate(false);
itemRigidBody.SetFreezeRotationX(true);
itemRigidBody.SetFreezeRotationY(true);
itemRigidBody.SetFreezeRotationZ(true);
//================================================================================================================================
//AI =============================================================================================================================
auto AI = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>(MAX_EID, "AI");
auto& AIRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(AI);
auto& AITransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(AI);
auto& AIRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(AI);
auto& AICollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(AI);
AIRenderable.SetMesh(handles.front());
AIRenderable.SetMaterial(baseRaccoonMatInstant);
AITransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f });
AICollider.AddBoundingBox();
AICollider.GetCollider(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
AICollider.GetCollider(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
AIRigidBody.SetInterpolate(false);
AIRigidBody.SetFreezeRotationX(true);
AIRigidBody.SetFreezeRotationY(true);
AIRigidBody.SetFreezeRotationZ(true);
//================================================================================================================================
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>()); SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
scriptEngine->AddScript(raccoonSpin, "RaccoonSpin"); scriptEngine->AddScript(racoon, "PlayerController");
scriptEngine->AddScript(racoon, "PickAndThrow");
scriptEngine->AddScript(racoonCamera, "ThirdPersonCamera");
scriptEngine->AddScript(AI, "AIPrototype");
scriptEngine->AddScript(item, "Item");
auto raccoonShowcase = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>(); auto raccoonShowcase = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase); auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase); auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
renderableShowcase.SetMesh(handles.front()); renderableShowcase.SetMesh(handles.front());
renderableShowcase.SetMaterial(customMat); renderableShowcase.SetMaterial(baseRaccoonMatInstant);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0); renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);

View File

@ -26,7 +26,6 @@ project "SHADE_Engine"
externalincludedirs externalincludedirs
{ {
"%{IncludeDir.assimp}\\include",
"%{IncludeDir.imgui}", "%{IncludeDir.imgui}",
"%{IncludeDir.imguizmo}", "%{IncludeDir.imguizmo}",
"%{IncludeDir.imnodes}", "%{IncludeDir.imnodes}",
@ -52,8 +51,6 @@ project "SHADE_Engine"
{ {
"%{prj.location}/libs", "%{prj.location}/libs",
"%{IncludeDir.VULKAN}/Lib", "%{IncludeDir.VULKAN}/Lib",
"%{IncludeDir.assimp}/lib/Debug",
"%{IncludeDir.assimp}/lib/Release",
"%{IncludeDir.RTTR}/lib", "%{IncludeDir.RTTR}/lib",
"%{IncludeDir.SDL}/lib", "%{IncludeDir.SDL}/lib",
"%{IncludeDir.spdlog}/lib", "%{IncludeDir.spdlog}/lib",
@ -119,7 +116,8 @@ project "SHADE_Engine"
filter "configurations:Debug" filter "configurations:Debug"
postbuildcommands postbuildcommands
{ {
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\"", "xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Debug\\ModelCompiler.exe\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodL.dll\" \"$(OutDir)\"", "xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodL.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\"" "xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\""
} }
@ -127,7 +125,8 @@ project "SHADE_Engine"
filter "configurations:Release" filter "configurations:Release"
postbuildcommands postbuildcommands
{ {
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"", "xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Release\\ModelCompiler.exe\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"", "xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\"" "xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
} }
@ -135,32 +134,35 @@ project "SHADE_Engine"
filter "configurations:Publish" filter "configurations:Publish"
postbuildcommands postbuildcommands
{ {
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"", --"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"", "xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\"" "xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
} }
filter "configurations:Publish" filter "configurations:Publish"
postbuildcommands {"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""} postbuildcommands
{
--"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""
}
warnings 'Extra' warnings 'Extra'
filter "configurations:Debug" filter "configurations:Debug"
symbols "On" symbols "On"
defines {"_DEBUG", "SHEDITOR"} defines {"_DEBUG", "SHEDITOR"}
links{"assimp-vc142-mtd.lib", "librttr_core_d.lib", "spdlogd.lib"} links{"librttr_core_d.lib", "spdlogd.lib"}
links{"fmodstudioL_vc.lib", "fmodL_vc.lib"} links{"fmodstudioL_vc.lib", "fmodL_vc.lib"}
filter "configurations:Release" filter "configurations:Release"
optimize "On" optimize "On"
defines{"_RELEASE", "SHEDITOR"} defines{"_RELEASE", "SHEDITOR"}
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"} links{"librttr_core.lib", "spdlog.lib"}
links{"fmodstudio_vc.lib", "fmod_vc.lib"} links{"fmodstudio_vc.lib", "fmod_vc.lib"}
filter "configurations:Publish" filter "configurations:Publish"
optimize "On" optimize "On"
defines{"_RELEASE", "_PUBLISH"} defines{"_RELEASE", "_PUBLISH"}
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"} links{"librttr_core.lib", "spdlog.lib"}
excludes excludes
{ {
-- "%{prj.location}/src/Editor/**.cpp", -- "%{prj.location}/src/Editor/**.cpp",

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "SHMeshAsset.h" #include "SHModelAsset.h"
#include "SHTextureAsset.h" #include "SHTextureAsset.h"

View File

@ -18,24 +18,31 @@
namespace SHADE namespace SHADE
{ {
struct SH_API SHMeshAssetHeader struct SHMeshAssetHeader
{ {
uint32_t vertexCount; uint32_t vertexCount;
uint32_t indexCount; uint32_t indexCount;
std::string name; std::string name;
}; };
struct SH_API SHMeshAsset : SHAssetData struct SHModelAssetHeader
{ {
bool compiled; size_t meshCount;
bool changed; };
struct SH_API SHMeshData : SHAssetData
{
SHMeshAssetHeader header; SHMeshAssetHeader header;
std::vector<SHVec3> VertexPositions;
std::vector<SHVec3> VertexTangents;
std::vector<SHVec3> VertexNormals;
std::vector<SHVec2> VertexTexCoords;
std::vector<uint32_t> Indices;
};
std::vector<SHVec3> vertexPosition; struct SH_API SHModelAsset : SHAssetData
std::vector<SHVec3> vertexTangent; {
std::vector<SHVec3> vertexNormal; SHModelAssetHeader header;
std::vector<SHVec2> texCoords; std::vector<SHMeshData*> subMeshes;
std::vector<uint32_t> indices;
}; };
} }

View File

@ -1,201 +0,0 @@
/*************************************************************************//**
* \file SHMeshCompiler.cpp
* \author Loh Xiao Qi
* \date 30 September 2022
* \brief Library to write data in SHMeshAsset into binary file for faster
* loading in the future
*
*
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
*****************************************************************************/
#include "SHpch.h"
#include "SHMeshCompiler.h"
#include "Graphics/MiddleEnd/Meshes/SHMeshData.h"
#include <assimp/postprocess.h>
#include <fstream>
namespace SHADE
{
Assimp::Importer SHMeshCompiler::aiImporter;
void SHMeshCompiler::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
{
for (size_t i{ 0 }; i < node.mNumMeshes; ++i)
{
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
meshes.push_back(ProcessMesh(*mesh));
}
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
{
ProcessNode(*node.mChildren[i], scene, meshes);
}
}
void SHMeshCompiler::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
{
if (scene.HasAnimations())
{
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
for (auto i{ 0 }; i < scene.mNumAnimations; ++i)
{
auto const& anim{ *scene.mAnimations[i] };
anims[i].name = anim.mName.C_Str();
anims[i].duration = anim.mDuration;
anims[i].ticksPerSecond = anim.mTicksPerSecond;
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
}
}
}
SHMeshAsset* SHMeshCompiler::ProcessMesh(aiMesh const& mesh) noexcept
{
SHMeshAsset* result = new SHMeshAsset();
result->compiled = false;
result->changed = false;
for (size_t i{ 0 }; i < mesh.mNumVertices; ++i)
{
// Vertex position
SHVec3 vertex;
vertex.x = mesh.mVertices[i].x;
vertex.y = mesh.mVertices[i].y;
vertex.z = mesh.mVertices[i].z;
result->vertexPosition.push_back(vertex);
// Tex coords
SHVec2 texCoord{ 0.f, 0.f };
if (mesh.mTextureCoords[0])
{
texCoord.x = mesh.mTextureCoords[0][i].x;
texCoord.y = mesh.mTextureCoords[0][i].y;
}
result->texCoords.push_back(texCoord);
// Normals
SHVec3 normal{ 0.f, 0.f, 0.f };
if (mesh.mNormals)
{
normal.x = mesh.mNormals[i].x;
normal.y = mesh.mNormals[i].y;
normal.z = mesh.mNormals[i].z;
}
result->vertexNormal.push_back(normal);
// Tangent
SHVec3 tangent{ 0.f, 0.f, 0.f };
if (mesh.mTangents)
{
tangent.x = mesh.mTangents[i].x;
tangent.y = mesh.mTangents[i].y;
tangent.z = mesh.mTangents[i].z;
}
result->vertexTangent.push_back(tangent);
}
for (size_t i{ 0 }; i < mesh.mNumFaces; ++i)
{
aiFace face = mesh.mFaces[i];
for (size_t j{ 0 }; j < face.mNumIndices; ++j)
{
result->indices.push_back(face.mIndices[j]);
}
}
result->header.vertexCount = static_cast<uint32_t>(result->vertexPosition.size());
result->header.indexCount = static_cast<uint32_t>(result->indices.size());
result->header.name = mesh.mName.C_Str();
return result;
}
void SHMeshCompiler::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
{
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
| aiProcess_RemoveRedundantMaterials // remove redundant materials
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
);
if (!scene || !scene->HasMeshes())
{
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
return;
}
//ExtractAnimations(*scene, anims);
ProcessNode(*scene->mRootNode, *scene, meshes);
aiImporter.FreeScene();
}
std::optional<AssetPath> SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
{
std::string newPath{ path.parent_path().string() + '/' };
newPath += asset.header.name + MESH_EXTENSION.data();
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
if (!file.is_open())
{
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
}
file.write(
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
sizeof(uint32_t)
);
file.write(
reinterpret_cast<const char*>(&(asset.header.indexCount)),
sizeof(uint32_t)
);
auto const vertexVec3Byte{ sizeof(SHVec3) * asset.header.vertexCount };
auto const vertexVec2Byte{ sizeof(SHVec2) * asset.header.vertexCount };
file.write(
reinterpret_cast<char const*>(asset.vertexPosition.data()),
vertexVec3Byte
);
file.write(
reinterpret_cast<char const*>(asset.vertexTangent.data()),
vertexVec3Byte
);
file.write(
reinterpret_cast<char const*>(asset.vertexNormal.data()),
vertexVec3Byte
);
file.write(
reinterpret_cast<char const*>(asset.texCoords.data()),
vertexVec2Byte
);
file.write(
reinterpret_cast<char const*>(asset.indices.data()),
sizeof(uint32_t) * asset.header.indexCount
);
file.close();
return newPath;
}
}

View File

@ -1,40 +0,0 @@
/*************************************************************************//**
* \file SHMeshCompiler.h
* \author Loh Xiao Qi
* \date 30 September 2022
* \brief Library to write data in SHMeshAsset into binary file for faster
* loading in the future
*
*
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
*****************************************************************************/
#pragma once
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <vector>
#include "Assets/Asset Types/SHAnimationAsset.h"
#include "Assets/Asset Types/SHMeshAsset.h"
#include "Assets/SHAssetMacros.h"
namespace SHADE
{
class SHMeshCompiler
{
using MeshVectorRef = std::vector<SHMeshAsset*>&;
using AnimVectorRef = std::vector<SHAnimationAsset*>&;
static Assimp::Importer aiImporter;
static void ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept;
static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
public:
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
static std::optional<AssetPath> CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
};
}

View File

@ -1,130 +0,0 @@
/*************************************************************************//**
* \file SHMeshLoader.cpp
* \author Loh Xiao Qi
* \date 30 September 2022
* \brief Implementation for Mesh loader. Accounts for custom binary format
* as well as GLTF file format.
*
*
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
*****************************************************************************/
#include "SHpch.h"
#include "SHMeshLoader.h"
#include <fstream>
namespace SHADE
{
void SHMeshLoader::LoadSHMesh(AssetPath path, SHMeshAsset& mesh) noexcept
{
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
if (!file.is_open())
{
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
return;
}
const std::string name{ path.stem().string() };
file.seekg(0);
uint32_t vertCount, indexCount;
std::vector<SHVec3> vertPos, vertTan, vertNorm;
std::vector<SHVec2> texCoord;
std::vector<uint32_t> indices;
file.read(reinterpret_cast<char*>(&vertCount), sizeof(uint32_t));
file.read(reinterpret_cast<char*>(&indexCount), sizeof(uint32_t));
auto const vertexVec3Byte{ sizeof(SHVec3) * vertCount };
auto const vertexVec2Byte{ sizeof(SHVec2) * vertCount };
vertPos.resize(vertCount);
vertTan.resize(vertCount);
vertNorm.resize(vertCount);
texCoord.resize(vertCount);
indices.resize(indexCount);
file.read(reinterpret_cast<char *>(vertPos.data()), vertexVec3Byte);
file.read(reinterpret_cast<char *>(vertTan.data()), vertexVec3Byte);
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
mesh.compiled = true;
mesh.changed = false;
mesh.header.indexCount = indexCount;
mesh.header.vertexCount = vertCount;
mesh.header.name = name;
mesh.vertexPosition = std::move(vertPos);
mesh.vertexTangent = std::move(vertTan);
mesh.vertexNormal = std::move(vertNorm);
mesh.texCoords = std::move(texCoord);
mesh.indices = std::move(indices);
file.close();
}
SHAssetData* SHMeshLoader::Load(AssetPath path)
{
auto result = new SHMeshAsset();
LoadSHMesh(path, *result);
return result;
}
void SHMeshLoader::Write(SHAssetData const* data, AssetPath path)
{
std::ofstream file{ path, std::ios::out | std::ios::binary | std::ios::trunc };
if (!file.is_open())
{
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
}
auto asset = *dynamic_cast<SHMeshAsset const*>(data);
file.write(
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
sizeof(uint32_t)
);
file.write(
reinterpret_cast<const char*>(&(asset.header.indexCount)),
sizeof(uint32_t)
);
auto const vertexVec3Byte{ sizeof(SHVec3) * asset.header.vertexCount };
auto const vertexVec2Byte{ sizeof(SHVec2) * asset.header.vertexCount };
file.write(
reinterpret_cast<char const*>(asset.vertexPosition.data()),
vertexVec3Byte
);
file.write(
reinterpret_cast<char const*>(asset.vertexTangent.data()),
vertexVec3Byte
);
file.write(
reinterpret_cast<char const*>(asset.vertexNormal.data()),
vertexVec3Byte
);
file.write(
reinterpret_cast<char const*>(asset.texCoords.data()),
vertexVec2Byte
);
file.write(
reinterpret_cast<char const*>(asset.indices.data()),
sizeof(uint32_t) * asset.header.indexCount
);
file.close();
}
}

View File

@ -0,0 +1,91 @@
/*************************************************************************//**
* \file SHModelLoader.cpp
* \author Loh Xiao Qi
* \date 30 September 2022
* \brief Implementation for Mesh loader. Accounts for custom binary format
* as well as GLTF file format.
*
*
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
*****************************************************************************/
#include "SHpch.h"
#include "SHModelLoader.h"
#include <fstream>
namespace SHADE
{
void SHModelLoader::ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept
{
file.read(
reinterpret_cast<char*>(&header),
sizeof(SHMeshLoaderHeader)
);
}
void SHModelLoader::ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshData& data) noexcept
{
auto const vertexVec3Byte{ sizeof(SHVec3) * header.vertexCount };
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
data.VertexPositions.resize(header.vertexCount);
data.VertexTangents.resize(header.vertexCount);
data.VertexNormals.resize(header.vertexCount);
data.VertexTexCoords.resize(header.vertexCount);
data.Indices.resize(header.indexCount);
data.header.name.resize(header.charCount);
file.read(data.header.name.data(), header.charCount);
file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte);
file.read(reinterpret_cast<char*>(data.VertexTangents.data()), vertexVec3Byte);
file.read(reinterpret_cast<char*>(data.VertexNormals.data()), vertexVec3Byte);
file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte);
file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount);
data.header.vertexCount = header.vertexCount;
data.header.indexCount = header.indexCount;
}
void SHModelLoader::LoadSHMesh(AssetPath path, SHModelAsset& model) noexcept
{
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
if (!file.is_open())
{
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
return;
}
file.seekg(0);
file.read(
reinterpret_cast<char*>(&model.header),
sizeof(SHModelAssetHeader)
);
std::vector<SHMeshLoaderHeader> headers(model.header.meshCount);
model.subMeshes.resize(model.header.meshCount);
for (auto i{ 0 }; i < model.header.meshCount; ++i)
{
model.subMeshes[i] = new SHMeshData();
ReadHeader(file, headers[i]);
ReadData(file, headers[i], *model.subMeshes[i]);
}
file.close();
}
SHAssetData* SHModelLoader::Load(AssetPath path)
{
auto result = new SHModelAsset();
LoadSHMesh(path, *result);
return result;
}
void SHModelLoader::Write(SHAssetData const* data, AssetPath path)
{
}
}

View File

@ -1,5 +1,5 @@
/*************************************************************************//** /*************************************************************************//**
* \file SHMeshLoader.h * \file SHModelLoader.h
* \author Loh Xiao Qi * \author Loh Xiao Qi
* \date 30 September 2022 * \date 30 September 2022
* \brief Library to load gltf mesh files and custom binary format * \brief Library to load gltf mesh files and custom binary format
@ -10,14 +10,27 @@
* of DigiPen Institute of Technology is prohibited. * of DigiPen Institute of Technology is prohibited.
*****************************************************************************/ *****************************************************************************/
#pragma once #pragma once
#include "Assets/Asset Types/SHMeshAsset.h" #include "Assets/Asset Types/SHModelAsset.h"
#include "SHAssetLoader.h" #include "SHAssetLoader.h"
#include <fstream>
namespace SHADE namespace SHADE
{ {
struct SHMeshLoader : SHAssetLoader class SHModelLoader : public SHAssetLoader
{ {
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept; struct SHMeshLoaderHeader
{
uint32_t vertexCount;
uint32_t indexCount;
uint32_t charCount;
};
void ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept;
void ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshData& data) noexcept;
public:
void LoadSHMesh(AssetPath path, SHModelAsset& model) noexcept;
SHAssetData* Load(AssetPath path) override; SHAssetData* Load(AssetPath path) override;
void Write(SHAssetData const* data, AssetPath path) override; void Write(SHAssetData const* data, AssetPath path) override;
}; };

View File

@ -22,5 +22,10 @@ namespace SHADE
AssetID id; AssetID id;
AssetType type; AssetType type;
AssetPath path; AssetPath path;
bool isSubAsset;
std::vector<SHAsset*> subAssets;
AssetID parent;
}; };
} }

View File

@ -47,10 +47,11 @@ enum class AssetType : AssetTypeMeta
SHADER, SHADER,
SHADER_BUILT_IN, SHADER_BUILT_IN,
TEXTURE, TEXTURE,
MESH, MODEL,
SCENE, SCENE,
PREFAB, PREFAB,
MATERIAL, MATERIAL,
MESH,
MAX_COUNT MAX_COUNT
}; };
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) }; constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
@ -64,6 +65,9 @@ constexpr std::string_view ASSET_ROOT {"../../Assets"};
constexpr std::string_view BUILT_IN_ASSET_ROOT{ "../../Built_In" }; constexpr std::string_view BUILT_IN_ASSET_ROOT{ "../../Built_In" };
#endif #endif
// COMPILER PATHS
constexpr std::string_view MODEL_COMPILER_EXE{ "ModelCompiler.exe" };
// INTERNAL ASSET PATHS // INTERNAL ASSET PATHS
constexpr std::string_view SCENE_FOLDER{ "/Scenes/" }; constexpr std::string_view SCENE_FOLDER{ "/Scenes/" };
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" }; constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" };
@ -81,7 +85,7 @@ constexpr std::string_view SCENE_EXTENSION {".shade"};
constexpr std::string_view PREFAB_EXTENSION {".shprefab"}; constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
constexpr std::string_view MATERIAL_EXTENSION {".shmat"}; constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
constexpr std::string_view TEXTURE_EXTENSION {".shtex"}; constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
constexpr std::string_view MESH_EXTENSION {".shmesh"}; constexpr std::string_view MODEL_EXTENSION {".shmodel"};
constexpr std::string_view EXTENSIONS[] = { constexpr std::string_view EXTENSIONS[] = {
AUDIO_EXTENSION, AUDIO_EXTENSION,
@ -89,7 +93,7 @@ constexpr std::string_view EXTENSIONS[] = {
SHADER_BUILT_IN_EXTENSION, SHADER_BUILT_IN_EXTENSION,
MATERIAL_EXTENSION, MATERIAL_EXTENSION,
TEXTURE_EXTENSION, TEXTURE_EXTENSION,
MESH_EXTENSION, MODEL_EXTENSION,
SCRIPT_EXTENSION, SCRIPT_EXTENSION,
SCENE_EXTENSION, SCENE_EXTENSION,
PREFAB_EXTENSION, PREFAB_EXTENSION,

View File

@ -11,15 +11,17 @@
#include <random> #include <random>
#include <chrono> #include <chrono>
#include <ranges> #include <ranges>
#include <cstdlib>
#include "SHAssetManager.h" #include "SHAssetManager.h"
#include "SHAssetMetaHandler.h" #include "SHAssetMetaHandler.h"
#include "Libraries/Loaders/SHMeshLoader.h" #include "Libraries/Loaders/SHModelLoader.h"
#include "Libraries/Loaders/SHTextureLoader.h" #include "Libraries/Loaders/SHTextureLoader.h"
#include "Libraries/Loaders/SHShaderSourceLoader.h" #include "Libraries/Loaders/SHShaderSourceLoader.h"
#include "Libraries/Loaders/SHTextBasedLoader.h" #include "Libraries/Loaders/SHTextBasedLoader.h"
#include "Libraries/Compilers/SHMeshCompiler.h" //#include "Libraries/Compilers/SHMeshCompiler.h"
#include "Libraries/Compilers/SHTextureCompiler.h" #include "Libraries/Compilers/SHTextureCompiler.h"
#include "Libraries/Compilers/SHShaderSourceCompiler.h" #include "Libraries/Compilers/SHShaderSourceCompiler.h"
@ -157,16 +159,22 @@ namespace SHADE
{ {
case AssetType::PREFAB: case AssetType::PREFAB:
newPath += PREFAB_FOLDER; newPath += PREFAB_FOLDER;
newPath += name;
newPath += PREFAB_EXTENSION;
data = new SHPrefabAsset(); data = new SHPrefabAsset();
break; break;
case AssetType::SCENE: case AssetType::SCENE:
newPath += SCENE_FOLDER; newPath += SCENE_FOLDER;
newPath += name;
newPath += SCENE_EXTENSION;
data = new SHSceneAsset(); data = new SHSceneAsset();
break; break;
case AssetType::MATERIAL: case AssetType::MATERIAL:
newPath += MATERIAL_FOLDER; newPath += MATERIAL_FOLDER;
newPath += name;
newPath += MATERIAL_EXTENSION;
data = new SHMaterialAsset(); data = new SHMaterialAsset();
break; break;
@ -180,7 +188,8 @@ namespace SHADE
name, name,
id, id,
type, type,
newPath newPath,
false
}; };
assetCollection.insert({ assetCollection.insert({
@ -189,7 +198,8 @@ namespace SHADE
name, name,
id, id,
type, type,
newPath newPath,
false
) )
}); });
@ -328,25 +338,32 @@ namespace SHADE
return result; return result;
} }
AssetID SHAssetManager::CompileAsset(AssetPath const& path) noexcept void SHAssetManager::CompileAsset(AssetPath const& path) noexcept
{ {
SHAsset newAsset if (!std::filesystem::exists(path))
{ {
.name = path.stem().string() SHLOG_ERROR("Path provided does not point to a file: {}", path.string());
}; return;
}
AssetPath newPath;
auto const ext{ path.extension().string() }; auto const ext{ path.extension().string() };
if (ext == GLSL_EXTENSION.data()) if (ext == GLSL_EXTENSION.data())
{ {
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value(); newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN); }
newAsset.type = AssetType::SHADER_BUILT_IN; else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
{
std::string command = MODEL_COMPILER_EXE.data();
command += " " + path.string();
std::system(command.c_str());
std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
modelPath += MODEL_EXTENSION;
newPath = modelPath;
GenerateNewMeta(newPath);
} }
assetCollection.insert({ newAsset.id, newAsset });
SHAssetMetaHandler::WriteMetaData(newAsset);
return newAsset.id;
} }
FolderPointer SHAssetManager::GetRootFolder() noexcept FolderPointer SHAssetManager::GetRootFolder() noexcept
@ -399,46 +416,28 @@ namespace SHADE
for (auto const& path : paths) for (auto const& path : paths)
{ {
SHAsset newAsset AssetPath newPath;
{
.name = path.stem().string()
};
auto const ext{ path.extension().string() }; auto const ext{ path.extension().string() };
if (ext == GLSL_EXTENSION.data()) if (ext == GLSL_EXTENSION.data())
{ {
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value(); newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN);
newAsset.type = AssetType::SHADER_BUILT_IN;
} }
else if (ext == DDS_EXTENSION.data()) else if (ext == DDS_EXTENSION.data())
{ {
newAsset.path = SHTextureCompiler::CompileTextureAsset(path).value(); newPath = SHTextureCompiler::CompileTextureAsset(path).value();
newAsset.id = GenerateAssetID(AssetType::TEXTURE);
newAsset.type = AssetType::TEXTURE;
} }
else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data()) else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
{ {
std::vector<SHMeshAsset*> meshes; std::string command = MODEL_COMPILER_EXE.data();
std::vector<SHAnimationAsset*> anims; command += " " + path.string();
SHMeshCompiler::LoadFromFile(path, meshes, anims); std::system(command.c_str());
for (auto const& mesh : meshes) std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
{ modelPath += MODEL_EXTENSION;
SHAsset meshAsset{ newPath = modelPath;
.name = mesh->header.name
};
meshAsset.path = SHMeshCompiler::CompileMeshBinary(*mesh, path).value();
meshAsset.id = GenerateAssetID(AssetType::MESH);
meshAsset.type = AssetType::MESH;
assetCollection.insert({ meshAsset.id, meshAsset });
SHAssetMetaHandler::WriteMetaData(meshAsset);
}
continue;
} }
assetCollection.insert({ newAsset.id, newAsset }); GenerateNewMeta(newPath);
SHAssetMetaHandler::WriteMetaData(newAsset);
} }
} }
@ -453,10 +452,11 @@ namespace SHADE
loaders[static_cast<size_t>(AssetType::SHADER)] = dynamic_cast<SHAssetLoader*>(new SHShaderSourceLoader()); loaders[static_cast<size_t>(AssetType::SHADER)] = dynamic_cast<SHAssetLoader*>(new SHShaderSourceLoader());
loaders[static_cast<size_t>(AssetType::SHADER_BUILT_IN)] = loaders[static_cast<size_t>(AssetType::SHADER)]; loaders[static_cast<size_t>(AssetType::SHADER_BUILT_IN)] = loaders[static_cast<size_t>(AssetType::SHADER)];
loaders[static_cast<size_t>(AssetType::TEXTURE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader()); loaders[static_cast<size_t>(AssetType::TEXTURE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader()); loaders[static_cast<size_t>(AssetType::MODEL)] = dynamic_cast<SHAssetLoader*>(new SHModelLoader());
loaders[static_cast<size_t>(AssetType::SCENE)] = dynamic_cast<SHAssetLoader*>(new SHTextBasedLoader()); loaders[static_cast<size_t>(AssetType::SCENE)] = dynamic_cast<SHAssetLoader*>(new SHTextBasedLoader());
loaders[static_cast<size_t>(AssetType::PREFAB)] = loaders[static_cast<size_t>(AssetType::SCENE)]; loaders[static_cast<size_t>(AssetType::PREFAB)] = loaders[static_cast<size_t>(AssetType::SCENE)];
loaders[static_cast<size_t>(AssetType::MATERIAL)] = loaders[static_cast<size_t>(AssetType::SCENE)]; loaders[static_cast<size_t>(AssetType::MATERIAL)] = loaders[static_cast<size_t>(AssetType::SCENE)];
loaders[static_cast<size_t>(AssetType::MESH)] = nullptr;
} }
/**************************************************************************** /****************************************************************************
@ -464,9 +464,9 @@ namespace SHADE
****************************************************************************/ ****************************************************************************/
void SHAssetManager::Load() noexcept void SHAssetManager::Load() noexcept
{ {
//CompileAll();
BuildAssetCollection(); BuildAssetCollection();
InitLoaders(); InitLoaders();
//CompileAll();
//LoadAllData(); //LoadAllData();
} }
@ -484,8 +484,12 @@ namespace SHADE
SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept
{ {
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path); if (asset.isSubAsset)
{
return LoadSubData(asset);
}
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
if (data == nullptr) if (data == nullptr)
{ {
SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string()); SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string());
@ -498,8 +502,120 @@ namespace SHADE
return data; return data;
} }
SHAssetData* SHAssetManager::LoadSubData(SHAsset const& asset) noexcept
{
auto const& parent = assetCollection[asset.parent];
auto parentData = loaders[static_cast<size_t>(parent.type)]->Load(parent.path);
if (parentData == nullptr)
{
SHLOG_ERROR("Unable to load asset into memory: {}\n", parent.path.string());
}
else
{
assetData.emplace(parent.id, parentData);
if (parent.type == AssetType::MODEL)
{
auto parentModel = reinterpret_cast<SHModelAsset*>(parentData);
for (auto i {0}; i < parent.subAssets.size(); ++i)
{
assetData.emplace(
parent.subAssets[i]->id,
parentModel->subMeshes[i]
);
}
}
return assetData[asset.id];
}
return parentData;
}
void SHAssetManager::LoadNewData(AssetPath path) noexcept
{
}
void SHAssetManager::GenerateNewMeta(AssetPath path) noexcept
{
auto const ext = path.extension().string();
if (ext == SHADER_BUILT_IN_EXTENSION.data())
{
SHAsset newAsset{
path.stem().string(),
GenerateAssetID(AssetType::SHADER_BUILT_IN),
AssetType::SHADER_BUILT_IN,
path,
false
};
assetCollection.emplace(newAsset.id, newAsset);
SHAssetMetaHandler::WriteMetaData(newAsset);
}
else if (ext == TEXTURE_EXTENSION.data())
{
SHAsset newAsset{
path.stem().string(),
GenerateAssetID(AssetType::SHADER_BUILT_IN),
AssetType::SHADER_BUILT_IN,
path,
false
};
assetCollection.emplace(newAsset.id, newAsset);
SHAssetMetaHandler::WriteMetaData(newAsset);
}
else if (ext == MODEL_EXTENSION)
{
SHAsset newAsset{
path.stem().string(),
GenerateAssetID(AssetType::MODEL),
AssetType::MODEL,
path,
false
};
assetCollection.emplace(newAsset.id, newAsset);
SHModelAsset* const data = reinterpret_cast<SHModelAsset*>(LoadData(newAsset));
assetData.emplace(newAsset.id, data);
for(auto const& subMesh : data->subMeshes)
{
SHAsset subAsset{
.name = subMesh->header.name,
.id = GenerateAssetID(AssetType::MESH),
.type = AssetType::MESH,
.isSubAsset = true,
.parent = newAsset.id
};
assetCollection.emplace(subAsset.id, subAsset);
assetCollection[newAsset.id].subAssets.push_back(&assetCollection[subAsset.id]);
assetData.emplace(subAsset.id, subMesh);
}
SHAssetMetaHandler::WriteMetaData(assetCollection[newAsset.id]);
}
}
void SHAssetManager::BuildAssetCollection() noexcept void SHAssetManager::BuildAssetCollection() noexcept
{ {
SHFileSystem::BuildDirectory(ASSET_ROOT.data(), folderRoot, assetCollection); SHFileSystem::BuildDirectory(ASSET_ROOT.data(), folderRoot, assetCollection);
for (auto& asset : std::ranges::views::values(assetCollection))
{
if (!asset.subAssets.empty())
{
// Add subasset data into map, replace pointer and free heap memory
for (auto i{ 0 }; i < asset.subAssets.size(); ++i)
{
auto const id = asset.subAssets[i]->id;
assetCollection[id] = *asset.subAssets[i];
delete asset.subAssets[i];
asset.subAssets[i] = &assetCollection[id];
}
}
}
} }
} }

View File

@ -87,7 +87,7 @@ namespace SHADE
static std::vector<SHAssetData const*> GetAllDataOfType(AssetType type) noexcept; static std::vector<SHAssetData const*> GetAllDataOfType(AssetType type) noexcept;
static std::vector<SHAsset> GetAllRecordOfType(AssetType type) noexcept; static std::vector<SHAsset> GetAllRecordOfType(AssetType type) noexcept;
static AssetID CompileAsset(AssetPath const& path) noexcept; static void CompileAsset(AssetPath const& path) noexcept;
static FolderPointer GetRootFolder() noexcept; static FolderPointer GetRootFolder() noexcept;
@ -96,6 +96,10 @@ namespace SHADE
static void InitLoaders() noexcept; static void InitLoaders() noexcept;
static void LoadAllData() noexcept; static void LoadAllData() noexcept;
static SHAssetData* LoadData(SHAsset const& asset) noexcept; static SHAssetData* LoadData(SHAsset const& asset) noexcept;
static SHAssetData* LoadSubData(SHAsset const& asset) noexcept;
static void LoadNewData(AssetPath path) noexcept;
static void GenerateNewMeta(AssetPath path) noexcept;
inline static void BuildAssetCollection() noexcept; inline static void BuildAssetCollection() noexcept;
static bool IsRecognised(char const*) noexcept; static bool IsRecognised(char const*) noexcept;

View File

@ -9,7 +9,6 @@
******************************************************************************/ ******************************************************************************/
#include "SHpch.h" #include "SHpch.h"
#include "SHAssetMetaHandler.h" #include "SHAssetMetaHandler.h"
#include <fstream>
#include <sstream> #include <sstream>
namespace SHADE namespace SHADE
@ -21,11 +20,15 @@ namespace SHADE
* \brief Helper function to retrieve field value from meta data file * \brief Helper function to retrieve field value from meta data file
* for processing * for processing
****************************************************************************/ ****************************************************************************/
void GetFieldValue(std::ifstream& file, std::string& line) noexcept bool GetFieldValue(std::ifstream& file, std::string& line) noexcept
{ {
line = ""; line = "";
std::getline(file, line); if (std::getline(file, line))
{
line = line.substr(line.find_last_of(':') + 2, line.length()); line = line.substr(line.find_last_of(':') + 2, line.length());
return true;
}
return false;
} }
/**************************************************************************** /****************************************************************************
@ -66,7 +69,8 @@ namespace SHADE
std::ifstream metaFile{ path.string(), std::ios_base::in }; std::ifstream metaFile{ path.string(), std::ios_base::in };
if (!metaFile.is_open()) if (!metaFile.is_open())
{ {
// Error unable to open SHLOG_ERROR("Unable to open meta file: {}", path.string());
return {};
} }
std::string line; std::string line;
@ -93,6 +97,43 @@ namespace SHADE
typeStream >> type; typeStream >> type;
meta.type = static_cast<AssetType>(type); meta.type = static_cast<AssetType>(type);
meta.isSubAsset = false;
// Burn Line
if (std::getline(metaFile, line))
{
// Name Line
while(GetFieldValue(metaFile, line))
{
auto subAsset = new SHAsset();
// Get resource name
std::stringstream nameStream{ line };
AssetName name;
nameStream >> name;
subAsset->name = name;
// Get resource id
GetFieldValue(metaFile, line);
std::stringstream idStream{ line };
AssetID id;
idStream >> id;
subAsset->id = id;
// Get resource type
GetFieldValue(metaFile, line);
std::stringstream typeStream{ line };
AssetTypeMeta type;
typeStream >> type;
subAsset->type = static_cast<AssetType>(type);
subAsset->isSubAsset = true;
subAsset->parent = meta.id;
meta.subAssets.push_back(subAsset);
}
}
metaFile.close(); metaFile.close();
meta.path = path.parent_path().string() + "/" + path.stem().string(); meta.path = path.parent_path().string() + "/" + path.stem().string();
@ -108,6 +149,12 @@ namespace SHADE
****************************************************************************/ ****************************************************************************/
void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept
{ {
if (meta.isSubAsset)
{
SHLOG_WARNING("Cannot write subasset meta: {}", meta.name);
return;
}
//TODO: Write into binary eventually //TODO: Write into binary eventually
std::string path{ meta.path.string() }; std::string path{ meta.path.string() };
path.append(META_EXTENSION); path.append(META_EXTENSION);
@ -124,7 +171,23 @@ namespace SHADE
metaFile << "ID: " << meta.id << "\n"; metaFile << "ID: " << meta.id << "\n";
metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl; metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
if (!meta.subAssets.empty())
{
metaFile << "Sub Assets:\n";
for (auto const& subAsset : meta.subAssets)
{
WriteSubAssetMeta(metaFile, *subAsset);
}
}
metaFile.close(); metaFile.close();
} }
void SHAssetMetaHandler::WriteSubAssetMeta(std::ofstream& metaFile, SHAsset const& subAsset) noexcept
{
metaFile << "Name: " << subAsset.name << "\n";
metaFile << "ID: " << subAsset.id << "\n";
metaFile << "Type: " << static_cast<AssetTypeMeta>(subAsset.type) << std::endl;
}
} }

View File

@ -12,6 +12,7 @@
#include "SHAssetMacros.h" #include "SHAssetMacros.h"
#include "SHAsset.h" #include "SHAsset.h"
#include <fstream>
namespace SHADE namespace SHADE
{ {
@ -45,6 +46,8 @@ namespace SHADE
* \brief Writes meta data into text file * \brief Writes meta data into text file
****************************************************************************/ ****************************************************************************/
static void WriteMetaData(SHAsset const&) noexcept; static void WriteMetaData(SHAsset const&) noexcept;
static void WriteSubAssetMeta(std::ofstream&, SHAsset const&) noexcept;
}; };
} }

View File

@ -5,15 +5,19 @@
#include "Editor/SHImGuiHelpers.hpp" #include "Editor/SHImGuiHelpers.hpp"
#include <imgui.h> #include <imgui.h>
#include <imgui_internal.h> #include <imgui_internal.h>
#include <misc/cpp/imgui_stdlib.h>
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/IconsFontAwesome6.h" #include "Editor/IconsFontAwesome6.h"
#include "Editor/SHEditor.h"
#include "Editor/DragDrop/SHDragDrop.hpp" #include "Editor/DragDrop/SHDragDrop.hpp"
#include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h"
namespace SHADE namespace SHADE
{ {
SHAssetBrowser::SHAssetBrowser() SHAssetBrowser::SHAssetBrowser()
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder) :SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder), assetBeingCreated(std::nullopt)
{ {
} }
@ -55,12 +59,31 @@ namespace SHADE
flags |= ImGuiTreeNodeFlags_DefaultOpen; flags |= ImGuiTreeNodeFlags_DefaultOpen;
bool isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data()); bool isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data());
ImGuiID folderID = ImGui::GetItemID();
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if(ImGui::IsItemClicked())
if (ImGui::BeginPopupContextItem())
{
if (ImGui::BeginMenu("Create Asset"))
{
//TODO: Change to rttr type enum align
if (ImGui::Selectable("Material"))
{
assetBeingCreated = { folder, AssetType::MATERIAL, "New Material" };
ImGui::TreeNodeSetOpen(folderID, true);
isOpen = true;
}
ImGui::EndMenu();
}
ImGui::EndPopup();
}
if (ImGui::IsItemClicked())
{ {
selectedFolders.clear(); selectedFolders.clear();
selectedFolders.push_back(folder); selectedFolders.push_back(folder);
} }
if (isOpen) if (isOpen)
{ {
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark); const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
@ -79,13 +102,18 @@ namespace SHADE
} }
for (auto const& file : files) for (auto const& file : files)
{ {
if(file.assetMeta == nullptr)
continue;
const float horizontalLineSize = 25.0f; const float horizontalLineSize = 25.0f;
const ImRect childRect = DrawFile(file); const ImRect childRect = DrawFile(file.assetMeta);
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f; const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1); drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
vertLineEnd.y = midPoint; vertLineEnd.y = midPoint;
} }
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1); drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
if(assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder)
DrawAssetBeingCreated();
ImGui::TreePop(); ImGui::TreePop();
} }
return nodeRect; return nodeRect;
@ -120,45 +148,111 @@ namespace SHADE
//} //}
} }
ImRect SHAssetBrowser::DrawFile(SHFile const& file) noexcept ImRect SHAssetBrowser::DrawFile(SHAsset const* const asset) noexcept
{ {
if (file.assetMeta == nullptr) if (asset == nullptr)
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
const bool isSelected = std::ranges::find(selectedAssets, file.assetMeta->id) != selectedAssets.end(); const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end();
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf; ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf;
if (isSelected) if (isSelected)
flags |= ImGuiTreeNodeFlags_Selected; flags |= ImGuiTreeNodeFlags_Selected;
std::string icon{}; std::string icon{};
switch(file.assetMeta->type) switch (asset->type)
{ {
case AssetType::INVALID: break; case AssetType::INVALID: break;
case AssetType::SHADER: icon = ICON_FA_FILE_CODE; break; case AssetType::SHADER: icon = ICON_FA_FILE_CODE; break;
case AssetType::SHADER_BUILT_IN: icon = ICON_FA_FILE_CODE; break; case AssetType::SHADER_BUILT_IN: icon = ICON_FA_FILE_CODE; break;
case AssetType::TEXTURE: icon = ICON_FA_IMAGES; break; case AssetType::TEXTURE: icon = ICON_FA_IMAGES; break;
case AssetType::MESH: icon = ICON_FA_CUBES; break; case AssetType::MODEL: icon = ICON_FA_CUBES_STACKED; break;
case AssetType::SCENE: icon = ICON_MD_IMAGE; break; case AssetType::SCENE: icon = ICON_MD_IMAGE; break;
case AssetType::PREFAB: icon = ICON_FA_BOX_OPEN; break; case AssetType::PREFAB: icon = ICON_FA_BOX_OPEN; break;
case AssetType::MATERIAL: break; case AssetType::MATERIAL: break;
case AssetType::MESH: icon = ICON_FA_CUBES; break;
case AssetType::MAX_COUNT: break; case AssetType::MAX_COUNT: break;
default: ; default:;
} }
ImGui::TreeNodeEx(file.assetMeta, flags, "%s %s", icon.data(), file.assetMeta->name.data()); bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s", icon.data(), asset->name.data());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if(SHDragDrop::BeginSource()) if (SHDragDrop::BeginSource())
{ {
auto id = file.assetMeta->id; auto id = asset->id;
ImGui::Text("Moving Asset: %s [%zu]", file.name.data(), file.assetMeta->id); ImGui::Text("Moving Asset: %s [%zu]", asset->name.data(), asset->id);
SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id); SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id);
SHDragDrop::EndSource(); SHDragDrop::EndSource();
} }
if(ImGui::IsItemClicked()) if (ImGui::IsItemClicked())
{ {
selectedAssets.clear(); selectedAssets.clear();
selectedAssets.push_back(file.assetMeta->id); selectedAssets.push_back(asset->id);
} }
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
switch (asset->type)
{
case AssetType::INVALID: break;
case AssetType::SHADER: break;
case AssetType::SHADER_BUILT_IN: break;
case AssetType::TEXTURE: break;
case AssetType::MESH: break;
case AssetType::SCENE:
if(auto editor = SHSystemManager::GetSystem<SHEditor>())
{
editor->LoadScene(asset->id);
}
break;
case AssetType::PREFAB: break;
case AssetType::MATERIAL:
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
{
matInspector->OpenMaterial(asset->id);
}
break;
case AssetType::MAX_COUNT: break;
default:;
}
}
//TODO: Combine Draw asset and Draw Folder recursive drawing
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
const float horizontalOffset = 0.0f;
ImDrawList* drawList = ImGui::GetWindowDrawList();
ImVec2 vertLineStart = ImGui::GetCursorScreenPos();
vertLineStart.x += horizontalOffset;
ImVec2 vertLineEnd = vertLineStart;
if(isOpen)
{
for(auto const& subAsset : asset->subAssets)
{
const float horizontalLineSize = 25.0f;
const ImRect childRect = DrawFile(subAsset);
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
vertLineEnd.y = midPoint;
}
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
ImGui::TreePop(); ImGui::TreePop();
}
return nodeRect; return nodeRect;
} }
void SHAssetBrowser::DrawAssetBeingCreated() noexcept
{
if (!assetBeingCreated.has_value())
return;
auto& path = std::get<0>(assetBeingCreated.value());
auto& type = std::get<1>(assetBeingCreated.value());
auto& assetName = std::get<2>(assetBeingCreated.value());
if (ImGui::InputText("##newAssetName", &assetName, ImGuiInputTextFlags_EnterReturnsTrue))
{
AssetID assetId = SHAssetManager::CreateNewAsset(type, assetName);
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
{
matInspector->OpenMaterial(assetId, true);
}
assetBeingCreated.reset();
}
}
} }

View File

@ -10,6 +10,7 @@ namespace SHADE
class SHAssetBrowser final : public SHEditorWindow class SHAssetBrowser final : public SHEditorWindow
{ {
public: public:
using AssetEntry = std::tuple<FolderPointer, AssetType, std::string>;
SHAssetBrowser(); SHAssetBrowser();
void Init(); void Init();
@ -20,12 +21,13 @@ namespace SHADE
void DrawMenuBar(); void DrawMenuBar();
ImRect RecursivelyDrawTree(FolderPointer folder); ImRect RecursivelyDrawTree(FolderPointer folder);
void DrawCurrentFolder(); void DrawCurrentFolder();
ImRect DrawFile(SHFile const& file) noexcept; ImRect DrawFile(SHAsset const* const asset) noexcept;
void DrawAssetBeingCreated() noexcept;
FolderPointer rootFolder, prevFolder, currentFolder; FolderPointer rootFolder, prevFolder, currentFolder;
std::optional<AssetEntry> assetBeingCreated;
std::vector<FolderPointer> selectedFolders; std::vector<FolderPointer> selectedFolders;
std::vector<AssetID> selectedAssets; std::vector<AssetID> selectedAssets;
static constexpr float tileWidth = 50.0f; static constexpr float tileWidth = 50.0f;
}; };
} }

View File

@ -108,6 +108,12 @@ namespace SHADE
} }
} }
if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
ParentSelectedEntities(MAX_EID, draggingEntities);
draggingEntities.clear();
ImGui::ClearDragDrop();
}
ImGui::End(); ImGui::End();
} }
@ -195,7 +201,7 @@ namespace SHADE
if (SHDragDrop::BeginSource()) if (SHDragDrop::BeginSource())
{ {
std::string moveLabel = "Moving EID: "; std::string moveLabel = "Moving EID: ";
static std::vector<EntityID> draggingEntities = editor->selectedEntities; draggingEntities = editor->selectedEntities;
if (!isSelected) if (!isSelected)
{ {
draggingEntities.clear(); draggingEntities.clear();
@ -217,7 +223,8 @@ namespace SHADE
{ {
if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID)) //If payload is valid if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID)) //If payload is valid
{ {
ParentSelectedEntities(eid); ParentSelectedEntities(eid, draggingEntities);
draggingEntities.clear();
SHDragDrop::EndTarget(); SHDragDrop::EndTarget();
} }
} }
@ -255,7 +262,7 @@ namespace SHADE
if ((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data())) if ((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
{ {
ParentSelectedEntities(MAX_EID); ParentSelectedEntities(MAX_EID, editor->selectedEntities);
} }
ImGui::EndPopup(); ImGui::EndPopup();
} }
@ -323,14 +330,16 @@ namespace SHADE
SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID); SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID);
} }
void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID) const noexcept void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID, std::vector<EntityID> const& entities) const noexcept
{ {
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto const editor = SHSystemManager::GetSystem<SHEditor>(); //auto const editor = SHSystemManager::GetSystem<SHEditor>();
SHEntityParentCommand::EntityParentData entityParentData; SHEntityParentCommand::EntityParentData entityParentData;
std::vector<EntityID> parentedEIDS; std::vector<EntityID> parentedEIDS;
for (auto const& eid : editor->selectedEntities) for (auto const& eid : entities)
{ {
if(eid == parentEID)
continue;
if (sceneGraph.GetChild(eid, parentEID) == nullptr) if (sceneGraph.GetChild(eid, parentEID) == nullptr)
{ {
parentedEIDS.push_back(eid); parentedEIDS.push_back(eid);

View File

@ -28,7 +28,7 @@ namespace SHADE
void DrawMenuBar() const noexcept; void DrawMenuBar() const noexcept;
ImRect RecursivelyDrawEntityNode(SHSceneNode* const); ImRect RecursivelyDrawEntityNode(SHSceneNode* const);
void CreateChildEntity(EntityID parentEID) const noexcept; void CreateChildEntity(EntityID parentEID) const noexcept;
void ParentSelectedEntities(EntityID parentEID) const noexcept; void ParentSelectedEntities(EntityID parentEID, std::vector<EntityID> const& entities) const noexcept;
void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID); void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID);
void SelectAllEntities(); void SelectAllEntities();
void CopySelectedEntities(); void CopySelectedEntities();
@ -37,6 +37,8 @@ namespace SHADE
std::string filter; std::string filter;
bool isAnyNodeSelected = false; bool isAnyNodeSelected = false;
EntityID scrollTo = MAX_EID; EntityID scrollTo = MAX_EID;
std::vector<EntityID> draggingEntities;
};//class SHHierarchyPanel };//class SHHierarchyPanel
//Might move to a different file //Might move to a different file

View File

@ -244,9 +244,12 @@ namespace SHADE
SHCollider* collider = &component->GetCollider(i); SHCollider* collider = &component->GetCollider(i);
auto cursorPos = ImGui::GetCursorPos(); auto cursorPos = ImGui::GetCursorPos();
//collider->IsTrigger
if (collider->GetType() == SHCollider::Type::BOX) if (collider->GetType() == SHCollider::Type::BOX)
{ {
SHEditorWidgets::BeginPanel(std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); SHEditorWidgets::BeginPanel(std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
SHEditorWidgets::CheckBox("Is Trigger", [collider]() {return collider->IsTrigger(); }, [collider](bool const& value) {collider->SetIsTrigger(value); }, "Is Trigger");
auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape()); auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
SHEditorWidgets::DragVec3 SHEditorWidgets::DragVec3
( (
@ -257,6 +260,7 @@ namespace SHADE
else if (collider->GetType() == SHCollider::Type::SPHERE) else if (collider->GetType() == SHCollider::Type::SPHERE)
{ {
SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
SHEditorWidgets::CheckBox("Is Trigger", [collider]() {return collider->IsTrigger(); }, [collider](bool const& value) {collider->SetIsTrigger(value); }, "Is Trigger");
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape()); auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
SHEditorWidgets::DragFloat SHEditorWidgets::DragFloat
( (
@ -372,6 +376,7 @@ namespace SHADE
{ {
DrawContextMenu(component); DrawContextMenu(component);
Handle<SHMesh> const& mesh = component->GetMesh(); Handle<SHMesh> const& mesh = component->GetMesh();
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Mesh", std::to_string(SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0)).data(), [component]() SHEditorWidgets::DragDropReadOnlyField<AssetID>("Mesh", std::to_string(SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0)).data(), [component]()
{ {
@ -383,6 +388,19 @@ namespace SHADE
component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id)); component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id));
SHResourceManager::FinaliseChanges(); SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE); }, SHDragDrop::DRAG_RESOURCE);
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", mat ? std::to_string(SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0)).data() : "", [component]()
{
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
if(!mat)
return static_cast<AssetID>(0);
return SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0);
},
[component](AssetID const& id)
{
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
component->SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(SHResourceManager::LoadOrGet<SHMaterial>(id)));
}, SHDragDrop::DRAG_RESOURCE);
} }
else else
{ {

View File

@ -0,0 +1,257 @@
#include "SHpch.h"
#include "Serialization/SHSerializationHelper.hpp"
#include "SHMaterialInspector.h"
#include "Editor/SHImGuiHelpers.hpp"
#include <imgui.h>
#include "Assets/SHAssetManager.h"
#include "Editor/IconsMaterialDesign.h"
#include "Editor/SHEditorWidgets.hpp"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Resource/SHResourceManager.h"
namespace SHADE
{
SHMaterialInspector::SHMaterialInspector()
:SHEditorWindow("Material Inspector", ImGuiWindowFlags_MenuBar), isDirty(false), isNewMaterial(false), currentViewedMaterial(0)
{
}
void SHMaterialInspector::OpenMaterial(AssetID const& assetId, bool isNew) noexcept
{
//Get mat data
if(isDirty)
return;
isDirty = isNew;
isOpen = true;
SetFocusToWindow();
currentViewedMaterial = assetId;
//currentMatSpec = //Get mat spec
currentMatSpec = SHResourceManager::LoadOrGet<SHMaterialSpec>(assetId);
currentMaterial = SHResourceManager::LoadOrGet<SHMaterial>(assetId);
}
void SHMaterialInspector::Init()
{
SHEditorWindow::Init();
}
void SHMaterialInspector::Update()
{
SHEditorWindow::Update();
if (Begin())
{
if(currentViewedMaterial)
{
DrawMenuBar();
//if (SHEditorWidgets::DragDropReadOnlyField<AssetID>("Vertex Shader", std::to_string(currentMatSpec->vertexShader), [&]() {return currentMatSpec->vertexShader; }, [&](AssetID const& id) {currentMatSpec->vertexShader = id; }, SHDragDrop::DRAG_RESOURCE))
//{
// isDirty = true;
// vertShaderHandle = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->vertexShader);
//}
//if (SHEditorWidgets::DragDropReadOnlyField<AssetID>("Fragment Shader", std::to_string(currentMatSpec->fragShader), [&]() {return currentMatSpec->fragShader; }, [&](AssetID const& id) {currentMatSpec->fragShader = id; }, SHDragDrop::DRAG_RESOURCE))
//{
// isDirty = true;
// fragShaderHandle = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);
//}
DrawShaderProperties(/*fragShaderHandle*/);
}
}
ImGui::End();
}
void SHMaterialInspector::Exit()
{
SHEditorWindow::Exit();
}
void SHMaterialInspector::DrawMenuBar()
{
if (ImGui::BeginMenuBar())
{
ImGui::BeginDisabled(!isDirty);
if(ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
{
//save
if(auto matAsset = SHAssetManager::GetData<SHMaterialAsset>(currentViewedMaterial))
{
YAML::Emitter out;
out << YAML::BeginSeq;
out << YAML::convert<SHMaterialSpec>::encode(*currentMatSpec);
out << YAML::EndSeq;
matAsset->data = out.c_str();
Handle<SHShaderBlockInterface> pipelineProperties = currentMaterial->GetShaderBlockInterface();
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
{
const std::string& PROP_NAME = pipelineProperties->GetVariableName(i);
const YAML::Node& PROP_NODE = currentMatSpec->properties[PROP_NAME.data()];
if (PROP_NODE.IsDefined())
{
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
switch (VARIABLE->type)
{
case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT:
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<float>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<int>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec2>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec3>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec4>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::OTHER:
default:
continue;
break;
}
}
}
if(SHAssetManager::SaveAsset(currentViewedMaterial))
{
isDirty = false;
}
}
}
ImGui::EndDisabled();
ImGui::EndMenuBar();
}
}
void SHMaterialInspector::DrawShaderProperties(/*Handle<SHVkShaderModule> shaderModule*/)
{
/*if(!shaderModule)
return;*/
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
auto interface = gfxSystem->GetDefaultMaterialInstance()->GetBaseMaterial()->GetShaderBlockInterface();
//auto interface = shaderModule->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA);
int const varCount = static_cast<int>(interface->GetVariableCount());
for (int i = 0; i < varCount; ++i)
{
auto variable = interface->GetVariable(i);
const std::string& VAR_NAME = interface->GetVariableName(i);
if(VAR_NAME.empty())
continue;
switch (variable->type)
{
case SHShaderBlockInterface::Variable::Type::FLOAT:
isDirty |= SHEditorWidgets::DragFloat(VAR_NAME,
[&]()
{
if (currentMatSpec->properties[VAR_NAME].IsDefined())
return currentMatSpec->properties[VAR_NAME].as<float>();
else
return 0.0f;
},
[&](float const& value)
{
currentMatSpec->properties[VAR_NAME] = value;
}
);
break;
case SHShaderBlockInterface::Variable::Type::INT:
isDirty |= SHEditorWidgets::DragInt(VAR_NAME,
[&]()
{
if (currentMatSpec->properties[VAR_NAME].IsDefined())
return currentMatSpec->properties[VAR_NAME].as<int>();
else
return 0;
},
[&](int const& value)
{
currentMatSpec->properties[VAR_NAME] = value;
}
);
if(SHDragDrop::BeginTarget())
{
if(AssetID* payload = SHDragDrop::AcceptPayload<AssetID>(SHDragDrop::DRAG_RESOURCE))
{
currentMatSpec->properties[VAR_NAME] = *payload;
isDirty = true;
SHDragDrop::EndTarget();
}
}
break;
case SHShaderBlockInterface::Variable::Type::VECTOR2:
isDirty |= SHEditorWidgets::DragVec2(VAR_NAME, { "X", "Y" },
[&]()
{
if (currentMatSpec->properties[VAR_NAME].IsDefined())
return currentMatSpec->properties[VAR_NAME].as<SHVec2>();
else
return SHVec2::Zero;
},
[&](SHVec2 const& value)
{
currentMatSpec->properties[VAR_NAME] = value;
}
);
break;
case SHShaderBlockInterface::Variable::Type::VECTOR3:
isDirty |= SHEditorWidgets::DragVec3(VAR_NAME, { "X", "Y", "Z" },
[&]()
{
if (currentMatSpec->properties[VAR_NAME].IsDefined())
return currentMatSpec->properties[VAR_NAME].as<SHVec3>();
else
return SHVec3::Zero;
},
[&](SHVec3 const& value)
{
currentMatSpec->properties[VAR_NAME] = value;
}
);
break;
case SHShaderBlockInterface::Variable::Type::VECTOR4:
isDirty |= SHEditorWidgets::DragVec4(VAR_NAME, { "X", "Y", "Z", "W" },
[&]()
{
if (currentMatSpec->properties[VAR_NAME].IsDefined())
return currentMatSpec->properties[VAR_NAME].as<SHVec4>();
else
return SHVec4::Zero;
},
[&](SHVec4 const& value)
{
currentMatSpec->properties[VAR_NAME] = value;
}
);
break;
case SHShaderBlockInterface::Variable::Type::OTHER:
isDirty |= SHEditorWidgets::InputText(VAR_NAME,
[&]()
{
if (currentMatSpec->properties[VAR_NAME].IsDefined())
return currentMatSpec->properties[VAR_NAME].as<std::string>();
else
return std::string();
},
[&](std::string const& value)
{
currentMatSpec->properties[VAR_NAME] = value;
}
);
default:
continue;
break;
}
}
}
}

View File

@ -0,0 +1,33 @@
#pragma once
#include "Assets/SHAssetMacros.h"
#include "Editor/EditorWindow/SHEditorWindow.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Resource/SHHandle.h"
namespace SHADE
{
class SHMaterialInspector final : public SHEditorWindow
{
public:
SHMaterialInspector();
~SHMaterialInspector() = default;
void Init() override;
void Update() override;
void Exit() override;
void OpenMaterial(AssetID const& assetId, bool isNew = false) noexcept;
private:
void DrawMenuBar();
void DrawShaderProperties(/*Handle<SHVkShaderModule> shaderModule*/);
bool isDirty;
bool isNewMaterial;
AssetID currentViewedMaterial;
Handle<SHMaterialSpec> currentMatSpec;
Handle<SHMaterial> currentMaterial;
Handle<SHVkShaderModule> vertShaderHandle, fragShaderHandle;
};
}

View File

@ -3,6 +3,7 @@
//#==============================================================# //#==============================================================#
//|| SHADE Includes || //|| SHADE Includes ||
//#==============================================================# //#==============================================================#
#include "Editor/SHEditorWidgets.hpp"
#include "Editor/SHEditor.h" #include "Editor/SHEditor.h"
#include "SHEditorMenuBar.h" #include "SHEditorMenuBar.h"
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
@ -17,7 +18,11 @@
#include <imgui_internal.h> #include <imgui_internal.h>
#include <rttr/type> #include <rttr/type>
#include "Assets/SHAssetManager.h"
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Scene/SHSceneManager.h"
#include "Serialization/SHSerialization.h" #include "Serialization/SHSerialization.h"
#include "Serialization/Configurations/SHConfigurationManager.h"
namespace SHADE namespace SHADE
{ {
@ -75,13 +80,17 @@ namespace SHADE
{ {
if (ImGui::BeginMenu("File")) if (ImGui::BeginMenu("File"))
{ {
if(ImGui::Selectable("New Scene"))
{
SHSystemManager::GetSystem<SHEditor>()->NewScene();
}
if(ImGui::Selectable("Save")) if(ImGui::Selectable("Save"))
{ {
SHSerialization::SerializeSceneToFile("../../Assets/Scenes/Test.SHADE"); SHSystemManager::GetSystem<SHEditor>()->SaveScene();
} }
if(ImGui::Selectable("Load")) if(ImGui::Selectable("Load"))
{ {
SHSerialization::DeserializeSceneFromFile("../../Assets/Scenes/Test.SHADE"); //SHSystemManager::GetSystem<SHEditor>()->LoadScene()
} }
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -155,6 +164,35 @@ namespace SHADE
} }
ImGui::EndMenu(); ImGui::EndMenu();
} }
if (ImGui::BeginMenu("Application Config"))
{
auto& appConfig = SHConfigurationManager::applicationConfig;
ImGui::InputText("Window Title", &appConfig.windowTitle);
ImGui::Checkbox("Start in Fullscreen", &appConfig.startInFullScreen);
SHEditorWidgets::DragN<float, 2>("Window Size", { "Width", "Height" }, { &appConfig.windowSize.x, &appConfig.windowSize.y });
//ImGui::InputScalar("Starting Scene", ImGuiDataType_U32, &appConfig.startingSceneID);
auto sceneAsset = SHAssetManager::GetData<SHSceneAsset>(appConfig.startingSceneID);
if(ImGui::BeginCombo("Starting Scne", sceneAsset ? sceneAsset->name.data() : ""))
{
auto scenes = SHAssetManager::GetAllRecordOfType(AssetType::SCENE);
for(auto const& scene : scenes)
{
if(ImGui::Selectable(scene.name.data()))
{
appConfig.startingSceneID = scene.id;
}
}
ImGui::EndCombo();
}
if (ImGui::Button("Save"))
{
SHConfigurationManager::SaveApplicationConfig();
}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar(); ImGui::EndMainMenuBar();
} }
@ -174,6 +212,8 @@ namespace SHADE
const auto editor = SHSystemManager::GetSystem<SHEditor>(); const auto editor = SHSystemManager::GetSystem<SHEditor>();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY); ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY);
if(ImGui::SmallButton(ICON_MD_PLAY_ARROW)) if(ImGui::SmallButton(ICON_MD_PLAY_ARROW))
{
if(editor->SaveScene())
{ {
const SHEditorStateChangeEvent STATE_CHANGE_EVENT const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{ {
@ -183,6 +223,7 @@ namespace SHADE
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT); SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
} }
}
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE); ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
if(ImGui::SmallButton(ICON_MD_PAUSE)) if(ImGui::SmallButton(ICON_MD_PAUSE))
@ -206,6 +247,7 @@ namespace SHADE
editor->editorState = SHEditor::State::STOP; editor->editorState = SHEditor::State::STOP;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT); SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
editor->LoadScene(SHSceneManager::GetCurrentSceneAssetID());
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::EndMenuBar(); ImGui::EndMenuBar();

View File

@ -19,7 +19,7 @@ namespace SHADE
//|| Public Member Functions || //|| Public Member Functions ||
//#==============================================================# //#==============================================================#
SHEditorWindow::SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags) SHEditorWindow::SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags)
: windowName(name), windowFlags(inFlags), io(ImGui::GetIO()) :isOpen(true), isWindowHovered(false), windowName(name), windowFlags(inFlags), io(ImGui::GetIO())
{ {
} }
@ -68,5 +68,10 @@ namespace SHADE
void SHEditorWindow::OnPosChange() void SHEditorWindow::OnPosChange()
{ {
} }
void SHEditorWindow::SetFocusToWindow()
{
ImGui::SetWindowFocus(windowName.data());
}
}//namespace SHADE }//namespace SHADE

View File

@ -34,6 +34,7 @@ namespace SHADE
virtual bool Begin(); virtual bool Begin();
virtual void OnResize(); virtual void OnResize();
virtual void OnPosChange(); virtual void OnPosChange();
virtual void SetFocusToWindow();
ImGuiWindowFlags windowFlags = 0; ImGuiWindowFlags windowFlags = 0;
ImGuiIO& io; ImGuiIO& io;

View File

@ -5,3 +5,4 @@
#include "Profiling/SHEditorProfiler.h" //Profiler #include "Profiling/SHEditorProfiler.h" //Profiler
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport #include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser #include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
#include "MaterialInspector/SHMaterialInspector.h" //Material Inspector

View File

@ -45,7 +45,11 @@
#include <backends/imgui_impl_sdl.h> #include <backends/imgui_impl_sdl.h>
#include <backends/imgui_impl_vulkan.h> #include <backends/imgui_impl_vulkan.h>
#include "Assets/SHAssetManager.h"
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h" #include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
#include "Scene/SHSceneManager.h"
#include "Serialization/SHSerialization.h"
#include "Tools/SHDebugDraw.h" #include "Tools/SHDebugDraw.h"
RTTR_REGISTRATION RTTR_REGISTRATION
@ -93,6 +97,8 @@ namespace SHADE
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>(); SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>(); SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>(); SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
SHEditorWindowManager::CreateEditorWindow<SHMaterialInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>(); SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
io = &ImGui::GetIO(); io = &ImGui::GetIO();
@ -146,6 +152,8 @@ namespace SHADE
} }
} }
RenderSceneNamePrompt();
RenderUnsavedChangesPrompt();
//PollPicking(); //PollPicking();
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z)) if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
@ -170,6 +178,60 @@ namespace SHADE
} }
} }
void SHEditor::RenderSceneNamePrompt() noexcept
{
if(isSceneNamePromptOpen)
{
ImGui::OpenPopup(sceneNamePromptName.data());
}
if(ImGui::BeginPopupModal(sceneNamePromptName.data(), &isSceneNamePromptOpen))
{
static std::string newSceneName{};
ImGui::Text("Enter new scene name");
ImGui::InputText("##name", &newSceneName);
ImGui::BeginDisabled(newSceneName.empty());
if(ImGui::Button("Save"))
{
SaveScene(newSceneName);
newSceneName.clear();
isSceneNamePromptOpen = false;
ImGui::CloseCurrentPopup();
}
ImGui::EndDisabled();
ImGui::SameLine();
if(ImGui::Button("Cancel"))
{
isSceneNamePromptOpen = false;
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
void SHEditor::RenderUnsavedChangesPrompt() noexcept
{
if(isUnsavedChangesPromptOpen)
{
ImGui::OpenPopup(unsavedChangesPromptName.data());
}
if(ImGui::BeginPopupModal(unsavedChangesPromptName.data(), &isUnsavedChangesPromptOpen))
{
ImGui::Text("You have unsaved changes!");
if(ImGui::Button("Save"))
{
isSceneNamePromptOpen = true;
}
ImGui::SameLine();
if(ImGui::Button("Cancel"))
{
isUnsavedChangesPromptOpen = false;
ImGui::CloseCurrentPopup();
}
}
}
void SHEditor::InitLayout() noexcept void SHEditor::InitLayout() noexcept
{ {
if(!std::filesystem::exists(io->IniFilename)) if(!std::filesystem::exists(io->IniFilename))
@ -468,6 +530,66 @@ namespace SHADE
} }
} }
void SHEditor::NewScene()
{
if(shWindow->IsUnsavedChanges())
{
//Unsaved changes prompt
sceneToLoad = 0;
isUnsavedChangesPromptOpen = true;
}
else
{
SHSceneManager::RestartScene(0);
shWindow->ToggleUnsavedChanges();
}
}
bool SHEditor::SaveScene(std::string const& newSceneName)
{
auto const data = SHAssetManager::GetData<SHSceneAsset>(SHSceneManager::GetCurrentSceneAssetID());
if (!data)
{
if (newSceneName.empty())
{
//Prompt for scene name
isSceneNamePromptOpen = true;
return false;
}
//Else We have a new name
SHSceneManager::SetCurrentSceneName(newSceneName);
SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, newSceneName));
}
//Get data, if data is null, asset doesn't exist, prompt for a name and create a new asset with the name
//serialize the scene
if(SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID()))
{
if(shWindow->IsUnsavedChanges())
shWindow->ToggleUnsavedChanges();
return true;
}
return false;
}
void SHEditor::LoadScene(AssetID const& assetID) noexcept
{
if(shWindow->IsUnsavedChanges())
{
//Unsaved changes prompt
isUnsavedChangesPromptOpen = true;
sceneToLoad = assetID;
}
else
{
//Load the scene
sceneToLoad = 0;
SHSceneManager::RestartScene(assetID);
}
}
void SHEditor::NewFrame() void SHEditor::NewFrame()
{ {
SDL_Event event; SDL_Event event;

View File

@ -16,15 +16,18 @@
#include "Resource/SHHandle.h" #include "Resource/SHHandle.h"
#include "EditorWindow/SHEditorWindow.h" #include "EditorWindow/SHEditorWindow.h"
#include "Tools/SHLog.h" #include "Tools/SHLog.h"
#include "Gizmos/SHTransformGizmo.h"` #include "Gizmos/SHTransformGizmo.h"
#include "Events/SHEventDefines.h" #include "Events/SHEventDefines.h"
#include "Events/SHEvent.h" #include "Events/SHEvent.h"
#include "Graphics/Windowing/SHWindow.h"
//#==============================================================# //#==============================================================#
//|| Library Includes || //|| Library Includes ||
//#==============================================================# //#==============================================================#
#include <SDL_video.h> #include <SDL_video.h>
#include "Assets/SHAssetMacros.h"
namespace SHADE namespace SHADE
{ {
//#==============================================================# //#==============================================================#
@ -171,9 +174,16 @@ namespace SHADE
void InitBackend(); void InitBackend();
void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;}; void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;};
void SetSHWindow(SHWindow* inWindow){shWindow = inWindow;}
void PollPicking(); void PollPicking();
void NewScene();
bool SaveScene(std::string const& newSceneName = {});
void LoadScene(AssetID const& assetID) noexcept;
// List of selected entities // List of selected entities
std::vector<EntityID> selectedEntities; std::vector<EntityID> selectedEntities;
@ -191,6 +201,10 @@ namespace SHADE
*/ */
void Render(); void Render();
void RenderSceneNamePrompt() noexcept;
void RenderUnsavedChangesPrompt() noexcept;
void InitLayout() noexcept; void InitLayout() noexcept;
void InitFonts() noexcept; void InitFonts() noexcept;
@ -199,12 +213,22 @@ namespace SHADE
SHEventHandle onEditorStateChanged(SHEventPtr eventPtr); SHEventHandle onEditorStateChanged(SHEventPtr eventPtr);
bool isSceneNamePromptOpen = false;
bool isUnsavedChangesPromptOpen = false;
static constexpr std::string_view sceneNamePromptName = "Save scene as...";
static constexpr std::string_view unsavedChangesPromptName = "Unsaved Changes";
AssetID sceneToLoad = 0;
// Handle to command pool used for ImGui Vulkan Backend // Handle to command pool used for ImGui Vulkan Backend
Handle<SHVkCommandPool> imguiCommandPool; Handle<SHVkCommandPool> imguiCommandPool;
// Handle to command buffer used for ImGui Vulkan Backend // Handle to command buffer used for ImGui Vulkan Backend
Handle<SHVkCommandBuffer> imguiCommandBuffer; Handle<SHVkCommandBuffer> imguiCommandBuffer;
SDL_Window* sdlWindow {nullptr}; SDL_Window* sdlWindow {nullptr};
SHWindow* shWindow {nullptr};
ImGuiIO* io{nullptr}; ImGuiIO* io{nullptr};

View File

@ -422,12 +422,13 @@ namespace SHADE
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::PushID(label.data()); ImGui::PushID(label.data());
TextLabel(label); TextLabel(label);
bool const changed = ImGui::InputText("##", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr); bool changed = ImGui::InputText("##", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr);
if(SHDragDrop::BeginTarget()) if(SHDragDrop::BeginTarget())
{ {
if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag)) if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))
{ {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), *payload, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), *payload, set)), false);
changed = true;
SHDragDrop::EndTarget(); SHDragDrop::EndTarget();
} }
} }

View File

@ -88,6 +88,7 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; }; Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; };
bool IsEmpty() const noexcept { return subBatches.empty(); }
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -68,6 +68,10 @@ namespace SHADE
return; return;
batch->Remove(renderable); batch->Remove(renderable);
// If batch is empty, remove batch
if (batch->IsEmpty())
batches.erase(batch);
} }
void SHSuperBatch::Clear() noexcept void SHSuperBatch::Clear() noexcept

View File

@ -14,7 +14,7 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <algorithm> #include <algorithm>
// Project Includes // Project Includes
#include "../Meshes/SHMeshData.h" #include "Assets/Asset Types/SHModelAsset.h"
#include "../Meshes/SHPrimitiveGenerator.h" #include "../Meshes/SHPrimitiveGenerator.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "SHGraphicsSystem.h" #include "SHGraphicsSystem.h"

View File

@ -41,6 +41,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
#include "Graphics/SHVkUtil.h" #include "Graphics/SHVkUtil.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h" #include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "../Meshes/SHPrimitiveGenerator.h"
namespace SHADE namespace SHADE
{ {
@ -52,7 +53,11 @@ namespace SHADE
/* BACKEND BOILERPLATE */ /* BACKEND BOILERPLATE */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// Set Up Instance // Set Up Instance
#ifdef _DEBUG
SHVkInstance::Init(true, true, true); SHVkInstance::Init(true, true, true);
#else
SHVkInstance::Init(true, false, true);
#endif
// Get Physical Device and Construct Logical Device // Get Physical Device and Construct Logical Device
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST); physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST);
@ -255,7 +260,6 @@ namespace SHADE
// Generate world render graph // Generate world render graph
worldRenderGraph->Generate(); worldRenderGraph->Generate();
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* BIND RENDER GRAPH TO RENDERER */ /* BIND RENDER GRAPH TO RENDERER */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -265,9 +269,6 @@ namespace SHADE
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector()); worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
// Create default materials
defaultMaterial = AddMaterial(defaultVertShader, defaultFragShader, gBufferSubpass);
// Create debug draw pipeline // Create debug draw pipeline
debugDrawPipeline = createDebugDrawPipeline(debugDrawNode->GetRenderpass(), debugDrawSubpass); debugDrawPipeline = createDebugDrawPipeline(debugDrawNode->GetRenderpass(), debugDrawSubpass);
debugDrawDepthPipeline = createDebugDrawPipeline(debugDrawNodeDepth->GetRenderpass(), debugDrawDepthSubpass); debugDrawDepthPipeline = createDebugDrawPipeline(debugDrawNodeDepth->GetRenderpass(), debugDrawDepthSubpass);
@ -309,7 +310,29 @@ namespace SHADE
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>(); lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
lightingSubSystem->Init(device, descPool); lightingSubSystem->Init(device, descPool);
}
void SHGraphicsSystem::InitBuiltInResources(void)
{
// Create default texture
std::array<SHTexture::PixelChannel, 4> defaultTextureData = { 255, 255, 255, 255 };
std::vector<uint32_t> mipOffsets{};
mipOffsets.push_back(0);
defaultTexture = AddTexture(4, defaultTextureData.data(), 1, 1, SHTexture::TextureFormat::eR8G8B8A8Unorm, mipOffsets);
BuildTextures();
// Create default meshes
primitiveMeshes[static_cast<int>(PrimitiveType::Cube)] = SHPrimitiveGenerator::Cube(meshLibrary);
primitiveMeshes[static_cast<int>(PrimitiveType::Sphere)] = SHPrimitiveGenerator::Sphere(meshLibrary);
BuildMeshBuffers();
// Create default materials
defaultMaterial = AddMaterial
(
defaultVertShader, defaultFragShader,
worldRenderGraph->GetNode("G-Buffer")->GetSubpass("G-Buffer Write")
);
defaultMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex);
} }
#ifdef SHEDITOR #ifdef SHEDITOR
@ -352,8 +375,7 @@ namespace SHADE
InitBoilerplate(); InitBoilerplate();
InitMiddleEnd(); InitMiddleEnd();
InitSubsystems(); InitSubsystems();
InitBuiltInResources();
} }
void SHGraphicsSystem::Exit(void) void SHGraphicsSystem::Exit(void)
@ -711,6 +733,18 @@ namespace SHADE
transferCmdBuffer.Free(); transferCmdBuffer = {}; transferCmdBuffer.Free(); transferCmdBuffer = {};
} }
Handle<SHMesh> SHGraphicsSystem::GetMeshPrimitive(PrimitiveType type) const noexcept
{
switch (type)
{
case PrimitiveType::Cube:
case PrimitiveType::Sphere:
return primitiveMeshes[static_cast<int>(type)];
default:
return {};
}
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Texture Registration Functions */ /* Texture Registration Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -743,6 +777,11 @@ namespace SHADE
graphicsTexCmdBuffer.Free(); graphicsTexCmdBuffer = {}; graphicsTexCmdBuffer.Free(); graphicsTexCmdBuffer = {};
} }
Handle<SHTexture> SHGraphicsSystem::GetTextureHandle(SHTexture::Index textureId) const
{
return texLibrary.GetTextureHandle(textureId);
}
#pragma endregion ADD_REMOVE #pragma endregion ADD_REMOVE
#pragma region ROUTINES #pragma region ROUTINES
@ -755,6 +794,7 @@ namespace SHADE
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{ {
SHResourceManager::FinaliseChanges();
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender(); reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
} }
@ -780,7 +820,6 @@ namespace SHADE
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{ {
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender(); reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
SHResourceManager::FinaliseChanges();
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -798,11 +837,6 @@ namespace SHADE
if (!renderable.HasChanged()) if (!renderable.HasChanged())
continue; continue;
if (!renderable.GetMesh())
{
SHLOG_CRITICAL("NULL Mesh provided!");
}
// Remove from the SuperBatch it is previously in (prevMat if mat has changed) // Remove from the SuperBatch it is previously in (prevMat if mat has changed)
Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial(); Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial();
if (prevMaterial) if (prevMaterial)
@ -812,8 +846,9 @@ namespace SHADE
} }
// Add to new SuperBatch if there is a material // Add to new SuperBatch if there is a material
// Add to new SuperBatch if there is a material and a mesh to render
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial(); Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
if (newMatInstance) if (newMatInstance && renderable.GetMesh())
{ {
Handle<SHSuperBatch> newSuperBatch = newMatInstance->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); Handle<SHSuperBatch> newSuperBatch = newMatInstance->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
newSuperBatch->Add(&renderable); newSuperBatch->Add(&renderable);

View File

@ -58,6 +58,19 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Type of built-in primitive meshes that are available.
*/
/***********************************************************************************/
enum class PrimitiveType
{
Cube,
Sphere
};
static constexpr int MAX_PRIMITIVE_TYPES = 2;
/***********************************************************************************/ /***********************************************************************************/
/*! /*!
\brief \brief
@ -72,6 +85,7 @@ namespace SHADE
void InitSceneRenderGraph (void) noexcept; void InitSceneRenderGraph (void) noexcept;
void InitMiddleEnd (void) noexcept; void InitMiddleEnd (void) noexcept;
void InitSubsystems (void) noexcept; void InitSubsystems (void) noexcept;
void InitBuiltInResources (void);
#ifdef SHEDITOR #ifdef SHEDITOR
void InitEditorRenderGraph (void) noexcept; void InitEditorRenderGraph (void) noexcept;
@ -207,6 +221,21 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void BuildMeshBuffers(); void BuildMeshBuffers();
/*******************************************************************************/
/*!
\brief
Retrieves the built-in mesh specified.
\param type
Type of built-in mesh to retrieve.
\returns
Handle to the mesh that was specfied. However, if an invalid type is specified,
a null Handle will be returned.
*/
/*******************************************************************************/
Handle<SHMesh> GetMeshPrimitive(PrimitiveType type) const noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Texture Registration Functions */ /* Texture Registration Functions */
@ -263,6 +292,33 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void BuildTextures(); void BuildTextures();
/***************************************************************************/
/*!
*
\brief
Retrieves the texture handle at the specified texture index.
\param textureId
Index of the texture to look for.
\returns
Handle to the texture
*/
/***************************************************************************/
Handle<SHTexture> GetTextureHandle(SHTexture::Index textureId) const;
/***************************************************************************/
/*!
*
\brief
Retrieves the handle to the default texture. A white 1x1 texture.
\returns
Handle to the default texture.
*/
/***************************************************************************/
Handle<SHTexture> GetDefaultTexture() const noexcept { return defaultTexture; }
void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept; void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept;
void HandleResize(void) noexcept; void HandleResize(void) noexcept;
@ -363,6 +419,13 @@ namespace SHADE
Handle<SHVkPipeline> debugDrawPipeline; Handle<SHVkPipeline> debugDrawPipeline;
Handle<SHVkPipeline> debugDrawDepthPipeline; Handle<SHVkPipeline> debugDrawDepthPipeline;
// Built-In Textures
Handle<SHTexture> defaultTexture;
// Built-In Meshes
std::array<Handle<SHMesh>, MAX_PRIMITIVE_TYPES> primitiveMeshes;
// Render Graphs
Handle<SHRenderGraph> worldRenderGraph; Handle<SHRenderGraph> worldRenderGraph;
// Sub systems // Sub systems

View File

@ -0,0 +1,74 @@
/************************************************************************************//*!
\file SHMaterialSpec.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 2, 2022
\brief Contains the function definitions of SHMaterialSpec.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#include "SHpch.h"
#include "SHMaterialSpec.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Resource/SHResourceManager.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------------*/
SHMaterialSpec::SHMaterialSpec(const SHMaterial& material)
{
// Get Shader Handles
const auto& SHADERS = material.GetPipeline()->GetPipelineLayout()->GetShaderModules();
Handle<SHVkShaderModule> vShaderMod, fShaderMod;
for (const auto& shader : SHADERS)
{
const auto FLAG_BITS = shader->GetShaderStageFlagBits();
if (FLAG_BITS & vk::ShaderStageFlagBits::eVertex)
vShaderMod = shader;
else if (FLAG_BITS & vk::ShaderStageFlagBits::eFragment)
fShaderMod = shader;
}
vertexShader = SHResourceManager::GetAssetID<SHVkShaderModule>(vShaderMod).value_or(0);
fragShader = SHResourceManager::GetAssetID<SHVkShaderModule>(fShaderMod).value_or(0);
subpassName = material.GetPipeline()->GetPipelineState().GetSubpass()->GetName();
// Write Properties
Handle<SHShaderBlockInterface> pipelineProperties = material.GetShaderBlockInterface();
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
{
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
if (!VARIABLE)
break;
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
YAML::Node propNode;
switch (VARIABLE->type)
{
case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT:
propNode = material.GetProperty<float>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
propNode = material.GetProperty<int>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
propNode = material.GetProperty<SHVec2>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
propNode = material.GetProperty<SHVec3>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
propNode = material.GetProperty<SHVec4>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::OTHER:
default:
continue;
break;
}
properties[VAR_NAME.data()] = propNode;
}
}
}

View File

@ -16,9 +16,18 @@ of DigiPen Institute of Technology is prohibited.
#include <utility> #include <utility>
// Project Includes // Project Includes
#include "Assets/SHAssetMacros.h" #include "Assets/SHAssetMacros.h"
#include <yaml-cpp/yaml.h>
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Forward Declaration */
/*-----------------------------------------------------------------------------------*/
class SHMaterial;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/ /*************************************************************************************/
/*! /*!
\brief \brief
@ -32,5 +41,11 @@ namespace SHADE
AssetID fragShader; AssetID fragShader;
std::string subpassName; std::string subpassName;
YAML::Node properties; YAML::Node properties;
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
SHMaterialSpec() = default;
explicit SHMaterialSpec(const SHMaterial& material);
}; };
} }

View File

@ -1,36 +0,0 @@
/************************************************************************************//*!
\file SHPrimitiveGenerator.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 18, 2022
\brief Contains the static class definition of SHPrimitiveGenerator.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// STL Includes
#include <vector>
// Project Includes
#include "Math/SHMath.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
namespace SHADE
{
/*************************************************************************************/
/*!
\brief
Static class that contains functions for generating 3D primitives.
*/
/*************************************************************************************/
struct SHMeshData
{
std::vector<SHMesh::VertexPosition> VertexPositions;
std::vector<SHMesh::VertexTexCoord> VertexTexCoords;
std::vector<SHMesh::VertexTangent> VertexTangents;
std::vector<SHMesh::VertexNormal> VertexNormals;
std::vector<SHMesh::Index> Indices;
};
}

View File

@ -13,7 +13,8 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes // Project Includes
#include "Math/SHMath.h" #include "Math/SHMath.h"
#include "SHMeshData.h" #include "Assets/Asset Types/SHModelAsset.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
#include "SH_API.h" #include "SH_API.h"
namespace SHADE namespace SHADE

View File

@ -156,14 +156,15 @@ namespace SHADE
/* Build Descriptor Set with all the Textures only if there are textures */ /* Build Descriptor Set with all the Textures only if there are textures */
if (!texOrder.empty()) if (!texOrder.empty())
{ {
if (!texDescriptors) if (texDescriptors)
{ {
texDescriptors.Free();
}
texDescriptors = descPool->Allocate texDescriptors = descPool->Allocate
( (
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS] }, { SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS] },
{ static_cast<uint32_t>(texOrder.size()) } { static_cast<uint32_t>(texOrder.size()) }
); );
}
texDescriptors->ModifyWriteDescImage texDescriptors->ModifyWriteDescImage
( (
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS, SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,

View File

@ -129,6 +129,21 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHVkDescriptorSetGroup> GetTextureDescriptorSetGroup() const noexcept { return texDescriptors; } Handle<SHVkDescriptorSetGroup> GetTextureDescriptorSetGroup() const noexcept { return texDescriptors; }
/***************************************************************************/
/*!
*
\brief
Retrieves the texture handle at the specified texture index.
\param textureId
Index of the texture to look for.
\returns
Handle to the texture
*/
/***************************************************************************/
Handle<SHTexture> GetTextureHandle(SHTexture::Index textureId) const { return texOrder[textureId]; };
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -70,7 +70,7 @@ namespace SHADE
, inputImageDescriptors{ std::move(rhs.inputImageDescriptors) } , inputImageDescriptors{ std::move(rhs.inputImageDescriptors) }
, inputDescriptorLayout{ rhs.inputDescriptorLayout } , inputDescriptorLayout{ rhs.inputDescriptorLayout }
, inputSamplers{ rhs.inputSamplers } , inputSamplers{ rhs.inputSamplers }
, name { rhs.name }
{ {
} }
@ -105,6 +105,7 @@ namespace SHADE
inputImageDescriptors = std::move(rhs.inputImageDescriptors); inputImageDescriptors = std::move(rhs.inputImageDescriptors);
inputDescriptorLayout = rhs.inputDescriptorLayout; inputDescriptorLayout = rhs.inputDescriptorLayout;
inputSamplers = rhs.inputSamplers; inputSamplers = rhs.inputSamplers;
name = std::move(rhs.name);
return *this; return *this;
} }

View File

@ -55,16 +55,6 @@ namespace SHADE
return variables.size(); return variables.size();
} }
SHShaderBlockInterface::SHShaderBlockInterface(void) noexcept
: bytesRequired{ 0 }
{}
SHShaderBlockInterface::SHShaderBlockInterface(SHShaderBlockInterface&& rhs) noexcept
: variables { std::move(rhs.variables) }
, variableIndexing { std::move(rhs.variableIndexing) }
, bytesRequired { rhs.bytesRequired }
{}
void SHShaderBlockInterface::SetBytesRequired(uint32_t bytes) noexcept void SHShaderBlockInterface::SetBytesRequired(uint32_t bytes) noexcept
{ {
bytesRequired = bytes; bytesRequired = bytes;
@ -75,16 +65,4 @@ namespace SHADE
{ {
return bytesRequired; return bytesRequired;
} }
SHADE::SHShaderBlockInterface& SHShaderBlockInterface::operator=(SHShaderBlockInterface&& rhs) noexcept
{
if (&rhs == this)
return *this;
variables = std::move(rhs.variables);
variableIndexing = std::move(rhs.variableIndexing);
bytesRequired = rhs.bytesRequired;
return *this;
}
} }

View File

@ -33,7 +33,7 @@ namespace SHADE
std::unordered_map<std::string, uint32_t> variableIndexing; std::unordered_map<std::string, uint32_t> variableIndexing;
//! bytes required by the block (includes padding). This variable is required //! bytes required by the block (includes padding). This variable is required
uint32_t bytesRequired; uint32_t bytesRequired = 0;
public: public:
void AddVariable (std::string name, Variable&& newVariable) noexcept; void AddVariable (std::string name, Variable&& newVariable) noexcept;
@ -43,13 +43,6 @@ namespace SHADE
const std::string& GetVariableName(uint32_t index) const noexcept; const std::string& GetVariableName(uint32_t index) const noexcept;
size_t GetVariableCount() const noexcept; size_t GetVariableCount() const noexcept;
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHShaderBlockInterface(void) noexcept;
SHShaderBlockInterface(SHShaderBlockInterface&& rhs) noexcept;
SHShaderBlockInterface& operator=(SHShaderBlockInterface&& rhs) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -4,7 +4,6 @@
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Input/SHInputManager.h" #include "Input/SHInputManager.h"
namespace SHADE namespace SHADE
{ {
SHWindow::SHWindow() SHWindow::SHWindow()
@ -151,11 +150,11 @@ namespace SHADE
SetWindowText(wndHWND, LPCWSTR(wndData.title.c_str())); SetWindowText(wndHWND, LPCWSTR(wndData.title.c_str()));
} }
SHWindow::SHVec2 SHWindow::GetPosition() const SHWindow::WindowSize SHWindow::GetPosition() const
{ {
RECT rect; RECT rect;
GetWindowRect(wndHWND, &rect); GetWindowRect(wndHWND, &rect);
return SHVec2(static_cast<uint32_t>(rect.left), static_cast<uint32_t>(rect.top)); return WindowSize(static_cast<uint32_t>(rect.left), static_cast<uint32_t>(rect.top));
} }
void SHWindow::SetPosition(unsigned x, unsigned y) void SHWindow::SetPosition(unsigned x, unsigned y)
@ -165,18 +164,18 @@ namespace SHADE
wndData.y = y; wndData.y = y;
} }
SHWindow::SHVec2 SHWindow::GetWindowSize() const SHWindow::WindowSize SHWindow::GetWindowSize() const
{ {
RECT rect; RECT rect;
GetClientRect(wndHWND, &rect); GetClientRect(wndHWND, &rect);
return SHVec2(static_cast<uint32_t>(rect.right - rect.left), static_cast<uint32_t>(rect.bottom - rect.top)); return WindowSize(static_cast<uint32_t>(rect.right - rect.left), static_cast<uint32_t>(rect.bottom - rect.top));
} }
SHWindow::SHVec2 SHWindow::GetCurrentDisplaySize() const SHWindow::WindowSize SHWindow::GetCurrentDisplaySize() const
{ {
unsigned screenWidth = GetSystemMetrics(SM_CXSCREEN); unsigned screenWidth = GetSystemMetrics(SM_CXSCREEN);
unsigned screenHeight = GetSystemMetrics(SM_CYSCREEN); unsigned screenHeight = GetSystemMetrics(SM_CYSCREEN);
return SHVec2(screenWidth, screenHeight); return WindowSize(screenWidth, screenHeight);
} }
void SHWindow::SetMouseVisible(bool show) void SHWindow::SetMouseVisible(bool show)
@ -260,7 +259,7 @@ namespace SHADE
return wndHWND; return wndHWND;
} }
const WindowData SHWindow::GetWindowData() const const WindowData SHWindow::GetWindowData() const noexcept
{ {
return wndData; return wndData;
} }
@ -287,6 +286,15 @@ namespace SHADE
windowCloseCallbacks.erase(callbackid); windowCloseCallbacks.erase(callbackid);
} }
void SHWindow::ToggleUnsavedChanges() noexcept
{
unsavedChanges = !unsavedChanges;
std::wstring title = wndData.title;
if(unsavedChanges)
title.append(L"*");
SetWindowText(wndHWND, title.data());
}
LRESULT SHWindow::WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) LRESULT SHWindow::WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{ {
auto window = windowMap.GetWindow(hwnd); auto window = windowMap.GetWindow(hwnd);

View File

@ -74,7 +74,7 @@ namespace SHADE
class SH_API SHWindow class SH_API SHWindow
{ {
public: public:
using SHVec2 = std::pair<uint32_t, uint32_t>; using WindowSize = std::pair<uint32_t, uint32_t>;
typedef std::function<void(uint32_t width, uint32_t height)> WindowResizeCallbackFn; typedef std::function<void(uint32_t width, uint32_t height)> WindowResizeCallbackFn;
typedef std::function<void(void)> WindowCloseCallbackFn; typedef std::function<void(void)> WindowCloseCallbackFn;
typedef uint16_t CALLBACKID; typedef uint16_t CALLBACKID;
@ -92,15 +92,15 @@ namespace SHADE
void SetTitle(std::wstring title); void SetTitle(std::wstring title);
SHVec2 GetPosition() const; WindowSize GetPosition() const;
void SetPosition(unsigned x, unsigned y); void SetPosition(unsigned x, unsigned y);
//void SetPosition(SHMathVec2U); //void SetPosition(SHMathVec2U);
SHVec2 GetWindowSize() const; WindowSize GetWindowSize() const;
//Get size of display the window is in (whichever window contains the window origin) //Get size of display the window is in (whichever window contains the window origin)
SHVec2 GetCurrentDisplaySize() const; WindowSize GetCurrentDisplaySize() const;
void SetMouseVisible(bool show); void SetMouseVisible(bool show);
@ -123,7 +123,7 @@ namespace SHADE
HWND GetHWND(); HWND GetHWND();
const WindowData GetWindowData() const; const WindowData GetWindowData() const noexcept;
CALLBACKID RegisterWindowSizeCallback(WindowResizeCallbackFn); CALLBACKID RegisterWindowSizeCallback(WindowResizeCallbackFn);
void UnregisterWindowSizeCallback(CALLBACKID const& callbackid); void UnregisterWindowSizeCallback(CALLBACKID const& callbackid);
@ -131,6 +131,8 @@ namespace SHADE
void UnregisterWindowCloseCallback(CALLBACKID const& callbackid); void UnregisterWindowCloseCallback(CALLBACKID const& callbackid);
bool IsMinimized() const { return wndData.isMinimised; } bool IsMinimized() const { return wndData.isMinimised; }
void ToggleUnsavedChanges() noexcept;
bool IsUnsavedChanges() const noexcept{return unsavedChanges;}
protected: protected:
static LRESULT CALLBACK WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); static LRESULT CALLBACK WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
@ -164,7 +166,8 @@ namespace SHADE
std::unordered_map<CALLBACKID, WindowCloseCallbackFn> windowCloseCallbacks; std::unordered_map<CALLBACKID, WindowCloseCallbackFn> windowCloseCallbacks;
CALLBACKID windowResizeCallbackCount{}; CALLBACKID windowResizeCallbackCount{};
CALLBACKID windowCloseCallbackCount{}; CALLBACKID windowCloseCallbackCount{};
//TODO: Shift to events abstraction
bool unsavedChanges = false;
void OnCreate(HWND hwnd, LPCREATESTRUCT create_struct); void OnCreate(HWND hwnd, LPCREATESTRUCT create_struct);
void OnClose(); void OnClose();

View File

@ -25,16 +25,16 @@ namespace SHADE
std::map<std::string, SHInputManager::SHLogicalBindingData> SHInputManager::bindings; std::map<std::string, SHInputManager::SHLogicalBindingData> SHInputManager::bindings;
unsigned SHInputManager::keyCount = 0; unsigned SHInputManager::keyCount = 0;
bool SHInputManager::keys[MAX_KEYS]; bool SHInputManager::keys[MAX_KEYS] = {};
bool SHInputManager::keysLast[MAX_KEYS]; bool SHInputManager::keysLast[MAX_KEYS] = {};
double SHInputManager::keysHeldTime[MAX_KEYS]; double SHInputManager::keysHeldTime[MAX_KEYS] = {};
double SHInputManager::keysReleasedTime[MAX_KEYS]; double SHInputManager::keysReleasedTime[MAX_KEYS] = {};
unsigned SHInputManager::keyToggleCount = 0; unsigned SHInputManager::keyToggleCount = 0;
bool SHInputManager::keysToggle[MAX_KEYS]; bool SHInputManager::keysToggle[MAX_KEYS] = {};
bool SHInputManager::keysToggleLast[MAX_KEYS]; bool SHInputManager::keysToggleLast[MAX_KEYS] = {};
double SHInputManager::keysToggleOnTime[MAX_KEYS]; double SHInputManager::keysToggleOnTime[MAX_KEYS] = {};
double SHInputManager::keysToggleOffTime[MAX_KEYS]; double SHInputManager::keysToggleOffTime[MAX_KEYS] = {};
int SHInputManager::mouseScreenX = 0; int SHInputManager::mouseScreenX = 0;
int SHInputManager::mouseScreenY = 0; int SHInputManager::mouseScreenY = 0;
@ -46,11 +46,11 @@ namespace SHADE
int SHInputManager::mouseWheelVerticalDeltaPoll = 0; int SHInputManager::mouseWheelVerticalDeltaPoll = 0;
unsigned char SHInputManager::controllersConnectedCount = 0; unsigned char SHInputManager::controllersConnectedCount = 0;
unsigned SHInputManager::controllersInputCount[XUSER_MAX_COUNT]; unsigned SHInputManager::controllersInputCount[XUSER_MAX_COUNT] = {};
unsigned SHInputManager::controllersButtonCount[XUSER_MAX_COUNT]; unsigned SHInputManager::controllersButtonCount[XUSER_MAX_COUNT] = {};
short SHInputManager::controllers[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT]; short SHInputManager::controllers[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT] = {};
short SHInputManager::controllersLast[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT]; short SHInputManager::controllersLast[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT] = {};
double SHInputManager::controllersHeldTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT]; double SHInputManager::controllersHeldTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT] = {};
double SHInputManager::controllersReleasedTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT]; double SHInputManager::controllersReleasedTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
//Internal helper function for splitting between inputs //Internal helper function for splitting between inputs
@ -106,9 +106,11 @@ namespace SHADE
memcpy(keysLast, keys, sizeof(keys)); memcpy(keysLast, keys, sizeof(keys));
//Poll //Poll
unsigned char keyboardState[MAX_KEYS]; unsigned char keyboardState[MAX_KEYS] = {};
SecureZeroMemory(keyboardState, sizeof(keyboardState));
//if (GetKeyboardState(keyboardState) == false) return; //if (GetKeyboardState(keyboardState) == false) return;
SHASSERT(GetKeyboardState(keyboardState), "SHInputManager:GetKeyboardState() failed ({})", GetLastError()); bool keyboardStateGot = GetKeyboardState(keyboardState);
SHASSERT(keyboardStateGot, "SHInputManager:GetKeyboardState() failed ({})", GetLastError());
keyCount = 0; keyCount = 0;
keyToggleCount = 0; keyToggleCount = 0;
for (size_t i = 0; i < MAX_KEYS; ++i) for (size_t i = 0; i < MAX_KEYS; ++i)

View File

@ -13,17 +13,20 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <unordered_map> #include <unordered_map>
namespace SHADE { class SHMaterial; }
// Project Includes // Project Includes
#include "SH_API.h" #include "SH_API.h"
#include "SHResourceLibrary.h" #include "SHResourceLibrary.h"
#include "Assets/SHAssetMacros.h" #include "Assets/SHAssetMacros.h"
#include "Assets/Asset Types/SHMeshAsset.h" #include "Assets/Asset Types/SHModelAsset.h"
#include "Assets/Asset Types/SHTextureAsset.h" #include "Assets/Asset Types/SHTextureAsset.h"
#include "Assets/Asset Types/SHShaderAsset.h" #include "Assets/Asset Types/SHShaderAsset.h"
#include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h" #include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h" #include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h" #include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Assets/Asset Types/SHMaterialAsset.h" #include "Assets/Asset Types/SHMaterialAsset.h"
namespace SHADE namespace SHADE
@ -33,12 +36,12 @@ namespace SHADE
/// </summary> /// </summary>
template<typename T = void> template<typename T = void>
struct SHResourceLoader { using AssetType = void; }; struct SHResourceLoader { using AssetType = void; };
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshAsset; }; template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshData; };
template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; }; template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; };
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; }; template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialAsset; }; template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
/// <summary> /// <summary>
/// Static class responsible for loading and caching runtime resources from their /// Static class responsible for loading and caching runtime resources from their
/// serialised Asset IDs. /// serialised Asset IDs.
/// </summary> /// </summary>
@ -61,6 +64,8 @@ namespace SHADE
/// <returns>Handle to a loaded runtime asset.</returns> /// <returns>Handle to a loaded runtime asset.</returns>
template<typename ResourceType> template<typename ResourceType>
static Handle<ResourceType> LoadOrGet(AssetID assetId); static Handle<ResourceType> LoadOrGet(AssetID assetId);
template<>
static inline Handle<SHMaterial> LoadOrGet<SHMaterial>(AssetID assetId);
/// <summary> /// <summary>
/// Unloads an existing loaded asset. Attempting to unload an invalid Handle will /// Unloads an existing loaded asset. Attempting to unload an invalid Handle will
/// simply do nothing except emit a warning. /// simply do nothing except emit a warning.

View File

@ -24,6 +24,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Serialization/SHYAMLConverters.h"
namespace SHADE namespace SHADE
{ {
@ -34,7 +35,12 @@ namespace SHADE
Handle<ResourceType> SHResourceManager::LoadOrGet(AssetID assetId) Handle<ResourceType> SHResourceManager::LoadOrGet(AssetID assetId)
{ {
// Check if it is an unsupported type // Check if it is an unsupported type
if (!std::is_same_v<ResourceType, SHMesh> && !std::is_same_v<ResourceType, SHTexture>) if (!std::is_same_v<ResourceType, SHMesh> &&
!std::is_same_v<ResourceType, SHTexture> &&
!std::is_same_v<ResourceType, SHVkShaderModule> &&
!std::is_same_v<ResourceType, SHMaterialSpec> &&
!std::is_same_v<ResourceType, SHMaterial>
)
{ {
static_assert(true, "Unsupported Resource Type specified for SHResourceManager."); static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
} }
@ -60,8 +66,35 @@ namespace SHADE
return handle; return handle;
} }
template<>
Handle<SHMaterial> SHResourceManager::LoadOrGet<SHMaterial>(AssetID assetId)
{
/* Attempt to get existing loaded asset */
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<SHMaterial>();
if (typedHandleMap.get().contains(assetId))
return Handle<SHMaterial>(typedHandleMap.get()[assetId]);
/* Otherwise, we need to load it! */
// Get system
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Get SHMaterialSpec
Handle<SHMaterialSpec> matSpec = LoadOrGet<SHMaterialSpec>(assetId);
if (!matSpec)
return {};
// Create the material
auto handle = load<SHMaterial>(assetId, *matSpec);
Handle genericHandle = Handle(handle);
typedHandleMap.get().emplace(assetId, genericHandle);
typedAssetIdMap.get().emplace(genericHandle, assetId);
return handle;
}
template<typename ResourceType> template<typename ResourceType>
void SHResourceManager::Unload(Handle<ResourceType> assetId) void SHResourceManager::Unload(Handle<ResourceType> asset)
{ {
// Check if it is an unsupported type // Check if it is an unsupported type
if (!std::is_same_v<ResourceType, SHMesh> && !std::is_same_v<ResourceType, SHTexture>) if (!std::is_same_v<ResourceType, SHMesh> && !std::is_same_v<ResourceType, SHTexture>)
@ -71,14 +104,18 @@ namespace SHADE
/* Attempt to get existing loaded asset */ /* Attempt to get existing loaded asset */
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>(); auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>();
if (typedHandleMap.get().contains(assetId)) if (typedHandleMap.get().contains(asset))
{ {
// Remove from ResourceHub if SHMaterialSpec
if (std::is_same_v<ResourceType, SHMaterialSpec>)
resourceHub.Free(asset);
// Dispose // Dispose
Handle handle = typedHandleMap.get()[assetId]; Handle handle = typedHandleMap.get()[asset];
Handle<ResourceType> typedHandle = static_cast<Handle<ResourceType>>(handle); auto typedHandle = static_cast<Handle<ResourceType>>(handle);
typedHandle.Free(); typedHandle.Free();
typedAssetIdMap.get().erase(handle); typedAssetIdMap.get().erase(handle);
typedHandleMap.get().erase(assetId); typedHandleMap.get().erase(asset);
} }
else else
{ {
@ -143,13 +180,13 @@ namespace SHADE
return gfxSystem->AddMesh return gfxSystem->AddMesh
( (
assetData.vertexPosition.size(), assetData.VertexPositions.size(),
assetData.vertexPosition.data(), assetData.VertexPositions.data(),
assetData.texCoords.data(), assetData.VertexTexCoords.data(),
assetData.vertexTangent.data(), assetData.VertexTangents.data(),
assetData.vertexNormal.data(), assetData.VertexNormals.data(),
assetData.indices.size(), assetData.Indices.size(),
assetData.indices.data() assetData.Indices.data()
); );
} }
// Textures // Textures
@ -181,15 +218,27 @@ namespace SHADE
shader->Reflect(); shader->Reflect();
return shader; return shader;
} }
// Material Spec
else if constexpr (std::is_same_v<ResourceType, SHMaterialSpec>)
{
// Get the data we need to construct
auto matSpec = resourceHub.Create<SHMaterialSpec>();
YAML::convert<SHMaterialSpec>::decode(*YAML::Load(assetData.data).begin(), *matSpec);
// Failed to load
if (matSpec->subpassName == "")
{
// Use default material
*matSpec = SHMaterialSpec(*gfxSystem->GetDefaultMaterial());
}
return matSpec;
}
// Materials // Materials
else if constexpr (std::is_same_v<ResourceType, SHMaterial>) else if constexpr (std::is_same_v<ResourceType, SHMaterial>)
{ {
// Get the data we need to construct
SHMaterialSpec matSpec = YAML::Node(assetData.data).as<SHMaterialSpec>();
// Load shaders // Load shaders
auto vertexShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(matSpec.vertexShader); auto vertexShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(assetData.vertexShader);
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(matSpec.fragShader); auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(assetData.fragShader);
// Ensure that both shaders are present // Ensure that both shaders are present
if (!(vertexShader && fragShader)) if (!(vertexShader && fragShader))
@ -205,7 +254,7 @@ namespace SHADE
SHLOG_ERROR("[SHResourceManager] Failed to load material as RenderPass could not be found."); SHLOG_ERROR("[SHResourceManager] Failed to load material as RenderPass could not be found.");
return {}; return {};
} }
auto subPass = renderPass->GetSubpass(matSpec.subpassName); auto subPass = renderPass->GetSubpass(assetData.subpassName);
if (!subPass) if (!subPass)
{ {
SHLOG_ERROR("[SHResourceManager] Failed to load material as SubPass could not be found."); SHLOG_ERROR("[SHResourceManager] Failed to load material as SubPass could not be found.");
@ -220,8 +269,8 @@ namespace SHADE
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i) for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
{ {
const std::string& PROP_NAME = pipelineProperties->GetVariableName(i); const std::string& PROP_NAME = pipelineProperties->GetVariableName(i);
const auto& PROP_NODE = matSpec.properties; const YAML::Node& PROP_NODE = assetData.properties[PROP_NAME.data()];
if (PROP_NODE) if (PROP_NODE.IsDefined())
{ {
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i); const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i); const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
@ -231,7 +280,21 @@ namespace SHADE
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<float>()); matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<float>());
break; break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT: case SHADE::SHShaderBlockInterface::Variable::Type::INT:
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<int>()); {
Handle<SHTexture> texture = LoadOrGet<SHTexture>(PROP_NODE.as<int>());
// HACK: Need to split this out to a separate pass before loading the materials and subsequently, the scenes
gfxSystem->BuildTextures();
if (texture)
{
matHandle->SetProperty(VARIABLE->offset, texture->TextureArrayIndex);
}
else
{
SHLOG_WARNING("[] Attempted to load invalid texture! Setting to 0.");
matHandle->SetProperty(VARIABLE->offset, 0);
}
}
break; break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2: case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec2>()); matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec2>());

View File

@ -13,6 +13,7 @@
#include <string> #include <string>
#include "SHSceneGraph.h" #include "SHSceneGraph.h"
#include "Assets/SHAssetMacros.h"
#include "ECS_Base/General/SHFamily.h" #include "ECS_Base/General/SHFamily.h"
namespace SHADE namespace SHADE
@ -32,6 +33,7 @@ namespace SHADE
virtual ~SHScene() = default; virtual ~SHScene() = default;
std::string sceneName; std::string sceneName;
AssetID sceneAssetID;
SHSceneGraph& GetSceneGraph() noexcept { return sceneGraph; } SHSceneGraph& GetSceneGraph() noexcept { return sceneGraph; }

View File

@ -29,7 +29,7 @@ namespace SHADE
std::string SHSceneManager::newSceneName{}; std::string SHSceneManager::newSceneName{};
uint32_t SHSceneManager::currentSceneID = UINT32_MAX; uint32_t SHSceneManager::currentSceneID = UINT32_MAX;
uint32_t SHSceneManager::nextSceneID = UINT32_MAX; uint32_t SHSceneManager::nextSceneID = UINT32_MAX;
AssetID SHSceneManager::currentSceneAssetID{};
SHScene* SHSceneManager::currentScene = nullptr; SHScene* SHSceneManager::currentScene = nullptr;
//SHScene* SHSceneManager::nextScene = nullptr; //SHScene* SHSceneManager::nextScene = nullptr;
@ -107,16 +107,18 @@ namespace SHADE
} }
} }
void SHSceneManager::RestartScene(std::string const& sceneName) noexcept void SHSceneManager::RestartScene(AssetID const& assetID ) noexcept
{ {
if (currentScene->sceneName != sceneName) if (currentScene->sceneAssetID != assetID)
{ {
cleanReload = true; //cleanReload = true;
newSceneName = sceneName; cleanReload = false;
//newSceneName = sceneName;
} }
else else
cleanReload = false; cleanReload = false;
currentScene->sceneAssetID = assetID;
nextSceneID = currentSceneID; nextSceneID = currentSceneID;
sceneChanged = true; sceneChanged = true;
} }
@ -151,4 +153,20 @@ namespace SHADE
{ {
return currentScene->sceneName; return currentScene->sceneName;
} }
void SHSceneManager::SetCurrentSceneName(std::string const& sceneName) noexcept
{
currentScene->sceneName = sceneName;
}
AssetID SHSceneManager::GetCurrentSceneAssetID() noexcept
{
return currentScene->sceneAssetID;
}
void SHSceneManager::SetCurrentSceneAssetID(AssetID const& newAssetID)
{
currentScene->sceneAssetID = newAssetID;
currentSceneAssetID = newAssetID;
}
} }

View File

@ -20,6 +20,7 @@
//Project Headers //Project Headers
#include "SH_API.h" #include "SH_API.h"
#include "ECS_Base/General/SHFamily.h" #include "ECS_Base/General/SHFamily.h"
#include "Assets/SHAssetMacros.h"
namespace SHADE namespace SHADE
{ {
@ -47,6 +48,9 @@ namespace SHADE
//pointer to the current scene //pointer to the current scene
static SHScene* currentScene; static SHScene* currentScene;
//Scene AssetID of the current scene
static AssetID currentSceneAssetID;
//Used in reloading scene. //Used in reloading scene.
static std::string newSceneName; static std::string newSceneName;
@ -80,10 +84,10 @@ namespace SHADE
* None. * None.
***************************************************************************/ ***************************************************************************/
template<typename T> template<typename T>
static std::enable_if_t<std::is_base_of_v<SHScene, T>, void> InitSceneManager(std::string const& sceneName) noexcept static std::enable_if_t<std::is_base_of_v<SHScene, T>, void> InitSceneManager(AssetID const& sceneAssetID) noexcept
{ {
//prevSceneCreate = newScene; //prevSceneCreate = newScene;
newScene = [sceneName]() { currentScene = new T(); currentScene->sceneName = sceneName; }; newScene = [sceneAssetID]() { currentScene = new T(); currentScene->sceneAssetID = sceneAssetID; };
//nextSceneID = SHFamilyID<SHScene>::GetID<T>(); //nextSceneID = SHFamilyID<SHScene>::GetID<T>();
nextSceneID = 0; nextSceneID = 0;
@ -99,7 +103,7 @@ namespace SHADE
* None. * None.
***************************************************************************/ ***************************************************************************/
template<typename T> template<typename T>
static std::enable_if_t<std::is_base_of_v<SHScene, T>, void> ChangeScene(std::string const& sceneName) noexcept static std::enable_if_t<std::is_base_of_v<SHScene, T>, void> ChangeScene(AssetID const& sceneAssetID) noexcept
{ {
//check if this new Scene is current Scene (Use RestartScene instead) //check if this new Scene is current Scene (Use RestartScene instead)
if (currentSceneID == SHFamilyID<SHScene>::GetID<T>()) if (currentSceneID == SHFamilyID<SHScene>::GetID<T>())
@ -107,7 +111,7 @@ namespace SHADE
return; return;
} }
//prevSceneCreate = newScene; //prevSceneCreate = newScene;
newScene = [sceneName]() { currentScene = new T(); currentScene->sceneName; }; newScene = [sceneAssetID]() { currentScene = new T(); currentScene->sceneAssetID = sceneAssetID; };
nextSceneID = SHFamilyID<SHScene>::GetID<T>(); nextSceneID = SHFamilyID<SHScene>::GetID<T>();
sceneChanged = true; sceneChanged = true;
} }
@ -137,11 +141,11 @@ namespace SHADE
* Restarts current scene. Only Scene::Init() and Scene::Free() * Restarts current scene. Only Scene::Init() and Scene::Free()
* Scene::Load() and Scene::Unload() will not be called. * Scene::Load() and Scene::Unload() will not be called.
* Edit: allows for RestartScene to restart the scene with a different * Edit: allows for RestartScene to restart the scene with a different
* scene name. * scene asset ID.
* If a sceneName is different from the current one, Load and Unload will * If a scene asset id is different from the current one, Load and Unload will
* run. * run.
***************************************************************************/ ***************************************************************************/
static void RestartScene(std::string const& sceneName ) noexcept; static void RestartScene(AssetID const& assetID ) noexcept;
/*!************************************************************************* /*!*************************************************************************
* \brief * \brief
@ -164,7 +168,10 @@ namespace SHADE
static void Exit() noexcept; static void Exit() noexcept;
static std::string GetSceneName() noexcept; static std::string GetSceneName() noexcept;
static void SetCurrentSceneName(std::string const& sceneName) noexcept;
static AssetID GetCurrentSceneAssetID() noexcept;
//Only if scene doesn't exist, and scene asset id needs to be updated to the new one
static void SetCurrentSceneAssetID(AssetID const& newAssetID);
}; };

View File

@ -0,0 +1,89 @@
#include "SHpch.h"
#include "SHConfigurationManager.h"
#include "Tools/FileIO/SHFileIO.h"
#include "Serialization/SHSerializationHelper.hpp"
namespace SHADE
{
SHApplicationConfig SHConfigurationManager::applicationConfig;
#ifdef SHEDITOR
SHEditorConfig SHConfigurationManager::editorConfig;
#endif
void SHConfigurationManager::SaveApplicationConfig()
{
YAML::Emitter out;
out << SHSerializationHelper::RTTRToNode(applicationConfig);
SHFileIO::WriteStringToFile(applicationConfigPath, out.c_str());
}
SHApplicationConfig& SHConfigurationManager::LoadApplicationConfig(WindowData* wndData)
{
if(!std::filesystem::exists(applicationConfigPath))
{
SaveApplicationConfig();
return applicationConfig;
}
auto const node = YAML::Load(SHFileIO::GetStringFromFile(applicationConfigPath));
auto properties = rttr::type::get<SHApplicationConfig>().get_properties();
for(auto const& property : properties)
{
if(node[property.get_name().data()].IsDefined())
SHSerializationHelper::InitializeProperty(&applicationConfig, property, node[property.get_name().data()]);
}
if(wndData != nullptr)
{
wndData->isFullscreen = applicationConfig.startInFullScreen;
wndData->title = std::wstring(applicationConfig.windowTitle.begin(), applicationConfig.windowTitle.end());
wndData->width = static_cast<uint32_t>(applicationConfig.windowSize.x);
wndData->height = static_cast<uint32_t>(applicationConfig.windowSize.y);
}
return applicationConfig;
}
#ifdef SHEDITOR
void SHConfigurationManager::SaveEditorConfig()
{
YAML::Emitter out;
out << SHSerializationHelper::RTTRToNode(editorConfig);
SHFileIO::WriteStringToFile(editorConfigPath, out.c_str());
}
SHEditorConfig& SHConfigurationManager::LoadEditorConfig()
{
auto const node = YAML::Load(SHFileIO::GetStringFromFile(editorConfigPath));
auto properties = rttr::type::get<SHApplicationConfig>().get_properties();
for(auto const& property : properties)
{
if(node[property.get_name().data()].IsDefined())
SHSerializationHelper::InitializeProperty(&editorConfig, property, node[property.get_name().data()]);
}
return editorConfig;
}
void SHConfigurationManager::FetchEditorCameraData()
{
}
void SHConfigurationManager::SetEditorCameraData()
{
}
#endif
}
RTTR_REGISTRATION
{
using namespace rttr;
using namespace SHADE;
registration::class_<SHApplicationConfig>("Application Config")
.property("Start in Fullscreen", &SHApplicationConfig::startInFullScreen)
.property("Starting Scene ID", &SHApplicationConfig::startingSceneID)
.property("Window Size", &SHApplicationConfig::windowSize)
.property("Window Title", &SHApplicationConfig::windowTitle);
}

View File

@ -0,0 +1,44 @@
#pragma once
#include <rttr/registration>
#include "Assets/SHAssetMacros.h"
#include "Graphics/Windowing/SHWindow.h"
#include "SH_API.h"
#include "Math/Vector/SHVec2.h"
namespace SHADE
{
struct SHApplicationConfig
{
bool startInFullScreen{ false };
AssetID startingSceneID{};
SHVec2 windowSize {1920, 1080};
std::string windowTitle {"SHADE Engine"};
RTTR_ENABLE()
};
struct SHEditorConfig
{
};
class SH_API SHConfigurationManager
{
public:
static constexpr std::string_view applicationConfigPath{"../../Assets/Application.SHConfig"};
static constexpr std::string_view editorConfigPath{"../../Assets/Editor/Editor.SHConfig"};
static void SaveApplicationConfig();
static SHApplicationConfig& LoadApplicationConfig(WindowData* wndData = nullptr);
static SHApplicationConfig applicationConfig;
#ifdef SHEDITOR
static void SaveEditorConfig();
static SHEditorConfig& LoadEditorConfig();
static SHEditorConfig editorConfig;
private:
static void FetchEditorCameraData();
static void SetEditorCameraData();
#endif
};
}

View File

@ -1,8 +1,8 @@
#include "SHpch.h" #include "SHpch.h"
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include "SHSerializationHelper.hpp"
#include "SHSerialization.h" #include "SHSerialization.h"
#include "SHSerializationHelper.hpp"
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
@ -10,6 +10,7 @@
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include <fstream> #include <fstream>
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Camera/SHCameraComponent.h" #include "Camera/SHCameraComponent.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
@ -17,19 +18,23 @@
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Tools/FileIO/SHFileIO.h"
namespace SHADE namespace SHADE
{ {
void SHSerialization::SerializeSceneToFile(std::filesystem::path const& path) bool SHSerialization::SerializeSceneToFile(AssetID const& sceneAssetID)
{ {
auto assetData = SHAssetManager::GetData<SHSceneAsset>(sceneAssetID);
if(!assetData)
{
SHLOG_ERROR("Asset does not exist: {}", sceneAssetID);
return false;
}
YAML::Emitter out; YAML::Emitter out;
SerializeSceneToEmitter(out); SerializeSceneToEmitter(out);
std::ofstream file(path.c_str()); assetData->data = out.c_str();
if (file.good())
{ return SHAssetManager::SaveAsset(sceneAssetID);
file << out.c_str();
file.close();
}
} }
std::string SHSerialization::SerializeSceneToString() std::string SHSerialization::SerializeSceneToString()
@ -91,31 +96,16 @@ namespace SHADE
return eid; return eid;
} }
void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path) std::string SHSerialization::DeserializeSceneFromFile(AssetID const& sceneAssetID) noexcept
{ {
//TODO:Shift to using XQ's FileIO auto assetData = SHAssetManager::GetData<SHSceneAsset>(sceneAssetID);
std::ifstream iFile; if(!assetData)
iFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
std::string fileContent = "";
try
{ {
// Open file SHLOG_ERROR("Attempted to load scene that doesn't exist {}", sceneAssetID)
// Read file's buffer contents into streams SHSceneManager::SetCurrentSceneAssetID(0);
iFile.open(path); return NewSceneName.data();
std::stringstream fileStream;
fileStream << iFile.rdbuf();
fileContent = fileStream.str();
// Close file handler
iFile.close();
} }
catch (std::ifstream::failure e) YAML::Node entities = YAML::Load(assetData->data);
{
SHLOG_ERROR("Could not read file");
}
YAML::Node entities = YAML::Load(fileContent);
std::vector<EntityID> createdEntities{}; std::vector<EntityID> createdEntities{};
//Create Entities //Create Entities
@ -126,14 +116,23 @@ namespace SHADE
if (createdEntities.empty()) if (createdEntities.empty())
{ {
SHLOG_ERROR("Failed to create entities from deserializaiton") SHLOG_ERROR("Failed to create entities from deserializaiton")
return; return NewSceneName.data();
} }
//Initialize Entity
auto entityVecIt = createdEntities.begin(); auto entityVecIt = createdEntities.begin();
AssetQueue assetQueue;
for (auto it = entities.begin(); it != entities.end(); ++it)
{
SHSerializationHelper::FetchAssetsFromComponent<SHRenderable>((*it)[ComponentsNode], *entityVecIt, assetQueue);
}
LoadAssetsFromAssetQueue(assetQueue);
//Initialize Entity
entityVecIt = createdEntities.begin();
for (auto it = entities.begin(); it != entities.end(); ++it) for (auto it = entities.begin(); it != entities.end(); ++it)
{ {
InitializeEntity(*it, *entityVecIt++); InitializeEntity(*it, *entityVecIt++);
} }
return assetData->name;
} }
void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out) void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out)
@ -264,6 +263,33 @@ namespace SHADE
return componentIDList; return componentIDList;
} }
void SHSerialization::LoadAssetsFromAssetQueue(AssetQueue& assetQueue)
{
for (auto& [assetId, assetType] : assetQueue)
{
switch(assetType)
{
case AssetType::INVALID: break;
case AssetType::SHADER: break;
case AssetType::SHADER_BUILT_IN: break;
case AssetType::TEXTURE:
SHResourceManager::LoadOrGet<SHTexture>(assetId);
break;
case AssetType::MESH:
SHResourceManager::LoadOrGet<SHMesh>(assetId);
break;
case AssetType::SCENE: break;
case AssetType::PREFAB: break;
case AssetType::MATERIAL:
SHResourceManager::LoadOrGet<SHMaterial>(assetId);
break;
case AssetType::MAX_COUNT: break;
default: ;
}
}
SHResourceManager::FinaliseChanges();
}
void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid) void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid)
{ {
auto const componentsNode = entityNode[ComponentsNode]; auto const componentsNode = entityNode[ComponentsNode];

View File

@ -4,7 +4,10 @@
#include <string> #include <string>
#include <filesystem> #include <filesystem>
#include <ECS_Base/Components/SHComponent.h>
#include "ECS_Base/SHECSMacros.h"
#include <Assets/SHAssetMacros.h>
#include <unordered_map>
namespace YAML namespace YAML
{ {
@ -25,12 +28,11 @@ namespace SHADE
struct SH_API SHSerialization struct SH_API SHSerialization
{ {
//TODO: change paths to resource ID static bool SerializeSceneToFile(AssetID const& sceneAssetID);
static void SerializeSceneToFile(std::filesystem::path const& path);
static std::string SerializeSceneToString(); static std::string SerializeSceneToString();
static void SerializeSceneToEmitter(YAML::Emitter& out); static void SerializeSceneToEmitter(YAML::Emitter& out);
static void DeserializeSceneFromFile(std::filesystem::path const& path); static std::string DeserializeSceneFromFile(AssetID const& sceneAssetID) noexcept;
static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out); static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out);
@ -42,7 +44,11 @@ namespace SHADE
static EntityID DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept; static EntityID DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept;
static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode); static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
static void LoadAssetsFromAssetQueue(std::unordered_map<AssetID, AssetType>& assetQueue);
private: private:
static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid); static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);
static constexpr std::string_view NewSceneName = "New Scene";
}; };
} }

View File

@ -1,392 +1,20 @@
#pragma once #pragma once
#include "SHYAMLConverters.h"
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include <rttr/registration> #include <rttr/registration>
#include <unordered_map>
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h"
#include "Math/Vector/SHVec4.h"
#include "Resource/SHResourceManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "SHSerializationTools.h"
#include "Physics/Components/SHColliderComponent.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Tools/SHLog.h" #include "Tools/SHLog.h"
namespace YAML
{
using namespace SHADE;
template<>
struct convert<SHVec4>
{
static constexpr const char* x = "x";
static constexpr const char* y = "y";
static constexpr const char* z = "z";
static constexpr const char* w = "w";
static Node encode(SHVec4 const& rhs)
{
Node node;
node.SetStyle(EmitterStyle::Flow);
node[x] = rhs.x;
node[y] = rhs.y;
node[z] = rhs.z;
node[w] = rhs.w;
return node;
}
static bool decode(Node const& node, SHVec4& rhs)
{
if (node[x].IsDefined())
rhs.x = node[x].as<float>();
if (node[y].IsDefined())
rhs.y = node[y].as<float>();
if (node[z].IsDefined())
rhs.z = node[z].as<float>();
if (node[w].IsDefined())
rhs.w = node[w].as<float>();
return true;
}
};
template<>
struct convert<SHVec3>
{
static constexpr const char* x = "x";
static constexpr const char* y = "y";
static constexpr const char* z = "z";
static Node encode(SHVec3 const& rhs)
{
Node node;
node.SetStyle(EmitterStyle::Flow);
node[x] = rhs.x;
node[y] = rhs.y;
node[z] = rhs.z;
return node;
}
static bool decode(Node const& node, SHVec3& rhs)
{
if (node[x].IsDefined())
rhs.x = node[x].as<float>();
if (node[y].IsDefined())
rhs.y = node[y].as<float>();
if (node[z].IsDefined())
rhs.z = node[z].as<float>();
return true;
}
};
template<>
struct convert<SHVec2>
{
static constexpr const char* x = "x";
static constexpr const char* y = "y";
static Node encode(SHVec2 const& rhs)
{
Node node;
node.SetStyle(EmitterStyle::Flow);
node[x] = rhs.x;
node[y] = rhs.y;
return node;
}
static bool decode(Node const& node, SHVec2& rhs)
{
if (node[x].IsDefined())
rhs.x = node[x].as<float>();
if (node[y].IsDefined())
rhs.y = node[y].as<float>();
return true;
}
};
template<>
struct convert<SHCollider>
{
static constexpr const char* IsTrigger = "Is Trigger";
static constexpr const char* Type = "Type";
static constexpr const char* HalfExtents = "Half Extents";
static constexpr const char* Radius = "Radius";
static constexpr const char* Friction = "Friction";
static constexpr const char* Bounciness = "Bounciness";
static constexpr const char* Density = "Density";
static constexpr const char* PositionOffset = "Position Offset";
static Node encode(SHCollider& rhs)
{
Node node;
node[IsTrigger] = rhs.IsTrigger();
rttr::type const shapeRttrType = rttr::type::get<SHCollider::Type>();
rttr::enumeration const enumAlign = shapeRttrType.get_enumeration();
SHCollider::Type colliderType = rhs.GetType();
node[Type] = enumAlign.value_to_name(colliderType).data();
switch (colliderType)
{
case SHCollider::Type::BOX:
{
auto const bb = reinterpret_cast<SHBoundingBox*>(rhs.GetShape());
node[HalfExtents] = bb->GetHalfExtents();
}
break;
case SHCollider::Type::SPHERE:
{
auto const bs = reinterpret_cast<SHBoundingSphere*>(rhs.GetShape());
node[Radius] = bs->GetRadius();
}
break;
case SHCollider::Type::CAPSULE: break;
default:;
}
node[Friction] = rhs.GetFriction();
node[Bounciness] = rhs.GetBounciness();
node[Density] = rhs.GetDensity();
node[PositionOffset] = rhs.GetPositionOffset();
return node;
}
static bool decode(Node const& node, SHCollider& rhs)
{
if (node[IsTrigger].IsDefined())
rhs.SetIsTrigger(node[IsTrigger].as<bool>());
if (!node[Type].IsDefined())
return false;
rttr::type const shapeRttrType = rttr::type::get<SHCollider::Type>();
rttr::enumeration const enumAlign = shapeRttrType.get_enumeration();
bool ok;
const SHCollider::Type colliderType = enumAlign.name_to_value(node[Type].as<std::string>()).convert<SHCollider::Type>(&ok);
if (!ok)
return false;
switch (colliderType)
{
case SHCollider::Type::BOX:
{
if(node[HalfExtents].IsDefined())
rhs.SetBoundingBox(node[HalfExtents].as<SHVec3>());
}
break;
case SHCollider::Type::SPHERE:
{
if(node[Radius].IsDefined())
rhs.SetBoundingSphere(node[Radius].as<float>());
}
break;
case SHCollider::Type::CAPSULE: break;
default:;
}
if (node[Friction].IsDefined())
rhs.SetFriction(node[Friction].as<float>());
if (node[Bounciness].IsDefined())
rhs.SetBounciness(rhs.GetBounciness());
if (node[Density].IsDefined())
rhs.SetDensity(node[Density].as<float>());
if (node[PositionOffset].IsDefined())
rhs.SetPositionOffset(node[PositionOffset].as<SHVec3>());
return true;
}
};
template<>
struct convert<SHColliderComponent>
{
static constexpr const char* Colliders = "Colliders";
static Node encode(SHColliderComponent& rhs)
{
Node node, collidersNode;
auto const& colliders = rhs.GetColliders();
int const numColliders = static_cast<int>(colliders.size());
for (int i = 0; i < numColliders; ++i)
{
auto& collider = rhs.GetCollider(i);
Node colliderNode = convert<SHCollider>::encode(collider);
if (colliderNode.IsDefined())
collidersNode[i] = colliderNode;
}
node[Colliders] = collidersNode;
return node;
}
static bool decode(Node const& node, SHColliderComponent& rhs)
{
if (node[Colliders].IsDefined())
{
int numColliders{};
for (auto const& colliderNode : node[Colliders])
{
rttr::type const shapeRttrType = rttr::type::get<SHCollider::Type>();
rttr::enumeration const enumAlign = shapeRttrType.get_enumeration();
bool ok = false;
const SHCollider::Type colliderType = enumAlign.name_to_value(colliderNode[convert<SHCollider>::Type].as<std::string>()).convert<SHCollider::Type>(&ok);
if (!ok)
return false;
switch (colliderType)
{
case SHCollider::Type::BOX: rhs.AddBoundingBox(); break;
case SHCollider::Type::SPHERE: rhs.AddBoundingSphere(); break;
case SHCollider::Type::CAPSULE: break;
default:;
}
YAML::convert<SHCollider>::decode(colliderNode, rhs.GetCollider(numColliders++));
}
}
return true;
}
};
template<>
struct convert<SHMaterial>
{
static constexpr std::string_view VERT_SHADER_YAML_TAG = "VertexShader";
static constexpr std::string_view FRAG_SHADER_YAML_TAG = "FragmentShader";
static constexpr std::string_view SUBPASS_YAML_TAG = "SubPass";
static constexpr std::string_view PROPS_YAML_TAG = "Properties";
static YAML::Node encode(SHMaterial const& rhs)
{
// Write Properties
YAML::Node propertiesNode;
Handle<SHShaderBlockInterface> pipelineProperties = rhs.GetShaderBlockInterface();
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
{
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
if (!VARIABLE)
break;
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
YAML::Node propNode;
switch (VARIABLE->type)
{
case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT:
propNode = rhs.GetProperty<float>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
propNode = rhs.GetProperty<int>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
propNode = rhs.GetProperty<SHVec2>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
propNode = rhs.GetProperty<SHVec3>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
propNode = rhs.GetProperty<SHVec4>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::OTHER:
default:
continue;
break;
}
propertiesNode[VAR_NAME.data()] = propNode;
}
// Get Shader Handles
const auto& SHADERS = rhs.GetPipeline()->GetPipelineLayout()->GetShaderModules();
Handle<SHVkShaderModule> vertexShader, fragShader;
for (const auto& shader : SHADERS)
{
const auto FLAG_BITS = shader->GetShaderStageFlagBits();
if (FLAG_BITS & vk::ShaderStageFlagBits::eVertex)
vertexShader = shader;
else if (FLAG_BITS & vk::ShaderStageFlagBits::eFragment)
fragShader = shader;
}
// Write Material
YAML::Node node;
node[VERT_SHADER_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHVkShaderModule>(vertexShader).value_or(0);
node[FRAG_SHADER_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHVkShaderModule>(fragShader).value_or(0);
node[SUBPASS_YAML_TAG.data()] = rhs.GetPipeline()->GetPipelineState().GetSubpass()->GetName();
node[PROPS_YAML_TAG.data()] = propertiesNode;
return node;
}
};
template<>
struct convert<SHMaterialSpec>
{
static constexpr std::string_view VERT_SHADER_YAML_TAG = "VertexShader";
static constexpr std::string_view FRAG_SHADER_YAML_TAG = "FragmentShader";
static constexpr std::string_view SUBPASS_YAML_TAG = "SubPass";
static constexpr std::string_view PROPS_YAML_TAG = "Properties";
static bool decode(YAML::Node const& node, SHMaterialSpec& rhs)
{
// Retrieve Shader Asset IDs
if (!node[VERT_SHADER_YAML_TAG.data()])
return false;
rhs.vertexShader = node[VERT_SHADER_YAML_TAG.data()].as<AssetID>();
if (!node[FRAG_SHADER_YAML_TAG.data()])
return false;
rhs.fragShader = node[FRAG_SHADER_YAML_TAG.data()].as<AssetID>();
// Retrieve Subpass
if (!node[SUBPASS_YAML_TAG.data()])
return false;
rhs.subpassName = node[SUBPASS_YAML_TAG.data()].as<std::string>();
// Retrieve
if (!node[PROPS_YAML_TAG.data()])
return false;
rhs.properties = node[PROPS_YAML_TAG.data()];
return true;
}
};
template<>
struct convert<SHRenderable>
{
static constexpr std::string_view MESH_YAML_TAG = "Mesh";
static constexpr std::string_view MAT_YAML_TAG = "Material";
static YAML::Node encode(SHRenderable const& rhs)
{
YAML::Node node;
node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHMesh>(rhs.GetMesh()).value_or(0);
node[MAT_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHMaterial>(rhs.GetMaterial()->GetBaseMaterial()).value_or(0);
return node;
}
static bool decode(YAML::Node const& node, SHRenderable& rhs)
{
if (node[MESH_YAML_TAG.data()].IsDefined())
{
rhs.SetMesh(SHResourceManager::LoadOrGet<SHMesh>(node[MESH_YAML_TAG.data()].as<AssetID>()));
}
if (node[MAT_YAML_TAG.data()].IsDefined())
{
// Temporarily, use default material
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (!gfxSystem)
return false;
Handle<SHMaterial> baseMat = SHResourceManager::LoadOrGet<SHMaterial>(node[MAT_YAML_TAG.data()].as<AssetID>());
if (!baseMat)
{
baseMat = gfxSystem->GetDefaultMaterial();
SHLog::Warning("[SHSerializationHelper] Unable to load specified material. Falling back to default material.");
}
rhs.SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(baseMat));
}
return true;
}
};
}
namespace SHADE namespace SHADE
{ {
using AssetQueue = std::unordered_map<AssetID, AssetType>;
struct SHSerializationHelper struct SHSerializationHelper
{ {
@ -460,6 +88,8 @@ namespace SHADE
node = YAML::Null; node = YAML::Null;
} }
} }
else if (varType == rttr::type::get<std::string>())
node = var.to_string();
else else
{ {
auto properties = var.get_type().get_properties(); auto properties = var.get_type().get_properties();
@ -495,63 +125,65 @@ namespace SHADE
return node; return node;
} }
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true> template <typename Type>
static void InitializeProperty(ComponentType* component, rttr::property const& prop, YAML::Node const& propertyNode) static void InitializeProperty(Type* object, rttr::property const& prop, YAML::Node const& propertyNode)
{ {
auto propType = prop.get_type(); auto propType = prop.get_type();
if (propType == rttr::type::get<SHVec4>()) if (propType == rttr::type::get<SHVec4>())
{ {
SHVec4 vec = propertyNode.as<SHVec4>(); SHVec4 vec = propertyNode.as<SHVec4>();
prop.set_value(component, vec); prop.set_value(object, vec);
} }
else if (propType == rttr::type::get<SHVec3>()) else if (propType == rttr::type::get<SHVec3>())
{ {
SHVec3 vec = propertyNode.as<SHVec3>(); SHVec3 vec = propertyNode.as<SHVec3>();
prop.set_value(component, vec); prop.set_value(object, vec);
} }
else if (propType == rttr::type::get<SHVec2>()) else if (propType == rttr::type::get<SHVec2>())
{ {
SHVec2 vec = propertyNode.as<SHVec2>(); SHVec2 vec = propertyNode.as<SHVec2>();
prop.set_value(component, vec); prop.set_value(object, vec);
} }
else if (propType.is_arithmetic()) else if (propType.is_arithmetic())
{ {
bool ok = false; bool ok = false;
if (propType == rttr::type::get<bool>()) if (propType == rttr::type::get<bool>())
prop.set_value(component, propertyNode.as<bool>()); prop.set_value(object, propertyNode.as<bool>());
else if (propType == rttr::type::get<int8_t>()) else if (propType == rttr::type::get<int8_t>())
prop.set_value(component, propertyNode.as<int8_t>()); prop.set_value(object, propertyNode.as<int8_t>());
else if (propType == rttr::type::get<int16_t>()) else if (propType == rttr::type::get<int16_t>())
prop.set_value(component, propertyNode.as<int16_t>()); prop.set_value(object, propertyNode.as<int16_t>());
else if (propType == rttr::type::get<int32_t>()) else if (propType == rttr::type::get<int32_t>())
prop.set_value(component, propertyNode.as<int32_t>()); prop.set_value(object, propertyNode.as<int32_t>());
else if (propType == rttr::type::get<int64_t>()) else if (propType == rttr::type::get<int64_t>())
prop.set_value(component, propertyNode.as<int64_t>()); prop.set_value(object, propertyNode.as<int64_t>());
else if (propType == rttr::type::get<uint8_t>()) else if (propType == rttr::type::get<uint8_t>())
prop.set_value(component, propertyNode.as<uint8_t>()); prop.set_value(object, propertyNode.as<uint8_t>());
else if (propType == rttr::type::get<uint16_t>()) else if (propType == rttr::type::get<uint16_t>())
prop.set_value(component, propertyNode.as<uint16_t>()); prop.set_value(object, propertyNode.as<uint16_t>());
else if (propType == rttr::type::get<uint32_t>()) else if (propType == rttr::type::get<uint32_t>())
prop.set_value(component, propertyNode.as<uint32_t>()); prop.set_value(object, propertyNode.as<uint32_t>());
else if (propType == rttr::type::get<uint64_t>()) else if (propType == rttr::type::get<uint64_t>())
prop.set_value(component, propertyNode.as<uint64_t>()); prop.set_value(object, propertyNode.as<uint64_t>());
else if (propType == rttr::type::get<float>()) else if (propType == rttr::type::get<float>())
prop.set_value(component, propertyNode.as<float>()); prop.set_value(object, propertyNode.as<float>());
else if (propType == rttr::type::get<double>()) else if (propType == rttr::type::get<double>())
prop.set_value(component, propertyNode.as<double>()); prop.set_value(object, propertyNode.as<double>());
} }
else if (propType.is_enumeration()) else if (propType.is_enumeration())
{ {
auto enumAlign = prop.get_enumeration(); auto enumAlign = prop.get_enumeration();
prop.set_value(component, enumAlign.name_to_value(propertyNode.as<std::string>())); prop.set_value(object, enumAlign.name_to_value(propertyNode.as<std::string>()));
} }
else if (propType == rttr::type::get<std::string>())
prop.set_value(object, propertyNode.as<std::string>());
else else
{ {
auto properties = propType.get_properties(); auto properties = propType.get_properties();
for (auto const& property : properties) for (auto const& property : properties)
{ {
if(propertyNode[property.get_name().data()].IsDefined()) if(propertyNode[property.get_name().data()].IsDefined())
InitializeProperty(component, property, propertyNode[property.get_name().data()]); InitializeProperty(object, property, propertyNode[property.get_name().data()]);
} }
} }
} }
@ -564,7 +196,7 @@ namespace SHADE
return; return;
auto rttrType = rttr::type::get<ComponentType>(); auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()]; auto componentNode = componentsNode[rttrType.get_name().data()];
if(!componentNode.IsDefined()) if (!componentNode.IsDefined())
return; return;
auto properties = rttrType.get_properties(); auto properties = rttrType.get_properties();
for (auto const& prop : properties) for (auto const& prop : properties)
@ -576,18 +208,73 @@ namespace SHADE
} }
} }
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static YAML::Node GetComponentNode(YAML::Node const& componentsNode, EntityID const& eid)
{
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component)
return {};
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (!componentNode.IsDefined())
return {};
return componentNode;
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true> template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void ConvertNodeToComponent(YAML::Node const& componentsNode, EntityID const& eid) static void ConvertNodeToComponent(YAML::Node const& componentsNode, EntityID const& eid)
{ {
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid); auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component) if (componentsNode.IsNull() && !component)
return; return;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()]; YAML::convert<ComponentType>::decode(GetComponentNode<ComponentType>(componentsNode, eid), *component);
if (!componentNode.IsDefined())
return;
YAML::convert<ComponentType>::decode(componentNode, *component);
} }
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void FetchAssetsFromComponent(YAML::Node const& componentsNode, EntityID const& eid, AssetQueue& assetQueue)
{
}
template<>
static void FetchAssetsFromComponent<SHRenderable>(YAML::Node const& componentsNode, EntityID const& eid, AssetQueue& assetQueue)
{
auto node = GetComponentNode<SHRenderable>(componentsNode, eid);
if(!node.IsDefined())
return;
if (auto const& meshNode = node[YAML::convert<SHRenderable>::MESH_YAML_TAG.data()]; meshNode.IsDefined())
{
assetQueue.insert({meshNode.as<AssetID>(), AssetType::MESH});
//SHResourceManager::LoadOrGet<SHMesh>(node[YAML::convert<SHRenderable>::MESH_YAML_TAG.data()].as<AssetID>());
}
if (auto const& matNode = node[YAML::convert<SHRenderable>::MAT_YAML_TAG.data()]; matNode.IsDefined())
{
auto const matAsset = SHAssetManager::GetData<SHMaterialAsset>(matNode.as<AssetID>());
if(matAsset)
{
SHMaterialSpec spec;
YAML::convert<SHMaterialSpec>::decode(*YAML::Load(matAsset->data).begin(), spec);
if(spec.properties.IsDefined())
{
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(spec.fragShader);
auto interface = fragShader->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA);
int const varCount = static_cast<int>(interface->GetVariableCount());
for (int i = 0; i < varCount; ++i)
{
auto variable = interface->GetVariable(i);
if(variable->type != SHShaderBlockInterface::Variable::Type::INT)
continue;
const std::string& VAR_NAME = interface->GetVariableName(i);
if(VAR_NAME.empty())
continue;
assetQueue.insert({spec.properties[VAR_NAME.data()].as<AssetID>(), AssetType::TEXTURE});
}
}
}
//assetQueue.insert({matNode.as<AssetID>(), AssetType::MATERIAL});
//SHResourceManager::LoadOrGet<SHMaterial>(node[YAML::convert<SHRenderable>::MAT_YAML_TAG.data()].as<AssetID>());
}
}
}; };
} }

View File

@ -0,0 +1,317 @@
#pragma once
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Math/Geometry/SHBoundingBox.h"
#include "Math/Geometry/SHBoundingSphere.h"
#include "Physics/SHCollider.h"
#include "Resource/SHResourceManager.h"
#include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h"
#include "Math/Vector/SHVec4.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "SHSerializationTools.h"
#include "Physics/Components/SHColliderComponent.h"
namespace YAML
{
using namespace SHADE;
template<>
struct convert<SHVec4>
{
static constexpr const char* x = "x";
static constexpr const char* y = "y";
static constexpr const char* z = "z";
static constexpr const char* w = "w";
static Node encode(SHVec4 const& rhs)
{
Node node;
node.SetStyle(EmitterStyle::Flow);
node[x] = rhs.x;
node[y] = rhs.y;
node[z] = rhs.z;
node[w] = rhs.w;
return node;
}
static bool decode(Node const& node, SHVec4& rhs)
{
if (node[x].IsDefined())
rhs.x = node[x].as<float>();
if (node[y].IsDefined())
rhs.y = node[y].as<float>();
if (node[z].IsDefined())
rhs.z = node[z].as<float>();
if (node[w].IsDefined())
rhs.w = node[w].as<float>();
return true;
}
};
template<>
struct convert<SHVec3>
{
static constexpr const char* x = "x";
static constexpr const char* y = "y";
static constexpr const char* z = "z";
static Node encode(SHVec3 const& rhs)
{
Node node;
node.SetStyle(EmitterStyle::Flow);
node[x] = rhs.x;
node[y] = rhs.y;
node[z] = rhs.z;
return node;
}
static bool decode(Node const& node, SHVec3& rhs)
{
if (node[x].IsDefined())
rhs.x = node[x].as<float>();
if (node[y].IsDefined())
rhs.y = node[y].as<float>();
if (node[z].IsDefined())
rhs.z = node[z].as<float>();
return true;
}
};
template<>
struct convert<SHVec2>
{
static constexpr const char* x = "x";
static constexpr const char* y = "y";
static Node encode(SHVec2 const& rhs)
{
Node node;
node.SetStyle(EmitterStyle::Flow);
node[x] = rhs.x;
node[y] = rhs.y;
return node;
}
static bool decode(Node const& node, SHVec2& rhs)
{
if (node[x].IsDefined())
rhs.x = node[x].as<float>();
if (node[y].IsDefined())
rhs.y = node[y].as<float>();
return true;
}
};
template<>
struct convert<SHCollider>
{
static constexpr const char* IsTrigger = "Is Trigger";
static constexpr const char* Type = "Type";
static constexpr const char* HalfExtents = "Half Extents";
static constexpr const char* Radius = "Radius";
static constexpr const char* Friction = "Friction";
static constexpr const char* Bounciness = "Bounciness";
static constexpr const char* Density = "Density";
static constexpr const char* PositionOffset = "Position Offset";
static Node encode(SHCollider& rhs)
{
Node node;
node[IsTrigger] = rhs.IsTrigger();
rttr::type const shapeRttrType = rttr::type::get<SHCollider::Type>();
rttr::enumeration const enumAlign = shapeRttrType.get_enumeration();
SHCollider::Type colliderType = rhs.GetType();
node[Type] = enumAlign.value_to_name(colliderType).data();
switch (colliderType)
{
case SHCollider::Type::BOX:
{
auto const bb = reinterpret_cast<SHBoundingBox*>(rhs.GetShape());
node[HalfExtents] = bb->GetHalfExtents();
}
break;
case SHCollider::Type::SPHERE:
{
auto const bs = reinterpret_cast<SHBoundingSphere*>(rhs.GetShape());
node[Radius] = bs->GetRadius();
}
break;
case SHCollider::Type::CAPSULE: break;
default:;
}
node[Friction] = rhs.GetFriction();
node[Bounciness] = rhs.GetBounciness();
node[Density] = rhs.GetDensity();
node[PositionOffset] = rhs.GetPositionOffset();
return node;
}
static bool decode(Node const& node, SHCollider& rhs)
{
if (node[IsTrigger].IsDefined())
rhs.SetIsTrigger(node[IsTrigger].as<bool>());
if (!node[Type].IsDefined())
return false;
rttr::type const shapeRttrType = rttr::type::get<SHCollider::Type>();
rttr::enumeration const enumAlign = shapeRttrType.get_enumeration();
bool ok;
const SHCollider::Type colliderType = enumAlign.name_to_value(node[Type].as<std::string>()).convert<SHCollider::Type>(&ok);
if (!ok)
return false;
switch (colliderType)
{
case SHCollider::Type::BOX:
{
if (node[HalfExtents].IsDefined())
rhs.SetBoundingBox(node[HalfExtents].as<SHVec3>());
}
break;
case SHCollider::Type::SPHERE:
{
if (node[Radius].IsDefined())
rhs.SetBoundingSphere(node[Radius].as<float>());
}
break;
case SHCollider::Type::CAPSULE: break;
default:;
}
if (node[Friction].IsDefined())
rhs.SetFriction(node[Friction].as<float>());
if (node[Bounciness].IsDefined())
rhs.SetBounciness(rhs.GetBounciness());
if (node[Density].IsDefined())
rhs.SetDensity(node[Density].as<float>());
if (node[PositionOffset].IsDefined())
rhs.SetPositionOffset(node[PositionOffset].as<SHVec3>());
return true;
}
};
template<>
struct convert<SHColliderComponent>
{
static constexpr const char* Colliders = "Colliders";
static Node encode(SHColliderComponent& rhs)
{
Node node, collidersNode;
auto const& colliders = rhs.GetColliders();
int const numColliders = static_cast<int>(colliders.size());
for (int i = 0; i < numColliders; ++i)
{
auto& collider = rhs.GetCollider(i);
Node colliderNode = convert<SHCollider>::encode(collider);
if (colliderNode.IsDefined())
collidersNode[i] = colliderNode;
}
node[Colliders] = collidersNode;
return node;
}
static bool decode(Node const& node, SHColliderComponent& rhs)
{
if (node[Colliders].IsDefined())
{
int numColliders{};
for (auto const& colliderNode : node[Colliders])
{
rttr::type const shapeRttrType = rttr::type::get<SHCollider::Type>();
rttr::enumeration const enumAlign = shapeRttrType.get_enumeration();
bool ok = false;
const SHCollider::Type colliderType = enumAlign.name_to_value(colliderNode[convert<SHCollider>::Type].as<std::string>()).convert<SHCollider::Type>(&ok);
if (!ok)
return false;
switch (colliderType)
{
case SHCollider::Type::BOX: rhs.AddBoundingBox(); break;
case SHCollider::Type::SPHERE: rhs.AddBoundingSphere(); break;
case SHCollider::Type::CAPSULE: break;
default:;
}
YAML::convert<SHCollider>::decode(colliderNode, rhs.GetCollider(numColliders++));
}
}
return true;
}
};
template<>
struct convert<SHMaterialSpec>
{
static constexpr std::string_view VERT_SHADER_YAML_TAG = "VertexShader";
static constexpr std::string_view FRAG_SHADER_YAML_TAG = "FragmentShader";
static constexpr std::string_view SUBPASS_YAML_TAG = "SubPass";
static constexpr std::string_view PROPS_YAML_TAG = "Properties";
static YAML::Node encode(SHMaterialSpec const& rhs)
{
YAML::Node node;
node[VERT_SHADER_YAML_TAG.data()] = rhs.vertexShader;
node[FRAG_SHADER_YAML_TAG.data()] = rhs.fragShader;
node[SUBPASS_YAML_TAG.data()] = rhs.subpassName;
node[PROPS_YAML_TAG.data()] = rhs.properties;
return node;
}
static bool decode(YAML::Node const& node, SHMaterialSpec& rhs)
{
// Retrieve Shader Asset IDs
if (node[VERT_SHADER_YAML_TAG.data()].IsDefined())
rhs.vertexShader = node[VERT_SHADER_YAML_TAG.data()].as<AssetID>();
if (node[FRAG_SHADER_YAML_TAG.data()].IsDefined())
rhs.fragShader = node[FRAG_SHADER_YAML_TAG.data()].as<AssetID>();
// Retrieve Subpass
if (node[SUBPASS_YAML_TAG.data()].IsDefined())
rhs.subpassName = node[SUBPASS_YAML_TAG.data()].as<std::string>();
// Retrieve
if (node[PROPS_YAML_TAG.data()].IsDefined())
rhs.properties = node[PROPS_YAML_TAG.data()];
return true;
}
};
template<>
struct convert<SHRenderable>
{
static constexpr std::string_view MESH_YAML_TAG = "Mesh";
static constexpr std::string_view MAT_YAML_TAG = "Material";
static YAML::Node encode(SHRenderable const& rhs)
{
YAML::Node node;
node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHMesh>(rhs.GetMesh()).value_or(0);
node[MAT_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHMaterial>(rhs.GetMaterial()->GetBaseMaterial()).value_or(0);
return node;
}
static bool decode(YAML::Node const& node, SHRenderable& rhs)
{
if (node[MESH_YAML_TAG.data()].IsDefined())
{
rhs.SetMesh(SHResourceManager::LoadOrGet<SHMesh>(node[MESH_YAML_TAG.data()].as<AssetID>()));
}
if (node[MAT_YAML_TAG.data()].IsDefined())
{
// Temporarily, use default material
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (!gfxSystem)
return false;
Handle<SHMaterial> baseMat = SHResourceManager::LoadOrGet<SHMaterial>(node[MAT_YAML_TAG.data()].as<AssetID>());
if (!baseMat)
{
baseMat = gfxSystem->GetDefaultMaterial();
SHLog::Warning("[SHSerializationHelper] Unable to load specified material. Falling back to default material.");
}
rhs.SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(baseMat));
}
return true;
}
};
}

View File

@ -0,0 +1,31 @@
#include "SHpch.h"
#include "SHFileIO.h"
#include <fstream>
namespace SHADE
{
int SHFileIO::WriteStringToFile(std::filesystem::path const& filePath, std::string_view const& strView)
{
std::ofstream file(filePath);
if(file.good())
{
file << strView;
file.close();
return 1;
}
return 0;
}
std::string SHFileIO::GetStringFromFile(std::filesystem::path const& filePath)
{
std::ifstream iFile;
iFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
std::string fileData{};
iFile.open(filePath, std::iostream::binary);
std::stringstream ss;
ss << iFile.rdbuf();
fileData = ss.str();
iFile.close();
return fileData;
}
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <filesystem>
#include <string>
#include <string_view>
#include <SH_API.h>
namespace SHADE
{
struct SH_API SHFileIO
{
static int WriteStringToFile(std::filesystem::path const& filePath, std::string_view const& strView);
static std::string GetStringFromFile(std::filesystem::path const& file);
};
}

View File

@ -38,6 +38,7 @@ project "SHADE_Managed"
"%{IncludeDir.RTTR}/include", "%{IncludeDir.RTTR}/include",
"%{IncludeDir.dotnet}\\include", "%{IncludeDir.dotnet}\\include",
"%{IncludeDir.reactphysics3d}\\include", "%{IncludeDir.reactphysics3d}\\include",
"%{IncludeDir.VULKAN}\\include",
"%{wks.location}/SHADE_Engine/src" "%{wks.location}/SHADE_Engine/src"
} }

View File

@ -123,5 +123,14 @@ namespace SHADE
} }
Vector3 Camera::GetRight()
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
SHVec3 forward, up, right;
system->GetCameraAxis(*GetNativeComponent(), forward, right, up);
return Convert::ToCLI(right);
}
} }

View File

@ -66,5 +66,7 @@ namespace SHADE
void SetMainCamera(); void SetMainCamera();
void LookAt(Vector3 targetPosition); void LookAt(Vector3 targetPosition);
Vector3 GetForward(); Vector3 GetForward();
Vector3 GetRight();
}; };
} }

View File

@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using SHADE;
public class AIPrototype : Script
{
//This object's relevant components
private Transform transform;
private RigidBody rb;
/*[SerializeField]
[Tooltip("The list of waypoints that the object will move around on")]
private Vector3[] waypoints;*/
private Vector3[] waypoints = { new Vector3(-8.0f, -2.0f, 3.5f), new Vector3(-8.0f, -2.0f, -13.0f), new Vector3(8.0f, -2.0f, -13.0f), new Vector3(8.0f, -2.0f, 3.5f) };
[SerializeField]
[Tooltip("How much force is applied in movement")]
private float movementForceMultiplier = 100.0f;
[SerializeField]
[Tooltip("How fast the object moves about waypoints")]
private float patrolSpeed = 0.4f;
[SerializeField]
[Tooltip("How fast the object moves while chasing")]
private float chaseSpeed = 0.8f;
[SerializeField]
[Tooltip("How near the player must be to the AI for capture")]
private float distanceToCapture = 1.2f;
[SerializeField]
[Tooltip("How near the player must be for the chase to begin. Should be less than distanceToEndChase")]
private float distanceToStartChase = 2.0f;
[SerializeField]
[Tooltip("How far the player must be for the chase to end. Should be greater than distanceToStartChase")]
private float distanceToEndChase = 2.5f;
//Whether the AI is chasing or not
private bool chaseMode;
//To cycle depending on the length of waypoints
private int currentTargetWaypointIndex;
private GameObject? player;
public AIPrototype(GameObject gameObj) : base(gameObj) { }
protected override void awake()
{
transform = GetComponent<Transform>();
if (transform == null)
{
Debug.LogError("Transform is NULL!");
}
rb = GetComponent<RigidBody>();
if (rb == null)
{
Debug.LogError("Rigidbody is NULL!");
}
currentTargetWaypointIndex = 0;
player = GameObject.Find("Player");
if (player == null)
{
Debug.LogError("Player is NULL!");
}
chaseMode = false;
}
protected override void fixedUpdate()
{
//Patrolling
if (!chaseMode)
{
//Head towards the next target
Vector3 normalisedDifference = waypoints[currentTargetWaypointIndex] - transform.GlobalPosition;
normalisedDifference /= normalisedDifference.GetMagnitude();
//transform.GlobalPosition += normalisedDifference * moveSpeed * (float)Time.DeltaTime;
//rb.LinearVelocity = normalisedDifference * patrolSpeed;
//ORIGINAL INTENDED CODE
/*rb.AddForce(new Vector3(normalisedDifference.x, 0.0f, normalisedDifference.z) * movementForceMultiplier);
float currentSpeed = MathF.Sqrt(rb.LinearVelocity.x * rb.LinearVelocity.x + rb.LinearVelocity.z * rb.LinearVelocity.z);
if (currentSpeed > patrolSpeed)
{
float adjustmentFactor = patrolSpeed / currentSpeed;
Vector3 adjustedVelocity = rb.LinearVelocity;
//adjustedVelocity *= adjustmentFactor;
adjustedVelocity.x = patrolSpeed;
adjustedVelocity.z = patrolSpeed;
rb.LinearVelocity = adjustedVelocity;
}*/
//TODO delete this when original intended code above works with velocity being limited correctly
rb.LinearVelocity = normalisedDifference * patrolSpeed;
//transform.GlobalRotation.SetLookRotation(waypoints[currentTargetWaypointIndex], Vector3.Up);
//Cycle to next waypoint if near enough current waypoint
if ((waypoints[currentTargetWaypointIndex] - transform.GlobalPosition).GetSqrMagnitude() <= 0.5f)
{
++currentTargetWaypointIndex;
if (currentTargetWaypointIndex >= waypoints.Length)
{
currentTargetWaypointIndex = 0; //Recycle
}
}
//Go chase if near enough to player
if (player != null)
{
Transform pTransform = player.GetValueOrDefault().GetComponent<Transform>();
if ((pTransform.GlobalPosition - transform.GlobalPosition).GetMagnitude() <= distanceToStartChase)
{
//Start the chase
chaseMode = true;
}
}
}
else //Chasing
{
if (player != null)
{
Transform pTransform = player.GetValueOrDefault().GetComponent<Transform>();
//Chase the player
Vector3 normalisedDifference = pTransform.GlobalPosition - transform.GlobalPosition;
normalisedDifference /= normalisedDifference.GetMagnitude();
//transform.GlobalPosition += normalisedDifference * moveSpeed * (float)Time.DeltaTime;
//ORIGINAL INTENDED CODE
/*rb.AddForce(new Vector3(normalisedDifference.x, 0.0f, normalisedDifference.z) * movementForceMultiplier);
float currentSpeed = MathF.Sqrt(rb.LinearVelocity.x * rb.LinearVelocity.x + rb.LinearVelocity.z * rb.LinearVelocity.z);
if (currentSpeed > chaseSpeed)
{
float adjustmentFactor = chaseSpeed / currentSpeed;
Vector3 adjustedVelocity = rb.LinearVelocity;
adjustedVelocity *= adjustmentFactor;
rb.LinearVelocity = adjustedVelocity;
}*/
//TODO delete this when original intended code above works with velocity being limited correctly
rb.LinearVelocity = normalisedDifference * chaseSpeed;
//Capture player if near enough
if ((pTransform.GlobalPosition - transform.GlobalPosition).GetMagnitude() <= distanceToCapture)
{
player.GetValueOrDefault().GetScript<PlayerController>().currentState = PlayerController.RaccoonStates.CAUGHT;
}
//End chase if too far
if ((pTransform.GlobalPosition - transform.GlobalPosition).GetMagnitude() >= distanceToEndChase)
{
//Stop the chase
chaseMode = false;
//Find the nearest waypoint to go instead
float nearestWaypointDistance = 99999999999999.9f;
for (int i = 0; i < waypoints.Length; ++i)
{
if ((waypoints[i] - transform.GlobalPosition).GetSqrMagnitude() < nearestWaypointDistance)
{
nearestWaypointDistance = waypoints[i].GetSqrMagnitude();
currentTargetWaypointIndex = i;
}
}
}
}
}
}
}

View File

@ -0,0 +1,24 @@
using SHADE;
using System;
public class CameraFix : Script
{
public CameraFix(GameObject gameObj) : base(gameObj) { }
private Transform tranform;
public Vector3 pos = Vector3.Zero;
public Vector3 rot = Vector3.Zero;
protected override void awake()
{
tranform = GetComponent<Transform>();
if (tranform == null)
Debug.LogError("tranform is NULL!");
else
{
tranform.LocalPosition = pos;
tranform.LocalEulerAngles = rot;
}
}
}

18
TempScriptsFolder/Item.cs Normal file
View File

@ -0,0 +1,18 @@
using SHADE;
using System;
public class Item : Script
{
public enum ItemCategory
{
LIGHT,
MEDIUM,
HEAVY
}
public ItemCategory currCategory;
public Item(GameObject gameObj) : base(gameObj) { }
protected override void awake()
{
}
}

View File

@ -0,0 +1,99 @@
using SHADE;
using System;
using static PlayerController;
public class PickAndThrow : Script
{
public Vector3 throwForce = new Vector3(100.0f, 200.0f, 100.0f);
public GameObject item;
private PlayerController pc;
private Camera cam;
private Transform itemTransform;
private RigidBody itemRidibody;
private Transform raccoonHoldLocation;
private float lastXDir;
private float lastZDir;
private bool inRange = false;
public PickAndThrow(GameObject gameObj) : base(gameObj) { }
protected override void awake()
{
pc = GetScript<PlayerController>();
raccoonHoldLocation = GetComponentInChildren<Transform>();
if (raccoonHoldLocation == null)
Debug.Log("CHILD EMPTY");
else
raccoonHoldLocation.LocalPosition = new Vector3(0.0f, 1.0f, 0.0f);
}
protected override void update()
{
if (cam == null)
cam = GetComponentInChildren<Camera>();
else if (cam != null)
{
Vector3 camerAixs = cam.GetForward();
camerAixs.y = 0;
camerAixs.Normalise();
lastXDir = camerAixs.x;
lastZDir = camerAixs.z;
}
if (item.GetScript<Item>() != null && itemTransform == null && itemRidibody == null)
{
itemTransform = item.GetComponent<Transform>();
if (itemTransform == null)
Debug.Log("Item transform EMPTY");
itemRidibody = item.GetComponent<RigidBody>();
if (itemRidibody == null)
Debug.Log("Item rb EMPTY");
}
if (pc != null && inRange && !pc.holdItem && Input.GetKey(Input.KeyCode.E))
pc.holdItem = true;
if (pc != null && itemRidibody != null && itemTransform != null && pc.holdItem)
{
itemTransform.LocalPosition = raccoonHoldLocation.GlobalPosition;
itemRidibody.IsGravityEnabled = false;
itemRidibody.LinearVelocity = Vector3.Zero;
itemRidibody.AngularVelocity = Vector3.Zero;
if (Input.GetMouseButtonDown(Input.MouseCode.LeftButton))
{
pc.holdItem = false;
inRange = false;
itemRidibody.IsGravityEnabled = true;
itemRidibody.AddForce(new Vector3(throwForce.x * lastXDir, throwForce.y, throwForce.z * lastZDir));
itemRidibody.LinearVelocity += pc.rb.LinearVelocity;
}
}
else if(!pc.holdItem && itemRidibody != null)
itemRidibody.IsGravityEnabled = true;
}
protected override void onCollisionEnter(CollisionInfo info)
{
}
protected override void onTriggerEnter(CollisionInfo info)
{
//Debug.Log("ENTER");
if (info.GameObject.GetScript<Item>() != null && !pc.holdItem)
{
item = info.GameObject;
inRange = true;
}
}
protected override void onTriggerStay(CollisionInfo info)
{
//Debug.Log("STAY");
}
protected override void onTriggerExit(CollisionInfo info)
{
//Debug.Log("EXIT");
if (info.GameObject.GetScript<Item>() != null && !pc.holdItem)
{
inRange = false;
}
}
}

View File

@ -0,0 +1,360 @@
using SHADE;
using System;
using static Item;
public class PlayerController : Script
{
public enum RaccoonStates
{
IDILE,
WALKING,
RUNNING,
JUMP,
FALLING,
CAUGHT,
TOTAL
}
public RigidBody rb;
private Transform tranform;
private Camera cam;
private PickAndThrow pat;
//to be remove
public float drag = 2.0f;
public bool holdItem { get; set; }
[SerializeField]
[Tooltip("The current state fo the raccoon")]
public RaccoonStates currentState = RaccoonStates.IDILE;
//Movement variables============================================================
[SerializeField]
[Tooltip("Max vel for walking")]
public float maxMoveVel = 2.0f;
[SerializeField]
[Tooltip("how much force is apply for walking")]
public float moveForce = 50.0f;
[SerializeField]
[Tooltip("increase the moveForce and maxMoveVel by its amt")]
public float sprintMultiplier = 2.0f;
private float oldForce;
private float maxOldVel;
private bool sprintIncreaseOnce = false;
public float xAxisMove { get; set; }
public float zAxisMove { get; set; }
public Vector2 axisMove { get; set; }
public bool isMoveKeyPress { get; set; }
[SerializeField]
[Tooltip("curr not working")]
public float rotationFactorPerFrame = 1.0f;
//Jumping vars==================================================================
[SerializeField]
[Tooltip("max height of the jump")]
public float maxJumpHeight = 4.0f;
[SerializeField]
[Tooltip("max amt of time it will take for the jump")]
public float maxJumpTime = 0.75f;
[SerializeField]
[Tooltip("increase gravity when falling")]
public float fallMultipler = 2.0f;
private float initialJumpVel;
private bool isGrounded = true;
private float gravity = -9.8f;
private float groundGravity = -0.5f;
//ItemMultipler==================================================================
public float lightMultiper = 0.75f;
public float mediumMultiper = 0.5f;
public float heavyMultiper = 0.25f;
public PlayerController(GameObject gameObj) : base(gameObj) { }
protected override void awake()
{
//default setup
isMoveKeyPress = false;
holdItem = false;
//Jump setup
float timeToApex = maxJumpTime / 2;
gravity = (-2 * maxJumpHeight) / MathF.Pow(timeToApex, 2);
initialJumpVel = (2 * maxJumpHeight) / timeToApex;
//rigidbody check
rb = GetComponent<RigidBody>();
if (rb == null)
Debug.LogError("RigidBody is NULL!");
else
{
rb.IsGravityEnabled = false;
rb.FreezeRotationX = true;
rb.FreezeRotationY = true;
rb.FreezeRotationZ = true;
rb.Drag = drag;
rb.Interpolating = false;
}
//Transform check
tranform = GetComponent<Transform>();
if(tranform == null)
Debug.LogError("tranform is NULL!");
//PickAndThrow checl
pat = GetScript<PickAndThrow>();
if (pat == null)
Debug.LogError("PickAndThrow is NULL!");
//toRemove
tranform.LocalPosition = new Vector3(-3.0f, -2.0f, -5.0f);
tranform.LocalRotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);
}
protected override void update()
{
if (cam == null)
cam = GetComponentInChildren<Camera>();
//toRemove
if (Input.GetKey(Input.KeyCode.G))
{
tranform.LocalRotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);
tranform.LocalPosition = new Vector3(-3.0f, -2.0f, -5.0f);
}
GotCaught();
MoveKey();
//Debug.Log(currentState.ToString() + " x:" + rb.LinearVelocity.x.ToString() + " y:" + rb.LinearVelocity.y.ToString() + " z:" + rb.LinearVelocity.z.ToString());
}
protected override void fixedUpdate()
{
//Rotation();
Move();
Sprint();
Jump();
Gravity();
}
private void MoveKey()
{
/* if (Input.GetKey(Input.KeyCode.A))
xAxisMove = -1;
else if (Input.GetKey(Input.KeyCode.D))
xAxisMove = 1;
else
xAxisMove = 0;
if (Input.GetKey(Input.KeyCode.W))
zAxisMove = -1;
else if (Input.GetKey(Input.KeyCode.S))
zAxisMove = 1;
else
zAxisMove = 0;*/
xAxisMove = 0;
zAxisMove = 0;
axisMove = Vector2.Zero;
if (Input.GetKey(Input.KeyCode.W))
{
Vector3 camerAixs = cam.GetForward();
camerAixs.y = 0;
camerAixs.Normalise();
xAxisMove = camerAixs.x;
zAxisMove = camerAixs.z;
axisMove += new Vector2(camerAixs.x, camerAixs.z);
}
if (Input.GetKey(Input.KeyCode.S))
{
Vector3 camerAixs = cam.GetForward();
camerAixs.y = 0;
camerAixs.Normalise();
xAxisMove = -camerAixs.x;
zAxisMove = -camerAixs.z;
axisMove -= new Vector2(camerAixs.x, camerAixs.z);
}
if (Input.GetKey(Input.KeyCode.A))
{
Vector3 camerAixs = cam.GetRight();
camerAixs.y = 0;
camerAixs.Normalise();
xAxisMove = -camerAixs.x;
zAxisMove = -camerAixs.z;
axisMove -= new Vector2(camerAixs.x, camerAixs.z);
}
if (Input.GetKey(Input.KeyCode.D))
{
Vector3 camerAixs = cam.GetRight();
camerAixs.y = 0;
camerAixs.Normalise();
xAxisMove = camerAixs.x;
zAxisMove = camerAixs.z;
axisMove += new Vector2(camerAixs.x, camerAixs.z);
}
axisMove.Normalise();
isMoveKeyPress = xAxisMove != 0 || zAxisMove != 0;
if(isMoveKeyPress && currentState != RaccoonStates.RUNNING && isGrounded)
currentState = RaccoonStates.WALKING;
if (!isMoveKeyPress && isGrounded)
currentState = RaccoonStates.IDILE;
}
private void Move()
{
if (rb != null)
{
rb.AddForce(new Vector3(axisMove.x, 0.0f,axisMove.y) * moveForce);
if (isMoveKeyPress)
{
if (rb.LinearVelocity.x > maxMoveVel || rb.LinearVelocity.x < -maxMoveVel)
{
Vector3 v = rb.LinearVelocity;
v.x = System.Math.Clamp(v.x, -maxMoveVel, maxMoveVel);
rb.LinearVelocity = v;
}
if (rb.LinearVelocity.z > maxMoveVel || rb.LinearVelocity.z < -maxMoveVel)
{
Vector3 v = rb.LinearVelocity;
v.z = System.Math.Clamp(v.z, -maxMoveVel, maxMoveVel);
rb.LinearVelocity = v;
}
}
}
}
private void Sprint()
{
if (Input.GetKey(Input.KeyCode.LeftShift) && isMoveKeyPress && isGrounded)
{
currentState = RaccoonStates.RUNNING;
holdItem = false;
if (!sprintIncreaseOnce)
{
sprintIncreaseOnce = true;
oldForce = moveForce;
moveForce *= sprintMultiplier;
maxOldVel = maxMoveVel;
maxMoveVel *= sprintMultiplier;
}
}
if (Input.GetKeyUp(Input.KeyCode.LeftShift))
{
if(isMoveKeyPress)
currentState = RaccoonStates.WALKING;
sprintIncreaseOnce = false;
moveForce = oldForce;
maxMoveVel = maxOldVel;
}
}
//press and hold jump
private void Jump()
{
if (currentState == RaccoonStates.WALKING || currentState == RaccoonStates.RUNNING || currentState == RaccoonStates.IDILE)
{
if (Input.GetKeyDown(Input.KeyCode.Space) && isGrounded && rb != null)
{
currentState = RaccoonStates.JUMP;
Vector3 v = rb.LinearVelocity;
v.y = initialJumpVel * 0.5f;
if (pat != null && pat.item.GetScript<Item>() != null && holdItem)
{
Item item = pat.item.GetScript<Item>();
if (item.currCategory == ItemCategory.LIGHT)
v.y *= lightMultiper;
if (item.currCategory == ItemCategory.MEDIUM)
v.y *= mediumMultiper;
if (item.currCategory == ItemCategory.HEAVY)
v.y *= heavyMultiper;
}
rb.LinearVelocity = v;
}
}
if(rb != null && !isGrounded && (rb.LinearVelocity.y < 0.0f || Input.GetKeyUp(Input.KeyCode.Space)))
currentState = RaccoonStates.FALLING;
}
private void Rotation()
{
Vector3 poitionToLookAt;
poitionToLookAt.x = xAxisMove;
poitionToLookAt.y = 0.0f;
poitionToLookAt.z = zAxisMove;
if (tranform != null)
{
Quaternion currentRotation = tranform.LocalRotation;
if (currentState == RaccoonStates.WALKING || currentState == RaccoonStates.RUNNING)
{
Quaternion targetRotation = Quaternion.LookRotation(poitionToLookAt, new Vector3(0.0f, 1.0f, 0.0f));
tranform.LocalRotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactorPerFrame * (float)Time.DeltaTime);
}
}
}
private void Gravity()
{
if (rb != null)
{
//check player vel.y if its close to zero its on the ground
if (SHADE.Math.CompareFloat(rb.LinearVelocity.y, 0.0f))
isGrounded = true;
else
isGrounded = false;
Vector3 v = rb.LinearVelocity;
if (isGrounded)
v.y = groundGravity;
else if (currentState == RaccoonStates.FALLING)
{
float prevYVel = v.y;
float newYVel = v.y + (gravity * fallMultipler * (float)Time.DeltaTime);
float nextYVel = (prevYVel + newYVel) * 0.5f;
v.y = nextYVel;
}
else
{
float prevYVel = v.y;
float newYVel = v.y + (gravity * (float)Time.DeltaTime);
float nextYVel = (prevYVel + newYVel) * 0.5f;
v.y = nextYVel;
}
rb.LinearVelocity = v;
}
}
private void GotCaught()
{
if (currentState == RaccoonStates.CAUGHT && tranform != null)
{
currentState = RaccoonStates.IDILE;
tranform.LocalPosition = new Vector3(-3.0f, -2.0f, -5.0f);
}
}
protected override void onCollisionEnter(CollisionInfo info)
{
}
}

View File

@ -11,7 +11,7 @@ namespace SHADE_Scripting
public class ThirdPersonCamera: Script public class ThirdPersonCamera: Script
{ {
public float armLength = 4.0f; public float armLength = 2.0f;
public float turnSpeedPitch = 0.3f; public float turnSpeedPitch = 0.3f;
public float turnSpeedYaw = 0.5f; public float turnSpeedYaw = 0.5f;
public float pitchClamp = 45.0f; public float pitchClamp = 45.0f;
@ -19,10 +19,13 @@ namespace SHADE_Scripting
protected override void awake() protected override void awake()
{ {
AddComponent<Transform>();
if(!GetComponent<Camera>()) if(!GetComponent<Camera>())
{ {
AddComponent<Camera>(); AddComponent<Camera>();
} }
GetComponent<Camera>().SetMainCamera();
if (!GetComponent<CameraArm>()) if (!GetComponent<CameraArm>())
{ {
AddComponent<CameraArm>(); AddComponent<CameraArm>();
@ -31,25 +34,28 @@ namespace SHADE_Scripting
} }
protected override void update() protected override void update()
{
if (Input.GetMouseButton(Input.MouseCode.RightButton))
{ {
CameraArm arm = GetComponent<CameraArm>(); CameraArm arm = GetComponent<CameraArm>();
if(arm) if (arm)
{ {
Vector2 vel = Input.GetMouseVelocity(); Vector2 vel = Input.GetMouseVelocity();
arm.Pitch -= vel.y * turnSpeedPitch * Time.DeltaTimeF; arm.Pitch -= vel.y * turnSpeedPitch * Time.DeltaTimeF;
arm.Yaw += vel.x * turnSpeedYaw * Time.DeltaTimeF; arm.Yaw += vel.x * turnSpeedYaw * Time.DeltaTimeF;
if(arm.Pitch > pitchClamp) if (arm.Pitch > pitchClamp)
{ {
arm.Pitch = pitchClamp; arm.Pitch = pitchClamp;
} }
else if(arm.Pitch < -pitchClamp) else if (arm.Pitch < 0)
{ {
arm.Pitch = -pitchClamp; arm.Pitch = 0;
} }
} }
} }
}
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,4 +30,5 @@ workspace "SHADE"
--include "Dependencies/tracy" --include "Dependencies/tracy"
include "Dependencies/yamlcpp" include "Dependencies/yamlcpp"
include "Dependencies/reactphysics3d" include "Dependencies/reactphysics3d"
include "Dependencies/ModelCompiler"
group "" group ""