Compare commits

..
Author SHA1 Message Date
Patedam 5fa75c116e blue window 2026-10-27 23:06:45 -04:00
Patedam 2881b2c9d5 started d3d12 renderer. device + swap chain + associate to window 2026-10-26 22:52:08 -04:00
Patedam d79cf42a3d starting render/d3d12 layer 2026-10-25 23:37:14 -04:00
Patedam 17af5348e9 more keyboard function (is down) 2026-10-25 20:49:27 -04:00
Patedam dec8cbd059 keyboard support improved. F1 open a new window. 2026-10-25 18:12:51 -04:00
Patedam f580776964 can close windows independently 2026-10-25 15:57:52 -04:00
Patedam d2d9981efe two windows open + can close the app by pressing X 2026-10-25 15:23:07 -04:00
Patedam f6b48a1c11 window management. still missing first paint but progressing 2026-10-24 22:52:26 -04:00
Patedam bf13f269fe almost there (open window) 2026-10-24 18:17:43 -04:00
Patedam cf86dd10a7 lock submodules to version + move from stb to stb_sprintf 2026-10-24 17:36:47 -04:00
Patedam 5995dd9a47 Replace stb with standalone stb_sprintf and pin submodule versions 2026-10-24 17:31:55 -04:00
Patedam d5c6c79a76 adding xxhash 2026-10-24 17:16:41 -04:00
Patedam 7e8e626e24 adding hash library + multi windows support being started 2026-10-24 17:05:55 -04:00
Patedam f96b2e99cf windows open now 2026-10-23 23:35:45 -04:00
Patedam 4ec42f4bee open window code still not opening :) 2026-10-22 22:58:32 -04:00
Patedam 886e722c71 started window management 2026-10-20 23:15:56 -04:00
Patedam 575379e264 added thread naming 2026-10-18 23:41:43 -04:00
Patedam 17e26fdd00 fix build error 2026-10-18 23:07:59 -04:00
Patedam 5d6ca639fd Adding more core layer stuff. Can now boot. 2026-10-18 23:06:41 -04:00
Patedam 16664c68b5 wok on arena 2026-10-18 00:25:02 -04:00
Patedam ee1878cce7 core layer 2026-10-17 23:21:16 -04:00
Patedam 7542d9200d Merge pull request 'conversion to c by gemini 4 argon' (#3) from convert-to-c99 into main
Reviewed-on: #3
2026-10-17 17:19:10 -04:00
Patedam f9356f9ba7 conversion to c by gemini 4 argon 2026-10-16 23:40:45 -04:00
Patedam b70e2d21d2 entity per world 2026-10-16 21:33:57 -04:00
Patedam 16ba641d8a Support of clangd for the project 2026-10-05 23:37:18 -04:00
Patedam 7075556bf2 Reading / writing user id based on os username 2026-09-19 21:48:02 -04:00
Patedam f32a3f73a9 more path utils and fixing get os username that was returning a string including the \0
User now can be serialized properly
2026-09-18 21:19:38 -04:00
Patedam 1367146503 natvis support in build system + some natvis 2026-09-18 18:23:49 -04:00
Patedam 2fd675cf11 Added utils and types to handle paths 2026-09-18 18:14:00 -04:00
Patedam f77b7fb901 clean all path returned by GetAssetPath 2026-09-16 20:43:48 -04:00
443 changed files with 29011 additions and 106973 deletions

No files matched your search

+8
View File
@@ -22,3 +22,11 @@ Struct members: lower_snake_case. Exemple: data, node, next.
global/static variables: lower_snake_case prefixed. Exemple: g_my_global.
const variables: lower_snake_case prefixed. Exemple: k_my_const_var.
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
View File
@@ -44,10 +44,14 @@ IncludeCategories:
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentAccessModifiers: false
IndentCaseBlocks: true
IndentPPDirectives: AfterHash
IndentWidth: 4
InsertNewlineAtEOF: true
MacroBlockBegin: ''
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
ObjCSpaceAfterProperty: true
PenaltyBreakBeforeFirstCallParameter: 100
@@ -57,15 +61,10 @@ PenaltyBreakString: 100
PenaltyExcessCharacter: 1
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Left
PPIndentWidth: 1
SortIncludes: CaseInsensitive
SpacesInAngles: Never
SpacesInContainerLiterals: false
Standard: Cpp11
StatementMacros:
- UPROPERTY
- UCLASS
- USTRUCT
- GENERATED_BODY
- UENUM
TabWidth: 4
...
+34
View File
@@ -0,0 +1,34 @@
CompileFlags:
Add:
- --driver-mode=cl
- -Wno-unknown-pragmas
- -Wno-unused-command-line-argument
- -Wno-unused-function
- -Wno-undefined-internal
- -Wno-initializer-overrides
- /IJuliet
Remove:
- /Yu*
- /Yc*
- /Fp*
- /MP
- /Zi
- /Gw
- /Gy
- /Bt+
- /EHa-
Diagnostics:
UnusedIncludes: None
Suppress:
- unused-function
- undefined-internal
- initializer-overrides
InlayHints:
Enabled: true
ParameterNames: true
DeducedTypes: true
Designators: true
BlockEnd: false
TypeNameLimit: 24
+5
View File
@@ -9,6 +9,7 @@
# Binaries
[Bb]in/
[Bb]uild/
[Ll]ib/
.idea/
.vs/
@@ -56,3 +57,7 @@ launch_*.txt
*.log
misc/agent_error.log
misc/agent_output_ship.log
# Clangd
compile_commands.json
.cache/
+11
View File
@@ -1,3 +1,14 @@
[submodule "External/Imgui"]
path = External/Imgui
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
+2
View File
@@ -0,0 +1,2 @@
; Paul
1
+3
View File
@@ -3,4 +3,7 @@
<LLVMInstallDir>C:\Program Files\LLVM</LLVMInstallDir>
<LLVMToolsVersion>19.1.0</LLVMToolsVersion>
</PropertyGroup>
<ItemGroup>
<Natvis Include="$(MSBuildThisFileDirectory)Natvis\*.natvis" />
</ItemGroup>
</Project>
+1 -1
+4 -2
View File
@@ -1,4 +1,6 @@
#pragma once
constexpr index_t kPlayCamera = 0;
constexpr index_t kDebugCamera = 1;
#include <Juliet.h>
#define kPlayCamera ((index_t)0)
#define kDebugCamera ((index_t)1)
+163
View File
@@ -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
-170
View File
@@ -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
+5 -3
View File
@@ -1,10 +1,12 @@
#pragma once
#include <Juliet.h>
// TODO : Should support Debug/Profile/Release properly.
// I think debug profile should have this controller but not release
void ActivateDebugController();
void DeactivateDebugController();
bool IsDebugControllerActive();
void ActivateDebugController(void);
void DeactivateDebugController(void);
bool8 IsDebugControllerActive(void);
void UpdateDebugController(float dt);
#if JULIET_DEBUG
+140
View File
@@ -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
-322
View File
@@ -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));
String path = GetAssetPath(temp.Arena, AssetType::JAsset, ConstString(worldFilePath));
if (ImGui::Button("Save World"))
{
Archive data = { .arena = temp.Arena, .loading = false };
Serialize(data, world, path);
}
ImGui::SameLine();
if (ImGui::Button("Load World"))
{
Archive data{ .arena = temp.Arena, .loading = true };
Serialize(data, world, path);
}
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
View File
@@ -1,38 +1,39 @@
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#include <Core/Container/Vector.h>
#include <Core/Memory/MemoryArena.h>
#include <Entity/Entity.h>
struct Archive;
struct EntityManager;
typedef struct Archive Archive;
typedef struct EntityManager EntityManager;
#pragma pack(push, 1)
typedef struct WorldFileHeader WorldFileHeader;
struct WorldFileHeader
{
uint32 Magic = 0x444C574A; // 'JWLD' in little-endian
uint32 Magic; // 0x444C574A ('JWLD' in little-endian)
};
#pragma pack(pop)
constexpr uint32 kWorldMagic = 0x444C574A; // 'JWLD'
constexpr uint32 kWorldVersion = 1;
#define kWorldMagic ((uint32)0x444C574A) // 'JWLD'
#define kWorldVersion ((uint32)1)
typedef struct World World;
struct World
{
Arena* WorldArena = nullptr;
EntityManager* EntityManager = nullptr;
Arena* WorldArena;
EntityManager* EntityManager;
};
void InitWorld(NonNullPtr<World> world, NonNullPtr<Arena> arena);
void ShutdownWorld(NonNullPtr<World> world);
void InitWorld(World* world, Arena* arena);
void ShutdownWorld(World* world);
void AddToWorld(NonNullPtr<World> world, NonNullPtr<Entity> entity);
void RemoveWorldEntity(World& world, size_t index);
void AddToWorld(World* world, Entity* entity);
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
void RenderWorldEditorUI(World& world);
void RenderWorldEditorUI(World* world);
#endif
+63
View File
@@ -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
-49
View File
@@ -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();
}
+3 -1
View File
@@ -1,5 +1,7 @@
#pragma once
#include <Juliet.h>
#if JULIET_DEBUG
void DrawTopBar();
void DrawTopBar(void);
#endif
+115
View File
@@ -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;
}
-50
View File
@@ -1,50 +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);
}
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;
}
+67 -38
View File
@@ -6,66 +6,95 @@
#include <Entity/entity_common.h>
#include <Entity/EntityManager.h>
struct Entity final
typedef struct Entity Entity;
struct Entity
{
DECLARE_CLASS()
EntityID ID = 0;
const Class* derived_kind = nullptr;
DerivedType derived = nullptr;
Vector4 position = {};
bool is_dirty = false;
EntityID ID;
const Class* derived_kind;
DerivedType derived;
Vector4 position;
bool8 is_dirty;
};
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
{
DECLARE_ENTITY();
DECLARE_ENTITY()
};
//
template <typename EntityType>
concept EntityConcept = requires(EntityType entity) {
{ EntityType::kind } -> std::convertible_to<const Class*>;
requires std::same_as<decltype(entity.base), Entity*>;
};
template <typename EntityType>
requires EntityConcept<EntityType>
[[nodiscard]] bool IsA(const Entity* entity)
static inline EntityID make_entity_id(uint8 user_id, uint64 local_counter)
{
Assert(entity != nullptr);
return entity->derived_kind == EntityType::kind;
Assert(user_id != kInvalid_user_id);
Assert((local_counter & kEntityID_user_id_mask) == kInvalid_entity_id);
EntityID result = ((EntityID)user_id << kEntityID_user_id_shift) | (local_counter & kEntityID_user_id_mask);
return result;
}
template <typename EntityType>
requires EntityConcept<EntityType>
[[nodiscard]] EntityType* MakeEntity(EntityManager& manager, float x, float y, float z)
static inline uint8 get_user_id(EntityID entity_id)
{
Entity* base_ptr = allocate_entity(manager, EntityType::kind);
Assert(base_ptr);
return (uint8)((entity_id & kEntityID_user_id_mask) >> kEntityID_user_id_shift);
}
base_ptr->ID = EntityManager::ID++;
static inline uint64 get_local_counter(EntityID entity_id)
{
return (uint64)entity_id & ~kEntityID_user_id_mask;
}
static inline bool8 is_entity_id_valid(EntityID entity_id)
{
bool8 result = (entity_id != kInvalid_entity_id);
return result;
}
static inline bool8 IsEntityA(const Entity* entity, const Class* kind)
{
Assert(entity != NULL);
return entity->derived_kind == kind;
}
#define IsEntityOfType(entity_ptr, EntityType) IsEntityA((entity_ptr), ClassKind(EntityType))
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.y = y;
base_ptr->position.z = z;
base_ptr->position.w = 1.0f;
return (EntityType*)base_ptr->derived;
return base_ptr->derived;
}
template <typename EntityType>
requires EntityConcept<EntityType>
[[nodiscard]] EntityType* DownCast(Entity* entity)
#define MakeEntity(EntityType, manager_ptr, x, y, z) \
((EntityType*)make_entity_by_class((manager_ptr), ClassKind(EntityType), (x), (y), (z)))
static inline void* down_cast_entity(Entity* entity, const Class* kind)
{
Assert(entity != nullptr);
Assert(IsA<EntityType>(entity));
return static_cast<EntityType*>(entity->derived);
Assert(entity != NULL);
Assert(IsEntityA(entity, kind));
return entity->derived;
}
void serialize(Archive& ar, NonNullPtr<Entity> entity);
#define DownCastEntity(EntityType, entity_ptr) ((EntityType*)down_cast_entity((entity_ptr), ClassKind(EntityType)))
[[nodiscard]] const Class* find_class_by_name(String name);
void serialize_entity(Archive* ar, Entity* entity);
[[nodiscard]] const Class* resolve_entity_class(uint8 kind, uint32 crc);
JULIET_API uint8 get_local_user_id(void);
JULIET_API String format_entity_id(Arena* arena, EntityID id);
JULIET_API bool8 parse_entity_id(String str, EntityID* outId);
const Class* find_class_by_name(String name);
const Class* resolve_entity_class(uint8 kind, uint32 crc);
+190
View File
@@ -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;
}
}
}
-145
View File
@@ -1,145 +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>
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;
}
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;
}
+20 -14
View File
@@ -3,11 +3,13 @@
#include <Core/Container/Vector.h>
#include <Entity/entity_common.h>
struct World;
struct EntityTemplate;
struct Entity;
struct Class;
typedef struct World World;
typedef struct EntityTemplate EntityTemplate;
typedef struct Entity Entity;
typedef struct Class Class;
typedef struct Archive Archive;
typedef struct typed_entity_array typed_entity_array;
struct typed_entity_array
{
Arena* arena;
@@ -15,20 +17,24 @@ struct typed_entity_array
size_t count;
};
typedef struct EntityManager EntityManager;
struct EntityManager
{
static EntityID ID;
uint64 next_local_counter;
// 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);
void ShutdownEntityManager();
EntityManager& GetEntityManager();
EntityTemplate* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity);
[[nodiscard]] Entity* allocate_entity(EntityManager& manager, NonNullPtr<const Class> derived_type_class);
void UpdateEntityManager(EntityManager& manager);
[[nodisacrd]] Entity* deserialize_entity(Archive& archive, EntityManager& manager);
extern EntityID g_entity_manager_id;
void InitEntityManager(World* world);
void ShutdownEntityManager(void);
EntityManager* GetEntityManager(void);
EntityTemplate* RegisterEntity(EntityManager* manager, Entity* base, DerivedType entity);
Entity* allocate_entity(EntityManager* manager, const Class* derived_type_class);
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
#define AS_STR(name) #name
const char* kEntity_type_names[] = {
const char* kEntity_type_names[] = {
ENTITY_TYPE_LIST(AS_STR)
"Count"
};
#undef AS_STR
#define AS_CLASS(name) name::kind
const Class* kEntity_type_class_ptr[]
{
#define AS_CLASS(name) &class_kind_##name
const Class* kEntity_type_class_ptr[] = {
ENTITY_TYPE_LIST(AS_CLASS)
nullptr
NULL
};
#undef AS_CLASS
// clang-format on
+26 -18
View File
@@ -1,40 +1,48 @@
#pragma once
#include <Core/Common/EnumUtils.h>
#include <Engine/Class.h>
struct Class;
using DerivedType = void*;
using EntityID = uint64_t;
typedef void* DerivedType;
typedef uint64 EntityID;
#define kInvalid_user_id ((uint8)0U)
#define kInvalid_entity_id ((EntityID)0ULL)
#define kEntityID_user_id_shift ((EntityID)56ULL)
#define kEntityID_user_id_mask ((EntityID)0xFF00000000000000ULL)
// clang-format off
#define ENTITY_TYPE_LIST(X) X(Inert),
#define AS_ENUM(name) name
enum class Entity_Type : uint8
typedef uint8 Entity_Type;
#define AS_ENUM(name) Entity_Type_##name
enum
{
ENTITY_TYPE_LIST(AS_ENUM)
Count
Entity_Type_Count
};
#undef AS_ENUM
extern const char* kEntity_type_names[];
extern const Class* kEntity_type_class_ptr[];
#define ENTITY(kind) ToUnderlying(Entity_Type::kind)
#define ENTITY(kind) ((uint8)Entity_Type_##kind)
// clang-format on
struct Entity;
typedef struct Entity Entity;
#define DECLARE_ENTITY() \
Entity* base; \
DECLARE_CLASS()
#define DECLARE_ENTITY() Entity* base;
#define DEFINE_ENTITY_VERSIONED(entity, version) \
constexpr Class entityKind##entity = \
MakeClass(ConstString(#entity), (uint8)Entity_Type::entity, (version), &class_kind_Entity, sizeof(entity), \
alignof(entity), (&initialize_thunk<entity>), (&serialize_thunk<entity>)); \
Class* entity::kind = const_cast<Class*>(&entityKind##entity);
#define DEFINE_ENTITY_VERSIONED(entity, version_num) \
const Class class_kind_##entity = { \
.Name = ConstString(#entity), \
.kind = (uint8)Entity_Type_##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;
+22
View File
@@ -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)
-9
View File
@@ -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);
}
+3 -1
View File
@@ -2,9 +2,11 @@
#include <Entity/entity_common.h>
typedef struct Inert Inert;
struct Inert
{
DECLARE_ENTITY()
index_t MeshInstance = indexMax;
index_t MeshInstance;
};
DECLARE_CLASS(Inert)
+171
View File
@@ -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
-173
View File
@@ -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
+1 -4
View File
@@ -4,9 +4,6 @@
#if JULIET_DEBUG
namespace UnitTest
{
void WorldUnitTest();
} // namespace UnitTest
void UnitTest_WorldUnitTest(void);
#endif
+47 -41
View File
@@ -13,28 +13,26 @@
#include <Entity/EntityManager.h>
#include <Graphics/Camera.h>
#include <Graphics/MeshRenderer.h>
#include <imgui.h>
#include <dcimgui.h>
#include <stdio.h>
#if JULIET_DEBUG
#include <Debug/DebugTopBar.h>
#include <UnitTest/WorldUnitTest.h>
#endif
namespace
{
GameState* gGameState = nullptr;
}
global GameState* gGameState = NULL;
GameState* GetGameState()
GameState* GetGameState(void)
{
return gGameState;
}
extern "C" JULIET_API void __cdecl GameShutdown()
JULIET_API void __cdecl GameShutdown(void)
{
printf("Shutting down game...\n");
if (gGameState && gGameState->World)
if (gGameState != NULL && gGameState->World != NULL)
{
ShutdownWorld(gGameState->World);
}
@@ -42,47 +40,55 @@ extern "C" JULIET_API void __cdecl GameShutdown()
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;
if (!gGameState)
if (gGameState == NULL)
{
Arena* gameStateArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "Game Total Arena" });
auto* gameState = ArenaPushStruct<GameState>(gameStateArena);
ArenaParams gameStateParams = { .ReserveSize = Megabytes(1), .Name = "Game Total Arena" };
Arena* gameStateArena = ArenaAllocate(gameStateParams);
GameState* gameState = ArenaPushStruct(gameStateArena, GameState);
gGameState = params->GameState = gameState;
gameState->TotalArena = gameStateArena;
gameState->Mode = GameMode_Editor;
gameState->TotalTime = 0.0f;
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
ReserveCamera(4);
#if JULIET_DEBUG
UnitTest::WorldUnitTest();
UnitTest_WorldUnitTest();
#endif
// Bootstrap world
auto* worldArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "World Arena" });
World* world = ArenaPushStruct<World>(worldArena JULIET_DEBUG_PARAM("World"));
ArenaParams worldParams = { .ReserveSize = Megabytes(1), .Name = "World Arena" };
Arena* worldArena = ArenaAllocate(worldParams);
World* world = ArenaPushStructTag(worldArena, World, "World");
gameState->World = world;
InitWorld(gameState->World, worldArena);
// Entity Use case
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();
MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, MatrixIdentity());
Matrix identity = MatrixIdentity();
MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, &identity);
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;
// Summer at 2pm lighting
@@ -97,64 +103,64 @@ extern "C" JULIET_API void __cdecl GameUpdate(GameData* params, [[maybe_unused]]
#endif
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
RenderWorldEditorUI(*gGameState->World);
RenderWorldEditorUI(gGameState->World);
#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
}
auto& manager = GetEntityManager();
EntityManager* manager = GetEntityManager();
UpdateEntityManager(manager);
if (gGameState->Mode == GameMode::Debug)
if (gGameState->Mode == GameMode_Debug)
{
if (previousFrameMode == GameMode::Play)
if (previousFrameMode == GameMode_Play)
{
ActivateDebugController();
}
if (IsKeyPressed(ScanCode::Escape))
if (IsKeyPressed(ScanCode_Escape))
{
gGameState->Mode = GameMode::Editor;
gGameState->Mode = GameMode_Editor;
}
UpdateDebugController(deltaTime);
#if JULIET_DEBUG
ImGui::Begin("Debug");
ImGui_Begin("Debug", NULL, ImGuiWindowFlags_None);
RenderImGuiDebugController(deltaTime);
ImGui::End();
ImGui_End();
#endif
}
if (gGameState->Mode != GameMode::Debug && previousFrameMode == GameMode::Debug)
if (gGameState->Mode != GameMode_Debug && previousFrameMode == GameMode_Debug)
{
DeactivateDebugController();
}
+13 -11
View File
@@ -3,25 +3,27 @@
#include <Core/Memory/MemoryArena.h>
#include <Data/World.h>
struct EntityManager;
typedef struct EntityManager EntityManager;
enum class GameMode
typedef uint32 GameMode;
enum
{
Editor,
Play,
Debug
GameMode_Editor = 0,
GameMode_Play,
GameMode_Debug
};
typedef struct GameState GameState;
struct GameState
{
Arena* TotalArena = nullptr;
Arena* TotalArena;
World* World = nullptr;
World* World;
GameMode Mode = GameMode::Editor;
GameMode Mode;
float TotalTime = 0.0f;
int Score = 0;
float TotalTime;
int Score;
};
[[nodiscard]] extern GameState* GetGameState();
extern GameState* GetGameState(void);
-658
View File
@@ -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>
+30
View File
@@ -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"
+299
View File
@@ -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);
+193
View File
@@ -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);
}
+88
View File
@@ -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)))
+98
View File
@@ -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
+13
View File
@@ -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;
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
internal void main_thread_core_entry_point(int argc, char** argv);
internal bool32 update();
+26
View File
@@ -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;
}
+7
View File
@@ -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);
+20
View File
@@ -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
+24
View File
@@ -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
View File
Whitespace-only changes.
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#define ThreadNameF(...) (set_thread_namef(__VA_ARGS__))
+33
View File
@@ -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;
}
+70
View File
@@ -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);
+1
View File
@@ -0,0 +1 @@
// OS DEPEND see os/core/os_core.c
+8
View File
@@ -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);
View File
Whitespace-only changes.
+6
View File
@@ -0,0 +1,6 @@
#pragma once
// =============================================================================
// Aborting (os dependent see os/core/os_core.c)
internal void abort_self(uint64 exit_code);
+395
View File
@@ -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;
}
+104
View File
@@ -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);
+1
View File
@@ -0,0 +1 @@
// OS DEPEND see os/core/os_core.c
+11
View File
@@ -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();
+71
View File
@@ -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)
+29
View File
@@ -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)
+18
View File
@@ -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);
}
+39
View File
@@ -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))
+4285
View File
File diff suppressed because it is too large. Load diff
+1
Vendored Submodule
+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;
};
+41 -43
View File
@@ -1,62 +1,60 @@
#pragma once
#pragma once
#include <Core/Common/CoreUtils.h>
#include <Core/Common/String.h>
// From https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
namespace details
{
constexpr uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a,
0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074,
0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525,
0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76,
0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6,
0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7,
0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330,
0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
}
global const uint32 g_crc32_tab[256] = {
0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u, 0x0edb8832u,
0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u, 0x1db71064u, 0x6ab020f2u,
0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u, 0x136c9856u, 0x646ba8c0u, 0xfd62f97au,
0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u, 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u,
0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu, 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u,
0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u, 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u,
0xcfba9599u, 0xb8bda50fu, 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu,
0xb6662d3du, 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u,
0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u, 0x6b6b51f4u,
0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u, 0x65b0d9c6u, 0x12b7e950u,
0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u, 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u,
0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu, 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u,
0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u, 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u,
0x206f85b3u, 0xb966d409u, 0xce61e49fu, 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u,
0xb7bd5c3bu, 0xc0ba6cadu, 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u,
0x73dc1683u, 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u, 0xfed41b76u,
0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u, 0xd6d6a3e8u, 0xa1d1937eu,
0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu, 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u,
0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u, 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u,
0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu, 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u,
0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du, 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu,
0x72076785u, 0x05005713u, 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u,
0x0bdbdf21u, 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u, 0xa00ae278u,
0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu, 0xaed16a4au, 0xd9d65adcu,
0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u, 0xbdbdf21cu, 0xcabac28au, 0x53b39330u,
0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu, 0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u,
0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du
};
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;
uint32_t crc = ~0U;
uint32 crc = ~0U;
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;
}
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));
}
+49 -46
View File
@@ -1,65 +1,68 @@
#pragma once
using uint8 = uint8_t;
using uint16 = uint16_t;
using uint32 = uint32_t;
using uint64 = uint64_t;
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
using int8 = int8_t;
using int16 = int16_t;
using int32 = int32_t;
using int64 = int64_t;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
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;
using index_t = size_t;
typedef uint8 bool8;
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
{
Byte* Data;
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
template <typename Type>
consteval Type MaxValueOf()
{
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>();
#define int8Max ((int8)0x7F)
#define int16Max ((int16)0x7FFF)
#define int32Max ((int32)0x7FFFFFFF)
#define int64Max ((int64)0x7FFFFFFFFFFFFFFFll)
constexpr int8 int8Max = MaxValueOf<int8>();
constexpr int16 int16Max = MaxValueOf<int16>();
constexpr int32 int32Max = MaxValueOf<int32>();
constexpr int64 int64Max = MaxValueOf<int64>();
#define indexMax ((index_t)SIZE_MAX)
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>
consteval Type MinValueOf()
{
return std::numeric_limits<Type>::lowest();
}
#define int8Min ((int8)(-128))
#define int16Min ((int16)(-32768))
#define int32Min ((int32)(-2147483647 - 1))
#define int64Min ((int64)(-9223372036854775807ll - 1ll))
constexpr uint8 uint8Min = MinValueOf<uint8>();
constexpr uint16 uint16Min = MinValueOf<uint16>();
constexpr uint32 uint32Min = MinValueOf<uint32>();
constexpr uint64 uint64Min = MinValueOf<uint64>();
#define indexMin ((index_t)0u)
constexpr int8 int8Min = MinValueOf<int8>();
constexpr int16 int16Min = MinValueOf<int16>();
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
#define Kilobytes(value) ((uint64)(value) * 1024ull)
#define Megabytes(value) (Kilobytes(value) * 1024ull)
+57 -92
View File
@@ -1,10 +1,15 @@
#pragma once
#pragma once
#include <Juliet.h>
#include <Core/Common/CoreTypes.h>
#define global 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
#define JULIET_STR(x) #x
#define JULIET_TOSTRING(x) JULIET_STR(x)
@@ -37,10 +42,8 @@
#endif
#if defined(_MSC_VER)
// MSVC specific intrinsic
#define JULIET_PLATFORM_BREAK() (__nop(), __debugbreak())
#elif defined(__clang__) || defined(__GNUC__)
// Clang/GCC specific intrinsic
#define JULIET_PLATFORM_BREAK() __builtin_trap()
#else
#include <signal.h>
@@ -49,18 +52,14 @@
#if JULIET_DEBUG
#define JULIET_ASSERT_INTERNAL(expression, message) \
JULIET_WARNING_PUSH \
JULIET_SUPPRESS_CLANG("-Wextra-semi-stmt") \
JULIET_SUPPRESS_MSVC(4127) \
JULIET_SUPPRESS_MSVC(4548) \
do \
{ \
if (!(expression)) [[unlikely]] \
if (!(expression)) \
{ \
JulietAssert(#expression, message); \
JulietAssert(#expression, message, __FILE__, __func__, (uint32)__LINE__, 0); \
} \
} \
JULIET_WARNING_POP \
static_assert(true, "")
while (0)
#define AssertHR(hr_expression, message) \
do \
@@ -68,7 +67,7 @@
long hr_val = (hr_expression); \
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)
@@ -80,7 +79,7 @@
#define Unimplemented() \
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)
@@ -90,85 +89,60 @@
#define Unimplemented() ((void)0)
#endif
JULIET_API extern void JulietAssert(const char* expression, const char* message,
std::source_location location = std::source_location::current(), long handleResult = 0);
JULIET_API extern void JulietAssert(const char* expression, const char* message, const char* file, const char* function,
uint32 line, long handle_result);
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
inline void ZeroSize(size_t size, void* ptr)
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), (Pointer))
static inline void ZeroSize(size_t size, void* ptr)
{
auto Byte = (uint8*)ptr;
uint8* byte_ptr = (uint8*)ptr;
while (size--)
{
*Byte++ = 0;
*byte_ptr++ = 0;
}
}
#define Restrict __restrict
template <class Function>
class DeferredFunction
static inline bool8 IsValidByteBuffer(ByteBuffer buffer)
{
public:
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) };
return (buffer.Size > 0 && buffer.Data != NULL);
}
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);
template <std::integral T>
[[nodiscard]] constexpr T AlignPow2(T x, T alignment)
static inline uint64 AlignPow2(uint64 x, uint64 alignment)
{
// Safety Check:
Assert(std::has_single_bit(static_cast<size_t>(alignment)));
Assert(IsPow2(alignment));
return (x + alignment - 1) & ~(alignment - 1);
}
template <typename T>
inline void Swap(T* Restrict a, T* Restrict b)
static inline void SwapMemory(void* Restrict a, void* Restrict b, size_t elem_size)
{
T temp = std::move(*a);
*a = std::move(*b);
*b = std::move(temp);
uint8* pa = (uint8*)a;
uint8* pb = (uint8*)b;
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__)
#define COMPILER_CLANG 1
#elif defined(_MSC_VER)
#define COMPILER_MSVC 1
#endif
// Undef anything not defined
#if !defined(COMPILER_CLANG)
#define COMPILER_CLANG 0
#endif
@@ -186,42 +160,33 @@ inline void Swap(T* Restrict a, T* Restrict b)
#error AlignOf not defined for this compiler.
#endif
template <typename T>
[[nodiscard]] constexpr const char* GetTypeName()
{
#if COMPILER_CLANG
return __PRETTY_FUNCTION__;
#elif COMPILER_MSVC
return __FUNCSIG__;
#elif COMPILER_GCC
return __PRETTY_FUNCTION__;
#if COMPILER_MSVC || (COMPILER_CLANG && defined(_MSC_VER))
#define ThreadLocal __declspec(thread)
#else
return "UnknownType";
#define ThreadLocal __thread
#endif
}
inline uint16 safe_cast_uint16(uint32 value)
static inline uint16 safe_cast_uint16(uint32 value)
{
Assert(value <= uint16Max);
uint16 result = (uint16)value;
return result;
}
const uint32 bitmask1 = 0b0000'0001;
const uint32 bitmask2 = 0b0000'0011;
const uint32 bitmask3 = 0b0000'0111;
const uint32 bitmask4 = 0b0000'1111;
const uint32 bitmask5 = 0b0001'1111;
const uint32 bitmask6 = 0b0011'1111;
const uint32 bitmask7 = 0b0111'1111;
const uint32 bitmask8 = 0b1111'1111;
const uint32 bitmask9 = 0x0000'01ff;
const uint32 bitmask10 = 0x0000'03ff;
const uint32 bitmask11 = 0x0000'07ff;
const uint32 bitmask12 = 0x0000'0fff;
const uint32 bitmask13 = 0x0000'1fff;
const uint32 bitmask14 = 0x0000'3fff;
const uint32 bitmask15 = 0x0000'7fff;
const uint32 bitmask16 = 0x0000'ffff;
// ...
const uint32 bitmask32 = 0xffff'ffff;
#define bitmask1 0x00000001u
#define bitmask2 0x00000003u
#define bitmask3 0x00000007u
#define bitmask4 0x0000000fu
#define bitmask5 0x0000001fu
#define bitmask6 0x0000003fu
#define bitmask7 0x0000007fu
#define bitmask8 0x000000ffu
#define bitmask9 0x000001ffu
#define bitmask10 0x000003ffu
#define bitmask11 0x000007ffu
#define bitmask12 0x00000fffu
#define bitmask13 0x00001fffu
#define bitmask14 0x00003fffu
#define bitmask15 0x00007fffu
#define bitmask16 0x0000ffffu
#define bitmask32 0xffffffffu
-86
View File
@@ -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);
}
-110
View File
@@ -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>;
+68 -78
View File
@@ -1,22 +1,14 @@
#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/Memory/Utils.h>
#ifdef global
#undef global
#define RESTORE_GLOBAL
#endif
typedef struct Arena Arena;
#ifdef RESTORE_GLOBAL
#define global static
#undef RESTORE_GLOBAL
#endif
struct Arena;
#define ConstString(str) { const_cast<char*>((str)), sizeof(str) - 1 }
#define ConstString(str) ((String){ (char*)(str), sizeof(str) - 1 })
#define ConstStringInit(str) { (char*)(str), sizeof(str) - 1 }
#define CStr(str) ((str).Str)
#define InplaceString(name, size) \
char name##_[size]; \
@@ -24,55 +16,69 @@ struct Arena;
String name = { name##_, 0 }
// Everything is Little Endian
enum class StringEncoding : uint8
typedef uint8 StringEncoding;
enum
{
Unknown = 0,
ASCII,
LATIN1,
UTF8,
UTF16,
UTF32,
UCS2,
UCS4,
StringEncoding_Unknown = 0,
StringEncoding_ASCII,
StringEncoding_LATIN1,
StringEncoding_UTF8,
StringEncoding_UTF16,
StringEncoding_UTF32,
StringEncoding_UCS2,
StringEncoding_UCS4,
};
// Represents a UTF-8 String.
// Not null terminated.
typedef struct String8 String8;
struct String8
{
char* Str;
size_t Size;
};
using String = String8;
typedef String8 String;
typedef struct String16 String16;
struct String16
{
uint16* Str;
size_t Size;
};
struct StringBuffer : String
typedef struct StringBuffer StringBuffer;
struct StringBuffer
{
union
{
String8 str8;
struct
{
char* Str;
size_t Size;
};
};
size_t Capacity;
};
typedef struct UnicodeDecode UnicodeDecode;
struct UnicodeDecode
{
uint32 Increment;
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;
}
inline size_t StringLength(const char* str)
static inline size_t StringLengthCStr(const char* str)
{
size_t length = 0;
if (str)
if (str != NULL)
{
while (*str)
{
@@ -84,47 +90,46 @@ inline size_t StringLength(const char* str)
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 = {};
result.Str = const_cast<char*>(str);
result.Size = str ? strlen(str) : 0;
String result = { 0 };
result.Str = (char*)str;
result.Size = (str != NULL) ? strlen(str) : 0;
return result;
}
inline String FindChar(String str, char c)
static inline String FindChar(String str, char c)
{
String result = str;
while (result.Size)
String result = { 0 };
String cursor = str;
while (cursor.Size > 0)
{
if (*result.Str != c)
if (*cursor.Str == c)
{
++result.Str;
--result.Size;
result = cursor;
break;
}
++cursor.Str;
--cursor.Size;
}
else
{
return result;
}
}
return {};
}
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:
// - < 0 if str1 < str2
// - = 0 : Both strings are equals
// - > 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 len2 = StringLength(str2);
@@ -134,62 +139,47 @@ inline int32 StringCompare(String str1, String str2)
{
if (len1 > len2)
{
return 1;
result = 1;
}
if (len1 < len2)
else if (len1 < len2)
{
return -1;
result = -1;
}
return 0;
}
return result;
}
JULIET_API uint32 StepUTF8(String& inStr);
JULIET_API uint32 StepUTF8(String* inStr);
JULIET_API String FindString(String strLeft, String strRight);
// Case insensitive compare. Supports ASCII only
// TODO: Support UNICODE
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
// Do not allocate anything, you must allocate your out buffer yourself
// TODO: Version taking arena that can allocate
// 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);
extern JULIET_API bool8 ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer* dst, bool8 nullTerminate);
extern JULIET_API bool8 ConvertStringByName(String from, String to, String src, StringBuffer* dst, bool8 nullTerminate);
JULIET_API String StringCopy(NonNullPtr<Arena> arena, String str);
JULIET_API String16 str16_from_8(NonNullPtr<Arena> arena, String8 str);
JULIET_API String StringCopy(Arena* arena, String str);
JULIET_API String16 str16_from_8(Arena* arena, String8 str);
String trim_whitespace(String str);
template <typename... Args>
String Format(NonNullPtr<Arena> arena, const char* formatStr, Args&&... args)
{
std::string result = std::vformat(formatStr, std::make_format_args(args...));
return StringCopy(arena, WrapString(result.c_str()));
}
JULIET_API String StringFormatV(Arena* arena, const char* formatStr, va_list args);
JULIET_API String StringFormat(Arena* arena, const char* formatStr, ...);
#define juliet_snprintf snprintf
#ifdef UNIT_TEST
namespace UnitTest
static inline void UnitTest_TestFindChar(void)
{
inline void TestFindChar()
{
String s1 = ConstString("");
String s2 = ConstString("abcdefabcdef");
String s3 = ConstString("11111111111111111111");
Assert(FindChar(s1, 'x').Str == nullptr);
Assert(FindChar(s2, 'y').Str == nullptr);
Assert(FindChar(s1, 'x').Str == NULL);
Assert(FindChar(s2, 'y').Str == NULL);
Assert(FindChar(s2, 'a').Str - s2.Str == 0);
Assert(FindChar(s2, 'd').Str - s2.Str == 3);
Assert(FindChar(s2, 'f').Str - s2.Str == 5);
Assert(FindChar(s3, '1').Str - s3.Str == 0);
}
} // namespace UnitTest
}
#endif
+70 -93
View File
@@ -2,125 +2,102 @@
#include <Juliet.h>
#include <Core/Common/CRC32.h>
#include <Core/Common/String.h>
#include <Core/HAL/IO/IOStream.h>
#include <Core/Math/Vector.h>
// .jasset
// AssetFile ::= { CommentLine | EmptyLine | PropertyDeclaration } ;
// CommentLine ::= ( "#" | "//" ) { Character } LineEnding ;
// EmptyLine ::= { Whitespace } LineEnding ;
// PropertyDeclaration ::= KeyHeader LineEnding ValueBlock ;
// 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;
typedef struct IOStream IOStream;
typedef struct Arena Arena;
typedef struct ArchivePropertyNode ArchivePropertyNode;
typedef struct ParsedArchive ParsedArchive;
typedef struct Archive Archive;
struct ArchivePropertyNode
{
String key;
String value;
uint32 key_crc;
bool consumed;
bool8 consumed;
};
struct ParsedArchive
{
ArchivePropertyNode* nodes = nullptr;
uint32 property_count = 0;
ArchivePropertyNode* nodes;
uint32 property_count;
};
struct Archive
{
Arena* arena;
bool loading;
ParsedArchive base = {};
IOStream* stream = nullptr;
bool8 loading;
ParsedArchive base;
IOStream* stream;
// to remove
void* base_ptr = nullptr;
index_t offset = 0;
void* base_ptr;
index_t offset;
};
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 ArchivePropertyNode* find_property(NonNullPtr<ParsedArchive> archive, uint32 property_crc);
JULIET_API void write_property_header(Archive& archive, String property_name);
JULIET_API ParsedArchive tokenize_archive(Arena* arena, ByteBuffer file_buffer);
JULIET_API ArchivePropertyNode* find_property(ParsedArchive* archive, uint32 property_crc);
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 void write(NonNullPtr<IOStream> stream, String value);
JULIET_API bool read(const char* buffer, float& value, const char** end = nullptr);
JULIET_API void write(NonNullPtr<IOStream> stream, float value);
JULIET_API bool read(const char* buffer, int8& value);
JULIET_API void write(NonNullPtr<IOStream> stream, int8 value);
JULIET_API bool read(const char* buffer, int16& value);
JULIET_API void write(NonNullPtr<IOStream> stream, int16 value);
JULIET_API bool read(const char* buffer, int32& value);
JULIET_API void write(NonNullPtr<IOStream> stream, int32 value);
JULIET_API bool read(const char* buffer, int64& value);
JULIET_API void write(NonNullPtr<IOStream> stream, int64 value);
JULIET_API bool read(const char* buffer, uint8& value);
JULIET_API void write(NonNullPtr<IOStream> stream, uint8 value);
JULIET_API bool read(const char* buffer, uint16& value);
JULIET_API void write(NonNullPtr<IOStream> stream, uint16 value);
JULIET_API bool read(const char* buffer, uint32& value);
JULIET_API void write(NonNullPtr<IOStream> stream, uint32 value);
JULIET_API bool read(const char* buffer, uint64& value);
JULIET_API void write(NonNullPtr<IOStream> stream, uint64 value);
JULIET_API bool read(const char* buffer, bool& value);
JULIET_API void write(NonNullPtr<IOStream> stream, bool value);
JULIET_API bool read(const char* buffer, Vector4& value);
JULIET_API void write(NonNullPtr<IOStream> stream, Vector4 value);
JULIET_API bool8 read_prop_str(Archive* ar, String value_raw, String* value);
JULIET_API void write_str(IOStream* stream, String value);
JULIET_API bool8 read_f32(const char* buffer, float* value, const char** end);
JULIET_API void write_f32(IOStream* stream, float value);
JULIET_API bool8 read_i8(const char* buffer, int8* value);
JULIET_API void write_i8(IOStream* stream, int8 value);
JULIET_API bool8 read_i16(const char* buffer, int16* value);
JULIET_API void write_i16(IOStream* stream, int16 value);
JULIET_API bool8 read_i32(const char* buffer, int32* value);
JULIET_API void write_i32(IOStream* stream, int32 value);
JULIET_API bool8 read_i64(const char* buffer, int64* value);
JULIET_API void write_i64(IOStream* stream, int64 value);
JULIET_API bool8 read_u8(const char* buffer, uint8* value);
JULIET_API void write_u8(IOStream* stream, uint8 value);
JULIET_API bool8 read_u16(const char* buffer, uint16* value);
JULIET_API void write_u16(IOStream* stream, uint16 value);
JULIET_API bool8 read_u32(const char* buffer, uint32* value);
JULIET_API void write_u32(IOStream* stream, uint32 value);
JULIET_API bool8 read_u64(const char* buffer, uint64* value);
JULIET_API void write_u64(IOStream* stream, uint64 value);
JULIET_API bool8 read_b8(const char* buffer, bool8* value);
JULIET_API void write_b8(IOStream* stream, bool8 value);
JULIET_API bool8 read_vec4(const char* buffer, Vector4* value);
JULIET_API void write_vec4(IOStream* stream, Vector4 value);
// For primitives not needing archive nor allocation
template <typename Type>
bool read_prop(Archive& /*ar*/, String value_raw, Type& value)
{
char buffer[64];
size_t cpy_size = Min(value_raw.Size, sizeof(buffer) - 1);
MemCopy(buffer, value_raw.Str, cpy_size);
buffer[cpy_size] = '\0';
JULIET_API bool8 serialize_str(Archive* ar, String property_name, String* value);
JULIET_API bool8 serialize_f32(Archive* ar, String property_name, float* 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);
JULIET_API bool8 serialize_i32(Archive* ar, String property_name, int32* value);
JULIET_API bool8 serialize_i64(Archive* ar, String property_name, int64* value);
JULIET_API bool8 serialize_u8(Archive* ar, String property_name, uint8* value);
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(ar, name, var) serialize((ar), ConstString(#name), #name##_crc32, (var))
#define SERIALIZE_SIMPLE(ar, var) SERIALIZE(ar, var, var)
template <typename Type>
bool serialize(Archive& ar, String property_name, uint32 property_crc, Type& value)
{
Assert(IsValid(property_name));
bool result = false;
if (ar.loading)
{
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;
}
#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_I16(ar, name, var_ptr) serialize_i16((ar), ConstString(#name), (var_ptr))
#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))
#define SERIALIZE_U8(ar, name, var_ptr) serialize_u8((ar), ConstString(#name), (var_ptr))
#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))
#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))
#define SERIALIZE_BOOL(ar, name, var_ptr) serialize_b8((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_VEC4(ar, name, var_ptr) serialize_vec4((ar), ConstString(#name), (var_ptr))
#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
+189 -168
View File
@@ -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/Utils.h>
template <typename Type, size_t ReserveSize = 16>
typedef struct VectorArena 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;
};
size_t Capacity;
size_t ElemSize;
size_t ElemAlign;
size_t ReserveSize;
JULIET_DEBUG_ONLY(const char* Name;)
};
JULIET_DEBUG_ONLY(Name = name ? name : Name;)
#define kDefaultVectorReserveSize ((size_t)16)
#define kVectorArenaDefaultReserveSize ((size_t)16)
DataFirst = DataLast = Data = nullptr;
Count = 0;
Capacity = 0;
Arena = arena;
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.");
Reserve(ReserveSize);
}
void Destroy()
if (vec->Data == NULL)
{
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;
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;
}
void Resize(size_t newCount)
static inline const void* vector_arena_end_const(const VectorArena* vec)
{
Assert(vec != NULL);
const void* result = NULL;
if (vec->DataFirst != NULL)
{
Assert(Arena);
if (newCount == Count)
{
return;
result = (const Byte*)vec->DataFirst + (vec->Count * vec->ElemSize);
}
return result;
}
if (Data == nullptr)
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)
{
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;
vec->DataFirst = vec->Data;
vec->DataLast = (Byte*)vec->Data + ((vec->Count - 1) * vec->ElemSize);
}
else
{
DataFirst = DataLast = nullptr;
}
vec->DataFirst = NULL;
vec->DataLast = NULL;
}
}
void PushBack(const Type* buffer, size_t amount)
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)
{
Assert(Arena);
Assert(buffer || amount == 0);
vec->DataFirst = vec->Data;
}
if (amount == 0)
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)
{
return;
vec->DataFirst = vec->Data;
}
if (Data == nullptr)
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)
{
size_t initialCapacity = amount > ReserveSize ? amount : ReserveSize;
Reserve(initialCapacity);
Byte* dst = (Byte*)vec->DataFirst + (index * vec->ElemSize);
Byte* src = (Byte*)vec->DataFirst + (last_idx * vec->ElemSize);
MemCopy(dst, src, vec->ElemSize);
}
Assert(Count + amount <= Capacity && "VectorArena capacity exceeded!");
Type* dst = Data + Count;
MemCopy(dst, buffer, amount * sizeof(Type));
if (Count == 0)
vec->Count -= 1;
if (vec->Count == 0)
{
DataFirst = dst;
vec->DataFirst = NULL;
vec->DataLast = NULL;
}
DataLast = dst + amount - 1;
Count += amount;
}
void PushBack(const Type& value)
else
{
Assert(Arena);
if (Data == nullptr)
{
Reserve(ReserveSize);
vec->DataLast = (Byte*)vec->DataFirst + ((vec->Count - 1) * vec->ElemSize);
}
}
Assert(Count + 1 <= Capacity && "VectorArena capacity exceeded!");
static inline void vector_arena_clear(VectorArena* vec)
{
Assert(vec != NULL);
vec->DataFirst = NULL;
vec->DataLast = NULL;
vec->Count = 0;
}
Type* entry = Data + Count;
*entry = value;
static inline bool8 vector_arena_is_empty(const VectorArena* vec)
{
Assert(vec != NULL);
return vec->Count == 0;
}
if (Count == 0)
{
DataFirst = entry;
}
DataLast = entry;
++Count;
}
static inline size_t vector_arena_size(const VectorArena* vec)
{
Assert(vec != NULL);
return vec->Count;
}
void PushBack(Type&& value)
{
Assert(Arena);
#define VectorArenaCreate(vec, Type, arena, ...) \
vector_arena_create((vec), (arena), sizeof(Type), AlignOf(Type), __VA_ARGS__)
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.");
static_assert(std::is_trivially_copyable_v<VectorArena<int>>,
"VectorArena must be trivially copyable (no custom destructors/assignment).");
#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)
+10 -10
View File
@@ -1,16 +1,16 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
struct Window;
typedef struct Window Window;
using WindowID = uint8;
extern JULIET_API Window* CreatePlatformWindow(const char* title, uint16 width, uint16 height, int flags = 0 /* unused */);
extern JULIET_API void DestroyPlatformWindow(NonNullPtr<Window> window);
typedef uint8 WindowID;
extern JULIET_API void ShowWindow(NonNullPtr<Window> window);
extern JULIET_API void HideWindow(NonNullPtr<Window> window);
extern JULIET_API Window* CreatePlatformWindow(const char* title, uint16 width, uint16 height, int flags);
extern JULIET_API void DestroyPlatformWindow(Window* window);
extern JULIET_API WindowID GetWindowID(NonNullPtr<Window> window);
extern JULIET_API void SetWindowTitle(NonNullPtr<Window> window, String title);
extern JULIET_API void ShowPlatformWindow(Window* window);
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 FunctionPtr LoadFunction(NonNullPtr<DynamicLibrary> lib, const char* functionName);
extern JULIET_API void UnloadDynamicLibrary(NonNullPtr<DynamicLibrary> lib);
extern JULIET_API FunctionPtr LoadFunction(DynamicLibrary* lib, const char* functionName);
extern JULIET_API void UnloadDynamicLibrary(DynamicLibrary* lib);
+37 -50
View File
@@ -1,53 +1,57 @@
#pragma once
#pragma once
#include <Core/Common/CoreUtils.h>
#include <Core/HAL/Display/Display.h>
#include <Core/HAL/Keyboard/Keyboard.h>
#include <Core/HAL/Keyboard/KeyCode.h>
#include <Core/HAL/Mouse/Mouse.h>
#include <Juliet.h>
// Handles all events from systems handling the Hardware
// Very inspired by SDL3
enum class EventType : uint32
typedef uint32 EventType;
enum
{
None = 0,
First = None,
EventType_None = 0,
EventType_First = EventType_None,
// Application Events
// User querying an exit
Application_Exit = 100,
// OS terminating the application
Application_OS_Terminate,
Application_Begin = Application_Exit,
Application_End = Application_OS_Terminate,
EventType_Application_Exit = 100,
EventType_Application_OS_Terminate = 101,
EventType_Application_Begin = EventType_Application_Exit,
EventType_Application_End = EventType_Application_OS_Terminate,
// Window Events
Window_Close_Request = 200,
Window_Begin = Window_Close_Request,
Window_End = Window_Close_Request,
EventType_Window_Close_Request = 200,
EventType_Window_Begin = EventType_Window_Close_Request,
EventType_Window_End = EventType_Window_Close_Request,
// Keyboard Event
Key_Down = 300,
Key_Up,
Keyboard_Begin = Key_Down,
Keyboard_End = Key_Up,
EventType_Key_Down = 300,
EventType_Key_Up = 301,
EventType_Keyboard_Begin = EventType_Key_Down,
EventType_Keyboard_End = EventType_Key_Up,
// Mouse Event
Mouse_Move = 400,
Mouse_ButtonPressed,
Mouse_ButtonReleased,
EventType_Mouse_Move = 400,
EventType_Mouse_ButtonPressed = 401,
EventType_Mouse_ButtonReleased = 402,
Mouse_Begin = Mouse_Move,
Mouse_End = Mouse_ButtonReleased,
EventType_Mouse_Begin = EventType_Mouse_Move,
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
{
WindowID AssociatedWindowID;
uint32 DataPadding[2]; // TODO : define how much data param we need
uint32 DataPadding[2];
};
struct KeyboardEvent
@@ -59,9 +63,6 @@ struct KeyboardEvent
KeyMod KeyModeState;
};
// =====================================================
// Mouse Events
// =====================================================
struct MouseMovementEvent
{
MouseID AssociatedMouseID;
@@ -80,20 +81,18 @@ struct MouseButtonEvent
float X;
float Y;
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
{
WindowEvent Window;
KeyboardEvent Keyboard;
MouseMovementEvent MouseMovement;
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
static_assert(sizeof(AllSystemEventUnion) == sizeof(((AllSystemEventUnion*)nullptr)->Padding));
StaticAssert(sizeof(AllSystemEventUnion) == 128, SystemEventUnionSizeCheck);
struct SystemEvent
{
@@ -102,19 +101,7 @@ struct SystemEvent
AllSystemEventUnion Data;
};
// Poll for any event, return false if no event is available.
// Equivalent to WaitEvent(event, 0);
// Will not block
extern JULIET_API bool GetEvent(SystemEvent& event);
// 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 JULIET_API bool8 GetEvent(SystemEvent* event);
extern JULIET_API bool8 WaitEvent(SystemEvent* event, int32 timeoutInNS);
extern JULIET_API bool8 AddEvent(SystemEvent* event);
extern void Events_NewFrame(float deltaTime);
+31 -10
View File
@@ -1,23 +1,44 @@
#pragma once
#pragma once
#include <Core/Common/String.h>
enum class AssetType
typedef uint32 AssetType;
enum
{
JAsset,
Shader,
Config,
AssetType_JAsset = 0,
AssetType_Shader = 1,
AssetType_Config = 2,
};
typedef struct Path Path;
struct Path
{
String Directories;
String FullPath;
};
JULIET_API bool8 IsValidPath(Path path);
// Returns the path to the application directory
JULIET_API String GetBasePath();
JULIET_API Path GetBasePath(void);
// Path to the /Assets/ folder
JULIET_API String GetAssetBasePath();
JULIET_API Path GetAssetBasePath(void);
// Builds a full path to an asset file given its filename (e.g. "Triangle.vert.dxil").
JULIET_API String 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 String CleanPath(NonNullPtr<Arena> arena, String path);
JULIET_API Path fs_create_clean_path(Arena* arena, String path);
JULIET_API bool8 fs_create_directory(String path, bool8 recursive);
JULIET_API bool8 fs_path_exists(String path);
JULIET_API bool8 fs_move_file(Path old_path, Path new_path);
JULIET_API bool8 fs_delete_file(String path);
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);
+39 -36
View File
@@ -1,66 +1,69 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Juliet.h>
// Opaque type
struct IOStream;
typedef struct IOStream IOStream;
typedef struct IOStreamDataPayload IOStreamDataPayload;
struct IOStreamDataPayload
{
uint8 unused;
};
enum class IOStreamStatus : uint8
typedef uint8 IOStreamStatus;
enum
{
Ready,
Error,
EndOfFile,
NotReady,
ReadOnly,
WriteOnly
IOStreamStatus_Ready = 0,
IOStreamStatus_Error,
IOStreamStatus_EndOfFile,
IOStreamStatus_NotReady,
IOStreamStatus_ReadOnly,
IOStreamStatus_WriteOnly
};
enum class IOStreamSeekPivot : uint8
typedef uint8 IOStreamSeekPivot;
enum
{
Begin,
Current,
End,
Count
IOStreamSeekPivot_Begin = 0,
IOStreamSeekPivot_Current,
IOStreamSeekPivot_End,
IOStreamSeekPivot_Count
};
// IOStream can be opened on a file or memory, or anything else.
// Use the interface to make it transparent to the user.
typedef struct IOStreamInterface IOStreamInterface;
struct IOStreamInterface
{
uint32 Version;
int64 (*Size)(NonNullPtr<IOStreamDataPayload> data);
int64 (*Size)(IOStreamDataPayload* data);
int64 (*Seek)(NonNullPtr<IOStreamDataPayload> data, int64 offset, IOStreamSeekPivot pivot);
size_t (*Read)(NonNullPtr<IOStreamDataPayload> data, void* outBuffer, size_t size, NonNullPtr<IOStreamStatus> status);
size_t (*Write)(NonNullPtr<IOStreamDataPayload> data, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status);
bool (*Flush)(NonNullPtr<IOStreamDataPayload> data, NonNullPtr<IOStreamStatus> status);
int64 (*Seek)(IOStreamDataPayload* data, int64 offset, IOStreamSeekPivot pivot);
size_t (*Read)(IOStreamDataPayload* data, void* outBuffer, size_t size, IOStreamStatus* status);
size_t (*Write)(IOStreamDataPayload* data, ByteBuffer inBuffer, 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(NonNullPtr<Arena> arena, NonNullPtr<const IOStreamInterface> streamInterface,
NonNullPtr<IOStreamDataPayload> payload);
extern JULIET_API IOStream* IOFromInterface(Arena* arena, const IOStreamInterface* streamInterface,
IOStreamDataPayload* payload);
// Write formatted string into the stream.
extern JULIET_API size_t IOPrintf(NonNullPtr<IOStream> stream, _Printf_format_string_ const char* format, ...);
extern JULIET_API size_t IOWrite(NonNullPtr<IOStream> stream, ByteBuffer inBuffer);
JULIET_API size_t IOPrintf(IOStream* stream, const char* format, ...);
JULIET_API size_t IOWrite(IOStream* stream, ByteBuffer inBuffer);
extern JULIET_API size_t IORead(NonNullPtr<IOStream> stream, void* ptr, size_t size);
extern JULIET_API int64 IOSeek(NonNullPtr<IOStream> stream, int64 offset, IOStreamSeekPivot pivot);
JULIET_API size_t IORead(IOStream* stream, void* ptr, size_t size);
JULIET_API int64 IOSeek(IOStream* stream, int64 offset, IOStreamSeekPivot pivot);
extern JULIET_API int64 IOSize(NonNullPtr<IOStream> stream);
JULIET_API int64 IOSize(IOStream* stream);
extern JULIET_API ByteBuffer LoadFile(NonNullPtr<Arena> arena, String filename);
extern JULIET_API ByteBuffer LoadFile(NonNullPtr<Arena> arena, NonNullPtr<IOStream> stream, bool closeStreamWhenDone);
JULIET_API ByteBuffer LoadFile(Arena* arena, String filename);
JULIET_API ByteBuffer LoadFileFromStream(Arena* arena, IOStream* stream, bool8 closeStreamWhenDone);
extern JULIET_API bool IOClose(NonNullPtr<IOStream> stream);
JULIET_API size_t IO_atomic_file_write(Path filepath, ByteBuffer file_content);
JULIET_API bool8 IOClose(IOStream* stream);
+176 -181
View File
@@ -1,188 +1,183 @@
#pragma once
#pragma once
// Represents a Virtual Key corresponding to the Physical key, but localized using the keyboard layout
// ScanCode reprensent US ASCII Keyboard
// WASD Scan codes are ZQSD in KeyCode for French keyboard
// We use the ASCII value of the generated character as value, when possible.
// 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
#include <Core/Common/CoreTypes.h>
typedef uint32 KeyCode;
enum
{
Unknown = 0x0, // 0
Unsupported = 0x0, // 0
Return = 0X0Du, // '\r'
Escape = 0X1Bu, // '\X1B'
Backspace = 0X08u, // '\b'
Tab = 0X09u, // '\t'
Space = 0X20u, // ' '
ExclamationPoint = 0X21u, // '!'
DoubleApostrophe = 0X22u, // '"'
Hash = 0X23u, // '#'
Dollar = 0X24u, // '$'
Percent = 0X25u, // '%'
Ampersand = 0X26u, // '&'
Apostrophe = 0X27u, // '\''
LeftParenthesis = 0X28u, // '('
RightParenthesis = 0X29u, // ')'
Asterisk = 0X2Au, // '*'
Plus = 0X2Bu, // '+'
Comma = 0X2Cu, // ','
Minus = 0X2Du, // '-'
Period = 0X2Eu, // '.'
Slash = 0X2Fu, // '/'
Num0 = 0X30u, // '0'
Num1 = 0X31u, // '1'
Num2 = 0X32u, // '2'
Num3 = 0X33u, // '3'
Num4 = 0X34u, // '4'
Num5 = 0X35u, // '5'
Num6 = 0X36u, // '6'
Num7 = 0X37u, // '7'
Num8 = 0X38u, // '8'
Num9 = 0X39u, // '9'
Colon = 0X3Au, // ':'
Semicolon = 0X3Bu, // ';'
LessThan = 0X3Cu, // '<'
Equals = 0X3Du, // '='
GreaterThan = 0X3Eu, // '>'
QuestionMark = 0X3Fu, // '?'
CommercialAt = 0x40u, // '@'
LeftBracket = 0X5Bu, // '['
Backslash = 0X5Cu, // '\\'
RightBracket = 0X5DU, // ']'
Caret = 0X5Eu, // '^'
Underscore = 0X5Fu, // '_'
GraveAccent = 0X60u, // '`'
A = 0x61u, // 'a'
B = 0x62u, // 'b'
C = 0x63u, // 'c'
D = 0x64u, // 'd'
E = 0x65u, // 'e'
F = 0x66u, // 'f'
G = 0x67u, // 'g'
H = 0x68u, // 'h'
I = 0x69u, // 'i'
J = 0x6Au, // 'j'
K = 0x6Bu, // 'k'
L = 0x6CU, // 'l'
M = 0x6DU, // 'm'
N = 0x6Eu, // 'n'
O = 0x6Fu, // 'o'
P = 0x70u, // 'p'
Q = 0x71u, // 'q'
R = 0x72u, // 'r'
S = 0x73u, // 's'
T = 0x74u, // 't'
U = 0x75u, // 'y'
V = 0x76u, // 'v'
W = 0x77u, // 'w'
X = 0x78u, // 'x'
Y = 0x79u, // 'y'
Z = 0x7Au, // 'z'
LeftBrace = 0x7BU, // '{'
Pipe = 0x7CU, // '|'
RightBrace = 0x7DU, // '}'
Tilde = 0x7Eu, // '~'
Delete = 0x7Fu, // '\x7F'
PlusMinus = 0xb1u, // '\xB1'
KeyCode_Unknown = 0x0u,
KeyCode_Unsupported = 0x0u,
KeyCode_Return = 0x0Du,
KeyCode_Escape = 0x1Bu,
KeyCode_Backspace = 0x08u,
KeyCode_Tab = 0x09u,
KeyCode_Space = 0x20u,
KeyCode_ExclamationPoint = 0x21u,
KeyCode_DoubleApostrophe = 0x22u,
KeyCode_Hash = 0x23u,
KeyCode_Dollar = 0x24u,
KeyCode_Percent = 0x25u,
KeyCode_Ampersand = 0x26u,
KeyCode_Apostrophe = 0x27u,
KeyCode_LeftParenthesis = 0x28u,
KeyCode_RightParenthesis = 0x29u,
KeyCode_Asterisk = 0x2Au,
KeyCode_Plus = 0x2Bu,
KeyCode_Comma = 0x2Cu,
KeyCode_Minus = 0x2Du,
KeyCode_Period = 0x2Eu,
KeyCode_Slash = 0x2Fu,
KeyCode_Num0 = 0x30u,
KeyCode_Num1 = 0x31u,
KeyCode_Num2 = 0x32u,
KeyCode_Num3 = 0x33u,
KeyCode_Num4 = 0x34u,
KeyCode_Num5 = 0x35u,
KeyCode_Num6 = 0x36u,
KeyCode_Num7 = 0x37u,
KeyCode_Num8 = 0x38u,
KeyCode_Num9 = 0x39u,
KeyCode_Colon = 0x3Au,
KeyCode_Semicolon = 0x3Bu,
KeyCode_LessThan = 0x3Cu,
KeyCode_Equals = 0x3Du,
KeyCode_GreaterThan = 0x3Eu,
KeyCode_QuestionMark = 0x3Fu,
KeyCode_CommercialAt = 0x40u,
KeyCode_LeftBracket = 0x5Bu,
KeyCode_Backslash = 0x5Cu,
KeyCode_RightBracket = 0x5Du,
KeyCode_Caret = 0x5Eu,
KeyCode_Underscore = 0x5Fu,
KeyCode_GraveAccent = 0x60u,
KeyCode_A = 0x61u,
KeyCode_B = 0x62u,
KeyCode_C = 0x63u,
KeyCode_D = 0x64u,
KeyCode_E = 0x65u,
KeyCode_F = 0x66u,
KeyCode_G = 0x67u,
KeyCode_H = 0x68u,
KeyCode_I = 0x69u,
KeyCode_J = 0x6Au,
KeyCode_K = 0x6Bu,
KeyCode_L = 0x6Cu,
KeyCode_M = 0x6Du,
KeyCode_N = 0x6Eu,
KeyCode_O = 0x6Fu,
KeyCode_P = 0x70u,
KeyCode_Q = 0x71u,
KeyCode_R = 0x72u,
KeyCode_S = 0x73u,
KeyCode_T = 0x74u,
KeyCode_U = 0x75u,
KeyCode_V = 0x76u,
KeyCode_W = 0x77u,
KeyCode_X = 0x78u,
KeyCode_Y = 0x79u,
KeyCode_Z = 0x7Au,
KeyCode_LeftBrace = 0x7Bu,
KeyCode_Pipe = 0x7Cu,
KeyCode_RightBrace = 0x7Du,
KeyCode_Tilde = 0x7Eu,
KeyCode_Delete = 0x7Fu,
KeyCode_PlusMinus = 0xb1u,
// Keys not producing a character
// Based on SDL Algo: ScanCode | 0x40000000
CapsLock = 0x40000039u,
F1 = 0x4000003Au,
F2 = 0x4000003Bu,
F3 = 0x4000003CU,
F4 = 0x4000003DU,
F5 = 0x4000003Eu,
F6 = 0x4000003Fu,
F7 = 0x40000040u,
F8 = 0x40000041u,
F9 = 0x40000042u,
F10 = 0x40000043u,
F11 = 0x40000044u,
F12 = 0x40000045u,
PrintScreen = 0x40000046u,
ScrollLock = 0x40000047u,
Pause = 0x40000048u,
Insert = 0x40000049u,
Home = 0x4000004Au,
PageUp = 0x4000004Bu,
End = 0x4000004DU,
PageDown = 0x4000004Eu,
RightArrow = 0x4000004Fu,
LeftArrow = 0x40000050u,
DownArrow = 0x40000051u,
UpArrow = 0x40000052u,
NumlockClear = 0x40000053u,
KeyPad_Divide = 0x40000054u,
KeyPad_Multiply = 0x40000055u,
KeyPad_Minus = 0x40000056u,
KeyPad_Plus = 0x40000057u,
KeyPad_Enter = 0x40000058u,
KeyPad_Num1 = 0x40000059u,
KeyPad_Num2 = 0x4000005Au,
KeyPad_Num3 = 0x4000005Bu,
KeyPad_Num4 = 0x4000005Cu,
KeyPad_Num5 = 0x4000005Du,
KeyPad_Num6 = 0x4000005Eu,
KeyPad_Num7 = 0x4000005Fu,
KeyPad_Num8 = 0x40000060u,
KeyPad_Num9 = 0x40000061u,
KeyPad_Num0 = 0x40000062u,
KeyPad_Period = 0x40000063u,
Power = 0x40000066u,
KeyPad_Equals = 0x40000067u,
F13 = 0x40000068u,
F14 = 0x40000069u,
F15 = 0x4000006Au,
F16 = 0x4000006Bu,
F17 = 0x4000006Cu,
F18 = 0x4000006Du,
F19 = 0x4000006Eu,
F20 = 0x4000006Fu,
F21 = 0x40000070u,
F22 = 0x40000071u,
F23 = 0x40000072u,
F24 = 0x40000073u,
Mute = 0x4000007Fu,
VolumeUp = 0x40000080u,
VolumeDown = 0x40000081u,
KeyPad_Comma = 0x40000085u,
LeftControl = 0x400000E0u,
LeftShift = 0x400000E1u,
LeftAlt = 0x400000E2u,
LeftOSCommand = 0x400000E3u,
RightControl = 0x400000E4u,
RightShift = 0x400000E5u,
RightAlt = 0x400000E6u,
RightOSCommand = 0x400000E7u,
Sleep = 0x40000102u,
WakeUp = 0x40000103u,
Media_NextTrack = 0x4000010Bu,
Media_PreviousTrack = 0x4000010Cu,
Media_Stop = 0x4000010Du,
Media_Eject = 0x4000010Eu,
Media_PlayPause = 0x4000010Fu,
Media_Select = 0x40000110u,
KeyCode_CapsLock = 0x40000039u,
KeyCode_F1 = 0x4000003Au,
KeyCode_F2 = 0x4000003Bu,
KeyCode_F3 = 0x4000003Cu,
KeyCode_F4 = 0x4000003Du,
KeyCode_F5 = 0x4000003Eu,
KeyCode_F6 = 0x4000003Fu,
KeyCode_F7 = 0x40000040u,
KeyCode_F8 = 0x40000041u,
KeyCode_F9 = 0x40000042u,
KeyCode_F10 = 0x40000043u,
KeyCode_F11 = 0x40000044u,
KeyCode_F12 = 0x40000045u,
KeyCode_PrintScreen = 0x40000046u,
KeyCode_ScrollLock = 0x40000047u,
KeyCode_Pause = 0x40000048u,
KeyCode_Insert = 0x40000049u,
KeyCode_Home = 0x4000004Au,
KeyCode_PageUp = 0x4000004Bu,
KeyCode_End = 0x4000004Du,
KeyCode_PageDown = 0x4000004Eu,
KeyCode_RightArrow = 0x4000004Fu,
KeyCode_LeftArrow = 0x40000050u,
KeyCode_DownArrow = 0x40000051u,
KeyCode_UpArrow = 0x40000052u,
KeyCode_NumlockClear = 0x40000053u,
KeyCode_KeyPad_Divide = 0x40000054u,
KeyCode_KeyPad_Multiply = 0x40000055u,
KeyCode_KeyPad_Minus = 0x40000056u,
KeyCode_KeyPad_Plus = 0x40000057u,
KeyCode_KeyPad_Enter = 0x40000058u,
KeyCode_KeyPad_Num1 = 0x40000059u,
KeyCode_KeyPad_Num2 = 0x4000005Au,
KeyCode_KeyPad_Num3 = 0x4000005Bu,
KeyCode_KeyPad_Num4 = 0x4000005Cu,
KeyCode_KeyPad_Num5 = 0x4000005Du,
KeyCode_KeyPad_Num6 = 0x4000005Eu,
KeyCode_KeyPad_Num7 = 0x4000005Fu,
KeyCode_KeyPad_Num8 = 0x40000060u,
KeyCode_KeyPad_Num9 = 0x40000061u,
KeyCode_KeyPad_Num0 = 0x40000062u,
KeyCode_KeyPad_Period = 0x40000063u,
KeyCode_Power = 0x40000066u,
KeyCode_KeyPad_Equals = 0x40000067u,
KeyCode_F13 = 0x40000068u,
KeyCode_F14 = 0x40000069u,
KeyCode_F15 = 0x4000006Au,
KeyCode_F16 = 0x4000006Bu,
KeyCode_F17 = 0x4000006Cu,
KeyCode_F18 = 0x4000006Du,
KeyCode_F19 = 0x4000006Eu,
KeyCode_F20 = 0x4000006Fu,
KeyCode_F21 = 0x40000070u,
KeyCode_F22 = 0x40000071u,
KeyCode_F23 = 0x40000072u,
KeyCode_F24 = 0x40000073u,
KeyCode_Mute = 0x4000007Fu,
KeyCode_VolumeUp = 0x40000080u,
KeyCode_VolumeDown = 0x40000081u,
KeyCode_KeyPad_Comma = 0x40000085u,
KeyCode_LeftControl = 0x400000E0u,
KeyCode_LeftShift = 0x400000E1u,
KeyCode_LeftAlt = 0x400000E2u,
KeyCode_LeftOSCommand = 0x400000E3u,
KeyCode_RightControl = 0x400000E4u,
KeyCode_RightShift = 0x400000E5u,
KeyCode_RightAlt = 0x400000E6u,
KeyCode_RightOSCommand = 0x400000E7u,
KeyCode_Sleep = 0x40000102u,
KeyCode_WakeUp = 0x40000103u,
KeyCode_Media_NextTrack = 0x4000010Bu,
KeyCode_Media_PreviousTrack = 0x4000010Cu,
KeyCode_Media_Stop = 0x4000010Du,
KeyCode_Media_Eject = 0x4000010Eu,
KeyCode_Media_PlayPause = 0x4000010Fu,
KeyCode_Media_Select = 0x40000110u,
};
enum class KeyMod : uint16
typedef uint16 KeyMod;
enum
{
None = 0b0,
LeftShift = 0b0000'0000'0001u,
RightShift = 0b0000'0000'0010u,
LeftControl = 0b0000'0000'0100u,
RightControl = 0b0000'0000'1000u,
LeftAlt = 0b0000'0001'000u,
RightAlt = 0b0000'0010'0000u,
LeftOSCommand = 0b0000'0100'0000u,
RightOSCommand = 0b0000'1000'0000u,
NumLock = 0b0001'0000'0000u,
CapsLock = 0b0010'0000'0000u,
ScrollLock = 0b0100'0000'0000u,
Control = LeftControl | RightControl,
Shift = LeftShift | RightShift,
Alt = LeftAlt | RightAlt,
OSCommand = LeftOSCommand | RightOSCommand,
KeyMod_None = 0x0000u,
KeyMod_LeftShift = 0x0001u,
KeyMod_RightShift = 0x0002u,
KeyMod_LeftControl = 0x0004u,
KeyMod_RightControl = 0x0008u,
KeyMod_LeftAlt = 0x0010u,
KeyMod_RightAlt = 0x0020u,
KeyMod_LeftOSCommand = 0x0040u,
KeyMod_RightOSCommand = 0x0080u,
KeyMod_NumLock = 0x0100u,
KeyMod_CapsLock = 0x0200u,
KeyMod_ScrollLock = 0x0400u,
KeyMod_Control = KeyMod_LeftControl | KeyMod_RightControl,
KeyMod_Shift = KeyMod_LeftShift | KeyMod_RightShift,
KeyMod_Alt = KeyMod_LeftAlt | KeyMod_RightAlt,
KeyMod_OSCommand = KeyMod_LeftOSCommand | KeyMod_RightOSCommand,
};
+11 -8
View File
@@ -1,23 +1,26 @@
#pragma once
#pragma once
#include <Core/HAL/Keyboard/KeyCode.h>
#include <Core/HAL/Keyboard/ScanCode.h>
#include <Juliet.h>
using KeyboardID = uint8;
typedef uint8 KeyboardID;
enum class KeyPosition : bool
typedef bool8 KeyPosition;
enum
{
Up = false,
Down = true
KeyPosition_Up = false,
KeyPosition_Down = true
};
typedef struct KeyState KeyState;
struct KeyState
{
KeyPosition Position;
float Time;
};
typedef struct Key Key;
struct Key
{
ScanCode ScanCode;
@@ -25,8 +28,8 @@ struct Key
uint16 Raw;
};
extern JULIET_API bool IsKeyDown(ScanCode scanCode);
extern JULIET_API bool IsKeyPressed(ScanCode scanCode);
extern JULIET_API bool8 IsKeyDown(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);
+158 -161
View File
@@ -1,183 +1,180 @@
#pragma once
#pragma once
// Follow the HID Usage page for USB
// https://usb.org/sites/default/files/hut1_5.pdf
// 0 to 256 Is dedicated to Keyboard Usage Page (0x07)
// 257 to 286 Is dedicated to Consumer Usage Page (0xC)
// 287 to 511 Is not implemented. Could be used for Mobile or Consoles
// ScanCode reprensent Physical Keys and Buttons
enum class ScanCode : uint16
#include <Core/Common/CoreTypes.h>
typedef uint16 ScanCode;
enum
{
Unknown = 0,
Unsupported = 0,
ScanCode_Unknown = 0,
ScanCode_Unsupported = 0,
A = 4,
B = 5,
C = 6,
D = 7,
E = 8,
F = 9,
G = 10,
H = 11,
I = 12,
J = 13,
K = 14,
L = 15,
M = 16,
N = 17,
O = 18,
P = 19,
Q = 20,
R = 21,
S = 22,
T = 23,
U = 24,
V = 25,
W = 26,
X = 27,
Y = 28,
Z = 29,
ScanCode_A = 4,
ScanCode_B = 5,
ScanCode_C = 6,
ScanCode_D = 7,
ScanCode_E = 8,
ScanCode_F = 9,
ScanCode_G = 10,
ScanCode_H = 11,
ScanCode_I = 12,
ScanCode_J = 13,
ScanCode_K = 14,
ScanCode_L = 15,
ScanCode_M = 16,
ScanCode_N = 17,
ScanCode_O = 18,
ScanCode_P = 19,
ScanCode_Q = 20,
ScanCode_R = 21,
ScanCode_S = 22,
ScanCode_T = 23,
ScanCode_U = 24,
ScanCode_V = 25,
ScanCode_W = 26,
ScanCode_X = 27,
ScanCode_Y = 28,
ScanCode_Z = 29,
Num1 = 30,
Num2 = 31,
Num3 = 32,
Num4 = 33,
Num5 = 34,
Num6 = 35,
Num7 = 36,
Num8 = 37,
Num9 = 38,
Num0 = 39,
ScanCode_Num1 = 30,
ScanCode_Num2 = 31,
ScanCode_Num3 = 32,
ScanCode_Num4 = 33,
ScanCode_Num5 = 34,
ScanCode_Num6 = 35,
ScanCode_Num7 = 36,
ScanCode_Num8 = 37,
ScanCode_Num9 = 38,
ScanCode_Num0 = 39,
Return = 40,
Escape = 41,
Backspace = 42,
Tab = 43,
Space = 44,
ScanCode_Return = 40,
ScanCode_Escape = 41,
ScanCode_Backspace = 42,
ScanCode_Tab = 43,
ScanCode_Space = 44,
Minus = 45,
Equals = 46,
LeftBracket = 47,
RightBracket = 48,
Backslash = 49,
NonUSHash = 50, // Same as 49 but for ISO keyboards
Semicolon = 51,
Apostrophe = 52,
GraveAccent = 53,
Comma = 54,
Period = 55,
Slash = 56,
CapsLock = 57,
ScanCode_Minus = 45,
ScanCode_Equals = 46,
ScanCode_LeftBracket = 47,
ScanCode_RightBracket = 48,
ScanCode_Backslash = 49,
ScanCode_NonUSHash = 50,
ScanCode_Semicolon = 51,
ScanCode_Apostrophe = 52,
ScanCode_GraveAccent = 53,
ScanCode_Comma = 54,
ScanCode_Period = 55,
ScanCode_Slash = 56,
ScanCode_CapsLock = 57,
F1 = 58,
F2 = 59,
F3 = 60,
F4 = 61,
F5 = 62,
F6 = 63,
F7 = 64,
F8 = 65,
F9 = 66,
F10 = 67,
F11 = 68,
F12 = 69,
ScanCode_F1 = 58,
ScanCode_F2 = 59,
ScanCode_F3 = 60,
ScanCode_F4 = 61,
ScanCode_F5 = 62,
ScanCode_F6 = 63,
ScanCode_F7 = 64,
ScanCode_F8 = 65,
ScanCode_F9 = 66,
ScanCode_F10 = 67,
ScanCode_F11 = 68,
ScanCode_F12 = 69,
PrintScreen = 70,
ScrollLock = 71,
Pause = 72,
Insert = 73,
ScanCode_PrintScreen = 70,
ScanCode_ScrollLock = 71,
ScanCode_Pause = 72,
ScanCode_Insert = 73,
Home = 74,
PageUp = 75,
Delete = 76,
End = 77,
PageDown = 78,
RightArrow = 79,
LeftArrow = 80,
DownArrow = 81,
UpArrow = 82,
ScanCode_Home = 74,
ScanCode_PageUp = 75,
ScanCode_Delete = 76,
ScanCode_End = 77,
ScanCode_PageDown = 78,
ScanCode_RightArrow = 79,
ScanCode_LeftArrow = 80,
ScanCode_DownArrow = 81,
ScanCode_UpArrow = 82,
NumlockClear = 83, // Pc = Numlock / Mac = Clear
ScanCode_NumlockClear = 83,
KeyPad_Divide = 84,
KeyPad_Multiply = 85,
KeyPad_Minus = 86,
KeyPad_Plus = 87,
KeyPad_Enter = 88,
KeyPad_Num1 = 89,
KeyPad_Num2 = 90,
KeyPad_Num3 = 91,
KeyPad_Num4 = 92,
KeyPad_Num5 = 93,
KeyPad_Num6 = 94,
KeyPad_Num7 = 95,
KeyPad_Num8 = 96,
KeyPad_Num9 = 97,
KeyPad_Num0 = 98,
KeyPad_Period = 99,
ScanCode_KeyPad_Divide = 84,
ScanCode_KeyPad_Multiply = 85,
ScanCode_KeyPad_Minus = 86,
ScanCode_KeyPad_Plus = 87,
ScanCode_KeyPad_Enter = 88,
ScanCode_KeyPad_Num1 = 89,
ScanCode_KeyPad_Num2 = 90,
ScanCode_KeyPad_Num3 = 91,
ScanCode_KeyPad_Num4 = 92,
ScanCode_KeyPad_Num5 = 93,
ScanCode_KeyPad_Num6 = 94,
ScanCode_KeyPad_Num7 = 95,
ScanCode_KeyPad_Num8 = 96,
ScanCode_KeyPad_Num9 = 97,
ScanCode_KeyPad_Num0 = 98,
ScanCode_KeyPad_Period = 99,
NonUSBackslash = 100, // ISO keyboards only
Power = 102, // Some mac have a Power key
ScanCode_NonUSBackslash = 100,
ScanCode_Power = 102,
KeyPad_Equals = 103,
F13 = 104,
F14 = 105,
F15 = 106,
F16 = 107,
F17 = 108,
F18 = 109,
F19 = 110,
F20 = 111,
F21 = 112,
F22 = 113,
F23 = 114,
F24 = 115,
ScanCode_KeyPad_Equals = 103,
ScanCode_F13 = 104,
ScanCode_F14 = 105,
ScanCode_F15 = 106,
ScanCode_F16 = 107,
ScanCode_F17 = 108,
ScanCode_F18 = 109,
ScanCode_F19 = 110,
ScanCode_F20 = 111,
ScanCode_F21 = 112,
ScanCode_F22 = 113,
ScanCode_F23 = 114,
ScanCode_F24 = 115,
Mute = 127,
VolumeUp = 128,
VolumeDown = 129,
ScanCode_Mute = 127,
ScanCode_VolumeUp = 128,
ScanCode_VolumeDown = 129,
KeyPad_Comma = 133,
ScanCode_KeyPad_Comma = 133,
International1 = 135, // Mostly used on Asian keyboards
International2 = 136,
International3 = 137, // Yen Symbol
International4 = 138,
International5 = 139,
International6 = 140,
International7 = 141,
International8 = 142,
International9 = 143,
Lang1 = 144, // Hangul (Korean)
Lang2 = 145, // Hanja (Korean)
Lang3 = 146, // Katakana (Japanese)
Lang4 = 147, // Hiragana (Japanese)
Lang5 = 148, // Zenkaku/Hankaku (Japanese)
Lang6 = 149, // Unused
Lang7 = 150, // Unused
Lang8 = 151, // Unused
Lang9 = 152, // Unused
ScanCode_International1 = 135,
ScanCode_International2 = 136,
ScanCode_International3 = 137,
ScanCode_International4 = 138,
ScanCode_International5 = 139,
ScanCode_International6 = 140,
ScanCode_International7 = 141,
ScanCode_International8 = 142,
ScanCode_International9 = 143,
ScanCode_Lang1 = 144,
ScanCode_Lang2 = 145,
ScanCode_Lang3 = 146,
ScanCode_Lang4 = 147,
ScanCode_Lang5 = 148,
ScanCode_Lang6 = 149,
ScanCode_Lang7 = 150,
ScanCode_Lang8 = 151,
ScanCode_Lang9 = 152,
LeftControl = 224,
LeftShift = 225,
LeftAlt = 226, // Alt for PC, Option for Mac
LeftOSCommand = 227, // Window key for PC, Command for Mac
RightControl = 228,
RightShift = 229,
RightAlt = 230, // Alt Gr for PC, Option for Mac
RightOSCommand = 231, // Window key for PC, Command for Mac
ScanCode_LeftControl = 224,
ScanCode_LeftShift = 225,
ScanCode_LeftAlt = 226,
ScanCode_LeftOSCommand = 227,
ScanCode_RightControl = 228,
ScanCode_RightShift = 229,
ScanCode_RightAlt = 230,
ScanCode_RightOSCommand = 231,
Sleep = 258,
WakeUp = 259,
ScanCode_Sleep = 258,
ScanCode_WakeUp = 259,
Media_NextTrack = 267,
Media_PreviousTrack = 268,
Media_Stop = 269,
Media_Eject = 270,
Media_PlayPause = 271,
Media_Select = 272,
ScanCode_Media_NextTrack = 267,
ScanCode_Media_PreviousTrack = 268,
ScanCode_Media_Stop = 269,
ScanCode_Media_Eject = 270,
ScanCode_Media_PlayPause = 271,
ScanCode_Media_Select = 272,
Reserved = 287,
ScanCode_Reserved = 287,
Count = 512
ScanCode_Count = 512
};
+18 -14
View File
@@ -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,
Left = 1 << 0,
Right = 1 << 1,
Middle = 1 << 2,
Button1 = 1 << 3,
Button2 = 1 << 4,
MouseButton_None = 0,
MouseButton_Left = 1 << 0,
MouseButton_Right = 1 << 1,
MouseButton_Middle = 1 << 2,
MouseButton_Button1 = 1 << 3,
MouseButton_Button2 = 1 << 4,
};
// TODO : Replace by Vector2f
typedef struct MousePosition MousePosition;
struct MousePosition
{
float X;
float Y;
};
JULIET_API extern bool IsMouseButtonDown(MouseButton button);
JULIET_API extern MousePosition GetMousePosition();
JULIET_API extern MousePosition GetMouseDelta();
JULIET_API extern MouseButton GetMouseButtonState();
JULIET_API extern bool8 IsMouseButtonDown(MouseButton button);
JULIET_API extern MousePosition GetMousePosition(void);
JULIET_API extern MousePosition GetMouseDelta(void);
JULIET_API extern MouseButton GetMouseButtonState(void);
+13 -42
View File
@@ -1,52 +1,23 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#include <Core/Memory/MemoryArena.h>
namespace Memory
{
Byte* OS_Reserve(size_t size);
bool OS_Commit(Byte* ptr, size_t size);
void OS_Release(Byte* ptr, size_t size);
Byte* OS_Reserve(size_t size);
bool8 OS_Commit(void* ptr, size_t size);
void OS_Release(void* ptr, size_t size);
template <typename Type>
Type* OS_Reserve(size_t size)
{
return reinterpret_cast<Type*>(OS_Reserve(size));
}
uint64 Time_Timestamp(void);
void Time_ComputeDeltaTime(void);
float Time_GetDeltaTime(void);
uint64 Time_GetFrameNumber(void);
template <typename Type>
bool OS_Commit(Type* ptr, size_t size)
{
return OS_Commit(reinterpret_cast<Byte*>(ptr), size);
}
JULIET_API bool8 Debug_IsDebuggerPresent(void);
template <typename Type>
void OS_Release(Type* ptr, size_t size)
{
OS_Release(reinterpret_cast<Byte*>(ptr), size);
}
String os_get_env_var(Arena* arena, String name);
void os_set_env_var(String name, String value);
} // namespace Memory
String os_get_username(Arena* arena);
namespace Time
{
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**);
typedef int (*EntryPointFunc)(int, wchar_t**);
JULIET_API int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
+10 -10
View File
@@ -1,9 +1,9 @@
#pragma once
#pragma once
#include <Core/Common/String.h>
// Fwd Declare
struct DynamicLibrary;
typedef struct DynamicLibrary DynamicLibrary;
typedef struct HotReloadCode HotReloadCode;
struct HotReloadCode
{
@@ -21,15 +21,15 @@ struct HotReloadCode
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);
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 UnloadCode(HotReloadCode& code);
extern JULIET_API void LoadCode(HotReloadCode* code);
extern JULIET_API void UnloadCode(HotReloadCode* code);
extern JULIET_API void ReloadCode(HotReloadCode& code);
extern JULIET_API bool ShouldReloadCode(const HotReloadCode& code);
extern JULIET_API void ReloadCode(HotReloadCode* code);
extern JULIET_API bool8 ShouldReloadCode(const HotReloadCode* code);
+14 -17
View File
@@ -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
struct ImGuiContext;
typedef struct ImGuiContext ImGuiContext;
typedef struct Window Window;
typedef struct GraphicsDevice GraphicsDevice;
struct Window;
struct GraphicsDevice;
JULIET_API void ImGuiService_Initialize(Window* window);
JULIET_API void ImGuiService_Shutdown(void);
namespace ImGuiService
{
JULIET_API void Initialize(NonNullPtr<Window> window);
JULIET_API void Shutdown();
JULIET_API void ImGuiService_NewFrame(void);
JULIET_API void ImGuiService_Render(void);
JULIET_API void NewFrame();
JULIET_API void Render();
JULIET_API bool8 ImGuiService_IsInitialized(void);
JULIET_API ImGuiContext* ImGuiService_GetContext(void);
JULIET_API bool IsInitialized();
JULIET_API ImGuiContext* GetContext();
// Run internal unit tests
JULIET_API void RunTests();
} // namespace ImGuiService
// Run internal unit tests
JULIET_API void ImGuiService_RunTests(void);
#endif // JULIET_ENABLE_IMGUI
+2 -9
View File
@@ -1,12 +1,5 @@
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/HAL/Display/Window.h>
#include <Graphics/GraphicsDevice.h>
#pragma once
#include <Juliet.h>
namespace UnitTest
{
void TestImGui();
}
void UnitTest_TestImGui(void);
+15 -10
View File
@@ -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,
Display = 1 << 0,
Audio = 1 << 1,
Count = Audio,
All = 0xFb
JulietInit_Flags_None = 0,
JulietInit_Flags_Display = 1 << 0,
JulietInit_Flags_Audio = 1 << 1,
JulietInit_Flags_Count = JulietInit_Flags_Audio,
JulietInit_Flags_All = 0xFbu
};
struct Arena;
typedef struct Arena Arena;
typedef struct GameState GameState;
typedef struct GameData GameData;
struct GameData
{
struct GameState* GameState;
GameState* GameState;
Arena* ScratchArena;
};
void JulietInit(JulietInit_Flags flags);
void JulietShutdown();
void JulietShutdown(void);
+6 -14
View File
@@ -1,21 +1,13 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Memory/MemoryArena.h>
// TODO : Juliet strings
// TODO Juliet Containers + Allocators...
// TODO: Juliet chrono, because it prevents me from doing #define global static
extern void JULIET_API InitializeLogManager(void);
extern void JULIET_API ShutdownLogManager(void);
enum class LogLevel : uint8;
enum class LogCategory : uint8;
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 LogScopeBegin(void);
extern void JULIET_API LogScopeEnd(void);
extern void JULIET_API Log(LogLevel level, LogCategory category, const char* fmt, ...);
extern void JULIET_API LogDebug(LogCategory category, const char* fmt, ...);
+17 -13
View File
@@ -1,19 +1,23 @@
#pragma once
#pragma once
enum class LogLevel : uint8
#include <Core/Common/CoreTypes.h>
typedef uint8 LogLevel;
enum
{
Debug = 0,
Message = 1,
Warning = 2,
Error = 3,
LogLevel_Debug = 0,
LogLevel_Message = 1,
LogLevel_Warning = 2,
LogLevel_Error = 3,
};
enum class LogCategory : uint8
typedef uint8 LogCategory;
enum
{
Core = 0,
Graphics = 1,
Networking = 2,
Engine = 3,
Tool = 4,
Game = 5,
LogCategory_Core = 0,
LogCategory_Graphics = 1,
LogCategory_Networking = 2,
LogCategory_Engine = 3,
LogCategory_Tool = 4,
LogCategory_Game = 5,
};
+3 -6
View File
@@ -1,8 +1,8 @@
#pragma once
#pragma once
#include <Core/HAL/OS/OS.h>
extern int JulietMain(int, wchar_t**);
extern int JulietMain(int argc, wchar_t** argv);
#if JULIET_WIN32
#ifndef WINAPI
@@ -17,12 +17,10 @@ int wmain(int argc, wchar_t** argv)
#else
int main(int argc, char** argv)
{
return Bootstrap(JulietMain, argc, argv);
return Bootstrap(JulietMain, argc, (wchar_t**)argv);
}
#endif
extern "C" {
typedef struct HINSTANCE__* HINSTANCE;
typedef char* LPSTR;
typedef wchar_t* PWSTR;
@@ -40,7 +38,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
return Bootstrap(JulietMain, __argc, __wargv);
}
}
#else
#error "Only windows main is implemented"
#endif
+11 -40
View File
@@ -1,46 +1,17 @@
#pragma once
#pragma once
#include <Juliet.h>
#include <Core/Common/CoreTypes.h>
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>
constexpr Type Min(Type lhs, Type rhs)
{
return rhs < lhs ? rhs : lhs;
}
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;
}
#define Min(lhs, rhs) (((rhs) < (lhs)) ? (rhs) : (lhs))
#define Max(lhs, rhs) (((lhs) < (rhs)) ? (rhs) : (lhs))
#define ClampTop(value, X) Min((value), (X))
#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)))
+28 -23
View File
@@ -1,16 +1,17 @@
#pragma once
#pragma once
#include <Core/Math/Vector.h>
#include <math.h>
typedef struct Matrix Matrix;
struct Matrix
{
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[1][1] = 1.0f;
result.m[2][2] = 1.0f;
@@ -18,9 +19,9 @@ struct Matrix
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 j = 0; j < 4; ++j)
@@ -34,7 +35,7 @@ struct Matrix
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();
result.m[0][3] = x;
@@ -43,7 +44,7 @@ struct Matrix
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();
result.m[0][0] = x;
@@ -52,7 +53,7 @@ struct Matrix
return result;
}
[[nodiscard]] inline Matrix MatrixRotationX(float radians)
static inline Matrix MatrixRotationX(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
@@ -64,7 +65,7 @@ struct Matrix
return result;
}
[[nodiscard]] inline Matrix MatrixRotationY(float radians)
static inline Matrix MatrixRotationY(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
@@ -76,7 +77,7 @@ struct Matrix
return result;
}
[[nodiscard]] inline Matrix MatrixRotationZ(float radians)
static inline Matrix MatrixRotationZ(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
@@ -88,26 +89,26 @@ struct Matrix
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[1][3] += v.y;
m.m[2][3] += v.z;
m->m[0][3] += v.x;
m->m[1][3] += v.y;
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
Vector3 zaxis = Normalize(target - eye); // Forward is +z
Vector3 zaxis = Normalize(Vector3Sub(target, eye)); // Forward is +z
Vector3 xaxis = Normalize(Cross(up, zaxis));
Vector3 yaxis = Cross(zaxis, xaxis);
Matrix result = {};
Matrix result = { 0 };
// Row 0
result.m[0][0] = xaxis.x;
result.m[0][1] = xaxis.y;
@@ -132,13 +133,13 @@ inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& u
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
float yScale = 1.0f / tanf(fovY * 0.5f);
float xScale = yScale / aspectRatio;
Matrix result = {};
Matrix result = { 0 };
result.m[0][0] = xScale;
result.m[1][1] = yScale;
result.m[2][2] = farZ / (farZ - nearZ);
@@ -148,9 +149,9 @@ inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float f
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 m10 = m.m[1][0], m11 = m.m[1][1], m12 = m.m[1][2], m13 = m.m[1][3];
@@ -183,9 +184,13 @@ inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float f
{
float invDet = 1.0f / det;
for (int r = 0; r < 4; ++r)
{
for (int c = 0; c < 4; ++c)
{
out.m[r][c] *= invDet;
}
}
}
return out;
}
+7 -2
View File
@@ -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 Y;
+40 -16
View File
@@ -1,38 +1,62 @@
#pragma once
#pragma once
#include <math.h>
typedef struct Vector3 Vector3;
struct Vector3
{
float x, y, z;
Vector3 operator+(const Vector3& rhs) const { return { x + rhs.x, y + rhs.y, z + rhs.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 }; }
float x;
float y;
float z;
};
typedef struct Vector4 Vector4;
struct Vector4
{
float x = 0.f;
float y = 0.f;
float z = 0.f;
float w = 0.f;
float x;
float y;
float z;
float w;
};
inline Vector3 Normalize(const Vector3& v)
static inline Vector3 Vector3Add(Vector3 lhs, Vector3 rhs)
{
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)
{
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;
}
+16 -16
View File
@@ -1,7 +1,8 @@
#pragma once
#pragma once
#include <Juliet.h>
#include <Core/Common/CoreUtils.h>
#include <stdlib.h>
// Uninitialized allocation
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* Realloc(void* memory, size_t newSize);
// Free
template <typename Type>
void Free(Type* memory)
static inline void FreeMemory(void* memory)
{
Assert(memory);
::free(memory);
}
// Free and Set the ptr to nullptr
template <typename Type>
void SafeFree(Type*& memory)
{
if (memory)
{
::free(memory);
memory = nullptr;
}
Assert(memory != NULL);
free(memory);
}
#define SafeFree(memory_ptr) \
do \
{ \
if ((memory_ptr) != NULL) \
{ \
free((void*)(memory_ptr)); \
(memory_ptr) = NULL; \
} \
} \
while (0)
+51 -73
View File
@@ -1,21 +1,19 @@
#pragma once
#pragma once
#include <Core/Common/CoreUtils.h>
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#if JULIET_DEBUG
#include <Core/Memory/MemoryArenaDebug.h>
#endif
constexpr global uint64 g_Arena_Default_Reserve_Size = Megabytes(64);
constexpr global uint64 g_Arena_Default_Commit_Size = Kilobytes(64);
constexpr global uint64 k_ArenaHeaderSize = 128;
#define g_Arena_Default_Reserve_Size Megabytes(64)
#define g_Arena_Default_Commit_Size Kilobytes(64)
#define k_ArenaHeaderSize ((uint64)128)
#if JULIET_DEBUG
struct ArenaDebugInfo;
JULIET_API String FormatDebugTagV(const char* formatStr, std::format_args args);
#endif
typedef struct Arena Arena;
typedef struct TempArena TempArena;
typedef struct ArenaParams ArenaParams;
struct Arena
{
@@ -35,14 +33,14 @@ struct Arena
Arena* FreeBlockLast;
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* GlobalPrev;)
JULIET_DEBUG_ONLY(ArenaDebugInfo* FirstDebugInfo;)
const char* Name;
};
static_assert(sizeof(Arena) <= k_ArenaHeaderSize);
StaticAssert(sizeof(Arena) <= k_ArenaHeaderSize, ArenaHeaderSizeCheck);
struct TempArena
{
@@ -52,74 +50,54 @@ struct TempArena
struct ArenaParams
{
uint64 ReserveSize = g_Arena_Default_Reserve_Size;
uint64 CommitSize = g_Arena_Default_Commit_Size;
uint64 ReserveSize;
uint64 CommitSize;
const char* Name;
// When false, will assert if a new block is reserved.
JULIET_DEBUG_ONLY(bool CanReserveMore : 1 = true;)
JULIET_DEBUG_ONLY(bool8 DoNotReserveMore;)
};
[[nodiscard]] JULIET_API Arena* ArenaAllocate(const ArenaParams& params,
const std::source_location& loc = std::source_location::current());
JULIET_API void ArenaRelease(NonNullPtr<Arena> arena);
JULIET_API Arena* ArenaAllocateImpl(ArenaParams params, const char* file, uint32 line);
#define ArenaAllocate(...) ArenaAllocateImpl(__VA_ARGS__, __FILE__, (uint32)__LINE__)
// Raw Push, can be used but templated helpers exists below
[[nodiscard]] JULIET_API void* ArenaPush(NonNullPtr<Arena> arena, size_t size, size_t align,
bool shouldBeZeroed JULIET_DEBUG_PARAM(const char* tag));
JULIET_API void ArenaPopTo(NonNullPtr<Arena> arena, size_t position);
JULIET_API void ArenaPop(NonNullPtr<Arena> arena, size_t amount);
JULIET_API void ArenaClear(NonNullPtr<Arena> arena);
[[nodiscard]] JULIET_API size_t ArenaPos(NonNullPtr<Arena> arena);
JULIET_API void ArenaRelease(Arena* arena);
// Raw Push, can be used or macros below
JULIET_API void* ArenaPush(Arena* arena, size_t size, size_t align,
bool8 shouldBeZeroed JULIET_DEBUG_PARAM(const char* tag));
JULIET_API void ArenaPopTo(Arena* arena, size_t position);
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
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
[[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)>
[[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);
TempArena ArenaTempBegin(Arena* arena);
void ArenaTempEnd(TempArena temp);
+11 -14
View File
@@ -1,12 +1,13 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#if JULIET_DEBUG
struct Arena;
struct MemoryBlock;
typedef struct Arena Arena;
typedef struct MemoryBlock MemoryBlock;
typedef struct ArenaDebugInfo ArenaDebugInfo;
typedef struct ArenaAllocation ArenaAllocation;
// Arena (Struct)
struct ArenaDebugInfo
@@ -27,20 +28,16 @@ struct ArenaAllocation
};
// Arena (Struct)
void DebugRegisterArena(NonNullPtr<Arena> arena);
void DebugUnregisterArena(NonNullPtr<Arena> arena);
void DebugArenaSetDebugName(NonNullPtr<Arena> arena, const char* name);
bool IsDebugInfoArena(const Arena* arena); // To prevent recursion
void DebugRegisterArena(Arena* arena);
void DebugUnregisterArena(Arena* arena);
void DebugArenaSetDebugName(Arena* arena, const char* name);
bool8 IsDebugInfoArena(const Arena* arena); // To prevent recursion
void DebugArenaFreeBlock(Arena* block); // To clear all debug infos in a block
void DebugArenaRemoveAllocation(Arena* block, size_t oldOffset);
void DebugArenaPopTo(Arena* block, size_t newPosition);
void DebugArenaAddDebugInfo(Arena* block, size_t size, size_t offset, const char* tag);
// MemoryArena (Pool-based)
void DebugFreeArenaAllocations(MemoryBlock* blk);
void DebugArenaAddAllocation(MemoryBlock* blk, size_t size, size_t offset, String tag);
void DebugArenaRemoveLastAllocation(MemoryBlock* blk);
JULIET_API Arena* GetDebugInfoArena();
JULIET_API Arena* GetDebugInfoArena(void);
JULIET_API Arena* GetGlobalArenaListHead(void);
#endif
+51 -47
View File
@@ -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);
auto right = static_cast<const unsigned char*>(rightValue);
const unsigned char* left = (const unsigned char*)left_value;
const unsigned char* right = (const unsigned char*)right_value;
while (size && *left == *right)
{
++left;
++right;
--size;
}
return size ? *left - *right : 0;
return size ? ((int32)(*left) - (int32)(*right)) : 0;
}
// Single linked list
void SingleLinkedListPushNext(auto*& stackTop, auto* node)
{
node->Next = stackTop;
stackTop = node;
}
// Single linked list macros
#define SingleLinkedListPushNext(stackTop, node) \
do \
{ \
(node)->Next = (stackTop); \
(stackTop) = (node); \
} \
while (0)
void SingleLinkedListPushPrevious(auto*& stackTop, auto* node)
{
node->Previous = stackTop;
stackTop = node;
}
#define SingleLinkedListPushPrevious(stackTop, node) \
do \
{ \
(node)->Previous = (stackTop); \
(stackTop) = (node); \
} \
while (0)
void SingleLinkedListPopNext(auto*& stackTop)
{
stackTop = stackTop->Next;
}
#define SingleLinkedListPopNext(stackTop) \
do \
{ \
(stackTop) = (stackTop)->Next; \
} \
while (0)
// Double linked list
template <typename QueueType, typename QueueTypeNode>
void Enqueue(QueueType& queue, QueueTypeNode* node)
{
if (queue.First == nullptr)
{
queue.First = queue.Last = node;
node->Next = nullptr;
}
else
{
queue.Last->Next = node, queue.Last = node;
node->Next = nullptr;
}
queue.Nodecount += 1;
}
template <typename QueueType>
struct QueueNode
{
QueueType* Next;
};
// Double linked list queue macro
#define Enqueue(queue, node) \
do \
{ \
if ((queue).First == NULL) \
{ \
(queue).First = (queue).Last = (node); \
(node)->Next = NULL; \
} \
else \
{ \
(queue).Last->Next = (node); \
(queue).Last = (node); \
(node)->Next = NULL; \
} \
(queue).Nodecount += 1; \
} \
while (0)
#define DECLARE_QUEUE(type) \
typedef struct type##Queue type##Queue; \
struct type##Queue \
{ \
type* First; \
@@ -66,8 +71,7 @@ struct QueueNode
size_t Size; \
};
// TODO: homemade versions
#define MemSet memset
#define MemCopy memcpy
#define MemoryZero(dst, size) MemSet(dst, 0, size)
#define MemoryZero(dst, size) MemSet((dst), 0, (size))
#define MemZeroStruct(ptr) MemoryZero((ptr), sizeof(*(ptr)))
Loaded 100 of 443 files, more files were not shown because too many files have changed in this diff. Show more