Added UI functionality to the Graphics System #232

Merged
Xenosas1337 merged 40 commits from UI_Integration into main 2022-11-20 15:43:34 +08:00
100 changed files with 8489 additions and 15803 deletions
Showing only changes of commit 1eb6bc5ef2 - Show all commits

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]
Pos=0,1060
Pos=0,1007
Size=1920,20
Collapsed=0
[Window][SHEditorMenuBar]
Pos=0,48
Size=1920,1012
Size=1920,959
Collapsed=0
[Window][Hierarchy Panel]
Pos=0,197
Size=308,863
Pos=0,189
Size=308,818
Collapsed=0
DockId=0x00000004,0
@ -21,13 +21,13 @@ Collapsed=0
[Window][Inspector]
Pos=1528,48
Size=392,1012
Size=392,959
Collapsed=0
DockId=0x00000006,0
[Window][Profiler]
Pos=0,48
Size=308,147
Size=308,139
Collapsed=0
DockId=0x00000003,0
@ -76,7 +76,7 @@ DockId=0x0000000B,0
[Window][ Viewport]
Pos=310,48
Size=1216,715
Size=1216,662
Collapsed=0
DockId=0x0000000B,0
@ -93,13 +93,19 @@ Collapsed=0
DockId=0x0000000A,0
[Window][ Asset Browser]
Pos=310,765
Pos=310,712
Size=1216,295
Collapsed=0
DockId=0x0000000C,0
[Window][Material Inspector]
Pos=1528,48
Size=392,959
Collapsed=0
DockId=0x00000006,1
[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=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y 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=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
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

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

@ -0,0 +1,259 @@
- 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: 24.7399445, y: 0.25, z: 8.75}
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: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts:
- Type: PlayerController
drag: 2
currentState: 0
maxMoveVel: 2
moveForce: 50
sprintMultiplier: 2
rotationFactorPerFrame: 1
maxJumpHeight: 4
maxJumpTime: 0.75
fallMultipler: 2
lightMultiper: 0.75
mediumMultiper: 0.5
heavyMultiper: 0.25
- Type: PickAndThrow
throwForce: [200, 300, 200]
item: 5
- 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:
- Type: SHADE_Scripting.ThirdPersonCamera
armLength: 2
turnSpeedPitch: 0.300000012
turnSpeedYaw: 0.5
pitchClamp: 45
- 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: 123745521
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: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
- Is Trigger: true
Type: Box
Half Extents: {x: 2, y: 2, z: 2}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts:
- Type: Item
currCategory: 0
- 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: 1, y: 1, z: 1}
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.5, y: 0.5, z: 0.5}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts:
- Type: AIPrototype
movementForceMultiplier: 100
patrolSpeed: 0.400000006
chaseSpeed: 0.800000012
distanceToCapture: 1.20000005
distanceToStartChase: 2
distanceToEndChase: 2.5
- EID: 7
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: -16.8647861, z: -14.039052}
Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 28.1434975, y: 28.1434975, z: 28.1434975}
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;
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;
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 "B - VMA"
echo "C - msdf"
echo "D - assimp"
echo "D - ModelCompiler"
echo "E - spdlog"
echo "F - reactphysics3d"
echo "G - imgui"
@ -29,7 +29,7 @@ set _e=%ERRORLEVEL%
if %_e%==1 goto VMA
if %_e%==2 goto VMA
if %_e%==3 goto MSDF
if %_e%==4 goto assimp
if %_e%==4 goto ModelCompiler
if %_e%==5 goto spdlog
if %_e%==6 goto reactphysics3d
if %_e%==7 goto imgui
@ -53,12 +53,13 @@ if %_e%==2 (goto :done) else (goto :MSDF)
echo -----------------------MSDF----------------------------
rmdir "Dependencies/msdf" /S /Q
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
echo -----------------------assimp----------------------------
rmdir "Dependencies/assimp" /S /Q
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/assimp"
:ModelCompiler
echo -----------------------ModelCompiler----------------------------
rmdir "Dependencies/ModelCompiler" /S /Q
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)
@REM :ktx

View File

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

View File

@ -41,6 +41,8 @@
#include "Assets/SHAssetManager.h"
#include "Scenes/SBMainScene.h"
#include "Serialization/Configurations/SHConfigurationManager.h"
#include "Tools/SHLogger.h"
#include "Tools/SHDebugDraw.h"
@ -60,8 +62,9 @@ namespace Sandbox
{
// Set working directory
SHFileUtilities::SetWorkDirToExecDir();
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
WindowData wndData{};
auto& appConfig = SHConfigurationManager::LoadApplicationConfig(&wndData);
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
// Create Systems
SHSystemManager::CreateSystem<SHGraphicsSystem>();
@ -80,7 +83,11 @@ namespace Sandbox
SDL_Init(SDL_INIT_VIDEO);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
SHSystemManager::CreateSystem<SHEditor>();
SHSystemManager::GetSystem<SHEditor>()->SetSDLWindow(sdlWindow);
if(auto editor = SHSystemManager::GetSystem<SHEditor>())
{
editor->SetSDLWindow(sdlWindow);
editor->SetSHWindow(&window);
}
#endif
// Create Routines
@ -128,7 +135,7 @@ namespace Sandbox
SHSystemManager::Init();
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
SHSceneManager::InitSceneManager<SBMainScene>(appConfig.startingSceneID);
SHFrameRateController::UpdateFRC();
@ -154,7 +161,7 @@ namespace Sandbox
editor->PollPicking();
static bool drawColliders = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::SPACE))
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
{
drawColliders = !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)
{
case AssetType::MESH:
if (asset.name == "Cube.012")
if (asset.name == "Raccoon")
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
break;
case AssetType::TEXTURE:
@ -65,58 +65,20 @@ namespace Sandbox
SHResourceManager::FinaliseChanges();
// Create Materials
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();
auto customMat = graphicsSystem->AddMaterialInstanceCopy(matInst);
customMat->SetProperty("data.color", SHVec4(0.0f, 1.0f, 1.0f, 1.0f));
customMat->SetProperty("data.textureIndex", 0);
customMat->SetProperty("data.alpha", 0.1f);
auto baseRaccoonMat = graphicsSystem->AddOrGetBaseMaterialInstance();
auto baseRaccoonMatInstant = graphicsSystem->AddMaterialInstanceCopy(baseRaccoonMat);
baseRaccoonMatInstant->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
baseRaccoonMatInstant->SetProperty("data.textureIndex", 0);
baseRaccoonMatInstant->SetProperty("data.alpha", 0.1f);
// Create Stress Test Objects
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One;
constexpr int NUM_ROWS = 3;
constexpr int NUM_COLS = 1;
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 };
auto baseFloorMatInstant = graphicsSystem->AddMaterialInstanceCopy(baseRaccoonMat);
baseFloorMatInstant->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
baseFloorMatInstant->SetProperty("data.textureIndex", 0);
baseFloorMatInstant->SetProperty("data.alpha", 0.1f);
for (int y = 0; y < NUM_ROWS; ++y)
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);
auto dummy = SHEntityManager::CreateEntity<>();
//renderable.Mesh = handles.front();
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 floor = SHEntityManager::CreateEntity<SHTransformComponent,SHRenderable, SHRigidBodyComponent, SHColliderComponent>();
auto& floorRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(floor);
auto& floorTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(floor);
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
@ -125,7 +87,7 @@ namespace Sandbox
floorRenderable.SetMesh(CUBE_MESH);
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 });
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
@ -138,17 +100,97 @@ namespace Sandbox
//testObjRenderable.Mesh = CUBE_MESH;
//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>());
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& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
renderableShowcase.SetMesh(handles.front());
renderableShowcase.SetMaterial(customMat);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
renderableShowcase.SetMaterial(baseRaccoonMatInstant);
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.textureIndex", 0);

View File

@ -26,7 +26,6 @@ project "SHADE_Engine"
externalincludedirs
{
"%{IncludeDir.assimp}\\include",
"%{IncludeDir.imgui}",
"%{IncludeDir.imguizmo}",
"%{IncludeDir.imnodes}",
@ -52,8 +51,6 @@ project "SHADE_Engine"
{
"%{prj.location}/libs",
"%{IncludeDir.VULKAN}/Lib",
"%{IncludeDir.assimp}/lib/Debug",
"%{IncludeDir.assimp}/lib/Release",
"%{IncludeDir.RTTR}/lib",
"%{IncludeDir.SDL}/lib",
"%{IncludeDir.spdlog}/lib",
@ -119,7 +116,8 @@ project "SHADE_Engine"
filter "configurations:Debug"
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\\fmodstudioL.dll\" \"$(OutDir)\""
}
@ -127,7 +125,8 @@ project "SHADE_Engine"
filter "configurations:Release"
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\\fmodstudio.dll\" \"$(OutDir)\""
}
@ -135,32 +134,35 @@ project "SHADE_Engine"
filter "configurations:Publish"
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\\fmodstudio.dll\" \"$(OutDir)\""
}
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'
filter "configurations:Debug"
symbols "On"
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"}
filter "configurations:Release"
optimize "On"
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"}
filter "configurations:Publish"
optimize "On"
defines{"_RELEASE", "_PUBLISH"}
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
links{"librttr_core.lib", "spdlog.lib"}
excludes
{
-- "%{prj.location}/src/Editor/**.cpp",

View File

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

View File

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

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
* \date 30 September 2022
* \brief Library to load gltf mesh files and custom binary format
@ -10,14 +10,27 @@
* of DigiPen Institute of Technology is prohibited.
*****************************************************************************/
#pragma once
#include "Assets/Asset Types/SHMeshAsset.h"
#include "Assets/Asset Types/SHModelAsset.h"
#include "SHAssetLoader.h"
#include <fstream>
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;
void Write(SHAssetData const* data, AssetPath path) override;
};

View File

@ -21,6 +21,11 @@ namespace SHADE
AssetName name;
AssetID id;
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_BUILT_IN,
TEXTURE,
MESH,
MODEL,
SCENE,
PREFAB,
MATERIAL,
MESH,
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" };
#endif
// COMPILER PATHS
constexpr std::string_view MODEL_COMPILER_EXE{ "ModelCompiler.exe" };
// INTERNAL ASSET PATHS
constexpr std::string_view SCENE_FOLDER{ "/Scenes/" };
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 MATERIAL_EXTENSION {".shmat"};
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[] = {
AUDIO_EXTENSION,
@ -89,7 +93,7 @@ constexpr std::string_view EXTENSIONS[] = {
SHADER_BUILT_IN_EXTENSION,
MATERIAL_EXTENSION,
TEXTURE_EXTENSION,
MESH_EXTENSION,
MODEL_EXTENSION,
SCRIPT_EXTENSION,
SCENE_EXTENSION,
PREFAB_EXTENSION,

View File

@ -11,15 +11,17 @@
#include <random>
#include <chrono>
#include <ranges>
#include <cstdlib>
#include "SHAssetManager.h"
#include "SHAssetMetaHandler.h"
#include "Libraries/Loaders/SHMeshLoader.h"
#include "Libraries/Loaders/SHModelLoader.h"
#include "Libraries/Loaders/SHTextureLoader.h"
#include "Libraries/Loaders/SHShaderSourceLoader.h"
#include "Libraries/Loaders/SHTextBasedLoader.h"
#include "Libraries/Compilers/SHMeshCompiler.h"
//#include "Libraries/Compilers/SHMeshCompiler.h"
#include "Libraries/Compilers/SHTextureCompiler.h"
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
@ -157,16 +159,22 @@ namespace SHADE
{
case AssetType::PREFAB:
newPath += PREFAB_FOLDER;
newPath += name;
newPath += PREFAB_EXTENSION;
data = new SHPrefabAsset();
break;
case AssetType::SCENE:
newPath += SCENE_FOLDER;
newPath += name;
newPath += SCENE_EXTENSION;
data = new SHSceneAsset();
break;
case AssetType::MATERIAL:
newPath += MATERIAL_FOLDER;
newPath += name;
newPath += MATERIAL_EXTENSION;
data = new SHMaterialAsset();
break;
@ -180,7 +188,8 @@ namespace SHADE
name,
id,
type,
newPath
newPath,
false
};
assetCollection.insert({
@ -189,7 +198,8 @@ namespace SHADE
name,
id,
type,
newPath
newPath,
false
)
});
@ -328,25 +338,32 @@ namespace SHADE
return result;
}
AssetID SHAssetManager::CompileAsset(AssetPath const& path) noexcept
void SHAssetManager::CompileAsset(AssetPath const& path) noexcept
{
SHAsset newAsset
{
.name = path.stem().string()
};
if (!std::filesystem::exists(path))
{
SHLOG_ERROR("Path provided does not point to a file: {}", path.string());
return;
}
AssetPath newPath;
auto const ext{ path.extension().string() };
if (ext == GLSL_EXTENSION.data())
{
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN);
newAsset.type = AssetType::SHADER_BUILT_IN;
newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
}
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());
assetCollection.insert({ newAsset.id, newAsset });
SHAssetMetaHandler::WriteMetaData(newAsset);
std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
modelPath += MODEL_EXTENSION;
newPath = modelPath;
GenerateNewMeta(newPath);
}
return newAsset.id;
}
FolderPointer SHAssetManager::GetRootFolder() noexcept
@ -399,46 +416,28 @@ namespace SHADE
for (auto const& path : paths)
{
SHAsset newAsset
{
.name = path.stem().string()
};
AssetPath newPath;
auto const ext{ path.extension().string() };
if (ext == GLSL_EXTENSION.data())
{
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN);
newAsset.type = AssetType::SHADER_BUILT_IN;
newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
}
else if (ext == DDS_EXTENSION.data())
{
newAsset.path = SHTextureCompiler::CompileTextureAsset(path).value();
newAsset.id = GenerateAssetID(AssetType::TEXTURE);
newAsset.type = AssetType::TEXTURE;
newPath = SHTextureCompiler::CompileTextureAsset(path).value();
}
else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
{
std::vector<SHMeshAsset*> meshes;
std::vector<SHAnimationAsset*> anims;
SHMeshCompiler::LoadFromFile(path, meshes, anims);
std::string command = MODEL_COMPILER_EXE.data();
command += " " + path.string();
std::system(command.c_str());
for (auto const& mesh : meshes)
{
SHAsset meshAsset{
.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;
std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
modelPath += MODEL_EXTENSION;
newPath = modelPath;
}
assetCollection.insert({ newAsset.id, newAsset });
SHAssetMetaHandler::WriteMetaData(newAsset);
GenerateNewMeta(newPath);
}
}
@ -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_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::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::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::MESH)] = nullptr;
}
/****************************************************************************
@ -464,9 +464,9 @@ namespace SHADE
****************************************************************************/
void SHAssetManager::Load() noexcept
{
//CompileAll();
BuildAssetCollection();
InitLoaders();
//CompileAll();
//LoadAllData();
}
@ -484,8 +484,12 @@ namespace SHADE
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)
{
SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string());
@ -498,8 +502,120 @@ namespace SHADE
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
{
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<SHAsset> GetAllRecordOfType(AssetType type) noexcept;
static AssetID CompileAsset(AssetPath const& path) noexcept;
static void CompileAsset(AssetPath const& path) noexcept;
static FolderPointer GetRootFolder() noexcept;
@ -95,7 +95,11 @@ namespace SHADE
static void InitLoaders() 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;
static bool IsRecognised(char const*) noexcept;

View File

@ -9,7 +9,6 @@
******************************************************************************/
#include "SHpch.h"
#include "SHAssetMetaHandler.h"
#include <fstream>
#include <sstream>
namespace SHADE
@ -21,11 +20,15 @@ namespace SHADE
* \brief Helper function to retrieve field value from meta data file
* for processing
****************************************************************************/
void GetFieldValue(std::ifstream& file, std::string& line) noexcept
bool GetFieldValue(std::ifstream& file, std::string& line) noexcept
{
line = "";
std::getline(file, line);
line = line.substr(line.find_last_of(':') + 2, line.length());
if (std::getline(file, line))
{
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 };
if (!metaFile.is_open())
{
// Error unable to open
SHLOG_ERROR("Unable to open meta file: {}", path.string());
return {};
}
std::string line;
@ -93,6 +97,43 @@ namespace SHADE
typeStream >> 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();
meta.path = path.parent_path().string() + "/" + path.stem().string();
@ -108,6 +149,12 @@ namespace SHADE
****************************************************************************/
void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept
{
if (meta.isSubAsset)
{
SHLOG_WARNING("Cannot write subasset meta: {}", meta.name);
return;
}
//TODO: Write into binary eventually
std::string path{ meta.path.string() };
path.append(META_EXTENSION);
@ -124,7 +171,23 @@ namespace SHADE
metaFile << "ID: " << meta.id << "\n";
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();
}
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 "SHAsset.h"
#include <fstream>
namespace SHADE
{
@ -45,6 +46,8 @@ namespace SHADE
* \brief Writes meta data into text file
****************************************************************************/
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 <imgui.h>
#include <imgui_internal.h>
#include <misc/cpp/imgui_stdlib.h>
#include "Assets/SHAssetManager.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/IconsFontAwesome6.h"
#include "Editor/SHEditor.h"
#include "Editor/DragDrop/SHDragDrop.hpp"
#include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h"
namespace SHADE
{
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;
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());
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.push_back(folder);
}
if (isOpen)
{
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
@ -79,13 +102,18 @@ namespace SHADE
}
for (auto const& file : files)
{
if(file.assetMeta == nullptr)
continue;
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;
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
vertLineEnd.y = midPoint;
}
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
if(assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder)
DrawAssetBeingCreated();
ImGui::TreePop();
}
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());
const bool isSelected = std::ranges::find(selectedAssets, file.assetMeta->id) != selectedAssets.end();
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf;
const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end();
ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf;
if (isSelected)
flags |= ImGuiTreeNodeFlags_Selected;
std::string icon{};
switch(file.assetMeta->type)
switch (asset->type)
{
case AssetType::INVALID: break;
case AssetType::SHADER: 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::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::PREFAB: icon = ICON_FA_BOX_OPEN; break;
case AssetType::MATERIAL: break;
case AssetType::MESH: icon = ICON_FA_CUBES; 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());
if(SHDragDrop::BeginSource())
if (SHDragDrop::BeginSource())
{
auto id = file.assetMeta->id;
ImGui::Text("Moving Asset: %s [%zu]", file.name.data(), file.assetMeta->id);
auto id = asset->id;
ImGui::Text("Moving Asset: %s [%zu]", asset->name.data(), asset->id);
SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id);
SHDragDrop::EndSource();
}
if(ImGui::IsItemClicked())
if (ImGui::IsItemClicked())
{
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;
}
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
{
public:
using AssetEntry = std::tuple<FolderPointer, AssetType, std::string>;
SHAssetBrowser();
void Init();
@ -20,12 +21,13 @@ namespace SHADE
void DrawMenuBar();
ImRect RecursivelyDrawTree(FolderPointer folder);
void DrawCurrentFolder();
ImRect DrawFile(SHFile const& file) noexcept;
ImRect DrawFile(SHAsset const* const asset) noexcept;
void DrawAssetBeingCreated() noexcept;
FolderPointer rootFolder, prevFolder, currentFolder;
std::optional<AssetEntry> assetBeingCreated;
std::vector<FolderPointer> selectedFolders;
std::vector<AssetID> selectedAssets;
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();
}
@ -195,7 +201,7 @@ namespace SHADE
if (SHDragDrop::BeginSource())
{
std::string moveLabel = "Moving EID: ";
static std::vector<EntityID> draggingEntities = editor->selectedEntities;
draggingEntities = editor->selectedEntities;
if (!isSelected)
{
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
{
ParentSelectedEntities(eid);
ParentSelectedEntities(eid, draggingEntities);
draggingEntities.clear();
SHDragDrop::EndTarget();
}
}
@ -255,7 +262,7 @@ namespace SHADE
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();
}
@ -323,14 +330,16 @@ namespace SHADE
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 editor = SHSystemManager::GetSystem<SHEditor>();
//auto const editor = SHSystemManager::GetSystem<SHEditor>();
SHEntityParentCommand::EntityParentData entityParentData;
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)
{
parentedEIDS.push_back(eid);

View File

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

View File

@ -244,9 +244,12 @@ namespace SHADE
SHCollider* collider = &component->GetCollider(i);
auto cursorPos = ImGui::GetCursorPos();
//collider->IsTrigger
if (collider->GetType() == SHCollider::Type::BOX)
{
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());
SHEditorWidgets::DragVec3
(
@ -257,6 +260,7 @@ namespace SHADE
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::CheckBox("Is Trigger", [collider]() {return collider->IsTrigger(); }, [collider](bool const& value) {collider->SetIsTrigger(value); }, "Is Trigger");
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
SHEditorWidgets::DragFloat
(
@ -372,6 +376,7 @@ namespace SHADE
{
DrawContextMenu(component);
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]()
{
@ -383,6 +388,19 @@ namespace SHADE
component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id));
SHResourceManager::FinaliseChanges();
}, 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
{

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 ||
//#==============================================================#
#include "Editor/SHEditorWidgets.hpp"
#include "Editor/SHEditor.h"
#include "SHEditorMenuBar.h"
#include "Editor/IconsMaterialDesign.h"
@ -17,7 +18,11 @@
#include <imgui_internal.h>
#include <rttr/type>
#include "Assets/SHAssetManager.h"
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Scene/SHSceneManager.h"
#include "Serialization/SHSerialization.h"
#include "Serialization/Configurations/SHConfigurationManager.h"
namespace SHADE
{
@ -75,13 +80,17 @@ namespace SHADE
{
if (ImGui::BeginMenu("File"))
{
if(ImGui::Selectable("New Scene"))
{
SHSystemManager::GetSystem<SHEditor>()->NewScene();
}
if(ImGui::Selectable("Save"))
{
SHSerialization::SerializeSceneToFile("../../Assets/Scenes/Test.SHADE");
SHSystemManager::GetSystem<SHEditor>()->SaveScene();
}
if(ImGui::Selectable("Load"))
{
SHSerialization::DeserializeSceneFromFile("../../Assets/Scenes/Test.SHADE");
//SHSystemManager::GetSystem<SHEditor>()->LoadScene()
}
ImGui::EndMenu();
}
@ -108,16 +117,22 @@ namespace SHADE
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->GenerateScriptsCsProjFile();
}
ImGui::BeginDisabled(SHSystemManager::GetSystem<SHEditor>()->editorState != SHEditor::State::STOP);
if (ImGui::Selectable("Build Scripts - Debug"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(true, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
}
if (ImGui::Selectable("Build Scripts - Release"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(false, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
}
ImGui::EndDisabled();
ImGui::EndMenu();
}
@ -155,6 +170,35 @@ namespace SHADE
}
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();
}
@ -175,13 +219,16 @@ namespace SHADE
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY);
if(ImGui::SmallButton(ICON_MD_PLAY_ARROW))
{
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
if(editor->SaveScene())
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::PLAY;
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::PLAY;
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::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
@ -206,6 +253,7 @@ namespace SHADE
editor->editorState = SHEditor::State::STOP;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
editor->LoadScene(SHSceneManager::GetCurrentSceneAssetID());
}
ImGui::EndDisabled();
ImGui::EndMenuBar();

View File

@ -19,7 +19,7 @@ namespace SHADE
//|| Public Member Functions ||
//#==============================================================#
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::SetFocusToWindow()
{
ImGui::SetWindowFocus(windowName.data());
}
}//namespace SHADE

View File

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

View File

@ -1,7 +1,8 @@
#pragma once
#include "MenuBar/SHEditorMenuBar.h" //Menu Bar
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
#include "Inspector/SHEditorInspector.h" //Inspector
#include "Profiling/SHEditorProfiler.h" //Profiler
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
#include "MenuBar/SHEditorMenuBar.h" //Menu Bar
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
#include "Inspector/SHEditorInspector.h" //Inspector
#include "Profiling/SHEditorProfiler.h" //Profiler
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
#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_vulkan.h>
#include "Assets/SHAssetManager.h"
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
#include "Scene/SHSceneManager.h"
#include "Serialization/SHSerialization.h"
#include "Tools/SHDebugDraw.h"
RTTR_REGISTRATION
@ -93,6 +97,8 @@ namespace SHADE
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
SHEditorWindowManager::CreateEditorWindow<SHMaterialInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
io = &ImGui::GetIO();
@ -146,6 +152,8 @@ namespace SHADE
}
}
RenderSceneNamePrompt();
RenderUnsavedChangesPrompt();
//PollPicking();
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
{
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()
{
SDL_Event event;

View File

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

View File

@ -422,12 +422,13 @@ namespace SHADE
ImGui::BeginGroup();
ImGui::PushID(label.data());
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(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), *payload, set)), false);
changed = true;
SHDragDrop::EndTarget();
}
}

View File

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

View File

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

View File

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

View File

@ -41,6 +41,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Resource/SHResourceManager.h"
#include "Graphics/SHVkUtil.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "../Meshes/SHPrimitiveGenerator.h"
namespace SHADE
{
@ -52,7 +53,11 @@ namespace SHADE
/* BACKEND BOILERPLATE */
/*-----------------------------------------------------------------------*/
// Set Up Instance
#ifdef _DEBUG
SHVkInstance::Init(true, true, true);
#else
SHVkInstance::Init(true, false, true);
#endif
// Get Physical Device and Construct Logical Device
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST);
@ -255,7 +260,6 @@ namespace SHADE
// Generate world render graph
worldRenderGraph->Generate();
/*-----------------------------------------------------------------------*/
/* BIND RENDER GRAPH TO RENDERER */
/*-----------------------------------------------------------------------*/
@ -265,9 +269,6 @@ namespace SHADE
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
// Create default materials
defaultMaterial = AddMaterial(defaultVertShader, defaultFragShader, gBufferSubpass);
// Create debug draw pipeline
debugDrawPipeline = createDebugDrawPipeline(debugDrawNode->GetRenderpass(), debugDrawSubpass);
debugDrawDepthPipeline = createDebugDrawPipeline(debugDrawNodeDepth->GetRenderpass(), debugDrawDepthSubpass);
@ -309,7 +310,29 @@ namespace SHADE
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
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
@ -352,8 +375,7 @@ namespace SHADE
InitBoilerplate();
InitMiddleEnd();
InitSubsystems();
InitBuiltInResources();
}
void SHGraphicsSystem::Exit(void)
@ -678,7 +700,7 @@ namespace SHADE
SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst)
{
return resourceManager.Create<SHMaterialInstance>(materialInst->GetBaseMaterial());
return resourceManager.Create<SHMaterialInstance>(materialInst->GetBaseMaterial());
}
void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance)
@ -691,26 +713,38 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
SHADE::Handle<SHADE::SHMesh> SHGraphicsSystem::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices)
{
return meshLibrary.AddMesh(vertexCount, positions, texCoords, tangents, normals, indexCount, indices);
return meshLibrary.AddMesh(vertexCount, positions, texCoords, tangents, normals, indexCount, indices);
}
void SHGraphicsSystem::RemoveMesh(Handle<SHMesh> mesh)
{
meshLibrary.RemoveMesh(mesh);
meshLibrary.RemoveMesh(mesh);
}
void SHGraphicsSystem::BuildMeshBuffers()
{
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
device->WaitIdle();
transferCmdBuffer->BeginRecording();
meshLibrary.BuildBuffers(device, transferCmdBuffer);
transferCmdBuffer->EndRecording();
graphicsQueue->SubmitCommandBuffer({ transferCmdBuffer });
transferCmdBuffer->BeginRecording();
meshLibrary.BuildBuffers(device, transferCmdBuffer);
transferCmdBuffer->EndRecording();
graphicsQueue->SubmitCommandBuffer({ transferCmdBuffer });
device->WaitIdle();
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 */
/*---------------------------------------------------------------------------------*/
@ -743,6 +777,11 @@ namespace SHADE
graphicsTexCmdBuffer.Free(); graphicsTexCmdBuffer = {};
}
Handle<SHTexture> SHGraphicsSystem::GetTextureHandle(SHTexture::Index textureId) const
{
return texLibrary.GetTextureHandle(textureId);
}
#pragma endregion ADD_REMOVE
#pragma region ROUTINES
@ -755,6 +794,7 @@ namespace SHADE
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{
SHResourceManager::FinaliseChanges();
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
}
@ -780,7 +820,6 @@ namespace SHADE
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
SHResourceManager::FinaliseChanges();
}
/*-----------------------------------------------------------------------------------*/
@ -792,17 +831,12 @@ namespace SHADE
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
{
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
for (auto& renderable : renderables)
{
if (!renderable.HasChanged())
continue;
if (!renderable.GetMesh())
{
SHLOG_CRITICAL("NULL Mesh provided!");
}
// Remove from the SuperBatch it is previously in (prevMat if mat has changed)
Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial();
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 and a mesh to render
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
if (newMatInstance)
if (newMatInstance && renderable.GetMesh())
{
Handle<SHSuperBatch> newSuperBatch = newMatInstance->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
newSuperBatch->Add(&renderable);

View File

@ -58,6 +58,19 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* 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
@ -72,6 +85,7 @@ namespace SHADE
void InitSceneRenderGraph (void) noexcept;
void InitMiddleEnd (void) noexcept;
void InitSubsystems (void) noexcept;
void InitBuiltInResources (void);
#ifdef SHEDITOR
void InitEditorRenderGraph (void) noexcept;
@ -81,25 +95,25 @@ namespace SHADE
class SH_API BeginRoutine final : public SHSystemRoutine
{
public:
BeginRoutine();
BeginRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API RenderRoutine final : public SHSystemRoutine
{
public:
RenderRoutine();
RenderRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API EndRoutine final : public SHSystemRoutine
{
public:
EndRoutine();
EndRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine
{
public:
BatcherDispatcherRoutine();
BatcherDispatcherRoutine();
virtual void Execute(double dt) noexcept override final;
};
@ -152,34 +166,34 @@ namespace SHADE
/*******************************************************************************/
/*!
\brief
Adds a mesh to the Mesh Library. But this does not mean that the meshes have
been added yet. A call to "BuildBuffers()" is required to transfer all
meshes into the GPU.
\brief
Adds a mesh to the Mesh Library. But this does not mean that the meshes have
been added yet. A call to "BuildBuffers()" is required to transfer all
meshes into the GPU.
\param vertexCount
Number of vertices in this Mesh.
\param positions
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
positions.
\param texCoords
Pointer to the first in a contiguous array of SHMathVec2s that define vertex
texture coordinates.
\param tangents
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
tangents.
\param normals
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
normals.
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
positions.
\param texCoords
Pointer to the first in a contiguous array of SHMathVec2s that define vertex
texture coordinates.
\param tangents
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
tangents.
\param normals
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
normals.
\param indexCount
Number of indices in this mesh.
\param indices
Pointer to the first in a contiguous array of uint32_ts that define mesh
indices.
Pointer to the first in a contiguous array of uint32_ts that define mesh
indices.
\return
Handle to the created Mesh. This is not valid to be used until a call to
BuildBuffers().
\return
Handle to the created Mesh. This is not valid to be used until a call to
BuildBuffers().
*/
/*******************************************************************************/
@ -188,9 +202,9 @@ namespace SHADE
/*!
\brief
Removes a mesh from the MeshLibrary. But this does not mean that the meshes
have been removed yet. A call to "BuildBuffers()" is required to finalise all
changes.
Removes a mesh from the MeshLibrary. But this does not mean that the meshes
have been removed yet. A call to "BuildBuffers()" is required to finalise all
changes.
\param mesh
Handle to the mesh to remove.
@ -207,6 +221,21 @@ namespace SHADE
*/
/***************************************************************************/
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 */
@ -263,6 +292,33 @@ namespace SHADE
*/
/***************************************************************************/
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 HandleResize(void) noexcept;
@ -363,6 +419,13 @@ namespace SHADE
Handle<SHVkPipeline> debugDrawPipeline;
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;
// 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>
// Project Includes
#include "Assets/SHAssetMacros.h"
#include <yaml-cpp/yaml.h>
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declaration */
/*-----------------------------------------------------------------------------------*/
class SHMaterial;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/
/*!
\brief
@ -32,5 +41,11 @@ namespace SHADE
AssetID fragShader;
std::string subpassName;
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

@ -288,7 +288,7 @@ namespace SHADE
{
return meshLibrary.AddMesh
(
static_cast<uint32_t>(meshData.VertexPositions.size()),
static_cast<uint32_t>(meshData.VertexPositions.size()),
meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(),
@ -302,12 +302,12 @@ namespace SHADE
{
return gfxSystem.AddMesh
(
static_cast<uint32_t>(meshData.VertexPositions.size()),
static_cast<uint32_t>(meshData.VertexPositions.size()),
meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(),
meshData.VertexNormals.data(),
static_cast<uint32_t>(meshData.Indices.size()),
static_cast<uint32_t>(meshData.Indices.size()),
meshData.Indices.data()
);
}

View File

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

View File

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

View File

@ -129,6 +129,21 @@ namespace SHADE
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
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:
/*-----------------------------------------------------------------------------*/

View File

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

View File

@ -55,16 +55,6 @@ namespace SHADE
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
{
bytesRequired = bytes;
@ -75,16 +65,4 @@ namespace SHADE
{
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;
//! bytes required by the block (includes padding). This variable is required
uint32_t bytesRequired;
uint32_t bytesRequired = 0;
public:
void AddVariable (std::string name, Variable&& newVariable) noexcept;
@ -43,13 +43,6 @@ namespace SHADE
const std::string& GetVariableName(uint32_t index) 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 */
/*-----------------------------------------------------------------------*/

View File

@ -4,7 +4,6 @@
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Input/SHInputManager.h"
namespace SHADE
{
SHWindow::SHWindow()
@ -151,11 +150,11 @@ namespace SHADE
SetWindowText(wndHWND, LPCWSTR(wndData.title.c_str()));
}
SHWindow::SHVec2 SHWindow::GetPosition() const
SHWindow::WindowSize SHWindow::GetPosition() const
{
RECT 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)
@ -165,18 +164,18 @@ namespace SHADE
wndData.y = y;
}
SHWindow::SHVec2 SHWindow::GetWindowSize() const
SHWindow::WindowSize SHWindow::GetWindowSize() const
{
RECT 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 screenHeight = GetSystemMetrics(SM_CYSCREEN);
return SHVec2(screenWidth, screenHeight);
return WindowSize(screenWidth, screenHeight);
}
void SHWindow::SetMouseVisible(bool show)
@ -260,7 +259,7 @@ namespace SHADE
return wndHWND;
}
const WindowData SHWindow::GetWindowData() const
const WindowData SHWindow::GetWindowData() const noexcept
{
return wndData;
}
@ -287,6 +286,15 @@ namespace SHADE
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)
{
auto window = windowMap.GetWindow(hwnd);

View File

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

View File

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

View File

@ -13,17 +13,20 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes
#include <unordered_map>
namespace SHADE { class SHMaterial; }
// Project Includes
#include "SH_API.h"
#include "SHResourceLibrary.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/SHShaderAsset.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Assets/Asset Types/SHMaterialAsset.h"
namespace SHADE
@ -33,12 +36,12 @@ namespace SHADE
/// </summary>
template<typename T = 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<SHVkShaderModule> { using AssetType = SHShaderAsset; };
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialAsset; };
/// <summary>
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
/// <summary>
/// Static class responsible for loading and caching runtime resources from their
/// serialised Asset IDs.
/// </summary>
@ -61,6 +64,8 @@ namespace SHADE
/// <returns>Handle to a loaded runtime asset.</returns>
template<typename ResourceType>
static Handle<ResourceType> LoadOrGet(AssetID assetId);
template<>
static inline Handle<SHMaterial> LoadOrGet<SHMaterial>(AssetID assetId);
/// <summary>
/// Unloads an existing loaded asset. Attempting to unload an invalid Handle will
/// 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/Devices/SHVkLogicalDevice.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Serialization/SHYAMLConverters.h"
namespace SHADE
{
@ -34,7 +35,12 @@ namespace SHADE
Handle<ResourceType> SHResourceManager::LoadOrGet(AssetID assetId)
{
// 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.");
}
@ -60,8 +66,35 @@ namespace SHADE
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>
void SHResourceManager::Unload(Handle<ResourceType> assetId)
void SHResourceManager::Unload(Handle<ResourceType> asset)
{
// Check if it is an unsupported type
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 */
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
Handle handle = typedHandleMap.get()[assetId];
Handle<ResourceType> typedHandle = static_cast<Handle<ResourceType>>(handle);
Handle handle = typedHandleMap.get()[asset];
auto typedHandle = static_cast<Handle<ResourceType>>(handle);
typedHandle.Free();
typedAssetIdMap.get().erase(handle);
typedHandleMap.get().erase(assetId);
typedHandleMap.get().erase(asset);
}
else
{
@ -143,13 +180,13 @@ namespace SHADE
return gfxSystem->AddMesh
(
assetData.vertexPosition.size(),
assetData.vertexPosition.data(),
assetData.texCoords.data(),
assetData.vertexTangent.data(),
assetData.vertexNormal.data(),
assetData.indices.size(),
assetData.indices.data()
assetData.VertexPositions.size(),
assetData.VertexPositions.data(),
assetData.VertexTexCoords.data(),
assetData.VertexTangents.data(),
assetData.VertexNormals.data(),
assetData.Indices.size(),
assetData.Indices.data()
);
}
// Textures
@ -181,15 +218,27 @@ namespace SHADE
shader->Reflect();
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
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
auto vertexShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(matSpec.vertexShader);
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(matSpec.fragShader);
auto vertexShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(assetData.vertexShader);
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(assetData.fragShader);
// Ensure that both shaders are present
if (!(vertexShader && fragShader))
@ -205,7 +254,7 @@ namespace SHADE
SHLOG_ERROR("[SHResourceManager] Failed to load material as RenderPass could not be found.");
return {};
}
auto subPass = renderPass->GetSubpass(matSpec.subpassName);
auto subPass = renderPass->GetSubpass(assetData.subpassName);
if (!subPass)
{
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)
{
const std::string& PROP_NAME = pipelineProperties->GetVariableName(i);
const auto& PROP_NODE = matSpec.properties;
if (PROP_NODE)
const YAML::Node& PROP_NODE = assetData.properties[PROP_NAME.data()];
if (PROP_NODE.IsDefined())
{
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
@ -231,7 +280,21 @@ namespace SHADE
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<float>());
break;
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;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
matHandle->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec2>());

View File

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

View File

@ -29,7 +29,7 @@ namespace SHADE
std::string SHSceneManager::newSceneName{};
uint32_t SHSceneManager::currentSceneID = UINT32_MAX;
uint32_t SHSceneManager::nextSceneID = UINT32_MAX;
AssetID SHSceneManager::currentSceneAssetID{};
SHScene* SHSceneManager::currentScene = 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;
newSceneName = sceneName;
//cleanReload = true;
cleanReload = false;
//newSceneName = sceneName;
}
else
cleanReload = false;
currentScene->sceneAssetID = assetID;
nextSceneID = currentSceneID;
sceneChanged = true;
}
@ -151,4 +153,20 @@ namespace SHADE
{
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
#include "SH_API.h"
#include "ECS_Base/General/SHFamily.h"
#include "Assets/SHAssetMacros.h"
namespace SHADE
{
@ -47,6 +48,9 @@ namespace SHADE
//pointer to the current scene
static SHScene* currentScene;
//Scene AssetID of the current scene
static AssetID currentSceneAssetID;
//Used in reloading scene.
static std::string newSceneName;
@ -80,10 +84,10 @@ namespace SHADE
* None.
***************************************************************************/
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;
newScene = [sceneName]() { currentScene = new T(); currentScene->sceneName = sceneName; };
newScene = [sceneAssetID]() { currentScene = new T(); currentScene->sceneAssetID = sceneAssetID; };
//nextSceneID = SHFamilyID<SHScene>::GetID<T>();
nextSceneID = 0;
@ -99,7 +103,7 @@ namespace SHADE
* None.
***************************************************************************/
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)
if (currentSceneID == SHFamilyID<SHScene>::GetID<T>())
@ -107,7 +111,7 @@ namespace SHADE
return;
}
//prevSceneCreate = newScene;
newScene = [sceneName]() { currentScene = new T(); currentScene->sceneName; };
newScene = [sceneAssetID]() { currentScene = new T(); currentScene->sceneAssetID = sceneAssetID; };
nextSceneID = SHFamilyID<SHScene>::GetID<T>();
sceneChanged = true;
}
@ -137,11 +141,11 @@ namespace SHADE
* Restarts current scene. Only Scene::Init() and Scene::Free()
* Scene::Load() and Scene::Unload() will not be called.
* Edit: allows for RestartScene to restart the scene with a different
* scene name.
* If a sceneName is different from the current one, Load and Unload will
* scene asset ID.
* If a scene asset id is different from the current one, Load and Unload will
* run.
***************************************************************************/
static void RestartScene(std::string const& sceneName ) noexcept;
static void RestartScene(AssetID const& assetID ) noexcept;
/*!*************************************************************************
* \brief
@ -164,7 +168,10 @@ namespace SHADE
static void Exit() 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 <yaml-cpp/yaml.h>
#include "SHSerializationHelper.hpp"
#include "SHSerialization.h"
#include "SHSerializationHelper.hpp"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Scene/SHSceneManager.h"
@ -10,6 +10,7 @@
#include "Assets/SHAssetManager.h"
#include <fstream>
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Camera/SHCameraComponent.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Math/Transform/SHTransformComponent.h"
@ -17,19 +18,23 @@
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
#include "Scripting/SHScriptEngine.h"
#include "Tools/FileIO/SHFileIO.h"
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;
SerializeSceneToEmitter(out);
std::ofstream file(path.c_str());
if (file.good())
{
file << out.c_str();
file.close();
}
assetData->data = out.c_str();
return SHAssetManager::SaveAsset(sceneAssetID);
}
std::string SHSerialization::SerializeSceneToString()
@ -91,31 +96,16 @@ namespace SHADE
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
std::ifstream iFile;
iFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
std::string fileContent = "";
try
auto assetData = SHAssetManager::GetData<SHSceneAsset>(sceneAssetID);
if(!assetData)
{
// Open file
// Read file's buffer contents into streams
iFile.open(path);
std::stringstream fileStream;
fileStream << iFile.rdbuf();
fileContent = fileStream.str();
// Close file handler
iFile.close();
SHLOG_ERROR("Attempted to load scene that doesn't exist {}", sceneAssetID)
SHSceneManager::SetCurrentSceneAssetID(0);
return NewSceneName.data();
}
catch (std::ifstream::failure e)
{
SHLOG_ERROR("Could not read file");
}
YAML::Node entities = YAML::Load(fileContent);
YAML::Node entities = YAML::Load(assetData->data);
std::vector<EntityID> createdEntities{};
//Create Entities
@ -126,14 +116,23 @@ namespace SHADE
if (createdEntities.empty())
{
SHLOG_ERROR("Failed to create entities from deserializaiton")
return;
return NewSceneName.data();
}
//Initialize Entity
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)
{
InitializeEntity(*it, *entityVecIt++);
}
return assetData->name;
}
void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out)
@ -264,6 +263,33 @@ namespace SHADE
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)
{
auto const componentsNode = entityNode[ComponentsNode];

View File

@ -4,7 +4,10 @@
#include <string>
#include <filesystem>
#include <ECS_Base/Components/SHComponent.h>
#include "ECS_Base/SHECSMacros.h"
#include <Assets/SHAssetMacros.h>
#include <unordered_map>
namespace YAML
{
@ -25,12 +28,11 @@ namespace SHADE
struct SH_API SHSerialization
{
//TODO: change paths to resource ID
static void SerializeSceneToFile(std::filesystem::path const& path);
static bool SerializeSceneToFile(AssetID const& sceneAssetID);
static std::string SerializeSceneToString();
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);
@ -42,7 +44,11 @@ namespace SHADE
static EntityID DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept;
static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
static void LoadAssetsFromAssetQueue(std::unordered_map<AssetID, AssetType>& assetQueue);
private:
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
#include "SHYAMLConverters.h"
#include <yaml-cpp/yaml.h>
#include "ECS_Base/Components/SHComponent.h"
#include <rttr/registration>
#include <unordered_map>
#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 "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
{
using AssetQueue = std::unordered_map<AssetID, AssetType>;
struct SHSerializationHelper
{
@ -460,6 +88,8 @@ namespace SHADE
node = YAML::Null;
}
}
else if (varType == rttr::type::get<std::string>())
node = var.to_string();
else
{
auto properties = var.get_type().get_properties();
@ -495,63 +125,65 @@ namespace SHADE
return node;
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeProperty(ComponentType* component, rttr::property const& prop, YAML::Node const& propertyNode)
template <typename Type>
static void InitializeProperty(Type* object, rttr::property const& prop, YAML::Node const& propertyNode)
{
auto propType = prop.get_type();
if (propType == rttr::type::get<SHVec4>())
{
SHVec4 vec = propertyNode.as<SHVec4>();
prop.set_value(component, vec);
prop.set_value(object, vec);
}
else if (propType == rttr::type::get<SHVec3>())
{
SHVec3 vec = propertyNode.as<SHVec3>();
prop.set_value(component, vec);
prop.set_value(object, vec);
}
else if (propType == rttr::type::get<SHVec2>())
{
SHVec2 vec = propertyNode.as<SHVec2>();
prop.set_value(component, vec);
prop.set_value(object, vec);
}
else if (propType.is_arithmetic())
{
bool ok = false;
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>())
prop.set_value(component, propertyNode.as<int8_t>());
prop.set_value(object, propertyNode.as<int8_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>())
prop.set_value(component, propertyNode.as<int32_t>());
prop.set_value(object, propertyNode.as<int32_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>())
prop.set_value(component, propertyNode.as<uint8_t>());
prop.set_value(object, propertyNode.as<uint8_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>())
prop.set_value(component, propertyNode.as<uint32_t>());
prop.set_value(object, propertyNode.as<uint32_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>())
prop.set_value(component, propertyNode.as<float>());
prop.set_value(object, propertyNode.as<float>());
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())
{
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
{
auto properties = propType.get_properties();
for (auto const& property : properties)
{
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;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if(!componentNode.IsDefined())
if (!componentNode.IsDefined())
return;
auto properties = rttrType.get_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>
static void ConvertNodeToComponent(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;
YAML::convert<ComponentType>::decode(componentNode, *component);
YAML::convert<ComponentType>::decode(GetComponentNode<ComponentType>(componentsNode, eid), *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>() * 2.0f);
}
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.dotnet}\\include",
"%{IncludeDir.reactphysics3d}\\include",
"%{IncludeDir.VULKAN}\\include",
"%{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 LookAt(Vector3 targetPosition);
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 { get; set; }
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 float armLength = 4.0f;
public float armLength = 2.0f;
public float turnSpeedPitch = 0.3f;
public float turnSpeedYaw = 0.5f;
public float pitchClamp = 45.0f;
@ -19,10 +19,13 @@ namespace SHADE_Scripting
protected override void awake()
{
AddComponent<Transform>();
if(!GetComponent<Camera>())
{
AddComponent<Camera>();
}
GetComponent<Camera>().SetMainCamera();
if (!GetComponent<CameraArm>())
{
AddComponent<CameraArm>();
@ -30,26 +33,29 @@ namespace SHADE_Scripting
GetComponent<CameraArm>().ArmLength = armLength;
}
protected override void update()
{
CameraArm arm = GetComponent<CameraArm>();
if(arm)
protected override void update()
{
if (Input.GetMouseButton(Input.MouseCode.RightButton))
{
CameraArm arm = GetComponent<CameraArm>();
if (arm)
{
Vector2 vel = Input.GetMouseVelocity();
arm.Pitch -= vel.y * turnSpeedPitch * Time.DeltaTimeF;
arm.Yaw += vel.x * turnSpeedYaw * Time.DeltaTimeF;
if (arm.Pitch > pitchClamp)
{
Vector2 vel = Input.GetMouseVelocity();
arm.Pitch -= vel.y * turnSpeedPitch * Time.DeltaTimeF;
arm.Yaw += vel.x * turnSpeedYaw * Time.DeltaTimeF;
if(arm.Pitch > pitchClamp)
{
arm.Pitch = pitchClamp;
}
else if(arm.Pitch < -pitchClamp)
{
arm.Pitch = -pitchClamp;
}
arm.Pitch = pitchClamp;
}
else if (arm.Pitch < 0)
{
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/yamlcpp"
include "Dependencies/reactphysics3d"
include "Dependencies/ModelCompiler"
group ""