Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fa75c116e | ||
|
|
2881b2c9d5 | ||
|
|
d79cf42a3d | ||
|
|
17af5348e9 | ||
|
|
dec8cbd059 | ||
|
|
f580776964 | ||
|
|
d2d9981efe | ||
|
|
f6b48a1c11 | ||
|
|
bf13f269fe | ||
|
|
cf86dd10a7 | ||
|
|
5995dd9a47 | ||
|
|
d5c6c79a76 | ||
|
|
7e8e626e24 | ||
|
|
f96b2e99cf | ||
|
|
4ec42f4bee | ||
|
|
886e722c71 | ||
|
|
575379e264 | ||
|
|
17e26fdd00 | ||
|
|
5d6ca639fd | ||
|
|
16664c68b5 | ||
|
|
ee1878cce7 | ||
|
|
7542d9200d | ||
|
|
f9356f9ba7 |
No files matched your search
@@ -22,3 +22,11 @@ Struct members: lower_snake_case. Exemple: data, node, next.
|
|||||||
global/static variables: lower_snake_case prefixed. Exemple: g_my_global.
|
global/static variables: lower_snake_case prefixed. Exemple: g_my_global.
|
||||||
const variables: lower_snake_case prefixed. Exemple: k_my_const_var.
|
const variables: lower_snake_case prefixed. Exemple: k_my_const_var.
|
||||||
Defines and Macros: ALL_CAPS_SNAKE. Exemple: MY_MACRO
|
Defines and Macros: ALL_CAPS_SNAKE. Exemple: MY_MACRO
|
||||||
|
|
||||||
|
Modular Architecture & Include Rules:
|
||||||
|
- Juliet uses a single-pass unity build pattern.
|
||||||
|
- Layer aggregators `<layer>_inc.h` and `<layer>_inc.c` dictate header and source inclusion order.
|
||||||
|
- Top-level translation units (e.g. `appbin_main.c`) include the layer `_inc` files in dependency order (`core` -> `render` -> `ui`...).
|
||||||
|
- Sub-files within a module (e.g. `core.h`, `core_arena.c`, `render.c`) must NEVER directly `#include` other module headers, sibling headers, or configuration defines (`core_defines.h`).
|
||||||
|
- Never add `#include` directives to sub-files to satisfy standalone LSP/compiler diagnostics. Tooling (`new_project_gen.c` / `compile_commands.json`) must supply preceding includes dynamically based on the base file include order.
|
||||||
|
- Always explain root causes and confirm with the user before editing project architecture or files.
|
||||||
+5
-6
@@ -44,10 +44,14 @@ IncludeCategories:
|
|||||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
IndentAccessModifiers: false
|
IndentAccessModifiers: false
|
||||||
IndentCaseBlocks: true
|
IndentCaseBlocks: true
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
InsertNewlineAtEOF: true
|
InsertNewlineAtEOF: true
|
||||||
MacroBlockBegin: ''
|
MacroBlockBegin: ''
|
||||||
MacroBlockEnd: ''
|
MacroBlockEnd: ''
|
||||||
|
Macros:
|
||||||
|
- 'EachIndex(it, count)=(uint64 it = 0; it < (count); ++it)'
|
||||||
|
- 'EachNode(it, Type, first)=(Type* it = first; it != 0; it = it->next)'
|
||||||
NamespaceIndentation: All
|
NamespaceIndentation: All
|
||||||
ObjCSpaceAfterProperty: true
|
ObjCSpaceAfterProperty: true
|
||||||
PenaltyBreakBeforeFirstCallParameter: 100
|
PenaltyBreakBeforeFirstCallParameter: 100
|
||||||
@@ -57,15 +61,10 @@ PenaltyBreakString: 100
|
|||||||
PenaltyExcessCharacter: 1
|
PenaltyExcessCharacter: 1
|
||||||
PenaltyReturnTypeOnItsOwnLine: 1000
|
PenaltyReturnTypeOnItsOwnLine: 1000
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
|
PPIndentWidth: 1
|
||||||
SortIncludes: CaseInsensitive
|
SortIncludes: CaseInsensitive
|
||||||
SpacesInAngles: Never
|
SpacesInAngles: Never
|
||||||
SpacesInContainerLiterals: false
|
SpacesInContainerLiterals: false
|
||||||
Standard: Cpp11
|
Standard: Cpp11
|
||||||
StatementMacros:
|
|
||||||
- UPROPERTY
|
|
||||||
- UCLASS
|
|
||||||
- USTRUCT
|
|
||||||
- GENERATED_BODY
|
|
||||||
- UENUM
|
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
...
|
...
|
||||||
@@ -3,6 +3,10 @@ CompileFlags:
|
|||||||
- --driver-mode=cl
|
- --driver-mode=cl
|
||||||
- -Wno-unknown-pragmas
|
- -Wno-unknown-pragmas
|
||||||
- -Wno-unused-command-line-argument
|
- -Wno-unused-command-line-argument
|
||||||
|
- -Wno-unused-function
|
||||||
|
- -Wno-undefined-internal
|
||||||
|
- -Wno-initializer-overrides
|
||||||
|
- /IJuliet
|
||||||
Remove:
|
Remove:
|
||||||
- /Yu*
|
- /Yu*
|
||||||
- /Yc*
|
- /Yc*
|
||||||
@@ -16,8 +20,15 @@ CompileFlags:
|
|||||||
|
|
||||||
Diagnostics:
|
Diagnostics:
|
||||||
UnusedIncludes: None
|
UnusedIncludes: None
|
||||||
|
Suppress:
|
||||||
|
- unused-function
|
||||||
|
- undefined-internal
|
||||||
|
- initializer-overrides
|
||||||
|
|
||||||
InlayHints:
|
InlayHints:
|
||||||
Enabled: Yes
|
Enabled: true
|
||||||
ParameterNames: Yes
|
ParameterNames: true
|
||||||
DeducedTypes: Yes
|
DeducedTypes: true
|
||||||
|
Designators: true
|
||||||
|
BlockEnd: false
|
||||||
|
TypeNameLimit: 24
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
# Binaries
|
# Binaries
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
|
[Bb]uild/
|
||||||
[Ll]ib/
|
[Ll]ib/
|
||||||
.idea/
|
.idea/
|
||||||
.vs/
|
.vs/
|
||||||
|
|||||||
+11
@@ -1,3 +1,14 @@
|
|||||||
[submodule "External/Imgui"]
|
[submodule "External/Imgui"]
|
||||||
path = External/Imgui
|
path = External/Imgui
|
||||||
url = https://github.com/ocornut/imgui.git
|
url = https://github.com/ocornut/imgui.git
|
||||||
|
# Pinned to v1.93.0 (c1aaac65e)
|
||||||
|
|
||||||
|
[submodule "Juliet/external/xxHash"]
|
||||||
|
path = Juliet/external/xxHash
|
||||||
|
url = https://github.com/Cyan4973/xxHash.git
|
||||||
|
# Pinned to v0.8.4 (c87183a77)
|
||||||
|
|
||||||
|
[submodule "Juliet/external/stb_sprintf"]
|
||||||
|
path = Juliet/external/stb_sprintf
|
||||||
|
url = https://github.com/nothings/stb_sprintf.git
|
||||||
|
# Pinned to v1.10 / commit 2ffb3379e
|
||||||
Vendored
+1
-1
Submodule External/Imgui updated: 9b7699f325...c1aaac65e8.
@@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
constexpr index_t kPlayCamera = 0;
|
#include <Juliet.h>
|
||||||
constexpr index_t kDebugCamera = 1;
|
|
||||||
|
#define kPlayCamera ((index_t)0)
|
||||||
|
#define kDebugCamera ((index_t)1)
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
#include <Controller/DebugCameraController.h>
|
||||||
|
|
||||||
|
#include <Controller/ControllerUtils.h>
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <Core/HAL/Keyboard/Keyboard.h>
|
||||||
|
#include <Core/HAL/Mouse/Mouse.h>
|
||||||
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
#include <Graphics/Camera.h>
|
||||||
|
#include <dcimgui.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
global bool8 gIsDebugCameraActive = false;
|
||||||
|
global index_t gPreviousCameraIndex = 0;
|
||||||
|
global float gPitch = 0.0f;
|
||||||
|
global float gYaw = 0.0f;
|
||||||
|
global bool8 gFirstUpdate = true;
|
||||||
|
global bool8 gIsFpsModeActive = false;
|
||||||
|
global bool8 gWasRightMouseButtonDown = false;
|
||||||
|
|
||||||
|
void ActivateDebugController(void)
|
||||||
|
{
|
||||||
|
Assert(gIsDebugCameraActive == false);
|
||||||
|
|
||||||
|
Camera* currentCam = GetCurrentCamera();
|
||||||
|
gPreviousCameraIndex = currentCam->Index;
|
||||||
|
|
||||||
|
SetCurrentCamera(kDebugCamera);
|
||||||
|
|
||||||
|
gIsDebugCameraActive = true;
|
||||||
|
gFirstUpdate = true;
|
||||||
|
gIsFpsModeActive = false;
|
||||||
|
gWasRightMouseButtonDown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeactivateDebugController(void)
|
||||||
|
{
|
||||||
|
Assert(gIsDebugCameraActive);
|
||||||
|
|
||||||
|
gIsDebugCameraActive = false;
|
||||||
|
|
||||||
|
SetCurrentCamera(gPreviousCameraIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 IsDebugControllerActive(void)
|
||||||
|
{
|
||||||
|
return gIsDebugCameraActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateDebugController(float dt)
|
||||||
|
{
|
||||||
|
Camera* currentCam = GetCurrentCamera();
|
||||||
|
|
||||||
|
if (gFirstUpdate)
|
||||||
|
{
|
||||||
|
Vector3 origin = { 0.0f, 0.0f, 0.0f };
|
||||||
|
Vector3 dir = Vector3Sub(origin, currentCam->Position);
|
||||||
|
dir = Normalize(dir);
|
||||||
|
gPitch = asinf(dir.z);
|
||||||
|
gYaw = atan2f(dir.y, dir.x);
|
||||||
|
gFirstUpdate = false;
|
||||||
|
|
||||||
|
Vector3 forward = { cosf(gPitch) * cosf(gYaw), cosf(gPitch) * sinf(gYaw), sinf(gPitch) };
|
||||||
|
Vector3 worldUp = { 0.0f, 0.0f, 1.0f };
|
||||||
|
Vector3 right = Normalize(Cross(worldUp, forward));
|
||||||
|
currentCam->Target = Vector3Add(currentCam->Position, forward);
|
||||||
|
currentCam->Up = Cross(forward, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 isRightMouseButtonDown = IsMouseButtonDown(MouseButton_Right);
|
||||||
|
if (isRightMouseButtonDown && !gWasRightMouseButtonDown)
|
||||||
|
{
|
||||||
|
gIsFpsModeActive = !gIsFpsModeActive;
|
||||||
|
}
|
||||||
|
gWasRightMouseButtonDown = isRightMouseButtonDown;
|
||||||
|
|
||||||
|
if (gIsFpsModeActive)
|
||||||
|
{
|
||||||
|
MousePosition mouseDelta = GetMouseDelta();
|
||||||
|
|
||||||
|
float sensitivity = 0.005f;
|
||||||
|
gYaw += (float)mouseDelta.X * sensitivity;
|
||||||
|
gPitch -= (float)mouseDelta.Y * sensitivity;
|
||||||
|
|
||||||
|
gPitch = Min(gPitch, 1.5f);
|
||||||
|
gPitch = Max(gPitch, -1.5f);
|
||||||
|
|
||||||
|
if (IsKeyDown(ScanCode_Q))
|
||||||
|
{
|
||||||
|
gYaw -= 2.0f * dt;
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_E))
|
||||||
|
{
|
||||||
|
gYaw += 2.0f * dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 forward = { cosf(gPitch) * cosf(gYaw), cosf(gPitch) * sinf(gYaw), sinf(gPitch) };
|
||||||
|
Vector3 worldUp = { 0.0f, 0.0f, 1.0f };
|
||||||
|
Vector3 right = Normalize(Cross(worldUp, forward));
|
||||||
|
Vector3 defaultUp = Cross(forward, right);
|
||||||
|
|
||||||
|
const float kMovementPerFrame = 10.f; // 10m/s
|
||||||
|
|
||||||
|
float speedPerFrame = kMovementPerFrame;
|
||||||
|
if (IsKeyDown(ScanCode_LeftShift))
|
||||||
|
{
|
||||||
|
speedPerFrame *= 10.f; // 100m/s
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsKeyDown(ScanCode_W))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Add(currentCam->Position, Vector3Scale(forward, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_S))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Sub(currentCam->Position, Vector3Scale(forward, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_D))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Add(currentCam->Position, Vector3Scale(right, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_A))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Sub(currentCam->Position, Vector3Scale(right, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_Space))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Add(currentCam->Position, Vector3Scale(defaultUp, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_LeftControl))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Sub(currentCam->Position, Vector3Scale(defaultUp, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
|
||||||
|
currentCam->Target = Vector3Add(currentCam->Position, forward);
|
||||||
|
currentCam->Up = defaultUp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if JULIET_DEBUG
|
||||||
|
void RenderImGuiDebugController(float dt)
|
||||||
|
{
|
||||||
|
Camera* currentCam = GetCurrentCamera();
|
||||||
|
|
||||||
|
ImGui_Text("Delta time: %f", (double)dt);
|
||||||
|
|
||||||
|
ImGui_Text("Camera:");
|
||||||
|
ImGui_Indent();
|
||||||
|
ImGui_BulletText("Index: %zu", (size_t)currentCam->Index);
|
||||||
|
ImGui_BulletText("Position: (%.3f, %.3f, %.3f)", (double)currentCam->Position.x, (double)currentCam->Position.y,
|
||||||
|
(double)currentCam->Position.z);
|
||||||
|
ImGui_BulletText("Target: (%.3f, %.3f, %.3f)", (double)currentCam->Target.x, (double)currentCam->Target.y,
|
||||||
|
(double)currentCam->Target.z);
|
||||||
|
ImGui_BulletText("Up: (%.3f, %.3f, %.3f)", (double)currentCam->Up.x, (double)currentCam->Up.y,
|
||||||
|
(double)currentCam->Up.z);
|
||||||
|
ImGui_BulletText("FOV: %.3f rad", (double)currentCam->FOV);
|
||||||
|
ImGui_BulletText("AspectRatio: %.3f", (double)currentCam->AspectRatio);
|
||||||
|
ImGui_BulletText("NearPlane: %.3f", (double)currentCam->NearPlane);
|
||||||
|
ImGui_BulletText("FarPlane: %.3f", (double)currentCam->FarPlane);
|
||||||
|
ImGui_BulletText("Pitch: %.3f, Yaw: %.3f", (double)gPitch, (double)gYaw);
|
||||||
|
ImGui_BulletText("FPS Mode: %s", gIsFpsModeActive ? "Active" : "Inactive");
|
||||||
|
ImGui_Unindent();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
#include <Controller/DebugCameraController.h>
|
|
||||||
|
|
||||||
#include <Controller/ControllerUtils.h>
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
|
||||||
#include <Core/HAL/Keyboard/Keyboard.h>
|
|
||||||
#include <Core/HAL/Mouse/Mouse.h>
|
|
||||||
#include <Graphics/Camera.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
bool gIsDebugCameraActive = false;
|
|
||||||
index_t gPreviousCameraIndex = 0;
|
|
||||||
|
|
||||||
float gPitch = 0.0f;
|
|
||||||
float gYaw = 0.0f;
|
|
||||||
bool gFirstUpdate = true;
|
|
||||||
bool gIsFpsModeActive = false;
|
|
||||||
bool gWasRightMouseButtonDown = false;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void ActivateDebugController()
|
|
||||||
{
|
|
||||||
Assert(gIsDebugCameraActive == false);
|
|
||||||
|
|
||||||
Camera* currentCam = GetCurrentCamera();
|
|
||||||
gPreviousCameraIndex = currentCam->Index;
|
|
||||||
|
|
||||||
SetCurrentCamera(kDebugCamera);
|
|
||||||
|
|
||||||
gIsDebugCameraActive = true;
|
|
||||||
gFirstUpdate = true;
|
|
||||||
gIsFpsModeActive = false;
|
|
||||||
gWasRightMouseButtonDown = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeactivateDebugController()
|
|
||||||
{
|
|
||||||
Assert(gIsDebugCameraActive);
|
|
||||||
|
|
||||||
gIsDebugCameraActive = false;
|
|
||||||
|
|
||||||
SetCurrentCamera(gPreviousCameraIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsDebugControllerActive()
|
|
||||||
{
|
|
||||||
return gIsDebugCameraActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateDebugController(float dt)
|
|
||||||
{
|
|
||||||
Camera* currentCam = GetCurrentCamera();
|
|
||||||
|
|
||||||
if (gFirstUpdate)
|
|
||||||
{
|
|
||||||
Vector3 dir = Vector3{ 0.0f, 0.0f, 0.0f } - currentCam->Position;
|
|
||||||
dir = Normalize(dir);
|
|
||||||
gPitch = asinf(dir.z);
|
|
||||||
gYaw = atan2f(dir.y, dir.x);
|
|
||||||
gFirstUpdate = false;
|
|
||||||
|
|
||||||
Vector3 forward;
|
|
||||||
forward.x = cosf(gPitch) * cosf(gYaw);
|
|
||||||
forward.y = cosf(gPitch) * sinf(gYaw);
|
|
||||||
forward.z = sinf(gPitch);
|
|
||||||
Vector3 right = Normalize(Cross(Vector3{ 0.0f, 0.0f, 1.0f }, forward));
|
|
||||||
currentCam->Target = currentCam->Position + forward;
|
|
||||||
currentCam->Up = Cross(forward, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isRightMouseButtonDown = IsMouseButtonDown(MouseButton::Right);
|
|
||||||
if (isRightMouseButtonDown && !gWasRightMouseButtonDown)
|
|
||||||
{
|
|
||||||
gIsFpsModeActive = !gIsFpsModeActive;
|
|
||||||
}
|
|
||||||
gWasRightMouseButtonDown = isRightMouseButtonDown;
|
|
||||||
|
|
||||||
if (!gIsFpsModeActive)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MousePosition mouseDelta = GetMouseDelta();
|
|
||||||
|
|
||||||
float sensitivity = 0.005f;
|
|
||||||
gYaw += mouseDelta.X * sensitivity;
|
|
||||||
gPitch -= mouseDelta.Y * sensitivity;
|
|
||||||
|
|
||||||
gPitch = std::min(gPitch, 1.5f);
|
|
||||||
gPitch = std::max(gPitch, -1.5f);
|
|
||||||
|
|
||||||
if (IsKeyDown(ScanCode::Q))
|
|
||||||
{
|
|
||||||
gYaw -= 2.0f * dt;
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::E))
|
|
||||||
{
|
|
||||||
gYaw += 2.0f * dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 forward;
|
|
||||||
forward.x = cosf(gPitch) * cosf(gYaw);
|
|
||||||
forward.y = cosf(gPitch) * sinf(gYaw);
|
|
||||||
forward.z = sinf(gPitch);
|
|
||||||
|
|
||||||
Vector3 right = Normalize(Cross(Vector3{ 0.0f, 0.0f, 1.0f }, forward));
|
|
||||||
Vector3 defaultUp = Cross(forward, right);
|
|
||||||
|
|
||||||
static const float kMovementPerFrame = 10.f; // 10m/s
|
|
||||||
|
|
||||||
float speedPerFrame = kMovementPerFrame;
|
|
||||||
if (IsKeyDown(ScanCode::LeftShift))
|
|
||||||
{
|
|
||||||
speedPerFrame *= 10.f; // 100m/s
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsKeyDown(ScanCode::W))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position + forward * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::S))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position - forward * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::D))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position + right * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::A))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position - right * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::Space))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position + defaultUp * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::LeftControl))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position - defaultUp * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentCam->Target = currentCam->Position + forward;
|
|
||||||
currentCam->Up = defaultUp;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
|
||||||
void RenderImGuiDebugController(float dt)
|
|
||||||
{
|
|
||||||
Camera* currentCam = GetCurrentCamera();
|
|
||||||
|
|
||||||
ImGui::Text("Delta time: %f", dt);
|
|
||||||
|
|
||||||
ImGui::Text("Camera:");
|
|
||||||
ImGui::Indent();
|
|
||||||
ImGui::BulletText("Index: %zu", (size_t)currentCam->Index);
|
|
||||||
ImGui::BulletText("Position: (%.3f, %.3f, %.3f)", currentCam->Position.x, currentCam->Position.y,
|
|
||||||
currentCam->Position.z);
|
|
||||||
ImGui::BulletText("Target: (%.3f, %.3f, %.3f)", currentCam->Target.x, currentCam->Target.y, currentCam->Target.z);
|
|
||||||
ImGui::BulletText("Up: (%.3f, %.3f, %.3f)", currentCam->Up.x, currentCam->Up.y, currentCam->Up.z);
|
|
||||||
ImGui::BulletText("FOV: %.3f rad", currentCam->FOV);
|
|
||||||
ImGui::BulletText("AspectRatio: %.3f", currentCam->AspectRatio);
|
|
||||||
ImGui::BulletText("NearPlane: %.3f", currentCam->NearPlane);
|
|
||||||
ImGui::BulletText("FarPlane: %.3f", currentCam->FarPlane);
|
|
||||||
ImGui::BulletText("Pitch: %.3f, Yaw: %.3f", gPitch, gYaw);
|
|
||||||
ImGui::BulletText("FPS Mode: %s", gIsFpsModeActive ? "Active" : "Inactive");
|
|
||||||
ImGui::Unindent();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
// TODO : Should support Debug/Profile/Release properly.
|
// TODO : Should support Debug/Profile/Release properly.
|
||||||
// I think debug profile should have this controller but not release
|
// I think debug profile should have this controller but not release
|
||||||
void ActivateDebugController();
|
void ActivateDebugController(void);
|
||||||
void DeactivateDebugController();
|
void DeactivateDebugController(void);
|
||||||
bool IsDebugControllerActive();
|
bool8 IsDebugControllerActive(void);
|
||||||
void UpdateDebugController(float dt);
|
void UpdateDebugController(float dt);
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
void RenderImGuiDebugController(float dt);
|
void RenderImGuiDebugController(float dt);
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
#include <Data/World.h>
|
||||||
|
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
#include <Core/HAL/Filesystem/Filesystem.h>
|
||||||
|
#include <Core/HAL/IO/IOStream.h>
|
||||||
|
#include <Core/Logging/LogManager.h>
|
||||||
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Core/Thread/ThreadContext.h>
|
||||||
|
#include <Entity/EntityManager.h>
|
||||||
|
#include <Graphics/MeshRenderer.h>
|
||||||
|
|
||||||
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
|
#include <dcimgui.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void InitWorld(World* world, Arena* arena)
|
||||||
|
{
|
||||||
|
Assert(world != NULL);
|
||||||
|
Assert(arena != NULL);
|
||||||
|
world->WorldArena = arena;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShutdownWorld(World* world)
|
||||||
|
{
|
||||||
|
Assert(world != NULL);
|
||||||
|
world->WorldArena = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddToWorld(World* world, Entity* entity)
|
||||||
|
{
|
||||||
|
(void)world;
|
||||||
|
(void)entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveWorldEntity(World* world, size_t index)
|
||||||
|
{
|
||||||
|
(void)world;
|
||||||
|
(void)index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializeWorld(Archive* ar, World* world, String filename)
|
||||||
|
{
|
||||||
|
(void)world;
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(IsValidString(filename));
|
||||||
|
|
||||||
|
EntityManager* entityManager = GetEntityManager();
|
||||||
|
|
||||||
|
if (ar->loading)
|
||||||
|
{
|
||||||
|
// Load
|
||||||
|
ByteBuffer fileBuffer = LoadFile(ar->arena, filename);
|
||||||
|
|
||||||
|
// TEST SERIALIZATION
|
||||||
|
ParsedArchive archive = tokenize_archive(ar->arena, fileBuffer);
|
||||||
|
#if JULIET_DEBUG
|
||||||
|
audit_unconsumed_properties(&archive, ConstString("World"));
|
||||||
|
#else
|
||||||
|
(void)archive;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Save
|
||||||
|
IOStream* stream = IOFromFile(ar->arena, filename, WrapString("wb"));
|
||||||
|
|
||||||
|
index_t beginPos = ArenaPos(ar->arena);
|
||||||
|
|
||||||
|
// Headers
|
||||||
|
WorldFileHeader* header = ArenaPushStruct(ar->arena, WorldFileHeader);
|
||||||
|
header->Magic = kWorldMagic;
|
||||||
|
|
||||||
|
// TODO : Move to a one file per entity model
|
||||||
|
for (uint8 i = 0; i < ENTITY(Count); ++i)
|
||||||
|
{
|
||||||
|
typed_entity_array* type = &entityManager->by_type[i];
|
||||||
|
serialize_elem(ar, type->count);
|
||||||
|
if (type->count > 0 && type->array != NULL)
|
||||||
|
{
|
||||||
|
EntityTemplate* element = type->array;
|
||||||
|
uint8* rawElement = (uint8*)element;
|
||||||
|
size_t stride = element->base->derived_kind->size_of;
|
||||||
|
for (index_t idx = 0; idx < type->count; ++idx)
|
||||||
|
{
|
||||||
|
Entity* entity = ((EntityTemplate*)(rawElement + (idx * stride)))->base;
|
||||||
|
serialize_entity(ar, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write
|
||||||
|
index_t endPos = ArenaPos(ar->arena);
|
||||||
|
ByteBuffer writeBuffer = { .Data = (Byte*)header, .Size = endPos - beginPos };
|
||||||
|
|
||||||
|
size_t written = IOWrite(stream, writeBuffer);
|
||||||
|
|
||||||
|
Assert(writeBuffer.Size == written);
|
||||||
|
|
||||||
|
IOClose(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 LoadWorld(World* world, String filename)
|
||||||
|
{
|
||||||
|
(void)world;
|
||||||
|
Assert(IsValidString(filename));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JULIET_EDITOR
|
||||||
|
void RenderWorldEditorUI(World* world)
|
||||||
|
{
|
||||||
|
Assert(world != NULL);
|
||||||
|
|
||||||
|
if (ImGui_Begin("World Editor", NULL, ImGuiWindowFlags_None))
|
||||||
|
{
|
||||||
|
TempArena temp = scratch_begin(NULL, 0);
|
||||||
|
static char worldFilePath[256] = "/world.bin";
|
||||||
|
ImGui_InputText("World File", worldFilePath, sizeof(worldFilePath));
|
||||||
|
|
||||||
|
Path path = GetAssetPath(temp.Arena, AssetType_JAsset, WrapString(worldFilePath));
|
||||||
|
|
||||||
|
if (ImGui_Button("Save World"))
|
||||||
|
{
|
||||||
|
Archive data = { .arena = temp.Arena, .loading = false };
|
||||||
|
SerializeWorld(&data, world, path.FullPath);
|
||||||
|
}
|
||||||
|
ImGui_SameLine(0.0f, -1.0f);
|
||||||
|
if (ImGui_Button("Load World"))
|
||||||
|
{
|
||||||
|
Archive data = { .arena = temp.Arena, .loading = true };
|
||||||
|
SerializeWorld(&data, world, path.FullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(temp);
|
||||||
|
}
|
||||||
|
ImGui_End();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,322 +0,0 @@
|
|||||||
#include <Data/World.h>
|
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
#include <Core/HAL/Filesystem/Filesystem.h>
|
|
||||||
#include <Core/HAL/IO/IOStream.h>
|
|
||||||
#include <Core/Logging/LogManager.h>
|
|
||||||
#include <Core/Logging/LogTypes.h>
|
|
||||||
#include <Core/Thread/ThreadContext.h>
|
|
||||||
#include <Entity/EntityManager.h>
|
|
||||||
#include <Graphics/MeshRenderer.h>
|
|
||||||
|
|
||||||
#ifdef JULIET_ENABLE_IMGUI
|
|
||||||
#include <imgui.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void InitWorld(NonNullPtr<World> world, NonNullPtr<Arena> arena)
|
|
||||||
{
|
|
||||||
world->WorldArena = arena.Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShutdownWorld(NonNullPtr<World> world)
|
|
||||||
{
|
|
||||||
world->WorldArena = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddToWorld(NonNullPtr<World> /*world*/, NonNullPtr<Entity> /*entity*/)
|
|
||||||
{
|
|
||||||
// RegisterEntity(*world->EntityManager, entity.Get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveWorldEntity(World& /*world*/, size_t /*index*/) {}
|
|
||||||
|
|
||||||
void Serialize(Archive& ar, World& /*world*/, String filename)
|
|
||||||
{
|
|
||||||
Assert(IsValid(filename));
|
|
||||||
|
|
||||||
auto& entityManager = GetEntityManager();
|
|
||||||
|
|
||||||
if (ar.loading)
|
|
||||||
{
|
|
||||||
// Load
|
|
||||||
ByteBuffer fileBuffer = LoadFile(ar.arena, filename);
|
|
||||||
|
|
||||||
// TEST SERIALIZATION
|
|
||||||
ParsedArchive archive = tokenize_archive(ar.arena, fileBuffer);
|
|
||||||
// ArchivePropertyNode* property = find_property(&archive, "Position"_crc32);
|
|
||||||
audit_unconsumed_properties(&archive, ConstString("World"));
|
|
||||||
|
|
||||||
// if (fileBuffer.Size >= sizeof(WorldFileHeader))
|
|
||||||
// {
|
|
||||||
// ar.base_ptr = fileBuffer.Data;
|
|
||||||
//
|
|
||||||
// WorldFileHeader header;
|
|
||||||
// serialize_elem(ar, header);
|
|
||||||
// Assert(header.Magic == kWorldMagic);
|
|
||||||
//
|
|
||||||
// for (typed_entity_array& type : entityManager.by_type)
|
|
||||||
// {
|
|
||||||
// serialize_elem(ar, type.count);
|
|
||||||
//
|
|
||||||
// if (type.count > 0)
|
|
||||||
// {
|
|
||||||
//
|
|
||||||
// // Unserialize the base entity to get informations
|
|
||||||
// Entity entity;
|
|
||||||
// // serialize(ar, &entity);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Save
|
|
||||||
IOStream* stream = IOFromFile(ar.arena, filename, WrapString("wb"));
|
|
||||||
|
|
||||||
index_t beginPos = ArenaPos(ar.arena);
|
|
||||||
|
|
||||||
// Headers
|
|
||||||
auto* header = ArenaPushStruct<WorldFileHeader>(ar.arena);
|
|
||||||
header->Magic = kWorldMagic;
|
|
||||||
|
|
||||||
ar.base_ptr = header;
|
|
||||||
|
|
||||||
// TODO : Move to a one file per entity model
|
|
||||||
for (typed_entity_array& type : entityManager.by_type)
|
|
||||||
{
|
|
||||||
serialize_elem(ar, type.count);
|
|
||||||
auto* element = type.array;
|
|
||||||
uint8* rawElement = reinterpret_cast<uint8*>(element);
|
|
||||||
size_t stride = element->base->derived_kind->size_of;
|
|
||||||
for (index_t idx = 0; idx < type.count; ++idx)
|
|
||||||
{
|
|
||||||
// Todo : utils
|
|
||||||
// Get base entity from type
|
|
||||||
Entity* entity = reinterpret_cast<EntityTemplate*>(rawElement + (idx * stride))->base;
|
|
||||||
serialize(ar, entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write
|
|
||||||
index_t endPos = ArenaPos(ar.arena);
|
|
||||||
ByteBuffer writeBuffer = { .Data = reinterpret_cast<Byte*>(header), .Size = endPos - beginPos };
|
|
||||||
|
|
||||||
size_t written = IOWrite(stream, writeBuffer);
|
|
||||||
|
|
||||||
Assert(writeBuffer.Size == written);
|
|
||||||
|
|
||||||
IOClose(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// uint32 entityCount = static_cast<uint32>(world.Entities.Size());
|
|
||||||
// size_t totalBytes = sizeof(WorldFileHeader) + static_cast<size_t>(entityCount) * sizeof(WorldEntityDiskRecord);
|
|
||||||
//
|
|
||||||
// ArenaParams tempParams = { .ReserveSize = Megabytes(1), .Name = "WorldSaveArena" };
|
|
||||||
// Arena* tempArena = ArenaAllocate(tempParams);
|
|
||||||
// if (!tempArena)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "SaveWorld: Failed to allocate memory for saving world.");
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// auto deferRelease = Defer([&]() { ArenaRelease(tempArena); });
|
|
||||||
//
|
|
||||||
// uint8* bufferData = ArenaPushArray<uint8, false>(tempArena, totalBytes);
|
|
||||||
// if (!bufferData)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "SaveWorld: Failed to allocate buffer in arena.");
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// auto* header = reinterpret_cast<WorldFileHeader*>(bufferData);
|
|
||||||
// header->Magic = kWorldMagic;
|
|
||||||
// header->Version = kWorldVersion;
|
|
||||||
// header->EntityCount = entityCount;
|
|
||||||
// header->Reserved = 0;
|
|
||||||
//
|
|
||||||
// auto* records = reinterpret_cast<WorldEntityDiskRecord*>(bufferData + sizeof(WorldFileHeader));
|
|
||||||
// for (size_t i = 0; i < entityCount; ++i)
|
|
||||||
// {
|
|
||||||
// const Entity& ent = world.Entities[i];
|
|
||||||
// records[i].X = ent.X;
|
|
||||||
// records[i].Y = ent.Y;
|
|
||||||
// records[i].Z = ent.Z;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// IOStream* stream = IOFromFile(tempArena, filename, WrapString("wb"));
|
|
||||||
// if (!stream)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "SaveWorld: Failed to open file for writing: %s", CStr(filename));
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ByteBuffer writeBuffer = { .Data = reinterpret_cast<Byte*>(bufferData), .Size = totalBytes };
|
|
||||||
//
|
|
||||||
// size_t written = IOWrite(stream, writeBuffer);
|
|
||||||
// IOClose(stream);
|
|
||||||
//
|
|
||||||
// if (written != totalBytes)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "SaveWorld: Failed to write complete world data to %s (wrote %zu / %zu bytes)",
|
|
||||||
// CStr(filename), written, totalBytes);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// LogMessage(LogCategory::Game, "World successfully saved to %s (%u entities)", CStr(filename), entityCount);
|
|
||||||
// return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool LoadWorld(World& /*world*/, String filename)
|
|
||||||
{
|
|
||||||
Assert(IsValid(filename));
|
|
||||||
// Assert(world.WorldArena != nullptr);
|
|
||||||
//
|
|
||||||
// TempArena loadArena = scratch_begin(nullptr, 0);
|
|
||||||
//
|
|
||||||
// ByteBuffer fileBuffer = LoadFile(loadArena.Arena, filename);
|
|
||||||
// if (fileBuffer.Data && fileBuffer.Size < sizeof(WorldFileHeader))
|
|
||||||
// {
|
|
||||||
// const WorldFileHeader* header = reinterpret_cast<const WorldFileHeader*>(fileBuffer.Data);
|
|
||||||
// const bool invalidMagicNum = header->Magic != kWorldMagic;
|
|
||||||
// const bool invalidVersion = header->Version != kWorldVersion;
|
|
||||||
// if (invalidMagicNum)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "LoadWorld: Invalid magic in world file: %s (expected 0x%08X, got 0x%08X)",
|
|
||||||
// CStr(filename), kWorldMagic, header->Magic);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (invalidVersion)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "LoadWorld: Unsupported world file version: %u in %s", header->Version, CStr(filename));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t expectedSize = sizeof(WorldFileHeader) + static_cast<size_t>(header->EntityCount) * sizeof(WorldEntityDiskRecord);
|
|
||||||
// const bool invalidSize = fileBuffer.Size < expectedSize;
|
|
||||||
// if (invalidSize)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "LoadWorld: Corrupted file %s: size %zu < expected %zu for %u entities",
|
|
||||||
// CStr(filename), fileBuffer.Size, expectedSize, header->EntityCount);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (!invalidMagicNum && !invalidVersion && !invalidSize)
|
|
||||||
// {
|
|
||||||
//
|
|
||||||
// // world.Entities.Clear();
|
|
||||||
// //
|
|
||||||
// // const auto* records = reinterpret_cast<const WorldEntityDiskRecord*>(
|
|
||||||
// // reinterpret_cast<const uint8*>(fileBuffer.Data) + sizeof(WorldFileHeader));
|
|
||||||
// //
|
|
||||||
// // for (uint32 i = 0; i < header->EntityCount; ++i)
|
|
||||||
// // {
|
|
||||||
// // Entity ent;
|
|
||||||
// // (void)AddWorldEntity(world, records[i].X, records[i].Y, records[i].Z);
|
|
||||||
// // }
|
|
||||||
//
|
|
||||||
// LogMessage(LogCategory::Game, "World successfully loaded from %s (%u entities)", CStr(filename), header->EntityCount);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "LoadWorld: Failed to read world file or file is too small: %s", CStr(filename));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// scratch_end(loadArena);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef JULIET_EDITOR
|
|
||||||
void RenderWorldEditorUI(World& world)
|
|
||||||
{
|
|
||||||
if (ImGui::Begin("World Editor"))
|
|
||||||
{
|
|
||||||
TempArena temp = scratch_begin(nullptr, 0);
|
|
||||||
static char worldFilePath[256] = "/world.bin";
|
|
||||||
ImGui::InputText("World File", worldFilePath, sizeof(worldFilePath));
|
|
||||||
|
|
||||||
Path path = GetAssetPath(temp.Arena, AssetType::JAsset, ConstString(worldFilePath));
|
|
||||||
|
|
||||||
if (ImGui::Button("Save World"))
|
|
||||||
{
|
|
||||||
Archive data = { .arena = temp.Arena, .loading = false };
|
|
||||||
Serialize(data, world, path.FullPath);
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Load World"))
|
|
||||||
{
|
|
||||||
Archive data{ .arena = temp.Arena, .loading = true };
|
|
||||||
Serialize(data, world, path.FullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
scratch_end(temp);
|
|
||||||
|
|
||||||
// ImGui::SameLine();
|
|
||||||
// if (ImGui::Button("Clear All"))
|
|
||||||
// {
|
|
||||||
// ClearWorld(world);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ImGui::Separator();
|
|
||||||
//
|
|
||||||
// if (ImGui::Button("Add Entity"))
|
|
||||||
// {
|
|
||||||
// (void)AddWorldEntity(world, 0.0f, 0.0f, 0.0f);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ImGui::Text("Entity Count: %zu", world.Entities.Size());
|
|
||||||
// ImGui::Separator();
|
|
||||||
//
|
|
||||||
// static int selectedEntity = -1;
|
|
||||||
// if (selectedEntity >= static_cast<int>(world.Entities.Size()))
|
|
||||||
// {
|
|
||||||
// selectedEntity = -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ImGui::BeginChild("EntityList", ImVec2(180, 200), true);
|
|
||||||
// for (size_t i = 0; i < world.Entities.Size(); ++i)
|
|
||||||
// {
|
|
||||||
// char label[64];
|
|
||||||
// snprintf(label, sizeof(label), "Entity #%zu (ID: %llu)", i, world.Entities[i].ID);
|
|
||||||
// if (ImGui::Selectable(label, selectedEntity == static_cast<int>(i)))
|
|
||||||
// {
|
|
||||||
// selectedEntity = static_cast<int>(i);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ImGui::EndChild();
|
|
||||||
//
|
|
||||||
// ImGui::SameLine();
|
|
||||||
//
|
|
||||||
// ImGui::BeginChild("EntityInspector", ImVec2(0, 200), true);
|
|
||||||
// if (selectedEntity >= 0 && selectedEntity < static_cast<int>(world.Entities.Size()))
|
|
||||||
// {
|
|
||||||
// Entity& ent = world.Entities[static_cast<size_t>(selectedEntity)];
|
|
||||||
// ImGui::Text("Selected: Entity #%d", selectedEntity);
|
|
||||||
// ImGui::Text("ID: %llu", ent.ID);
|
|
||||||
//
|
|
||||||
// float pos[3] = { ent.X, ent.Y, ent.Z };
|
|
||||||
// if (ImGui::DragFloat3("Position", pos, 0.1f))
|
|
||||||
// {
|
|
||||||
// ent.X = pos[0];
|
|
||||||
// ent.Y = pos[1];
|
|
||||||
// ent.Z = pos[2];
|
|
||||||
// UpdateWorld(world);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (ImGui::Button("Delete Entity"))
|
|
||||||
// {
|
|
||||||
// RemoveWorldEntity(world, static_cast<size_t>(selectedEntity));
|
|
||||||
// selectedEntity = -1;
|
|
||||||
// UpdateWorld(world);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// ImGui::Text("Select an entity to edit its properties.");
|
|
||||||
// }
|
|
||||||
// ImGui::EndChild();
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
+15
-14
@@ -1,38 +1,39 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
#include <Core/Container/Vector.h>
|
#include <Core/Container/Vector.h>
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
#include <Entity/Entity.h>
|
#include <Entity/Entity.h>
|
||||||
|
|
||||||
struct Archive;
|
typedef struct Archive Archive;
|
||||||
struct EntityManager;
|
typedef struct EntityManager EntityManager;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
typedef struct WorldFileHeader WorldFileHeader;
|
||||||
struct WorldFileHeader
|
struct WorldFileHeader
|
||||||
{
|
{
|
||||||
uint32 Magic = 0x444C574A; // 'JWLD' in little-endian
|
uint32 Magic; // 0x444C574A ('JWLD' in little-endian)
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
constexpr uint32 kWorldMagic = 0x444C574A; // 'JWLD'
|
#define kWorldMagic ((uint32)0x444C574A) // 'JWLD'
|
||||||
constexpr uint32 kWorldVersion = 1;
|
#define kWorldVersion ((uint32)1)
|
||||||
|
|
||||||
|
typedef struct World World;
|
||||||
struct World
|
struct World
|
||||||
{
|
{
|
||||||
Arena* WorldArena = nullptr;
|
Arena* WorldArena;
|
||||||
EntityManager* EntityManager = nullptr;
|
EntityManager* EntityManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitWorld(NonNullPtr<World> world, NonNullPtr<Arena> arena);
|
void InitWorld(World* world, Arena* arena);
|
||||||
void ShutdownWorld(NonNullPtr<World> world);
|
void ShutdownWorld(World* world);
|
||||||
|
|
||||||
void AddToWorld(NonNullPtr<World> world, NonNullPtr<Entity> entity);
|
void AddToWorld(World* world, Entity* entity);
|
||||||
void RemoveWorldEntity(World& world, size_t index);
|
void RemoveWorldEntity(World* world, size_t index);
|
||||||
|
|
||||||
void Serialize(Archive& data, World& world, String filename);
|
void SerializeWorld(Archive* data, World* world, String filename);
|
||||||
|
|
||||||
#if JULIET_EDITOR
|
#if JULIET_EDITOR
|
||||||
void RenderWorldEditorUI(World& world);
|
void RenderWorldEditorUI(World* world);
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#include <Debug/DebugTopBar.h>
|
||||||
|
|
||||||
|
#if JULIET_DEBUG
|
||||||
|
#include <game.h>
|
||||||
|
#include <dcimgui.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
internal String GetGameModeName(GameMode gameMode)
|
||||||
|
{
|
||||||
|
String result = WrapString("Unknown ERROR");
|
||||||
|
if (gameMode == GameMode_Editor)
|
||||||
|
{
|
||||||
|
result = WrapString("Editor");
|
||||||
|
}
|
||||||
|
else if (gameMode == GameMode_Play)
|
||||||
|
{
|
||||||
|
result = WrapString("Play");
|
||||||
|
}
|
||||||
|
else if (gameMode == GameMode_Debug)
|
||||||
|
{
|
||||||
|
result = WrapString("Debug");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTopBar(void)
|
||||||
|
{
|
||||||
|
GameState* gameState = GetGameState();
|
||||||
|
|
||||||
|
ImVec2_c viewportPos = ImGui_GetMainViewportPos();
|
||||||
|
ImVec2_c viewportSize = ImGui_GetMainViewportSize();
|
||||||
|
ImGui_SetNextWindowPos(viewportPos);
|
||||||
|
ImVec2_c barSize = { viewportSize.x, 10.0f };
|
||||||
|
ImGui_SetNextWindowSize(barSize);
|
||||||
|
|
||||||
|
ImGuiWindowFlags_c flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
||||||
|
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing |
|
||||||
|
ImGuiWindowFlags_NoNav;
|
||||||
|
|
||||||
|
ImVec4_c bgCol = { 0.0f, 0.0f, 0.0f, 0.6f };
|
||||||
|
ImVec2_c padding = { 10.0f, 5.0f };
|
||||||
|
ImGui_PushStyleColor(ImGuiCol_WindowBg, bgCol);
|
||||||
|
ImGui_PushStyleVarVec2(ImGuiStyleVar_WindowPadding, padding);
|
||||||
|
|
||||||
|
if (ImGui_Begin("TopBarOverlay", NULL, flags))
|
||||||
|
{
|
||||||
|
ImGui_Text("Game Mode: %s", CStr(GetGameModeName(gameState->Mode)));
|
||||||
|
|
||||||
|
float framerate = ImGuiIO_GetFramerate();
|
||||||
|
char fps_text[32];
|
||||||
|
snprintf(fps_text, sizeof(fps_text), "FPS: %.1f (%.2f ms)", (double)framerate, (double)(1000.0f / framerate));
|
||||||
|
float text_width = ImGui_CalcTextSize(fps_text, NULL).x;
|
||||||
|
ImGui_SameLine(viewportSize.x - text_width - 15.0f, -1.0f); // 15px right padding
|
||||||
|
// Render FPS text
|
||||||
|
ImGui_Text("%s", fps_text);
|
||||||
|
}
|
||||||
|
ImGui_End();
|
||||||
|
|
||||||
|
ImGui_PopStyleVar(1);
|
||||||
|
ImGui_PopStyleColor(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#include <Debug/DebugTopBar.h>
|
|
||||||
|
|
||||||
#include <game.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
String GetGameModeName(GameMode gameMode)
|
|
||||||
{
|
|
||||||
switch (gameMode)
|
|
||||||
{
|
|
||||||
case GameMode::Editor: return WrapString("Editor");
|
|
||||||
case GameMode::Play: return WrapString("Play");
|
|
||||||
case GameMode::Debug: return WrapString("Debug");
|
|
||||||
default: return WrapString("Unknown ERROR");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void DrawTopBar()
|
|
||||||
{
|
|
||||||
auto* gameState = GetGameState();
|
|
||||||
|
|
||||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
|
||||||
ImGui::SetNextWindowPos(viewport->Pos);
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, 10.0f));
|
|
||||||
|
|
||||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
|
|
||||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
|
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.6f));
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 5.0f));
|
|
||||||
|
|
||||||
if (ImGui::Begin("TopBarOverlay", nullptr, flags))
|
|
||||||
{
|
|
||||||
ImGui::Text("Game Mode: %s", CStr(GetGameModeName(gameState->Mode)));
|
|
||||||
|
|
||||||
char fps_text[32];
|
|
||||||
snprintf(fps_text, sizeof(fps_text), "FPS: %.1f (%.2f ms)", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate);
|
|
||||||
float text_width = ImGui::CalcTextSize(fps_text).x;
|
|
||||||
ImGui::SameLine(viewport->Size.x - text_width - 15.0f); // 15px right padding
|
|
||||||
// Render FPS text
|
|
||||||
ImGui::Text("%s", fps_text);
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
void DrawTopBar();
|
void DrawTopBar(void);
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#include <Entity/Entity.h>
|
||||||
|
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
#include <Core/Memory/Utils.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void serialize_entity(Archive* ar, Entity* entity)
|
||||||
|
{
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(entity != NULL);
|
||||||
|
|
||||||
|
// Entity fields
|
||||||
|
serialize_class(ar, ClassKind(Entity), entity);
|
||||||
|
|
||||||
|
// Derived fields
|
||||||
|
if (entity->derived_kind != NULL && entity->derived != NULL)
|
||||||
|
{
|
||||||
|
serialize_class(ar, entity->derived_kind, entity->derived);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void init_Entity(void* payload)
|
||||||
|
{
|
||||||
|
Assert(payload != NULL);
|
||||||
|
Entity* entity = (Entity*)payload;
|
||||||
|
MemZeroStruct(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void serialize_Entity(Archive* ar, uint16 version, void* payload)
|
||||||
|
{
|
||||||
|
(void)version;
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(payload != NULL);
|
||||||
|
Entity* entity = (Entity*)payload;
|
||||||
|
SERIALIZE_U64(ar, id, &entity->ID);
|
||||||
|
SERIALIZE_VEC4(ar, position, &entity->position);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_CLASS_VERSIONED(Entity, 1, NULL)
|
||||||
|
|
||||||
|
String format_entity_id(Arena* arena, EntityID entity_id)
|
||||||
|
{
|
||||||
|
Assert(arena != NULL);
|
||||||
|
|
||||||
|
// Format:
|
||||||
|
// U = UserID
|
||||||
|
// LC = Local Entity Counter
|
||||||
|
// UU_LCLCLCLCLCLCLC
|
||||||
|
uint8 user_id = get_user_id(entity_id);
|
||||||
|
uint64 counter = get_local_counter(entity_id);
|
||||||
|
|
||||||
|
const size_t kBufferSize = 18;
|
||||||
|
char* buffer = ArenaPushArray(arena, char, kBufferSize);
|
||||||
|
Assert(buffer != NULL);
|
||||||
|
|
||||||
|
juliet_snprintf(buffer, kBufferSize, "%02X_%014llX", (unsigned int)user_id, (unsigned long long)counter);
|
||||||
|
String result = { .Str = buffer, .Size = kBufferSize - 1 };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 parse_entity_id(String str, EntityID* out_id)
|
||||||
|
{
|
||||||
|
Assert(out_id != NULL);
|
||||||
|
|
||||||
|
bool8 result = false;
|
||||||
|
*out_id = kInvalid_entity_id;
|
||||||
|
|
||||||
|
if (!(str.Size != 17 || str.Str == NULL || str.Str[2] != '_'))
|
||||||
|
{
|
||||||
|
char user_hex[3] = { str.Str[0], str.Str[1], '\0' };
|
||||||
|
char* end = user_hex;
|
||||||
|
uint8 user_id = (uint8)strtoul(user_hex, &end, 16);
|
||||||
|
if (end != user_hex && user_id != kInvalid_user_id)
|
||||||
|
{
|
||||||
|
char* counter_hex = str.Str + 3;
|
||||||
|
end = counter_hex;
|
||||||
|
uint64 counter = strtoull(counter_hex, &end, 16);
|
||||||
|
if (end != counter_hex && counter < kEntityID_user_id_mask)
|
||||||
|
{
|
||||||
|
*out_id = make_entity_id(user_id, counter);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Class* resolve_entity_class(uint8 kind, uint32 crc)
|
||||||
|
{
|
||||||
|
Assert(kind <= ENTITY(Count));
|
||||||
|
|
||||||
|
const Class* class_ptr = kEntity_type_class_ptr[kind];
|
||||||
|
Assert(class_ptr != NULL);
|
||||||
|
Assert(class_get_crc(class_ptr) == crc);
|
||||||
|
|
||||||
|
return class_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Class* find_class_by_name(String name)
|
||||||
|
{
|
||||||
|
Assert(IsValidString(name));
|
||||||
|
|
||||||
|
const Class* result = NULL;
|
||||||
|
const uint32 name_crc = crc32_bytes(name.Str, name.Size);
|
||||||
|
for (uint8 kind = 0; kind < ENTITY(Count); ++kind)
|
||||||
|
{
|
||||||
|
const Class* class_ptr = resolve_entity_class(kind, name_crc);
|
||||||
|
if (class_ptr != NULL)
|
||||||
|
{
|
||||||
|
result = class_ptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
#include <Entity/Entity.h>
|
|
||||||
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
|
|
||||||
void serialize(Archive& ar, NonNullPtr<Entity> entity)
|
|
||||||
{
|
|
||||||
// Entity fields
|
|
||||||
serialize(ar, Entity::kind, entity.Get());
|
|
||||||
|
|
||||||
// Derived fields
|
|
||||||
if (entity->derived_kind != nullptr && entity->derived != nullptr)
|
|
||||||
{
|
|
||||||
serialize(ar, entity->derived_kind, entity->derived);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_CLASS_VERSIONED(Entity, 1, nullptr)
|
|
||||||
internal void serialize(Archive& ar, uint16 /*version*/, Entity& entity)
|
|
||||||
{
|
|
||||||
SERIALIZE(ar, id, entity.ID);
|
|
||||||
SERIALIZE(ar, position, entity.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
String format_entity_id(NonNullPtr<Arena> arena, EntityID entity_id)
|
|
||||||
{
|
|
||||||
// Format:
|
|
||||||
// U = UserID
|
|
||||||
// LC = Local Entity Counter
|
|
||||||
// UU_LCLCLCLCLCLCLC
|
|
||||||
uint8 user_id = get_user_id(entity_id);
|
|
||||||
uint64 counter = get_local_counter(entity_id);
|
|
||||||
|
|
||||||
constexpr size_t kBufferSize = 18;
|
|
||||||
char* buffer = ArenaPushArray<char>(arena, kBufferSize);
|
|
||||||
Assert(buffer);
|
|
||||||
|
|
||||||
juliet_snprintf(buffer, kBufferSize, "%02X_%014llX", (unsigned int)user_id, counter);
|
|
||||||
return { buffer, kBufferSize - 1 };
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_entity_id(String str, EntityID& out_id)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
out_id = kInvalid_entity_id;
|
|
||||||
|
|
||||||
if (!(str.Size != 17 || str.Str == nullptr || str.Str[2] != '_'))
|
|
||||||
{
|
|
||||||
char user_hex[3]{ str.Str[0], str.Str[1], '\0' };
|
|
||||||
char* end = user_hex;
|
|
||||||
uint8 user_id = strtoul(user_hex, &end, 16);
|
|
||||||
if (end != user_hex && user_id != kInvalid_user_id)
|
|
||||||
{
|
|
||||||
char* counter_hex = str.Str + 3;
|
|
||||||
end = counter_hex;
|
|
||||||
uint64 counter = strtoull(counter_hex, &end, 16);
|
|
||||||
if (end != counter_hex && counter < kEntityID_user_id_mask)
|
|
||||||
{
|
|
||||||
out_id = make_entity_id(user_id, counter);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Class* resolve_entity_class(uint8 kind, uint32 crc)
|
|
||||||
{
|
|
||||||
Assert(kind <= ENTITY(Count));
|
|
||||||
|
|
||||||
NonNullPtr<const Class> class_ptr = kEntity_type_class_ptr[kind];
|
|
||||||
Assert(class_ptr->CRC == crc);
|
|
||||||
|
|
||||||
return class_ptr.Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Class* find_class_by_name(String name)
|
|
||||||
{
|
|
||||||
Assert(IsValid(name));
|
|
||||||
|
|
||||||
const Class* result = nullptr;
|
|
||||||
const uint32 name_crc = crc32(name.Str, name.Size);
|
|
||||||
for (uint8 kind = 0; kind < ENTITY(Count); ++kind)
|
|
||||||
{
|
|
||||||
const Class* class_ptr = resolve_entity_class(kind, name_crc);
|
|
||||||
if (class_ptr != nullptr)
|
|
||||||
{
|
|
||||||
result = class_ptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
+48
-51
@@ -6,98 +6,95 @@
|
|||||||
#include <Entity/entity_common.h>
|
#include <Entity/entity_common.h>
|
||||||
#include <Entity/EntityManager.h>
|
#include <Entity/EntityManager.h>
|
||||||
|
|
||||||
struct Entity final
|
typedef struct Entity Entity;
|
||||||
|
struct Entity
|
||||||
{
|
{
|
||||||
DECLARE_CLASS()
|
EntityID ID;
|
||||||
|
const Class* derived_kind;
|
||||||
EntityID ID = 0;
|
DerivedType derived;
|
||||||
const Class* derived_kind = nullptr;
|
Vector4 position;
|
||||||
DerivedType derived = nullptr;
|
bool8 is_dirty;
|
||||||
Vector4 position = {};
|
|
||||||
bool is_dirty = false;
|
|
||||||
};
|
};
|
||||||
|
DECLARE_CLASS(Entity)
|
||||||
|
|
||||||
// Can reinterpret cast to this to have the offset of Base and Kind for any entity
|
// Can cast to this to have the offset of base for any entity
|
||||||
|
typedef struct EntityTemplate EntityTemplate;
|
||||||
struct EntityTemplate
|
struct EntityTemplate
|
||||||
{
|
{
|
||||||
DECLARE_ENTITY();
|
DECLARE_ENTITY()
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
static inline EntityID make_entity_id(uint8 user_id, uint64 local_counter)
|
||||||
template <typename EntityType>
|
|
||||||
concept EntityConcept = requires(EntityType entity) {
|
|
||||||
{ EntityType::kind } -> std::convertible_to<const Class*>;
|
|
||||||
requires std::same_as<decltype(entity.base), Entity*>;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline constexpr EntityID make_entity_id(uint8 user_id, uint64 local_counter)
|
|
||||||
{
|
{
|
||||||
Assert(user_id != kInvalid_user_id);
|
Assert(user_id != kInvalid_user_id);
|
||||||
Assert((local_counter & kEntityID_user_id_mask) == kInvalid_entity_id);
|
Assert((local_counter & kEntityID_user_id_mask) == kInvalid_entity_id);
|
||||||
|
|
||||||
EntityID result = kInvalid_user_id;
|
EntityID result = ((EntityID)user_id << kEntityID_user_id_shift) | (local_counter & kEntityID_user_id_mask);
|
||||||
result = ((EntityID)user_id << kEntityID_user_id_shift) | (local_counter & kEntityID_user_id_mask);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr uint8 get_user_id(EntityID entity_id)
|
static inline uint8 get_user_id(EntityID entity_id)
|
||||||
{
|
{
|
||||||
return (((uint8)entity_id & kEntityID_user_id_mask) << kEntityID_user_id_shift);
|
return (uint8)((entity_id & kEntityID_user_id_mask) >> kEntityID_user_id_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr uint64 get_local_counter(EntityID entity_id)
|
static inline uint64 get_local_counter(EntityID entity_id)
|
||||||
{
|
{
|
||||||
return (uint64)entity_id & kEntityID_user_id_mask;
|
return (uint64)entity_id & ~kEntityID_user_id_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr bool is_entity_id_valid(EntityID entity_id)
|
static inline bool8 is_entity_id_valid(EntityID entity_id)
|
||||||
{
|
{
|
||||||
bool result = entity_id != kInvalid_entity_id;
|
bool8 result = (entity_id != kInvalid_entity_id);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename EntityType>
|
static inline bool8 IsEntityA(const Entity* entity, const Class* kind)
|
||||||
requires EntityConcept<EntityType>
|
|
||||||
[[nodiscard]] bool IsA(const Entity* entity)
|
|
||||||
{
|
{
|
||||||
Assert(entity != nullptr);
|
Assert(entity != NULL);
|
||||||
return entity->derived_kind == EntityType::kind;
|
return entity->derived_kind == kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename EntityType>
|
#define IsEntityOfType(entity_ptr, EntityType) IsEntityA((entity_ptr), ClassKind(EntityType))
|
||||||
requires EntityConcept<EntityType>
|
|
||||||
[[nodiscard]] EntityType* MakeEntity(EntityManager& manager, float x, float y, float z)
|
|
||||||
{
|
|
||||||
Entity* base_ptr = allocate_entity(manager, EntityType::kind);
|
|
||||||
Assert(base_ptr);
|
|
||||||
|
|
||||||
base_ptr->ID = EntityManager::ID++;
|
static inline void* make_entity_by_class(EntityManager* manager, const Class* kind, float x, float y, float z)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
Assert(kind != NULL);
|
||||||
|
|
||||||
|
Entity* base_ptr = allocate_entity(manager, kind);
|
||||||
|
Assert(base_ptr != NULL);
|
||||||
|
|
||||||
|
base_ptr->ID = g_entity_manager_id++;
|
||||||
|
|
||||||
base_ptr->position.x = x;
|
base_ptr->position.x = x;
|
||||||
base_ptr->position.y = y;
|
base_ptr->position.y = y;
|
||||||
base_ptr->position.z = z;
|
base_ptr->position.z = z;
|
||||||
base_ptr->position.w = 1.0f;
|
base_ptr->position.w = 1.0f;
|
||||||
|
|
||||||
return (EntityType*)base_ptr->derived;
|
return base_ptr->derived;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename EntityType>
|
#define MakeEntity(EntityType, manager_ptr, x, y, z) \
|
||||||
requires EntityConcept<EntityType>
|
((EntityType*)make_entity_by_class((manager_ptr), ClassKind(EntityType), (x), (y), (z)))
|
||||||
[[nodiscard]] EntityType* DownCast(Entity* entity)
|
|
||||||
|
static inline void* down_cast_entity(Entity* entity, const Class* kind)
|
||||||
{
|
{
|
||||||
Assert(entity != nullptr);
|
Assert(entity != NULL);
|
||||||
Assert(IsA<EntityType>(entity));
|
Assert(IsEntityA(entity, kind));
|
||||||
return static_cast<EntityType*>(entity->derived);
|
return entity->derived;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialize(Archive& ar, NonNullPtr<Entity> entity);
|
#define DownCastEntity(EntityType, entity_ptr) ((EntityType*)down_cast_entity((entity_ptr), ClassKind(EntityType)))
|
||||||
|
|
||||||
JULIET_API uint8 get_local_user_id();
|
void serialize_entity(Archive* ar, Entity* entity);
|
||||||
|
|
||||||
JULIET_API String format_entity_id(NonNullPtr<Arena> arena, EntityID id);
|
JULIET_API uint8 get_local_user_id(void);
|
||||||
|
|
||||||
JULIET_API bool parse_entity_id(String str, EntityID& outId);
|
JULIET_API String format_entity_id(Arena* arena, EntityID id);
|
||||||
|
|
||||||
[[nodiscard]] const Class* find_class_by_name(String name);
|
JULIET_API bool8 parse_entity_id(String str, EntityID* outId);
|
||||||
|
|
||||||
[[nodiscard]] const Class* resolve_entity_class(uint8 kind, uint32 crc);
|
const Class* find_class_by_name(String name);
|
||||||
|
|
||||||
|
const Class* resolve_entity_class(uint8 kind, uint32 crc);
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
#include <Entity/EntityManager.h>
|
||||||
|
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
#include <Core/Memory/Utils.h>
|
||||||
|
#include <Data/World.h>
|
||||||
|
#include <Engine/user.h>
|
||||||
|
#include <Entity/Entity.h>
|
||||||
|
#include <Entity/entity_types.h>
|
||||||
|
#include <game.h>
|
||||||
|
#include <Graphics/MeshRenderer.h>
|
||||||
|
|
||||||
|
EntityID g_entity_manager_id = 0;
|
||||||
|
|
||||||
|
void InitEntityManager(World* world)
|
||||||
|
{
|
||||||
|
Assert(world != NULL);
|
||||||
|
|
||||||
|
EntityManager* newManager = ArenaPushStruct(world->WorldArena, EntityManager);
|
||||||
|
newManager->next_local_counter = 1ULL;
|
||||||
|
world->EntityManager = newManager;
|
||||||
|
|
||||||
|
VectorArenaCreate(&newManager->Entities, Entity, world->WorldArena, 100000 JULIET_DEBUG_PARAM("Entities"));
|
||||||
|
|
||||||
|
ArenaParams by_type_params = { .ReserveSize = Kilobytes(1),
|
||||||
|
.CommitSize = Kilobytes(1),
|
||||||
|
.Name = "" JULIET_DEBUG_ONLY(, .DoNotReserveMore = true) };
|
||||||
|
for (uint8 i = 0; i < ENTITY(Count); ++i)
|
||||||
|
{
|
||||||
|
by_type_params.Name = kEntity_type_names[i];
|
||||||
|
newManager->by_type[i].arena = ArenaAllocate(by_type_params);
|
||||||
|
newManager->by_type[i].array = NULL;
|
||||||
|
newManager->by_type[i].count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShutdownEntityManager(void)
|
||||||
|
{
|
||||||
|
EntityManager* manager = GetEntityManager();
|
||||||
|
for (uint8 i = 0; i < ENTITY(Count); ++i)
|
||||||
|
{
|
||||||
|
ArenaRelease(manager->by_type[i].arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector_arena_destroy(&manager->Entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityManager* GetEntityManager(void)
|
||||||
|
{
|
||||||
|
EntityManager* entityManager = GetGameState()->World->EntityManager;
|
||||||
|
Assert(entityManager != NULL);
|
||||||
|
return entityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityID generate_next_entity_id(EntityManager* manager)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
|
||||||
|
UserID user = get_local_user_id();
|
||||||
|
Assert(user != kInvalid_user_id);
|
||||||
|
Assert(manager->next_local_counter != kEntityID_user_id_mask);
|
||||||
|
|
||||||
|
EntityID new_id = make_entity_id(user, manager->next_local_counter);
|
||||||
|
manager->next_local_counter += 1ULL;
|
||||||
|
return new_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityTemplate* RegisterEntity(EntityManager* manager, Entity* base, DerivedType entity)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
Assert(base != NULL);
|
||||||
|
|
||||||
|
base->ID = g_entity_manager_id++;
|
||||||
|
base->derived = entity;
|
||||||
|
|
||||||
|
VectorArenaPushPtr(Entity, &manager->Entities, base);
|
||||||
|
|
||||||
|
EntityTemplate* ptr = (EntityTemplate*)ArenaPushSize(
|
||||||
|
manager->by_type[base->derived_kind->kind].arena, base->derived_kind->size_of, base->derived_kind->alignment,
|
||||||
|
false JULIET_DEBUG_PARAM(kEntity_type_names[base->derived_kind->kind]));
|
||||||
|
MemCopy(ptr, entity, base->derived_kind->size_of);
|
||||||
|
manager->by_type[base->derived_kind->kind].count += 1;
|
||||||
|
|
||||||
|
ptr->base = VectorArenaBack(Entity, &manager->Entities);
|
||||||
|
|
||||||
|
if (manager->by_type[base->derived_kind->kind].array == NULL)
|
||||||
|
{
|
||||||
|
manager->by_type[base->derived_kind->kind].array = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* allocate_entity(EntityManager* manager, const Class* derived_type_class)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
Assert(derived_type_class != NULL);
|
||||||
|
Assert(derived_type_class->kind < ENTITY(Count));
|
||||||
|
Assert(derived_type_class->size_of >= sizeof(EntityTemplate));
|
||||||
|
Assert(derived_type_class->alignment > 0);
|
||||||
|
Assert(derived_type_class->initialize_fct != NULL);
|
||||||
|
|
||||||
|
Entity base_template = { 0 };
|
||||||
|
base_template.derived_kind = derived_type_class;
|
||||||
|
base_template.is_dirty = true;
|
||||||
|
|
||||||
|
VectorArenaPushPtr(Entity, &manager->Entities, &base_template);
|
||||||
|
Entity* base_ptr = VectorArenaBack(Entity, &manager->Entities);
|
||||||
|
Assert(base_ptr != NULL);
|
||||||
|
|
||||||
|
typed_entity_array* typed_array = &manager->by_type[derived_type_class->kind];
|
||||||
|
Assert(typed_array->arena != NULL);
|
||||||
|
|
||||||
|
void* derived = ArenaPushSize(typed_array->arena, derived_type_class->size_of, derived_type_class->alignment,
|
||||||
|
false JULIET_DEBUG_PARAM(kEntity_type_names[derived_type_class->kind]));
|
||||||
|
Assert(derived != NULL);
|
||||||
|
derived_type_class->initialize_fct(derived);
|
||||||
|
|
||||||
|
EntityTemplate* derived_template = (EntityTemplate*)derived;
|
||||||
|
|
||||||
|
base_ptr->derived = derived;
|
||||||
|
derived_template->base = base_ptr;
|
||||||
|
|
||||||
|
if (typed_array->array == NULL)
|
||||||
|
{
|
||||||
|
typed_array->array = derived_template;
|
||||||
|
}
|
||||||
|
typed_array->count += 1;
|
||||||
|
|
||||||
|
return base_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateEntityManager(EntityManager* manager)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
|
||||||
|
// Todo : inert by definition dont move, but this is for test
|
||||||
|
typed_entity_array* by_type = &manager->by_type[ENTITY(Inert)];
|
||||||
|
for (index_t i = 0; i < by_type->count; ++i)
|
||||||
|
{
|
||||||
|
Inert* inert = ((Inert*)by_type->array) + i;
|
||||||
|
if (inert->MeshInstance != indexMax)
|
||||||
|
{
|
||||||
|
Matrix transform =
|
||||||
|
MatrixTranslation(inert->base->position.x, inert->base->position.y, inert->base->position.z);
|
||||||
|
SetMeshInstanceTransform(inert->MeshInstance, &transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* deserialize_entity(Archive* ar, EntityManager* manager)
|
||||||
|
{
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(manager != NULL);
|
||||||
|
Assert(ar->loading);
|
||||||
|
|
||||||
|
String class_name = { 0 };
|
||||||
|
SERIALIZE_STR(ar, Class, &class_name);
|
||||||
|
|
||||||
|
const Class* class_ptr = find_class_by_name(class_name);
|
||||||
|
Assert(class_ptr != NULL);
|
||||||
|
|
||||||
|
Entity* entity_base = allocate_entity(manager, class_ptr);
|
||||||
|
Assert(entity_base != NULL);
|
||||||
|
|
||||||
|
serialize_entity(ar, entity_base);
|
||||||
|
|
||||||
|
if (entity_base->ID >= g_entity_manager_id)
|
||||||
|
{
|
||||||
|
g_entity_manager_id = entity_base->ID + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_base->is_dirty = false;
|
||||||
|
|
||||||
|
return entity_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_local_counter(EntityManager* manager, EntityID entity_id)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
|
||||||
|
uint8 user_id = get_local_user_id();
|
||||||
|
if (get_user_id(entity_id) == user_id)
|
||||||
|
{
|
||||||
|
uint64 counter = get_local_counter(entity_id);
|
||||||
|
if (counter >= manager->next_local_counter)
|
||||||
|
{
|
||||||
|
manager->next_local_counter = counter + 1ULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
#include <Entity/EntityManager.h>
|
|
||||||
|
|
||||||
#include <Core/Common/EnumUtils.h>
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
#include <Data/World.h>
|
|
||||||
#include <Entity/Entity.h>
|
|
||||||
#include <Entity/entity_types.h>
|
|
||||||
#include <game.h>
|
|
||||||
#include <Graphics/MeshRenderer.h>
|
|
||||||
#include "Engine/user.h"
|
|
||||||
|
|
||||||
EntityID EntityManager::ID = 0;
|
|
||||||
|
|
||||||
void InitEntityManager(NonNullPtr<World> world)
|
|
||||||
{
|
|
||||||
EntityManager* newManager = ArenaPushStruct<EntityManager>(world->WorldArena);
|
|
||||||
world->EntityManager = newManager;
|
|
||||||
|
|
||||||
newManager->Entities.Create(world->WorldArena JULIET_DEBUG_PARAM("Entities"));
|
|
||||||
|
|
||||||
ArenaParams by_type_params{ .ReserveSize = Kilobytes(1),
|
|
||||||
.CommitSize = Kilobytes(1),
|
|
||||||
.Name = "" JULIET_DEBUG_ONLY(, .CanReserveMore = false) };
|
|
||||||
for (uint8 i = 0; i < ENTITY(Count); ++i)
|
|
||||||
{
|
|
||||||
by_type_params.Name = kEntity_type_names[i];
|
|
||||||
newManager->by_type[i].arena = ArenaAllocate(by_type_params);
|
|
||||||
newManager->by_type[i].array = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShutdownEntityManager()
|
|
||||||
{
|
|
||||||
auto& manager = GetEntityManager();
|
|
||||||
for (typed_entity_array& type : manager.by_type)
|
|
||||||
{
|
|
||||||
ArenaRelease(type.arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager.Entities.Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityManager& GetEntityManager()
|
|
||||||
{
|
|
||||||
NonNullPtr entityManager = GetGameState()->World->EntityManager;
|
|
||||||
return *entityManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityID generate_next_entity_id(EntityManager& manager)
|
|
||||||
{
|
|
||||||
UserID user = get_local_user_id();
|
|
||||||
Assert(user != kInvalid_user_id);
|
|
||||||
Assert(manager.next_local_counter != kEntityID_user_id_mask);
|
|
||||||
|
|
||||||
EntityID new_id = make_entity_id(user, manager.next_local_counter);
|
|
||||||
manager.next_local_counter += 1ULL;
|
|
||||||
return new_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityTemplate* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity)
|
|
||||||
{
|
|
||||||
base->ID = EntityManager::ID++;
|
|
||||||
base->derived = entity;
|
|
||||||
|
|
||||||
manager.Entities.PushBack(*base);
|
|
||||||
|
|
||||||
auto* ptr = (EntityTemplate*)ArenaPushSize(manager.by_type[base->derived_kind->kind].arena,
|
|
||||||
base->derived_kind->size_of, base->derived_kind->alignment,
|
|
||||||
false JULIET_DEBUG_PARAM(kEntity_type_names[base->derived_kind->kind]));
|
|
||||||
MemCopy(ptr, entity, base->derived_kind->size_of);
|
|
||||||
manager.by_type[base->derived_kind->kind].count += 1;
|
|
||||||
|
|
||||||
ptr->base = manager.Entities.Back();
|
|
||||||
|
|
||||||
if (manager.by_type[base->derived_kind->kind].array == nullptr)
|
|
||||||
{
|
|
||||||
manager.by_type[base->derived_kind->kind].array = ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity* allocate_entity(EntityManager& manager, NonNullPtr<const Class> derived_type_class)
|
|
||||||
{
|
|
||||||
Assert(derived_type_class->kind < ENTITY(Count));
|
|
||||||
Assert(derived_type_class->size_of >= sizeof(EntityTemplate));
|
|
||||||
Assert(derived_type_class->alignment > 0);
|
|
||||||
Assert(derived_type_class->initialize_fct);
|
|
||||||
|
|
||||||
Entity base_template = {};
|
|
||||||
base_template.derived_kind = derived_type_class;
|
|
||||||
base_template.is_dirty = true;
|
|
||||||
|
|
||||||
manager.Entities.PushBack(base_template);
|
|
||||||
Entity* base_ptr = manager.Entities.Back();
|
|
||||||
Assert(base_ptr);
|
|
||||||
|
|
||||||
typed_entity_array& typed_array = manager.by_type[derived_type_class->kind];
|
|
||||||
Assert(typed_array.arena);
|
|
||||||
|
|
||||||
void* derived = ArenaPushSize(typed_array.arena, derived_type_class->size_of, derived_type_class->alignment,
|
|
||||||
false JULIET_DEBUG_PARAM(kEntity_type_names[derived_type_class->kind]));
|
|
||||||
Assert(derived);
|
|
||||||
derived_type_class->initialize_fct(derived);
|
|
||||||
|
|
||||||
auto* derived_template = (EntityTemplate*)derived;
|
|
||||||
|
|
||||||
base_ptr->derived = derived;
|
|
||||||
derived_template->base = base_ptr;
|
|
||||||
|
|
||||||
if (typed_array.array == nullptr)
|
|
||||||
{
|
|
||||||
typed_array.array = derived_template;
|
|
||||||
}
|
|
||||||
typed_array.count += 1;
|
|
||||||
|
|
||||||
return base_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateEntityManager(EntityManager& manager)
|
|
||||||
{
|
|
||||||
// Todo : inert by definition dont move, but this is for test
|
|
||||||
auto& by_type = manager.by_type[ENTITY(Inert)];
|
|
||||||
for (index_t i = 0; i < by_type.count; ++i)
|
|
||||||
{
|
|
||||||
Inert* inert = reinterpret_cast<Inert*>(by_type.array) + i;
|
|
||||||
if (inert->MeshInstance != indexMax)
|
|
||||||
{
|
|
||||||
SetMeshInstanceTransform(inert->MeshInstance,
|
|
||||||
MatrixTranslation(inert->base->position.x, inert->base->position.y,
|
|
||||||
inert->base->position.z));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity* deserialize_entity(Archive& ar, EntityManager& manager)
|
|
||||||
{
|
|
||||||
Assert(ar.loading);
|
|
||||||
|
|
||||||
String class_name;
|
|
||||||
SERIALIZE(ar, Class, class_name);
|
|
||||||
|
|
||||||
NonNullPtr<const Class> class_ptr = find_class_by_name(class_name);
|
|
||||||
|
|
||||||
NonNullPtr<Entity> entity_base = allocate_entity(manager, class_ptr);
|
|
||||||
|
|
||||||
serialize(ar, entity_base);
|
|
||||||
|
|
||||||
if (entity_base->ID >= EntityManager::ID)
|
|
||||||
{
|
|
||||||
EntityManager::ID = entity_base->ID + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity_base->is_dirty = false;
|
|
||||||
|
|
||||||
return entity_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_local_counter(EntityManager& manager, EntityID entity_id)
|
|
||||||
{
|
|
||||||
uint8 user_id = get_local_user_id();
|
|
||||||
if (get_user_id(entity_id) == user_id)
|
|
||||||
{
|
|
||||||
uint64 counter = get_local_counter(entity_id);
|
|
||||||
if (counter >= manager.next_local_counter)
|
|
||||||
{
|
|
||||||
manager.next_local_counter = counter + 1ULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+20
-16
@@ -3,11 +3,13 @@
|
|||||||
#include <Core/Container/Vector.h>
|
#include <Core/Container/Vector.h>
|
||||||
#include <Entity/entity_common.h>
|
#include <Entity/entity_common.h>
|
||||||
|
|
||||||
struct World;
|
typedef struct World World;
|
||||||
struct EntityTemplate;
|
typedef struct EntityTemplate EntityTemplate;
|
||||||
struct Entity;
|
typedef struct Entity Entity;
|
||||||
struct Class;
|
typedef struct Class Class;
|
||||||
|
typedef struct Archive Archive;
|
||||||
|
|
||||||
|
typedef struct typed_entity_array typed_entity_array;
|
||||||
struct typed_entity_array
|
struct typed_entity_array
|
||||||
{
|
{
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
@@ -15,22 +17,24 @@ struct typed_entity_array
|
|||||||
size_t count;
|
size_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct EntityManager EntityManager;
|
||||||
struct EntityManager
|
struct EntityManager
|
||||||
{
|
{
|
||||||
static EntityID ID;
|
uint64 next_local_counter;
|
||||||
uint64 next_local_counter = 1ULL;
|
|
||||||
|
|
||||||
// TODO: Should be a pool
|
// TODO: Should be a pool
|
||||||
VectorArena<Entity, 100'000> Entities;
|
VectorArena Entities;
|
||||||
|
|
||||||
typed_entity_array by_type[ENTITY(Count)];
|
typed_entity_array by_type[Entity_Type_Count];
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitEntityManager(NonNullPtr<World> world);
|
extern EntityID g_entity_manager_id;
|
||||||
void ShutdownEntityManager();
|
|
||||||
EntityManager& GetEntityManager();
|
void InitEntityManager(World* world);
|
||||||
EntityTemplate* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity);
|
void ShutdownEntityManager(void);
|
||||||
[[nodiscard]] Entity* allocate_entity(EntityManager& manager, NonNullPtr<const Class> derived_type_class);
|
EntityManager* GetEntityManager(void);
|
||||||
void UpdateEntityManager(EntityManager& manager);
|
EntityTemplate* RegisterEntity(EntityManager* manager, Entity* base, DerivedType entity);
|
||||||
[[nodiscard]] Entity* deserialize_entity(Archive& archive, EntityManager& manager);
|
Entity* allocate_entity(EntityManager* manager, const Class* derived_type_class);
|
||||||
void update_local_counter(EntityManager& manager, EntityID entity_id);
|
void UpdateEntityManager(EntityManager* manager);
|
||||||
|
Entity* deserialize_entity(Archive* archive, EntityManager* manager);
|
||||||
|
void update_local_counter(EntityManager* manager, EntityID entity_id);
|
||||||
@@ -5,17 +5,16 @@
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#define AS_STR(name) #name
|
#define AS_STR(name) #name
|
||||||
const char* kEntity_type_names[] = {
|
const char* kEntity_type_names[] = {
|
||||||
ENTITY_TYPE_LIST(AS_STR)
|
ENTITY_TYPE_LIST(AS_STR)
|
||||||
"Count"
|
"Count"
|
||||||
};
|
};
|
||||||
#undef AS_STR
|
#undef AS_STR
|
||||||
|
|
||||||
#define AS_CLASS(name) name::kind
|
#define AS_CLASS(name) &class_kind_##name
|
||||||
const Class* kEntity_type_class_ptr[]
|
const Class* kEntity_type_class_ptr[] = {
|
||||||
{
|
|
||||||
ENTITY_TYPE_LIST(AS_CLASS)
|
ENTITY_TYPE_LIST(AS_CLASS)
|
||||||
nullptr
|
NULL
|
||||||
};
|
};
|
||||||
#undef AS_CLASS
|
#undef AS_CLASS
|
||||||
// clang-format on
|
// clang-format on
|
||||||
+26
-24
@@ -1,46 +1,48 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/EnumUtils.h>
|
|
||||||
#include <Engine/Class.h>
|
#include <Engine/Class.h>
|
||||||
|
|
||||||
struct Class;
|
typedef void* DerivedType;
|
||||||
using DerivedType = void*;
|
typedef uint64 EntityID;
|
||||||
using EntityID = uint64_t;
|
|
||||||
|
|
||||||
constexpr uint8 kInvalid_user_id = 0U;
|
#define kInvalid_user_id ((uint8)0U)
|
||||||
constexpr EntityID kInvalid_entity_id = 0ULL;
|
#define kInvalid_entity_id ((EntityID)0ULL)
|
||||||
|
#define kEntityID_user_id_shift ((EntityID)56ULL)
|
||||||
constexpr EntityID kEntityID_user_id_shift = 56ULL;
|
#define kEntityID_user_id_mask ((EntityID)0xFF00000000000000ULL)
|
||||||
constexpr EntityID kEntityID_user_id_mask = 0xFF00'0000'0000'0000ULL;
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#define ENTITY_TYPE_LIST(X) X(Inert),
|
#define ENTITY_TYPE_LIST(X) X(Inert),
|
||||||
|
|
||||||
#define AS_ENUM(name) name
|
typedef uint8 Entity_Type;
|
||||||
enum class Entity_Type : uint8
|
#define AS_ENUM(name) Entity_Type_##name
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
ENTITY_TYPE_LIST(AS_ENUM)
|
ENTITY_TYPE_LIST(AS_ENUM)
|
||||||
Count
|
Entity_Type_Count
|
||||||
};
|
};
|
||||||
#undef AS_ENUM
|
#undef AS_ENUM
|
||||||
|
|
||||||
extern const char* kEntity_type_names[];
|
extern const char* kEntity_type_names[];
|
||||||
extern const Class* kEntity_type_class_ptr[];
|
extern const Class* kEntity_type_class_ptr[];
|
||||||
|
|
||||||
#define ENTITY(kind) ToUnderlying(Entity_Type::kind)
|
#define ENTITY(kind) ((uint8)Entity_Type_##kind)
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
struct Entity;
|
typedef struct Entity Entity;
|
||||||
|
|
||||||
#define DECLARE_ENTITY() \
|
#define DECLARE_ENTITY() Entity* base;
|
||||||
Entity* base; \
|
|
||||||
DECLARE_CLASS()
|
|
||||||
|
|
||||||
#define DEFINE_ENTITY_VERSIONED(entity, version) \
|
#define DEFINE_ENTITY_VERSIONED(entity, version_num) \
|
||||||
constexpr Class entityKind##entity = \
|
const Class class_kind_##entity = { \
|
||||||
MakeClass(ConstString(#entity), (uint8)Entity_Type::entity, (version), &class_kind_Entity, sizeof(entity), \
|
.Name = ConstString(#entity), \
|
||||||
alignof(entity), (&initialize_thunk<entity>), (&serialize_thunk<entity>)); \
|
.kind = (uint8)Entity_Type_##entity, \
|
||||||
Class* entity::kind = const_cast<Class*>(&entityKind##entity);
|
.version = (version_num), \
|
||||||
|
.base_class = &class_kind_Entity, \
|
||||||
|
.initialize_fct = init_##entity, \
|
||||||
|
.serialize_fct = serialize_##entity, \
|
||||||
|
.size_of = sizeof(entity), \
|
||||||
|
.alignment = AlignOf(entity) \
|
||||||
|
};
|
||||||
|
|
||||||
// Note: Needed by every classes see define above
|
// Note: Needed by every entity class (see define above)
|
||||||
extern const Class class_kind_Entity;
|
extern const Class class_kind_Entity;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include <Entity/entity_types.h>
|
||||||
|
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
|
||||||
|
internal void init_Inert(void* payload)
|
||||||
|
{
|
||||||
|
Assert(payload != NULL);
|
||||||
|
Inert* inert = (Inert*)payload;
|
||||||
|
inert->base = NULL;
|
||||||
|
inert->MeshInstance = indexMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void serialize_Inert(Archive* ar, uint16 version, void* payload)
|
||||||
|
{
|
||||||
|
(void)version;
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(payload != NULL);
|
||||||
|
Inert* inert = (Inert*)payload;
|
||||||
|
SERIALIZE_U64(ar, MeshInstance, &inert->MeshInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ENTITY_VERSIONED(Inert, 1)
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#include <Entity/entity_types.h>
|
|
||||||
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
|
|
||||||
DEFINE_ENTITY_VERSIONED(Inert, 1)
|
|
||||||
internal void serialize(Archive& ar, uint16 /*version*/, Inert& inert)
|
|
||||||
{
|
|
||||||
SERIALIZE(ar, MeshInstance, inert.MeshInstance);
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
#include <Entity/entity_common.h>
|
#include <Entity/entity_common.h>
|
||||||
|
|
||||||
|
typedef struct Inert Inert;
|
||||||
struct Inert
|
struct Inert
|
||||||
{
|
{
|
||||||
DECLARE_ENTITY()
|
DECLARE_ENTITY()
|
||||||
|
|
||||||
index_t MeshInstance = indexMax;
|
index_t MeshInstance;
|
||||||
};
|
};
|
||||||
|
DECLARE_CLASS(Inert)
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
#include <UnitTest/WorldUnitTest.h>
|
||||||
|
|
||||||
|
#if JULIET_DEBUG
|
||||||
|
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
#include <Core/HAL/IO/IOStream.h>
|
||||||
|
#include <Core/Logging/LogManager.h>
|
||||||
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
#include <Core/Thread/ThreadContext.h>
|
||||||
|
#include <Data/World.h>
|
||||||
|
#include <Entity/Entity.h>
|
||||||
|
#include <Entity/entity_types.h>
|
||||||
|
#include <game.h>
|
||||||
|
|
||||||
|
internal void TestEntityAllocationAndWiring(void)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestEntityAllocationAndWiring...");
|
||||||
|
|
||||||
|
TempArena tempArena = scratch_begin(NULL, 0);
|
||||||
|
|
||||||
|
GameState* gameState = GetGameState();
|
||||||
|
World testWorld = { 0 };
|
||||||
|
gameState->World = &testWorld;
|
||||||
|
InitWorld(&testWorld, tempArena.Arena);
|
||||||
|
|
||||||
|
InitEntityManager(&testWorld);
|
||||||
|
EntityManager* manager = testWorld.EntityManager;
|
||||||
|
|
||||||
|
// 1. Allocate Inert Entity via allocate_entity
|
||||||
|
Entity* base_entity = allocate_entity(manager, ClassKind(Inert));
|
||||||
|
Assert(base_entity != NULL);
|
||||||
|
Assert(base_entity->ID == 0); // Pure memory allocator leaves ID unassigned (0) until MakeEntity or deserialization
|
||||||
|
base_entity->ID = ++g_entity_manager_id;
|
||||||
|
Assert(base_entity->ID > 0);
|
||||||
|
Assert(base_entity->derived_kind == ClassKind(Inert));
|
||||||
|
Assert(base_entity->derived != NULL);
|
||||||
|
Assert(base_entity->is_dirty == true);
|
||||||
|
|
||||||
|
// 2. Validate mutual back-pointer wiring
|
||||||
|
EntityTemplate* derived = (EntityTemplate*)base_entity->derived;
|
||||||
|
Assert(derived->base == base_entity);
|
||||||
|
|
||||||
|
// 3. DownCast verification
|
||||||
|
Inert* inert = DownCastEntity(Inert, base_entity);
|
||||||
|
Assert(inert != NULL);
|
||||||
|
Assert(inert->base == base_entity);
|
||||||
|
|
||||||
|
// 4. Validate typed array tracking
|
||||||
|
typed_entity_array* inert_array = &manager->by_type[ENTITY(Inert)];
|
||||||
|
Assert(inert_array->count == 1);
|
||||||
|
Assert(inert_array->array == derived);
|
||||||
|
|
||||||
|
ShutdownEntityManager();
|
||||||
|
ShutdownWorld(&testWorld);
|
||||||
|
|
||||||
|
gameState->World = NULL;
|
||||||
|
|
||||||
|
scratch_end(tempArena);
|
||||||
|
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestEntityAllocationAndWiring");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void TestInPlaceDeserialization(void)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestInPlaceDeserialization...");
|
||||||
|
TempArena tempArena = scratch_begin(NULL, 0);
|
||||||
|
|
||||||
|
GameState* gameState = GetGameState();
|
||||||
|
World testWorld = { 0 };
|
||||||
|
gameState->World = &testWorld;
|
||||||
|
InitWorld(&testWorld, tempArena.Arena);
|
||||||
|
|
||||||
|
InitEntityManager(&testWorld);
|
||||||
|
EntityManager* manager = testWorld.EntityManager;
|
||||||
|
// 1. In-memory .jasset text fixture (no streams or files needed)
|
||||||
|
String asset_content = ConstString("; Class\n"
|
||||||
|
"Inert\n"
|
||||||
|
"; version\n"
|
||||||
|
"1\n"
|
||||||
|
"; class_version\n"
|
||||||
|
"1\n"
|
||||||
|
"; id\n"
|
||||||
|
"42\n"
|
||||||
|
"; position\n"
|
||||||
|
"12.5 -44.0 108.2 1.0\n"
|
||||||
|
"; MeshInstance\n"
|
||||||
|
"42\n");
|
||||||
|
ByteBuffer buffer = { .Data = (Byte*)asset_content.Str, .Size = asset_content.Size };
|
||||||
|
// 2. Tokenize into Archive
|
||||||
|
Archive load_ar = { 0 };
|
||||||
|
load_ar.arena = tempArena.Arena;
|
||||||
|
load_ar.loading = true;
|
||||||
|
load_ar.base = tokenize_archive(tempArena.Arena, buffer);
|
||||||
|
// 3. Deserialize in-place
|
||||||
|
Entity* loaded_base = deserialize_entity(&load_ar, manager);
|
||||||
|
// 4. Verify in-place allocations and values
|
||||||
|
Assert(loaded_base != NULL);
|
||||||
|
Assert(loaded_base->ID == 42);
|
||||||
|
Assert(g_entity_manager_id > 42); // Generator counter advanced past loaded ID
|
||||||
|
Assert(loaded_base->position.x == 12.5f);
|
||||||
|
Assert(loaded_base->position.y == -44.0f);
|
||||||
|
Assert(loaded_base->position.z == 108.2f);
|
||||||
|
Assert(loaded_base->is_dirty == false);
|
||||||
|
Inert* loaded_inert = DownCastEntity(Inert, loaded_base);
|
||||||
|
Assert(loaded_inert != NULL);
|
||||||
|
Assert(loaded_inert->base == loaded_base);
|
||||||
|
Assert(loaded_inert->MeshInstance == 42);
|
||||||
|
ShutdownEntityManager();
|
||||||
|
ShutdownWorld(&testWorld);
|
||||||
|
|
||||||
|
gameState->World = NULL;
|
||||||
|
|
||||||
|
scratch_end(tempArena);
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestInPlaceDeserialization");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void TestDirtyTrackingLifecycle(void)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestDirtyTrackingLifecycle...");
|
||||||
|
|
||||||
|
TempArena tempArena = scratch_begin(NULL, 0);
|
||||||
|
|
||||||
|
GameState* gameState = GetGameState();
|
||||||
|
World testWorld = { 0 };
|
||||||
|
gameState->World = &testWorld;
|
||||||
|
InitWorld(&testWorld, tempArena.Arena);
|
||||||
|
|
||||||
|
InitEntityManager(&testWorld);
|
||||||
|
EntityManager* manager = testWorld.EntityManager;
|
||||||
|
|
||||||
|
Entity* entity = allocate_entity(manager, ClassKind(Inert));
|
||||||
|
Assert(entity->is_dirty == true);
|
||||||
|
|
||||||
|
// TODO : proper save and mutation
|
||||||
|
// Simulate save
|
||||||
|
entity->is_dirty = false;
|
||||||
|
Assert(entity->is_dirty == false);
|
||||||
|
|
||||||
|
// Simulate mutation
|
||||||
|
entity->position.x += 1.0f;
|
||||||
|
entity->is_dirty = true;
|
||||||
|
Assert(entity->is_dirty == true);
|
||||||
|
|
||||||
|
ShutdownEntityManager();
|
||||||
|
ShutdownWorld(&testWorld);
|
||||||
|
|
||||||
|
gameState->World = NULL;
|
||||||
|
|
||||||
|
scratch_end(tempArena);
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestDirtyTrackingLifecycle");
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitTest_WorldUnitTest(void)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "==================================================");
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "Starting Entity Allocation & Lifecycle Unit Tests");
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "==================================================");
|
||||||
|
|
||||||
|
TestEntityAllocationAndWiring();
|
||||||
|
TestInPlaceDeserialization();
|
||||||
|
// TestSwapAndPopPointerFixup(); // Deferred to Entity_Removal_Brainstorm.md
|
||||||
|
TestDirtyTrackingLifecycle();
|
||||||
|
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "==================================================");
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "All Entity Lifecycle Unit Tests PASSED Successfully");
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "==================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
#include <UnitTest/WorldUnitTest.h>
|
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
#include <Core/HAL/IO/IOStream.h>
|
|
||||||
#include <Core/Logging/LogManager.h>
|
|
||||||
#include <Core/Logging/LogTypes.h>
|
|
||||||
#include <Core/Memory/MemoryArena.h>
|
|
||||||
#include <Core/Thread/ThreadContext.h>
|
|
||||||
#include <Data/World.h>
|
|
||||||
#include <Entity/entity_types.h>
|
|
||||||
#include <game.h>
|
|
||||||
|
|
||||||
namespace UnitTest
|
|
||||||
{
|
|
||||||
internal void TestEntityAllocationAndWiring()
|
|
||||||
{
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestEntityAllocationAndWiring...");
|
|
||||||
|
|
||||||
TempArena tempArena = scratch_begin(nullptr, 0);
|
|
||||||
|
|
||||||
GameState* gameState = GetGameState();
|
|
||||||
World testWorld{};
|
|
||||||
gameState->World = &testWorld;
|
|
||||||
InitWorld(&testWorld, tempArena.Arena);
|
|
||||||
|
|
||||||
InitEntityManager(&testWorld);
|
|
||||||
EntityManager& manager = *testWorld.EntityManager;
|
|
||||||
|
|
||||||
// 1. Allocate Inert Entity via AllocateEntity
|
|
||||||
Entity* base_entity = allocate_entity(manager, Inert::kind);
|
|
||||||
Assert(base_entity != nullptr);
|
|
||||||
Assert(base_entity->ID == 0); // Pure memory allocator leaves ID unassigned (0) until MakeEntity or deserialization
|
|
||||||
base_entity->ID = ++EntityManager::ID;
|
|
||||||
Assert(base_entity->ID > 0);
|
|
||||||
Assert(base_entity->derived_kind == Inert::kind);
|
|
||||||
Assert(base_entity->derived != nullptr);
|
|
||||||
Assert(base_entity->is_dirty == true);
|
|
||||||
|
|
||||||
// 2. Validate mutual back-pointer wiring
|
|
||||||
auto* derived = reinterpret_cast<EntityTemplate*>(base_entity->derived);
|
|
||||||
Assert(derived->base == base_entity);
|
|
||||||
|
|
||||||
// 3. DownCast verification
|
|
||||||
Inert* inert = DownCast<Inert>(base_entity);
|
|
||||||
Assert(inert != nullptr);
|
|
||||||
Assert(inert->base == base_entity);
|
|
||||||
|
|
||||||
// 4. Validate typed array tracking
|
|
||||||
typed_entity_array& inert_array = manager.by_type[ENTITY(Inert)];
|
|
||||||
Assert(inert_array.count == 1);
|
|
||||||
Assert(inert_array.array == derived);
|
|
||||||
|
|
||||||
ShutdownEntityManager();
|
|
||||||
ShutdownWorld(&testWorld);
|
|
||||||
|
|
||||||
gameState->World = nullptr;
|
|
||||||
|
|
||||||
scratch_end(tempArena);
|
|
||||||
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestEntityAllocationAndWiring");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void TestInPlaceDeserialization()
|
|
||||||
{
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestInPlaceDeserialization...");
|
|
||||||
TempArena tempArena = scratch_begin(nullptr, 0);
|
|
||||||
|
|
||||||
GameState* gameState = GetGameState();
|
|
||||||
World testWorld{};
|
|
||||||
gameState->World = &testWorld;
|
|
||||||
InitWorld(&testWorld, tempArena.Arena);
|
|
||||||
|
|
||||||
InitEntityManager(&testWorld);
|
|
||||||
EntityManager& manager = *testWorld.EntityManager;
|
|
||||||
// 1. In-memory .jasset text fixture (no streams or files needed)
|
|
||||||
String asset_content = ConstString("; Class\n"
|
|
||||||
"Inert\n"
|
|
||||||
"; version\n"
|
|
||||||
"1\n"
|
|
||||||
"; class_version\n"
|
|
||||||
"1\n"
|
|
||||||
"; id\n"
|
|
||||||
"42\n"
|
|
||||||
"; position\n"
|
|
||||||
"12.5 -44.0 108.2 1.0\n"
|
|
||||||
"; MeshInstance\n"
|
|
||||||
"42\n");
|
|
||||||
ByteBuffer buffer = { .Data = reinterpret_cast<Byte*>(asset_content.Str), .Size = asset_content.Size };
|
|
||||||
// 2. Tokenize into Archive
|
|
||||||
Archive load_ar = {};
|
|
||||||
load_ar.arena = tempArena.Arena;
|
|
||||||
load_ar.loading = true;
|
|
||||||
load_ar.base = tokenize_archive(tempArena.Arena, buffer);
|
|
||||||
// 3. Deserialize in-place
|
|
||||||
Entity* loaded_base = deserialize_entity(load_ar, manager);
|
|
||||||
// 4. Verify in-place allocations and values
|
|
||||||
Assert(loaded_base != nullptr);
|
|
||||||
Assert(loaded_base->ID == 42);
|
|
||||||
Assert(EntityManager::ID > 42); // Generator counter advanced past loaded ID
|
|
||||||
Assert(loaded_base->position.x == 12.5f);
|
|
||||||
Assert(loaded_base->position.y == -44.0f);
|
|
||||||
Assert(loaded_base->position.z == 108.2f);
|
|
||||||
Assert(loaded_base->is_dirty == false);
|
|
||||||
Inert* loaded_inert = DownCast<Inert>(loaded_base);
|
|
||||||
Assert(loaded_inert != nullptr);
|
|
||||||
Assert(loaded_inert->base == loaded_base);
|
|
||||||
Assert(loaded_inert->MeshInstance == 42);
|
|
||||||
ShutdownEntityManager();
|
|
||||||
ShutdownWorld(&testWorld);
|
|
||||||
|
|
||||||
gameState->World = nullptr;
|
|
||||||
|
|
||||||
scratch_end(tempArena);
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestInPlaceDeserialization");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void TestDirtyTrackingLifecycle()
|
|
||||||
{
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestDirtyTrackingLifecycle...");
|
|
||||||
|
|
||||||
TempArena tempArena = scratch_begin(nullptr, 0);
|
|
||||||
|
|
||||||
GameState* gameState = GetGameState();
|
|
||||||
World testWorld{};
|
|
||||||
gameState->World = &testWorld;
|
|
||||||
InitWorld(&testWorld, tempArena.Arena);
|
|
||||||
|
|
||||||
InitEntityManager(&testWorld);
|
|
||||||
EntityManager& manager = *testWorld.EntityManager;
|
|
||||||
|
|
||||||
Entity* entity = allocate_entity(manager, Inert::kind);
|
|
||||||
Assert(entity->is_dirty == true);
|
|
||||||
|
|
||||||
// TODO : proper save and mutation
|
|
||||||
// Simulate save
|
|
||||||
entity->is_dirty = false;
|
|
||||||
Assert(entity->is_dirty == false);
|
|
||||||
|
|
||||||
// Simulate mutation
|
|
||||||
entity->position.x += 1.0f;
|
|
||||||
entity->is_dirty = true;
|
|
||||||
Assert(entity->is_dirty == true);
|
|
||||||
|
|
||||||
ShutdownEntityManager();
|
|
||||||
ShutdownWorld(&testWorld);
|
|
||||||
|
|
||||||
gameState->World = nullptr;
|
|
||||||
|
|
||||||
scratch_end(tempArena);
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestDirtyTrackingLifecycle");
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldUnitTest()
|
|
||||||
{
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "==================================================");
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "Starting Entity Allocation & Lifecycle Unit Tests");
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "==================================================");
|
|
||||||
|
|
||||||
TestEntityAllocationAndWiring();
|
|
||||||
TestInPlaceDeserialization();
|
|
||||||
// TestSwapAndPopPointerFixup(); // Deferred to Entity_Removal_Brainstorm.md
|
|
||||||
TestDirtyTrackingLifecycle();
|
|
||||||
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "==================================================");
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "All Entity Lifecycle Unit Tests PASSED Successfully");
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "==================================================");
|
|
||||||
}
|
|
||||||
} // namespace UnitTest
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
|
|
||||||
namespace UnitTest
|
void UnitTest_WorldUnitTest(void);
|
||||||
{
|
|
||||||
void WorldUnitTest();
|
|
||||||
} // namespace UnitTest
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+48
-42
@@ -13,28 +13,26 @@
|
|||||||
#include <Entity/EntityManager.h>
|
#include <Entity/EntityManager.h>
|
||||||
#include <Graphics/Camera.h>
|
#include <Graphics/Camera.h>
|
||||||
#include <Graphics/MeshRenderer.h>
|
#include <Graphics/MeshRenderer.h>
|
||||||
#include <imgui.h>
|
#include <dcimgui.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
#include <Debug/DebugTopBar.h>
|
#include <Debug/DebugTopBar.h>
|
||||||
#include <UnitTest/WorldUnitTest.h>
|
#include <UnitTest/WorldUnitTest.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace
|
global GameState* gGameState = NULL;
|
||||||
{
|
|
||||||
GameState* gGameState = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameState* GetGameState()
|
GameState* GetGameState(void)
|
||||||
{
|
{
|
||||||
return gGameState;
|
return gGameState;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JULIET_API void __cdecl GameShutdown()
|
JULIET_API void __cdecl GameShutdown(void)
|
||||||
{
|
{
|
||||||
printf("Shutting down game...\n");
|
printf("Shutting down game...\n");
|
||||||
|
|
||||||
if (gGameState && gGameState->World)
|
if (gGameState != NULL && gGameState->World != NULL)
|
||||||
{
|
{
|
||||||
ShutdownWorld(gGameState->World);
|
ShutdownWorld(gGameState->World);
|
||||||
}
|
}
|
||||||
@@ -42,47 +40,55 @@ extern "C" JULIET_API void __cdecl GameShutdown()
|
|||||||
ShutdownEntityManager();
|
ShutdownEntityManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JULIET_API void __cdecl GameUpdate(GameData* params, [[maybe_unused]] float deltaTime)
|
JULIET_API void __cdecl GameUpdate(GameData* params, float deltaTime)
|
||||||
{
|
{
|
||||||
|
Assert(params != NULL);
|
||||||
|
|
||||||
gGameState = params->GameState;
|
gGameState = params->GameState;
|
||||||
if (!gGameState)
|
if (gGameState == NULL)
|
||||||
{
|
{
|
||||||
Arena* gameStateArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "Game Total Arena" });
|
ArenaParams gameStateParams = { .ReserveSize = Megabytes(1), .Name = "Game Total Arena" };
|
||||||
auto* gameState = ArenaPushStruct<GameState>(gameStateArena);
|
Arena* gameStateArena = ArenaAllocate(gameStateParams);
|
||||||
|
GameState* gameState = ArenaPushStruct(gameStateArena, GameState);
|
||||||
gGameState = params->GameState = gameState;
|
gGameState = params->GameState = gameState;
|
||||||
gameState->TotalArena = gameStateArena;
|
gameState->TotalArena = gameStateArena;
|
||||||
|
gameState->Mode = GameMode_Editor;
|
||||||
|
|
||||||
gameState->TotalTime = 0.0f;
|
gameState->TotalTime = 0.0f;
|
||||||
gameState->Score = 0;
|
gameState->Score = 0;
|
||||||
|
|
||||||
printf("Game Arena Allocated: %p\n", static_cast<void*>(gameState));
|
printf("Game Arena Allocated: %p\n", (void*)gameState);
|
||||||
|
|
||||||
// Reserve cameras. Lets go with 4 for now
|
// Reserve cameras. Lets go with 4 for now
|
||||||
ReserveCamera(4);
|
ReserveCamera(4);
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
UnitTest::WorldUnitTest();
|
UnitTest_WorldUnitTest();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Bootstrap world
|
// Bootstrap world
|
||||||
auto* worldArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "World Arena" });
|
ArenaParams worldParams = { .ReserveSize = Megabytes(1), .Name = "World Arena" };
|
||||||
World* world = ArenaPushStruct<World>(worldArena JULIET_DEBUG_PARAM("World"));
|
Arena* worldArena = ArenaAllocate(worldParams);
|
||||||
gameState->World = world;
|
World* world = ArenaPushStructTag(worldArena, World, "World");
|
||||||
|
gameState->World = world;
|
||||||
InitWorld(gameState->World, worldArena);
|
InitWorld(gameState->World, worldArena);
|
||||||
|
|
||||||
// Entity Use case
|
// Entity Use case
|
||||||
InitEntityManager(gameState->World);
|
InitEntityManager(gameState->World);
|
||||||
auto& manager = GetEntityManager();
|
EntityManager* manager = GetEntityManager();
|
||||||
|
|
||||||
NonNullPtr mesh = MakeEntity<Inert>(manager, 1.f, 2.f, 0.f);
|
Inert* mesh = MakeEntity(Inert, manager, 1.f, 2.f, 0.f);
|
||||||
|
Assert(mesh != NULL);
|
||||||
|
|
||||||
MeshAssetID cubeAsset = GetCubePrimitiveMeshAssetID();
|
MeshAssetID cubeAsset = GetCubePrimitiveMeshAssetID();
|
||||||
MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, MatrixIdentity());
|
Matrix identity = MatrixIdentity();
|
||||||
|
MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, &identity);
|
||||||
mesh->MeshInstance = meshInst;
|
mesh->MeshInstance = meshInst;
|
||||||
|
|
||||||
NonNullPtr mesh2 = MakeEntity<Inert>(manager, 4.f, 0.f, 2.f);
|
Inert* mesh2 = MakeEntity(Inert, manager, 4.f, 0.f, 2.f);
|
||||||
|
Assert(mesh2 != NULL);
|
||||||
|
|
||||||
MeshInstanceID meshInst2 = CreateMeshInstance(cubeAsset, 0, MatrixIdentity());
|
MeshInstanceID meshInst2 = CreateMeshInstance(cubeAsset, 0, &identity);
|
||||||
mesh2->MeshInstance = meshInst2;
|
mesh2->MeshInstance = meshInst2;
|
||||||
|
|
||||||
// Summer at 2pm lighting
|
// Summer at 2pm lighting
|
||||||
@@ -97,64 +103,64 @@ extern "C" JULIET_API void __cdecl GameUpdate(GameData* params, [[maybe_unused]]
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
GameMode previousFrameMode = gGameState->Mode;
|
GameMode previousFrameMode = gGameState->Mode;
|
||||||
if (IsKeyPressed(ScanCode::F1))
|
if (IsKeyPressed(ScanCode_F1))
|
||||||
{
|
{
|
||||||
if (previousFrameMode == GameMode::Play)
|
if (previousFrameMode == GameMode_Play)
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Debug;
|
gGameState->Mode = GameMode_Debug;
|
||||||
}
|
}
|
||||||
else if (previousFrameMode == GameMode::Debug)
|
else if (previousFrameMode == GameMode_Debug)
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Play;
|
gGameState->Mode = GameMode_Play;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gGameState->Mode == GameMode::Editor)
|
if (gGameState->Mode == GameMode_Editor)
|
||||||
{
|
{
|
||||||
if (IsKeyPressed(ScanCode::F5))
|
if (IsKeyPressed(ScanCode_F5))
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Play;
|
gGameState->Mode = GameMode_Play;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JULIET_EDITOR
|
#if JULIET_EDITOR
|
||||||
RenderWorldEditorUI(*gGameState->World);
|
RenderWorldEditorUI(gGameState->World);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gGameState->Mode == GameMode::Play)
|
if (gGameState->Mode == GameMode_Play)
|
||||||
{
|
{
|
||||||
if (IsKeyPressed(ScanCode::Escape))
|
if (IsKeyPressed(ScanCode_Escape))
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Editor;
|
gGameState->Mode = GameMode_Editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update game
|
// update game
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& manager = GetEntityManager();
|
EntityManager* manager = GetEntityManager();
|
||||||
UpdateEntityManager(manager);
|
UpdateEntityManager(manager);
|
||||||
|
|
||||||
if (gGameState->Mode == GameMode::Debug)
|
if (gGameState->Mode == GameMode_Debug)
|
||||||
{
|
{
|
||||||
if (previousFrameMode == GameMode::Play)
|
if (previousFrameMode == GameMode_Play)
|
||||||
{
|
{
|
||||||
ActivateDebugController();
|
ActivateDebugController();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsKeyPressed(ScanCode::Escape))
|
if (IsKeyPressed(ScanCode_Escape))
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Editor;
|
gGameState->Mode = GameMode_Editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateDebugController(deltaTime);
|
UpdateDebugController(deltaTime);
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
ImGui::Begin("Debug");
|
ImGui_Begin("Debug", NULL, ImGuiWindowFlags_None);
|
||||||
RenderImGuiDebugController(deltaTime);
|
RenderImGuiDebugController(deltaTime);
|
||||||
ImGui::End();
|
ImGui_End();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (gGameState->Mode != GameMode::Debug && previousFrameMode == GameMode::Debug)
|
if (gGameState->Mode != GameMode_Debug && previousFrameMode == GameMode_Debug)
|
||||||
{
|
{
|
||||||
DeactivateDebugController();
|
DeactivateDebugController();
|
||||||
}
|
}
|
||||||
+13
-11
@@ -3,25 +3,27 @@
|
|||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
#include <Data/World.h>
|
#include <Data/World.h>
|
||||||
|
|
||||||
struct EntityManager;
|
typedef struct EntityManager EntityManager;
|
||||||
|
|
||||||
enum class GameMode
|
typedef uint32 GameMode;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Editor,
|
GameMode_Editor = 0,
|
||||||
Play,
|
GameMode_Play,
|
||||||
Debug
|
GameMode_Debug
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct GameState GameState;
|
||||||
struct GameState
|
struct GameState
|
||||||
{
|
{
|
||||||
Arena* TotalArena = nullptr;
|
Arena* TotalArena;
|
||||||
|
|
||||||
World* World = nullptr;
|
World* World;
|
||||||
|
|
||||||
GameMode Mode = GameMode::Editor;
|
GameMode Mode;
|
||||||
|
|
||||||
float TotalTime = 0.0f;
|
float TotalTime;
|
||||||
int Score = 0;
|
int Score;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] extern GameState* GetGameState();
|
extern GameState* GetGameState(void);
|
||||||
@@ -1,658 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="src">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Application">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Common">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Container">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Display">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Display\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\DynLib">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\DynLib\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Event">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Filesystem">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Filesystem\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\IO">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\IO\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\OS">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\OS\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HotReload">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HotReload\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\ImGui">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Logging">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Math">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Memory">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Networking">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Networking\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Engine">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Engine\Debug">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Graphics">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Graphics\D3D12">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Graphics\D3D12\AgilitySDK">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Graphics\D3D12\AgilitySDK\d3dx12">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\UnitTest">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\UnitTest\Container">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Application">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Common">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Container">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Display">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\DynLib">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Event">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Filesystem">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\IO">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Keyboard">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Mouse">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\OS">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HotReload">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\ImGui">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Logging">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Math">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Memory">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Networking">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Thread">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Engine">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Engine\Debug">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Graphics">
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="src\Core\Application\ApplicationManager.cpp">
|
|
||||||
<Filter>src\Core\Application</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Common\CoreUtils.cpp">
|
|
||||||
<Filter>src\Core\Common</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Common\String.cpp">
|
|
||||||
<Filter>src\Core\Common</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Container\Vector.cpp">
|
|
||||||
<Filter>src\Core\Container</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Display\Display.cpp">
|
|
||||||
<Filter>src\Core\HAL\Display</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayDevice.cpp">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.cpp">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32Window.cpp">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\DynLib\Win32\DynamicLibrary.cpp">
|
|
||||||
<Filter>src\Core\HAL\DynLib\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\Keyboard.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\KeyboardMapping.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\Mouse.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\SystemEvent.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\WindowEvent.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Filesystem\Filesystem.cpp">
|
|
||||||
<Filter>src\Core\HAL\Filesystem</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Filesystem\Win32\Win32Filesystem.cpp">
|
|
||||||
<Filter>src\Core\HAL\Filesystem\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\IO\IOStream.cpp">
|
|
||||||
<Filter>src\Core\HAL\IO</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\IO\Win32\Win32IOStream.cpp">
|
|
||||||
<Filter>src\Core\HAL\IO\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\OS\OS.cpp">
|
|
||||||
<Filter>src\Core\HAL\OS</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\OS\Win32\Win32OS.cpp">
|
|
||||||
<Filter>src\Core\HAL\OS\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HotReload\HotReload.cpp">
|
|
||||||
<Filter>src\Core\HotReload</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HotReload\Win32\Win32HotReload.cpp">
|
|
||||||
<Filter>src\Core\HotReload\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\ImGui\ImGuiService.cpp">
|
|
||||||
<Filter>src\Core\ImGui</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\ImGui\ImGuiTests.cpp">
|
|
||||||
<Filter>src\Core\ImGui</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Juliet.cpp">
|
|
||||||
<Filter>src\Core</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Logging\LogManager.cpp">
|
|
||||||
<Filter>src\Core\Logging</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Math\MathRound.cpp">
|
|
||||||
<Filter>src\Core\Math</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\Allocator.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\MemoryArena.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\MemoryArenaDebug.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\MemoryArenaTests.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\ScratchArena.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\NetworkPacket.cpp">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\Socket.cpp">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\TcpListener.cpp">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\TcpSocket.cpp">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp">
|
|
||||||
<Filter>src\Core\Networking\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\PCH.cpp">
|
|
||||||
<Filter>src\Core</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Engine\Debug\MemoryDebugger.cpp">
|
|
||||||
<Filter>src\Engine\Debug</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Engine\Engine.cpp">
|
|
||||||
<Filter>src\Engine</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_property_format_table.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Buffer.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12CommandList.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Common.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12DescriptorHeap.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12GraphicsDevice.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12GraphicsPipeline.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12InternalTests.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12RenderPass.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Shader.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12SwapChain.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Synchronization.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Texture.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Utils.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\DebugDisplayRenderer.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\Graphics.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\ImGuiRenderer.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\Mesh.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\MeshRenderer.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\SkyboxRenderer.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\UnitTest\Container\VectorUnitTest.cpp">
|
|
||||||
<Filter>src\UnitTest\Container</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\UnitTest\RunUnitTests.cpp">
|
|
||||||
<Filter>src\UnitTest</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClInclude Include="include\Core\Application\ApplicationManager.h">
|
|
||||||
<Filter>include\Core\Application</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Application\IApplication.h">
|
|
||||||
<Filter>include\Core\Application</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\CoreTypes.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\CoreUtils.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\CRC32.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\EnumUtils.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\NonNullPtr.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\String.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Container\Vector.h">
|
|
||||||
<Filter>include\Core\Container</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Display\Display.h">
|
|
||||||
<Filter>include\Core\HAL\Display</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\DynLib\DynamicLibrary.h">
|
|
||||||
<Filter>include\Core\HAL\DynLib</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Event\SystemEvent.h">
|
|
||||||
<Filter>include\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Filesystem\Filesystem.h">
|
|
||||||
<Filter>include\Core\HAL\Filesystem</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\IO\IOStream.h">
|
|
||||||
<Filter>include\Core\HAL\IO</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Keyboard\Keyboard.h">
|
|
||||||
<Filter>include\Core\HAL\Keyboard</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Keyboard\KeyCode.h">
|
|
||||||
<Filter>include\Core\HAL\Keyboard</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Keyboard\ScanCode.h">
|
|
||||||
<Filter>include\Core\HAL\Keyboard</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Mouse\Mouse.h">
|
|
||||||
<Filter>include\Core\HAL\Mouse</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\OS\OS.h">
|
|
||||||
<Filter>include\Core\HAL\OS</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HotReload\HotReload.h">
|
|
||||||
<Filter>include\Core\HotReload</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\ImGui\ImGuiService.h">
|
|
||||||
<Filter>include\Core\ImGui</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\ImGui\ImGuiTests.h">
|
|
||||||
<Filter>include\Core\ImGui</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\JulietInit.h">
|
|
||||||
<Filter>include\Core</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Logging\LogManager.h">
|
|
||||||
<Filter>include\Core\Logging</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Logging\LogTypes.h">
|
|
||||||
<Filter>include\Core\Logging</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Main.h">
|
|
||||||
<Filter>include\Core</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Math\MathUtils.h">
|
|
||||||
<Filter>include\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Math\Matrix.h">
|
|
||||||
<Filter>include\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Math\Shape.h">
|
|
||||||
<Filter>include\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Math\Vector.h">
|
|
||||||
<Filter>include\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\Allocator.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\MemoryArena.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\MemoryArenaDebug.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\ScratchArena.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\Utils.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\IPAddress.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\NetworkPacket.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\Socket.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\SocketHandle.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\TcpListener.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\TcpSocket.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\PCH.h">
|
|
||||||
<Filter>include\Core</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Thread\Mutex.h">
|
|
||||||
<Filter>include\Core\Thread</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Thread\Thread.h">
|
|
||||||
<Filter>include\Core\Thread</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Engine\Class.h">
|
|
||||||
<Filter>include\Engine</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Engine\Debug\MemoryDebugger.h">
|
|
||||||
<Filter>include\Engine\Debug</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Engine\Engine.h">
|
|
||||||
<Filter>include\Engine</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Camera.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Colors.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\DebugDisplay.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Graphics.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\GraphicsBuffer.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\GraphicsConfig.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\GraphicsPipeline.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\ImGuiRenderer.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Lighting.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Mesh.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\MeshRenderer.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\PushConstants.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\RenderPass.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Shader.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\SkyboxRenderer.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Texture.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\VertexData.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Juliet.h">
|
|
||||||
<Filter>include</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\DisplayDevice.h">
|
|
||||||
<Filter>src\Core\HAL\Display</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\Display_Private.h">
|
|
||||||
<Filter>src\Core\HAL\Display</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.h">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\Win32\Win32Window.h">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\Window.h">
|
|
||||||
<Filter>src\Core\HAL\Display</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\KeyboardMapping.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\Keyboard_Private.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\Mouse_Private.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\Win32ScanCode.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Platform.h">
|
|
||||||
<Filter>src\Core\HAL\Filesystem</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Private.h">
|
|
||||||
<Filter>src\Core\HAL\Filesystem</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\IO\IOStream_Private.h">
|
|
||||||
<Filter>src\Core\HAL\IO</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\OS\OS_Private.h">
|
|
||||||
<Filter>src\Core\HAL\OS</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Win32.h">
|
|
||||||
<Filter>src\Core\HAL</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\Math\Math_Private.h">
|
|
||||||
<Filter>src\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12compatibility.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12sdklayers.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12shader.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12video.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dcommon.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_barriers.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_check_feature_support.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_core.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_default.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_pipeline_state_stream.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_property_format_table.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_render_pass.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_resource_helpers.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_root_signature.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_state_object.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\dxgiformat.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Buffer.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12CommandList.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Common.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12DescriptorHeap.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12GraphicsDevice.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12GraphicsPipeline.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Includes.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12InternalTests.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12RenderPass.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Shader.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12SwapChain.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Synchronization.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Texture.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Utils.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\GraphicsDevice.h">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\UnitTest\VectorTestHelper.h">
|
|
||||||
<Filter>src\UnitTest</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\D3D12TokenizedProgramFormat.hpp">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// =============================================================================
|
||||||
|
// Safe Casts
|
||||||
|
|
||||||
|
internal uint16 safe_cast_uint16(uint32 val)
|
||||||
|
{
|
||||||
|
AssertAlways(val <= max_uint16);
|
||||||
|
uint16 result = (uint16)val;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint32 safe_cast_uint32(uint64 val)
|
||||||
|
{
|
||||||
|
AssertAlways(val <= max_uint32);
|
||||||
|
uint32 result = (uint32)val;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal int32 safe_cast_int32(int64 val)
|
||||||
|
{
|
||||||
|
AssertAlways(val <= max_int32);
|
||||||
|
int32 result = (int32)val;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Third party includes
|
||||||
|
|
||||||
|
#define STB_SPRINTF_IMPLEMENTATION
|
||||||
|
#define STB_SPRINTF_STATIC
|
||||||
|
#include "external/stb_sprintf/stb_sprintf.h"
|
||||||
@@ -0,0 +1,299 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Third party includes
|
||||||
|
|
||||||
|
#define STB_SPRINTF_DECORATE(name) juliet_##name
|
||||||
|
#define STB_SPRINTF_STATIC
|
||||||
|
#include "external/stb_sprintf/stb_sprintf.h"
|
||||||
|
|
||||||
|
#define internal static
|
||||||
|
#define global static
|
||||||
|
#define local_persist static
|
||||||
|
|
||||||
|
#if (COMPILER_CLANG && OS_WINDOWS) || COMPILER_MSVC
|
||||||
|
# pragma section(".rdata$", read)
|
||||||
|
# define read_only __declspec(allocate(".rdata$"))
|
||||||
|
#elif (COMPILER_CLANG && OS_LINUX)
|
||||||
|
# define read_only __attribute__((section(".rodata")))
|
||||||
|
#else
|
||||||
|
// Note: not possible with GCC
|
||||||
|
# define read_only
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if COMPILER_CLANG || COMPILER_GCC
|
||||||
|
# define thread_static __thread
|
||||||
|
#elif COMPILER_MSVC
|
||||||
|
# define thread_static __declspec(thread)
|
||||||
|
#else
|
||||||
|
# error thread_static not defined for this compiler
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Units
|
||||||
|
|
||||||
|
#define KB(d) ((uint64)(d) << 10)
|
||||||
|
#define MB(d) ((uint64)(d) << 20)
|
||||||
|
#define GB(d) ((uint64)(d) << 30)
|
||||||
|
#define Million(n) ((n) * 1000000)
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Branch predictor hints
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# define Expect(expr, val) __builtin_expect((expr), (val))
|
||||||
|
#else
|
||||||
|
# define Expect(expr, val) (expr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Likely(expr) Expect(expr, 1)
|
||||||
|
#define Unlikely(expr) Expect(expr, 0)
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Min Max Clamp
|
||||||
|
|
||||||
|
#define Min(A, B) (((A) < (B) ? (A) : (B)))
|
||||||
|
#define Max(A, B) (((A) > (B) ? (A) : (B)))
|
||||||
|
#define ClampTop(A, X) Min(A, X)
|
||||||
|
#define ClampBottom(X, B) Max(X, B)
|
||||||
|
#define Clamp(A, X, B) (((X) < (A)) ? (A) : ((X) > (B)) ? (B) : (X))
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Alignment
|
||||||
|
#if COMPILER_CLANG || COMPILER_GCC
|
||||||
|
# define AlignOf(Type) __alignof(Type)
|
||||||
|
#elif COMPILER_MSVC
|
||||||
|
# define AlignOf(Type) __alignof(Type)
|
||||||
|
#else
|
||||||
|
# error AlignOf not defined for this compiler
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// For loop helpers
|
||||||
|
|
||||||
|
#define DeferLoop(begin, end) for (int _i_ = ((begin), 0); !_i_; ++_i_, (end))
|
||||||
|
|
||||||
|
#define EachIndex(it, count) (uint64 it = 0; it < (count); ++it)
|
||||||
|
#define EachNode(it, Type, first) (Type* it = first; it != 0; it = it->next)
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Memory Helpers
|
||||||
|
|
||||||
|
#define MemoryCopy(dst, src, size) memmove((dst), (src), (size))
|
||||||
|
#define MemorySet(dst, src, size) memset((dst), (src), (size))
|
||||||
|
#define MemoryCompare(a, b, size) memcmp((a), (b), (size))
|
||||||
|
|
||||||
|
#define MemoryZero(ptr, size) memset((ptr), 0, (size))
|
||||||
|
#define MemoryZeroStruct(s) MemoryZero((s), sizeof(*(s)))
|
||||||
|
#define MemoryZeroArray(arr) MemoryZero((arr), sizeof(arr))
|
||||||
|
|
||||||
|
#define MemoryMatch(a, b, size) (MemoryCompare((a), (b), (size)) == 0)
|
||||||
|
#define MemoryMatchStruct(a, b) MemoryMatch((a), (b), sizeof(*(a)))
|
||||||
|
#define MemoryMatchArray(a, b) MemoryMatch((a), (b), sizeof(a))
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Asserts
|
||||||
|
|
||||||
|
#if COMPILER_CLANG || COMPILER_GCC
|
||||||
|
# define Trap() __builtin_trap()
|
||||||
|
#elif COMPILER_MSVC
|
||||||
|
# define Trap() __debugbreak()
|
||||||
|
#else
|
||||||
|
# error Unknown trap intrinsic for this compiler
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AssertAlways(cond) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (!(cond)) \
|
||||||
|
{ \
|
||||||
|
Trap(); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
# define Assert(cond) AssertAlways(cond)
|
||||||
|
#else
|
||||||
|
# define Assert(cond) (void)(cond)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define StaticAssert(cond, ID) global uint8 GLUE(ID, __LINE__)[(cond) ? 1 : -1]
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Linked List macro
|
||||||
|
|
||||||
|
// Linked list macro helpers
|
||||||
|
#define CheckNil(nil, ptr) ((ptr) == 0 || (ptr) == nil)
|
||||||
|
#define SetNil(nil, ptr) ((ptr) = nil)
|
||||||
|
|
||||||
|
// Doubly-linked-lists
|
||||||
|
// clang-format off
|
||||||
|
#define DLL_insert_next_prev_zero(nil, first, last, ptr, node, next, previous) \
|
||||||
|
(CheckNil(nil, first) ? ((first) = (last) = (node), SetNil(nil, (node)->next), SetNil(nil, (node)->previous)) \
|
||||||
|
: CheckNil(nil, ptr) ? ((node)->next = (first), (first)->previous = (node), (first) = (node), SetNil(nil, (node)->previous)) \
|
||||||
|
: ((ptr) == (last)) ? ((last)->next = (node), (node )->previous = (last), (last ) = (node), SetNil(nil, (node)->next)) \
|
||||||
|
: (((CheckNil(nil, ptr) && CheckNil(nil, (ptr)->next)) ? (0) : ((ptr)->next->previous = (node))), \
|
||||||
|
((node)->next = (ptr)->next), ((ptr)->next = (node)), ((node)->previous = (ptr))))
|
||||||
|
#define DLL_push_back_next_prev_zero(nil, first, last, node, next, previous) \
|
||||||
|
DLL_insert_next_prev_zero(nil, first, last, last, node, next, previous)
|
||||||
|
#define DLL_remove_next_prev_zero(nil, first, last, node, next, previous) \
|
||||||
|
(((node) == (first) ? (first) = (node)->next : (0)), ((node) == (last) ? (last) = (last)->previous : (0)), \
|
||||||
|
(CheckNil(nil, (node)->previous) ? (0) : ((node)->previous->next = (node)->next)), \
|
||||||
|
(CheckNil(nil, (node)->next) ? (0) : ((node)->next->previous = (node)->previous)))
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// Single link double head lists (= queues)
|
||||||
|
#define SLL_queue_push_next_zero(nil, first, last, node, next) \
|
||||||
|
(CheckNil(nil, first) ? ((first) = (last) = (node), SetNil(nil, (node)->next)) \
|
||||||
|
: ((last)->next = (node), (last) = (node), SetNil(nil, (node)->next)))
|
||||||
|
|
||||||
|
// Single (link & head) lists (= stacks)
|
||||||
|
#define SLL_stack_push_next(first, node, next) ((node)->next = (first), (first) = (node))
|
||||||
|
#define SLL_stack_pop_next(first, next) ((first) = (first)->next);
|
||||||
|
|
||||||
|
// Double linked list helpers
|
||||||
|
#define DLL_push_back_next_prev(first, last, node, next, previous) \
|
||||||
|
DLL_push_back_next_prev_zero(0, first, last, node, next, previous)
|
||||||
|
#define DLL_remove_next_prev(first, last, node, next, prev) DLL_remove_next_prev_zero(0, first, last, node, next, prev)
|
||||||
|
#define DLL_push_back(first, last, node) DLL_push_back_next_prev_zero(0, first, last, node, next, previous)
|
||||||
|
#define DLL_remove(first, last, node) DLL_remove_next_prev_zero(0, first, last, node, next, previous)
|
||||||
|
|
||||||
|
// Queue helpers
|
||||||
|
#define SLL_queue_push(first, last, node) SLL_queue_push_next_zero(0, first, last, node, next)
|
||||||
|
|
||||||
|
// Stack helpers
|
||||||
|
#define SLL_stack_push(first, node) SLL_stack_push_next(first, node, next)
|
||||||
|
#define SLL_stack_pop(first) SLL_stack_pop_next(first, next)
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
#define AlignPow2(x, align) (((x) + (align) - 1) & (~((align) - 1)))
|
||||||
|
|
||||||
|
#define Stringify_(S) #S
|
||||||
|
#define Stringify(S) Stringify_(S)
|
||||||
|
|
||||||
|
#define GLUE_(A, B) A##B
|
||||||
|
#define GLUE(A, B) GLUE_(A, B)
|
||||||
|
|
||||||
|
#define ArrayCount(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
|
#if ARCH_64BIT
|
||||||
|
# define IntFromPtr(ptr) ((uint64)(ptr))
|
||||||
|
#else
|
||||||
|
# error Missing pointer to integer cast for this architecture
|
||||||
|
#endif
|
||||||
|
#define PtrFromInt(i) (void*)(i)
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Core Types
|
||||||
|
|
||||||
|
typedef uint8_t uint8;
|
||||||
|
typedef uint16_t uint16;
|
||||||
|
typedef uint32_t uint32;
|
||||||
|
typedef uint64_t uint64;
|
||||||
|
typedef int8_t int8;
|
||||||
|
typedef int16_t int16;
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef int64_t int64;
|
||||||
|
typedef float float32;
|
||||||
|
typedef double float64;
|
||||||
|
|
||||||
|
typedef int8 bool8;
|
||||||
|
typedef int16 bool16;
|
||||||
|
typedef int32 bool32;
|
||||||
|
typedef int64 bool64;
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Core Constants
|
||||||
|
|
||||||
|
global uint8 max_uint8 = 0xFF;
|
||||||
|
global uint16 max_uint16 = 0xFFFF;
|
||||||
|
global uint32 max_uint32 = 0xFFFFFFFF;
|
||||||
|
global uint64 max_uint64 = 0xFFFFFFFFFFFFFFFFll;
|
||||||
|
|
||||||
|
global int8 max_int8 = (int8)0x7F;
|
||||||
|
global int16 max_int16 = (int16)0x7FFF;
|
||||||
|
global int32 max_int32 = (int32)0x7FFFFFFF;
|
||||||
|
global int64 max_int64 = (int64)0x7FFFFFFFFFFFFFFFll;
|
||||||
|
|
||||||
|
global const uint32 bitmask1 = 0x00000001;
|
||||||
|
global const uint32 bitmask2 = 0x00000003;
|
||||||
|
global const uint32 bitmask3 = 0x00000007;
|
||||||
|
global const uint32 bitmask4 = 0x0000000f;
|
||||||
|
global const uint32 bitmask5 = 0x0000001f;
|
||||||
|
global const uint32 bitmask6 = 0x0000003f;
|
||||||
|
global const uint32 bitmask7 = 0x0000007f;
|
||||||
|
global const uint32 bitmask8 = 0x000000ff;
|
||||||
|
global const uint32 bitmask9 = 0x000001ff;
|
||||||
|
global const uint32 bitmask10 = 0x000003ff;
|
||||||
|
global const uint32 bitmask11 = 0x000007ff;
|
||||||
|
global const uint32 bitmask12 = 0x00000fff;
|
||||||
|
global const uint32 bitmask13 = 0x00001fff;
|
||||||
|
global const uint32 bitmask14 = 0x00003fff;
|
||||||
|
global const uint32 bitmask15 = 0x00007fff;
|
||||||
|
global const uint32 bitmask16 = 0x0000ffff;
|
||||||
|
global const uint32 bitmask17 = 0x0001ffff;
|
||||||
|
global const uint32 bitmask18 = 0x0003ffff;
|
||||||
|
global const uint32 bitmask19 = 0x0007ffff;
|
||||||
|
global const uint32 bitmask20 = 0x000fffff;
|
||||||
|
global const uint32 bitmask21 = 0x001fffff;
|
||||||
|
global const uint32 bitmask22 = 0x003fffff;
|
||||||
|
global const uint32 bitmask23 = 0x007fffff;
|
||||||
|
global const uint32 bitmask24 = 0x00ffffff;
|
||||||
|
global const uint32 bitmask25 = 0x01ffffff;
|
||||||
|
global const uint32 bitmask26 = 0x03ffffff;
|
||||||
|
global const uint32 bitmask27 = 0x07ffffff;
|
||||||
|
global const uint32 bitmask28 = 0x0fffffff;
|
||||||
|
global const uint32 bitmask29 = 0x1fffffff;
|
||||||
|
global const uint32 bitmask30 = 0x3fffffff;
|
||||||
|
global const uint32 bitmask31 = 0x7fffffff;
|
||||||
|
global const uint32 bitmask32 = 0xffffffff;
|
||||||
|
|
||||||
|
global const uint32 bit1 = (1 << 0);
|
||||||
|
global const uint32 bit2 = (1 << 1);
|
||||||
|
global const uint32 bit3 = (1 << 2);
|
||||||
|
global const uint32 bit4 = (1 << 3);
|
||||||
|
global const uint32 bit5 = (1 << 4);
|
||||||
|
global const uint32 bit6 = (1 << 5);
|
||||||
|
global const uint32 bit7 = (1 << 6);
|
||||||
|
global const uint32 bit8 = (1 << 7);
|
||||||
|
global const uint32 bit9 = (1 << 8);
|
||||||
|
global const uint32 bit10 = (1 << 9);
|
||||||
|
global const uint32 bit11 = (1 << 10);
|
||||||
|
global const uint32 bit12 = (1 << 11);
|
||||||
|
global const uint32 bit13 = (1 << 12);
|
||||||
|
global const uint32 bit14 = (1 << 13);
|
||||||
|
global const uint32 bit15 = (1 << 14);
|
||||||
|
global const uint32 bit16 = (1 << 15);
|
||||||
|
global const uint32 bit17 = (1 << 16);
|
||||||
|
global const uint32 bit18 = (1 << 17);
|
||||||
|
global const uint32 bit19 = (1 << 18);
|
||||||
|
global const uint32 bit20 = (1 << 19);
|
||||||
|
global const uint32 bit21 = (1 << 20);
|
||||||
|
global const uint32 bit22 = (1 << 21);
|
||||||
|
global const uint32 bit23 = (1 << 22);
|
||||||
|
global const uint32 bit24 = (1 << 23);
|
||||||
|
global const uint32 bit25 = (1 << 24);
|
||||||
|
global const uint32 bit26 = (1 << 25);
|
||||||
|
global const uint32 bit27 = (1 << 26);
|
||||||
|
global const uint32 bit28 = (1 << 27);
|
||||||
|
global const uint32 bit29 = (1 << 28);
|
||||||
|
global const uint32 bit30 = (1 << 29);
|
||||||
|
global const uint32 bit31 = (1 << 30);
|
||||||
|
global const uint32 bit32 = (1 << 31);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Safe Casts
|
||||||
|
|
||||||
|
internal uint16 safe_cast_uint16(uint32 val);
|
||||||
|
internal uint32 safe_cast_uint32(uint64 val);
|
||||||
|
internal int32 safe_cast_int32(int64 val);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Time functions
|
||||||
|
|
||||||
|
internal uint64 now_time_us();
|
||||||
|
internal void sleep_ms(uint32 ms);
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
// =============================================================================
|
||||||
|
// Arena Functions
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
internal Arena* arena_alloc_internal(ArenaParams* params)
|
||||||
|
{
|
||||||
|
uint64 committed = params->commit_size;
|
||||||
|
uint64 reserved = params->reserve_size;
|
||||||
|
|
||||||
|
// Initial block
|
||||||
|
void* base = NULL;
|
||||||
|
if (params->flags & ArenaFlag_LargePages)
|
||||||
|
{
|
||||||
|
uint64 page_size = get_system_info()->large_page_size;
|
||||||
|
reserved = AlignPow2(reserved, page_size);
|
||||||
|
committed = AlignPow2(committed, page_size);
|
||||||
|
|
||||||
|
base = reserve_memory_large(reserved);
|
||||||
|
commit_memory_large(base, committed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint64 page_size = get_system_info()->page_size;
|
||||||
|
reserved = AlignPow2(reserved, page_size);
|
||||||
|
committed = AlignPow2(committed, page_size);
|
||||||
|
|
||||||
|
base = reserve_memory(reserved);
|
||||||
|
commit_memory(base, committed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Unlikely(base == 0))
|
||||||
|
{
|
||||||
|
abort_self(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Arena* arena = base;
|
||||||
|
arena->current = arena;
|
||||||
|
arena->commit_size = params->commit_size;
|
||||||
|
arena->reserve_size = params->reserve_size;
|
||||||
|
arena->base_position = 0;
|
||||||
|
arena->position = ARENA_HEADER_SIZE;
|
||||||
|
arena->committed = committed;
|
||||||
|
arena->reserved = reserved;
|
||||||
|
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
arena->alloc_file = params->alloc_file;
|
||||||
|
arena->alloc_line = params->alloc_line;
|
||||||
|
arena->name = params->name;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return arena;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void arena_release(Arena* arena)
|
||||||
|
{
|
||||||
|
for (Arena *p = arena->current, *prev = 0; p != 0; p = prev)
|
||||||
|
{
|
||||||
|
prev = p->previous;
|
||||||
|
release_memory(p, p->reserved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Arena Push/Pop core Functions
|
||||||
|
|
||||||
|
internal void* arena_push(Arena* arena, uint64 size, uint64 align, bool32 zero)
|
||||||
|
{
|
||||||
|
Arena* current = arena->current;
|
||||||
|
uint64 pos_pre = AlignPow2(current->position, align);
|
||||||
|
uint64 pos_post = pos_pre + size;
|
||||||
|
|
||||||
|
uint64 size_to_zero = 0;
|
||||||
|
if (zero)
|
||||||
|
{
|
||||||
|
size_to_zero = Min(current->committed, pos_post) - pos_pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current->reserved < pos_post && !(arena->flags & ArenaFlag_NoChain))
|
||||||
|
{
|
||||||
|
Arena* new_block = 0;
|
||||||
|
if (new_block == 0)
|
||||||
|
{
|
||||||
|
uint64 reserved_size = arena->reserve_size;
|
||||||
|
uint64 committed_size = arena->commit_size;
|
||||||
|
if (size + ARENA_HEADER_SIZE > reserved_size)
|
||||||
|
{
|
||||||
|
reserved_size = AlignPow2(size + ARENA_HEADER_SIZE, align);
|
||||||
|
committed_size = AlignPow2(size + ARENA_HEADER_SIZE, align);
|
||||||
|
}
|
||||||
|
new_block = arena_alloc(.reserve_size = reserved_size, .commit_size = committed_size, .flags = arena->flags,
|
||||||
|
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
.alloc_file = arena->alloc_file, .alloc_line = arena->alloc_line
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
size_to_zero = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_to_zero = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_block->base_position = current->base_position + current->reserved;
|
||||||
|
SLL_stack_push_next(arena->current, new_block, previous);
|
||||||
|
|
||||||
|
current = new_block;
|
||||||
|
pos_pre = AlignPow2(current->position, align);
|
||||||
|
pos_post = pos_pre + size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// commit new pages if needed
|
||||||
|
if (current->committed < pos_post)
|
||||||
|
{
|
||||||
|
uint64 committed_past_aligned = pos_post + current->commit_size - 1;
|
||||||
|
committed_past_aligned -= committed_past_aligned % current->commit_size;
|
||||||
|
uint64 committed_past_clamped = ClampTop(committed_past_aligned, current->reserved);
|
||||||
|
uint64 committed_size = committed_past_clamped - current->committed;
|
||||||
|
uint8* committed_ptr = (uint8*)current + current->committed;
|
||||||
|
if (current->flags & ArenaFlag_LargePages)
|
||||||
|
{
|
||||||
|
commit_memory_large(committed_ptr, committed_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
commit_memory(committed_ptr, committed_size);
|
||||||
|
}
|
||||||
|
current->committed = committed_past_clamped;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* result = 0;
|
||||||
|
if (current->committed >= pos_post)
|
||||||
|
{
|
||||||
|
result = (uint8*)current + pos_pre;
|
||||||
|
current->position = pos_post;
|
||||||
|
MemoryZero(result, size_to_zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Unlikely(result == 0))
|
||||||
|
{
|
||||||
|
abort_self(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint64 arena_pos(Arena* arena)
|
||||||
|
{
|
||||||
|
Arena* current = arena->current;
|
||||||
|
uint64 position = current->base_position + current->position;
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void arena_pop_to(Arena* arena, uint64 position)
|
||||||
|
{
|
||||||
|
uint64 clamped_pos = ClampBottom(ARENA_HEADER_SIZE, position);
|
||||||
|
Arena* current = arena->current;
|
||||||
|
|
||||||
|
for (Arena* previous = 0; current->base_position >= clamped_pos; current = previous)
|
||||||
|
{
|
||||||
|
previous = current->previous;
|
||||||
|
release_memory(current, current->reserved);
|
||||||
|
}
|
||||||
|
arena->current = current;
|
||||||
|
uint64 new_position = clamped_pos - current->base_position;
|
||||||
|
AssertAlways(new_position <= current->position);
|
||||||
|
current->position = new_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void arena_clear(Arena* arena)
|
||||||
|
{
|
||||||
|
arena_pop_to(arena, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void arena_pop(Arena* arena, uint64 amount)
|
||||||
|
{
|
||||||
|
uint64 pos_old = arena_pos(arena);
|
||||||
|
Assert(pos_old > amount);
|
||||||
|
uint64 pos_new = pos_old - amount;
|
||||||
|
arena_pop_to(arena, pos_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temp arena
|
||||||
|
internal TempArena temp_begin(Arena* arena)
|
||||||
|
{
|
||||||
|
uint64 position = arena_pos(arena);
|
||||||
|
TempArena temp = { arena, position };
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void temp_end(TempArena temp)
|
||||||
|
{
|
||||||
|
arena_pop_to(temp.arena, temp.position);
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define ARENA_HEADER_SIZE 128
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Arena Types
|
||||||
|
|
||||||
|
typedef uint64 ArenaFlags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ArenaFlag_NoChain = (1 << 0),
|
||||||
|
ArenaFlag_LargePages = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ArenaParams ArenaParams;
|
||||||
|
struct ArenaParams
|
||||||
|
{
|
||||||
|
ArenaFlags flags;
|
||||||
|
uint64 commit_size;
|
||||||
|
uint64 reserve_size;
|
||||||
|
char* alloc_file;
|
||||||
|
int alloc_line;
|
||||||
|
char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Arena Arena;
|
||||||
|
struct Arena
|
||||||
|
{
|
||||||
|
Arena* previous;
|
||||||
|
Arena* current;
|
||||||
|
ArenaFlags flags;
|
||||||
|
uint64 base_position;
|
||||||
|
uint64 position;
|
||||||
|
uint64 commit_size;
|
||||||
|
uint64 committed;
|
||||||
|
uint64 reserve_size;
|
||||||
|
uint64 reserved;
|
||||||
|
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
char* alloc_file;
|
||||||
|
int alloc_line;
|
||||||
|
char* name;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
|
||||||
|
|
||||||
|
typedef struct TempArena TempArena;
|
||||||
|
struct TempArena
|
||||||
|
{
|
||||||
|
Arena* arena;
|
||||||
|
uint64 position;
|
||||||
|
};
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Arena Functions
|
||||||
|
|
||||||
|
global uint64 arena_default_reserve_size = MB(64);
|
||||||
|
global uint64 arena_default_commit_size = KB(64);
|
||||||
|
|
||||||
|
internal Arena* arena_alloc_internal(ArenaParams* params);
|
||||||
|
#define arena_alloc(...) \
|
||||||
|
arena_alloc_internal(&(ArenaParams){ .commit_size = arena_default_commit_size, \
|
||||||
|
.reserve_size = arena_default_reserve_size, \
|
||||||
|
.alloc_file = __FILE__, \
|
||||||
|
.alloc_line = __LINE__, \
|
||||||
|
__VA_ARGS__ })
|
||||||
|
internal void arena_release(Arena* arena);
|
||||||
|
|
||||||
|
// Arena Push/Pop core Functions
|
||||||
|
|
||||||
|
internal void* arena_push(Arena* arena, uint64 size, uint64 align, bool32 zero);
|
||||||
|
internal uint64 arena_pos(Arena* arena);
|
||||||
|
internal void arena_pop_to(Arena* arena, uint64 position);
|
||||||
|
internal void arena_clear(Arena* arena);
|
||||||
|
internal void arena_pop(Arena* arena, uint64 amount);
|
||||||
|
|
||||||
|
// Temp arena
|
||||||
|
internal TempArena temp_begin(Arena* arena);
|
||||||
|
internal void temp_end(TempArena temp);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Push Helper Macros
|
||||||
|
|
||||||
|
#define push_array_no_zero_aligned(arr, Type, count, align) \
|
||||||
|
(Type*)arena_push((arr), sizeof(Type) * (count), (align), (0))
|
||||||
|
#define push_array_aligned(arr, Type, count, align) (Type*)arena_push((arr), sizeof(Type) * (count), (align), (1))
|
||||||
|
#define push_array_no_zero(arr, Type, count) push_array_no_zero_aligned(arr, Type, count, Max(8, AlignOf(Type)))
|
||||||
|
#define push_array(arr, Type, count) push_array_aligned(arr, Type, count, Max(8, AlignOf(Type)))
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ========================================================================== //
|
||||||
|
// Compiler defines | Clang
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
|
||||||
|
# define COMPILER_CLANG 1
|
||||||
|
|
||||||
|
# if defined(_WIN32)
|
||||||
|
# define OS_WINDOWS 1
|
||||||
|
# else
|
||||||
|
# error Compiler / OS combo is not supported
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||||
|
# define ARCH_X64 1
|
||||||
|
# else
|
||||||
|
# error Architecture not supported
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
|
||||||
|
# define COMPILER_MSVC 1
|
||||||
|
|
||||||
|
# if defined(_WIN32)
|
||||||
|
# define OS_WINDOWS 1
|
||||||
|
# else
|
||||||
|
# error Compiler / OS combo is not supported
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if defined(_M_AMD64)
|
||||||
|
# define ARCH_X64 1
|
||||||
|
# else
|
||||||
|
# error Architecture not supported
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error Compiler not supported.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ========================================================================== //
|
||||||
|
// Architecture
|
||||||
|
|
||||||
|
#if defined(ARCH_X64)
|
||||||
|
# define ARCH_64BIT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ========================================================================== //
|
||||||
|
// Language
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
# define LANG_CPP 1
|
||||||
|
#else
|
||||||
|
# define LANG_C 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ========================================================================== //
|
||||||
|
// Build Options
|
||||||
|
|
||||||
|
#if !defined(BUILD_DEBUG)
|
||||||
|
# define BUILD_DEBUG 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ========================================================================== //
|
||||||
|
// Zeroing unused Options
|
||||||
|
|
||||||
|
#if !defined(ARCH_X64)
|
||||||
|
# define ARCH_X64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(ARCH_X86)
|
||||||
|
# define ARCH_X86 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(COMPILER_CLANG)
|
||||||
|
# define COMPILER_CLANG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(COMPILER_MSVC)
|
||||||
|
# define COMPILER_MSVC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(OS_WINDOWS)
|
||||||
|
# define OS_WINDOWS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LANG_CPP)
|
||||||
|
# define LANG_CPP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LANG_C)
|
||||||
|
# define LANG_C 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !ARCH_X64
|
||||||
|
# error Trying to build unsupported architecture. Only x64 is supported.
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
internal void entry_point();
|
||||||
|
|
||||||
|
internal void main_thread_core_entry_point(int argc, char** argv)
|
||||||
|
{
|
||||||
|
ThreadNameF("main_thread");
|
||||||
|
entry_point();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool32 update()
|
||||||
|
{
|
||||||
|
bool32 result = frame();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
internal void main_thread_core_entry_point(int argc, char** argv);
|
||||||
|
internal bool32 update();
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// =============================================================================
|
||||||
|
// Hash Functions
|
||||||
|
|
||||||
|
#pragma push_macro("__cpuid")
|
||||||
|
#undef __cpuid
|
||||||
|
#if !defined(XXH_IMPLEMENTATION)
|
||||||
|
# define XXH_INLINE_ALL
|
||||||
|
# define XXH_IMPLEMENTATION
|
||||||
|
# define XXH_STATIC_LINKING_ONLY
|
||||||
|
# include "external/xxHash/xxhash.h"
|
||||||
|
#endif
|
||||||
|
#pragma pop_macro("__cpuid")
|
||||||
|
|
||||||
|
#define HASH_SEED 4259
|
||||||
|
|
||||||
|
internal uint64 uint64_hash_from_string(String8 string)
|
||||||
|
{
|
||||||
|
uint64 result = uint64_hash_from_seed_string(HASH_SEED, string);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint64 uint64_hash_from_seed_string(uint64 seed, String8 string)
|
||||||
|
{
|
||||||
|
uint64 result = XXH3_64bits_withSeed(string.str, string.size, seed);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Hash Functions
|
||||||
|
|
||||||
|
internal uint64 uint64_hash_from_string(String8 string);
|
||||||
|
internal uint64 uint64_hash_from_seed_string(uint64 seed, String8 string);
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// clang-format off
|
||||||
|
#include "core.c"
|
||||||
|
#include "core_memory.c"
|
||||||
|
#include "core_arena.c"
|
||||||
|
#include "core_math.c"
|
||||||
|
#include "core_string.c"
|
||||||
|
#include "core_hash.c"
|
||||||
|
#include "core_system.c"
|
||||||
|
#include "core_threads.c"
|
||||||
|
#include "core_thread_context.c"
|
||||||
|
#include "core_processes.c"
|
||||||
|
#include "core_markup.c"
|
||||||
|
#include "core_entry_point.c"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
|
# include "win32/core/win32_core.c"
|
||||||
|
#elif
|
||||||
|
# error Unsupported OS
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
#include "core_defines.h"
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include "core_memory.h"
|
||||||
|
#include "core_processes.h"
|
||||||
|
#include "core_arena.h"
|
||||||
|
#include "core_math.h"
|
||||||
|
#include "core_string.h"
|
||||||
|
#include "core_hash.h"
|
||||||
|
#include "core_system.h"
|
||||||
|
#include "core_threads.h"
|
||||||
|
#include "core_thread_context.h"
|
||||||
|
#include "core_markup.h"
|
||||||
|
#include "core_entry_point.h"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
|
# include "win32/core/win32_core.h"
|
||||||
|
#elif
|
||||||
|
# error Unsupported OS
|
||||||
|
#endif
|
||||||
Whitespace-only changes.
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define ThreadNameF(...) (set_thread_namef(__VA_ARGS__))
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// =============================================================================
|
||||||
|
// Functions
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Vectors
|
||||||
|
|
||||||
|
internal Vector2f vector_2f(float32 x, float32 y)
|
||||||
|
{
|
||||||
|
Vector2f v = { x, y };
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Rectangles
|
||||||
|
|
||||||
|
internal Rect2f rect_2f(Vector2f min, Vector2f max)
|
||||||
|
{
|
||||||
|
Rect2f rect = { min, max };
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool32 contains_2f(Rect2f rect, Vector2f x)
|
||||||
|
{
|
||||||
|
bool32 cond = (rect.min.x <= x.x && x.x < rect.max.x && rect.min.y <= x.y && x.y < rect.max.y);
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Vector2f dimension_2f(Rect2f rect)
|
||||||
|
{
|
||||||
|
Vector2f dim = { ((rect.max.x > rect.min.x) ? (rect.max.x - rect.min.x) : 0),
|
||||||
|
((rect.max.y > rect.min.y) ? (rect.max.y - rect.min.y) : 0) };
|
||||||
|
return dim;
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Vector Types
|
||||||
|
|
||||||
|
typedef union Vector2f Vector2f;
|
||||||
|
union Vector2f
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float32 x;
|
||||||
|
float32 y;
|
||||||
|
};
|
||||||
|
float32 v[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union Vector2i Vector2i;
|
||||||
|
union Vector2i
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int32 x;
|
||||||
|
int32 y;
|
||||||
|
};
|
||||||
|
int32 v[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Rect Types
|
||||||
|
|
||||||
|
typedef union Rect2f Rect2f;
|
||||||
|
union Rect2f
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Vector2f min;
|
||||||
|
Vector2f max;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Vector2f p0;
|
||||||
|
Vector2f p1;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float32 x0;
|
||||||
|
float32 y0;
|
||||||
|
float32 x1;
|
||||||
|
float32 y1;
|
||||||
|
};
|
||||||
|
Vector2f v[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Functions
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Vectors
|
||||||
|
|
||||||
|
#define vector2f(x, y) vector_2f((x), (y))
|
||||||
|
internal Vector2f vector_2f(float32 x, float32 y);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Rectangles
|
||||||
|
|
||||||
|
#define rect2f(min, max) rect_2f((min), (max))
|
||||||
|
#define rect2fp(x, y, z, w) rect2f(vector2f((x), (y)), vector2f((z), (w)))
|
||||||
|
internal Rect2f rect_2f(Vector2f min, Vector2f max);
|
||||||
|
internal bool32 contains_2f(Rect2f rect, Vector2f x);
|
||||||
|
internal Vector2f dimension_2f(Rect2f rect);
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// OS DEPEND see os/core/os_core.c
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
internal void* reserve_memory(uint64 size);
|
||||||
|
internal bool32 commit_memory(void* ptr, uint64 size);
|
||||||
|
internal void* reserve_memory_large(uint64 size);
|
||||||
|
internal bool32 commit_memory_large(void* ptr, uint64 size);
|
||||||
|
internal void decommit_memory(void* ptr, uint64 size);
|
||||||
|
internal void release_memory(void* ptr, uint64 size);
|
||||||
Whitespace-only changes.
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Aborting (os dependent see os/core/os_core.c)
|
||||||
|
|
||||||
|
internal void abort_self(uint64 exit_code);
|
||||||
@@ -0,0 +1,395 @@
|
|||||||
|
#ifndef MEM_STATIC
|
||||||
|
# define MEM_STATIC
|
||||||
|
# define MEM_API static inline
|
||||||
|
# include "external/memfun/memfun.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String conversions
|
||||||
|
|
||||||
|
internal bool32 char_is_upper(uint8 c)
|
||||||
|
{
|
||||||
|
return ('A' <= c && c <= 'Z');
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool32 char_is_lower(uint8 c)
|
||||||
|
{
|
||||||
|
return ('a' <= c && c <= 'z');
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool32 char_is_slash(uint8 c)
|
||||||
|
{
|
||||||
|
return (c == '/' || c == '\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint8 lower_from_char(uint8 c)
|
||||||
|
{
|
||||||
|
if (char_is_upper(c))
|
||||||
|
{
|
||||||
|
c += ('a' - 'A');
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint8 upper_from_char(uint8 c)
|
||||||
|
{
|
||||||
|
if (char_is_lower(c))
|
||||||
|
{
|
||||||
|
c += ('A' - 'a');
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint8 correct_slash_from_char(uint8 c)
|
||||||
|
{
|
||||||
|
if (char_is_slash(c))
|
||||||
|
{
|
||||||
|
c = '/';
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================================================== //
|
||||||
|
// String Length
|
||||||
|
|
||||||
|
internal uint64 cstring8_length(uint8* cstring)
|
||||||
|
{
|
||||||
|
uint64 length = 0;
|
||||||
|
if (cstring)
|
||||||
|
{
|
||||||
|
uint8* p = cstring;
|
||||||
|
for (; *p != '\0'; ++p)
|
||||||
|
;
|
||||||
|
length = (uint64)(p - cstring);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint64 cstring16_length(uint16* cstring)
|
||||||
|
{
|
||||||
|
uint64 length = 0;
|
||||||
|
if (cstring)
|
||||||
|
{
|
||||||
|
uint16* p = cstring;
|
||||||
|
for (; *p != '\0'; ++p)
|
||||||
|
;
|
||||||
|
length = (uint64)(p - cstring);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint64 cstring32_length(uint32* cstring)
|
||||||
|
{
|
||||||
|
uint64 length = 0;
|
||||||
|
if (cstring)
|
||||||
|
{
|
||||||
|
uint32* p = cstring;
|
||||||
|
for (; *p != '\0'; ++p)
|
||||||
|
;
|
||||||
|
length = (uint64)(p - cstring);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================================================== //
|
||||||
|
// String Constructor
|
||||||
|
|
||||||
|
internal String8 str8(uint8* str, uint64 size)
|
||||||
|
{
|
||||||
|
String8 result = { str, size };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String8 str8_zero()
|
||||||
|
{
|
||||||
|
String8 result = { 0 };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String16 str16(uint16* str, uint64 size)
|
||||||
|
{
|
||||||
|
String16 result = { str, size };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String16 str16_zero()
|
||||||
|
{
|
||||||
|
String16 result = { 0 };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String8 str8_cstring(const char* cstring)
|
||||||
|
{
|
||||||
|
String8 result = { (uint8*)cstring, cstring8_length((uint8*)cstring) };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String16 str16_cstring(uint16* cstring)
|
||||||
|
{
|
||||||
|
String16 result = { (uint16*)cstring, cstring16_length((uint16*)cstring) };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String32 str32_cstring(uint32* cstring)
|
||||||
|
{
|
||||||
|
String32 result = { (uint32*)cstring, cstring32_length((uint32*)cstring) };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String Matching
|
||||||
|
|
||||||
|
internal bool32 str8_match(String8 a, String8 b, StringMatchFlags flags)
|
||||||
|
{
|
||||||
|
bool32 result = 0;
|
||||||
|
if (a.size == b.size && flags == 0)
|
||||||
|
{
|
||||||
|
result = MemIsEqual(a.str, b.str, b.size);
|
||||||
|
}
|
||||||
|
else if (a.size == b.size && flags == StringMatchFlag_CaseInsensitive)
|
||||||
|
{
|
||||||
|
result = MemCompareI(a.str, b.str, a.size) == 0;
|
||||||
|
}
|
||||||
|
else if (a.size == b.size || (flags * StringMatchFlag_RightSideSloppy))
|
||||||
|
{
|
||||||
|
bool32 case_insensitive = (flags & StringMatchFlag_CaseInsensitive);
|
||||||
|
bool32 slash_insensitive = (flags & StringMatchFlag_SlashInsensitive);
|
||||||
|
uint64 size = Min(a.size, b.size);
|
||||||
|
result = 1;
|
||||||
|
for EachIndex(i, size)
|
||||||
|
{
|
||||||
|
uint8 at = a.str[i];
|
||||||
|
uint8 bt = b.str[i];
|
||||||
|
if (case_insensitive)
|
||||||
|
{
|
||||||
|
at = upper_from_char(at);
|
||||||
|
bt = upper_from_char(bt);
|
||||||
|
}
|
||||||
|
if (slash_insensitive)
|
||||||
|
{
|
||||||
|
at = correct_slash_from_char(at);
|
||||||
|
bt = correct_slash_from_char(bt);
|
||||||
|
}
|
||||||
|
if (at != bt)
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String Formatting & Copying
|
||||||
|
|
||||||
|
internal String8 str8_copy(Arena* arena, String8 in)
|
||||||
|
{
|
||||||
|
String8 str;
|
||||||
|
str.size = in.size;
|
||||||
|
str.str = push_array_no_zero(arena, uint8, str.size + 1);
|
||||||
|
MemoryCopy(str.str, in.str, in.size);
|
||||||
|
str.str[str.size] = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String8 str8fv(Arena* arena, char* fmt, va_list args)
|
||||||
|
{
|
||||||
|
va_list args2;
|
||||||
|
va_copy(args2, args);
|
||||||
|
uint32 needed_bytes = juliet_vsnprintf(0, 0, fmt, args) + 1;
|
||||||
|
String8 result = { 0 };
|
||||||
|
result.str = push_array_no_zero(arena, uint8, needed_bytes);
|
||||||
|
result.size = juliet_vsnprintf((char*)result.str, needed_bytes, fmt, args2);
|
||||||
|
result.str[result.size] = '\0';
|
||||||
|
va_end(args2);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Unicode String Encode/Decode
|
||||||
|
|
||||||
|
read_only global uint8 utf8_class[32] = {
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
internal UnicodeDecode utf8_decode(uint8* str, uint64 max)
|
||||||
|
{
|
||||||
|
UnicodeDecode result = { 1, max_uint32 };
|
||||||
|
uint8 byte = str[0];
|
||||||
|
uint8 byte_class = utf8_class[byte >> 3];
|
||||||
|
switch (byte_class)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
result.codepoint = byte;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if (1 < max)
|
||||||
|
{
|
||||||
|
uint8 cont_byte = str[1];
|
||||||
|
if (utf8_class[cont_byte >> 3] == 0)
|
||||||
|
{
|
||||||
|
result.codepoint = (byte & bitmask5) << 6;
|
||||||
|
result.codepoint |= (cont_byte & bitmask6);
|
||||||
|
result.increment = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if (2 < max)
|
||||||
|
{
|
||||||
|
uint8 cont_byte[2] = { str[1], str[2] };
|
||||||
|
if (utf8_class[cont_byte[0] >> 3] == 0 && utf8_class[cont_byte[1] >> 3] == 0)
|
||||||
|
{
|
||||||
|
result.codepoint = (byte & bitmask4) << 12;
|
||||||
|
result.codepoint |= ((cont_byte[0] & bitmask6) << 6);
|
||||||
|
result.codepoint |= (cont_byte[1] & bitmask6);
|
||||||
|
result.increment = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
if (3 < max)
|
||||||
|
{
|
||||||
|
uint8 cont_byte[3] = { str[1], str[2], str[3] };
|
||||||
|
if (utf8_class[cont_byte[0] >> 3] == 0 && utf8_class[cont_byte[1] >> 3] == 0 && utf8_class[cont_byte[2] >> 3] == 0)
|
||||||
|
{
|
||||||
|
result.codepoint = (byte & bitmask3) << 18;
|
||||||
|
result.codepoint |= ((cont_byte[0] & bitmask6 << 12));
|
||||||
|
result.codepoint |= ((cont_byte[1] & bitmask6) << 6);
|
||||||
|
result.codepoint |= (cont_byte[2] & bitmask6);
|
||||||
|
result.increment = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal UnicodeDecode utf16_decode(uint16* str, uint64 max)
|
||||||
|
{
|
||||||
|
UnicodeDecode result = { 1, max_uint32 };
|
||||||
|
result.codepoint = str[0];
|
||||||
|
result.increment = 1;
|
||||||
|
if (max > 1 && 0xD800 <= str[0] && str[0] < 0xDC00 && 0xDC00 <= str[1] && str[1] < 0xE000)
|
||||||
|
{
|
||||||
|
result.codepoint = ((str[0] - 0xD800) << 10) | ((str[1] - 0xDC00) + 0x10000);
|
||||||
|
result.increment = 2;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint32 utf8_encode(uint8* str, uint32 codepoint)
|
||||||
|
{
|
||||||
|
uint32 increment = 0;
|
||||||
|
if (codepoint <= 0x7f)
|
||||||
|
{
|
||||||
|
str[0] = (uint8)codepoint;
|
||||||
|
increment = 1;
|
||||||
|
}
|
||||||
|
else if (codepoint <= 0x7FF)
|
||||||
|
{
|
||||||
|
str[0] = (bitmask2 << 6) | ((codepoint >> 6) & bitmask5);
|
||||||
|
str[1] = bit8 | (codepoint & bitmask6);
|
||||||
|
increment = 2;
|
||||||
|
}
|
||||||
|
else if (codepoint <= 0xFFFF)
|
||||||
|
{
|
||||||
|
str[0] = (bitmask3 << 5) | ((codepoint >> 12) & bitmask4);
|
||||||
|
str[1] = bit8 | ((codepoint >> 6) & bitmask6);
|
||||||
|
str[2] = bit8 | (codepoint & bitmask6);
|
||||||
|
increment = 3;
|
||||||
|
}
|
||||||
|
else if (codepoint <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
str[0] = (bitmask4 << 4) | ((codepoint >> 18) & bitmask3);
|
||||||
|
str[1] = bit8 | ((codepoint >> 12) & bitmask6);
|
||||||
|
str[2] = bit8 | (codepoint >> 6 & bitmask6);
|
||||||
|
str[3] = bit8 | (codepoint & bitmask6);
|
||||||
|
increment = 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str[0] = '?';
|
||||||
|
increment = 1;
|
||||||
|
}
|
||||||
|
return increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint32 utf16_encode(uint16* str, uint32 codepoint)
|
||||||
|
{
|
||||||
|
uint32 increment = 1;
|
||||||
|
if (codepoint == max_uint32)
|
||||||
|
{
|
||||||
|
str[0] = (uint16)'?';
|
||||||
|
}
|
||||||
|
else if (codepoint < 0x10000)
|
||||||
|
{
|
||||||
|
str[0] = (uint16)codepoint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32 v = codepoint - 0x10000;
|
||||||
|
str[0] = safe_cast_uint16(0xD800 + (v >> 10));
|
||||||
|
str[1] = safe_cast_uint16(0xDC00 + (v & bitmask10));
|
||||||
|
increment = 2;
|
||||||
|
}
|
||||||
|
return increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Unicode String Conversions
|
||||||
|
|
||||||
|
internal String8 str8_from_16(Arena* arena, String16 in)
|
||||||
|
{
|
||||||
|
String8 result = str8_zero();
|
||||||
|
if (in.size)
|
||||||
|
{
|
||||||
|
uint64 capacity = in.size * 3;
|
||||||
|
uint8* str = push_array_no_zero(arena, uint8, capacity + 1);
|
||||||
|
uint16* ptr = in.str;
|
||||||
|
uint16* opl = ptr + in.size;
|
||||||
|
uint64 size = 0;
|
||||||
|
UnicodeDecode consume;
|
||||||
|
for (; ptr < opl; ptr += consume.increment)
|
||||||
|
{
|
||||||
|
consume = utf16_decode(ptr, opl - ptr);
|
||||||
|
size += utf8_encode(str + size, consume.codepoint);
|
||||||
|
}
|
||||||
|
str[size] = '\0';
|
||||||
|
arena_pop(arena, (capacity - size));
|
||||||
|
result = str8(str, size);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String16 str16_from_8(Arena* arena, String8 in)
|
||||||
|
{
|
||||||
|
String16 result = str16_zero();
|
||||||
|
if (in.size)
|
||||||
|
{
|
||||||
|
uint64 capacity = in.size * 2;
|
||||||
|
uint16* str = push_array_no_zero(arena, uint16, capacity + 1);
|
||||||
|
uint8* ptr = in.str;
|
||||||
|
uint8* opl = ptr + in.size;
|
||||||
|
uint64 size = 0;
|
||||||
|
UnicodeDecode consume;
|
||||||
|
for (; ptr < opl; ptr += consume.increment)
|
||||||
|
{
|
||||||
|
consume = utf8_decode(ptr, opl - ptr);
|
||||||
|
size += utf16_encode(str + size, consume.codepoint);
|
||||||
|
}
|
||||||
|
str[size] = '\0';
|
||||||
|
arena_pop(arena, (capacity - size) * 2);
|
||||||
|
result = str16(str, size);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String Types
|
||||||
|
|
||||||
|
typedef struct String8 String8;
|
||||||
|
struct String8
|
||||||
|
{
|
||||||
|
uint8* str;
|
||||||
|
uint64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct String16 String16;
|
||||||
|
struct String16
|
||||||
|
{
|
||||||
|
uint16* str;
|
||||||
|
uint64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct String32 String32;
|
||||||
|
struct String32
|
||||||
|
{
|
||||||
|
uint32* str;
|
||||||
|
uint64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String Matching Types
|
||||||
|
|
||||||
|
typedef uint32 StringMatchFlags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
StringMatchFlag_CaseInsensitive = (1 << 0),
|
||||||
|
StringMatchFlag_RightSideSloppy = (1 << 1),
|
||||||
|
StringMatchFlag_SlashInsensitive = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Unicode decoding Types
|
||||||
|
|
||||||
|
typedef struct UnicodeDecode UnicodeDecode;
|
||||||
|
struct UnicodeDecode
|
||||||
|
{
|
||||||
|
uint32 increment;
|
||||||
|
uint32 codepoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String conversions
|
||||||
|
|
||||||
|
internal bool32 char_is_upper(uint8 c);
|
||||||
|
internal bool32 char_is_lower(uint8 c);
|
||||||
|
internal bool32 char_is_slash(uint8 c);
|
||||||
|
internal uint8 lower_from_char(uint8 c);
|
||||||
|
internal uint8 upper_from_char(uint8 c);
|
||||||
|
internal uint8 correct_slash_from_char(uint8 c);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String Length
|
||||||
|
|
||||||
|
internal uint64 cstring8_length(uint8* cstring);
|
||||||
|
internal uint64 cstring16_length(uint16* cstring);
|
||||||
|
internal uint64 cstring32_length(uint32* cstring);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String Constructor
|
||||||
|
|
||||||
|
#define str8_literal(S) str8((uint8*)(S), sizeof(S) - 1)
|
||||||
|
|
||||||
|
#define str8_struct(S) str8((uint8*)(S), sizeof(*(S)))
|
||||||
|
|
||||||
|
internal String8 str8(uint8* str, uint64 size);
|
||||||
|
internal String8 str8_zero();
|
||||||
|
internal String16 str16(uint16* str, uint64 size);
|
||||||
|
internal String16 str16_zero();
|
||||||
|
internal String8 str8_cstring(const char* cstring);
|
||||||
|
internal String16 str16_cstring(uint16* cstring);
|
||||||
|
internal String32 str32_cstring(uint32* cstring);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String Matching
|
||||||
|
|
||||||
|
internal bool32 str8_match(String8 a, String8 b, StringMatchFlags flags);
|
||||||
|
#define str8_matchi(a, b) str8_match(a, b, StringMatchFlag_CaseInsensitive)
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// String Formatting & Copying
|
||||||
|
|
||||||
|
internal String8 str8_copy(Arena* arena, String8 in);
|
||||||
|
internal String8 str8fv(Arena* arena, char* fmt, va_list args);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Unicode String Encode/Decode
|
||||||
|
|
||||||
|
internal UnicodeDecode utf8_decode(uint8* str, uint64 max);
|
||||||
|
internal UnicodeDecode utf16_decode(uint16* str, uint64 max);
|
||||||
|
internal uint32 utf8_encode(uint8* str, uint32 codepoint);
|
||||||
|
internal uint32 utf16_encode(uint16* str, uint32 codepoint);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Unicode String Conversions
|
||||||
|
|
||||||
|
internal String8 str8_from_16(Arena* arena, String16 in);
|
||||||
|
internal String16 str16_from_8(Arena* arena, String8 in);
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// OS DEPEND see os/core/os_core.c
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct SystemInfo SystemInfo;
|
||||||
|
struct SystemInfo
|
||||||
|
{
|
||||||
|
uint64 page_size;
|
||||||
|
uint64 large_page_size;
|
||||||
|
String8 machine_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
internal SystemInfo* get_system_info();
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// =============================================================================
|
||||||
|
// Globals
|
||||||
|
|
||||||
|
thread_static TCTX* tctx_thread_local;
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Thread Context Functions
|
||||||
|
|
||||||
|
// Thread Context allocation
|
||||||
|
internal TCTX* tctx_alloc()
|
||||||
|
{
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
thread_static static char name[2][1024];
|
||||||
|
juliet_snprintf(name[0], sizeof(name[0]), "Scratch/0[TID:%u]", tid());
|
||||||
|
juliet_snprintf(name[1], sizeof(name[1]), "Scratch/1[TID:%u]", tid());
|
||||||
|
Arena* arena_0 = arena_alloc(.name = name[0]);
|
||||||
|
Arena* arena_1 = arena_alloc(.name = name[1]);
|
||||||
|
#else
|
||||||
|
Arena* arena_0 = arena_alloc();
|
||||||
|
Arena* arena_1 = arena_alloc();
|
||||||
|
#endif
|
||||||
|
TCTX* tctx = push_array(arena_0, TCTX, 1);
|
||||||
|
tctx->arenas[0] = arena_0;
|
||||||
|
tctx->arenas[1] = arena_1;
|
||||||
|
return tctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void tctx_release(TCTX* tctx)
|
||||||
|
{
|
||||||
|
arena_release(tctx->arenas[1]);
|
||||||
|
arena_release(tctx->arenas[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void tctx_select(TCTX* tctx)
|
||||||
|
{
|
||||||
|
tctx_thread_local = tctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal TCTX* tctx_selected()
|
||||||
|
{
|
||||||
|
return tctx_thread_local;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Arena* tctx_get_scratch(Arena** conflicts, uint64 count)
|
||||||
|
{
|
||||||
|
TCTX* tctx = tctx_selected();
|
||||||
|
Arena* result = 0;
|
||||||
|
Arena** arena_ptr = tctx->arenas;
|
||||||
|
for (uint64 i = 0; i < ArrayCount(tctx->arenas); ++i, ++arena_ptr)
|
||||||
|
{
|
||||||
|
Arena** conflict_ptr = conflicts;
|
||||||
|
bool32 has_conflict = 0;
|
||||||
|
for (uint64 j = 0; j < count; ++j, ++conflict_ptr)
|
||||||
|
{
|
||||||
|
if (*arena_ptr == *conflict_ptr)
|
||||||
|
{
|
||||||
|
has_conflict = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!has_conflict)
|
||||||
|
{
|
||||||
|
result = *arena_ptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count)))
|
||||||
|
#define scratch_end(scratch) temp_end(scratch)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct TCTX TCTX;
|
||||||
|
struct TCTX
|
||||||
|
{
|
||||||
|
// Scratch arenas
|
||||||
|
Arena* arenas[2];
|
||||||
|
|
||||||
|
uint8 thread_name[32];
|
||||||
|
uint64 thread_name_size;
|
||||||
|
|
||||||
|
char* file_name;
|
||||||
|
uint64 line_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern thread_static TCTX* tctx_thread_local;
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Thread Context Functions
|
||||||
|
|
||||||
|
// Thread Context allocation
|
||||||
|
internal TCTX* tctx_alloc();
|
||||||
|
internal void tctx_release(TCTX* tctx);
|
||||||
|
internal void tctx_select(TCTX* tctx);
|
||||||
|
internal TCTX* tctx_selected();
|
||||||
|
|
||||||
|
internal Arena* tctx_get_scratch(Arena** conflicts, uint64 count);
|
||||||
|
#define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count)))
|
||||||
|
#define scratch_end(scratch) temp_end(scratch)
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Thread Info Helpers
|
||||||
|
internal void set_thread_name(String8 name)
|
||||||
|
{
|
||||||
|
set_platform_thread_name(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void set_thread_namef(char* fmt, ...)
|
||||||
|
{
|
||||||
|
TempArena scratch = scratch_begin(0, 0);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
String8 string = str8fv(scratch.arena, fmt, args);
|
||||||
|
set_thread_name(string);
|
||||||
|
va_end(args);
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Synchronization primitives types
|
||||||
|
|
||||||
|
typedef struct RWMutex RWMutex;
|
||||||
|
struct RWMutex
|
||||||
|
{
|
||||||
|
uint64 handle[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Thread Info Helpers
|
||||||
|
internal void set_thread_name(String8 name);
|
||||||
|
internal void set_thread_namef(char* fmt, ...);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Thread Info
|
||||||
|
|
||||||
|
internal uint32 tid();
|
||||||
|
internal void set_platform_thread_name(String8 name);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Synchronization primitive functions
|
||||||
|
|
||||||
|
// Read Write Mutexes functions
|
||||||
|
|
||||||
|
internal RWMutex rw_mutex_alloc();
|
||||||
|
internal void rw_mutex_release(RWMutex mutex);
|
||||||
|
internal void rw_mutex_take(RWMutex mutex, bool32 write_mode);
|
||||||
|
internal void rw_mutex_drop(RWMutex mutex, bool32 write_mode);
|
||||||
|
#define rw_mutex_take_r(m) rw_mutex_take((m), (0))
|
||||||
|
#define rw_mutex_take_w(m) rw_mutex_take((m), (1))
|
||||||
|
#define rw_mutex_drop_r(m) rw_mutex_drop((m), (0))
|
||||||
|
#define rw_mutex_drop_w(m) rw_mutex_drop((m), (1))
|
||||||
|
|
||||||
|
// Scope macros
|
||||||
|
#define MutexScopeR(mutex) DeferLoop(rw_mutex_take_r(mutex), rw_mutex_drop_r(mutex))
|
||||||
|
#define MutexScopeW(mutex) DeferLoop(rw_mutex_take_w(mutex), rw_mutex_drop_w(mutex))
|
||||||
Vendored
+4285
File diff suppressed because it is too large.
Load diff
+1
Submodule Juliet/external/stb_sprintf added at 2ffb3379e8.
+1
Submodule Juliet/external/xxHash added at c87183a77d.
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Application/IApplication.h>
|
|
||||||
#include <Juliet.h>
|
|
||||||
|
|
||||||
enum class JulietInit_Flags : uint8;
|
|
||||||
|
|
||||||
struct Arena;
|
|
||||||
extern JULIET_API void StartApplication(IApplication& app, JulietInit_Flags flags);
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
|
|
||||||
struct Camera;
|
|
||||||
struct RenderPass;
|
|
||||||
struct CommandList;
|
|
||||||
struct Texture;
|
|
||||||
struct ColorTargetInfo;
|
|
||||||
struct DepthStencilTargetInfo;
|
|
||||||
struct Arena;
|
|
||||||
|
|
||||||
class IApplication
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~IApplication() = default;
|
|
||||||
virtual void Init(NonNullPtr<Arena> arena) = 0;
|
|
||||||
virtual void Shutdown() = 0;
|
|
||||||
virtual void Update(float deltaTime) = 0;
|
|
||||||
virtual bool IsRunning() = 0;
|
|
||||||
|
|
||||||
// Accessors for Engine Systems
|
|
||||||
virtual struct Window* GetPlatformWindow() = 0;
|
|
||||||
virtual struct GraphicsDevice* GetGraphicsDevice() = 0;
|
|
||||||
|
|
||||||
// Render Lifecycle (Engine-Managed Render Loop)
|
|
||||||
virtual ColorTargetInfo GetColorTargetInfo(Texture* swapchainTexture) = 0;
|
|
||||||
virtual DepthStencilTargetInfo* GetDepthTargetInfo() = 0;
|
|
||||||
};
|
|
||||||
@@ -1,62 +1,60 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
// From https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
|
// From https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
|
||||||
|
|
||||||
namespace details
|
global const uint32 g_crc32_tab[256] = {
|
||||||
{
|
0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u, 0x0edb8832u,
|
||||||
constexpr uint32_t crc32_tab[] = {
|
0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u, 0x1db71064u, 0x6ab020f2u,
|
||||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
|
0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u, 0x136c9856u, 0x646ba8c0u, 0xfd62f97au,
|
||||||
0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u, 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u,
|
||||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a,
|
0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu, 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u,
|
||||||
0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u, 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u,
|
||||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
0xcfba9599u, 0xb8bda50fu, 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu,
|
||||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
0xb6662d3du, 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u,
|
||||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
|
0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u, 0x6b6b51f4u,
|
||||||
0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u, 0x65b0d9c6u, 0x12b7e950u,
|
||||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
|
0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u, 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u,
|
||||||
0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu, 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u,
|
||||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074,
|
0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u, 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u,
|
||||||
0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
0x206f85b3u, 0xb966d409u, 0xce61e49fu, 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u,
|
||||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525,
|
0xb7bd5c3bu, 0xc0ba6cadu, 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u,
|
||||||
0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
0x73dc1683u, 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
|
||||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u, 0xfed41b76u,
|
||||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u, 0xd6d6a3e8u, 0xa1d1937eu,
|
||||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76,
|
0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu, 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u,
|
||||||
0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u, 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u,
|
||||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6,
|
0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu, 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u,
|
||||||
0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du, 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu,
|
||||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
|
0x72076785u, 0x05005713u, 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u,
|
||||||
0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
0x0bdbdf21u, 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
|
||||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7,
|
0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u, 0xa00ae278u,
|
||||||
0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu, 0xaed16a4au, 0xd9d65adcu,
|
||||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u, 0xbdbdf21cu, 0xcabac28au, 0x53b39330u,
|
||||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu, 0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u,
|
||||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330,
|
0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du
|
||||||
0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
};
|
||||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr uint32 crc32(const char* str, size_t length)
|
static inline uint32 crc32_bytes(const char* str, size_t length)
|
||||||
{
|
{
|
||||||
Assert(str && length > 0);
|
Assert(str != NULL && length > 0);
|
||||||
const char* p = str;
|
const char* p = str;
|
||||||
uint32_t crc = ~0U;
|
uint32 crc = ~0U;
|
||||||
while (length--)
|
while (length--)
|
||||||
{
|
{
|
||||||
crc = details::crc32_tab[(crc ^ static_cast<uint8>(*p++)) & 0xFF] ^ (crc >> 8);
|
crc = g_crc32_tab[(crc ^ (uint8)(*p++)) & 0xFFu] ^ (crc >> 8);
|
||||||
}
|
}
|
||||||
return crc ^ ~0U;
|
return crc ^ ~0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint32 crc32(String str)
|
static inline uint32 crc32_str(String str)
|
||||||
{
|
{
|
||||||
return crc32(str.Str, str.Size);
|
return crc32_bytes(str.Str, str.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
consteval uint32 operator""_crc32(const char* str, size_t length)
|
static inline uint32 crc32_cstr(const char* str)
|
||||||
{
|
{
|
||||||
return crc32(str, length);
|
return crc32_bytes(str, StringLengthCStr(str));
|
||||||
}
|
}
|
||||||
@@ -1,65 +1,68 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
using uint8 = uint8_t;
|
#include <limits.h>
|
||||||
using uint16 = uint16_t;
|
#include <stddef.h>
|
||||||
using uint32 = uint32_t;
|
#include <stdint.h>
|
||||||
using uint64 = uint64_t;
|
|
||||||
|
|
||||||
using int8 = int8_t;
|
typedef uint8_t uint8;
|
||||||
using int16 = int16_t;
|
typedef uint16_t uint16;
|
||||||
using int32 = int32_t;
|
typedef uint32_t uint32;
|
||||||
using int64 = int64_t;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
using Byte = std::byte;
|
typedef int8_t int8;
|
||||||
|
typedef int16_t int16;
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef int64_t int64;
|
||||||
|
|
||||||
using size_t = std::size_t;
|
typedef uint8 bool8;
|
||||||
using index_t = size_t;
|
typedef uint16 bool16;
|
||||||
|
typedef uint32 bool32;
|
||||||
|
typedef uint64 bool64;
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#ifndef true
|
||||||
|
#define true 1
|
||||||
|
#endif
|
||||||
|
#ifndef false
|
||||||
|
#define false 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef uint8 Byte;
|
||||||
|
typedef size_t index_t;
|
||||||
|
|
||||||
|
typedef struct ByteBuffer ByteBuffer;
|
||||||
struct ByteBuffer
|
struct ByteBuffer
|
||||||
{
|
{
|
||||||
Byte* Data;
|
Byte* Data;
|
||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ptrdiff_t = decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr));
|
typedef void (*FunctionPtr)(void);
|
||||||
|
|
||||||
using FunctionPtr = auto (*)(void) -> void;
|
#define uint8Max ((uint8)0xFFu)
|
||||||
|
#define uint16Max ((uint16)0xFFFFu)
|
||||||
|
#define uint32Max ((uint32)0xFFFFFFFFu)
|
||||||
|
#define uint64Max ((uint64)0xFFFFFFFFFFFFFFFFull)
|
||||||
|
|
||||||
// Limits
|
#define int8Max ((int8)0x7F)
|
||||||
template <typename Type>
|
#define int16Max ((int16)0x7FFF)
|
||||||
consteval Type MaxValueOf()
|
#define int32Max ((int32)0x7FFFFFFF)
|
||||||
{
|
#define int64Max ((int64)0x7FFFFFFFFFFFFFFFll)
|
||||||
return std::numeric_limits<Type>::max();
|
|
||||||
}
|
|
||||||
constexpr uint8 uint8Max = MaxValueOf<uint8>();
|
|
||||||
constexpr uint16 uint16Max = MaxValueOf<uint16>();
|
|
||||||
constexpr uint32 uint32Max = MaxValueOf<uint32>();
|
|
||||||
constexpr uint64 uint64Max = MaxValueOf<uint64>();
|
|
||||||
|
|
||||||
constexpr int8 int8Max = MaxValueOf<int8>();
|
#define indexMax ((index_t)SIZE_MAX)
|
||||||
constexpr int16 int16Max = MaxValueOf<int16>();
|
|
||||||
constexpr int32 int32Max = MaxValueOf<int32>();
|
|
||||||
constexpr int64 int64Max = MaxValueOf<int64>();
|
|
||||||
|
|
||||||
constexpr index_t indexMax = MaxValueOf<index_t>();
|
#define uint8Min ((uint8)0u)
|
||||||
|
#define uint16Min ((uint16)0u)
|
||||||
|
#define uint32Min ((uint32)0u)
|
||||||
|
#define uint64Min ((uint64)0ull)
|
||||||
|
|
||||||
template <typename Type>
|
#define int8Min ((int8)(-128))
|
||||||
consteval Type MinValueOf()
|
#define int16Min ((int16)(-32768))
|
||||||
{
|
#define int32Min ((int32)(-2147483647 - 1))
|
||||||
return std::numeric_limits<Type>::lowest();
|
#define int64Min ((int64)(-9223372036854775807ll - 1ll))
|
||||||
}
|
|
||||||
|
|
||||||
constexpr uint8 uint8Min = MinValueOf<uint8>();
|
#define indexMin ((index_t)0u)
|
||||||
constexpr uint16 uint16Min = MinValueOf<uint16>();
|
|
||||||
constexpr uint32 uint32Min = MinValueOf<uint32>();
|
|
||||||
constexpr uint64 uint64Min = MinValueOf<uint64>();
|
|
||||||
|
|
||||||
constexpr int8 int8Min = MinValueOf<int8>();
|
#define Kilobytes(value) ((uint64)(value) * 1024ull)
|
||||||
constexpr int16 int16Min = MinValueOf<int16>();
|
#define Megabytes(value) (Kilobytes(value) * 1024ull)
|
||||||
constexpr int32 int32Min = MinValueOf<int32>();
|
|
||||||
constexpr int64 int64Min = MinValueOf<int64>();
|
|
||||||
|
|
||||||
constexpr index_t indexMin = MinValueOf<index_t>();
|
|
||||||
|
|
||||||
#define Kilobytes(value) value * 1024
|
|
||||||
#define Megabytes(value) Kilobytes(value) * 1024
|
|
||||||
@@ -1,22 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
#define global static
|
#define global static
|
||||||
#define internal static
|
#define internal static
|
||||||
|
|
||||||
|
#define Glue_(A, B) A##B
|
||||||
|
#define Glue(A, B) Glue_(A, B)
|
||||||
|
#define StaticAssert(C, ID) global uint8 Glue(ID, __LINE__)[(C) ? 1 : -1]
|
||||||
|
|
||||||
// 1. Stringify helpers
|
// 1. Stringify helpers
|
||||||
#define JULIET_STR(x) #x
|
#define JULIET_STR(x) #x
|
||||||
#define JULIET_TOSTRING(x) JULIET_STR(x)
|
#define JULIET_TOSTRING(x) JULIET_STR(x)
|
||||||
|
|
||||||
// 2. Define the pragma operator based on compiler
|
// 2. Define the pragma operator based on compiler
|
||||||
#if defined(__clang__) || defined(__GNUC__)
|
#if defined(__clang__) || defined(__GNUC__)
|
||||||
#define JULIET_PRAGMA(x) _Pragma(#x)
|
#define JULIET_PRAGMA(x) _Pragma(#x)
|
||||||
#define JULIET_SUPPRESS_MSVC(id)
|
#define JULIET_SUPPRESS_MSVC(id)
|
||||||
#define JULIET_SUPPRESS_CLANG(str) JULIET_PRAGMA(clang diagnostic ignored str)
|
#define JULIET_SUPPRESS_CLANG(str) JULIET_PRAGMA(clang diagnostic ignored str)
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define JULIET_PRAGMA(x) __pragma(x)
|
#define JULIET_PRAGMA(x) __pragma(x)
|
||||||
#define JULIET_SUPPRESS_MSVC(id) JULIET_PRAGMA(warning(disable : id))
|
#define JULIET_SUPPRESS_MSVC(id) JULIET_PRAGMA(warning(disable : id))
|
||||||
#define JULIET_SUPPRESS_CLANG(str)
|
#define JULIET_SUPPRESS_CLANG(str)
|
||||||
#else
|
#else
|
||||||
#define JULIET_PRAGMA(x)
|
#define JULIET_PRAGMA(x)
|
||||||
@@ -27,20 +32,18 @@
|
|||||||
// 3. The Agnostic "Push/Pop"
|
// 3. The Agnostic "Push/Pop"
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define JULIET_WARNING_PUSH JULIET_PRAGMA(clang diagnostic push)
|
#define JULIET_WARNING_PUSH JULIET_PRAGMA(clang diagnostic push)
|
||||||
#define JULIET_WARNING_POP JULIET_PRAGMA(clang diagnostic pop)
|
#define JULIET_WARNING_POP JULIET_PRAGMA(clang diagnostic pop)
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define JULIET_WARNING_PUSH JULIET_PRAGMA(warning(push))
|
#define JULIET_WARNING_PUSH JULIET_PRAGMA(warning(push))
|
||||||
#define JULIET_WARNING_POP JULIET_PRAGMA(warning(pop))
|
#define JULIET_WARNING_POP JULIET_PRAGMA(warning(pop))
|
||||||
#else
|
#else
|
||||||
#define JULIET_WARNING_PUSH
|
#define JULIET_WARNING_PUSH
|
||||||
#define JULIET_WARNING_POP
|
#define JULIET_WARNING_POP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
// MSVC specific intrinsic
|
|
||||||
#define JULIET_PLATFORM_BREAK() (__nop(), __debugbreak())
|
#define JULIET_PLATFORM_BREAK() (__nop(), __debugbreak())
|
||||||
#elif defined(__clang__) || defined(__GNUC__)
|
#elif defined(__clang__) || defined(__GNUC__)
|
||||||
// Clang/GCC specific intrinsic
|
|
||||||
#define JULIET_PLATFORM_BREAK() __builtin_trap()
|
#define JULIET_PLATFORM_BREAK() __builtin_trap()
|
||||||
#else
|
#else
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -49,18 +52,14 @@
|
|||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
#define JULIET_ASSERT_INTERNAL(expression, message) \
|
#define JULIET_ASSERT_INTERNAL(expression, message) \
|
||||||
JULIET_WARNING_PUSH \
|
do \
|
||||||
JULIET_SUPPRESS_CLANG("-Wextra-semi-stmt") \
|
|
||||||
JULIET_SUPPRESS_MSVC(4127) \
|
|
||||||
JULIET_SUPPRESS_MSVC(4548) \
|
|
||||||
{ \
|
{ \
|
||||||
if (!(expression)) [[unlikely]] \
|
if (!(expression)) \
|
||||||
{ \
|
{ \
|
||||||
JulietAssert(#expression, message); \
|
JulietAssert(#expression, message, __FILE__, __func__, (uint32)__LINE__, 0); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
JULIET_WARNING_POP \
|
while (0)
|
||||||
static_assert(true, "")
|
|
||||||
|
|
||||||
#define AssertHR(hr_expression, message) \
|
#define AssertHR(hr_expression, message) \
|
||||||
do \
|
do \
|
||||||
@@ -68,7 +67,7 @@
|
|||||||
long hr_val = (hr_expression); \
|
long hr_val = (hr_expression); \
|
||||||
if (hr_val < 0) \
|
if (hr_val < 0) \
|
||||||
{ \
|
{ \
|
||||||
JulietAssert(#hr_expression, message, std::source_location::current(), hr_val); \
|
JulietAssert(#hr_expression, message, __FILE__, __func__, (uint32)__LINE__, hr_val); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
@@ -80,95 +79,70 @@
|
|||||||
#define Unimplemented() \
|
#define Unimplemented() \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
JulietAssert("UNIMPLEMENTED", "This code path is not yet functional."); \
|
JulietAssert("UNIMPLEMENTED", "This code path is not yet functional.", __FILE__, __func__, (uint32)__LINE__, 0); \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define Assert(...) ((void)0)
|
#define Assert(...) ((void)0)
|
||||||
#define AssertHR(hr_expression, message) ((void)(hr_expression))
|
#define AssertHR(hr_expression, message) ((void)(hr_expression))
|
||||||
#define Unimplemented() ((void)0)
|
#define Unimplemented() ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JULIET_API extern void JulietAssert(const char* expression, const char* message,
|
JULIET_API extern void JulietAssert(const char* expression, const char* message, const char* file, const char* function,
|
||||||
std::source_location location = std::source_location::current(), long handleResult = 0);
|
uint32 line, long handle_result);
|
||||||
|
|
||||||
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
|
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
|
||||||
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
|
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
|
||||||
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
|
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), (Pointer))
|
||||||
inline void ZeroSize(size_t size, void* ptr)
|
|
||||||
|
static inline void ZeroSize(size_t size, void* ptr)
|
||||||
{
|
{
|
||||||
auto Byte = (uint8*)ptr;
|
uint8* byte_ptr = (uint8*)ptr;
|
||||||
while (size--)
|
while (size--)
|
||||||
{
|
{
|
||||||
*Byte++ = 0;
|
*byte_ptr++ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Restrict __restrict
|
#define Restrict __restrict
|
||||||
|
|
||||||
template <class Function>
|
static inline bool8 IsValidByteBuffer(ByteBuffer buffer)
|
||||||
class DeferredFunction
|
|
||||||
{
|
{
|
||||||
public:
|
return (buffer.Size > 0 && buffer.Data != NULL);
|
||||||
explicit DeferredFunction(const Function& otherFct) noexcept
|
|
||||||
: Callback(otherFct)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit DeferredFunction(Function&& otherFct) noexcept
|
|
||||||
: Callback(std::move(otherFct))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~DeferredFunction() noexcept { Callback(); }
|
|
||||||
|
|
||||||
DeferredFunction(const DeferredFunction&) = delete;
|
|
||||||
DeferredFunction(const DeferredFunction&&) = delete;
|
|
||||||
void operator=(const DeferredFunction&) = delete;
|
|
||||||
void operator=(DeferredFunction&&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Function Callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Function>
|
|
||||||
auto Defer(Function&& fct) noexcept
|
|
||||||
{
|
|
||||||
return DeferredFunction<std::decay_t<Function>>{ std::forward<Function>(fct) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsValid(ByteBuffer buffer)
|
extern JULIET_API void FreeByteBuffer(ByteBuffer* buffer);
|
||||||
|
|
||||||
|
static inline bool8 IsPow2(uint64 x)
|
||||||
{
|
{
|
||||||
return buffer.Size > 0 && buffer.Data;
|
return (x != 0) && ((x & (x - 1)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern JULIET_API void Free(ByteBuffer& buffer);
|
static inline uint64 AlignPow2(uint64 x, uint64 alignment)
|
||||||
|
|
||||||
template <std::integral T>
|
|
||||||
[[nodiscard]] constexpr T AlignPow2(T x, T alignment)
|
|
||||||
{
|
{
|
||||||
// Safety Check:
|
Assert(IsPow2(alignment));
|
||||||
Assert(std::has_single_bit(static_cast<size_t>(alignment)));
|
|
||||||
|
|
||||||
return (x + alignment - 1) & ~(alignment - 1);
|
return (x + alignment - 1) & ~(alignment - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
static inline void SwapMemory(void* Restrict a, void* Restrict b, size_t elem_size)
|
||||||
inline void Swap(T* Restrict a, T* Restrict b)
|
|
||||||
{
|
{
|
||||||
T temp = std::move(*a);
|
uint8* pa = (uint8*)a;
|
||||||
*a = std::move(*b);
|
uint8* pb = (uint8*)b;
|
||||||
*b = std::move(temp);
|
for (size_t i = 0; i < elem_size; ++i)
|
||||||
|
{
|
||||||
|
uint8 tmp = pa[i];
|
||||||
|
pa[i] = pb[i];
|
||||||
|
pb[i] = tmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to another file dedicated to those
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define COMPILER_CLANG 1
|
#define COMPILER_CLANG 1
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define COMPILER_MSVC 1
|
#define COMPILER_MSVC 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Undef anything not defined
|
|
||||||
#if !defined(COMPILER_CLANG)
|
#if !defined(COMPILER_CLANG)
|
||||||
#define COMPILER_CLANG 0
|
#define COMPILER_CLANG 0
|
||||||
#endif
|
#endif
|
||||||
@@ -186,42 +160,33 @@ inline void Swap(T* Restrict a, T* Restrict b)
|
|||||||
#error AlignOf not defined for this compiler.
|
#error AlignOf not defined for this compiler.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
#if COMPILER_MSVC || (COMPILER_CLANG && defined(_MSC_VER))
|
||||||
[[nodiscard]] constexpr const char* GetTypeName()
|
#define ThreadLocal __declspec(thread)
|
||||||
{
|
|
||||||
#if COMPILER_CLANG
|
|
||||||
return __PRETTY_FUNCTION__;
|
|
||||||
#elif COMPILER_MSVC
|
|
||||||
return __FUNCSIG__;
|
|
||||||
#elif COMPILER_GCC
|
|
||||||
return __PRETTY_FUNCTION__;
|
|
||||||
#else
|
#else
|
||||||
return "UnknownType";
|
#define ThreadLocal __thread
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
inline uint16 safe_cast_uint16(uint32 value)
|
static inline uint16 safe_cast_uint16(uint32 value)
|
||||||
{
|
{
|
||||||
Assert(value <= uint16Max);
|
Assert(value <= uint16Max);
|
||||||
uint16 result = (uint16)value;
|
uint16 result = (uint16)value;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32 bitmask1 = 0b0000'0001;
|
#define bitmask1 0x00000001u
|
||||||
const uint32 bitmask2 = 0b0000'0011;
|
#define bitmask2 0x00000003u
|
||||||
const uint32 bitmask3 = 0b0000'0111;
|
#define bitmask3 0x00000007u
|
||||||
const uint32 bitmask4 = 0b0000'1111;
|
#define bitmask4 0x0000000fu
|
||||||
const uint32 bitmask5 = 0b0001'1111;
|
#define bitmask5 0x0000001fu
|
||||||
const uint32 bitmask6 = 0b0011'1111;
|
#define bitmask6 0x0000003fu
|
||||||
const uint32 bitmask7 = 0b0111'1111;
|
#define bitmask7 0x0000007fu
|
||||||
const uint32 bitmask8 = 0b1111'1111;
|
#define bitmask8 0x000000ffu
|
||||||
const uint32 bitmask9 = 0x0000'01ff;
|
#define bitmask9 0x000001ffu
|
||||||
const uint32 bitmask10 = 0x0000'03ff;
|
#define bitmask10 0x000003ffu
|
||||||
const uint32 bitmask11 = 0x0000'07ff;
|
#define bitmask11 0x000007ffu
|
||||||
const uint32 bitmask12 = 0x0000'0fff;
|
#define bitmask12 0x00000fffu
|
||||||
const uint32 bitmask13 = 0x0000'1fff;
|
#define bitmask13 0x00001fffu
|
||||||
const uint32 bitmask14 = 0x0000'3fff;
|
#define bitmask14 0x00003fffu
|
||||||
const uint32 bitmask15 = 0x0000'7fff;
|
#define bitmask15 0x00007fffu
|
||||||
const uint32 bitmask16 = 0x0000'ffff;
|
#define bitmask16 0x0000ffffu
|
||||||
// ...
|
#define bitmask32 0xffffffffu
|
||||||
const uint32 bitmask32 = 0xffff'ffff;
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept IsEnum = std::is_enum_v<T>;
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator~(E lhs) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(~static_cast<std::underlying_type_t<E>>(lhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator|(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(static_cast<std::underlying_type_t<E>>(lhs) | static_cast<std::underlying_type_t<E>>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E& operator|=(E& lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs = (lhs | rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator&(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(static_cast<std::underlying_type_t<E>>(lhs) & static_cast<std::underlying_type_t<E>>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E& operator&=(E& lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs = (lhs & rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator^(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(static_cast<std::underlying_type_t<E>>(lhs) ^ static_cast<std::underlying_type_t<E>>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E& operator^=(E& lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs = (lhs ^ rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr std::underlying_type_t<E> operator-(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
using T = std::underlying_type_t<E>;
|
|
||||||
return static_cast<T>(static_cast<T>(lhs) - static_cast<T>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr std::underlying_type_t<E> operator+(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
using T = std::underlying_type_t<E>;
|
|
||||||
return static_cast<T>(static_cast<T>(lhs) + static_cast<T>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator-(E lhs, std::underlying_type_t<E> rhs) noexcept
|
|
||||||
{
|
|
||||||
using T = std::underlying_type_t<E>;
|
|
||||||
return static_cast<E>(static_cast<T>(static_cast<T>(lhs) - rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator+(E lhs, std::underlying_type_t<E> rhs) noexcept
|
|
||||||
{
|
|
||||||
using T = std::underlying_type_t<E>;
|
|
||||||
return static_cast<E>(static_cast<T>(static_cast<T>(lhs) + rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr std::underlying_type_t<E> ToUnderlying(E enm) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<std::underlying_type_t<E>>(enm);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E ToEnum(std::underlying_type_t<E> value) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(value);
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
|
||||||
|
|
||||||
template <typename Type, typename OtherType>
|
|
||||||
concept NonNullPtr_Convertible = std::is_convertible_v<OtherType*, Type*>;
|
|
||||||
|
|
||||||
template <typename Type, typename OtherType>
|
|
||||||
concept NonNullPtr_SameType = std::is_same_v<OtherType*, Type*>;
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
class NonNullPtr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
constexpr NonNullPtr(Type* ptr)
|
|
||||||
: InternalPtr(ptr)
|
|
||||||
{
|
|
||||||
Assert(ptr, "Tried to initialize a NonNullPtr with a null pointer");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OtherType>
|
|
||||||
requires NonNullPtr_Convertible<OtherType*, Type*>
|
|
||||||
constexpr NonNullPtr(const NonNullPtr<OtherType>& otherPtr)
|
|
||||||
: InternalPtr(otherPtr.Get())
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "Fatal Error: Assigned a non null ptr using another NonNullPtr but its was null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assignment
|
|
||||||
[[nodiscard]] constexpr NonNullPtr& operator=(Type* ptr)
|
|
||||||
{
|
|
||||||
Assert(ptr, "Tried to assign a null pointer to a NonNullPtr!");
|
|
||||||
InternalPtr = ptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OtherType>
|
|
||||||
requires NonNullPtr_Convertible<OtherType*, Type*>
|
|
||||||
[[nodiscard]] constexpr NonNullPtr& operator=(const NonNullPtr<OtherType>& otherPtr)
|
|
||||||
{
|
|
||||||
InternalPtr = otherPtr.Get();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
[[nodiscard]] constexpr operator Type*() const
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
||||||
return InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr Type* Get() const
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
||||||
return InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr Type& operator*() const
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
||||||
return *InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr Type* operator->() const
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
||||||
return InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comparisons
|
|
||||||
[[nodiscard]] constexpr bool operator==(const NonNullPtr& otherPtr) const
|
|
||||||
{
|
|
||||||
return InternalPtr == otherPtr.InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OtherType>
|
|
||||||
requires NonNullPtr_SameType<Type, OtherType>
|
|
||||||
[[nodiscard]] constexpr bool operator==(OtherType* otherRawPtr) const
|
|
||||||
{
|
|
||||||
return InternalPtr == otherRawPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OtherType>
|
|
||||||
requires NonNullPtr_SameType<Type, OtherType>
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(OtherType* otherRawPtr, const NonNullPtr& nonNullPtr)
|
|
||||||
{
|
|
||||||
return otherRawPtr == nonNullPtr.InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forbid assigning a nullptr at compile time
|
|
||||||
constexpr NonNullPtr(std::nullptr_t)
|
|
||||||
: InternalPtr(nullptr)
|
|
||||||
{
|
|
||||||
static_assert(sizeof(Type) == 0, "Trying to initialize a NonNullPtr with a nullptr value");
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr NonNullPtr& operator=(std::nullptr_t)
|
|
||||||
{
|
|
||||||
static_assert(sizeof(Type) == 0, "Trying to assign a NonNullPtr with a nullptr value");
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr explicit operator bool() const { return InternalPtr != nullptr; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Type* InternalPtr;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
NonNullPtr(T*) -> NonNullPtr<T>;
|
|
||||||
@@ -1,78 +1,84 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/Math/MathUtils.h>
|
#include <Core/Math/MathUtils.h>
|
||||||
#include <Core/Memory/Utils.h>
|
#include <Core/Memory/Utils.h>
|
||||||
|
|
||||||
#ifdef global
|
typedef struct Arena Arena;
|
||||||
#undef global
|
|
||||||
#define RESTORE_GLOBAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RESTORE_GLOBAL
|
#define ConstString(str) ((String){ (char*)(str), sizeof(str) - 1 })
|
||||||
#define global static
|
#define ConstStringInit(str) { (char*)(str), sizeof(str) - 1 }
|
||||||
#undef RESTORE_GLOBAL
|
#define CStr(str) ((str).Str)
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Arena;
|
|
||||||
|
|
||||||
#define ConstString(str) { const_cast<char*>((str)), sizeof(str) - 1 }
|
|
||||||
#define CStr(str) ((str).Str)
|
|
||||||
#define InplaceString(name, size) \
|
#define InplaceString(name, size) \
|
||||||
char name##_[size]; \
|
char name##_[size]; \
|
||||||
MemSet(name##_, 0, sizeof(uint32)); \
|
MemSet(name##_, 0, sizeof(uint32)); \
|
||||||
String name = { name##_, 0 }
|
String name = { name##_, 0 }
|
||||||
|
|
||||||
// Everything is Little Endian
|
// Everything is Little Endian
|
||||||
enum class StringEncoding : uint8
|
typedef uint8 StringEncoding;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Unknown = 0,
|
StringEncoding_Unknown = 0,
|
||||||
ASCII,
|
StringEncoding_ASCII,
|
||||||
LATIN1,
|
StringEncoding_LATIN1,
|
||||||
UTF8,
|
StringEncoding_UTF8,
|
||||||
UTF16,
|
StringEncoding_UTF16,
|
||||||
UTF32,
|
StringEncoding_UTF32,
|
||||||
UCS2,
|
StringEncoding_UCS2,
|
||||||
UCS4,
|
StringEncoding_UCS4,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Represents a UTF-8 String.
|
// Represents a UTF-8 String.
|
||||||
// Not null terminated.
|
// Not null terminated.
|
||||||
|
typedef struct String8 String8;
|
||||||
struct String8
|
struct String8
|
||||||
{
|
{
|
||||||
char* Str;
|
char* Str;
|
||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
using String = String8;
|
typedef String8 String;
|
||||||
|
|
||||||
|
typedef struct String16 String16;
|
||||||
struct String16
|
struct String16
|
||||||
{
|
{
|
||||||
uint16* Str;
|
uint16* Str;
|
||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StringBuffer : String
|
typedef struct StringBuffer StringBuffer;
|
||||||
|
struct StringBuffer
|
||||||
{
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
String8 str8;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char* Str;
|
||||||
|
size_t Size;
|
||||||
|
};
|
||||||
|
};
|
||||||
size_t Capacity;
|
size_t Capacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct UnicodeDecode UnicodeDecode;
|
||||||
struct UnicodeDecode
|
struct UnicodeDecode
|
||||||
{
|
{
|
||||||
uint32 Increment;
|
uint32 Increment;
|
||||||
uint32 Codepoint;
|
uint32 Codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr uint32 kInvalidUTF8 = 0xFFFD;
|
#define kInvalidUTF8 ((uint32)0xFFFDu)
|
||||||
|
|
||||||
inline size_t StringLength(String str)
|
static inline size_t StringLength(String str)
|
||||||
{
|
{
|
||||||
return str.Size;
|
return str.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t StringLength(const char* str)
|
static inline size_t StringLengthCStr(const char* str)
|
||||||
{
|
{
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
if (str)
|
if (str != NULL)
|
||||||
{
|
{
|
||||||
while (*str)
|
while (*str)
|
||||||
{
|
{
|
||||||
@@ -84,47 +90,46 @@ inline size_t StringLength(const char* str)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsValid(String str)
|
static inline bool8 IsValidString(String str)
|
||||||
{
|
{
|
||||||
return str.Size > 0 && str.Str != nullptr && *str.Str;
|
return (str.Size > 0 && str.Str != NULL && *str.Str != '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String WrapString(const char* str)
|
static inline String WrapString(const char* str)
|
||||||
{
|
{
|
||||||
String result = {};
|
String result = { 0 };
|
||||||
result.Str = const_cast<char*>(str);
|
result.Str = (char*)str;
|
||||||
result.Size = str ? strlen(str) : 0;
|
result.Size = (str != NULL) ? strlen(str) : 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String FindChar(String str, char c)
|
static inline String FindChar(String str, char c)
|
||||||
{
|
{
|
||||||
String result = str;
|
String result = { 0 };
|
||||||
while (result.Size)
|
String cursor = str;
|
||||||
|
while (cursor.Size > 0)
|
||||||
{
|
{
|
||||||
if (*result.Str != c)
|
if (*cursor.Str == c)
|
||||||
{
|
{
|
||||||
++result.Str;
|
result = cursor;
|
||||||
--result.Size;
|
break;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
++cursor.Str;
|
||||||
|
--cursor.Size;
|
||||||
}
|
}
|
||||||
return {};
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool ContainsChar(String str, char c)
|
static inline bool8 ContainsChar(String str, char c)
|
||||||
{
|
{
|
||||||
return IsValid(FindChar(str, c));
|
return IsValidString(FindChar(str, c));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return:
|
// Return:
|
||||||
// - < 0 if str1 < str2
|
// - < 0 if str1 < str2
|
||||||
// - = 0 : Both strings are equals
|
// - = 0 : Both strings are equals
|
||||||
// - > 0 if str1 > str2
|
// - > 0 if str1 > str2
|
||||||
inline int32 StringCompare(String str1, String str2)
|
static inline int32 StringCompare(String str1, String str2)
|
||||||
{
|
{
|
||||||
size_t len1 = StringLength(str1);
|
size_t len1 = StringLength(str1);
|
||||||
size_t len2 = StringLength(str2);
|
size_t len2 = StringLength(str2);
|
||||||
@@ -134,62 +139,47 @@ inline int32 StringCompare(String str1, String str2)
|
|||||||
{
|
{
|
||||||
if (len1 > len2)
|
if (len1 > len2)
|
||||||
{
|
{
|
||||||
return 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
if (len1 < len2)
|
else if (len1 < len2)
|
||||||
{
|
{
|
||||||
return -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
JULIET_API uint32 StepUTF8(String& inStr);
|
JULIET_API uint32 StepUTF8(String* inStr);
|
||||||
JULIET_API String FindString(String strLeft, String strRight);
|
JULIET_API String FindString(String strLeft, String strRight);
|
||||||
|
|
||||||
// Case insensitive compare. Supports ASCII only
|
// Case insensitive compare. Supports ASCII only
|
||||||
// TODO: Support UNICODE
|
|
||||||
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
|
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
|
||||||
|
|
||||||
// Do not allocate anything, you must allocate your out buffer yourself
|
extern JULIET_API bool8 ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer* dst, bool8 nullTerminate);
|
||||||
// TODO: Version taking arena that can allocate
|
extern JULIET_API bool8 ConvertStringByName(String from, String to, String src, StringBuffer* dst, bool8 nullTerminate);
|
||||||
// Do not take String type because we dont know the string encoding we are going from/to
|
|
||||||
// src and dst will be casted based on the encoding.
|
|
||||||
// size will correspond to the number of characters
|
|
||||||
// Will convert \0 character if present.
|
|
||||||
extern JULIET_API bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst, bool nullTerminate);
|
|
||||||
extern JULIET_API bool ConvertString(String from, String to, String src, StringBuffer& dst, bool nullTerminate);
|
|
||||||
|
|
||||||
JULIET_API String StringCopy(NonNullPtr<Arena> arena, String str);
|
JULIET_API String StringCopy(Arena* arena, String str);
|
||||||
JULIET_API String16 str16_from_8(NonNullPtr<Arena> arena, String8 str);
|
JULIET_API String16 str16_from_8(Arena* arena, String8 str);
|
||||||
|
|
||||||
String trim_whitespace(String str);
|
String trim_whitespace(String str);
|
||||||
|
|
||||||
template <typename... Args>
|
JULIET_API String StringFormatV(Arena* arena, const char* formatStr, va_list args);
|
||||||
String Format(NonNullPtr<Arena> arena, const char* formatStr, Args&&... args)
|
JULIET_API String StringFormat(Arena* arena, const char* formatStr, ...);
|
||||||
{
|
|
||||||
std::string result = std::vformat(formatStr, std::make_format_args(args...));
|
|
||||||
return StringCopy(arena, WrapString(result.c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define juliet_snprintf snprintf
|
#define juliet_snprintf snprintf
|
||||||
|
|
||||||
#ifdef UNIT_TEST
|
#ifdef UNIT_TEST
|
||||||
namespace UnitTest
|
static inline void UnitTest_TestFindChar(void)
|
||||||
{
|
{
|
||||||
inline void TestFindChar()
|
String s1 = ConstString("");
|
||||||
{
|
String s2 = ConstString("abcdefabcdef");
|
||||||
String s1 = ConstString("");
|
String s3 = ConstString("11111111111111111111");
|
||||||
String s2 = ConstString("abcdefabcdef");
|
|
||||||
String s3 = ConstString("11111111111111111111");
|
|
||||||
|
|
||||||
Assert(FindChar(s1, 'x').Str == nullptr);
|
Assert(FindChar(s1, 'x').Str == NULL);
|
||||||
Assert(FindChar(s2, 'y').Str == nullptr);
|
Assert(FindChar(s2, 'y').Str == NULL);
|
||||||
Assert(FindChar(s2, 'a').Str - s2.Str == 0);
|
Assert(FindChar(s2, 'a').Str - s2.Str == 0);
|
||||||
Assert(FindChar(s2, 'd').Str - s2.Str == 3);
|
Assert(FindChar(s2, 'd').Str - s2.Str == 3);
|
||||||
Assert(FindChar(s2, 'f').Str - s2.Str == 5);
|
Assert(FindChar(s2, 'f').Str - s2.Str == 5);
|
||||||
Assert(FindChar(s3, '1').Str - s3.Str == 0);
|
Assert(FindChar(s3, '1').Str - s3.Str == 0);
|
||||||
}
|
}
|
||||||
} // namespace UnitTest
|
|
||||||
#endif
|
#endif
|
||||||
@@ -2,125 +2,102 @@
|
|||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
#include <Core/Common/CRC32.h>
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
#include <Core/HAL/IO/IOStream.h>
|
#include <Core/HAL/IO/IOStream.h>
|
||||||
|
#include <Core/Math/Vector.h>
|
||||||
|
|
||||||
// .jasset
|
typedef struct IOStream IOStream;
|
||||||
// AssetFile ::= { CommentLine | EmptyLine | PropertyDeclaration } ;
|
typedef struct Arena Arena;
|
||||||
// CommentLine ::= ( "#" | "//" ) { Character } LineEnding ;
|
typedef struct ArchivePropertyNode ArchivePropertyNode;
|
||||||
// EmptyLine ::= { Whitespace } LineEnding ;
|
typedef struct ParsedArchive ParsedArchive;
|
||||||
// PropertyDeclaration ::= KeyHeader LineEnding ValueBlock ;
|
typedef struct Archive Archive;
|
||||||
// KeyHeader ::= ";" { Whitespace } Identifier ;
|
|
||||||
// ValueBlock ::= { ValueLine LineEnding } ;
|
|
||||||
// ValueLine ::= { Whitespace } ValueString { Whitespace } ;
|
|
||||||
// LineEnding ::= "\r\n" | "\n" ;
|
|
||||||
// Identifier ::= [a-zA-Z_][a-zA-Z0-9_]* ;
|
|
||||||
|
|
||||||
struct Vector4;
|
|
||||||
struct IOStream;
|
|
||||||
struct Arena;
|
|
||||||
|
|
||||||
struct ArchivePropertyNode
|
struct ArchivePropertyNode
|
||||||
{
|
{
|
||||||
String key;
|
String key;
|
||||||
String value;
|
String value;
|
||||||
uint32 key_crc;
|
uint32 key_crc;
|
||||||
bool consumed;
|
bool8 consumed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ParsedArchive
|
struct ParsedArchive
|
||||||
{
|
{
|
||||||
ArchivePropertyNode* nodes = nullptr;
|
ArchivePropertyNode* nodes;
|
||||||
uint32 property_count = 0;
|
uint32 property_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Archive
|
struct Archive
|
||||||
{
|
{
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
bool loading;
|
bool8 loading;
|
||||||
ParsedArchive base = {};
|
ParsedArchive base;
|
||||||
IOStream* stream = nullptr;
|
IOStream* stream;
|
||||||
|
|
||||||
// to remove
|
void* base_ptr;
|
||||||
void* base_ptr = nullptr;
|
index_t offset;
|
||||||
index_t offset = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JULIET_API void serialize(Archive& ar, void* data, size_t size);
|
JULIET_API void serialize_bytes(Archive* ar, void* data, size_t size);
|
||||||
|
|
||||||
#define serialize_elem(ar, val) serialize((ar), &(val), sizeof(val))
|
#define serialize_elem(ar, val) serialize_bytes((ar), &(val), sizeof(val))
|
||||||
|
|
||||||
JULIET_API ParsedArchive tokenize_archive(NonNullPtr<Arena> arena, ByteBuffer file_buffer);
|
JULIET_API ParsedArchive tokenize_archive(Arena* arena, ByteBuffer file_buffer);
|
||||||
JULIET_API ArchivePropertyNode* find_property(NonNullPtr<ParsedArchive> archive, uint32 property_crc);
|
JULIET_API ArchivePropertyNode* find_property(ParsedArchive* archive, uint32 property_crc);
|
||||||
JULIET_API void write_property_header(Archive& archive, String property_name);
|
JULIET_API void write_property_header(Archive* archive, String property_name);
|
||||||
|
|
||||||
JULIET_API bool read_prop(Archive& ar, String value_raw, String& value);
|
JULIET_API bool8 read_prop_str(Archive* ar, String value_raw, String* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, String value);
|
JULIET_API void write_str(IOStream* stream, String value);
|
||||||
JULIET_API bool read(const char* buffer, float& value, const char** end = nullptr);
|
JULIET_API bool8 read_f32(const char* buffer, float* value, const char** end);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, float value);
|
JULIET_API void write_f32(IOStream* stream, float value);
|
||||||
JULIET_API bool read(const char* buffer, int8& value);
|
JULIET_API bool8 read_i8(const char* buffer, int8* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, int8 value);
|
JULIET_API void write_i8(IOStream* stream, int8 value);
|
||||||
JULIET_API bool read(const char* buffer, int16& value);
|
JULIET_API bool8 read_i16(const char* buffer, int16* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, int16 value);
|
JULIET_API void write_i16(IOStream* stream, int16 value);
|
||||||
JULIET_API bool read(const char* buffer, int32& value);
|
JULIET_API bool8 read_i32(const char* buffer, int32* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, int32 value);
|
JULIET_API void write_i32(IOStream* stream, int32 value);
|
||||||
JULIET_API bool read(const char* buffer, int64& value);
|
JULIET_API bool8 read_i64(const char* buffer, int64* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, int64 value);
|
JULIET_API void write_i64(IOStream* stream, int64 value);
|
||||||
JULIET_API bool read(const char* buffer, uint8& value);
|
JULIET_API bool8 read_u8(const char* buffer, uint8* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, uint8 value);
|
JULIET_API void write_u8(IOStream* stream, uint8 value);
|
||||||
JULIET_API bool read(const char* buffer, uint16& value);
|
JULIET_API bool8 read_u16(const char* buffer, uint16* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, uint16 value);
|
JULIET_API void write_u16(IOStream* stream, uint16 value);
|
||||||
JULIET_API bool read(const char* buffer, uint32& value);
|
JULIET_API bool8 read_u32(const char* buffer, uint32* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, uint32 value);
|
JULIET_API void write_u32(IOStream* stream, uint32 value);
|
||||||
JULIET_API bool read(const char* buffer, uint64& value);
|
JULIET_API bool8 read_u64(const char* buffer, uint64* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, uint64 value);
|
JULIET_API void write_u64(IOStream* stream, uint64 value);
|
||||||
JULIET_API bool read(const char* buffer, bool& value);
|
JULIET_API bool8 read_b8(const char* buffer, bool8* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, bool value);
|
JULIET_API void write_b8(IOStream* stream, bool8 value);
|
||||||
JULIET_API bool read(const char* buffer, Vector4& value);
|
JULIET_API bool8 read_vec4(const char* buffer, Vector4* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, Vector4 value);
|
JULIET_API void write_vec4(IOStream* stream, Vector4 value);
|
||||||
|
|
||||||
// For primitives not needing archive nor allocation
|
JULIET_API bool8 serialize_str(Archive* ar, String property_name, String* value);
|
||||||
template <typename Type>
|
JULIET_API bool8 serialize_f32(Archive* ar, String property_name, float* value);
|
||||||
bool read_prop(Archive& /*ar*/, String value_raw, Type& value)
|
JULIET_API bool8 serialize_i8(Archive* ar, String property_name, int8* value);
|
||||||
{
|
JULIET_API bool8 serialize_i16(Archive* ar, String property_name, int16* value);
|
||||||
char buffer[64];
|
JULIET_API bool8 serialize_i32(Archive* ar, String property_name, int32* value);
|
||||||
size_t cpy_size = Min(value_raw.Size, sizeof(buffer) - 1);
|
JULIET_API bool8 serialize_i64(Archive* ar, String property_name, int64* value);
|
||||||
MemCopy(buffer, value_raw.Str, cpy_size);
|
JULIET_API bool8 serialize_u8(Archive* ar, String property_name, uint8* value);
|
||||||
buffer[cpy_size] = '\0';
|
JULIET_API bool8 serialize_u16(Archive* ar, String property_name, uint16* value);
|
||||||
|
JULIET_API bool8 serialize_u32(Archive* ar, String property_name, uint32* value);
|
||||||
|
JULIET_API bool8 serialize_u64(Archive* ar, String property_name, uint64* value);
|
||||||
|
JULIET_API bool8 serialize_b8(Archive* ar, String property_name, bool8* value);
|
||||||
|
JULIET_API bool8 serialize_vec4(Archive* ar, String property_name, Vector4* value);
|
||||||
|
|
||||||
return read(buffer, value);
|
#define SERIALIZE_STR(ar, name, var_ptr) serialize_str((ar), ConstString(#name), (var_ptr))
|
||||||
}
|
#define SERIALIZE_F32(ar, name, var_ptr) serialize_f32((ar), ConstString(#name), (var_ptr))
|
||||||
|
#define SERIALIZE_I8(ar, name, var_ptr) serialize_i8((ar), ConstString(#name), (var_ptr))
|
||||||
#define SERIALIZE(ar, name, var) serialize((ar), ConstString(#name), #name##_crc32, (var))
|
#define SERIALIZE_I16(ar, name, var_ptr) serialize_i16((ar), ConstString(#name), (var_ptr))
|
||||||
#define SERIALIZE_SIMPLE(ar, var) SERIALIZE(ar, var, var)
|
#define SERIALIZE_I32(ar, name, var_ptr) serialize_i32((ar), ConstString(#name), (var_ptr))
|
||||||
|
#define SERIALIZE_I64(ar, name, var_ptr) serialize_i64((ar), ConstString(#name), (var_ptr))
|
||||||
template <typename Type>
|
#define SERIALIZE_U8(ar, name, var_ptr) serialize_u8((ar), ConstString(#name), (var_ptr))
|
||||||
bool serialize(Archive& ar, String property_name, uint32 property_crc, Type& value)
|
#define SERIALIZE_U16(ar, name, var_ptr) serialize_u16((ar), ConstString(#name), (var_ptr))
|
||||||
{
|
#define SERIALIZE_U32(ar, name, var_ptr) serialize_u32((ar), ConstString(#name), (var_ptr))
|
||||||
Assert(IsValid(property_name));
|
#define SERIALIZE_U64(ar, name, var_ptr) serialize_u64((ar), ConstString(#name), (var_ptr))
|
||||||
|
#define SERIALIZE_B8(ar, name, var_ptr) serialize_b8((ar), ConstString(#name), (var_ptr))
|
||||||
bool result = false;
|
#define SERIALIZE_BOOL(ar, name, var_ptr) serialize_b8((ar), ConstString(#name), (var_ptr))
|
||||||
if (ar.loading)
|
#define SERIALIZE_VEC4(ar, name, var_ptr) serialize_vec4((ar), ConstString(#name), (var_ptr))
|
||||||
{
|
|
||||||
if (auto* prop = find_property(&ar.base, property_crc))
|
|
||||||
{
|
|
||||||
if (read_prop(ar, prop->value, value))
|
|
||||||
{
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Save
|
|
||||||
write_property_header(ar, property_name);
|
|
||||||
write(ar.stream, value);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
JULIET_API void audit_unconsumed_properties(NonNullPtr<ParsedArchive> archive, String context_name);
|
JULIET_API void audit_unconsumed_properties(ParsedArchive* archive, String context_name);
|
||||||
#endif
|
#endif
|
||||||
@@ -1,211 +1,232 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
#include <Core/Memory/Utils.h>
|
||||||
|
|
||||||
template <typename Type, size_t ReserveSize = 16>
|
typedef struct VectorArena VectorArena;
|
||||||
struct VectorArena
|
struct VectorArena
|
||||||
{
|
{
|
||||||
void Create(NonNullPtr<Arena> arena JULIET_DEBUG_PARAM(const char* name = nullptr))
|
Arena* Arena;
|
||||||
|
void* DataFirst;
|
||||||
|
void* DataLast;
|
||||||
|
void* Data;
|
||||||
|
union
|
||||||
{
|
{
|
||||||
Assert(!Arena);
|
size_t Count;
|
||||||
|
size_t Size;
|
||||||
JULIET_DEBUG_ONLY(Name = name ? name : Name;)
|
};
|
||||||
|
size_t Capacity;
|
||||||
DataFirst = DataLast = Data = nullptr;
|
size_t ElemSize;
|
||||||
Count = 0;
|
size_t ElemAlign;
|
||||||
Capacity = 0;
|
size_t ReserveSize;
|
||||||
Arena = arena;
|
JULIET_DEBUG_ONLY(const char* Name;)
|
||||||
|
|
||||||
Reserve(ReserveSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Destroy()
|
|
||||||
{
|
|
||||||
DataFirst = DataLast = Data = nullptr;
|
|
||||||
Count = 0;
|
|
||||||
Capacity = 0;
|
|
||||||
Arena = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reserve(size_t newCapacity)
|
|
||||||
{
|
|
||||||
Assert(Arena);
|
|
||||||
Assert(newCapacity <= ReserveSize && "VectorArena capacity should be <= ReserveSize.");
|
|
||||||
|
|
||||||
if (Data == nullptr)
|
|
||||||
{
|
|
||||||
Data = ArenaPushArray<Type>(Arena, newCapacity JULIET_DEBUG_PARAM(Name));
|
|
||||||
Capacity = newCapacity;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Unimplemented();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Resize(size_t newCount)
|
|
||||||
{
|
|
||||||
Assert(Arena);
|
|
||||||
if (newCount == Count)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Data == nullptr)
|
|
||||||
{
|
|
||||||
size_t initialCapacity = newCount > ReserveSize ? newCount : ReserveSize;
|
|
||||||
Reserve(initialCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert(newCount <= Capacity && "VectorArena capacity exceeded!");
|
|
||||||
Count = newCount;
|
|
||||||
|
|
||||||
if (Count > 0)
|
|
||||||
{
|
|
||||||
DataFirst = Data;
|
|
||||||
DataLast = Data + Count - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DataFirst = DataLast = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushBack(const Type* buffer, size_t amount)
|
|
||||||
{
|
|
||||||
Assert(Arena);
|
|
||||||
Assert(buffer || amount == 0);
|
|
||||||
|
|
||||||
if (amount == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Data == nullptr)
|
|
||||||
{
|
|
||||||
size_t initialCapacity = amount > ReserveSize ? amount : ReserveSize;
|
|
||||||
Reserve(initialCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert(Count + amount <= Capacity && "VectorArena capacity exceeded!");
|
|
||||||
|
|
||||||
Type* dst = Data + Count;
|
|
||||||
MemCopy(dst, buffer, amount * sizeof(Type));
|
|
||||||
|
|
||||||
if (Count == 0)
|
|
||||||
{
|
|
||||||
DataFirst = dst;
|
|
||||||
}
|
|
||||||
DataLast = dst + amount - 1;
|
|
||||||
Count += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushBack(const Type& value)
|
|
||||||
{
|
|
||||||
Assert(Arena);
|
|
||||||
|
|
||||||
if (Data == nullptr)
|
|
||||||
{
|
|
||||||
Reserve(ReserveSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert(Count + 1 <= Capacity && "VectorArena capacity exceeded!");
|
|
||||||
|
|
||||||
Type* entry = Data + Count;
|
|
||||||
*entry = value;
|
|
||||||
|
|
||||||
if (Count == 0)
|
|
||||||
{
|
|
||||||
DataFirst = entry;
|
|
||||||
}
|
|
||||||
DataLast = entry;
|
|
||||||
++Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushBack(Type&& value)
|
|
||||||
{
|
|
||||||
Assert(Arena);
|
|
||||||
|
|
||||||
if (Data == nullptr)
|
|
||||||
{
|
|
||||||
Reserve(ReserveSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert(Count + 1 <= Capacity && "VectorArena capacity exceeded!");
|
|
||||||
|
|
||||||
Type* entry = Data + Count;
|
|
||||||
*entry = std::move(value);
|
|
||||||
|
|
||||||
if (Count == 0)
|
|
||||||
{
|
|
||||||
DataFirst = entry;
|
|
||||||
}
|
|
||||||
DataLast = entry;
|
|
||||||
++Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveAtFast(index_t index)
|
|
||||||
{
|
|
||||||
Assert(Arena);
|
|
||||||
Assert(index < Count);
|
|
||||||
Assert(Count > 0);
|
|
||||||
|
|
||||||
Type* elementAdr = DataFirst + index;
|
|
||||||
|
|
||||||
// Swap DataLast and element
|
|
||||||
if (DataLast != elementAdr)
|
|
||||||
{
|
|
||||||
Swap(DataLast, elementAdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
--DataLast;
|
|
||||||
--Count;
|
|
||||||
|
|
||||||
if (Count == 0)
|
|
||||||
{
|
|
||||||
DataFirst = DataLast = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
Assert(Arena);
|
|
||||||
|
|
||||||
DataFirst = DataLast = nullptr;
|
|
||||||
Count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool IsEmpty() const { return Count == 0; }
|
|
||||||
|
|
||||||
// C++ Accessors for loop supports and Index based access
|
|
||||||
[[nodiscard]] Type& operator[](size_t index) { return DataFirst[index]; }
|
|
||||||
[[nodiscard]] const Type& operator[](size_t index) const { return DataFirst[index]; }
|
|
||||||
|
|
||||||
[[nodiscard]] Type* begin() { return DataFirst; }
|
|
||||||
[[nodiscard]] Type* end() { return DataFirst + Count; }
|
|
||||||
|
|
||||||
[[nodiscard]] const Type* begin() const { return DataFirst; }
|
|
||||||
[[nodiscard]] const Type* end() const { return DataFirst + Count; }
|
|
||||||
|
|
||||||
[[nodiscard]] Type* First() { return DataFirst; }
|
|
||||||
[[nodiscard]] Type* Front() { return DataFirst; }
|
|
||||||
[[nodiscard]] Type* Last() { return DataLast; }
|
|
||||||
[[nodiscard]] Type* Back() { return DataLast; }
|
|
||||||
[[nodiscard]] Type* DataPtr() { return Data; }
|
|
||||||
[[nodiscard]] const Type* DataPtr() const { return Data; }
|
|
||||||
|
|
||||||
[[nodiscard]] size_t Size() const { return Count; }
|
|
||||||
|
|
||||||
Arena* Arena = nullptr;
|
|
||||||
Type* DataFirst = nullptr;
|
|
||||||
Type* DataLast = nullptr;
|
|
||||||
Type* Data = nullptr;
|
|
||||||
size_t Count = 0;
|
|
||||||
size_t Capacity = 0;
|
|
||||||
JULIET_DEBUG_ONLY(const char* Name = "VectorArena";)
|
|
||||||
};
|
};
|
||||||
static_assert(std::is_standard_layout_v<VectorArena<int>>,
|
|
||||||
"VectorArena must have a standard layout to remain POD-like.");
|
#define kDefaultVectorReserveSize ((size_t)16)
|
||||||
static_assert(std::is_trivially_copyable_v<VectorArena<int>>,
|
#define kVectorArenaDefaultReserveSize ((size_t)16)
|
||||||
"VectorArena must be trivially copyable (no custom destructors/assignment).");
|
|
||||||
|
static inline void vector_arena_reserve(VectorArena* vec, size_t new_capacity)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
Assert(vec->Arena != NULL);
|
||||||
|
Assert(new_capacity <= vec->ReserveSize && "VectorArena capacity should be <= ReserveSize.");
|
||||||
|
|
||||||
|
if (vec->Data == NULL)
|
||||||
|
{
|
||||||
|
vec->Data = ArenaPush(vec->Arena, new_capacity * vec->ElemSize, Max(8ull, (uint64)vec->ElemAlign),
|
||||||
|
true JULIET_DEBUG_PARAM(vec->Name));
|
||||||
|
vec->Capacity = new_capacity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Unimplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vector_arena_create(VectorArena* vec, Arena* arena, size_t elem_size, size_t elem_align,
|
||||||
|
size_t reserve_size JULIET_DEBUG_PARAM(const char* name))
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
Assert(arena != NULL);
|
||||||
|
Assert(vec->Arena == NULL);
|
||||||
|
Assert(elem_size > 0);
|
||||||
|
|
||||||
|
JULIET_DEBUG_ONLY(vec->Name = (name != NULL) ? name : "VectorArena";)
|
||||||
|
|
||||||
|
vec->DataFirst = NULL;
|
||||||
|
vec->DataLast = NULL;
|
||||||
|
vec->Data = NULL;
|
||||||
|
vec->Count = 0;
|
||||||
|
vec->Capacity = 0;
|
||||||
|
vec->ElemSize = elem_size;
|
||||||
|
vec->ElemAlign = elem_align;
|
||||||
|
vec->ReserveSize = (reserve_size > 0) ? reserve_size : 16;
|
||||||
|
vec->Arena = arena;
|
||||||
|
|
||||||
|
vector_arena_reserve(vec, vec->ReserveSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vector_arena_destroy(VectorArena* vec)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
vec->DataFirst = NULL;
|
||||||
|
vec->DataLast = NULL;
|
||||||
|
vec->Data = NULL;
|
||||||
|
vec->Count = 0;
|
||||||
|
vec->Capacity = 0;
|
||||||
|
vec->Arena = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void* vector_arena_begin(VectorArena* vec)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
return vec->DataFirst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const void* vector_arena_begin_const(const VectorArena* vec)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
return vec->DataFirst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void* vector_arena_end(VectorArena* vec)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
void* result = NULL;
|
||||||
|
if (vec->DataFirst != NULL)
|
||||||
|
{
|
||||||
|
result = (Byte*)vec->DataFirst + (vec->Count * vec->ElemSize);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const void* vector_arena_end_const(const VectorArena* vec)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
const void* result = NULL;
|
||||||
|
if (vec->DataFirst != NULL)
|
||||||
|
{
|
||||||
|
result = (const Byte*)vec->DataFirst + (vec->Count * vec->ElemSize);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vector_arena_resize(VectorArena* vec, size_t new_size)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
Assert(new_size <= vec->Capacity);
|
||||||
|
vec->Count = new_size;
|
||||||
|
if (vec->Count > 0)
|
||||||
|
{
|
||||||
|
vec->DataFirst = vec->Data;
|
||||||
|
vec->DataLast = (Byte*)vec->Data + ((vec->Count - 1) * vec->ElemSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec->DataFirst = NULL;
|
||||||
|
vec->DataLast = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vector_arena_push_buffer(VectorArena* vec, const void* buffer, size_t amount)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
Assert(buffer != NULL);
|
||||||
|
Assert(amount > 0);
|
||||||
|
Assert(vec->Count + amount <= vec->Capacity && "VectorArena capacity exceeded!");
|
||||||
|
|
||||||
|
Byte* dest = (Byte*)vec->Data + (vec->Count * vec->ElemSize);
|
||||||
|
MemCopy(dest, buffer, amount * vec->ElemSize);
|
||||||
|
|
||||||
|
if (vec->DataFirst == NULL)
|
||||||
|
{
|
||||||
|
vec->DataFirst = vec->Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->Count += amount;
|
||||||
|
vec->DataLast = (Byte*)vec->Data + ((vec->Count - 1) * vec->ElemSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define vector_arena_push_array vector_arena_push_buffer
|
||||||
|
|
||||||
|
static inline void vector_arena_push_elem(VectorArena* vec, const void* value_ptr)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
Assert(value_ptr != NULL);
|
||||||
|
Assert(vec->Count + 1 <= vec->Capacity && "VectorArena capacity exceeded!");
|
||||||
|
|
||||||
|
Byte* dest = (Byte*)vec->Data + (vec->Count * vec->ElemSize);
|
||||||
|
MemCopy(dest, value_ptr, vec->ElemSize);
|
||||||
|
|
||||||
|
if (vec->DataFirst == NULL)
|
||||||
|
{
|
||||||
|
vec->DataFirst = vec->Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->Count += 1;
|
||||||
|
vec->DataLast = dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vector_arena_remove_at_fast(VectorArena* vec, index_t index)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
Assert(index < vec->Count);
|
||||||
|
|
||||||
|
size_t last_idx = vec->Count - 1;
|
||||||
|
if (index != last_idx)
|
||||||
|
{
|
||||||
|
Byte* dst = (Byte*)vec->DataFirst + (index * vec->ElemSize);
|
||||||
|
Byte* src = (Byte*)vec->DataFirst + (last_idx * vec->ElemSize);
|
||||||
|
MemCopy(dst, src, vec->ElemSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->Count -= 1;
|
||||||
|
if (vec->Count == 0)
|
||||||
|
{
|
||||||
|
vec->DataFirst = NULL;
|
||||||
|
vec->DataLast = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec->DataLast = (Byte*)vec->DataFirst + ((vec->Count - 1) * vec->ElemSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vector_arena_clear(VectorArena* vec)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
vec->DataFirst = NULL;
|
||||||
|
vec->DataLast = NULL;
|
||||||
|
vec->Count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool8 vector_arena_is_empty(const VectorArena* vec)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
return vec->Count == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t vector_arena_size(const VectorArena* vec)
|
||||||
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
return vec->Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VectorArenaCreate(vec, Type, arena, ...) \
|
||||||
|
vector_arena_create((vec), (arena), sizeof(Type), AlignOf(Type), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define VectorArenaAt(Type, vec, idx) (((Type*)((vec)->DataFirst))[idx])
|
||||||
|
#define VectorArenaData(Type, vec) ((Type*)((vec)->Data))
|
||||||
|
#define VectorArenaBegin(Type, vec) ((Type*)((vec)->DataFirst))
|
||||||
|
#define VectorArenaEnd(Type, vec) (((vec)->DataFirst != NULL) ? (((Type*)((vec)->DataFirst)) + (vec)->Count) : NULL)
|
||||||
|
#define VectorArenaLast(Type, vec) ((Type*)((vec)->DataLast))
|
||||||
|
#define VectorArenaBack(Type, vec) ((Type*)((vec)->DataLast))
|
||||||
|
#define VectorArenaPushPtr(Type, vec, ptr) vector_arena_push_elem((vec), (ptr))
|
||||||
|
#define VectorArenaPushVal(Type, vec, val) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
Type _vec_tmp_val = (val); \
|
||||||
|
vector_arena_push_elem((vec), &_vec_tmp_val); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
struct Window;
|
typedef struct Window Window;
|
||||||
|
|
||||||
using WindowID = uint8;
|
typedef uint8 WindowID;
|
||||||
extern JULIET_API Window* CreatePlatformWindow(const char* title, uint16 width, uint16 height, int flags = 0 /* unused */);
|
|
||||||
extern JULIET_API void DestroyPlatformWindow(NonNullPtr<Window> window);
|
|
||||||
|
|
||||||
extern JULIET_API void ShowWindow(NonNullPtr<Window> window);
|
extern JULIET_API Window* CreatePlatformWindow(const char* title, uint16 width, uint16 height, int flags);
|
||||||
extern JULIET_API void HideWindow(NonNullPtr<Window> window);
|
extern JULIET_API void DestroyPlatformWindow(Window* window);
|
||||||
|
|
||||||
extern JULIET_API WindowID GetWindowID(NonNullPtr<Window> window);
|
extern JULIET_API void ShowPlatformWindow(Window* window);
|
||||||
extern JULIET_API void SetWindowTitle(NonNullPtr<Window> window, String title);
|
extern JULIET_API void HidePlatformWindow(Window* window);
|
||||||
|
|
||||||
|
extern JULIET_API WindowID GetWindowID(Window* window);
|
||||||
|
extern JULIET_API void SetWindowTitle(Window* window, String title);
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
struct DynamicLibrary;
|
typedef struct DynamicLibrary DynamicLibrary;
|
||||||
|
|
||||||
extern JULIET_API DynamicLibrary* LoadDynamicLibrary(const char* filename);
|
extern JULIET_API DynamicLibrary* LoadDynamicLibrary(const char* filename);
|
||||||
extern JULIET_API FunctionPtr LoadFunction(NonNullPtr<DynamicLibrary> lib, const char* functionName);
|
extern JULIET_API FunctionPtr LoadFunction(DynamicLibrary* lib, const char* functionName);
|
||||||
extern JULIET_API void UnloadDynamicLibrary(NonNullPtr<DynamicLibrary> lib);
|
extern JULIET_API void UnloadDynamicLibrary(DynamicLibrary* lib);
|
||||||
@@ -1,53 +1,57 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/HAL/Display/Display.h>
|
#include <Core/HAL/Display/Display.h>
|
||||||
#include <Core/HAL/Keyboard/Keyboard.h>
|
#include <Core/HAL/Keyboard/Keyboard.h>
|
||||||
#include <Core/HAL/Keyboard/KeyCode.h>
|
#include <Core/HAL/Keyboard/KeyCode.h>
|
||||||
#include <Core/HAL/Mouse/Mouse.h>
|
#include <Core/HAL/Mouse/Mouse.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
// Handles all events from systems handling the Hardware
|
typedef uint32 EventType;
|
||||||
// Very inspired by SDL3
|
enum
|
||||||
|
|
||||||
enum class EventType : uint32
|
|
||||||
{
|
{
|
||||||
None = 0,
|
EventType_None = 0,
|
||||||
First = None,
|
EventType_First = EventType_None,
|
||||||
|
|
||||||
// Application Events
|
// Application Events
|
||||||
// User querying an exit
|
EventType_Application_Exit = 100,
|
||||||
Application_Exit = 100,
|
EventType_Application_OS_Terminate = 101,
|
||||||
// OS terminating the application
|
EventType_Application_Begin = EventType_Application_Exit,
|
||||||
Application_OS_Terminate,
|
EventType_Application_End = EventType_Application_OS_Terminate,
|
||||||
Application_Begin = Application_Exit,
|
|
||||||
Application_End = Application_OS_Terminate,
|
|
||||||
|
|
||||||
// Window Events
|
// Window Events
|
||||||
Window_Close_Request = 200,
|
EventType_Window_Close_Request = 200,
|
||||||
Window_Begin = Window_Close_Request,
|
EventType_Window_Begin = EventType_Window_Close_Request,
|
||||||
Window_End = Window_Close_Request,
|
EventType_Window_End = EventType_Window_Close_Request,
|
||||||
|
|
||||||
// Keyboard Event
|
// Keyboard Event
|
||||||
Key_Down = 300,
|
EventType_Key_Down = 300,
|
||||||
Key_Up,
|
EventType_Key_Up = 301,
|
||||||
Keyboard_Begin = Key_Down,
|
EventType_Keyboard_Begin = EventType_Key_Down,
|
||||||
Keyboard_End = Key_Up,
|
EventType_Keyboard_End = EventType_Key_Up,
|
||||||
|
|
||||||
// Mouse Event
|
// Mouse Event
|
||||||
Mouse_Move = 400,
|
EventType_Mouse_Move = 400,
|
||||||
Mouse_ButtonPressed,
|
EventType_Mouse_ButtonPressed = 401,
|
||||||
Mouse_ButtonReleased,
|
EventType_Mouse_ButtonReleased = 402,
|
||||||
|
|
||||||
Mouse_Begin = Mouse_Move,
|
EventType_Mouse_Begin = EventType_Mouse_Move,
|
||||||
Mouse_End = Mouse_ButtonReleased,
|
EventType_Mouse_End = EventType_Mouse_ButtonReleased,
|
||||||
|
|
||||||
Last // Get value from the previous one
|
EventType_Last
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct WindowEvent WindowEvent;
|
||||||
|
typedef struct KeyboardEvent KeyboardEvent;
|
||||||
|
typedef struct MouseMovementEvent MouseMovementEvent;
|
||||||
|
typedef struct MouseButtonEvent MouseButtonEvent;
|
||||||
|
typedef union AllSystemEventUnion AllSystemEventUnion;
|
||||||
|
typedef struct SystemEvent SystemEvent;
|
||||||
|
|
||||||
struct WindowEvent
|
struct WindowEvent
|
||||||
{
|
{
|
||||||
WindowID AssociatedWindowID;
|
WindowID AssociatedWindowID;
|
||||||
uint32 DataPadding[2]; // TODO : define how much data param we need
|
uint32 DataPadding[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KeyboardEvent
|
struct KeyboardEvent
|
||||||
@@ -59,9 +63,6 @@ struct KeyboardEvent
|
|||||||
KeyMod KeyModeState;
|
KeyMod KeyModeState;
|
||||||
};
|
};
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// Mouse Events
|
|
||||||
// =====================================================
|
|
||||||
struct MouseMovementEvent
|
struct MouseMovementEvent
|
||||||
{
|
{
|
||||||
MouseID AssociatedMouseID;
|
MouseID AssociatedMouseID;
|
||||||
@@ -80,20 +81,18 @@ struct MouseButtonEvent
|
|||||||
float X;
|
float X;
|
||||||
float Y;
|
float Y;
|
||||||
MouseButton ButtonState;
|
MouseButton ButtonState;
|
||||||
bool IsPressed : 1;
|
bool8 IsPressed;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Tagged union representing ALL possible system events + a bit of data for custom event if needed
|
|
||||||
union AllSystemEventUnion
|
union AllSystemEventUnion
|
||||||
{
|
{
|
||||||
WindowEvent Window;
|
WindowEvent Window;
|
||||||
KeyboardEvent Keyboard;
|
KeyboardEvent Keyboard;
|
||||||
MouseMovementEvent MouseMovement;
|
MouseMovementEvent MouseMovement;
|
||||||
MouseButtonEvent MouseButton;
|
MouseButtonEvent MouseButton;
|
||||||
uint8 Padding[128]; // Make sure that the union is fixed in size and big enough on all platforms.
|
uint8 Padding[128];
|
||||||
};
|
};
|
||||||
// Make sure we do not bust the union size
|
StaticAssert(sizeof(AllSystemEventUnion) == 128, SystemEventUnionSizeCheck);
|
||||||
static_assert(sizeof(AllSystemEventUnion) == sizeof(((AllSystemEventUnion*)nullptr)->Padding));
|
|
||||||
|
|
||||||
struct SystemEvent
|
struct SystemEvent
|
||||||
{
|
{
|
||||||
@@ -102,19 +101,7 @@ struct SystemEvent
|
|||||||
AllSystemEventUnion Data;
|
AllSystemEventUnion Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Poll for any event, return false if no event is available.
|
extern JULIET_API bool8 GetEvent(SystemEvent* event);
|
||||||
// Equivalent to WaitEvent(event, 0);
|
extern JULIET_API bool8 WaitEvent(SystemEvent* event, int32 timeoutInNS);
|
||||||
// Will not block
|
extern JULIET_API bool8 AddEvent(SystemEvent* event);
|
||||||
extern JULIET_API bool GetEvent(SystemEvent& event);
|
extern void Events_NewFrame(float deltaTime);
|
||||||
|
|
||||||
// TODO : use chrono to tag the timeout correctly with nanosec
|
|
||||||
// timeout == -1 means wait for any event before pursuing
|
|
||||||
// timeout == 0 means checking once for the frame and getting out
|
|
||||||
// timeout > 0 means wait until time is out
|
|
||||||
extern JULIET_API bool WaitEvent(SystemEvent& event, int32 timeoutInNS = -1);
|
|
||||||
|
|
||||||
// Add an event onto the event queue.
|
|
||||||
// TODO : support array of events
|
|
||||||
extern JULIET_API bool AddEvent(SystemEvent& event);
|
|
||||||
|
|
||||||
extern void Events_NewFrame(float deltaTime);
|
|
||||||
@@ -2,41 +2,43 @@
|
|||||||
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
enum class AssetType
|
typedef uint32 AssetType;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
JAsset,
|
AssetType_JAsset = 0,
|
||||||
Shader,
|
AssetType_Shader = 1,
|
||||||
Config,
|
AssetType_Config = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct Path Path;
|
||||||
struct Path
|
struct Path
|
||||||
{
|
{
|
||||||
String Directories;
|
String Directories;
|
||||||
String FullPath;
|
String FullPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
JULIET_API bool IsValid(Path path);
|
JULIET_API bool8 IsValidPath(Path path);
|
||||||
|
|
||||||
// Returns the path to the application directory
|
// Returns the path to the application directory
|
||||||
JULIET_API Path GetBasePath();
|
JULIET_API Path GetBasePath(void);
|
||||||
|
|
||||||
// Path to the /Assets/ folder
|
// Path to the /Assets/ folder
|
||||||
JULIET_API Path GetAssetBasePath();
|
JULIET_API Path GetAssetBasePath(void);
|
||||||
|
|
||||||
// Builds a full path to an asset file given its filename (e.g. "Triangle.vert.dxil").
|
// Builds a full path to an asset file given its filename (e.g. "Triangle.vert.dxil").
|
||||||
JULIET_API Path GetAssetPath(NonNullPtr<Arena> arena, AssetType type, String filename);
|
JULIET_API Path GetAssetPath(Arena* arena, AssetType type, String filename);
|
||||||
|
|
||||||
JULIET_API bool IsAbsolutePath(String path);
|
JULIET_API bool8 IsAbsolutePath(String path);
|
||||||
|
|
||||||
JULIET_API Path fs_create_clean_path(NonNullPtr<Arena> arena, String path);
|
JULIET_API Path fs_create_clean_path(Arena* arena, String path);
|
||||||
|
|
||||||
JULIET_API bool fs_create_directory(String path, bool recursive);
|
JULIET_API bool8 fs_create_directory(String path, bool8 recursive);
|
||||||
|
|
||||||
JULIET_API bool fs_path_exists(String path);
|
JULIET_API bool8 fs_path_exists(String path);
|
||||||
|
|
||||||
JULIET_API bool fs_move_file(Path old_path, Path new_path);
|
JULIET_API bool8 fs_move_file(Path old_path, Path new_path);
|
||||||
|
|
||||||
JULIET_API bool fs_delete_file(String path);
|
JULIET_API bool8 fs_delete_file(String path);
|
||||||
|
|
||||||
using fs_iterate_director_callback = void (*)(Path path, bool is_director, void* user_payload);
|
typedef void (*fs_iterate_director_callback)(Path path, bool8 is_director, void* user_payload);
|
||||||
JULIET_API void fs_iterate_directory(Path directory_path, String extension, void* user_payload, fs_iterate_director_callback callback);
|
JULIET_API void fs_iterate_directory(Path directory_path, String extension, void* user_payload, fs_iterate_director_callback callback);
|
||||||
@@ -1,69 +1,69 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
#include <Core/HAL/Filesystem/Filesystem.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
#include "Core/HAL/Filesystem/Filesystem.h"
|
|
||||||
|
|
||||||
// Opaque type
|
// Opaque type
|
||||||
struct IOStream;
|
typedef struct IOStream IOStream;
|
||||||
|
typedef struct IOStreamDataPayload IOStreamDataPayload;
|
||||||
|
|
||||||
struct IOStreamDataPayload
|
struct IOStreamDataPayload
|
||||||
{
|
{
|
||||||
|
uint8 unused;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IOStreamStatus : uint8
|
typedef uint8 IOStreamStatus;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Ready,
|
IOStreamStatus_Ready = 0,
|
||||||
Error,
|
IOStreamStatus_Error,
|
||||||
EndOfFile,
|
IOStreamStatus_EndOfFile,
|
||||||
NotReady,
|
IOStreamStatus_NotReady,
|
||||||
ReadOnly,
|
IOStreamStatus_ReadOnly,
|
||||||
WriteOnly
|
IOStreamStatus_WriteOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IOStreamSeekPivot : uint8
|
typedef uint8 IOStreamSeekPivot;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Begin,
|
IOStreamSeekPivot_Begin = 0,
|
||||||
Current,
|
IOStreamSeekPivot_Current,
|
||||||
End,
|
IOStreamSeekPivot_End,
|
||||||
Count
|
IOStreamSeekPivot_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
// IOStream can be opened on a file or memory, or anything else.
|
typedef struct IOStreamInterface IOStreamInterface;
|
||||||
// Use the interface to make it transparent to the user.
|
|
||||||
struct IOStreamInterface
|
struct IOStreamInterface
|
||||||
{
|
{
|
||||||
uint32 Version;
|
uint32 Version;
|
||||||
|
|
||||||
int64 (*Size)(NonNullPtr<IOStreamDataPayload> data);
|
int64 (*Size)(IOStreamDataPayload* data);
|
||||||
|
|
||||||
int64 (*Seek)(NonNullPtr<IOStreamDataPayload> data, int64 offset, IOStreamSeekPivot pivot);
|
int64 (*Seek)(IOStreamDataPayload* data, int64 offset, IOStreamSeekPivot pivot);
|
||||||
size_t (*Read)(NonNullPtr<IOStreamDataPayload> data, void* outBuffer, size_t size, NonNullPtr<IOStreamStatus> status);
|
size_t (*Read)(IOStreamDataPayload* data, void* outBuffer, size_t size, IOStreamStatus* status);
|
||||||
size_t (*Write)(NonNullPtr<IOStreamDataPayload> data, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status);
|
size_t (*Write)(IOStreamDataPayload* data, ByteBuffer inBuffer, IOStreamStatus* status);
|
||||||
bool (*Flush)(NonNullPtr<IOStreamDataPayload> data, NonNullPtr<IOStreamStatus> status);
|
bool8 (*Flush)(IOStreamDataPayload* data, IOStreamStatus* status);
|
||||||
|
|
||||||
bool (*Close)(NonNullPtr<IOStreamDataPayload> data);
|
bool8 (*Close)(IOStreamDataPayload* data);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JULIET_API IOStream* IOFromFile(NonNullPtr<Arena> arena, String filename, String mode);
|
extern JULIET_API IOStream* IOFromFile(Arena* arena, String filename, String mode);
|
||||||
|
|
||||||
// Let you use an interface to open any io. Is used internally by IOFromFile
|
extern JULIET_API IOStream* IOFromInterface(Arena* arena, const IOStreamInterface* streamInterface,
|
||||||
extern JULIET_API IOStream* IOFromInterface(NonNullPtr<Arena> arena, NonNullPtr<const IOStreamInterface> streamInterface,
|
IOStreamDataPayload* payload);
|
||||||
NonNullPtr<IOStreamDataPayload> payload);
|
|
||||||
|
|
||||||
// Write formatted string into the stream.
|
JULIET_API size_t IOPrintf(IOStream* stream, const char* format, ...);
|
||||||
JULIET_API size_t IOPrintf(NonNullPtr<IOStream> stream, _Printf_format_string_ const char* format, ...);
|
JULIET_API size_t IOWrite(IOStream* stream, ByteBuffer inBuffer);
|
||||||
JULIET_API size_t IOWrite(NonNullPtr<IOStream> stream, ByteBuffer inBuffer);
|
|
||||||
|
|
||||||
JULIET_API size_t IORead(NonNullPtr<IOStream> stream, void* ptr, size_t size);
|
JULIET_API size_t IORead(IOStream* stream, void* ptr, size_t size);
|
||||||
JULIET_API int64 IOSeek(NonNullPtr<IOStream> stream, int64 offset, IOStreamSeekPivot pivot);
|
JULIET_API int64 IOSeek(IOStream* stream, int64 offset, IOStreamSeekPivot pivot);
|
||||||
|
|
||||||
JULIET_API int64 IOSize(NonNullPtr<IOStream> stream);
|
JULIET_API int64 IOSize(IOStream* stream);
|
||||||
|
|
||||||
JULIET_API ByteBuffer LoadFile(NonNullPtr<Arena> arena, String filename);
|
JULIET_API ByteBuffer LoadFile(Arena* arena, String filename);
|
||||||
JULIET_API ByteBuffer LoadFile(NonNullPtr<Arena> arena, NonNullPtr<IOStream> stream, bool closeStreamWhenDone);
|
JULIET_API ByteBuffer LoadFileFromStream(Arena* arena, IOStream* stream, bool8 closeStreamWhenDone);
|
||||||
|
|
||||||
JULIET_API size_t IO_atomic_file_write(Path filepath, ByteBuffer file_content);
|
JULIET_API size_t IO_atomic_file_write(Path filepath, ByteBuffer file_content);
|
||||||
|
|
||||||
JULIET_API bool IOClose(NonNullPtr<IOStream> stream);
|
JULIET_API bool8 IOClose(IOStream* stream);
|
||||||
@@ -1,188 +1,183 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Represents a Virtual Key corresponding to the Physical key, but localized using the keyboard layout
|
#include <Core/Common/CoreTypes.h>
|
||||||
// ScanCode reprensent US ASCII Keyboard
|
|
||||||
// WASD Scan codes are ZQSD in KeyCode for French keyboard
|
typedef uint32 KeyCode;
|
||||||
// We use the ASCII value of the generated character as value, when possible.
|
enum
|
||||||
// Keys that do not produce a character are converted to an abritrary value high enough to not conflict
|
|
||||||
// Reference: https://www.asciitable.com/
|
|
||||||
// Reference: https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-6.0/aa299374(v=vs.60)
|
|
||||||
enum class KeyCode : uint32
|
|
||||||
{
|
{
|
||||||
Unknown = 0x0, // 0
|
KeyCode_Unknown = 0x0u,
|
||||||
Unsupported = 0x0, // 0
|
KeyCode_Unsupported = 0x0u,
|
||||||
Return = 0X0Du, // '\r'
|
KeyCode_Return = 0x0Du,
|
||||||
Escape = 0X1Bu, // '\X1B'
|
KeyCode_Escape = 0x1Bu,
|
||||||
Backspace = 0X08u, // '\b'
|
KeyCode_Backspace = 0x08u,
|
||||||
Tab = 0X09u, // '\t'
|
KeyCode_Tab = 0x09u,
|
||||||
Space = 0X20u, // ' '
|
KeyCode_Space = 0x20u,
|
||||||
ExclamationPoint = 0X21u, // '!'
|
KeyCode_ExclamationPoint = 0x21u,
|
||||||
DoubleApostrophe = 0X22u, // '"'
|
KeyCode_DoubleApostrophe = 0x22u,
|
||||||
Hash = 0X23u, // '#'
|
KeyCode_Hash = 0x23u,
|
||||||
Dollar = 0X24u, // '$'
|
KeyCode_Dollar = 0x24u,
|
||||||
Percent = 0X25u, // '%'
|
KeyCode_Percent = 0x25u,
|
||||||
Ampersand = 0X26u, // '&'
|
KeyCode_Ampersand = 0x26u,
|
||||||
Apostrophe = 0X27u, // '\''
|
KeyCode_Apostrophe = 0x27u,
|
||||||
LeftParenthesis = 0X28u, // '('
|
KeyCode_LeftParenthesis = 0x28u,
|
||||||
RightParenthesis = 0X29u, // ')'
|
KeyCode_RightParenthesis = 0x29u,
|
||||||
Asterisk = 0X2Au, // '*'
|
KeyCode_Asterisk = 0x2Au,
|
||||||
Plus = 0X2Bu, // '+'
|
KeyCode_Plus = 0x2Bu,
|
||||||
Comma = 0X2Cu, // ','
|
KeyCode_Comma = 0x2Cu,
|
||||||
Minus = 0X2Du, // '-'
|
KeyCode_Minus = 0x2Du,
|
||||||
Period = 0X2Eu, // '.'
|
KeyCode_Period = 0x2Eu,
|
||||||
Slash = 0X2Fu, // '/'
|
KeyCode_Slash = 0x2Fu,
|
||||||
Num0 = 0X30u, // '0'
|
KeyCode_Num0 = 0x30u,
|
||||||
Num1 = 0X31u, // '1'
|
KeyCode_Num1 = 0x31u,
|
||||||
Num2 = 0X32u, // '2'
|
KeyCode_Num2 = 0x32u,
|
||||||
Num3 = 0X33u, // '3'
|
KeyCode_Num3 = 0x33u,
|
||||||
Num4 = 0X34u, // '4'
|
KeyCode_Num4 = 0x34u,
|
||||||
Num5 = 0X35u, // '5'
|
KeyCode_Num5 = 0x35u,
|
||||||
Num6 = 0X36u, // '6'
|
KeyCode_Num6 = 0x36u,
|
||||||
Num7 = 0X37u, // '7'
|
KeyCode_Num7 = 0x37u,
|
||||||
Num8 = 0X38u, // '8'
|
KeyCode_Num8 = 0x38u,
|
||||||
Num9 = 0X39u, // '9'
|
KeyCode_Num9 = 0x39u,
|
||||||
Colon = 0X3Au, // ':'
|
KeyCode_Colon = 0x3Au,
|
||||||
Semicolon = 0X3Bu, // ';'
|
KeyCode_Semicolon = 0x3Bu,
|
||||||
LessThan = 0X3Cu, // '<'
|
KeyCode_LessThan = 0x3Cu,
|
||||||
Equals = 0X3Du, // '='
|
KeyCode_Equals = 0x3Du,
|
||||||
GreaterThan = 0X3Eu, // '>'
|
KeyCode_GreaterThan = 0x3Eu,
|
||||||
QuestionMark = 0X3Fu, // '?'
|
KeyCode_QuestionMark = 0x3Fu,
|
||||||
CommercialAt = 0x40u, // '@'
|
KeyCode_CommercialAt = 0x40u,
|
||||||
LeftBracket = 0X5Bu, // '['
|
KeyCode_LeftBracket = 0x5Bu,
|
||||||
Backslash = 0X5Cu, // '\\'
|
KeyCode_Backslash = 0x5Cu,
|
||||||
RightBracket = 0X5DU, // ']'
|
KeyCode_RightBracket = 0x5Du,
|
||||||
Caret = 0X5Eu, // '^'
|
KeyCode_Caret = 0x5Eu,
|
||||||
Underscore = 0X5Fu, // '_'
|
KeyCode_Underscore = 0x5Fu,
|
||||||
GraveAccent = 0X60u, // '`'
|
KeyCode_GraveAccent = 0x60u,
|
||||||
A = 0x61u, // 'a'
|
KeyCode_A = 0x61u,
|
||||||
B = 0x62u, // 'b'
|
KeyCode_B = 0x62u,
|
||||||
C = 0x63u, // 'c'
|
KeyCode_C = 0x63u,
|
||||||
D = 0x64u, // 'd'
|
KeyCode_D = 0x64u,
|
||||||
E = 0x65u, // 'e'
|
KeyCode_E = 0x65u,
|
||||||
F = 0x66u, // 'f'
|
KeyCode_F = 0x66u,
|
||||||
G = 0x67u, // 'g'
|
KeyCode_G = 0x67u,
|
||||||
H = 0x68u, // 'h'
|
KeyCode_H = 0x68u,
|
||||||
I = 0x69u, // 'i'
|
KeyCode_I = 0x69u,
|
||||||
J = 0x6Au, // 'j'
|
KeyCode_J = 0x6Au,
|
||||||
K = 0x6Bu, // 'k'
|
KeyCode_K = 0x6Bu,
|
||||||
L = 0x6CU, // 'l'
|
KeyCode_L = 0x6Cu,
|
||||||
M = 0x6DU, // 'm'
|
KeyCode_M = 0x6Du,
|
||||||
N = 0x6Eu, // 'n'
|
KeyCode_N = 0x6Eu,
|
||||||
O = 0x6Fu, // 'o'
|
KeyCode_O = 0x6Fu,
|
||||||
P = 0x70u, // 'p'
|
KeyCode_P = 0x70u,
|
||||||
Q = 0x71u, // 'q'
|
KeyCode_Q = 0x71u,
|
||||||
R = 0x72u, // 'r'
|
KeyCode_R = 0x72u,
|
||||||
S = 0x73u, // 's'
|
KeyCode_S = 0x73u,
|
||||||
T = 0x74u, // 't'
|
KeyCode_T = 0x74u,
|
||||||
U = 0x75u, // 'y'
|
KeyCode_U = 0x75u,
|
||||||
V = 0x76u, // 'v'
|
KeyCode_V = 0x76u,
|
||||||
W = 0x77u, // 'w'
|
KeyCode_W = 0x77u,
|
||||||
X = 0x78u, // 'x'
|
KeyCode_X = 0x78u,
|
||||||
Y = 0x79u, // 'y'
|
KeyCode_Y = 0x79u,
|
||||||
Z = 0x7Au, // 'z'
|
KeyCode_Z = 0x7Au,
|
||||||
LeftBrace = 0x7BU, // '{'
|
KeyCode_LeftBrace = 0x7Bu,
|
||||||
Pipe = 0x7CU, // '|'
|
KeyCode_Pipe = 0x7Cu,
|
||||||
RightBrace = 0x7DU, // '}'
|
KeyCode_RightBrace = 0x7Du,
|
||||||
Tilde = 0x7Eu, // '~'
|
KeyCode_Tilde = 0x7Eu,
|
||||||
Delete = 0x7Fu, // '\x7F'
|
KeyCode_Delete = 0x7Fu,
|
||||||
PlusMinus = 0xb1u, // '\xB1'
|
KeyCode_PlusMinus = 0xb1u,
|
||||||
|
|
||||||
// Keys not producing a character
|
KeyCode_CapsLock = 0x40000039u,
|
||||||
// Based on SDL Algo: ScanCode | 0x40000000
|
KeyCode_F1 = 0x4000003Au,
|
||||||
CapsLock = 0x40000039u,
|
KeyCode_F2 = 0x4000003Bu,
|
||||||
F1 = 0x4000003Au,
|
KeyCode_F3 = 0x4000003Cu,
|
||||||
F2 = 0x4000003Bu,
|
KeyCode_F4 = 0x4000003Du,
|
||||||
F3 = 0x4000003CU,
|
KeyCode_F5 = 0x4000003Eu,
|
||||||
F4 = 0x4000003DU,
|
KeyCode_F6 = 0x4000003Fu,
|
||||||
F5 = 0x4000003Eu,
|
KeyCode_F7 = 0x40000040u,
|
||||||
F6 = 0x4000003Fu,
|
KeyCode_F8 = 0x40000041u,
|
||||||
F7 = 0x40000040u,
|
KeyCode_F9 = 0x40000042u,
|
||||||
F8 = 0x40000041u,
|
KeyCode_F10 = 0x40000043u,
|
||||||
F9 = 0x40000042u,
|
KeyCode_F11 = 0x40000044u,
|
||||||
F10 = 0x40000043u,
|
KeyCode_F12 = 0x40000045u,
|
||||||
F11 = 0x40000044u,
|
KeyCode_PrintScreen = 0x40000046u,
|
||||||
F12 = 0x40000045u,
|
KeyCode_ScrollLock = 0x40000047u,
|
||||||
PrintScreen = 0x40000046u,
|
KeyCode_Pause = 0x40000048u,
|
||||||
ScrollLock = 0x40000047u,
|
KeyCode_Insert = 0x40000049u,
|
||||||
Pause = 0x40000048u,
|
KeyCode_Home = 0x4000004Au,
|
||||||
Insert = 0x40000049u,
|
KeyCode_PageUp = 0x4000004Bu,
|
||||||
Home = 0x4000004Au,
|
KeyCode_End = 0x4000004Du,
|
||||||
PageUp = 0x4000004Bu,
|
KeyCode_PageDown = 0x4000004Eu,
|
||||||
End = 0x4000004DU,
|
KeyCode_RightArrow = 0x4000004Fu,
|
||||||
PageDown = 0x4000004Eu,
|
KeyCode_LeftArrow = 0x40000050u,
|
||||||
RightArrow = 0x4000004Fu,
|
KeyCode_DownArrow = 0x40000051u,
|
||||||
LeftArrow = 0x40000050u,
|
KeyCode_UpArrow = 0x40000052u,
|
||||||
DownArrow = 0x40000051u,
|
KeyCode_NumlockClear = 0x40000053u,
|
||||||
UpArrow = 0x40000052u,
|
KeyCode_KeyPad_Divide = 0x40000054u,
|
||||||
NumlockClear = 0x40000053u,
|
KeyCode_KeyPad_Multiply = 0x40000055u,
|
||||||
KeyPad_Divide = 0x40000054u,
|
KeyCode_KeyPad_Minus = 0x40000056u,
|
||||||
KeyPad_Multiply = 0x40000055u,
|
KeyCode_KeyPad_Plus = 0x40000057u,
|
||||||
KeyPad_Minus = 0x40000056u,
|
KeyCode_KeyPad_Enter = 0x40000058u,
|
||||||
KeyPad_Plus = 0x40000057u,
|
KeyCode_KeyPad_Num1 = 0x40000059u,
|
||||||
KeyPad_Enter = 0x40000058u,
|
KeyCode_KeyPad_Num2 = 0x4000005Au,
|
||||||
KeyPad_Num1 = 0x40000059u,
|
KeyCode_KeyPad_Num3 = 0x4000005Bu,
|
||||||
KeyPad_Num2 = 0x4000005Au,
|
KeyCode_KeyPad_Num4 = 0x4000005Cu,
|
||||||
KeyPad_Num3 = 0x4000005Bu,
|
KeyCode_KeyPad_Num5 = 0x4000005Du,
|
||||||
KeyPad_Num4 = 0x4000005Cu,
|
KeyCode_KeyPad_Num6 = 0x4000005Eu,
|
||||||
KeyPad_Num5 = 0x4000005Du,
|
KeyCode_KeyPad_Num7 = 0x4000005Fu,
|
||||||
KeyPad_Num6 = 0x4000005Eu,
|
KeyCode_KeyPad_Num8 = 0x40000060u,
|
||||||
KeyPad_Num7 = 0x4000005Fu,
|
KeyCode_KeyPad_Num9 = 0x40000061u,
|
||||||
KeyPad_Num8 = 0x40000060u,
|
KeyCode_KeyPad_Num0 = 0x40000062u,
|
||||||
KeyPad_Num9 = 0x40000061u,
|
KeyCode_KeyPad_Period = 0x40000063u,
|
||||||
KeyPad_Num0 = 0x40000062u,
|
KeyCode_Power = 0x40000066u,
|
||||||
KeyPad_Period = 0x40000063u,
|
KeyCode_KeyPad_Equals = 0x40000067u,
|
||||||
Power = 0x40000066u,
|
KeyCode_F13 = 0x40000068u,
|
||||||
KeyPad_Equals = 0x40000067u,
|
KeyCode_F14 = 0x40000069u,
|
||||||
F13 = 0x40000068u,
|
KeyCode_F15 = 0x4000006Au,
|
||||||
F14 = 0x40000069u,
|
KeyCode_F16 = 0x4000006Bu,
|
||||||
F15 = 0x4000006Au,
|
KeyCode_F17 = 0x4000006Cu,
|
||||||
F16 = 0x4000006Bu,
|
KeyCode_F18 = 0x4000006Du,
|
||||||
F17 = 0x4000006Cu,
|
KeyCode_F19 = 0x4000006Eu,
|
||||||
F18 = 0x4000006Du,
|
KeyCode_F20 = 0x4000006Fu,
|
||||||
F19 = 0x4000006Eu,
|
KeyCode_F21 = 0x40000070u,
|
||||||
F20 = 0x4000006Fu,
|
KeyCode_F22 = 0x40000071u,
|
||||||
F21 = 0x40000070u,
|
KeyCode_F23 = 0x40000072u,
|
||||||
F22 = 0x40000071u,
|
KeyCode_F24 = 0x40000073u,
|
||||||
F23 = 0x40000072u,
|
KeyCode_Mute = 0x4000007Fu,
|
||||||
F24 = 0x40000073u,
|
KeyCode_VolumeUp = 0x40000080u,
|
||||||
Mute = 0x4000007Fu,
|
KeyCode_VolumeDown = 0x40000081u,
|
||||||
VolumeUp = 0x40000080u,
|
KeyCode_KeyPad_Comma = 0x40000085u,
|
||||||
VolumeDown = 0x40000081u,
|
KeyCode_LeftControl = 0x400000E0u,
|
||||||
KeyPad_Comma = 0x40000085u,
|
KeyCode_LeftShift = 0x400000E1u,
|
||||||
LeftControl = 0x400000E0u,
|
KeyCode_LeftAlt = 0x400000E2u,
|
||||||
LeftShift = 0x400000E1u,
|
KeyCode_LeftOSCommand = 0x400000E3u,
|
||||||
LeftAlt = 0x400000E2u,
|
KeyCode_RightControl = 0x400000E4u,
|
||||||
LeftOSCommand = 0x400000E3u,
|
KeyCode_RightShift = 0x400000E5u,
|
||||||
RightControl = 0x400000E4u,
|
KeyCode_RightAlt = 0x400000E6u,
|
||||||
RightShift = 0x400000E5u,
|
KeyCode_RightOSCommand = 0x400000E7u,
|
||||||
RightAlt = 0x400000E6u,
|
KeyCode_Sleep = 0x40000102u,
|
||||||
RightOSCommand = 0x400000E7u,
|
KeyCode_WakeUp = 0x40000103u,
|
||||||
Sleep = 0x40000102u,
|
KeyCode_Media_NextTrack = 0x4000010Bu,
|
||||||
WakeUp = 0x40000103u,
|
KeyCode_Media_PreviousTrack = 0x4000010Cu,
|
||||||
Media_NextTrack = 0x4000010Bu,
|
KeyCode_Media_Stop = 0x4000010Du,
|
||||||
Media_PreviousTrack = 0x4000010Cu,
|
KeyCode_Media_Eject = 0x4000010Eu,
|
||||||
Media_Stop = 0x4000010Du,
|
KeyCode_Media_PlayPause = 0x4000010Fu,
|
||||||
Media_Eject = 0x4000010Eu,
|
KeyCode_Media_Select = 0x40000110u,
|
||||||
Media_PlayPause = 0x4000010Fu,
|
|
||||||
Media_Select = 0x40000110u,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class KeyMod : uint16
|
typedef uint16 KeyMod;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
None = 0b0,
|
KeyMod_None = 0x0000u,
|
||||||
LeftShift = 0b0000'0000'0001u,
|
KeyMod_LeftShift = 0x0001u,
|
||||||
RightShift = 0b0000'0000'0010u,
|
KeyMod_RightShift = 0x0002u,
|
||||||
LeftControl = 0b0000'0000'0100u,
|
KeyMod_LeftControl = 0x0004u,
|
||||||
RightControl = 0b0000'0000'1000u,
|
KeyMod_RightControl = 0x0008u,
|
||||||
LeftAlt = 0b0000'0001'000u,
|
KeyMod_LeftAlt = 0x0010u,
|
||||||
RightAlt = 0b0000'0010'0000u,
|
KeyMod_RightAlt = 0x0020u,
|
||||||
LeftOSCommand = 0b0000'0100'0000u,
|
KeyMod_LeftOSCommand = 0x0040u,
|
||||||
RightOSCommand = 0b0000'1000'0000u,
|
KeyMod_RightOSCommand = 0x0080u,
|
||||||
NumLock = 0b0001'0000'0000u,
|
KeyMod_NumLock = 0x0100u,
|
||||||
CapsLock = 0b0010'0000'0000u,
|
KeyMod_CapsLock = 0x0200u,
|
||||||
ScrollLock = 0b0100'0000'0000u,
|
KeyMod_ScrollLock = 0x0400u,
|
||||||
Control = LeftControl | RightControl,
|
KeyMod_Control = KeyMod_LeftControl | KeyMod_RightControl,
|
||||||
Shift = LeftShift | RightShift,
|
KeyMod_Shift = KeyMod_LeftShift | KeyMod_RightShift,
|
||||||
Alt = LeftAlt | RightAlt,
|
KeyMod_Alt = KeyMod_LeftAlt | KeyMod_RightAlt,
|
||||||
OSCommand = LeftOSCommand | RightOSCommand,
|
KeyMod_OSCommand = KeyMod_LeftOSCommand | KeyMod_RightOSCommand,
|
||||||
};
|
};
|
||||||
@@ -1,23 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/HAL/Keyboard/KeyCode.h>
|
#include <Core/HAL/Keyboard/KeyCode.h>
|
||||||
#include <Core/HAL/Keyboard/ScanCode.h>
|
#include <Core/HAL/Keyboard/ScanCode.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
using KeyboardID = uint8;
|
typedef uint8 KeyboardID;
|
||||||
|
|
||||||
enum class KeyPosition : bool
|
typedef bool8 KeyPosition;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Up = false,
|
KeyPosition_Up = false,
|
||||||
Down = true
|
KeyPosition_Down = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct KeyState KeyState;
|
||||||
struct KeyState
|
struct KeyState
|
||||||
{
|
{
|
||||||
KeyPosition Position;
|
KeyPosition Position;
|
||||||
float Time;
|
float Time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct Key Key;
|
||||||
struct Key
|
struct Key
|
||||||
{
|
{
|
||||||
ScanCode ScanCode;
|
ScanCode ScanCode;
|
||||||
@@ -25,8 +28,8 @@ struct Key
|
|||||||
uint16 Raw;
|
uint16 Raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JULIET_API bool IsKeyDown(ScanCode scanCode);
|
extern JULIET_API bool8 IsKeyDown(ScanCode scanCode);
|
||||||
extern JULIET_API bool IsKeyPressed(ScanCode scanCode);
|
extern JULIET_API bool8 IsKeyPressed(ScanCode scanCode);
|
||||||
|
|
||||||
extern JULIET_API KeyMod GetKeyModState();
|
extern JULIET_API KeyMod GetKeyModState(void);
|
||||||
extern JULIET_API KeyCode GetKeyCodeFromScanCode(ScanCode scanCode, KeyMod keyModState);
|
extern JULIET_API KeyCode GetKeyCodeFromScanCode(ScanCode scanCode, KeyMod keyModState);
|
||||||
@@ -1,183 +1,180 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Follow the HID Usage page for USB
|
#include <Core/Common/CoreTypes.h>
|
||||||
// https://usb.org/sites/default/files/hut1_5.pdf
|
|
||||||
// 0 to 256 Is dedicated to Keyboard Usage Page (0x07)
|
typedef uint16 ScanCode;
|
||||||
// 257 to 286 Is dedicated to Consumer Usage Page (0xC)
|
enum
|
||||||
// 287 to 511 Is not implemented. Could be used for Mobile or Consoles
|
|
||||||
// ScanCode reprensent Physical Keys and Buttons
|
|
||||||
enum class ScanCode : uint16
|
|
||||||
{
|
{
|
||||||
Unknown = 0,
|
ScanCode_Unknown = 0,
|
||||||
Unsupported = 0,
|
ScanCode_Unsupported = 0,
|
||||||
|
|
||||||
A = 4,
|
ScanCode_A = 4,
|
||||||
B = 5,
|
ScanCode_B = 5,
|
||||||
C = 6,
|
ScanCode_C = 6,
|
||||||
D = 7,
|
ScanCode_D = 7,
|
||||||
E = 8,
|
ScanCode_E = 8,
|
||||||
F = 9,
|
ScanCode_F = 9,
|
||||||
G = 10,
|
ScanCode_G = 10,
|
||||||
H = 11,
|
ScanCode_H = 11,
|
||||||
I = 12,
|
ScanCode_I = 12,
|
||||||
J = 13,
|
ScanCode_J = 13,
|
||||||
K = 14,
|
ScanCode_K = 14,
|
||||||
L = 15,
|
ScanCode_L = 15,
|
||||||
M = 16,
|
ScanCode_M = 16,
|
||||||
N = 17,
|
ScanCode_N = 17,
|
||||||
O = 18,
|
ScanCode_O = 18,
|
||||||
P = 19,
|
ScanCode_P = 19,
|
||||||
Q = 20,
|
ScanCode_Q = 20,
|
||||||
R = 21,
|
ScanCode_R = 21,
|
||||||
S = 22,
|
ScanCode_S = 22,
|
||||||
T = 23,
|
ScanCode_T = 23,
|
||||||
U = 24,
|
ScanCode_U = 24,
|
||||||
V = 25,
|
ScanCode_V = 25,
|
||||||
W = 26,
|
ScanCode_W = 26,
|
||||||
X = 27,
|
ScanCode_X = 27,
|
||||||
Y = 28,
|
ScanCode_Y = 28,
|
||||||
Z = 29,
|
ScanCode_Z = 29,
|
||||||
|
|
||||||
Num1 = 30,
|
ScanCode_Num1 = 30,
|
||||||
Num2 = 31,
|
ScanCode_Num2 = 31,
|
||||||
Num3 = 32,
|
ScanCode_Num3 = 32,
|
||||||
Num4 = 33,
|
ScanCode_Num4 = 33,
|
||||||
Num5 = 34,
|
ScanCode_Num5 = 34,
|
||||||
Num6 = 35,
|
ScanCode_Num6 = 35,
|
||||||
Num7 = 36,
|
ScanCode_Num7 = 36,
|
||||||
Num8 = 37,
|
ScanCode_Num8 = 37,
|
||||||
Num9 = 38,
|
ScanCode_Num9 = 38,
|
||||||
Num0 = 39,
|
ScanCode_Num0 = 39,
|
||||||
|
|
||||||
Return = 40,
|
ScanCode_Return = 40,
|
||||||
Escape = 41,
|
ScanCode_Escape = 41,
|
||||||
Backspace = 42,
|
ScanCode_Backspace = 42,
|
||||||
Tab = 43,
|
ScanCode_Tab = 43,
|
||||||
Space = 44,
|
ScanCode_Space = 44,
|
||||||
|
|
||||||
Minus = 45,
|
ScanCode_Minus = 45,
|
||||||
Equals = 46,
|
ScanCode_Equals = 46,
|
||||||
LeftBracket = 47,
|
ScanCode_LeftBracket = 47,
|
||||||
RightBracket = 48,
|
ScanCode_RightBracket = 48,
|
||||||
Backslash = 49,
|
ScanCode_Backslash = 49,
|
||||||
NonUSHash = 50, // Same as 49 but for ISO keyboards
|
ScanCode_NonUSHash = 50,
|
||||||
Semicolon = 51,
|
ScanCode_Semicolon = 51,
|
||||||
Apostrophe = 52,
|
ScanCode_Apostrophe = 52,
|
||||||
GraveAccent = 53,
|
ScanCode_GraveAccent = 53,
|
||||||
Comma = 54,
|
ScanCode_Comma = 54,
|
||||||
Period = 55,
|
ScanCode_Period = 55,
|
||||||
Slash = 56,
|
ScanCode_Slash = 56,
|
||||||
CapsLock = 57,
|
ScanCode_CapsLock = 57,
|
||||||
|
|
||||||
F1 = 58,
|
ScanCode_F1 = 58,
|
||||||
F2 = 59,
|
ScanCode_F2 = 59,
|
||||||
F3 = 60,
|
ScanCode_F3 = 60,
|
||||||
F4 = 61,
|
ScanCode_F4 = 61,
|
||||||
F5 = 62,
|
ScanCode_F5 = 62,
|
||||||
F6 = 63,
|
ScanCode_F6 = 63,
|
||||||
F7 = 64,
|
ScanCode_F7 = 64,
|
||||||
F8 = 65,
|
ScanCode_F8 = 65,
|
||||||
F9 = 66,
|
ScanCode_F9 = 66,
|
||||||
F10 = 67,
|
ScanCode_F10 = 67,
|
||||||
F11 = 68,
|
ScanCode_F11 = 68,
|
||||||
F12 = 69,
|
ScanCode_F12 = 69,
|
||||||
|
|
||||||
PrintScreen = 70,
|
ScanCode_PrintScreen = 70,
|
||||||
ScrollLock = 71,
|
ScanCode_ScrollLock = 71,
|
||||||
Pause = 72,
|
ScanCode_Pause = 72,
|
||||||
Insert = 73,
|
ScanCode_Insert = 73,
|
||||||
|
|
||||||
Home = 74,
|
ScanCode_Home = 74,
|
||||||
PageUp = 75,
|
ScanCode_PageUp = 75,
|
||||||
Delete = 76,
|
ScanCode_Delete = 76,
|
||||||
End = 77,
|
ScanCode_End = 77,
|
||||||
PageDown = 78,
|
ScanCode_PageDown = 78,
|
||||||
RightArrow = 79,
|
ScanCode_RightArrow = 79,
|
||||||
LeftArrow = 80,
|
ScanCode_LeftArrow = 80,
|
||||||
DownArrow = 81,
|
ScanCode_DownArrow = 81,
|
||||||
UpArrow = 82,
|
ScanCode_UpArrow = 82,
|
||||||
|
|
||||||
NumlockClear = 83, // Pc = Numlock / Mac = Clear
|
ScanCode_NumlockClear = 83,
|
||||||
|
|
||||||
KeyPad_Divide = 84,
|
ScanCode_KeyPad_Divide = 84,
|
||||||
KeyPad_Multiply = 85,
|
ScanCode_KeyPad_Multiply = 85,
|
||||||
KeyPad_Minus = 86,
|
ScanCode_KeyPad_Minus = 86,
|
||||||
KeyPad_Plus = 87,
|
ScanCode_KeyPad_Plus = 87,
|
||||||
KeyPad_Enter = 88,
|
ScanCode_KeyPad_Enter = 88,
|
||||||
KeyPad_Num1 = 89,
|
ScanCode_KeyPad_Num1 = 89,
|
||||||
KeyPad_Num2 = 90,
|
ScanCode_KeyPad_Num2 = 90,
|
||||||
KeyPad_Num3 = 91,
|
ScanCode_KeyPad_Num3 = 91,
|
||||||
KeyPad_Num4 = 92,
|
ScanCode_KeyPad_Num4 = 92,
|
||||||
KeyPad_Num5 = 93,
|
ScanCode_KeyPad_Num5 = 93,
|
||||||
KeyPad_Num6 = 94,
|
ScanCode_KeyPad_Num6 = 94,
|
||||||
KeyPad_Num7 = 95,
|
ScanCode_KeyPad_Num7 = 95,
|
||||||
KeyPad_Num8 = 96,
|
ScanCode_KeyPad_Num8 = 96,
|
||||||
KeyPad_Num9 = 97,
|
ScanCode_KeyPad_Num9 = 97,
|
||||||
KeyPad_Num0 = 98,
|
ScanCode_KeyPad_Num0 = 98,
|
||||||
KeyPad_Period = 99,
|
ScanCode_KeyPad_Period = 99,
|
||||||
|
|
||||||
NonUSBackslash = 100, // ISO keyboards only
|
ScanCode_NonUSBackslash = 100,
|
||||||
Power = 102, // Some mac have a Power key
|
ScanCode_Power = 102,
|
||||||
|
|
||||||
KeyPad_Equals = 103,
|
ScanCode_KeyPad_Equals = 103,
|
||||||
F13 = 104,
|
ScanCode_F13 = 104,
|
||||||
F14 = 105,
|
ScanCode_F14 = 105,
|
||||||
F15 = 106,
|
ScanCode_F15 = 106,
|
||||||
F16 = 107,
|
ScanCode_F16 = 107,
|
||||||
F17 = 108,
|
ScanCode_F17 = 108,
|
||||||
F18 = 109,
|
ScanCode_F18 = 109,
|
||||||
F19 = 110,
|
ScanCode_F19 = 110,
|
||||||
F20 = 111,
|
ScanCode_F20 = 111,
|
||||||
F21 = 112,
|
ScanCode_F21 = 112,
|
||||||
F22 = 113,
|
ScanCode_F22 = 113,
|
||||||
F23 = 114,
|
ScanCode_F23 = 114,
|
||||||
F24 = 115,
|
ScanCode_F24 = 115,
|
||||||
|
|
||||||
Mute = 127,
|
ScanCode_Mute = 127,
|
||||||
VolumeUp = 128,
|
ScanCode_VolumeUp = 128,
|
||||||
VolumeDown = 129,
|
ScanCode_VolumeDown = 129,
|
||||||
|
|
||||||
KeyPad_Comma = 133,
|
ScanCode_KeyPad_Comma = 133,
|
||||||
|
|
||||||
International1 = 135, // Mostly used on Asian keyboards
|
ScanCode_International1 = 135,
|
||||||
International2 = 136,
|
ScanCode_International2 = 136,
|
||||||
International3 = 137, // Yen Symbol
|
ScanCode_International3 = 137,
|
||||||
International4 = 138,
|
ScanCode_International4 = 138,
|
||||||
International5 = 139,
|
ScanCode_International5 = 139,
|
||||||
International6 = 140,
|
ScanCode_International6 = 140,
|
||||||
International7 = 141,
|
ScanCode_International7 = 141,
|
||||||
International8 = 142,
|
ScanCode_International8 = 142,
|
||||||
International9 = 143,
|
ScanCode_International9 = 143,
|
||||||
Lang1 = 144, // Hangul (Korean)
|
ScanCode_Lang1 = 144,
|
||||||
Lang2 = 145, // Hanja (Korean)
|
ScanCode_Lang2 = 145,
|
||||||
Lang3 = 146, // Katakana (Japanese)
|
ScanCode_Lang3 = 146,
|
||||||
Lang4 = 147, // Hiragana (Japanese)
|
ScanCode_Lang4 = 147,
|
||||||
Lang5 = 148, // Zenkaku/Hankaku (Japanese)
|
ScanCode_Lang5 = 148,
|
||||||
Lang6 = 149, // Unused
|
ScanCode_Lang6 = 149,
|
||||||
Lang7 = 150, // Unused
|
ScanCode_Lang7 = 150,
|
||||||
Lang8 = 151, // Unused
|
ScanCode_Lang8 = 151,
|
||||||
Lang9 = 152, // Unused
|
ScanCode_Lang9 = 152,
|
||||||
|
|
||||||
LeftControl = 224,
|
ScanCode_LeftControl = 224,
|
||||||
LeftShift = 225,
|
ScanCode_LeftShift = 225,
|
||||||
LeftAlt = 226, // Alt for PC, Option for Mac
|
ScanCode_LeftAlt = 226,
|
||||||
LeftOSCommand = 227, // Window key for PC, Command for Mac
|
ScanCode_LeftOSCommand = 227,
|
||||||
RightControl = 228,
|
ScanCode_RightControl = 228,
|
||||||
RightShift = 229,
|
ScanCode_RightShift = 229,
|
||||||
RightAlt = 230, // Alt Gr for PC, Option for Mac
|
ScanCode_RightAlt = 230,
|
||||||
RightOSCommand = 231, // Window key for PC, Command for Mac
|
ScanCode_RightOSCommand = 231,
|
||||||
|
|
||||||
Sleep = 258,
|
ScanCode_Sleep = 258,
|
||||||
WakeUp = 259,
|
ScanCode_WakeUp = 259,
|
||||||
|
|
||||||
Media_NextTrack = 267,
|
ScanCode_Media_NextTrack = 267,
|
||||||
Media_PreviousTrack = 268,
|
ScanCode_Media_PreviousTrack = 268,
|
||||||
Media_Stop = 269,
|
ScanCode_Media_Stop = 269,
|
||||||
Media_Eject = 270,
|
ScanCode_Media_Eject = 270,
|
||||||
Media_PlayPause = 271,
|
ScanCode_Media_PlayPause = 271,
|
||||||
Media_Select = 272,
|
ScanCode_Media_Select = 272,
|
||||||
|
|
||||||
Reserved = 287,
|
ScanCode_Reserved = 287,
|
||||||
|
|
||||||
Count = 512
|
ScanCode_Count = 512
|
||||||
};
|
};
|
||||||
@@ -1,25 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
using MouseID = uint8;
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
enum class MouseButton : uint8
|
typedef uint8 MouseID;
|
||||||
|
|
||||||
|
typedef uint8 MouseButton;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
None = 0,
|
MouseButton_None = 0,
|
||||||
Left = 1 << 0,
|
MouseButton_Left = 1 << 0,
|
||||||
Right = 1 << 1,
|
MouseButton_Right = 1 << 1,
|
||||||
Middle = 1 << 2,
|
MouseButton_Middle = 1 << 2,
|
||||||
Button1 = 1 << 3,
|
MouseButton_Button1 = 1 << 3,
|
||||||
Button2 = 1 << 4,
|
MouseButton_Button2 = 1 << 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO : Replace by Vector2f
|
typedef struct MousePosition MousePosition;
|
||||||
struct MousePosition
|
struct MousePosition
|
||||||
{
|
{
|
||||||
float X;
|
float X;
|
||||||
float Y;
|
float Y;
|
||||||
};
|
};
|
||||||
|
|
||||||
JULIET_API extern bool IsMouseButtonDown(MouseButton button);
|
JULIET_API extern bool8 IsMouseButtonDown(MouseButton button);
|
||||||
JULIET_API extern MousePosition GetMousePosition();
|
JULIET_API extern MousePosition GetMousePosition(void);
|
||||||
JULIET_API extern MousePosition GetMouseDelta();
|
JULIET_API extern MousePosition GetMouseDelta(void);
|
||||||
JULIET_API extern MouseButton GetMouseButtonState();
|
JULIET_API extern MouseButton GetMouseButtonState(void);
|
||||||
@@ -1,52 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
|
||||||
namespace Memory
|
Byte* OS_Reserve(size_t size);
|
||||||
{
|
bool8 OS_Commit(void* ptr, size_t size);
|
||||||
Byte* OS_Reserve(size_t size);
|
void OS_Release(void* ptr, size_t size);
|
||||||
bool OS_Commit(Byte* ptr, size_t size);
|
|
||||||
void OS_Release(Byte* ptr, size_t size);
|
|
||||||
|
|
||||||
template <typename Type>
|
uint64 Time_Timestamp(void);
|
||||||
Type* OS_Reserve(size_t size)
|
void Time_ComputeDeltaTime(void);
|
||||||
{
|
float Time_GetDeltaTime(void);
|
||||||
return reinterpret_cast<Type*>(OS_Reserve(size));
|
uint64 Time_GetFrameNumber(void);
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
JULIET_API bool8 Debug_IsDebuggerPresent(void);
|
||||||
bool OS_Commit(Type* ptr, size_t size)
|
|
||||||
{
|
|
||||||
return OS_Commit(reinterpret_cast<Byte*>(ptr), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
String os_get_env_var(Arena* arena, String name);
|
||||||
void OS_Release(Type* ptr, size_t size)
|
void os_set_env_var(String name, String value);
|
||||||
{
|
|
||||||
OS_Release(reinterpret_cast<Byte*>(ptr), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Memory
|
String os_get_username(Arena* arena);
|
||||||
|
|
||||||
namespace Time
|
typedef int (*EntryPointFunc)(int, wchar_t**);
|
||||||
{
|
|
||||||
uint64 Timestamp();
|
|
||||||
void ComputeDeltaTime();
|
|
||||||
float GetDeltaTime();
|
|
||||||
uint64 GetFrameNumber();
|
|
||||||
} // namespace Time
|
|
||||||
|
|
||||||
namespace Debug
|
|
||||||
{
|
|
||||||
JULIET_API bool IsDebuggerPresent();
|
|
||||||
} // namespace Debug
|
|
||||||
|
|
||||||
String os_get_env_var(NonNullPtr<Arena> arena, const String& name);
|
|
||||||
void os_set_env_var(const String& name, const String& value);
|
|
||||||
|
|
||||||
String os_get_username(NonNullPtr<Arena> arena);
|
|
||||||
|
|
||||||
using EntryPointFunc = int (*)(int, wchar_t**);
|
|
||||||
JULIET_API int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
|
JULIET_API int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
// Fwd Declare
|
typedef struct DynamicLibrary DynamicLibrary;
|
||||||
struct DynamicLibrary;
|
typedef struct HotReloadCode HotReloadCode;
|
||||||
|
|
||||||
struct HotReloadCode
|
struct HotReloadCode
|
||||||
{
|
{
|
||||||
@@ -21,15 +21,15 @@ struct HotReloadCode
|
|||||||
|
|
||||||
uint32 UniqueID;
|
uint32 UniqueID;
|
||||||
|
|
||||||
bool IsValid : 1;
|
bool8 IsValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JULIET_API void InitHotReloadCode(NonNullPtr<Arena> arena, HotReloadCode& code, String dllName,
|
extern JULIET_API void InitHotReloadCode(Arena* arena, HotReloadCode* code, String dllName,
|
||||||
String transientDllName, String lockFilename);
|
String transientDllName, String lockFilename);
|
||||||
extern JULIET_API void ShutdownHotReloadCode(HotReloadCode& code);
|
extern JULIET_API void ShutdownHotReloadCode(HotReloadCode* code);
|
||||||
|
|
||||||
extern JULIET_API void LoadCode(HotReloadCode& code);
|
extern JULIET_API void LoadCode(HotReloadCode* code);
|
||||||
extern JULIET_API void UnloadCode(HotReloadCode& code);
|
extern JULIET_API void UnloadCode(HotReloadCode* code);
|
||||||
|
|
||||||
extern JULIET_API void ReloadCode(HotReloadCode& code);
|
extern JULIET_API void ReloadCode(HotReloadCode* code);
|
||||||
extern JULIET_API bool ShouldReloadCode(const HotReloadCode& code);
|
extern JULIET_API bool8 ShouldReloadCode(const HotReloadCode* code);
|
||||||
@@ -1,27 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
#ifdef JULIET_ENABLE_IMGUI
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
|
|
||||||
struct ImGuiContext;
|
typedef struct ImGuiContext ImGuiContext;
|
||||||
|
typedef struct Window Window;
|
||||||
|
typedef struct GraphicsDevice GraphicsDevice;
|
||||||
|
|
||||||
struct Window;
|
JULIET_API void ImGuiService_Initialize(Window* window);
|
||||||
struct GraphicsDevice;
|
JULIET_API void ImGuiService_Shutdown(void);
|
||||||
|
|
||||||
namespace ImGuiService
|
JULIET_API void ImGuiService_NewFrame(void);
|
||||||
{
|
JULIET_API void ImGuiService_Render(void);
|
||||||
JULIET_API void Initialize(NonNullPtr<Window> window);
|
|
||||||
JULIET_API void Shutdown();
|
|
||||||
|
|
||||||
JULIET_API void NewFrame();
|
JULIET_API bool8 ImGuiService_IsInitialized(void);
|
||||||
JULIET_API void Render();
|
JULIET_API ImGuiContext* ImGuiService_GetContext(void);
|
||||||
|
|
||||||
JULIET_API bool IsInitialized();
|
// Run internal unit tests
|
||||||
JULIET_API ImGuiContext* GetContext();
|
JULIET_API void ImGuiService_RunTests(void);
|
||||||
|
|
||||||
// Run internal unit tests
|
|
||||||
JULIET_API void RunTests();
|
|
||||||
} // namespace ImGuiService
|
|
||||||
|
|
||||||
#endif // JULIET_ENABLE_IMGUI
|
#endif // JULIET_ENABLE_IMGUI
|
||||||
@@ -1,12 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/HAL/Display/Window.h>
|
|
||||||
#include <Graphics/GraphicsDevice.h>
|
|
||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
namespace UnitTest
|
void UnitTest_TestImGui(void);
|
||||||
{
|
|
||||||
void TestImGui();
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum class JulietInit_Flags : uint8
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
typedef uint8 JulietInit_Flags;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
None = 0,
|
JulietInit_Flags_None = 0,
|
||||||
Display = 1 << 0,
|
JulietInit_Flags_Display = 1 << 0,
|
||||||
Audio = 1 << 1,
|
JulietInit_Flags_Audio = 1 << 1,
|
||||||
Count = Audio,
|
JulietInit_Flags_Count = JulietInit_Flags_Audio,
|
||||||
All = 0xFb
|
JulietInit_Flags_All = 0xFbu
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Arena;
|
typedef struct Arena Arena;
|
||||||
|
typedef struct GameState GameState;
|
||||||
|
typedef struct GameData GameData;
|
||||||
|
|
||||||
struct GameData
|
struct GameData
|
||||||
{
|
{
|
||||||
struct GameState* GameState;
|
GameState* GameState;
|
||||||
Arena* ScratchArena;
|
Arena* ScratchArena;
|
||||||
};
|
};
|
||||||
|
|
||||||
void JulietInit(JulietInit_Flags flags);
|
void JulietInit(JulietInit_Flags flags);
|
||||||
void JulietShutdown();
|
void JulietShutdown(void);
|
||||||
@@ -1,21 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Logging/LogTypes.h>
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
|
||||||
// TODO : Juliet strings
|
extern void JULIET_API InitializeLogManager(void);
|
||||||
// TODO Juliet Containers + Allocators...
|
extern void JULIET_API ShutdownLogManager(void);
|
||||||
// TODO: Juliet chrono, because it prevents me from doing #define global static
|
|
||||||
|
|
||||||
enum class LogLevel : uint8;
|
extern void JULIET_API LogScopeBegin(void);
|
||||||
enum class LogCategory : uint8;
|
extern void JULIET_API LogScopeEnd(void);
|
||||||
|
|
||||||
extern void JULIET_API InitializeLogManager();
|
|
||||||
extern void JULIET_API ShutdownLogManager();
|
|
||||||
|
|
||||||
extern void JULIET_API LogScopeBegin();
|
|
||||||
// TODO everything that happened in there to export them to file or something
|
|
||||||
extern void JULIET_API LogScopeEnd();
|
|
||||||
|
|
||||||
extern void JULIET_API Log(LogLevel level, LogCategory category, const char* fmt, ...);
|
extern void JULIET_API Log(LogLevel level, LogCategory category, const char* fmt, ...);
|
||||||
extern void JULIET_API LogDebug(LogCategory category, const char* fmt, ...);
|
extern void JULIET_API LogDebug(LogCategory category, const char* fmt, ...);
|
||||||
|
|||||||
@@ -1,19 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum class LogLevel : uint8
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
typedef uint8 LogLevel;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Debug = 0,
|
LogLevel_Debug = 0,
|
||||||
Message = 1,
|
LogLevel_Message = 1,
|
||||||
Warning = 2,
|
LogLevel_Warning = 2,
|
||||||
Error = 3,
|
LogLevel_Error = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class LogCategory : uint8
|
typedef uint8 LogCategory;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Core = 0,
|
LogCategory_Core = 0,
|
||||||
Graphics = 1,
|
LogCategory_Graphics = 1,
|
||||||
Networking = 2,
|
LogCategory_Networking = 2,
|
||||||
Engine = 3,
|
LogCategory_Engine = 3,
|
||||||
Tool = 4,
|
LogCategory_Tool = 4,
|
||||||
Game = 5,
|
LogCategory_Game = 5,
|
||||||
};
|
};
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/HAL/OS/OS.h>
|
#include <Core/HAL/OS/OS.h>
|
||||||
|
|
||||||
extern int JulietMain(int, wchar_t**);
|
extern int JulietMain(int argc, wchar_t** argv);
|
||||||
|
|
||||||
#if JULIET_WIN32
|
#if JULIET_WIN32
|
||||||
#ifndef WINAPI
|
#ifndef WINAPI
|
||||||
@@ -17,12 +17,10 @@ int wmain(int argc, wchar_t** argv)
|
|||||||
#else
|
#else
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
return Bootstrap(JulietMain, argc, argv);
|
return Bootstrap(JulietMain, argc, (wchar_t**)argv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
typedef struct HINSTANCE__* HINSTANCE;
|
typedef struct HINSTANCE__* HINSTANCE;
|
||||||
typedef char* LPSTR;
|
typedef char* LPSTR;
|
||||||
typedef wchar_t* PWSTR;
|
typedef wchar_t* PWSTR;
|
||||||
@@ -40,7 +38,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
|
|||||||
|
|
||||||
return Bootstrap(JulietMain, __argc, __wargv);
|
return Bootstrap(JulietMain, __argc, __wargv);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
#error "Only windows main is implemented"
|
#error "Only windows main is implemented"
|
||||||
#endif
|
#endif
|
||||||
@@ -1,46 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Juliet.h>
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
extern JULIET_API float RoundF(float value);
|
extern JULIET_API float RoundF(float value);
|
||||||
|
|
||||||
inline int32 LRoundF(float value)
|
static inline int32 LRoundF(float value)
|
||||||
{
|
{
|
||||||
return static_cast<int32>(RoundF(value));
|
return (int32)RoundF(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
#define Min(lhs, rhs) (((rhs) < (lhs)) ? (rhs) : (lhs))
|
||||||
constexpr Type Min(Type lhs, Type rhs)
|
#define Max(lhs, rhs) (((lhs) < (rhs)) ? (rhs) : (lhs))
|
||||||
{
|
#define ClampTop(value, X) Min((value), (X))
|
||||||
return rhs < lhs ? rhs : lhs;
|
#define ClampBottom(value, X) Max((value), (X))
|
||||||
}
|
#define Clamp(val, min_v, max_v) (((val) < (min_v)) ? (min_v) : (((val) > (max_v)) ? (max_v) : (val)))
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
constexpr Type Max(Type lhs, Type rhs)
|
|
||||||
{
|
|
||||||
return lhs < rhs ? rhs : lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
constexpr Type ClampTop(Type value, Type X)
|
|
||||||
{
|
|
||||||
return Min(value, X);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
constexpr Type ClampBottom(Type value, Type X)
|
|
||||||
{
|
|
||||||
return Max(value, X);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
constexpr Type Clamp(Type val, Type min, Type max)
|
|
||||||
{
|
|
||||||
if (val < min)
|
|
||||||
{
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
if (val > max)
|
|
||||||
{
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Math/Vector.h>
|
#include <Core/Math/Vector.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
typedef struct Matrix Matrix;
|
||||||
struct Matrix
|
struct Matrix
|
||||||
{
|
{
|
||||||
float m[4][4];
|
float m[4][4];
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixIdentity()
|
static inline Matrix MatrixIdentity(void)
|
||||||
{
|
{
|
||||||
Matrix result = {};
|
Matrix result = { 0 };
|
||||||
result.m[0][0] = 1.0f;
|
result.m[0][0] = 1.0f;
|
||||||
result.m[1][1] = 1.0f;
|
result.m[1][1] = 1.0f;
|
||||||
result.m[2][2] = 1.0f;
|
result.m[2][2] = 1.0f;
|
||||||
@@ -18,9 +19,9 @@ struct Matrix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix operator*(const Matrix& lhs, const Matrix& rhs)
|
static inline Matrix MatrixMultiply(Matrix lhs, Matrix rhs)
|
||||||
{
|
{
|
||||||
Matrix result = {};
|
Matrix result = { 0 };
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 4; ++j)
|
for (int j = 0; j < 4; ++j)
|
||||||
@@ -34,80 +35,80 @@ struct Matrix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixTranslation(float x, float y, float z)
|
static inline Matrix MatrixTranslation(float x, float y, float z)
|
||||||
{
|
{
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
result.m[0][3] = x;
|
result.m[0][3] = x;
|
||||||
result.m[1][3] = y;
|
result.m[1][3] = y;
|
||||||
result.m[2][3] = z;
|
result.m[2][3] = z;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixScale(float x, float y, float z)
|
static inline Matrix MatrixScale(float x, float y, float z)
|
||||||
{
|
{
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
result.m[0][0] = x;
|
result.m[0][0] = x;
|
||||||
result.m[1][1] = y;
|
result.m[1][1] = y;
|
||||||
result.m[2][2] = z;
|
result.m[2][2] = z;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixRotationX(float radians)
|
static inline Matrix MatrixRotationX(float radians)
|
||||||
{
|
{
|
||||||
float c = cosf(radians);
|
float c = cosf(radians);
|
||||||
float s = sinf(radians);
|
float s = sinf(radians);
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
result.m[1][1] = c;
|
result.m[1][1] = c;
|
||||||
result.m[1][2] = -s;
|
result.m[1][2] = -s;
|
||||||
result.m[2][1] = s;
|
result.m[2][1] = s;
|
||||||
result.m[2][2] = c;
|
result.m[2][2] = c;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixRotationY(float radians)
|
static inline Matrix MatrixRotationY(float radians)
|
||||||
{
|
{
|
||||||
float c = cosf(radians);
|
float c = cosf(radians);
|
||||||
float s = sinf(radians);
|
float s = sinf(radians);
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
result.m[0][0] = c;
|
result.m[0][0] = c;
|
||||||
result.m[0][2] = s;
|
result.m[0][2] = s;
|
||||||
result.m[2][0] = -s;
|
result.m[2][0] = -s;
|
||||||
result.m[2][2] = c;
|
result.m[2][2] = c;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixRotationZ(float radians)
|
static inline Matrix MatrixRotationZ(float radians)
|
||||||
{
|
{
|
||||||
float c = cosf(radians);
|
float c = cosf(radians);
|
||||||
float s = sinf(radians);
|
float s = sinf(radians);
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
result.m[0][0] = c;
|
result.m[0][0] = c;
|
||||||
result.m[0][1] = -s;
|
result.m[0][1] = -s;
|
||||||
result.m[1][0] = s;
|
result.m[1][0] = s;
|
||||||
result.m[1][1] = c;
|
result.m[1][1] = c;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MatrixTranslate(Matrix& m, const Vector3& v)
|
static inline void MatrixTranslate(Matrix* m, Vector3 v)
|
||||||
{
|
{
|
||||||
m.m[0][3] += v.x;
|
m->m[0][3] += v.x;
|
||||||
m.m[1][3] += v.y;
|
m->m[1][3] += v.y;
|
||||||
m.m[2][3] += v.z;
|
m->m[2][3] += v.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixRotation(float x, float y, float z)
|
static inline Matrix MatrixRotation(float x, float y, float z)
|
||||||
{
|
{
|
||||||
return MatrixRotationX(x) * MatrixRotationY(y) * MatrixRotationZ(z);
|
return MatrixMultiply(MatrixMultiply(MatrixRotationX(x), MatrixRotationY(y)), MatrixRotationZ(z));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& up)
|
static inline Matrix LookAt(Vector3 eye, Vector3 target, Vector3 up)
|
||||||
{
|
{
|
||||||
// Left-Handed convention
|
// Left-Handed convention
|
||||||
Vector3 zaxis = Normalize(target - eye); // Forward is +z
|
Vector3 zaxis = Normalize(Vector3Sub(target, eye)); // Forward is +z
|
||||||
Vector3 xaxis = Normalize(Cross(up, zaxis));
|
Vector3 xaxis = Normalize(Cross(up, zaxis));
|
||||||
Vector3 yaxis = Cross(zaxis, xaxis);
|
Vector3 yaxis = Cross(zaxis, xaxis);
|
||||||
|
|
||||||
Matrix result = {};
|
Matrix result = { 0 };
|
||||||
// Row 0
|
// Row 0
|
||||||
result.m[0][0] = xaxis.x;
|
result.m[0][0] = xaxis.x;
|
||||||
result.m[0][1] = xaxis.y;
|
result.m[0][1] = xaxis.y;
|
||||||
@@ -132,25 +133,25 @@ inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& u
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float farZ)
|
static inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float farZ)
|
||||||
{
|
{
|
||||||
// Left-Handed Perspective
|
// Left-Handed Perspective
|
||||||
float yScale = 1.0f / tanf(fovY * 0.5f);
|
float yScale = 1.0f / tanf(fovY * 0.5f);
|
||||||
float xScale = yScale / aspectRatio;
|
float xScale = yScale / aspectRatio;
|
||||||
|
|
||||||
Matrix result = {};
|
Matrix result = { 0 };
|
||||||
result.m[0][0] = xScale;
|
result.m[0][0] = xScale;
|
||||||
result.m[1][1] = yScale;
|
result.m[1][1] = yScale;
|
||||||
result.m[2][2] = farZ / (farZ - nearZ);
|
result.m[2][2] = farZ / (farZ - nearZ);
|
||||||
result.m[2][3] = (-nearZ * farZ) / (farZ - nearZ);
|
result.m[2][3] = (-nearZ * farZ) / (farZ - nearZ);
|
||||||
result.m[3][2] = 1.0f;
|
result.m[3][2] = 1.0f;
|
||||||
result.m[3][3] = 0.0f;
|
result.m[3][3] = 0.0f;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixInverse(const Matrix& m)
|
static inline Matrix MatrixInverse(Matrix m)
|
||||||
{
|
{
|
||||||
Matrix out = {};
|
Matrix out = { 0 };
|
||||||
|
|
||||||
float m00 = m.m[0][0], m01 = m.m[0][1], m02 = m.m[0][2], m03 = m.m[0][3];
|
float m00 = m.m[0][0], m01 = m.m[0][1], m02 = m.m[0][2], m03 = m.m[0][3];
|
||||||
float m10 = m.m[1][0], m11 = m.m[1][1], m12 = m.m[1][2], m13 = m.m[1][3];
|
float m10 = m.m[1][0], m11 = m.m[1][1], m12 = m.m[1][2], m13 = m.m[1][3];
|
||||||
@@ -183,8 +184,12 @@ inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float f
|
|||||||
{
|
{
|
||||||
float invDet = 1.0f / det;
|
float invDet = 1.0f / det;
|
||||||
for (int r = 0; r < 4; ++r)
|
for (int r = 0; r < 4; ++r)
|
||||||
|
{
|
||||||
for (int c = 0; c < 4; ++c)
|
for (int c = 0; c < 4; ++c)
|
||||||
|
{
|
||||||
out.m[r][c] *= invDet;
|
out.m[r][c] *= invDet;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct Rectangle
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
#define Rectangle JulietRectangle
|
||||||
|
|
||||||
|
typedef struct JulietRectangle JulietRectangle;
|
||||||
|
struct JulietRectangle
|
||||||
{
|
{
|
||||||
int32 X;
|
int32 X;
|
||||||
int32 Y;
|
int32 Y;
|
||||||
|
|||||||
@@ -1,38 +1,62 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
typedef struct Vector3 Vector3;
|
||||||
struct Vector3
|
struct Vector3
|
||||||
{
|
{
|
||||||
float x, y, z;
|
float x;
|
||||||
|
float y;
|
||||||
Vector3 operator+(const Vector3& rhs) const { return { x + rhs.x, y + rhs.y, z + rhs.z }; }
|
float z;
|
||||||
Vector3 operator-(const Vector3& rhs) const { return { x - rhs.x, y - rhs.y, z - rhs.z }; }
|
|
||||||
Vector3 operator*(float s) const { return { x * s, y * s, z * s }; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct Vector4 Vector4;
|
||||||
struct Vector4
|
struct Vector4
|
||||||
{
|
{
|
||||||
float x = 0.f;
|
float x;
|
||||||
float y = 0.f;
|
float y;
|
||||||
float z = 0.f;
|
float z;
|
||||||
float w = 0.f;
|
float w;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Vector3 Normalize(const Vector3& v)
|
static inline Vector3 Vector3Add(Vector3 lhs, Vector3 rhs)
|
||||||
{
|
{
|
||||||
float len = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
Vector3 res = { lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z };
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Vector3 Vector3Sub(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
Vector3 res = { lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z };
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Vector3 Vector3Scale(Vector3 v, float s)
|
||||||
|
{
|
||||||
|
Vector3 res = { v.x * s, v.y * s, v.z * s };
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Vector3 Normalize(Vector3 v)
|
||||||
|
{
|
||||||
|
Vector3 result = v;
|
||||||
|
float len = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||||
if (len > 0.0001f)
|
if (len > 0.0001f)
|
||||||
{
|
{
|
||||||
return { v.x / len, v.y / len, v.z / len };
|
result.x = v.x / len;
|
||||||
|
result.y = v.y / len;
|
||||||
|
result.z = v.z / len;
|
||||||
}
|
}
|
||||||
return v;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Vector3 Cross(const Vector3& a, const Vector3& b)
|
static inline Vector3 Cross(Vector3 a, Vector3 b)
|
||||||
{
|
{
|
||||||
return { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x };
|
Vector3 res = { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x };
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float Dot(const Vector3& a, const Vector3& b)
|
static inline float Dot(Vector3 a, Vector3 b)
|
||||||
{
|
{
|
||||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
#include <Core/Common/CoreUtils.h>
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
// Uninitialized allocation
|
// Uninitialized allocation
|
||||||
JULIET_API void* Malloc(size_t elem_size);
|
JULIET_API void* Malloc(size_t elem_size);
|
||||||
@@ -9,20 +10,19 @@ JULIET_API void* Malloc(size_t elem_size);
|
|||||||
JULIET_API void* Calloc(size_t nb_elem, size_t elem_size);
|
JULIET_API void* Calloc(size_t nb_elem, size_t elem_size);
|
||||||
JULIET_API void* Realloc(void* memory, size_t newSize);
|
JULIET_API void* Realloc(void* memory, size_t newSize);
|
||||||
|
|
||||||
// Free
|
static inline void FreeMemory(void* memory)
|
||||||
template <typename Type>
|
|
||||||
void Free(Type* memory)
|
|
||||||
{
|
{
|
||||||
Assert(memory);
|
Assert(memory != NULL);
|
||||||
::free(memory);
|
free(memory);
|
||||||
}
|
|
||||||
// Free and Set the ptr to nullptr
|
|
||||||
template <typename Type>
|
|
||||||
void SafeFree(Type*& memory)
|
|
||||||
{
|
|
||||||
if (memory)
|
|
||||||
{
|
|
||||||
::free(memory);
|
|
||||||
memory = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SafeFree(memory_ptr) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if ((memory_ptr) != NULL) \
|
||||||
|
{ \
|
||||||
|
free((void*)(memory_ptr)); \
|
||||||
|
(memory_ptr) = NULL; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
@@ -1,21 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
#include <Core/Memory/MemoryArenaDebug.h>
|
#include <Core/Memory/MemoryArenaDebug.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr global uint64 g_Arena_Default_Reserve_Size = Megabytes(64);
|
#define g_Arena_Default_Reserve_Size Megabytes(64)
|
||||||
constexpr global uint64 g_Arena_Default_Commit_Size = Kilobytes(64);
|
#define g_Arena_Default_Commit_Size Kilobytes(64)
|
||||||
constexpr global uint64 k_ArenaHeaderSize = 128;
|
#define k_ArenaHeaderSize ((uint64)128)
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
typedef struct Arena Arena;
|
||||||
struct ArenaDebugInfo;
|
typedef struct TempArena TempArena;
|
||||||
JULIET_API String FormatDebugTagV(const char* formatStr, std::format_args args);
|
typedef struct ArenaParams ArenaParams;
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Arena
|
struct Arena
|
||||||
{
|
{
|
||||||
@@ -35,14 +33,14 @@ struct Arena
|
|||||||
Arena* FreeBlockLast;
|
Arena* FreeBlockLast;
|
||||||
|
|
||||||
JULIET_DEBUG_ONLY(uint16 LostNodeCount;)
|
JULIET_DEBUG_ONLY(uint16 LostNodeCount;)
|
||||||
JULIET_DEBUG_ONLY(bool CanReserveMore : 1;)
|
JULIET_DEBUG_ONLY(bool8 CanReserveMore;)
|
||||||
|
|
||||||
JULIET_DEBUG_ONLY(Arena* GlobalNext;)
|
JULIET_DEBUG_ONLY(Arena* GlobalNext;)
|
||||||
JULIET_DEBUG_ONLY(Arena* GlobalPrev;)
|
JULIET_DEBUG_ONLY(Arena* GlobalPrev;)
|
||||||
JULIET_DEBUG_ONLY(ArenaDebugInfo* FirstDebugInfo;)
|
JULIET_DEBUG_ONLY(ArenaDebugInfo* FirstDebugInfo;)
|
||||||
const char* Name;
|
const char* Name;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Arena) <= k_ArenaHeaderSize);
|
StaticAssert(sizeof(Arena) <= k_ArenaHeaderSize, ArenaHeaderSizeCheck);
|
||||||
|
|
||||||
struct TempArena
|
struct TempArena
|
||||||
{
|
{
|
||||||
@@ -52,74 +50,54 @@ struct TempArena
|
|||||||
|
|
||||||
struct ArenaParams
|
struct ArenaParams
|
||||||
{
|
{
|
||||||
uint64 ReserveSize = g_Arena_Default_Reserve_Size;
|
uint64 ReserveSize;
|
||||||
uint64 CommitSize = g_Arena_Default_Commit_Size;
|
uint64 CommitSize;
|
||||||
|
|
||||||
const char* Name;
|
const char* Name;
|
||||||
|
JULIET_DEBUG_ONLY(bool8 DoNotReserveMore;)
|
||||||
// When false, will assert if a new block is reserved.
|
|
||||||
JULIET_DEBUG_ONLY(bool CanReserveMore : 1 = true;)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] JULIET_API Arena* ArenaAllocate(const ArenaParams& params,
|
JULIET_API Arena* ArenaAllocateImpl(ArenaParams params, const char* file, uint32 line);
|
||||||
const std::source_location& loc = std::source_location::current());
|
#define ArenaAllocate(...) ArenaAllocateImpl(__VA_ARGS__, __FILE__, (uint32)__LINE__)
|
||||||
JULIET_API void ArenaRelease(NonNullPtr<Arena> arena);
|
|
||||||
|
|
||||||
// Raw Push, can be used but templated helpers exists below
|
JULIET_API void ArenaRelease(Arena* arena);
|
||||||
[[nodiscard]] JULIET_API void* ArenaPush(NonNullPtr<Arena> arena, size_t size, size_t align,
|
|
||||||
bool shouldBeZeroed JULIET_DEBUG_PARAM(const char* tag));
|
// Raw Push, can be used or macros below
|
||||||
JULIET_API void ArenaPopTo(NonNullPtr<Arena> arena, size_t position);
|
JULIET_API void* ArenaPush(Arena* arena, size_t size, size_t align,
|
||||||
JULIET_API void ArenaPop(NonNullPtr<Arena> arena, size_t amount);
|
bool8 shouldBeZeroed JULIET_DEBUG_PARAM(const char* tag));
|
||||||
JULIET_API void ArenaClear(NonNullPtr<Arena> arena);
|
JULIET_API void ArenaPopTo(Arena* arena, size_t position);
|
||||||
[[nodiscard]] JULIET_API size_t ArenaPos(NonNullPtr<Arena> arena);
|
JULIET_API void ArenaPop(Arena* arena, size_t amount);
|
||||||
|
JULIET_API void ArenaClear(Arena* arena);
|
||||||
|
JULIET_API size_t ArenaPos(Arena* arena);
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
template <typename FirstDebugArg, typename... DebugArgs>
|
#define ArenaPushSize(...) ArenaPush(__VA_ARGS__)
|
||||||
|
#define ArenaPushStruct(arena, Type) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true, #Type))
|
||||||
|
#define ArenaPushStructTag(arena, Type, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true, (tag)))
|
||||||
|
#define ArenaPushArray(arena, Type, count) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true, #Type))
|
||||||
|
#define ArenaPushArrayTag(arena, Type, count, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true, (tag)))
|
||||||
|
#define ArenaPushArrayNoZero(arena, Type, count) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false, #Type))
|
||||||
|
#define ArenaPushArrayNoZeroTag(arena, Type, count, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false, (tag)))
|
||||||
|
#else
|
||||||
|
#define ArenaPushSize(...) ArenaPush(__VA_ARGS__)
|
||||||
|
#define ArenaPushStruct(arena, Type) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true))
|
||||||
|
#define ArenaPushStructTag(arena, Type, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true))
|
||||||
|
#define ArenaPushArray(arena, Type, count) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true))
|
||||||
|
#define ArenaPushArrayTag(arena, Type, count, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true))
|
||||||
|
#define ArenaPushArrayNoZero(arena, Type, count) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false))
|
||||||
|
#define ArenaPushArrayNoZeroTag(arena, Type, count, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false))
|
||||||
#endif
|
#endif
|
||||||
[[nodiscard]] inline void* ArenaPushSize(NonNullPtr<Arena> arena, size_t size, size_t align,
|
|
||||||
bool shouldBeZeroed JULIET_DEBUG_PARAM(FirstDebugArg&& firstDebugArg, DebugArgs&&... debugArgs))
|
|
||||||
{
|
|
||||||
return ArenaPush(arena, size, align,
|
|
||||||
shouldBeZeroed JULIET_DEBUG_PARAM(
|
|
||||||
[&]() -> const char*
|
|
||||||
{
|
|
||||||
return Format(GetDebugInfoArena(), std::forward<FirstDebugArg>(firstDebugArg),
|
|
||||||
std::forward<DebugArgs>(debugArgs)...)
|
|
||||||
.Str;
|
|
||||||
}()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type JULIET_DEBUG_ONLY(, typename... DebugArgs)>
|
TempArena ArenaTempBegin(Arena* arena);
|
||||||
[[nodiscard]] Type* ArenaPushStruct(NonNullPtr<Arena> arena JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs))
|
|
||||||
{
|
|
||||||
return static_cast<Type*>(
|
|
||||||
ArenaPush(arena, sizeof(Type) * 1, AlignOf(Type),
|
|
||||||
true JULIET_DEBUG_PARAM(
|
|
||||||
[&]() -> const char*
|
|
||||||
{
|
|
||||||
if constexpr (sizeof...(DebugArgs) > 0)
|
|
||||||
{
|
|
||||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
|
|
||||||
}
|
|
||||||
return GetTypeName<Type>();
|
|
||||||
}())));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type, bool shouldZero = true JULIET_DEBUG_ONLY(, typename... DebugArgs)>
|
|
||||||
[[nodiscard]] Type* ArenaPushArray(NonNullPtr<Arena> arena, size_t count JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs))
|
|
||||||
{
|
|
||||||
return static_cast<Type*>(
|
|
||||||
ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)),
|
|
||||||
shouldZero JULIET_DEBUG_PARAM(
|
|
||||||
[&]() -> const char*
|
|
||||||
{
|
|
||||||
if constexpr (sizeof...(DebugArgs) > 0)
|
|
||||||
{
|
|
||||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
|
|
||||||
}
|
|
||||||
return GetTypeName<Type>();
|
|
||||||
}())));
|
|
||||||
}
|
|
||||||
|
|
||||||
TempArena ArenaTempBegin(NonNullPtr<Arena> arena);
|
|
||||||
void ArenaTempEnd(TempArena temp);
|
void ArenaTempEnd(TempArena temp);
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
|
|
||||||
struct Arena;
|
typedef struct Arena Arena;
|
||||||
struct MemoryBlock;
|
typedef struct MemoryBlock MemoryBlock;
|
||||||
|
typedef struct ArenaDebugInfo ArenaDebugInfo;
|
||||||
|
typedef struct ArenaAllocation ArenaAllocation;
|
||||||
|
|
||||||
// Arena (Struct)
|
// Arena (Struct)
|
||||||
struct ArenaDebugInfo
|
struct ArenaDebugInfo
|
||||||
@@ -27,20 +28,16 @@ struct ArenaAllocation
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Arena (Struct)
|
// Arena (Struct)
|
||||||
void DebugRegisterArena(NonNullPtr<Arena> arena);
|
void DebugRegisterArena(Arena* arena);
|
||||||
void DebugUnregisterArena(NonNullPtr<Arena> arena);
|
void DebugUnregisterArena(Arena* arena);
|
||||||
void DebugArenaSetDebugName(NonNullPtr<Arena> arena, const char* name);
|
void DebugArenaSetDebugName(Arena* arena, const char* name);
|
||||||
bool IsDebugInfoArena(const Arena* arena); // To prevent recursion
|
bool8 IsDebugInfoArena(const Arena* arena); // To prevent recursion
|
||||||
void DebugArenaFreeBlock(Arena* block); // To clear all debug infos in a block
|
void DebugArenaFreeBlock(Arena* block); // To clear all debug infos in a block
|
||||||
void DebugArenaRemoveAllocation(Arena* block, size_t oldOffset);
|
void DebugArenaRemoveAllocation(Arena* block, size_t oldOffset);
|
||||||
void DebugArenaPopTo(Arena* block, size_t newPosition);
|
void DebugArenaPopTo(Arena* block, size_t newPosition);
|
||||||
void DebugArenaAddDebugInfo(Arena* block, size_t size, size_t offset, const char* tag);
|
void DebugArenaAddDebugInfo(Arena* block, size_t size, size_t offset, const char* tag);
|
||||||
|
|
||||||
// MemoryArena (Pool-based)
|
JULIET_API Arena* GetDebugInfoArena(void);
|
||||||
void DebugFreeArenaAllocations(MemoryBlock* blk);
|
JULIET_API Arena* GetGlobalArenaListHead(void);
|
||||||
void DebugArenaAddAllocation(MemoryBlock* blk, size_t size, size_t offset, String tag);
|
|
||||||
void DebugArenaRemoveLastAllocation(MemoryBlock* blk);
|
|
||||||
|
|
||||||
JULIET_API Arena* GetDebugInfoArena();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,63 +1,68 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ArraySize(array) (sizeof(array) / sizeof(array[0]))
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
inline int32 MemCompare(const void* leftValue, const void* rightValue, size_t size)
|
#define ArraySize(array) (sizeof(array) / sizeof((array)[0]))
|
||||||
|
|
||||||
|
static inline int32 MemCompare(const void* left_value, const void* right_value, size_t size)
|
||||||
{
|
{
|
||||||
auto left = static_cast<const unsigned char*>(leftValue);
|
const unsigned char* left = (const unsigned char*)left_value;
|
||||||
auto right = static_cast<const unsigned char*>(rightValue);
|
const unsigned char* right = (const unsigned char*)right_value;
|
||||||
while (size && *left == *right)
|
while (size && *left == *right)
|
||||||
{
|
{
|
||||||
++left;
|
++left;
|
||||||
++right;
|
++right;
|
||||||
--size;
|
--size;
|
||||||
}
|
}
|
||||||
return size ? *left - *right : 0;
|
return size ? ((int32)(*left) - (int32)(*right)) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single linked list
|
// Single linked list macros
|
||||||
void SingleLinkedListPushNext(auto*& stackTop, auto* node)
|
#define SingleLinkedListPushNext(stackTop, node) \
|
||||||
{
|
do \
|
||||||
node->Next = stackTop;
|
{ \
|
||||||
stackTop = node;
|
(node)->Next = (stackTop); \
|
||||||
}
|
(stackTop) = (node); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
void SingleLinkedListPushPrevious(auto*& stackTop, auto* node)
|
#define SingleLinkedListPushPrevious(stackTop, node) \
|
||||||
{
|
do \
|
||||||
node->Previous = stackTop;
|
{ \
|
||||||
stackTop = node;
|
(node)->Previous = (stackTop); \
|
||||||
}
|
(stackTop) = (node); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
void SingleLinkedListPopNext(auto*& stackTop)
|
#define SingleLinkedListPopNext(stackTop) \
|
||||||
{
|
do \
|
||||||
stackTop = stackTop->Next;
|
{ \
|
||||||
}
|
(stackTop) = (stackTop)->Next; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
// Double linked list
|
// Double linked list queue macro
|
||||||
template <typename QueueType, typename QueueTypeNode>
|
#define Enqueue(queue, node) \
|
||||||
void Enqueue(QueueType& queue, QueueTypeNode* node)
|
do \
|
||||||
{
|
{ \
|
||||||
if (queue.First == nullptr)
|
if ((queue).First == NULL) \
|
||||||
{
|
{ \
|
||||||
queue.First = queue.Last = node;
|
(queue).First = (queue).Last = (node); \
|
||||||
node->Next = nullptr;
|
(node)->Next = NULL; \
|
||||||
}
|
} \
|
||||||
else
|
else \
|
||||||
{
|
{ \
|
||||||
queue.Last->Next = node, queue.Last = node;
|
(queue).Last->Next = (node); \
|
||||||
node->Next = nullptr;
|
(queue).Last = (node); \
|
||||||
}
|
(node)->Next = NULL; \
|
||||||
|
} \
|
||||||
queue.Nodecount += 1;
|
(queue).Nodecount += 1; \
|
||||||
}
|
} \
|
||||||
|
while (0)
|
||||||
template <typename QueueType>
|
|
||||||
struct QueueNode
|
|
||||||
{
|
|
||||||
QueueType* Next;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DECLARE_QUEUE(type) \
|
#define DECLARE_QUEUE(type) \
|
||||||
|
typedef struct type##Queue type##Queue; \
|
||||||
struct type##Queue \
|
struct type##Queue \
|
||||||
{ \
|
{ \
|
||||||
type* First; \
|
type* First; \
|
||||||
@@ -66,8 +71,7 @@ struct QueueNode
|
|||||||
size_t Size; \
|
size_t Size; \
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: homemade versions
|
#define MemSet memset
|
||||||
#define MemSet memset
|
#define MemCopy memcpy
|
||||||
#define MemCopy memcpy
|
#define MemoryZero(dst, size) MemSet((dst), 0, (size))
|
||||||
|
#define MemZeroStruct(ptr) MemoryZero((ptr), sizeof(*(ptr)))
|
||||||
#define MemoryZero(dst, size) MemSet(dst, 0, size)
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// TODO : Do something better.
|
|
||||||
constexpr uint32 kLocalhost = (127 << 3) | (0 << 2) | (0 << 1) | 1;
|
|
||||||
constexpr uint32 kAnyIp = 0;
|
|
||||||
constexpr uint32 kBroadcastIp = (255 << 3) | (255 << 2) | (255 << 1) | 255;
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Container/Vector.h>
|
|
||||||
|
|
||||||
class NetworkPacket
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NetworkPacket();
|
|
||||||
NetworkPacket(Arena& arena);
|
|
||||||
virtual ~NetworkPacket();
|
|
||||||
NetworkPacket(NetworkPacket&);
|
|
||||||
NetworkPacket& operator=(const NetworkPacket&);
|
|
||||||
NetworkPacket(NetworkPacket&&) noexcept;
|
|
||||||
NetworkPacket& operator=(NetworkPacket&&) noexcept;
|
|
||||||
|
|
||||||
void Create(Arena& arena);
|
|
||||||
|
|
||||||
[[nodiscard]] ByteBuffer GetRawData();
|
|
||||||
|
|
||||||
// Pack
|
|
||||||
NetworkPacket& operator<<(uint32 value);
|
|
||||||
NetworkPacket& operator<<(char* data);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void Append(ByteBuffer buffer);
|
|
||||||
|
|
||||||
friend class TcpSocket;
|
|
||||||
|
|
||||||
private:
|
|
||||||
VectorArena<Byte, 4096> Data;
|
|
||||||
size_t PartialSendIndex = 0;
|
|
||||||
};
|
|
||||||
Loaded 100 of 437 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user