conversion to c by gemini 4 argon
This commit is contained in:
1 parent
b70e2d21d2
commit
f9356f9ba7
369 files changed
+17929
-107489
No files matched your search
@@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
constexpr index_t kPlayCamera = 0;
|
#include <Juliet.h>
|
||||||
constexpr index_t kDebugCamera = 1;
|
|
||||||
|
#define kPlayCamera ((index_t)0)
|
||||||
|
#define kDebugCamera ((index_t)1)
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
#include <Controller/DebugCameraController.h>
|
||||||
|
|
||||||
|
#include <Controller/ControllerUtils.h>
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <Core/HAL/Keyboard/Keyboard.h>
|
||||||
|
#include <Core/HAL/Mouse/Mouse.h>
|
||||||
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
#include <Graphics/Camera.h>
|
||||||
|
#include <dcimgui.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
global bool8 gIsDebugCameraActive = false;
|
||||||
|
global index_t gPreviousCameraIndex = 0;
|
||||||
|
global float gPitch = 0.0f;
|
||||||
|
global float gYaw = 0.0f;
|
||||||
|
global bool8 gFirstUpdate = true;
|
||||||
|
global bool8 gIsFpsModeActive = false;
|
||||||
|
global bool8 gWasRightMouseButtonDown = false;
|
||||||
|
|
||||||
|
void ActivateDebugController(void)
|
||||||
|
{
|
||||||
|
Assert(gIsDebugCameraActive == false);
|
||||||
|
|
||||||
|
Camera* currentCam = GetCurrentCamera();
|
||||||
|
gPreviousCameraIndex = currentCam->Index;
|
||||||
|
|
||||||
|
SetCurrentCamera(kDebugCamera);
|
||||||
|
|
||||||
|
gIsDebugCameraActive = true;
|
||||||
|
gFirstUpdate = true;
|
||||||
|
gIsFpsModeActive = false;
|
||||||
|
gWasRightMouseButtonDown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeactivateDebugController(void)
|
||||||
|
{
|
||||||
|
Assert(gIsDebugCameraActive);
|
||||||
|
|
||||||
|
gIsDebugCameraActive = false;
|
||||||
|
|
||||||
|
SetCurrentCamera(gPreviousCameraIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 IsDebugControllerActive(void)
|
||||||
|
{
|
||||||
|
return gIsDebugCameraActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateDebugController(float dt)
|
||||||
|
{
|
||||||
|
Camera* currentCam = GetCurrentCamera();
|
||||||
|
|
||||||
|
if (gFirstUpdate)
|
||||||
|
{
|
||||||
|
Vector3 origin = { 0.0f, 0.0f, 0.0f };
|
||||||
|
Vector3 dir = Vector3Sub(origin, currentCam->Position);
|
||||||
|
dir = Normalize(dir);
|
||||||
|
gPitch = asinf(dir.z);
|
||||||
|
gYaw = atan2f(dir.y, dir.x);
|
||||||
|
gFirstUpdate = false;
|
||||||
|
|
||||||
|
Vector3 forward = { cosf(gPitch) * cosf(gYaw), cosf(gPitch) * sinf(gYaw), sinf(gPitch) };
|
||||||
|
Vector3 worldUp = { 0.0f, 0.0f, 1.0f };
|
||||||
|
Vector3 right = Normalize(Cross(worldUp, forward));
|
||||||
|
currentCam->Target = Vector3Add(currentCam->Position, forward);
|
||||||
|
currentCam->Up = Cross(forward, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 isRightMouseButtonDown = IsMouseButtonDown(MouseButton_Right);
|
||||||
|
if (isRightMouseButtonDown && !gWasRightMouseButtonDown)
|
||||||
|
{
|
||||||
|
gIsFpsModeActive = !gIsFpsModeActive;
|
||||||
|
}
|
||||||
|
gWasRightMouseButtonDown = isRightMouseButtonDown;
|
||||||
|
|
||||||
|
if (gIsFpsModeActive)
|
||||||
|
{
|
||||||
|
MousePosition mouseDelta = GetMouseDelta();
|
||||||
|
|
||||||
|
float sensitivity = 0.005f;
|
||||||
|
gYaw += (float)mouseDelta.X * sensitivity;
|
||||||
|
gPitch -= (float)mouseDelta.Y * sensitivity;
|
||||||
|
|
||||||
|
gPitch = Min(gPitch, 1.5f);
|
||||||
|
gPitch = Max(gPitch, -1.5f);
|
||||||
|
|
||||||
|
if (IsKeyDown(ScanCode_Q))
|
||||||
|
{
|
||||||
|
gYaw -= 2.0f * dt;
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_E))
|
||||||
|
{
|
||||||
|
gYaw += 2.0f * dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 forward = { cosf(gPitch) * cosf(gYaw), cosf(gPitch) * sinf(gYaw), sinf(gPitch) };
|
||||||
|
Vector3 worldUp = { 0.0f, 0.0f, 1.0f };
|
||||||
|
Vector3 right = Normalize(Cross(worldUp, forward));
|
||||||
|
Vector3 defaultUp = Cross(forward, right);
|
||||||
|
|
||||||
|
const float kMovementPerFrame = 10.f; // 10m/s
|
||||||
|
|
||||||
|
float speedPerFrame = kMovementPerFrame;
|
||||||
|
if (IsKeyDown(ScanCode_LeftShift))
|
||||||
|
{
|
||||||
|
speedPerFrame *= 10.f; // 100m/s
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsKeyDown(ScanCode_W))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Add(currentCam->Position, Vector3Scale(forward, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_S))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Sub(currentCam->Position, Vector3Scale(forward, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_D))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Add(currentCam->Position, Vector3Scale(right, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_A))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Sub(currentCam->Position, Vector3Scale(right, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_Space))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Add(currentCam->Position, Vector3Scale(defaultUp, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
if (IsKeyDown(ScanCode_LeftControl))
|
||||||
|
{
|
||||||
|
currentCam->Position = Vector3Sub(currentCam->Position, Vector3Scale(defaultUp, speedPerFrame * dt));
|
||||||
|
}
|
||||||
|
|
||||||
|
currentCam->Target = Vector3Add(currentCam->Position, forward);
|
||||||
|
currentCam->Up = defaultUp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if JULIET_DEBUG
|
||||||
|
void RenderImGuiDebugController(float dt)
|
||||||
|
{
|
||||||
|
Camera* currentCam = GetCurrentCamera();
|
||||||
|
|
||||||
|
ImGui_Text("Delta time: %f", (double)dt);
|
||||||
|
|
||||||
|
ImGui_Text("Camera:");
|
||||||
|
ImGui_Indent();
|
||||||
|
ImGui_BulletText("Index: %zu", (size_t)currentCam->Index);
|
||||||
|
ImGui_BulletText("Position: (%.3f, %.3f, %.3f)", (double)currentCam->Position.x, (double)currentCam->Position.y,
|
||||||
|
(double)currentCam->Position.z);
|
||||||
|
ImGui_BulletText("Target: (%.3f, %.3f, %.3f)", (double)currentCam->Target.x, (double)currentCam->Target.y,
|
||||||
|
(double)currentCam->Target.z);
|
||||||
|
ImGui_BulletText("Up: (%.3f, %.3f, %.3f)", (double)currentCam->Up.x, (double)currentCam->Up.y,
|
||||||
|
(double)currentCam->Up.z);
|
||||||
|
ImGui_BulletText("FOV: %.3f rad", (double)currentCam->FOV);
|
||||||
|
ImGui_BulletText("AspectRatio: %.3f", (double)currentCam->AspectRatio);
|
||||||
|
ImGui_BulletText("NearPlane: %.3f", (double)currentCam->NearPlane);
|
||||||
|
ImGui_BulletText("FarPlane: %.3f", (double)currentCam->FarPlane);
|
||||||
|
ImGui_BulletText("Pitch: %.3f, Yaw: %.3f", (double)gPitch, (double)gYaw);
|
||||||
|
ImGui_BulletText("FPS Mode: %s", gIsFpsModeActive ? "Active" : "Inactive");
|
||||||
|
ImGui_Unindent();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
#include <Controller/DebugCameraController.h>
|
|
||||||
|
|
||||||
#include <Controller/ControllerUtils.h>
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
|
||||||
#include <Core/HAL/Keyboard/Keyboard.h>
|
|
||||||
#include <Core/HAL/Mouse/Mouse.h>
|
|
||||||
#include <Graphics/Camera.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
bool gIsDebugCameraActive = false;
|
|
||||||
index_t gPreviousCameraIndex = 0;
|
|
||||||
|
|
||||||
float gPitch = 0.0f;
|
|
||||||
float gYaw = 0.0f;
|
|
||||||
bool gFirstUpdate = true;
|
|
||||||
bool gIsFpsModeActive = false;
|
|
||||||
bool gWasRightMouseButtonDown = false;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void ActivateDebugController()
|
|
||||||
{
|
|
||||||
Assert(gIsDebugCameraActive == false);
|
|
||||||
|
|
||||||
Camera* currentCam = GetCurrentCamera();
|
|
||||||
gPreviousCameraIndex = currentCam->Index;
|
|
||||||
|
|
||||||
SetCurrentCamera(kDebugCamera);
|
|
||||||
|
|
||||||
gIsDebugCameraActive = true;
|
|
||||||
gFirstUpdate = true;
|
|
||||||
gIsFpsModeActive = false;
|
|
||||||
gWasRightMouseButtonDown = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeactivateDebugController()
|
|
||||||
{
|
|
||||||
Assert(gIsDebugCameraActive);
|
|
||||||
|
|
||||||
gIsDebugCameraActive = false;
|
|
||||||
|
|
||||||
SetCurrentCamera(gPreviousCameraIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsDebugControllerActive()
|
|
||||||
{
|
|
||||||
return gIsDebugCameraActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateDebugController(float dt)
|
|
||||||
{
|
|
||||||
Camera* currentCam = GetCurrentCamera();
|
|
||||||
|
|
||||||
if (gFirstUpdate)
|
|
||||||
{
|
|
||||||
Vector3 dir = Vector3{ 0.0f, 0.0f, 0.0f } - currentCam->Position;
|
|
||||||
dir = Normalize(dir);
|
|
||||||
gPitch = asinf(dir.z);
|
|
||||||
gYaw = atan2f(dir.y, dir.x);
|
|
||||||
gFirstUpdate = false;
|
|
||||||
|
|
||||||
Vector3 forward;
|
|
||||||
forward.x = cosf(gPitch) * cosf(gYaw);
|
|
||||||
forward.y = cosf(gPitch) * sinf(gYaw);
|
|
||||||
forward.z = sinf(gPitch);
|
|
||||||
Vector3 right = Normalize(Cross(Vector3{ 0.0f, 0.0f, 1.0f }, forward));
|
|
||||||
currentCam->Target = currentCam->Position + forward;
|
|
||||||
currentCam->Up = Cross(forward, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isRightMouseButtonDown = IsMouseButtonDown(MouseButton::Right);
|
|
||||||
if (isRightMouseButtonDown && !gWasRightMouseButtonDown)
|
|
||||||
{
|
|
||||||
gIsFpsModeActive = !gIsFpsModeActive;
|
|
||||||
}
|
|
||||||
gWasRightMouseButtonDown = isRightMouseButtonDown;
|
|
||||||
|
|
||||||
if (!gIsFpsModeActive)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MousePosition mouseDelta = GetMouseDelta();
|
|
||||||
|
|
||||||
float sensitivity = 0.005f;
|
|
||||||
gYaw += mouseDelta.X * sensitivity;
|
|
||||||
gPitch -= mouseDelta.Y * sensitivity;
|
|
||||||
|
|
||||||
gPitch = std::min(gPitch, 1.5f);
|
|
||||||
gPitch = std::max(gPitch, -1.5f);
|
|
||||||
|
|
||||||
if (IsKeyDown(ScanCode::Q))
|
|
||||||
{
|
|
||||||
gYaw -= 2.0f * dt;
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::E))
|
|
||||||
{
|
|
||||||
gYaw += 2.0f * dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 forward;
|
|
||||||
forward.x = cosf(gPitch) * cosf(gYaw);
|
|
||||||
forward.y = cosf(gPitch) * sinf(gYaw);
|
|
||||||
forward.z = sinf(gPitch);
|
|
||||||
|
|
||||||
Vector3 right = Normalize(Cross(Vector3{ 0.0f, 0.0f, 1.0f }, forward));
|
|
||||||
Vector3 defaultUp = Cross(forward, right);
|
|
||||||
|
|
||||||
static const float kMovementPerFrame = 10.f; // 10m/s
|
|
||||||
|
|
||||||
float speedPerFrame = kMovementPerFrame;
|
|
||||||
if (IsKeyDown(ScanCode::LeftShift))
|
|
||||||
{
|
|
||||||
speedPerFrame *= 10.f; // 100m/s
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsKeyDown(ScanCode::W))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position + forward * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::S))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position - forward * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::D))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position + right * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::A))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position - right * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::Space))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position + defaultUp * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
if (IsKeyDown(ScanCode::LeftControl))
|
|
||||||
{
|
|
||||||
currentCam->Position = currentCam->Position - defaultUp * (speedPerFrame * dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentCam->Target = currentCam->Position + forward;
|
|
||||||
currentCam->Up = defaultUp;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
|
||||||
void RenderImGuiDebugController(float dt)
|
|
||||||
{
|
|
||||||
Camera* currentCam = GetCurrentCamera();
|
|
||||||
|
|
||||||
ImGui::Text("Delta time: %f", dt);
|
|
||||||
|
|
||||||
ImGui::Text("Camera:");
|
|
||||||
ImGui::Indent();
|
|
||||||
ImGui::BulletText("Index: %zu", (size_t)currentCam->Index);
|
|
||||||
ImGui::BulletText("Position: (%.3f, %.3f, %.3f)", currentCam->Position.x, currentCam->Position.y,
|
|
||||||
currentCam->Position.z);
|
|
||||||
ImGui::BulletText("Target: (%.3f, %.3f, %.3f)", currentCam->Target.x, currentCam->Target.y, currentCam->Target.z);
|
|
||||||
ImGui::BulletText("Up: (%.3f, %.3f, %.3f)", currentCam->Up.x, currentCam->Up.y, currentCam->Up.z);
|
|
||||||
ImGui::BulletText("FOV: %.3f rad", currentCam->FOV);
|
|
||||||
ImGui::BulletText("AspectRatio: %.3f", currentCam->AspectRatio);
|
|
||||||
ImGui::BulletText("NearPlane: %.3f", currentCam->NearPlane);
|
|
||||||
ImGui::BulletText("FarPlane: %.3f", currentCam->FarPlane);
|
|
||||||
ImGui::BulletText("Pitch: %.3f, Yaw: %.3f", gPitch, gYaw);
|
|
||||||
ImGui::BulletText("FPS Mode: %s", gIsFpsModeActive ? "Active" : "Inactive");
|
|
||||||
ImGui::Unindent();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
// TODO : Should support Debug/Profile/Release properly.
|
// TODO : Should support Debug/Profile/Release properly.
|
||||||
// I think debug profile should have this controller but not release
|
// I think debug profile should have this controller but not release
|
||||||
void ActivateDebugController();
|
void ActivateDebugController(void);
|
||||||
void DeactivateDebugController();
|
void DeactivateDebugController(void);
|
||||||
bool IsDebugControllerActive();
|
bool8 IsDebugControllerActive(void);
|
||||||
void UpdateDebugController(float dt);
|
void UpdateDebugController(float dt);
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
#include <Data/World.h>
|
||||||
|
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
#include <Core/HAL/Filesystem/Filesystem.h>
|
||||||
|
#include <Core/HAL/IO/IOStream.h>
|
||||||
|
#include <Core/Logging/LogManager.h>
|
||||||
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Core/Thread/ThreadContext.h>
|
||||||
|
#include <Entity/EntityManager.h>
|
||||||
|
#include <Graphics/MeshRenderer.h>
|
||||||
|
|
||||||
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
|
#include <dcimgui.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void InitWorld(World* world, Arena* arena)
|
||||||
|
{
|
||||||
|
Assert(world != NULL);
|
||||||
|
Assert(arena != NULL);
|
||||||
|
world->WorldArena = arena;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShutdownWorld(World* world)
|
||||||
|
{
|
||||||
|
Assert(world != NULL);
|
||||||
|
world->WorldArena = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddToWorld(World* world, Entity* entity)
|
||||||
|
{
|
||||||
|
(void)world;
|
||||||
|
(void)entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveWorldEntity(World* world, size_t index)
|
||||||
|
{
|
||||||
|
(void)world;
|
||||||
|
(void)index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializeWorld(Archive* ar, World* world, String filename)
|
||||||
|
{
|
||||||
|
(void)world;
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(IsValidString(filename));
|
||||||
|
|
||||||
|
EntityManager* entityManager = GetEntityManager();
|
||||||
|
|
||||||
|
if (ar->loading)
|
||||||
|
{
|
||||||
|
// Load
|
||||||
|
ByteBuffer fileBuffer = LoadFile(ar->arena, filename);
|
||||||
|
|
||||||
|
// TEST SERIALIZATION
|
||||||
|
ParsedArchive archive = tokenize_archive(ar->arena, fileBuffer);
|
||||||
|
#if JULIET_DEBUG
|
||||||
|
audit_unconsumed_properties(&archive, ConstString("World"));
|
||||||
|
#else
|
||||||
|
(void)archive;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Save
|
||||||
|
IOStream* stream = IOFromFile(ar->arena, filename, WrapString("wb"));
|
||||||
|
|
||||||
|
index_t beginPos = ArenaPos(ar->arena);
|
||||||
|
|
||||||
|
// Headers
|
||||||
|
WorldFileHeader* header = ArenaPushStruct(ar->arena, WorldFileHeader);
|
||||||
|
header->Magic = kWorldMagic;
|
||||||
|
|
||||||
|
// TODO : Move to a one file per entity model
|
||||||
|
for (uint8 i = 0; i < ENTITY(Count); ++i)
|
||||||
|
{
|
||||||
|
typed_entity_array* type = &entityManager->by_type[i];
|
||||||
|
serialize_elem(ar, type->count);
|
||||||
|
if (type->count > 0 && type->array != NULL)
|
||||||
|
{
|
||||||
|
EntityTemplate* element = type->array;
|
||||||
|
uint8* rawElement = (uint8*)element;
|
||||||
|
size_t stride = element->base->derived_kind->size_of;
|
||||||
|
for (index_t idx = 0; idx < type->count; ++idx)
|
||||||
|
{
|
||||||
|
Entity* entity = ((EntityTemplate*)(rawElement + (idx * stride)))->base;
|
||||||
|
serialize_entity(ar, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write
|
||||||
|
index_t endPos = ArenaPos(ar->arena);
|
||||||
|
ByteBuffer writeBuffer = { .Data = (Byte*)header, .Size = endPos - beginPos };
|
||||||
|
|
||||||
|
size_t written = IOWrite(stream, writeBuffer);
|
||||||
|
|
||||||
|
Assert(writeBuffer.Size == written);
|
||||||
|
|
||||||
|
IOClose(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 LoadWorld(World* world, String filename)
|
||||||
|
{
|
||||||
|
(void)world;
|
||||||
|
Assert(IsValidString(filename));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JULIET_EDITOR
|
||||||
|
void RenderWorldEditorUI(World* world)
|
||||||
|
{
|
||||||
|
Assert(world != NULL);
|
||||||
|
|
||||||
|
if (ImGui_Begin("World Editor", NULL, ImGuiWindowFlags_None))
|
||||||
|
{
|
||||||
|
TempArena temp = scratch_begin(NULL, 0);
|
||||||
|
static char worldFilePath[256] = "/world.bin";
|
||||||
|
ImGui_InputText("World File", worldFilePath, sizeof(worldFilePath));
|
||||||
|
|
||||||
|
Path path = GetAssetPath(temp.Arena, AssetType_JAsset, WrapString(worldFilePath));
|
||||||
|
|
||||||
|
if (ImGui_Button("Save World"))
|
||||||
|
{
|
||||||
|
Archive data = { .arena = temp.Arena, .loading = false };
|
||||||
|
SerializeWorld(&data, world, path.FullPath);
|
||||||
|
}
|
||||||
|
ImGui_SameLine(0.0f, -1.0f);
|
||||||
|
if (ImGui_Button("Load World"))
|
||||||
|
{
|
||||||
|
Archive data = { .arena = temp.Arena, .loading = true };
|
||||||
|
SerializeWorld(&data, world, path.FullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(temp);
|
||||||
|
}
|
||||||
|
ImGui_End();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,322 +0,0 @@
|
|||||||
#include <Data/World.h>
|
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
#include <Core/HAL/Filesystem/Filesystem.h>
|
|
||||||
#include <Core/HAL/IO/IOStream.h>
|
|
||||||
#include <Core/Logging/LogManager.h>
|
|
||||||
#include <Core/Logging/LogTypes.h>
|
|
||||||
#include <Core/Thread/ThreadContext.h>
|
|
||||||
#include <Entity/EntityManager.h>
|
|
||||||
#include <Graphics/MeshRenderer.h>
|
|
||||||
|
|
||||||
#ifdef JULIET_ENABLE_IMGUI
|
|
||||||
#include <imgui.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void InitWorld(NonNullPtr<World> world, NonNullPtr<Arena> arena)
|
|
||||||
{
|
|
||||||
world->WorldArena = arena.Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShutdownWorld(NonNullPtr<World> world)
|
|
||||||
{
|
|
||||||
world->WorldArena = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddToWorld(NonNullPtr<World> /*world*/, NonNullPtr<Entity> /*entity*/)
|
|
||||||
{
|
|
||||||
// RegisterEntity(*world->EntityManager, entity.Get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveWorldEntity(World& /*world*/, size_t /*index*/) {}
|
|
||||||
|
|
||||||
void Serialize(Archive& ar, World& /*world*/, String filename)
|
|
||||||
{
|
|
||||||
Assert(IsValid(filename));
|
|
||||||
|
|
||||||
auto& entityManager = GetEntityManager();
|
|
||||||
|
|
||||||
if (ar.loading)
|
|
||||||
{
|
|
||||||
// Load
|
|
||||||
ByteBuffer fileBuffer = LoadFile(ar.arena, filename);
|
|
||||||
|
|
||||||
// TEST SERIALIZATION
|
|
||||||
ParsedArchive archive = tokenize_archive(ar.arena, fileBuffer);
|
|
||||||
// ArchivePropertyNode* property = find_property(&archive, "Position"_crc32);
|
|
||||||
audit_unconsumed_properties(&archive, ConstString("World"));
|
|
||||||
|
|
||||||
// if (fileBuffer.Size >= sizeof(WorldFileHeader))
|
|
||||||
// {
|
|
||||||
// ar.base_ptr = fileBuffer.Data;
|
|
||||||
//
|
|
||||||
// WorldFileHeader header;
|
|
||||||
// serialize_elem(ar, header);
|
|
||||||
// Assert(header.Magic == kWorldMagic);
|
|
||||||
//
|
|
||||||
// for (typed_entity_array& type : entityManager.by_type)
|
|
||||||
// {
|
|
||||||
// serialize_elem(ar, type.count);
|
|
||||||
//
|
|
||||||
// if (type.count > 0)
|
|
||||||
// {
|
|
||||||
//
|
|
||||||
// // Unserialize the base entity to get informations
|
|
||||||
// Entity entity;
|
|
||||||
// // serialize(ar, &entity);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Save
|
|
||||||
IOStream* stream = IOFromFile(ar.arena, filename, WrapString("wb"));
|
|
||||||
|
|
||||||
index_t beginPos = ArenaPos(ar.arena);
|
|
||||||
|
|
||||||
// Headers
|
|
||||||
auto* header = ArenaPushStruct<WorldFileHeader>(ar.arena);
|
|
||||||
header->Magic = kWorldMagic;
|
|
||||||
|
|
||||||
ar.base_ptr = header;
|
|
||||||
|
|
||||||
// TODO : Move to a one file per entity model
|
|
||||||
for (typed_entity_array& type : entityManager.by_type)
|
|
||||||
{
|
|
||||||
serialize_elem(ar, type.count);
|
|
||||||
auto* element = type.array;
|
|
||||||
uint8* rawElement = reinterpret_cast<uint8*>(element);
|
|
||||||
size_t stride = element->base->derived_kind->size_of;
|
|
||||||
for (index_t idx = 0; idx < type.count; ++idx)
|
|
||||||
{
|
|
||||||
// Todo : utils
|
|
||||||
// Get base entity from type
|
|
||||||
Entity* entity = reinterpret_cast<EntityTemplate*>(rawElement + (idx * stride))->base;
|
|
||||||
serialize(ar, entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write
|
|
||||||
index_t endPos = ArenaPos(ar.arena);
|
|
||||||
ByteBuffer writeBuffer = { .Data = reinterpret_cast<Byte*>(header), .Size = endPos - beginPos };
|
|
||||||
|
|
||||||
size_t written = IOWrite(stream, writeBuffer);
|
|
||||||
|
|
||||||
Assert(writeBuffer.Size == written);
|
|
||||||
|
|
||||||
IOClose(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// uint32 entityCount = static_cast<uint32>(world.Entities.Size());
|
|
||||||
// size_t totalBytes = sizeof(WorldFileHeader) + static_cast<size_t>(entityCount) * sizeof(WorldEntityDiskRecord);
|
|
||||||
//
|
|
||||||
// ArenaParams tempParams = { .ReserveSize = Megabytes(1), .Name = "WorldSaveArena" };
|
|
||||||
// Arena* tempArena = ArenaAllocate(tempParams);
|
|
||||||
// if (!tempArena)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "SaveWorld: Failed to allocate memory for saving world.");
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// auto deferRelease = Defer([&]() { ArenaRelease(tempArena); });
|
|
||||||
//
|
|
||||||
// uint8* bufferData = ArenaPushArray<uint8, false>(tempArena, totalBytes);
|
|
||||||
// if (!bufferData)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "SaveWorld: Failed to allocate buffer in arena.");
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// auto* header = reinterpret_cast<WorldFileHeader*>(bufferData);
|
|
||||||
// header->Magic = kWorldMagic;
|
|
||||||
// header->Version = kWorldVersion;
|
|
||||||
// header->EntityCount = entityCount;
|
|
||||||
// header->Reserved = 0;
|
|
||||||
//
|
|
||||||
// auto* records = reinterpret_cast<WorldEntityDiskRecord*>(bufferData + sizeof(WorldFileHeader));
|
|
||||||
// for (size_t i = 0; i < entityCount; ++i)
|
|
||||||
// {
|
|
||||||
// const Entity& ent = world.Entities[i];
|
|
||||||
// records[i].X = ent.X;
|
|
||||||
// records[i].Y = ent.Y;
|
|
||||||
// records[i].Z = ent.Z;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// IOStream* stream = IOFromFile(tempArena, filename, WrapString("wb"));
|
|
||||||
// if (!stream)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "SaveWorld: Failed to open file for writing: %s", CStr(filename));
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ByteBuffer writeBuffer = { .Data = reinterpret_cast<Byte*>(bufferData), .Size = totalBytes };
|
|
||||||
//
|
|
||||||
// size_t written = IOWrite(stream, writeBuffer);
|
|
||||||
// IOClose(stream);
|
|
||||||
//
|
|
||||||
// if (written != totalBytes)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "SaveWorld: Failed to write complete world data to %s (wrote %zu / %zu bytes)",
|
|
||||||
// CStr(filename), written, totalBytes);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// LogMessage(LogCategory::Game, "World successfully saved to %s (%u entities)", CStr(filename), entityCount);
|
|
||||||
// return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool LoadWorld(World& /*world*/, String filename)
|
|
||||||
{
|
|
||||||
Assert(IsValid(filename));
|
|
||||||
// Assert(world.WorldArena != nullptr);
|
|
||||||
//
|
|
||||||
// TempArena loadArena = scratch_begin(nullptr, 0);
|
|
||||||
//
|
|
||||||
// ByteBuffer fileBuffer = LoadFile(loadArena.Arena, filename);
|
|
||||||
// if (fileBuffer.Data && fileBuffer.Size < sizeof(WorldFileHeader))
|
|
||||||
// {
|
|
||||||
// const WorldFileHeader* header = reinterpret_cast<const WorldFileHeader*>(fileBuffer.Data);
|
|
||||||
// const bool invalidMagicNum = header->Magic != kWorldMagic;
|
|
||||||
// const bool invalidVersion = header->Version != kWorldVersion;
|
|
||||||
// if (invalidMagicNum)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "LoadWorld: Invalid magic in world file: %s (expected 0x%08X, got 0x%08X)",
|
|
||||||
// CStr(filename), kWorldMagic, header->Magic);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (invalidVersion)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "LoadWorld: Unsupported world file version: %u in %s", header->Version, CStr(filename));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t expectedSize = sizeof(WorldFileHeader) + static_cast<size_t>(header->EntityCount) * sizeof(WorldEntityDiskRecord);
|
|
||||||
// const bool invalidSize = fileBuffer.Size < expectedSize;
|
|
||||||
// if (invalidSize)
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "LoadWorld: Corrupted file %s: size %zu < expected %zu for %u entities",
|
|
||||||
// CStr(filename), fileBuffer.Size, expectedSize, header->EntityCount);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (!invalidMagicNum && !invalidVersion && !invalidSize)
|
|
||||||
// {
|
|
||||||
//
|
|
||||||
// // world.Entities.Clear();
|
|
||||||
// //
|
|
||||||
// // const auto* records = reinterpret_cast<const WorldEntityDiskRecord*>(
|
|
||||||
// // reinterpret_cast<const uint8*>(fileBuffer.Data) + sizeof(WorldFileHeader));
|
|
||||||
// //
|
|
||||||
// // for (uint32 i = 0; i < header->EntityCount; ++i)
|
|
||||||
// // {
|
|
||||||
// // Entity ent;
|
|
||||||
// // (void)AddWorldEntity(world, records[i].X, records[i].Y, records[i].Z);
|
|
||||||
// // }
|
|
||||||
//
|
|
||||||
// LogMessage(LogCategory::Game, "World successfully loaded from %s (%u entities)", CStr(filename), header->EntityCount);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// LogError(LogCategory::Game, "LoadWorld: Failed to read world file or file is too small: %s", CStr(filename));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// scratch_end(loadArena);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef JULIET_EDITOR
|
|
||||||
void RenderWorldEditorUI(World& world)
|
|
||||||
{
|
|
||||||
if (ImGui::Begin("World Editor"))
|
|
||||||
{
|
|
||||||
TempArena temp = scratch_begin(nullptr, 0);
|
|
||||||
static char worldFilePath[256] = "/world.bin";
|
|
||||||
ImGui::InputText("World File", worldFilePath, sizeof(worldFilePath));
|
|
||||||
|
|
||||||
Path path = GetAssetPath(temp.Arena, AssetType::JAsset, ConstString(worldFilePath));
|
|
||||||
|
|
||||||
if (ImGui::Button("Save World"))
|
|
||||||
{
|
|
||||||
Archive data = { .arena = temp.Arena, .loading = false };
|
|
||||||
Serialize(data, world, path.FullPath);
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Load World"))
|
|
||||||
{
|
|
||||||
Archive data{ .arena = temp.Arena, .loading = true };
|
|
||||||
Serialize(data, world, path.FullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
scratch_end(temp);
|
|
||||||
|
|
||||||
// ImGui::SameLine();
|
|
||||||
// if (ImGui::Button("Clear All"))
|
|
||||||
// {
|
|
||||||
// ClearWorld(world);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ImGui::Separator();
|
|
||||||
//
|
|
||||||
// if (ImGui::Button("Add Entity"))
|
|
||||||
// {
|
|
||||||
// (void)AddWorldEntity(world, 0.0f, 0.0f, 0.0f);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ImGui::Text("Entity Count: %zu", world.Entities.Size());
|
|
||||||
// ImGui::Separator();
|
|
||||||
//
|
|
||||||
// static int selectedEntity = -1;
|
|
||||||
// if (selectedEntity >= static_cast<int>(world.Entities.Size()))
|
|
||||||
// {
|
|
||||||
// selectedEntity = -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ImGui::BeginChild("EntityList", ImVec2(180, 200), true);
|
|
||||||
// for (size_t i = 0; i < world.Entities.Size(); ++i)
|
|
||||||
// {
|
|
||||||
// char label[64];
|
|
||||||
// snprintf(label, sizeof(label), "Entity #%zu (ID: %llu)", i, world.Entities[i].ID);
|
|
||||||
// if (ImGui::Selectable(label, selectedEntity == static_cast<int>(i)))
|
|
||||||
// {
|
|
||||||
// selectedEntity = static_cast<int>(i);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ImGui::EndChild();
|
|
||||||
//
|
|
||||||
// ImGui::SameLine();
|
|
||||||
//
|
|
||||||
// ImGui::BeginChild("EntityInspector", ImVec2(0, 200), true);
|
|
||||||
// if (selectedEntity >= 0 && selectedEntity < static_cast<int>(world.Entities.Size()))
|
|
||||||
// {
|
|
||||||
// Entity& ent = world.Entities[static_cast<size_t>(selectedEntity)];
|
|
||||||
// ImGui::Text("Selected: Entity #%d", selectedEntity);
|
|
||||||
// ImGui::Text("ID: %llu", ent.ID);
|
|
||||||
//
|
|
||||||
// float pos[3] = { ent.X, ent.Y, ent.Z };
|
|
||||||
// if (ImGui::DragFloat3("Position", pos, 0.1f))
|
|
||||||
// {
|
|
||||||
// ent.X = pos[0];
|
|
||||||
// ent.Y = pos[1];
|
|
||||||
// ent.Z = pos[2];
|
|
||||||
// UpdateWorld(world);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (ImGui::Button("Delete Entity"))
|
|
||||||
// {
|
|
||||||
// RemoveWorldEntity(world, static_cast<size_t>(selectedEntity));
|
|
||||||
// selectedEntity = -1;
|
|
||||||
// UpdateWorld(world);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// ImGui::Text("Select an entity to edit its properties.");
|
|
||||||
// }
|
|
||||||
// ImGui::EndChild();
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
+15
-14
@@ -1,38 +1,39 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
#include <Core/Container/Vector.h>
|
#include <Core/Container/Vector.h>
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
#include <Entity/Entity.h>
|
#include <Entity/Entity.h>
|
||||||
|
|
||||||
struct Archive;
|
typedef struct Archive Archive;
|
||||||
struct EntityManager;
|
typedef struct EntityManager EntityManager;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
typedef struct WorldFileHeader WorldFileHeader;
|
||||||
struct WorldFileHeader
|
struct WorldFileHeader
|
||||||
{
|
{
|
||||||
uint32 Magic = 0x444C574A; // 'JWLD' in little-endian
|
uint32 Magic; // 0x444C574A ('JWLD' in little-endian)
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
constexpr uint32 kWorldMagic = 0x444C574A; // 'JWLD'
|
#define kWorldMagic ((uint32)0x444C574A) // 'JWLD'
|
||||||
constexpr uint32 kWorldVersion = 1;
|
#define kWorldVersion ((uint32)1)
|
||||||
|
|
||||||
|
typedef struct World World;
|
||||||
struct World
|
struct World
|
||||||
{
|
{
|
||||||
Arena* WorldArena = nullptr;
|
Arena* WorldArena;
|
||||||
EntityManager* EntityManager = nullptr;
|
EntityManager* EntityManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitWorld(NonNullPtr<World> world, NonNullPtr<Arena> arena);
|
void InitWorld(World* world, Arena* arena);
|
||||||
void ShutdownWorld(NonNullPtr<World> world);
|
void ShutdownWorld(World* world);
|
||||||
|
|
||||||
void AddToWorld(NonNullPtr<World> world, NonNullPtr<Entity> entity);
|
void AddToWorld(World* world, Entity* entity);
|
||||||
void RemoveWorldEntity(World& world, size_t index);
|
void RemoveWorldEntity(World* world, size_t index);
|
||||||
|
|
||||||
void Serialize(Archive& data, World& world, String filename);
|
void SerializeWorld(Archive* data, World* world, String filename);
|
||||||
|
|
||||||
#if JULIET_EDITOR
|
#if JULIET_EDITOR
|
||||||
void RenderWorldEditorUI(World& world);
|
void RenderWorldEditorUI(World* world);
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#include <Debug/DebugTopBar.h>
|
||||||
|
|
||||||
|
#if JULIET_DEBUG
|
||||||
|
#include <game.h>
|
||||||
|
#include <dcimgui.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
internal String GetGameModeName(GameMode gameMode)
|
||||||
|
{
|
||||||
|
String result = WrapString("Unknown ERROR");
|
||||||
|
if (gameMode == GameMode_Editor)
|
||||||
|
{
|
||||||
|
result = WrapString("Editor");
|
||||||
|
}
|
||||||
|
else if (gameMode == GameMode_Play)
|
||||||
|
{
|
||||||
|
result = WrapString("Play");
|
||||||
|
}
|
||||||
|
else if (gameMode == GameMode_Debug)
|
||||||
|
{
|
||||||
|
result = WrapString("Debug");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTopBar(void)
|
||||||
|
{
|
||||||
|
GameState* gameState = GetGameState();
|
||||||
|
|
||||||
|
ImVec2_c viewportPos = ImGui_GetMainViewportPos();
|
||||||
|
ImVec2_c viewportSize = ImGui_GetMainViewportSize();
|
||||||
|
ImGui_SetNextWindowPos(viewportPos);
|
||||||
|
ImVec2_c barSize = { viewportSize.x, 10.0f };
|
||||||
|
ImGui_SetNextWindowSize(barSize);
|
||||||
|
|
||||||
|
ImGuiWindowFlags_c flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
||||||
|
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing |
|
||||||
|
ImGuiWindowFlags_NoNav;
|
||||||
|
|
||||||
|
ImVec4_c bgCol = { 0.0f, 0.0f, 0.0f, 0.6f };
|
||||||
|
ImVec2_c padding = { 10.0f, 5.0f };
|
||||||
|
ImGui_PushStyleColor(ImGuiCol_WindowBg, bgCol);
|
||||||
|
ImGui_PushStyleVarVec2(ImGuiStyleVar_WindowPadding, padding);
|
||||||
|
|
||||||
|
if (ImGui_Begin("TopBarOverlay", NULL, flags))
|
||||||
|
{
|
||||||
|
ImGui_Text("Game Mode: %s", CStr(GetGameModeName(gameState->Mode)));
|
||||||
|
|
||||||
|
float framerate = ImGuiIO_GetFramerate();
|
||||||
|
char fps_text[32];
|
||||||
|
snprintf(fps_text, sizeof(fps_text), "FPS: %.1f (%.2f ms)", (double)framerate, (double)(1000.0f / framerate));
|
||||||
|
float text_width = ImGui_CalcTextSize(fps_text, NULL).x;
|
||||||
|
ImGui_SameLine(viewportSize.x - text_width - 15.0f, -1.0f); // 15px right padding
|
||||||
|
// Render FPS text
|
||||||
|
ImGui_Text("%s", fps_text);
|
||||||
|
}
|
||||||
|
ImGui_End();
|
||||||
|
|
||||||
|
ImGui_PopStyleVar(1);
|
||||||
|
ImGui_PopStyleColor(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#include <Debug/DebugTopBar.h>
|
|
||||||
|
|
||||||
#include <game.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
String GetGameModeName(GameMode gameMode)
|
|
||||||
{
|
|
||||||
switch (gameMode)
|
|
||||||
{
|
|
||||||
case GameMode::Editor: return WrapString("Editor");
|
|
||||||
case GameMode::Play: return WrapString("Play");
|
|
||||||
case GameMode::Debug: return WrapString("Debug");
|
|
||||||
default: return WrapString("Unknown ERROR");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void DrawTopBar()
|
|
||||||
{
|
|
||||||
auto* gameState = GetGameState();
|
|
||||||
|
|
||||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
|
||||||
ImGui::SetNextWindowPos(viewport->Pos);
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, 10.0f));
|
|
||||||
|
|
||||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
|
|
||||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
|
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.6f));
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 5.0f));
|
|
||||||
|
|
||||||
if (ImGui::Begin("TopBarOverlay", nullptr, flags))
|
|
||||||
{
|
|
||||||
ImGui::Text("Game Mode: %s", CStr(GetGameModeName(gameState->Mode)));
|
|
||||||
|
|
||||||
char fps_text[32];
|
|
||||||
snprintf(fps_text, sizeof(fps_text), "FPS: %.1f (%.2f ms)", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate);
|
|
||||||
float text_width = ImGui::CalcTextSize(fps_text).x;
|
|
||||||
ImGui::SameLine(viewport->Size.x - text_width - 15.0f); // 15px right padding
|
|
||||||
// Render FPS text
|
|
||||||
ImGui::Text("%s", fps_text);
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
void DrawTopBar();
|
void DrawTopBar(void);
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#include <Entity/Entity.h>
|
||||||
|
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
#include <Core/Memory/Utils.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void serialize_entity(Archive* ar, Entity* entity)
|
||||||
|
{
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(entity != NULL);
|
||||||
|
|
||||||
|
// Entity fields
|
||||||
|
serialize_class(ar, ClassKind(Entity), entity);
|
||||||
|
|
||||||
|
// Derived fields
|
||||||
|
if (entity->derived_kind != NULL && entity->derived != NULL)
|
||||||
|
{
|
||||||
|
serialize_class(ar, entity->derived_kind, entity->derived);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void init_Entity(void* payload)
|
||||||
|
{
|
||||||
|
Assert(payload != NULL);
|
||||||
|
Entity* entity = (Entity*)payload;
|
||||||
|
MemZeroStruct(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void serialize_Entity(Archive* ar, uint16 version, void* payload)
|
||||||
|
{
|
||||||
|
(void)version;
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(payload != NULL);
|
||||||
|
Entity* entity = (Entity*)payload;
|
||||||
|
SERIALIZE_U64(ar, id, &entity->ID);
|
||||||
|
SERIALIZE_VEC4(ar, position, &entity->position);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_CLASS_VERSIONED(Entity, 1, NULL)
|
||||||
|
|
||||||
|
String format_entity_id(Arena* arena, EntityID entity_id)
|
||||||
|
{
|
||||||
|
Assert(arena != NULL);
|
||||||
|
|
||||||
|
// Format:
|
||||||
|
// U = UserID
|
||||||
|
// LC = Local Entity Counter
|
||||||
|
// UU_LCLCLCLCLCLCLC
|
||||||
|
uint8 user_id = get_user_id(entity_id);
|
||||||
|
uint64 counter = get_local_counter(entity_id);
|
||||||
|
|
||||||
|
const size_t kBufferSize = 18;
|
||||||
|
char* buffer = ArenaPushArray(arena, char, kBufferSize);
|
||||||
|
Assert(buffer != NULL);
|
||||||
|
|
||||||
|
juliet_snprintf(buffer, kBufferSize, "%02X_%014llX", (unsigned int)user_id, (unsigned long long)counter);
|
||||||
|
String result = { .Str = buffer, .Size = kBufferSize - 1 };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 parse_entity_id(String str, EntityID* out_id)
|
||||||
|
{
|
||||||
|
Assert(out_id != NULL);
|
||||||
|
|
||||||
|
bool8 result = false;
|
||||||
|
*out_id = kInvalid_entity_id;
|
||||||
|
|
||||||
|
if (!(str.Size != 17 || str.Str == NULL || str.Str[2] != '_'))
|
||||||
|
{
|
||||||
|
char user_hex[3] = { str.Str[0], str.Str[1], '\0' };
|
||||||
|
char* end = user_hex;
|
||||||
|
uint8 user_id = (uint8)strtoul(user_hex, &end, 16);
|
||||||
|
if (end != user_hex && user_id != kInvalid_user_id)
|
||||||
|
{
|
||||||
|
char* counter_hex = str.Str + 3;
|
||||||
|
end = counter_hex;
|
||||||
|
uint64 counter = strtoull(counter_hex, &end, 16);
|
||||||
|
if (end != counter_hex && counter < kEntityID_user_id_mask)
|
||||||
|
{
|
||||||
|
*out_id = make_entity_id(user_id, counter);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Class* resolve_entity_class(uint8 kind, uint32 crc)
|
||||||
|
{
|
||||||
|
Assert(kind <= ENTITY(Count));
|
||||||
|
|
||||||
|
const Class* class_ptr = kEntity_type_class_ptr[kind];
|
||||||
|
Assert(class_ptr != NULL);
|
||||||
|
Assert(class_get_crc(class_ptr) == crc);
|
||||||
|
|
||||||
|
return class_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Class* find_class_by_name(String name)
|
||||||
|
{
|
||||||
|
Assert(IsValidString(name));
|
||||||
|
|
||||||
|
const Class* result = NULL;
|
||||||
|
const uint32 name_crc = crc32_bytes(name.Str, name.Size);
|
||||||
|
for (uint8 kind = 0; kind < ENTITY(Count); ++kind)
|
||||||
|
{
|
||||||
|
const Class* class_ptr = resolve_entity_class(kind, name_crc);
|
||||||
|
if (class_ptr != NULL)
|
||||||
|
{
|
||||||
|
result = class_ptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
#include <Entity/Entity.h>
|
|
||||||
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
|
|
||||||
void serialize(Archive& ar, NonNullPtr<Entity> entity)
|
|
||||||
{
|
|
||||||
// Entity fields
|
|
||||||
serialize(ar, Entity::kind, entity.Get());
|
|
||||||
|
|
||||||
// Derived fields
|
|
||||||
if (entity->derived_kind != nullptr && entity->derived != nullptr)
|
|
||||||
{
|
|
||||||
serialize(ar, entity->derived_kind, entity->derived);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_CLASS_VERSIONED(Entity, 1, nullptr)
|
|
||||||
internal void serialize(Archive& ar, uint16 /*version*/, Entity& entity)
|
|
||||||
{
|
|
||||||
SERIALIZE(ar, id, entity.ID);
|
|
||||||
SERIALIZE(ar, position, entity.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
String format_entity_id(NonNullPtr<Arena> arena, EntityID entity_id)
|
|
||||||
{
|
|
||||||
// Format:
|
|
||||||
// U = UserID
|
|
||||||
// LC = Local Entity Counter
|
|
||||||
// UU_LCLCLCLCLCLCLC
|
|
||||||
uint8 user_id = get_user_id(entity_id);
|
|
||||||
uint64 counter = get_local_counter(entity_id);
|
|
||||||
|
|
||||||
constexpr size_t kBufferSize = 18;
|
|
||||||
char* buffer = ArenaPushArray<char>(arena, kBufferSize);
|
|
||||||
Assert(buffer);
|
|
||||||
|
|
||||||
juliet_snprintf(buffer, kBufferSize, "%02X_%014llX", (unsigned int)user_id, counter);
|
|
||||||
return { buffer, kBufferSize - 1 };
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_entity_id(String str, EntityID& out_id)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
out_id = kInvalid_entity_id;
|
|
||||||
|
|
||||||
if (!(str.Size != 17 || str.Str == nullptr || str.Str[2] != '_'))
|
|
||||||
{
|
|
||||||
char user_hex[3]{ str.Str[0], str.Str[1], '\0' };
|
|
||||||
char* end = user_hex;
|
|
||||||
uint8 user_id = strtoul(user_hex, &end, 16);
|
|
||||||
if (end != user_hex && user_id != kInvalid_user_id)
|
|
||||||
{
|
|
||||||
char* counter_hex = str.Str + 3;
|
|
||||||
end = counter_hex;
|
|
||||||
uint64 counter = strtoull(counter_hex, &end, 16);
|
|
||||||
if (end != counter_hex && counter < kEntityID_user_id_mask)
|
|
||||||
{
|
|
||||||
out_id = make_entity_id(user_id, counter);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Class* resolve_entity_class(uint8 kind, uint32 crc)
|
|
||||||
{
|
|
||||||
Assert(kind <= ENTITY(Count));
|
|
||||||
|
|
||||||
NonNullPtr<const Class> class_ptr = kEntity_type_class_ptr[kind];
|
|
||||||
Assert(class_ptr->CRC == crc);
|
|
||||||
|
|
||||||
return class_ptr.Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Class* find_class_by_name(String name)
|
|
||||||
{
|
|
||||||
Assert(IsValid(name));
|
|
||||||
|
|
||||||
const Class* result = nullptr;
|
|
||||||
const uint32 name_crc = crc32(name.Str, name.Size);
|
|
||||||
for (uint8 kind = 0; kind < ENTITY(Count); ++kind)
|
|
||||||
{
|
|
||||||
const Class* class_ptr = resolve_entity_class(kind, name_crc);
|
|
||||||
if (class_ptr != nullptr)
|
|
||||||
{
|
|
||||||
result = class_ptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
+48
-51
@@ -6,98 +6,95 @@
|
|||||||
#include <Entity/entity_common.h>
|
#include <Entity/entity_common.h>
|
||||||
#include <Entity/EntityManager.h>
|
#include <Entity/EntityManager.h>
|
||||||
|
|
||||||
struct Entity final
|
typedef struct Entity Entity;
|
||||||
|
struct Entity
|
||||||
{
|
{
|
||||||
DECLARE_CLASS()
|
EntityID ID;
|
||||||
|
const Class* derived_kind;
|
||||||
EntityID ID = 0;
|
DerivedType derived;
|
||||||
const Class* derived_kind = nullptr;
|
Vector4 position;
|
||||||
DerivedType derived = nullptr;
|
bool8 is_dirty;
|
||||||
Vector4 position = {};
|
|
||||||
bool is_dirty = false;
|
|
||||||
};
|
};
|
||||||
|
DECLARE_CLASS(Entity)
|
||||||
|
|
||||||
// Can reinterpret cast to this to have the offset of Base and Kind for any entity
|
// Can cast to this to have the offset of base for any entity
|
||||||
|
typedef struct EntityTemplate EntityTemplate;
|
||||||
struct EntityTemplate
|
struct EntityTemplate
|
||||||
{
|
{
|
||||||
DECLARE_ENTITY();
|
DECLARE_ENTITY()
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
static inline EntityID make_entity_id(uint8 user_id, uint64 local_counter)
|
||||||
template <typename EntityType>
|
|
||||||
concept EntityConcept = requires(EntityType entity) {
|
|
||||||
{ EntityType::kind } -> std::convertible_to<const Class*>;
|
|
||||||
requires std::same_as<decltype(entity.base), Entity*>;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline constexpr EntityID make_entity_id(uint8 user_id, uint64 local_counter)
|
|
||||||
{
|
{
|
||||||
Assert(user_id != kInvalid_user_id);
|
Assert(user_id != kInvalid_user_id);
|
||||||
Assert((local_counter & kEntityID_user_id_mask) == kInvalid_entity_id);
|
Assert((local_counter & kEntityID_user_id_mask) == kInvalid_entity_id);
|
||||||
|
|
||||||
EntityID result = kInvalid_user_id;
|
EntityID result = ((EntityID)user_id << kEntityID_user_id_shift) | (local_counter & kEntityID_user_id_mask);
|
||||||
result = ((EntityID)user_id << kEntityID_user_id_shift) | (local_counter & kEntityID_user_id_mask);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr uint8 get_user_id(EntityID entity_id)
|
static inline uint8 get_user_id(EntityID entity_id)
|
||||||
{
|
{
|
||||||
return (((uint8)entity_id & kEntityID_user_id_mask) << kEntityID_user_id_shift);
|
return (uint8)((entity_id & kEntityID_user_id_mask) >> kEntityID_user_id_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr uint64 get_local_counter(EntityID entity_id)
|
static inline uint64 get_local_counter(EntityID entity_id)
|
||||||
{
|
{
|
||||||
return (uint64)entity_id & kEntityID_user_id_mask;
|
return (uint64)entity_id & ~kEntityID_user_id_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr bool is_entity_id_valid(EntityID entity_id)
|
static inline bool8 is_entity_id_valid(EntityID entity_id)
|
||||||
{
|
{
|
||||||
bool result = entity_id != kInvalid_entity_id;
|
bool8 result = (entity_id != kInvalid_entity_id);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename EntityType>
|
static inline bool8 IsEntityA(const Entity* entity, const Class* kind)
|
||||||
requires EntityConcept<EntityType>
|
|
||||||
[[nodiscard]] bool IsA(const Entity* entity)
|
|
||||||
{
|
{
|
||||||
Assert(entity != nullptr);
|
Assert(entity != NULL);
|
||||||
return entity->derived_kind == EntityType::kind;
|
return entity->derived_kind == kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename EntityType>
|
#define IsEntityOfType(entity_ptr, EntityType) IsEntityA((entity_ptr), ClassKind(EntityType))
|
||||||
requires EntityConcept<EntityType>
|
|
||||||
[[nodiscard]] EntityType* MakeEntity(EntityManager& manager, float x, float y, float z)
|
|
||||||
{
|
|
||||||
Entity* base_ptr = allocate_entity(manager, EntityType::kind);
|
|
||||||
Assert(base_ptr);
|
|
||||||
|
|
||||||
base_ptr->ID = EntityManager::ID++;
|
static inline void* make_entity_by_class(EntityManager* manager, const Class* kind, float x, float y, float z)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
Assert(kind != NULL);
|
||||||
|
|
||||||
|
Entity* base_ptr = allocate_entity(manager, kind);
|
||||||
|
Assert(base_ptr != NULL);
|
||||||
|
|
||||||
|
base_ptr->ID = g_entity_manager_id++;
|
||||||
|
|
||||||
base_ptr->position.x = x;
|
base_ptr->position.x = x;
|
||||||
base_ptr->position.y = y;
|
base_ptr->position.y = y;
|
||||||
base_ptr->position.z = z;
|
base_ptr->position.z = z;
|
||||||
base_ptr->position.w = 1.0f;
|
base_ptr->position.w = 1.0f;
|
||||||
|
|
||||||
return (EntityType*)base_ptr->derived;
|
return base_ptr->derived;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename EntityType>
|
#define MakeEntity(EntityType, manager_ptr, x, y, z) \
|
||||||
requires EntityConcept<EntityType>
|
((EntityType*)make_entity_by_class((manager_ptr), ClassKind(EntityType), (x), (y), (z)))
|
||||||
[[nodiscard]] EntityType* DownCast(Entity* entity)
|
|
||||||
|
static inline void* down_cast_entity(Entity* entity, const Class* kind)
|
||||||
{
|
{
|
||||||
Assert(entity != nullptr);
|
Assert(entity != NULL);
|
||||||
Assert(IsA<EntityType>(entity));
|
Assert(IsEntityA(entity, kind));
|
||||||
return static_cast<EntityType*>(entity->derived);
|
return entity->derived;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialize(Archive& ar, NonNullPtr<Entity> entity);
|
#define DownCastEntity(EntityType, entity_ptr) ((EntityType*)down_cast_entity((entity_ptr), ClassKind(EntityType)))
|
||||||
|
|
||||||
JULIET_API uint8 get_local_user_id();
|
void serialize_entity(Archive* ar, Entity* entity);
|
||||||
|
|
||||||
JULIET_API String format_entity_id(NonNullPtr<Arena> arena, EntityID id);
|
JULIET_API uint8 get_local_user_id(void);
|
||||||
|
|
||||||
JULIET_API bool parse_entity_id(String str, EntityID& outId);
|
JULIET_API String format_entity_id(Arena* arena, EntityID id);
|
||||||
|
|
||||||
[[nodiscard]] const Class* find_class_by_name(String name);
|
JULIET_API bool8 parse_entity_id(String str, EntityID* outId);
|
||||||
|
|
||||||
[[nodiscard]] const Class* resolve_entity_class(uint8 kind, uint32 crc);
|
const Class* find_class_by_name(String name);
|
||||||
|
|
||||||
|
const Class* resolve_entity_class(uint8 kind, uint32 crc);
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
#include <Entity/EntityManager.h>
|
||||||
|
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
#include <Core/Memory/Utils.h>
|
||||||
|
#include <Data/World.h>
|
||||||
|
#include <Engine/user.h>
|
||||||
|
#include <Entity/Entity.h>
|
||||||
|
#include <Entity/entity_types.h>
|
||||||
|
#include <game.h>
|
||||||
|
#include <Graphics/MeshRenderer.h>
|
||||||
|
|
||||||
|
EntityID g_entity_manager_id = 0;
|
||||||
|
|
||||||
|
void InitEntityManager(World* world)
|
||||||
|
{
|
||||||
|
Assert(world != NULL);
|
||||||
|
|
||||||
|
EntityManager* newManager = ArenaPushStruct(world->WorldArena, EntityManager);
|
||||||
|
newManager->next_local_counter = 1ULL;
|
||||||
|
world->EntityManager = newManager;
|
||||||
|
|
||||||
|
VectorArenaCreate(&newManager->Entities, Entity, world->WorldArena, 100000 JULIET_DEBUG_PARAM("Entities"));
|
||||||
|
|
||||||
|
ArenaParams by_type_params = { .ReserveSize = Kilobytes(1),
|
||||||
|
.CommitSize = Kilobytes(1),
|
||||||
|
.Name = "" JULIET_DEBUG_ONLY(, .DoNotReserveMore = true) };
|
||||||
|
for (uint8 i = 0; i < ENTITY(Count); ++i)
|
||||||
|
{
|
||||||
|
by_type_params.Name = kEntity_type_names[i];
|
||||||
|
newManager->by_type[i].arena = ArenaAllocate(by_type_params);
|
||||||
|
newManager->by_type[i].array = NULL;
|
||||||
|
newManager->by_type[i].count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShutdownEntityManager(void)
|
||||||
|
{
|
||||||
|
EntityManager* manager = GetEntityManager();
|
||||||
|
for (uint8 i = 0; i < ENTITY(Count); ++i)
|
||||||
|
{
|
||||||
|
ArenaRelease(manager->by_type[i].arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector_arena_destroy(&manager->Entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityManager* GetEntityManager(void)
|
||||||
|
{
|
||||||
|
EntityManager* entityManager = GetGameState()->World->EntityManager;
|
||||||
|
Assert(entityManager != NULL);
|
||||||
|
return entityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityID generate_next_entity_id(EntityManager* manager)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
|
||||||
|
UserID user = get_local_user_id();
|
||||||
|
Assert(user != kInvalid_user_id);
|
||||||
|
Assert(manager->next_local_counter != kEntityID_user_id_mask);
|
||||||
|
|
||||||
|
EntityID new_id = make_entity_id(user, manager->next_local_counter);
|
||||||
|
manager->next_local_counter += 1ULL;
|
||||||
|
return new_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityTemplate* RegisterEntity(EntityManager* manager, Entity* base, DerivedType entity)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
Assert(base != NULL);
|
||||||
|
|
||||||
|
base->ID = g_entity_manager_id++;
|
||||||
|
base->derived = entity;
|
||||||
|
|
||||||
|
VectorArenaPushPtr(Entity, &manager->Entities, base);
|
||||||
|
|
||||||
|
EntityTemplate* ptr = (EntityTemplate*)ArenaPushSize(
|
||||||
|
manager->by_type[base->derived_kind->kind].arena, base->derived_kind->size_of, base->derived_kind->alignment,
|
||||||
|
false JULIET_DEBUG_PARAM(kEntity_type_names[base->derived_kind->kind]));
|
||||||
|
MemCopy(ptr, entity, base->derived_kind->size_of);
|
||||||
|
manager->by_type[base->derived_kind->kind].count += 1;
|
||||||
|
|
||||||
|
ptr->base = VectorArenaBack(Entity, &manager->Entities);
|
||||||
|
|
||||||
|
if (manager->by_type[base->derived_kind->kind].array == NULL)
|
||||||
|
{
|
||||||
|
manager->by_type[base->derived_kind->kind].array = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* allocate_entity(EntityManager* manager, const Class* derived_type_class)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
Assert(derived_type_class != NULL);
|
||||||
|
Assert(derived_type_class->kind < ENTITY(Count));
|
||||||
|
Assert(derived_type_class->size_of >= sizeof(EntityTemplate));
|
||||||
|
Assert(derived_type_class->alignment > 0);
|
||||||
|
Assert(derived_type_class->initialize_fct != NULL);
|
||||||
|
|
||||||
|
Entity base_template = { 0 };
|
||||||
|
base_template.derived_kind = derived_type_class;
|
||||||
|
base_template.is_dirty = true;
|
||||||
|
|
||||||
|
VectorArenaPushPtr(Entity, &manager->Entities, &base_template);
|
||||||
|
Entity* base_ptr = VectorArenaBack(Entity, &manager->Entities);
|
||||||
|
Assert(base_ptr != NULL);
|
||||||
|
|
||||||
|
typed_entity_array* typed_array = &manager->by_type[derived_type_class->kind];
|
||||||
|
Assert(typed_array->arena != NULL);
|
||||||
|
|
||||||
|
void* derived = ArenaPushSize(typed_array->arena, derived_type_class->size_of, derived_type_class->alignment,
|
||||||
|
false JULIET_DEBUG_PARAM(kEntity_type_names[derived_type_class->kind]));
|
||||||
|
Assert(derived != NULL);
|
||||||
|
derived_type_class->initialize_fct(derived);
|
||||||
|
|
||||||
|
EntityTemplate* derived_template = (EntityTemplate*)derived;
|
||||||
|
|
||||||
|
base_ptr->derived = derived;
|
||||||
|
derived_template->base = base_ptr;
|
||||||
|
|
||||||
|
if (typed_array->array == NULL)
|
||||||
|
{
|
||||||
|
typed_array->array = derived_template;
|
||||||
|
}
|
||||||
|
typed_array->count += 1;
|
||||||
|
|
||||||
|
return base_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateEntityManager(EntityManager* manager)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
|
||||||
|
// Todo : inert by definition dont move, but this is for test
|
||||||
|
typed_entity_array* by_type = &manager->by_type[ENTITY(Inert)];
|
||||||
|
for (index_t i = 0; i < by_type->count; ++i)
|
||||||
|
{
|
||||||
|
Inert* inert = ((Inert*)by_type->array) + i;
|
||||||
|
if (inert->MeshInstance != indexMax)
|
||||||
|
{
|
||||||
|
Matrix transform =
|
||||||
|
MatrixTranslation(inert->base->position.x, inert->base->position.y, inert->base->position.z);
|
||||||
|
SetMeshInstanceTransform(inert->MeshInstance, &transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* deserialize_entity(Archive* ar, EntityManager* manager)
|
||||||
|
{
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(manager != NULL);
|
||||||
|
Assert(ar->loading);
|
||||||
|
|
||||||
|
String class_name = { 0 };
|
||||||
|
SERIALIZE_STR(ar, Class, &class_name);
|
||||||
|
|
||||||
|
const Class* class_ptr = find_class_by_name(class_name);
|
||||||
|
Assert(class_ptr != NULL);
|
||||||
|
|
||||||
|
Entity* entity_base = allocate_entity(manager, class_ptr);
|
||||||
|
Assert(entity_base != NULL);
|
||||||
|
|
||||||
|
serialize_entity(ar, entity_base);
|
||||||
|
|
||||||
|
if (entity_base->ID >= g_entity_manager_id)
|
||||||
|
{
|
||||||
|
g_entity_manager_id = entity_base->ID + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_base->is_dirty = false;
|
||||||
|
|
||||||
|
return entity_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_local_counter(EntityManager* manager, EntityID entity_id)
|
||||||
|
{
|
||||||
|
Assert(manager != NULL);
|
||||||
|
|
||||||
|
uint8 user_id = get_local_user_id();
|
||||||
|
if (get_user_id(entity_id) == user_id)
|
||||||
|
{
|
||||||
|
uint64 counter = get_local_counter(entity_id);
|
||||||
|
if (counter >= manager->next_local_counter)
|
||||||
|
{
|
||||||
|
manager->next_local_counter = counter + 1ULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
#include <Entity/EntityManager.h>
|
|
||||||
|
|
||||||
#include <Core/Common/EnumUtils.h>
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
#include <Data/World.h>
|
|
||||||
#include <Entity/Entity.h>
|
|
||||||
#include <Entity/entity_types.h>
|
|
||||||
#include <game.h>
|
|
||||||
#include <Graphics/MeshRenderer.h>
|
|
||||||
#include "Engine/user.h"
|
|
||||||
|
|
||||||
EntityID EntityManager::ID = 0;
|
|
||||||
|
|
||||||
void InitEntityManager(NonNullPtr<World> world)
|
|
||||||
{
|
|
||||||
EntityManager* newManager = ArenaPushStruct<EntityManager>(world->WorldArena);
|
|
||||||
world->EntityManager = newManager;
|
|
||||||
|
|
||||||
newManager->Entities.Create(world->WorldArena JULIET_DEBUG_PARAM("Entities"));
|
|
||||||
|
|
||||||
ArenaParams by_type_params{ .ReserveSize = Kilobytes(1),
|
|
||||||
.CommitSize = Kilobytes(1),
|
|
||||||
.Name = "" JULIET_DEBUG_ONLY(, .CanReserveMore = false) };
|
|
||||||
for (uint8 i = 0; i < ENTITY(Count); ++i)
|
|
||||||
{
|
|
||||||
by_type_params.Name = kEntity_type_names[i];
|
|
||||||
newManager->by_type[i].arena = ArenaAllocate(by_type_params);
|
|
||||||
newManager->by_type[i].array = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShutdownEntityManager()
|
|
||||||
{
|
|
||||||
auto& manager = GetEntityManager();
|
|
||||||
for (typed_entity_array& type : manager.by_type)
|
|
||||||
{
|
|
||||||
ArenaRelease(type.arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager.Entities.Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityManager& GetEntityManager()
|
|
||||||
{
|
|
||||||
NonNullPtr entityManager = GetGameState()->World->EntityManager;
|
|
||||||
return *entityManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityID generate_next_entity_id(EntityManager& manager)
|
|
||||||
{
|
|
||||||
UserID user = get_local_user_id();
|
|
||||||
Assert(user != kInvalid_user_id);
|
|
||||||
Assert(manager.next_local_counter != kEntityID_user_id_mask);
|
|
||||||
|
|
||||||
EntityID new_id = make_entity_id(user, manager.next_local_counter);
|
|
||||||
manager.next_local_counter += 1ULL;
|
|
||||||
return new_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityTemplate* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity)
|
|
||||||
{
|
|
||||||
base->ID = EntityManager::ID++;
|
|
||||||
base->derived = entity;
|
|
||||||
|
|
||||||
manager.Entities.PushBack(*base);
|
|
||||||
|
|
||||||
auto* ptr = (EntityTemplate*)ArenaPushSize(manager.by_type[base->derived_kind->kind].arena,
|
|
||||||
base->derived_kind->size_of, base->derived_kind->alignment,
|
|
||||||
false JULIET_DEBUG_PARAM(kEntity_type_names[base->derived_kind->kind]));
|
|
||||||
MemCopy(ptr, entity, base->derived_kind->size_of);
|
|
||||||
manager.by_type[base->derived_kind->kind].count += 1;
|
|
||||||
|
|
||||||
ptr->base = manager.Entities.Back();
|
|
||||||
|
|
||||||
if (manager.by_type[base->derived_kind->kind].array == nullptr)
|
|
||||||
{
|
|
||||||
manager.by_type[base->derived_kind->kind].array = ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity* allocate_entity(EntityManager& manager, NonNullPtr<const Class> derived_type_class)
|
|
||||||
{
|
|
||||||
Assert(derived_type_class->kind < ENTITY(Count));
|
|
||||||
Assert(derived_type_class->size_of >= sizeof(EntityTemplate));
|
|
||||||
Assert(derived_type_class->alignment > 0);
|
|
||||||
Assert(derived_type_class->initialize_fct);
|
|
||||||
|
|
||||||
Entity base_template = {};
|
|
||||||
base_template.derived_kind = derived_type_class;
|
|
||||||
base_template.is_dirty = true;
|
|
||||||
|
|
||||||
manager.Entities.PushBack(base_template);
|
|
||||||
Entity* base_ptr = manager.Entities.Back();
|
|
||||||
Assert(base_ptr);
|
|
||||||
|
|
||||||
typed_entity_array& typed_array = manager.by_type[derived_type_class->kind];
|
|
||||||
Assert(typed_array.arena);
|
|
||||||
|
|
||||||
void* derived = ArenaPushSize(typed_array.arena, derived_type_class->size_of, derived_type_class->alignment,
|
|
||||||
false JULIET_DEBUG_PARAM(kEntity_type_names[derived_type_class->kind]));
|
|
||||||
Assert(derived);
|
|
||||||
derived_type_class->initialize_fct(derived);
|
|
||||||
|
|
||||||
auto* derived_template = (EntityTemplate*)derived;
|
|
||||||
|
|
||||||
base_ptr->derived = derived;
|
|
||||||
derived_template->base = base_ptr;
|
|
||||||
|
|
||||||
if (typed_array.array == nullptr)
|
|
||||||
{
|
|
||||||
typed_array.array = derived_template;
|
|
||||||
}
|
|
||||||
typed_array.count += 1;
|
|
||||||
|
|
||||||
return base_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateEntityManager(EntityManager& manager)
|
|
||||||
{
|
|
||||||
// Todo : inert by definition dont move, but this is for test
|
|
||||||
auto& by_type = manager.by_type[ENTITY(Inert)];
|
|
||||||
for (index_t i = 0; i < by_type.count; ++i)
|
|
||||||
{
|
|
||||||
Inert* inert = reinterpret_cast<Inert*>(by_type.array) + i;
|
|
||||||
if (inert->MeshInstance != indexMax)
|
|
||||||
{
|
|
||||||
SetMeshInstanceTransform(inert->MeshInstance,
|
|
||||||
MatrixTranslation(inert->base->position.x, inert->base->position.y,
|
|
||||||
inert->base->position.z));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity* deserialize_entity(Archive& ar, EntityManager& manager)
|
|
||||||
{
|
|
||||||
Assert(ar.loading);
|
|
||||||
|
|
||||||
String class_name;
|
|
||||||
SERIALIZE(ar, Class, class_name);
|
|
||||||
|
|
||||||
NonNullPtr<const Class> class_ptr = find_class_by_name(class_name);
|
|
||||||
|
|
||||||
NonNullPtr<Entity> entity_base = allocate_entity(manager, class_ptr);
|
|
||||||
|
|
||||||
serialize(ar, entity_base);
|
|
||||||
|
|
||||||
if (entity_base->ID >= EntityManager::ID)
|
|
||||||
{
|
|
||||||
EntityManager::ID = entity_base->ID + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity_base->is_dirty = false;
|
|
||||||
|
|
||||||
return entity_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_local_counter(EntityManager& manager, EntityID entity_id)
|
|
||||||
{
|
|
||||||
uint8 user_id = get_local_user_id();
|
|
||||||
if (get_user_id(entity_id) == user_id)
|
|
||||||
{
|
|
||||||
uint64 counter = get_local_counter(entity_id);
|
|
||||||
if (counter >= manager.next_local_counter)
|
|
||||||
{
|
|
||||||
manager.next_local_counter = counter + 1ULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+20
-16
@@ -3,11 +3,13 @@
|
|||||||
#include <Core/Container/Vector.h>
|
#include <Core/Container/Vector.h>
|
||||||
#include <Entity/entity_common.h>
|
#include <Entity/entity_common.h>
|
||||||
|
|
||||||
struct World;
|
typedef struct World World;
|
||||||
struct EntityTemplate;
|
typedef struct EntityTemplate EntityTemplate;
|
||||||
struct Entity;
|
typedef struct Entity Entity;
|
||||||
struct Class;
|
typedef struct Class Class;
|
||||||
|
typedef struct Archive Archive;
|
||||||
|
|
||||||
|
typedef struct typed_entity_array typed_entity_array;
|
||||||
struct typed_entity_array
|
struct typed_entity_array
|
||||||
{
|
{
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
@@ -15,22 +17,24 @@ struct typed_entity_array
|
|||||||
size_t count;
|
size_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct EntityManager EntityManager;
|
||||||
struct EntityManager
|
struct EntityManager
|
||||||
{
|
{
|
||||||
static EntityID ID;
|
uint64 next_local_counter;
|
||||||
uint64 next_local_counter = 1ULL;
|
|
||||||
|
|
||||||
// TODO: Should be a pool
|
// TODO: Should be a pool
|
||||||
VectorArena<Entity, 100'000> Entities;
|
VectorArena Entities;
|
||||||
|
|
||||||
typed_entity_array by_type[ENTITY(Count)];
|
typed_entity_array by_type[Entity_Type_Count];
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitEntityManager(NonNullPtr<World> world);
|
extern EntityID g_entity_manager_id;
|
||||||
void ShutdownEntityManager();
|
|
||||||
EntityManager& GetEntityManager();
|
void InitEntityManager(World* world);
|
||||||
EntityTemplate* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity);
|
void ShutdownEntityManager(void);
|
||||||
[[nodiscard]] Entity* allocate_entity(EntityManager& manager, NonNullPtr<const Class> derived_type_class);
|
EntityManager* GetEntityManager(void);
|
||||||
void UpdateEntityManager(EntityManager& manager);
|
EntityTemplate* RegisterEntity(EntityManager* manager, Entity* base, DerivedType entity);
|
||||||
[[nodiscard]] Entity* deserialize_entity(Archive& archive, EntityManager& manager);
|
Entity* allocate_entity(EntityManager* manager, const Class* derived_type_class);
|
||||||
void update_local_counter(EntityManager& manager, EntityID entity_id);
|
void UpdateEntityManager(EntityManager* manager);
|
||||||
|
Entity* deserialize_entity(Archive* archive, EntityManager* manager);
|
||||||
|
void update_local_counter(EntityManager* manager, EntityID entity_id);
|
||||||
@@ -5,17 +5,16 @@
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#define AS_STR(name) #name
|
#define AS_STR(name) #name
|
||||||
const char* kEntity_type_names[] = {
|
const char* kEntity_type_names[] = {
|
||||||
ENTITY_TYPE_LIST(AS_STR)
|
ENTITY_TYPE_LIST(AS_STR)
|
||||||
"Count"
|
"Count"
|
||||||
};
|
};
|
||||||
#undef AS_STR
|
#undef AS_STR
|
||||||
|
|
||||||
#define AS_CLASS(name) name::kind
|
#define AS_CLASS(name) &class_kind_##name
|
||||||
const Class* kEntity_type_class_ptr[]
|
const Class* kEntity_type_class_ptr[] = {
|
||||||
{
|
|
||||||
ENTITY_TYPE_LIST(AS_CLASS)
|
ENTITY_TYPE_LIST(AS_CLASS)
|
||||||
nullptr
|
NULL
|
||||||
};
|
};
|
||||||
#undef AS_CLASS
|
#undef AS_CLASS
|
||||||
// clang-format on
|
// clang-format on
|
||||||
+25
-23
@@ -1,46 +1,48 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/EnumUtils.h>
|
|
||||||
#include <Engine/Class.h>
|
#include <Engine/Class.h>
|
||||||
|
|
||||||
struct Class;
|
typedef void* DerivedType;
|
||||||
using DerivedType = void*;
|
typedef uint64 EntityID;
|
||||||
using EntityID = uint64_t;
|
|
||||||
|
|
||||||
constexpr uint8 kInvalid_user_id = 0U;
|
#define kInvalid_user_id ((uint8)0U)
|
||||||
constexpr EntityID kInvalid_entity_id = 0ULL;
|
#define kInvalid_entity_id ((EntityID)0ULL)
|
||||||
|
#define kEntityID_user_id_shift ((EntityID)56ULL)
|
||||||
constexpr EntityID kEntityID_user_id_shift = 56ULL;
|
#define kEntityID_user_id_mask ((EntityID)0xFF00000000000000ULL)
|
||||||
constexpr EntityID kEntityID_user_id_mask = 0xFF00'0000'0000'0000ULL;
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#define ENTITY_TYPE_LIST(X) X(Inert),
|
#define ENTITY_TYPE_LIST(X) X(Inert),
|
||||||
|
|
||||||
#define AS_ENUM(name) name
|
typedef uint8 Entity_Type;
|
||||||
enum class Entity_Type : uint8
|
#define AS_ENUM(name) Entity_Type_##name
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
ENTITY_TYPE_LIST(AS_ENUM)
|
ENTITY_TYPE_LIST(AS_ENUM)
|
||||||
Count
|
Entity_Type_Count
|
||||||
};
|
};
|
||||||
#undef AS_ENUM
|
#undef AS_ENUM
|
||||||
|
|
||||||
extern const char* kEntity_type_names[];
|
extern const char* kEntity_type_names[];
|
||||||
extern const Class* kEntity_type_class_ptr[];
|
extern const Class* kEntity_type_class_ptr[];
|
||||||
|
|
||||||
#define ENTITY(kind) ToUnderlying(Entity_Type::kind)
|
#define ENTITY(kind) ((uint8)Entity_Type_##kind)
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
struct Entity;
|
typedef struct Entity Entity;
|
||||||
|
|
||||||
#define DECLARE_ENTITY() \
|
#define DECLARE_ENTITY() Entity* base;
|
||||||
Entity* base; \
|
|
||||||
DECLARE_CLASS()
|
|
||||||
|
|
||||||
#define DEFINE_ENTITY_VERSIONED(entity, version) \
|
#define DEFINE_ENTITY_VERSIONED(entity, version_num) \
|
||||||
constexpr Class entityKind##entity = \
|
const Class class_kind_##entity = { \
|
||||||
MakeClass(ConstString(#entity), (uint8)Entity_Type::entity, (version), &class_kind_Entity, sizeof(entity), \
|
.Name = ConstString(#entity), \
|
||||||
alignof(entity), (&initialize_thunk<entity>), (&serialize_thunk<entity>)); \
|
.kind = (uint8)Entity_Type_##entity, \
|
||||||
Class* entity::kind = const_cast<Class*>(&entityKind##entity);
|
.version = (version_num), \
|
||||||
|
.base_class = &class_kind_Entity, \
|
||||||
|
.initialize_fct = init_##entity, \
|
||||||
|
.serialize_fct = serialize_##entity, \
|
||||||
|
.size_of = sizeof(entity), \
|
||||||
|
.alignment = AlignOf(entity) \
|
||||||
|
};
|
||||||
|
|
||||||
// Note: Needed by every classes see define above
|
// Note: Needed by every entity class (see define above)
|
||||||
extern const Class class_kind_Entity;
|
extern const Class class_kind_Entity;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include <Entity/entity_types.h>
|
||||||
|
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
|
||||||
|
internal void init_Inert(void* payload)
|
||||||
|
{
|
||||||
|
Assert(payload != NULL);
|
||||||
|
Inert* inert = (Inert*)payload;
|
||||||
|
inert->base = NULL;
|
||||||
|
inert->MeshInstance = indexMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void serialize_Inert(Archive* ar, uint16 version, void* payload)
|
||||||
|
{
|
||||||
|
(void)version;
|
||||||
|
Assert(ar != NULL);
|
||||||
|
Assert(payload != NULL);
|
||||||
|
Inert* inert = (Inert*)payload;
|
||||||
|
SERIALIZE_U64(ar, MeshInstance, &inert->MeshInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ENTITY_VERSIONED(Inert, 1)
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#include <Entity/entity_types.h>
|
|
||||||
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
|
|
||||||
DEFINE_ENTITY_VERSIONED(Inert, 1)
|
|
||||||
internal void serialize(Archive& ar, uint16 /*version*/, Inert& inert)
|
|
||||||
{
|
|
||||||
SERIALIZE(ar, MeshInstance, inert.MeshInstance);
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
#include <Entity/entity_common.h>
|
#include <Entity/entity_common.h>
|
||||||
|
|
||||||
|
typedef struct Inert Inert;
|
||||||
struct Inert
|
struct Inert
|
||||||
{
|
{
|
||||||
DECLARE_ENTITY()
|
DECLARE_ENTITY()
|
||||||
|
|
||||||
index_t MeshInstance = indexMax;
|
index_t MeshInstance;
|
||||||
};
|
};
|
||||||
|
DECLARE_CLASS(Inert)
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
#include <UnitTest/WorldUnitTest.h>
|
||||||
|
|
||||||
|
#if JULIET_DEBUG
|
||||||
|
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <Core/Common/serialization.h>
|
||||||
|
#include <Core/HAL/IO/IOStream.h>
|
||||||
|
#include <Core/Logging/LogManager.h>
|
||||||
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
#include <Core/Thread/ThreadContext.h>
|
||||||
|
#include <Data/World.h>
|
||||||
|
#include <Entity/Entity.h>
|
||||||
|
#include <Entity/entity_types.h>
|
||||||
|
#include <game.h>
|
||||||
|
|
||||||
|
internal void TestEntityAllocationAndWiring(void)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestEntityAllocationAndWiring...");
|
||||||
|
|
||||||
|
TempArena tempArena = scratch_begin(NULL, 0);
|
||||||
|
|
||||||
|
GameState* gameState = GetGameState();
|
||||||
|
World testWorld = { 0 };
|
||||||
|
gameState->World = &testWorld;
|
||||||
|
InitWorld(&testWorld, tempArena.Arena);
|
||||||
|
|
||||||
|
InitEntityManager(&testWorld);
|
||||||
|
EntityManager* manager = testWorld.EntityManager;
|
||||||
|
|
||||||
|
// 1. Allocate Inert Entity via allocate_entity
|
||||||
|
Entity* base_entity = allocate_entity(manager, ClassKind(Inert));
|
||||||
|
Assert(base_entity != NULL);
|
||||||
|
Assert(base_entity->ID == 0); // Pure memory allocator leaves ID unassigned (0) until MakeEntity or deserialization
|
||||||
|
base_entity->ID = ++g_entity_manager_id;
|
||||||
|
Assert(base_entity->ID > 0);
|
||||||
|
Assert(base_entity->derived_kind == ClassKind(Inert));
|
||||||
|
Assert(base_entity->derived != NULL);
|
||||||
|
Assert(base_entity->is_dirty == true);
|
||||||
|
|
||||||
|
// 2. Validate mutual back-pointer wiring
|
||||||
|
EntityTemplate* derived = (EntityTemplate*)base_entity->derived;
|
||||||
|
Assert(derived->base == base_entity);
|
||||||
|
|
||||||
|
// 3. DownCast verification
|
||||||
|
Inert* inert = DownCastEntity(Inert, base_entity);
|
||||||
|
Assert(inert != NULL);
|
||||||
|
Assert(inert->base == base_entity);
|
||||||
|
|
||||||
|
// 4. Validate typed array tracking
|
||||||
|
typed_entity_array* inert_array = &manager->by_type[ENTITY(Inert)];
|
||||||
|
Assert(inert_array->count == 1);
|
||||||
|
Assert(inert_array->array == derived);
|
||||||
|
|
||||||
|
ShutdownEntityManager();
|
||||||
|
ShutdownWorld(&testWorld);
|
||||||
|
|
||||||
|
gameState->World = NULL;
|
||||||
|
|
||||||
|
scratch_end(tempArena);
|
||||||
|
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestEntityAllocationAndWiring");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void TestInPlaceDeserialization(void)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestInPlaceDeserialization...");
|
||||||
|
TempArena tempArena = scratch_begin(NULL, 0);
|
||||||
|
|
||||||
|
GameState* gameState = GetGameState();
|
||||||
|
World testWorld = { 0 };
|
||||||
|
gameState->World = &testWorld;
|
||||||
|
InitWorld(&testWorld, tempArena.Arena);
|
||||||
|
|
||||||
|
InitEntityManager(&testWorld);
|
||||||
|
EntityManager* manager = testWorld.EntityManager;
|
||||||
|
// 1. In-memory .jasset text fixture (no streams or files needed)
|
||||||
|
String asset_content = ConstString("; Class\n"
|
||||||
|
"Inert\n"
|
||||||
|
"; version\n"
|
||||||
|
"1\n"
|
||||||
|
"; class_version\n"
|
||||||
|
"1\n"
|
||||||
|
"; id\n"
|
||||||
|
"42\n"
|
||||||
|
"; position\n"
|
||||||
|
"12.5 -44.0 108.2 1.0\n"
|
||||||
|
"; MeshInstance\n"
|
||||||
|
"42\n");
|
||||||
|
ByteBuffer buffer = { .Data = (Byte*)asset_content.Str, .Size = asset_content.Size };
|
||||||
|
// 2. Tokenize into Archive
|
||||||
|
Archive load_ar = { 0 };
|
||||||
|
load_ar.arena = tempArena.Arena;
|
||||||
|
load_ar.loading = true;
|
||||||
|
load_ar.base = tokenize_archive(tempArena.Arena, buffer);
|
||||||
|
// 3. Deserialize in-place
|
||||||
|
Entity* loaded_base = deserialize_entity(&load_ar, manager);
|
||||||
|
// 4. Verify in-place allocations and values
|
||||||
|
Assert(loaded_base != NULL);
|
||||||
|
Assert(loaded_base->ID == 42);
|
||||||
|
Assert(g_entity_manager_id > 42); // Generator counter advanced past loaded ID
|
||||||
|
Assert(loaded_base->position.x == 12.5f);
|
||||||
|
Assert(loaded_base->position.y == -44.0f);
|
||||||
|
Assert(loaded_base->position.z == 108.2f);
|
||||||
|
Assert(loaded_base->is_dirty == false);
|
||||||
|
Inert* loaded_inert = DownCastEntity(Inert, loaded_base);
|
||||||
|
Assert(loaded_inert != NULL);
|
||||||
|
Assert(loaded_inert->base == loaded_base);
|
||||||
|
Assert(loaded_inert->MeshInstance == 42);
|
||||||
|
ShutdownEntityManager();
|
||||||
|
ShutdownWorld(&testWorld);
|
||||||
|
|
||||||
|
gameState->World = NULL;
|
||||||
|
|
||||||
|
scratch_end(tempArena);
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestInPlaceDeserialization");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void TestDirtyTrackingLifecycle(void)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestDirtyTrackingLifecycle...");
|
||||||
|
|
||||||
|
TempArena tempArena = scratch_begin(NULL, 0);
|
||||||
|
|
||||||
|
GameState* gameState = GetGameState();
|
||||||
|
World testWorld = { 0 };
|
||||||
|
gameState->World = &testWorld;
|
||||||
|
InitWorld(&testWorld, tempArena.Arena);
|
||||||
|
|
||||||
|
InitEntityManager(&testWorld);
|
||||||
|
EntityManager* manager = testWorld.EntityManager;
|
||||||
|
|
||||||
|
Entity* entity = allocate_entity(manager, ClassKind(Inert));
|
||||||
|
Assert(entity->is_dirty == true);
|
||||||
|
|
||||||
|
// TODO : proper save and mutation
|
||||||
|
// Simulate save
|
||||||
|
entity->is_dirty = false;
|
||||||
|
Assert(entity->is_dirty == false);
|
||||||
|
|
||||||
|
// Simulate mutation
|
||||||
|
entity->position.x += 1.0f;
|
||||||
|
entity->is_dirty = true;
|
||||||
|
Assert(entity->is_dirty == true);
|
||||||
|
|
||||||
|
ShutdownEntityManager();
|
||||||
|
ShutdownWorld(&testWorld);
|
||||||
|
|
||||||
|
gameState->World = NULL;
|
||||||
|
|
||||||
|
scratch_end(tempArena);
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestDirtyTrackingLifecycle");
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitTest_WorldUnitTest(void)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "==================================================");
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "Starting Entity Allocation & Lifecycle Unit Tests");
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "==================================================");
|
||||||
|
|
||||||
|
TestEntityAllocationAndWiring();
|
||||||
|
TestInPlaceDeserialization();
|
||||||
|
// TestSwapAndPopPointerFixup(); // Deferred to Entity_Removal_Brainstorm.md
|
||||||
|
TestDirtyTrackingLifecycle();
|
||||||
|
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "==================================================");
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "All Entity Lifecycle Unit Tests PASSED Successfully");
|
||||||
|
Log(LogLevel_Message, LogCategory_Game, "==================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
#include <UnitTest/WorldUnitTest.h>
|
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
|
||||||
#include <Core/Common/serialization.h>
|
|
||||||
#include <Core/HAL/IO/IOStream.h>
|
|
||||||
#include <Core/Logging/LogManager.h>
|
|
||||||
#include <Core/Logging/LogTypes.h>
|
|
||||||
#include <Core/Memory/MemoryArena.h>
|
|
||||||
#include <Core/Thread/ThreadContext.h>
|
|
||||||
#include <Data/World.h>
|
|
||||||
#include <Entity/entity_types.h>
|
|
||||||
#include <game.h>
|
|
||||||
|
|
||||||
namespace UnitTest
|
|
||||||
{
|
|
||||||
internal void TestEntityAllocationAndWiring()
|
|
||||||
{
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestEntityAllocationAndWiring...");
|
|
||||||
|
|
||||||
TempArena tempArena = scratch_begin(nullptr, 0);
|
|
||||||
|
|
||||||
GameState* gameState = GetGameState();
|
|
||||||
World testWorld{};
|
|
||||||
gameState->World = &testWorld;
|
|
||||||
InitWorld(&testWorld, tempArena.Arena);
|
|
||||||
|
|
||||||
InitEntityManager(&testWorld);
|
|
||||||
EntityManager& manager = *testWorld.EntityManager;
|
|
||||||
|
|
||||||
// 1. Allocate Inert Entity via AllocateEntity
|
|
||||||
Entity* base_entity = allocate_entity(manager, Inert::kind);
|
|
||||||
Assert(base_entity != nullptr);
|
|
||||||
Assert(base_entity->ID == 0); // Pure memory allocator leaves ID unassigned (0) until MakeEntity or deserialization
|
|
||||||
base_entity->ID = ++EntityManager::ID;
|
|
||||||
Assert(base_entity->ID > 0);
|
|
||||||
Assert(base_entity->derived_kind == Inert::kind);
|
|
||||||
Assert(base_entity->derived != nullptr);
|
|
||||||
Assert(base_entity->is_dirty == true);
|
|
||||||
|
|
||||||
// 2. Validate mutual back-pointer wiring
|
|
||||||
auto* derived = reinterpret_cast<EntityTemplate*>(base_entity->derived);
|
|
||||||
Assert(derived->base == base_entity);
|
|
||||||
|
|
||||||
// 3. DownCast verification
|
|
||||||
Inert* inert = DownCast<Inert>(base_entity);
|
|
||||||
Assert(inert != nullptr);
|
|
||||||
Assert(inert->base == base_entity);
|
|
||||||
|
|
||||||
// 4. Validate typed array tracking
|
|
||||||
typed_entity_array& inert_array = manager.by_type[ENTITY(Inert)];
|
|
||||||
Assert(inert_array.count == 1);
|
|
||||||
Assert(inert_array.array == derived);
|
|
||||||
|
|
||||||
ShutdownEntityManager();
|
|
||||||
ShutdownWorld(&testWorld);
|
|
||||||
|
|
||||||
gameState->World = nullptr;
|
|
||||||
|
|
||||||
scratch_end(tempArena);
|
|
||||||
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestEntityAllocationAndWiring");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void TestInPlaceDeserialization()
|
|
||||||
{
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestInPlaceDeserialization...");
|
|
||||||
TempArena tempArena = scratch_begin(nullptr, 0);
|
|
||||||
|
|
||||||
GameState* gameState = GetGameState();
|
|
||||||
World testWorld{};
|
|
||||||
gameState->World = &testWorld;
|
|
||||||
InitWorld(&testWorld, tempArena.Arena);
|
|
||||||
|
|
||||||
InitEntityManager(&testWorld);
|
|
||||||
EntityManager& manager = *testWorld.EntityManager;
|
|
||||||
// 1. In-memory .jasset text fixture (no streams or files needed)
|
|
||||||
String asset_content = ConstString("; Class\n"
|
|
||||||
"Inert\n"
|
|
||||||
"; version\n"
|
|
||||||
"1\n"
|
|
||||||
"; class_version\n"
|
|
||||||
"1\n"
|
|
||||||
"; id\n"
|
|
||||||
"42\n"
|
|
||||||
"; position\n"
|
|
||||||
"12.5 -44.0 108.2 1.0\n"
|
|
||||||
"; MeshInstance\n"
|
|
||||||
"42\n");
|
|
||||||
ByteBuffer buffer = { .Data = reinterpret_cast<Byte*>(asset_content.Str), .Size = asset_content.Size };
|
|
||||||
// 2. Tokenize into Archive
|
|
||||||
Archive load_ar = {};
|
|
||||||
load_ar.arena = tempArena.Arena;
|
|
||||||
load_ar.loading = true;
|
|
||||||
load_ar.base = tokenize_archive(tempArena.Arena, buffer);
|
|
||||||
// 3. Deserialize in-place
|
|
||||||
Entity* loaded_base = deserialize_entity(load_ar, manager);
|
|
||||||
// 4. Verify in-place allocations and values
|
|
||||||
Assert(loaded_base != nullptr);
|
|
||||||
Assert(loaded_base->ID == 42);
|
|
||||||
Assert(EntityManager::ID > 42); // Generator counter advanced past loaded ID
|
|
||||||
Assert(loaded_base->position.x == 12.5f);
|
|
||||||
Assert(loaded_base->position.y == -44.0f);
|
|
||||||
Assert(loaded_base->position.z == 108.2f);
|
|
||||||
Assert(loaded_base->is_dirty == false);
|
|
||||||
Inert* loaded_inert = DownCast<Inert>(loaded_base);
|
|
||||||
Assert(loaded_inert != nullptr);
|
|
||||||
Assert(loaded_inert->base == loaded_base);
|
|
||||||
Assert(loaded_inert->MeshInstance == 42);
|
|
||||||
ShutdownEntityManager();
|
|
||||||
ShutdownWorld(&testWorld);
|
|
||||||
|
|
||||||
gameState->World = nullptr;
|
|
||||||
|
|
||||||
scratch_end(tempArena);
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestInPlaceDeserialization");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void TestDirtyTrackingLifecycle()
|
|
||||||
{
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestDirtyTrackingLifecycle...");
|
|
||||||
|
|
||||||
TempArena tempArena = scratch_begin(nullptr, 0);
|
|
||||||
|
|
||||||
GameState* gameState = GetGameState();
|
|
||||||
World testWorld{};
|
|
||||||
gameState->World = &testWorld;
|
|
||||||
InitWorld(&testWorld, tempArena.Arena);
|
|
||||||
|
|
||||||
InitEntityManager(&testWorld);
|
|
||||||
EntityManager& manager = *testWorld.EntityManager;
|
|
||||||
|
|
||||||
Entity* entity = allocate_entity(manager, Inert::kind);
|
|
||||||
Assert(entity->is_dirty == true);
|
|
||||||
|
|
||||||
// TODO : proper save and mutation
|
|
||||||
// Simulate save
|
|
||||||
entity->is_dirty = false;
|
|
||||||
Assert(entity->is_dirty == false);
|
|
||||||
|
|
||||||
// Simulate mutation
|
|
||||||
entity->position.x += 1.0f;
|
|
||||||
entity->is_dirty = true;
|
|
||||||
Assert(entity->is_dirty == true);
|
|
||||||
|
|
||||||
ShutdownEntityManager();
|
|
||||||
ShutdownWorld(&testWorld);
|
|
||||||
|
|
||||||
gameState->World = nullptr;
|
|
||||||
|
|
||||||
scratch_end(tempArena);
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestDirtyTrackingLifecycle");
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldUnitTest()
|
|
||||||
{
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "==================================================");
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "Starting Entity Allocation & Lifecycle Unit Tests");
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "==================================================");
|
|
||||||
|
|
||||||
TestEntityAllocationAndWiring();
|
|
||||||
TestInPlaceDeserialization();
|
|
||||||
// TestSwapAndPopPointerFixup(); // Deferred to Entity_Removal_Brainstorm.md
|
|
||||||
TestDirtyTrackingLifecycle();
|
|
||||||
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "==================================================");
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "All Entity Lifecycle Unit Tests PASSED Successfully");
|
|
||||||
Log(LogLevel::Message, LogCategory::Game, "==================================================");
|
|
||||||
}
|
|
||||||
} // namespace UnitTest
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
|
|
||||||
namespace UnitTest
|
void UnitTest_WorldUnitTest(void);
|
||||||
{
|
|
||||||
void WorldUnitTest();
|
|
||||||
} // namespace UnitTest
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+47
-41
@@ -13,28 +13,26 @@
|
|||||||
#include <Entity/EntityManager.h>
|
#include <Entity/EntityManager.h>
|
||||||
#include <Graphics/Camera.h>
|
#include <Graphics/Camera.h>
|
||||||
#include <Graphics/MeshRenderer.h>
|
#include <Graphics/MeshRenderer.h>
|
||||||
#include <imgui.h>
|
#include <dcimgui.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
#include <Debug/DebugTopBar.h>
|
#include <Debug/DebugTopBar.h>
|
||||||
#include <UnitTest/WorldUnitTest.h>
|
#include <UnitTest/WorldUnitTest.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace
|
global GameState* gGameState = NULL;
|
||||||
{
|
|
||||||
GameState* gGameState = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameState* GetGameState()
|
GameState* GetGameState(void)
|
||||||
{
|
{
|
||||||
return gGameState;
|
return gGameState;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JULIET_API void __cdecl GameShutdown()
|
JULIET_API void __cdecl GameShutdown(void)
|
||||||
{
|
{
|
||||||
printf("Shutting down game...\n");
|
printf("Shutting down game...\n");
|
||||||
|
|
||||||
if (gGameState && gGameState->World)
|
if (gGameState != NULL && gGameState->World != NULL)
|
||||||
{
|
{
|
||||||
ShutdownWorld(gGameState->World);
|
ShutdownWorld(gGameState->World);
|
||||||
}
|
}
|
||||||
@@ -42,47 +40,55 @@ extern "C" JULIET_API void __cdecl GameShutdown()
|
|||||||
ShutdownEntityManager();
|
ShutdownEntityManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JULIET_API void __cdecl GameUpdate(GameData* params, [[maybe_unused]] float deltaTime)
|
JULIET_API void __cdecl GameUpdate(GameData* params, float deltaTime)
|
||||||
{
|
{
|
||||||
|
Assert(params != NULL);
|
||||||
|
|
||||||
gGameState = params->GameState;
|
gGameState = params->GameState;
|
||||||
if (!gGameState)
|
if (gGameState == NULL)
|
||||||
{
|
{
|
||||||
Arena* gameStateArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "Game Total Arena" });
|
ArenaParams gameStateParams = { .ReserveSize = Megabytes(1), .Name = "Game Total Arena" };
|
||||||
auto* gameState = ArenaPushStruct<GameState>(gameStateArena);
|
Arena* gameStateArena = ArenaAllocate(gameStateParams);
|
||||||
|
GameState* gameState = ArenaPushStruct(gameStateArena, GameState);
|
||||||
gGameState = params->GameState = gameState;
|
gGameState = params->GameState = gameState;
|
||||||
gameState->TotalArena = gameStateArena;
|
gameState->TotalArena = gameStateArena;
|
||||||
|
gameState->Mode = GameMode_Editor;
|
||||||
|
|
||||||
gameState->TotalTime = 0.0f;
|
gameState->TotalTime = 0.0f;
|
||||||
gameState->Score = 0;
|
gameState->Score = 0;
|
||||||
|
|
||||||
printf("Game Arena Allocated: %p\n", static_cast<void*>(gameState));
|
printf("Game Arena Allocated: %p\n", (void*)gameState);
|
||||||
|
|
||||||
// Reserve cameras. Lets go with 4 for now
|
// Reserve cameras. Lets go with 4 for now
|
||||||
ReserveCamera(4);
|
ReserveCamera(4);
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
UnitTest::WorldUnitTest();
|
UnitTest_WorldUnitTest();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Bootstrap world
|
// Bootstrap world
|
||||||
auto* worldArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "World Arena" });
|
ArenaParams worldParams = { .ReserveSize = Megabytes(1), .Name = "World Arena" };
|
||||||
World* world = ArenaPushStruct<World>(worldArena JULIET_DEBUG_PARAM("World"));
|
Arena* worldArena = ArenaAllocate(worldParams);
|
||||||
|
World* world = ArenaPushStructTag(worldArena, World, "World");
|
||||||
gameState->World = world;
|
gameState->World = world;
|
||||||
InitWorld(gameState->World, worldArena);
|
InitWorld(gameState->World, worldArena);
|
||||||
|
|
||||||
// Entity Use case
|
// Entity Use case
|
||||||
InitEntityManager(gameState->World);
|
InitEntityManager(gameState->World);
|
||||||
auto& manager = GetEntityManager();
|
EntityManager* manager = GetEntityManager();
|
||||||
|
|
||||||
NonNullPtr mesh = MakeEntity<Inert>(manager, 1.f, 2.f, 0.f);
|
Inert* mesh = MakeEntity(Inert, manager, 1.f, 2.f, 0.f);
|
||||||
|
Assert(mesh != NULL);
|
||||||
|
|
||||||
MeshAssetID cubeAsset = GetCubePrimitiveMeshAssetID();
|
MeshAssetID cubeAsset = GetCubePrimitiveMeshAssetID();
|
||||||
MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, MatrixIdentity());
|
Matrix identity = MatrixIdentity();
|
||||||
|
MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, &identity);
|
||||||
mesh->MeshInstance = meshInst;
|
mesh->MeshInstance = meshInst;
|
||||||
|
|
||||||
NonNullPtr mesh2 = MakeEntity<Inert>(manager, 4.f, 0.f, 2.f);
|
Inert* mesh2 = MakeEntity(Inert, manager, 4.f, 0.f, 2.f);
|
||||||
|
Assert(mesh2 != NULL);
|
||||||
|
|
||||||
MeshInstanceID meshInst2 = CreateMeshInstance(cubeAsset, 0, MatrixIdentity());
|
MeshInstanceID meshInst2 = CreateMeshInstance(cubeAsset, 0, &identity);
|
||||||
mesh2->MeshInstance = meshInst2;
|
mesh2->MeshInstance = meshInst2;
|
||||||
|
|
||||||
// Summer at 2pm lighting
|
// Summer at 2pm lighting
|
||||||
@@ -97,64 +103,64 @@ extern "C" JULIET_API void __cdecl GameUpdate(GameData* params, [[maybe_unused]]
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
GameMode previousFrameMode = gGameState->Mode;
|
GameMode previousFrameMode = gGameState->Mode;
|
||||||
if (IsKeyPressed(ScanCode::F1))
|
if (IsKeyPressed(ScanCode_F1))
|
||||||
{
|
{
|
||||||
if (previousFrameMode == GameMode::Play)
|
if (previousFrameMode == GameMode_Play)
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Debug;
|
gGameState->Mode = GameMode_Debug;
|
||||||
}
|
}
|
||||||
else if (previousFrameMode == GameMode::Debug)
|
else if (previousFrameMode == GameMode_Debug)
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Play;
|
gGameState->Mode = GameMode_Play;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gGameState->Mode == GameMode::Editor)
|
if (gGameState->Mode == GameMode_Editor)
|
||||||
{
|
{
|
||||||
if (IsKeyPressed(ScanCode::F5))
|
if (IsKeyPressed(ScanCode_F5))
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Play;
|
gGameState->Mode = GameMode_Play;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JULIET_EDITOR
|
#if JULIET_EDITOR
|
||||||
RenderWorldEditorUI(*gGameState->World);
|
RenderWorldEditorUI(gGameState->World);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gGameState->Mode == GameMode::Play)
|
if (gGameState->Mode == GameMode_Play)
|
||||||
{
|
{
|
||||||
if (IsKeyPressed(ScanCode::Escape))
|
if (IsKeyPressed(ScanCode_Escape))
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Editor;
|
gGameState->Mode = GameMode_Editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update game
|
// update game
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& manager = GetEntityManager();
|
EntityManager* manager = GetEntityManager();
|
||||||
UpdateEntityManager(manager);
|
UpdateEntityManager(manager);
|
||||||
|
|
||||||
if (gGameState->Mode == GameMode::Debug)
|
if (gGameState->Mode == GameMode_Debug)
|
||||||
{
|
{
|
||||||
if (previousFrameMode == GameMode::Play)
|
if (previousFrameMode == GameMode_Play)
|
||||||
{
|
{
|
||||||
ActivateDebugController();
|
ActivateDebugController();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsKeyPressed(ScanCode::Escape))
|
if (IsKeyPressed(ScanCode_Escape))
|
||||||
{
|
{
|
||||||
gGameState->Mode = GameMode::Editor;
|
gGameState->Mode = GameMode_Editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateDebugController(deltaTime);
|
UpdateDebugController(deltaTime);
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
ImGui::Begin("Debug");
|
ImGui_Begin("Debug", NULL, ImGuiWindowFlags_None);
|
||||||
RenderImGuiDebugController(deltaTime);
|
RenderImGuiDebugController(deltaTime);
|
||||||
ImGui::End();
|
ImGui_End();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (gGameState->Mode != GameMode::Debug && previousFrameMode == GameMode::Debug)
|
if (gGameState->Mode != GameMode_Debug && previousFrameMode == GameMode_Debug)
|
||||||
{
|
{
|
||||||
DeactivateDebugController();
|
DeactivateDebugController();
|
||||||
}
|
}
|
||||||
+13
-11
@@ -3,25 +3,27 @@
|
|||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
#include <Data/World.h>
|
#include <Data/World.h>
|
||||||
|
|
||||||
struct EntityManager;
|
typedef struct EntityManager EntityManager;
|
||||||
|
|
||||||
enum class GameMode
|
typedef uint32 GameMode;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Editor,
|
GameMode_Editor = 0,
|
||||||
Play,
|
GameMode_Play,
|
||||||
Debug
|
GameMode_Debug
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct GameState GameState;
|
||||||
struct GameState
|
struct GameState
|
||||||
{
|
{
|
||||||
Arena* TotalArena = nullptr;
|
Arena* TotalArena;
|
||||||
|
|
||||||
World* World = nullptr;
|
World* World;
|
||||||
|
|
||||||
GameMode Mode = GameMode::Editor;
|
GameMode Mode;
|
||||||
|
|
||||||
float TotalTime = 0.0f;
|
float TotalTime;
|
||||||
int Score = 0;
|
int Score;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] extern GameState* GetGameState();
|
extern GameState* GetGameState(void);
|
||||||
@@ -1,658 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="src">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Application">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Common">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Container">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Display">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Display\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\DynLib">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\DynLib\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Event">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Filesystem">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\Filesystem\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\IO">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\IO\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\OS">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HAL\OS\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HotReload">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\HotReload\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\ImGui">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Logging">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Math">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Memory">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Networking">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Core\Networking\Win32">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Engine">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Engine\Debug">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Graphics">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Graphics\D3D12">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Graphics\D3D12\AgilitySDK">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\Graphics\D3D12\AgilitySDK\d3dx12">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\UnitTest">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="src\UnitTest\Container">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Application">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Common">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Container">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Display">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\DynLib">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Event">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Filesystem">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\IO">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Keyboard">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\Mouse">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HAL\OS">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\HotReload">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\ImGui">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Logging">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Math">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Memory">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Networking">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Core\Thread">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Engine">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Engine\Debug">
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="include\Graphics">
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="src\Core\Application\ApplicationManager.cpp">
|
|
||||||
<Filter>src\Core\Application</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Common\CoreUtils.cpp">
|
|
||||||
<Filter>src\Core\Common</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Common\String.cpp">
|
|
||||||
<Filter>src\Core\Common</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Container\Vector.cpp">
|
|
||||||
<Filter>src\Core\Container</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Display\Display.cpp">
|
|
||||||
<Filter>src\Core\HAL\Display</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayDevice.cpp">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.cpp">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32Window.cpp">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\DynLib\Win32\DynamicLibrary.cpp">
|
|
||||||
<Filter>src\Core\HAL\DynLib\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\Keyboard.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\KeyboardMapping.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\Mouse.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\SystemEvent.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Event\WindowEvent.cpp">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Filesystem\Filesystem.cpp">
|
|
||||||
<Filter>src\Core\HAL\Filesystem</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\Filesystem\Win32\Win32Filesystem.cpp">
|
|
||||||
<Filter>src\Core\HAL\Filesystem\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\IO\IOStream.cpp">
|
|
||||||
<Filter>src\Core\HAL\IO</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\IO\Win32\Win32IOStream.cpp">
|
|
||||||
<Filter>src\Core\HAL\IO\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\OS\OS.cpp">
|
|
||||||
<Filter>src\Core\HAL\OS</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HAL\OS\Win32\Win32OS.cpp">
|
|
||||||
<Filter>src\Core\HAL\OS\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HotReload\HotReload.cpp">
|
|
||||||
<Filter>src\Core\HotReload</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\HotReload\Win32\Win32HotReload.cpp">
|
|
||||||
<Filter>src\Core\HotReload\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\ImGui\ImGuiService.cpp">
|
|
||||||
<Filter>src\Core\ImGui</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\ImGui\ImGuiTests.cpp">
|
|
||||||
<Filter>src\Core\ImGui</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Juliet.cpp">
|
|
||||||
<Filter>src\Core</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Logging\LogManager.cpp">
|
|
||||||
<Filter>src\Core\Logging</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Math\MathRound.cpp">
|
|
||||||
<Filter>src\Core\Math</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\Allocator.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\MemoryArena.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\MemoryArenaDebug.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\MemoryArenaTests.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Memory\ScratchArena.cpp">
|
|
||||||
<Filter>src\Core\Memory</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\NetworkPacket.cpp">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\Socket.cpp">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\TcpListener.cpp">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\TcpSocket.cpp">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp">
|
|
||||||
<Filter>src\Core\Networking\Win32</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Core\PCH.cpp">
|
|
||||||
<Filter>src\Core</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Engine\Debug\MemoryDebugger.cpp">
|
|
||||||
<Filter>src\Engine\Debug</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Engine\Engine.cpp">
|
|
||||||
<Filter>src\Engine</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_property_format_table.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Buffer.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12CommandList.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Common.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12DescriptorHeap.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12GraphicsDevice.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12GraphicsPipeline.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12InternalTests.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12RenderPass.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Shader.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12SwapChain.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Synchronization.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Texture.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Utils.cpp">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\DebugDisplayRenderer.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\Graphics.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\ImGuiRenderer.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\Mesh.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\MeshRenderer.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Graphics\SkyboxRenderer.cpp">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\UnitTest\Container\VectorUnitTest.cpp">
|
|
||||||
<Filter>src\UnitTest\Container</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\UnitTest\RunUnitTests.cpp">
|
|
||||||
<Filter>src\UnitTest</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClInclude Include="include\Core\Application\ApplicationManager.h">
|
|
||||||
<Filter>include\Core\Application</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Application\IApplication.h">
|
|
||||||
<Filter>include\Core\Application</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\CoreTypes.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\CoreUtils.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\CRC32.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\EnumUtils.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\NonNullPtr.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Common\String.h">
|
|
||||||
<Filter>include\Core\Common</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Container\Vector.h">
|
|
||||||
<Filter>include\Core\Container</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Display\Display.h">
|
|
||||||
<Filter>include\Core\HAL\Display</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\DynLib\DynamicLibrary.h">
|
|
||||||
<Filter>include\Core\HAL\DynLib</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Event\SystemEvent.h">
|
|
||||||
<Filter>include\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Filesystem\Filesystem.h">
|
|
||||||
<Filter>include\Core\HAL\Filesystem</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\IO\IOStream.h">
|
|
||||||
<Filter>include\Core\HAL\IO</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Keyboard\Keyboard.h">
|
|
||||||
<Filter>include\Core\HAL\Keyboard</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Keyboard\KeyCode.h">
|
|
||||||
<Filter>include\Core\HAL\Keyboard</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Keyboard\ScanCode.h">
|
|
||||||
<Filter>include\Core\HAL\Keyboard</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\Mouse\Mouse.h">
|
|
||||||
<Filter>include\Core\HAL\Mouse</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HAL\OS\OS.h">
|
|
||||||
<Filter>include\Core\HAL\OS</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\HotReload\HotReload.h">
|
|
||||||
<Filter>include\Core\HotReload</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\ImGui\ImGuiService.h">
|
|
||||||
<Filter>include\Core\ImGui</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\ImGui\ImGuiTests.h">
|
|
||||||
<Filter>include\Core\ImGui</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\JulietInit.h">
|
|
||||||
<Filter>include\Core</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Logging\LogManager.h">
|
|
||||||
<Filter>include\Core\Logging</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Logging\LogTypes.h">
|
|
||||||
<Filter>include\Core\Logging</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Main.h">
|
|
||||||
<Filter>include\Core</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Math\MathUtils.h">
|
|
||||||
<Filter>include\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Math\Matrix.h">
|
|
||||||
<Filter>include\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Math\Shape.h">
|
|
||||||
<Filter>include\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Math\Vector.h">
|
|
||||||
<Filter>include\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\Allocator.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\MemoryArena.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\MemoryArenaDebug.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\ScratchArena.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Memory\Utils.h">
|
|
||||||
<Filter>include\Core\Memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\IPAddress.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\NetworkPacket.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\Socket.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\SocketHandle.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\TcpListener.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Networking\TcpSocket.h">
|
|
||||||
<Filter>include\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\PCH.h">
|
|
||||||
<Filter>include\Core</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Thread\Mutex.h">
|
|
||||||
<Filter>include\Core\Thread</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Core\Thread\Thread.h">
|
|
||||||
<Filter>include\Core\Thread</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Engine\Class.h">
|
|
||||||
<Filter>include\Engine</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Engine\Debug\MemoryDebugger.h">
|
|
||||||
<Filter>include\Engine\Debug</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Engine\Engine.h">
|
|
||||||
<Filter>include\Engine</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Camera.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Colors.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\DebugDisplay.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Graphics.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\GraphicsBuffer.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\GraphicsConfig.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\GraphicsPipeline.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\ImGuiRenderer.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Lighting.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Mesh.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\MeshRenderer.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\PushConstants.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\RenderPass.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Shader.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\SkyboxRenderer.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\Texture.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Graphics\VertexData.h">
|
|
||||||
<Filter>include\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\Juliet.h">
|
|
||||||
<Filter>include</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\DisplayDevice.h">
|
|
||||||
<Filter>src\Core\HAL\Display</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\Display_Private.h">
|
|
||||||
<Filter>src\Core\HAL\Display</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.h">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\Win32\Win32Window.h">
|
|
||||||
<Filter>src\Core\HAL\Display\Win32</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Display\Window.h">
|
|
||||||
<Filter>src\Core\HAL\Display</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\KeyboardMapping.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\Keyboard_Private.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\Mouse_Private.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\Win32ScanCode.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h">
|
|
||||||
<Filter>src\Core\HAL\Event</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Platform.h">
|
|
||||||
<Filter>src\Core\HAL\Filesystem</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Private.h">
|
|
||||||
<Filter>src\Core\HAL\Filesystem</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\IO\IOStream_Private.h">
|
|
||||||
<Filter>src\Core\HAL\IO</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\OS\OS_Private.h">
|
|
||||||
<Filter>src\Core\HAL\OS</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\HAL\Win32.h">
|
|
||||||
<Filter>src\Core\HAL</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\Math\Math_Private.h">
|
|
||||||
<Filter>src\Core\Math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h">
|
|
||||||
<Filter>src\Core\Networking</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12compatibility.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12sdklayers.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12shader.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12video.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dcommon.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_barriers.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_check_feature_support.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_core.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_default.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_pipeline_state_stream.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_property_format_table.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_render_pass.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_resource_helpers.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_root_signature.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_state_object.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\dxgiformat.h">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Buffer.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12CommandList.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Common.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12DescriptorHeap.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12GraphicsDevice.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12GraphicsPipeline.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Includes.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12InternalTests.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12RenderPass.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Shader.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12SwapChain.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Synchronization.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Texture.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Utils.h">
|
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\GraphicsDevice.h">
|
|
||||||
<Filter>src\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\UnitTest\VectorTestHelper.h">
|
|
||||||
<Filter>src\UnitTest</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\D3D12TokenizedProgramFormat.hpp">
|
|
||||||
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Application/IApplication.h>
|
|
||||||
#include <Juliet.h>
|
|
||||||
|
|
||||||
enum class JulietInit_Flags : uint8;
|
|
||||||
|
|
||||||
struct Arena;
|
|
||||||
extern JULIET_API void StartApplication(IApplication& app, JulietInit_Flags flags);
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
|
|
||||||
struct Camera;
|
|
||||||
struct RenderPass;
|
|
||||||
struct CommandList;
|
|
||||||
struct Texture;
|
|
||||||
struct ColorTargetInfo;
|
|
||||||
struct DepthStencilTargetInfo;
|
|
||||||
struct Arena;
|
|
||||||
|
|
||||||
class IApplication
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~IApplication() = default;
|
|
||||||
virtual void Init(NonNullPtr<Arena> arena) = 0;
|
|
||||||
virtual void Shutdown() = 0;
|
|
||||||
virtual void Update(float deltaTime) = 0;
|
|
||||||
virtual bool IsRunning() = 0;
|
|
||||||
|
|
||||||
// Accessors for Engine Systems
|
|
||||||
virtual struct Window* GetPlatformWindow() = 0;
|
|
||||||
virtual struct GraphicsDevice* GetGraphicsDevice() = 0;
|
|
||||||
|
|
||||||
// Render Lifecycle (Engine-Managed Render Loop)
|
|
||||||
virtual ColorTargetInfo GetColorTargetInfo(Texture* swapchainTexture) = 0;
|
|
||||||
virtual DepthStencilTargetInfo* GetDepthTargetInfo() = 0;
|
|
||||||
};
|
|
||||||
@@ -1,62 +1,60 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
// From https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
|
// From https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
|
||||||
|
|
||||||
namespace details
|
global const uint32 g_crc32_tab[256] = {
|
||||||
{
|
0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u, 0x0edb8832u,
|
||||||
constexpr uint32_t crc32_tab[] = {
|
0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u, 0x1db71064u, 0x6ab020f2u,
|
||||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
|
0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u, 0x136c9856u, 0x646ba8c0u, 0xfd62f97au,
|
||||||
0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u, 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u,
|
||||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a,
|
0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu, 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u,
|
||||||
0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u, 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u,
|
||||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
0xcfba9599u, 0xb8bda50fu, 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu,
|
||||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
0xb6662d3du, 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u,
|
||||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
|
0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u, 0x6b6b51f4u,
|
||||||
0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u, 0x65b0d9c6u, 0x12b7e950u,
|
||||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
|
0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u, 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u,
|
||||||
0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu, 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u,
|
||||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074,
|
0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u, 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u,
|
||||||
0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
0x206f85b3u, 0xb966d409u, 0xce61e49fu, 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u,
|
||||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525,
|
0xb7bd5c3bu, 0xc0ba6cadu, 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u,
|
||||||
0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
0x73dc1683u, 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
|
||||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u, 0xfed41b76u,
|
||||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u, 0xd6d6a3e8u, 0xa1d1937eu,
|
||||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76,
|
0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu, 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u,
|
||||||
0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u, 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u,
|
||||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6,
|
0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu, 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u,
|
||||||
0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du, 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu,
|
||||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
|
0x72076785u, 0x05005713u, 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u,
|
||||||
0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
0x0bdbdf21u, 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
|
||||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7,
|
0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u, 0xa00ae278u,
|
||||||
0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu, 0xaed16a4au, 0xd9d65adcu,
|
||||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u, 0xbdbdf21cu, 0xcabac28au, 0x53b39330u,
|
||||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu, 0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u,
|
||||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330,
|
0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du
|
||||||
0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
};
|
||||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr uint32 crc32(const char* str, size_t length)
|
static inline uint32 crc32_bytes(const char* str, size_t length)
|
||||||
{
|
{
|
||||||
Assert(str && length > 0);
|
Assert(str != NULL && length > 0);
|
||||||
const char* p = str;
|
const char* p = str;
|
||||||
uint32_t crc = ~0U;
|
uint32 crc = ~0U;
|
||||||
while (length--)
|
while (length--)
|
||||||
{
|
{
|
||||||
crc = details::crc32_tab[(crc ^ static_cast<uint8>(*p++)) & 0xFF] ^ (crc >> 8);
|
crc = g_crc32_tab[(crc ^ (uint8)(*p++)) & 0xFFu] ^ (crc >> 8);
|
||||||
}
|
}
|
||||||
return crc ^ ~0U;
|
return crc ^ ~0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint32 crc32(String str)
|
static inline uint32 crc32_str(String str)
|
||||||
{
|
{
|
||||||
return crc32(str.Str, str.Size);
|
return crc32_bytes(str.Str, str.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
consteval uint32 operator""_crc32(const char* str, size_t length)
|
static inline uint32 crc32_cstr(const char* str)
|
||||||
{
|
{
|
||||||
return crc32(str, length);
|
return crc32_bytes(str, StringLengthCStr(str));
|
||||||
}
|
}
|
||||||
@@ -1,65 +1,68 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
using uint8 = uint8_t;
|
#include <limits.h>
|
||||||
using uint16 = uint16_t;
|
#include <stddef.h>
|
||||||
using uint32 = uint32_t;
|
#include <stdint.h>
|
||||||
using uint64 = uint64_t;
|
|
||||||
|
|
||||||
using int8 = int8_t;
|
typedef uint8_t uint8;
|
||||||
using int16 = int16_t;
|
typedef uint16_t uint16;
|
||||||
using int32 = int32_t;
|
typedef uint32_t uint32;
|
||||||
using int64 = int64_t;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
using Byte = std::byte;
|
typedef int8_t int8;
|
||||||
|
typedef int16_t int16;
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef int64_t int64;
|
||||||
|
|
||||||
using size_t = std::size_t;
|
typedef uint8 bool8;
|
||||||
using index_t = size_t;
|
typedef uint16 bool16;
|
||||||
|
typedef uint32 bool32;
|
||||||
|
typedef uint64 bool64;
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#ifndef true
|
||||||
|
#define true 1
|
||||||
|
#endif
|
||||||
|
#ifndef false
|
||||||
|
#define false 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef uint8 Byte;
|
||||||
|
typedef size_t index_t;
|
||||||
|
|
||||||
|
typedef struct ByteBuffer ByteBuffer;
|
||||||
struct ByteBuffer
|
struct ByteBuffer
|
||||||
{
|
{
|
||||||
Byte* Data;
|
Byte* Data;
|
||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ptrdiff_t = decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr));
|
typedef void (*FunctionPtr)(void);
|
||||||
|
|
||||||
using FunctionPtr = auto (*)(void) -> void;
|
#define uint8Max ((uint8)0xFFu)
|
||||||
|
#define uint16Max ((uint16)0xFFFFu)
|
||||||
|
#define uint32Max ((uint32)0xFFFFFFFFu)
|
||||||
|
#define uint64Max ((uint64)0xFFFFFFFFFFFFFFFFull)
|
||||||
|
|
||||||
// Limits
|
#define int8Max ((int8)0x7F)
|
||||||
template <typename Type>
|
#define int16Max ((int16)0x7FFF)
|
||||||
consteval Type MaxValueOf()
|
#define int32Max ((int32)0x7FFFFFFF)
|
||||||
{
|
#define int64Max ((int64)0x7FFFFFFFFFFFFFFFll)
|
||||||
return std::numeric_limits<Type>::max();
|
|
||||||
}
|
|
||||||
constexpr uint8 uint8Max = MaxValueOf<uint8>();
|
|
||||||
constexpr uint16 uint16Max = MaxValueOf<uint16>();
|
|
||||||
constexpr uint32 uint32Max = MaxValueOf<uint32>();
|
|
||||||
constexpr uint64 uint64Max = MaxValueOf<uint64>();
|
|
||||||
|
|
||||||
constexpr int8 int8Max = MaxValueOf<int8>();
|
#define indexMax ((index_t)SIZE_MAX)
|
||||||
constexpr int16 int16Max = MaxValueOf<int16>();
|
|
||||||
constexpr int32 int32Max = MaxValueOf<int32>();
|
|
||||||
constexpr int64 int64Max = MaxValueOf<int64>();
|
|
||||||
|
|
||||||
constexpr index_t indexMax = MaxValueOf<index_t>();
|
#define uint8Min ((uint8)0u)
|
||||||
|
#define uint16Min ((uint16)0u)
|
||||||
|
#define uint32Min ((uint32)0u)
|
||||||
|
#define uint64Min ((uint64)0ull)
|
||||||
|
|
||||||
template <typename Type>
|
#define int8Min ((int8)(-128))
|
||||||
consteval Type MinValueOf()
|
#define int16Min ((int16)(-32768))
|
||||||
{
|
#define int32Min ((int32)(-2147483647 - 1))
|
||||||
return std::numeric_limits<Type>::lowest();
|
#define int64Min ((int64)(-9223372036854775807ll - 1ll))
|
||||||
}
|
|
||||||
|
|
||||||
constexpr uint8 uint8Min = MinValueOf<uint8>();
|
#define indexMin ((index_t)0u)
|
||||||
constexpr uint16 uint16Min = MinValueOf<uint16>();
|
|
||||||
constexpr uint32 uint32Min = MinValueOf<uint32>();
|
|
||||||
constexpr uint64 uint64Min = MinValueOf<uint64>();
|
|
||||||
|
|
||||||
constexpr int8 int8Min = MinValueOf<int8>();
|
#define Kilobytes(value) ((uint64)(value) * 1024ull)
|
||||||
constexpr int16 int16Min = MinValueOf<int16>();
|
#define Megabytes(value) (Kilobytes(value) * 1024ull)
|
||||||
constexpr int32 int32Min = MinValueOf<int32>();
|
|
||||||
constexpr int64 int64Min = MinValueOf<int64>();
|
|
||||||
|
|
||||||
constexpr index_t indexMin = MinValueOf<index_t>();
|
|
||||||
|
|
||||||
#define Kilobytes(value) value * 1024
|
|
||||||
#define Megabytes(value) Kilobytes(value) * 1024
|
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
#define global static
|
#define global static
|
||||||
#define internal static
|
#define internal static
|
||||||
|
|
||||||
|
#define Glue_(A, B) A##B
|
||||||
|
#define Glue(A, B) Glue_(A, B)
|
||||||
|
#define StaticAssert(C, ID) global uint8 Glue(ID, __LINE__)[(C) ? 1 : -1]
|
||||||
|
|
||||||
// 1. Stringify helpers
|
// 1. Stringify helpers
|
||||||
#define JULIET_STR(x) #x
|
#define JULIET_STR(x) #x
|
||||||
#define JULIET_TOSTRING(x) JULIET_STR(x)
|
#define JULIET_TOSTRING(x) JULIET_STR(x)
|
||||||
@@ -37,10 +42,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
// MSVC specific intrinsic
|
|
||||||
#define JULIET_PLATFORM_BREAK() (__nop(), __debugbreak())
|
#define JULIET_PLATFORM_BREAK() (__nop(), __debugbreak())
|
||||||
#elif defined(__clang__) || defined(__GNUC__)
|
#elif defined(__clang__) || defined(__GNUC__)
|
||||||
// Clang/GCC specific intrinsic
|
|
||||||
#define JULIET_PLATFORM_BREAK() __builtin_trap()
|
#define JULIET_PLATFORM_BREAK() __builtin_trap()
|
||||||
#else
|
#else
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -49,18 +52,14 @@
|
|||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
#define JULIET_ASSERT_INTERNAL(expression, message) \
|
#define JULIET_ASSERT_INTERNAL(expression, message) \
|
||||||
JULIET_WARNING_PUSH \
|
do \
|
||||||
JULIET_SUPPRESS_CLANG("-Wextra-semi-stmt") \
|
|
||||||
JULIET_SUPPRESS_MSVC(4127) \
|
|
||||||
JULIET_SUPPRESS_MSVC(4548) \
|
|
||||||
{ \
|
{ \
|
||||||
if (!(expression)) [[unlikely]] \
|
if (!(expression)) \
|
||||||
{ \
|
{ \
|
||||||
JulietAssert(#expression, message); \
|
JulietAssert(#expression, message, __FILE__, __func__, (uint32)__LINE__, 0); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
JULIET_WARNING_POP \
|
while (0)
|
||||||
static_assert(true, "")
|
|
||||||
|
|
||||||
#define AssertHR(hr_expression, message) \
|
#define AssertHR(hr_expression, message) \
|
||||||
do \
|
do \
|
||||||
@@ -68,7 +67,7 @@
|
|||||||
long hr_val = (hr_expression); \
|
long hr_val = (hr_expression); \
|
||||||
if (hr_val < 0) \
|
if (hr_val < 0) \
|
||||||
{ \
|
{ \
|
||||||
JulietAssert(#hr_expression, message, std::source_location::current(), hr_val); \
|
JulietAssert(#hr_expression, message, __FILE__, __func__, (uint32)__LINE__, hr_val); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
@@ -80,7 +79,7 @@
|
|||||||
#define Unimplemented() \
|
#define Unimplemented() \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
JulietAssert("UNIMPLEMENTED", "This code path is not yet functional."); \
|
JulietAssert("UNIMPLEMENTED", "This code path is not yet functional.", __FILE__, __func__, (uint32)__LINE__, 0); \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
@@ -90,85 +89,60 @@
|
|||||||
#define Unimplemented() ((void)0)
|
#define Unimplemented() ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JULIET_API extern void JulietAssert(const char* expression, const char* message,
|
JULIET_API extern void JulietAssert(const char* expression, const char* message, const char* file, const char* function,
|
||||||
std::source_location location = std::source_location::current(), long handleResult = 0);
|
uint32 line, long handle_result);
|
||||||
|
|
||||||
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
|
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
|
||||||
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
|
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
|
||||||
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
|
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), (Pointer))
|
||||||
inline void ZeroSize(size_t size, void* ptr)
|
|
||||||
|
static inline void ZeroSize(size_t size, void* ptr)
|
||||||
{
|
{
|
||||||
auto Byte = (uint8*)ptr;
|
uint8* byte_ptr = (uint8*)ptr;
|
||||||
while (size--)
|
while (size--)
|
||||||
{
|
{
|
||||||
*Byte++ = 0;
|
*byte_ptr++ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Restrict __restrict
|
#define Restrict __restrict
|
||||||
|
|
||||||
template <class Function>
|
static inline bool8 IsValidByteBuffer(ByteBuffer buffer)
|
||||||
class DeferredFunction
|
|
||||||
{
|
{
|
||||||
public:
|
return (buffer.Size > 0 && buffer.Data != NULL);
|
||||||
explicit DeferredFunction(const Function& otherFct) noexcept
|
|
||||||
: Callback(otherFct)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit DeferredFunction(Function&& otherFct) noexcept
|
|
||||||
: Callback(std::move(otherFct))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~DeferredFunction() noexcept { Callback(); }
|
|
||||||
|
|
||||||
DeferredFunction(const DeferredFunction&) = delete;
|
|
||||||
DeferredFunction(const DeferredFunction&&) = delete;
|
|
||||||
void operator=(const DeferredFunction&) = delete;
|
|
||||||
void operator=(DeferredFunction&&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Function Callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Function>
|
|
||||||
auto Defer(Function&& fct) noexcept
|
|
||||||
{
|
|
||||||
return DeferredFunction<std::decay_t<Function>>{ std::forward<Function>(fct) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsValid(ByteBuffer buffer)
|
extern JULIET_API void FreeByteBuffer(ByteBuffer* buffer);
|
||||||
|
|
||||||
|
static inline bool8 IsPow2(uint64 x)
|
||||||
{
|
{
|
||||||
return buffer.Size > 0 && buffer.Data;
|
return (x != 0) && ((x & (x - 1)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern JULIET_API void Free(ByteBuffer& buffer);
|
static inline uint64 AlignPow2(uint64 x, uint64 alignment)
|
||||||
|
|
||||||
template <std::integral T>
|
|
||||||
[[nodiscard]] constexpr T AlignPow2(T x, T alignment)
|
|
||||||
{
|
{
|
||||||
// Safety Check:
|
Assert(IsPow2(alignment));
|
||||||
Assert(std::has_single_bit(static_cast<size_t>(alignment)));
|
|
||||||
|
|
||||||
return (x + alignment - 1) & ~(alignment - 1);
|
return (x + alignment - 1) & ~(alignment - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
static inline void SwapMemory(void* Restrict a, void* Restrict b, size_t elem_size)
|
||||||
inline void Swap(T* Restrict a, T* Restrict b)
|
|
||||||
{
|
{
|
||||||
T temp = std::move(*a);
|
uint8* pa = (uint8*)a;
|
||||||
*a = std::move(*b);
|
uint8* pb = (uint8*)b;
|
||||||
*b = std::move(temp);
|
for (size_t i = 0; i < elem_size; ++i)
|
||||||
|
{
|
||||||
|
uint8 tmp = pa[i];
|
||||||
|
pa[i] = pb[i];
|
||||||
|
pb[i] = tmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to another file dedicated to those
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define COMPILER_CLANG 1
|
#define COMPILER_CLANG 1
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define COMPILER_MSVC 1
|
#define COMPILER_MSVC 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Undef anything not defined
|
|
||||||
#if !defined(COMPILER_CLANG)
|
#if !defined(COMPILER_CLANG)
|
||||||
#define COMPILER_CLANG 0
|
#define COMPILER_CLANG 0
|
||||||
#endif
|
#endif
|
||||||
@@ -186,42 +160,33 @@ inline void Swap(T* Restrict a, T* Restrict b)
|
|||||||
#error AlignOf not defined for this compiler.
|
#error AlignOf not defined for this compiler.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
#if COMPILER_MSVC || (COMPILER_CLANG && defined(_MSC_VER))
|
||||||
[[nodiscard]] constexpr const char* GetTypeName()
|
#define ThreadLocal __declspec(thread)
|
||||||
{
|
|
||||||
#if COMPILER_CLANG
|
|
||||||
return __PRETTY_FUNCTION__;
|
|
||||||
#elif COMPILER_MSVC
|
|
||||||
return __FUNCSIG__;
|
|
||||||
#elif COMPILER_GCC
|
|
||||||
return __PRETTY_FUNCTION__;
|
|
||||||
#else
|
#else
|
||||||
return "UnknownType";
|
#define ThreadLocal __thread
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
inline uint16 safe_cast_uint16(uint32 value)
|
static inline uint16 safe_cast_uint16(uint32 value)
|
||||||
{
|
{
|
||||||
Assert(value <= uint16Max);
|
Assert(value <= uint16Max);
|
||||||
uint16 result = (uint16)value;
|
uint16 result = (uint16)value;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32 bitmask1 = 0b0000'0001;
|
#define bitmask1 0x00000001u
|
||||||
const uint32 bitmask2 = 0b0000'0011;
|
#define bitmask2 0x00000003u
|
||||||
const uint32 bitmask3 = 0b0000'0111;
|
#define bitmask3 0x00000007u
|
||||||
const uint32 bitmask4 = 0b0000'1111;
|
#define bitmask4 0x0000000fu
|
||||||
const uint32 bitmask5 = 0b0001'1111;
|
#define bitmask5 0x0000001fu
|
||||||
const uint32 bitmask6 = 0b0011'1111;
|
#define bitmask6 0x0000003fu
|
||||||
const uint32 bitmask7 = 0b0111'1111;
|
#define bitmask7 0x0000007fu
|
||||||
const uint32 bitmask8 = 0b1111'1111;
|
#define bitmask8 0x000000ffu
|
||||||
const uint32 bitmask9 = 0x0000'01ff;
|
#define bitmask9 0x000001ffu
|
||||||
const uint32 bitmask10 = 0x0000'03ff;
|
#define bitmask10 0x000003ffu
|
||||||
const uint32 bitmask11 = 0x0000'07ff;
|
#define bitmask11 0x000007ffu
|
||||||
const uint32 bitmask12 = 0x0000'0fff;
|
#define bitmask12 0x00000fffu
|
||||||
const uint32 bitmask13 = 0x0000'1fff;
|
#define bitmask13 0x00001fffu
|
||||||
const uint32 bitmask14 = 0x0000'3fff;
|
#define bitmask14 0x00003fffu
|
||||||
const uint32 bitmask15 = 0x0000'7fff;
|
#define bitmask15 0x00007fffu
|
||||||
const uint32 bitmask16 = 0x0000'ffff;
|
#define bitmask16 0x0000ffffu
|
||||||
// ...
|
#define bitmask32 0xffffffffu
|
||||||
const uint32 bitmask32 = 0xffff'ffff;
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept IsEnum = std::is_enum_v<T>;
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator~(E lhs) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(~static_cast<std::underlying_type_t<E>>(lhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator|(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(static_cast<std::underlying_type_t<E>>(lhs) | static_cast<std::underlying_type_t<E>>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E& operator|=(E& lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs = (lhs | rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator&(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(static_cast<std::underlying_type_t<E>>(lhs) & static_cast<std::underlying_type_t<E>>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E& operator&=(E& lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs = (lhs & rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator^(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(static_cast<std::underlying_type_t<E>>(lhs) ^ static_cast<std::underlying_type_t<E>>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E& operator^=(E& lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs = (lhs ^ rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr std::underlying_type_t<E> operator-(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
using T = std::underlying_type_t<E>;
|
|
||||||
return static_cast<T>(static_cast<T>(lhs) - static_cast<T>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr std::underlying_type_t<E> operator+(E lhs, E rhs) noexcept
|
|
||||||
{
|
|
||||||
using T = std::underlying_type_t<E>;
|
|
||||||
return static_cast<T>(static_cast<T>(lhs) + static_cast<T>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator-(E lhs, std::underlying_type_t<E> rhs) noexcept
|
|
||||||
{
|
|
||||||
using T = std::underlying_type_t<E>;
|
|
||||||
return static_cast<E>(static_cast<T>(static_cast<T>(lhs) - rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E operator+(E lhs, std::underlying_type_t<E> rhs) noexcept
|
|
||||||
{
|
|
||||||
using T = std::underlying_type_t<E>;
|
|
||||||
return static_cast<E>(static_cast<T>(static_cast<T>(lhs) + rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr std::underlying_type_t<E> ToUnderlying(E enm) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<std::underlying_type_t<E>>(enm);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <IsEnum E>
|
|
||||||
constexpr E ToEnum(std::underlying_type_t<E> value) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<E>(value);
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
|
||||||
|
|
||||||
template <typename Type, typename OtherType>
|
|
||||||
concept NonNullPtr_Convertible = std::is_convertible_v<OtherType*, Type*>;
|
|
||||||
|
|
||||||
template <typename Type, typename OtherType>
|
|
||||||
concept NonNullPtr_SameType = std::is_same_v<OtherType*, Type*>;
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
class NonNullPtr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
constexpr NonNullPtr(Type* ptr)
|
|
||||||
: InternalPtr(ptr)
|
|
||||||
{
|
|
||||||
Assert(ptr, "Tried to initialize a NonNullPtr with a null pointer");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OtherType>
|
|
||||||
requires NonNullPtr_Convertible<OtherType*, Type*>
|
|
||||||
constexpr NonNullPtr(const NonNullPtr<OtherType>& otherPtr)
|
|
||||||
: InternalPtr(otherPtr.Get())
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "Fatal Error: Assigned a non null ptr using another NonNullPtr but its was null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assignment
|
|
||||||
[[nodiscard]] constexpr NonNullPtr& operator=(Type* ptr)
|
|
||||||
{
|
|
||||||
Assert(ptr, "Tried to assign a null pointer to a NonNullPtr!");
|
|
||||||
InternalPtr = ptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OtherType>
|
|
||||||
requires NonNullPtr_Convertible<OtherType*, Type*>
|
|
||||||
[[nodiscard]] constexpr NonNullPtr& operator=(const NonNullPtr<OtherType>& otherPtr)
|
|
||||||
{
|
|
||||||
InternalPtr = otherPtr.Get();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
[[nodiscard]] constexpr operator Type*() const
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
||||||
return InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr Type* Get() const
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
||||||
return InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr Type& operator*() const
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
||||||
return *InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr Type* operator->() const
|
|
||||||
{
|
|
||||||
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
|
|
||||||
return InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comparisons
|
|
||||||
[[nodiscard]] constexpr bool operator==(const NonNullPtr& otherPtr) const
|
|
||||||
{
|
|
||||||
return InternalPtr == otherPtr.InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OtherType>
|
|
||||||
requires NonNullPtr_SameType<Type, OtherType>
|
|
||||||
[[nodiscard]] constexpr bool operator==(OtherType* otherRawPtr) const
|
|
||||||
{
|
|
||||||
return InternalPtr == otherRawPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OtherType>
|
|
||||||
requires NonNullPtr_SameType<Type, OtherType>
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(OtherType* otherRawPtr, const NonNullPtr& nonNullPtr)
|
|
||||||
{
|
|
||||||
return otherRawPtr == nonNullPtr.InternalPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forbid assigning a nullptr at compile time
|
|
||||||
constexpr NonNullPtr(std::nullptr_t)
|
|
||||||
: InternalPtr(nullptr)
|
|
||||||
{
|
|
||||||
static_assert(sizeof(Type) == 0, "Trying to initialize a NonNullPtr with a nullptr value");
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr NonNullPtr& operator=(std::nullptr_t)
|
|
||||||
{
|
|
||||||
static_assert(sizeof(Type) == 0, "Trying to assign a NonNullPtr with a nullptr value");
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr explicit operator bool() const { return InternalPtr != nullptr; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Type* InternalPtr;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
NonNullPtr(T*) -> NonNullPtr<T>;
|
|
||||||
@@ -1,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/Math/MathUtils.h>
|
||||||
#include <Core/Memory/Utils.h>
|
#include <Core/Memory/Utils.h>
|
||||||
|
|
||||||
#ifdef global
|
typedef struct Arena Arena;
|
||||||
#undef global
|
|
||||||
#define RESTORE_GLOBAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RESTORE_GLOBAL
|
#define ConstString(str) ((String){ (char*)(str), sizeof(str) - 1 })
|
||||||
#define global static
|
#define ConstStringInit(str) { (char*)(str), sizeof(str) - 1 }
|
||||||
#undef RESTORE_GLOBAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Arena;
|
|
||||||
|
|
||||||
#define ConstString(str) { const_cast<char*>((str)), sizeof(str) - 1 }
|
|
||||||
#define CStr(str) ((str).Str)
|
#define CStr(str) ((str).Str)
|
||||||
#define InplaceString(name, size) \
|
#define InplaceString(name, size) \
|
||||||
char name##_[size]; \
|
char name##_[size]; \
|
||||||
@@ -24,55 +16,69 @@ struct Arena;
|
|||||||
String name = { name##_, 0 }
|
String name = { name##_, 0 }
|
||||||
|
|
||||||
// Everything is Little Endian
|
// Everything is Little Endian
|
||||||
enum class StringEncoding : uint8
|
typedef uint8 StringEncoding;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Unknown = 0,
|
StringEncoding_Unknown = 0,
|
||||||
ASCII,
|
StringEncoding_ASCII,
|
||||||
LATIN1,
|
StringEncoding_LATIN1,
|
||||||
UTF8,
|
StringEncoding_UTF8,
|
||||||
UTF16,
|
StringEncoding_UTF16,
|
||||||
UTF32,
|
StringEncoding_UTF32,
|
||||||
UCS2,
|
StringEncoding_UCS2,
|
||||||
UCS4,
|
StringEncoding_UCS4,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Represents a UTF-8 String.
|
// Represents a UTF-8 String.
|
||||||
// Not null terminated.
|
// Not null terminated.
|
||||||
|
typedef struct String8 String8;
|
||||||
struct String8
|
struct String8
|
||||||
{
|
{
|
||||||
char* Str;
|
char* Str;
|
||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
using String = String8;
|
typedef String8 String;
|
||||||
|
|
||||||
|
typedef struct String16 String16;
|
||||||
struct String16
|
struct String16
|
||||||
{
|
{
|
||||||
uint16* Str;
|
uint16* Str;
|
||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StringBuffer : String
|
typedef struct StringBuffer StringBuffer;
|
||||||
|
struct StringBuffer
|
||||||
{
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
String8 str8;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char* Str;
|
||||||
|
size_t Size;
|
||||||
|
};
|
||||||
|
};
|
||||||
size_t Capacity;
|
size_t Capacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct UnicodeDecode UnicodeDecode;
|
||||||
struct UnicodeDecode
|
struct UnicodeDecode
|
||||||
{
|
{
|
||||||
uint32 Increment;
|
uint32 Increment;
|
||||||
uint32 Codepoint;
|
uint32 Codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr uint32 kInvalidUTF8 = 0xFFFD;
|
#define kInvalidUTF8 ((uint32)0xFFFDu)
|
||||||
|
|
||||||
inline size_t StringLength(String str)
|
static inline size_t StringLength(String str)
|
||||||
{
|
{
|
||||||
return str.Size;
|
return str.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t StringLength(const char* str)
|
static inline size_t StringLengthCStr(const char* str)
|
||||||
{
|
{
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
if (str)
|
if (str != NULL)
|
||||||
{
|
{
|
||||||
while (*str)
|
while (*str)
|
||||||
{
|
{
|
||||||
@@ -84,47 +90,46 @@ inline size_t StringLength(const char* str)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsValid(String str)
|
static inline bool8 IsValidString(String str)
|
||||||
{
|
{
|
||||||
return str.Size > 0 && str.Str != nullptr && *str.Str;
|
return (str.Size > 0 && str.Str != NULL && *str.Str != '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String WrapString(const char* str)
|
static inline String WrapString(const char* str)
|
||||||
{
|
{
|
||||||
String result = {};
|
String result = { 0 };
|
||||||
result.Str = const_cast<char*>(str);
|
result.Str = (char*)str;
|
||||||
result.Size = str ? strlen(str) : 0;
|
result.Size = (str != NULL) ? strlen(str) : 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String FindChar(String str, char c)
|
static inline String FindChar(String str, char c)
|
||||||
{
|
{
|
||||||
String result = str;
|
String result = { 0 };
|
||||||
while (result.Size)
|
String cursor = str;
|
||||||
|
while (cursor.Size > 0)
|
||||||
{
|
{
|
||||||
if (*result.Str != c)
|
if (*cursor.Str == c)
|
||||||
{
|
{
|
||||||
++result.Str;
|
result = cursor;
|
||||||
--result.Size;
|
break;
|
||||||
|
}
|
||||||
|
++cursor.Str;
|
||||||
|
--cursor.Size;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return result;
|
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:
|
// Return:
|
||||||
// - < 0 if str1 < str2
|
// - < 0 if str1 < str2
|
||||||
// - = 0 : Both strings are equals
|
// - = 0 : Both strings are equals
|
||||||
// - > 0 if str1 > str2
|
// - > 0 if str1 > str2
|
||||||
inline int32 StringCompare(String str1, String str2)
|
static inline int32 StringCompare(String str1, String str2)
|
||||||
{
|
{
|
||||||
size_t len1 = StringLength(str1);
|
size_t len1 = StringLength(str1);
|
||||||
size_t len2 = StringLength(str2);
|
size_t len2 = StringLength(str2);
|
||||||
@@ -134,62 +139,47 @@ inline int32 StringCompare(String str1, String str2)
|
|||||||
{
|
{
|
||||||
if (len1 > len2)
|
if (len1 > len2)
|
||||||
{
|
{
|
||||||
return 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
if (len1 < len2)
|
else if (len1 < len2)
|
||||||
{
|
{
|
||||||
return -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
JULIET_API uint32 StepUTF8(String& inStr);
|
JULIET_API uint32 StepUTF8(String* inStr);
|
||||||
JULIET_API String FindString(String strLeft, String strRight);
|
JULIET_API String FindString(String strLeft, String strRight);
|
||||||
|
|
||||||
// Case insensitive compare. Supports ASCII only
|
// Case insensitive compare. Supports ASCII only
|
||||||
// TODO: Support UNICODE
|
|
||||||
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
|
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
|
||||||
|
|
||||||
// Do not allocate anything, you must allocate your out buffer yourself
|
extern JULIET_API bool8 ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer* dst, bool8 nullTerminate);
|
||||||
// TODO: Version taking arena that can allocate
|
extern JULIET_API bool8 ConvertStringByName(String from, String to, String src, StringBuffer* dst, bool8 nullTerminate);
|
||||||
// Do not take String type because we dont know the string encoding we are going from/to
|
|
||||||
// src and dst will be casted based on the encoding.
|
|
||||||
// size will correspond to the number of characters
|
|
||||||
// Will convert \0 character if present.
|
|
||||||
extern JULIET_API bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst, bool nullTerminate);
|
|
||||||
extern JULIET_API bool ConvertString(String from, String to, String src, StringBuffer& dst, bool nullTerminate);
|
|
||||||
|
|
||||||
JULIET_API String StringCopy(NonNullPtr<Arena> arena, String str);
|
JULIET_API String StringCopy(Arena* arena, String str);
|
||||||
JULIET_API String16 str16_from_8(NonNullPtr<Arena> arena, String8 str);
|
JULIET_API String16 str16_from_8(Arena* arena, String8 str);
|
||||||
|
|
||||||
String trim_whitespace(String str);
|
String trim_whitespace(String str);
|
||||||
|
|
||||||
template <typename... Args>
|
JULIET_API String StringFormatV(Arena* arena, const char* formatStr, va_list args);
|
||||||
String Format(NonNullPtr<Arena> arena, const char* formatStr, Args&&... args)
|
JULIET_API String StringFormat(Arena* arena, const char* formatStr, ...);
|
||||||
{
|
|
||||||
std::string result = std::vformat(formatStr, std::make_format_args(args...));
|
|
||||||
return StringCopy(arena, WrapString(result.c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define juliet_snprintf snprintf
|
#define juliet_snprintf snprintf
|
||||||
|
|
||||||
#ifdef UNIT_TEST
|
#ifdef UNIT_TEST
|
||||||
namespace UnitTest
|
static inline void UnitTest_TestFindChar(void)
|
||||||
{
|
{
|
||||||
inline void TestFindChar()
|
|
||||||
{
|
|
||||||
String s1 = ConstString("");
|
String s1 = ConstString("");
|
||||||
String s2 = ConstString("abcdefabcdef");
|
String s2 = ConstString("abcdefabcdef");
|
||||||
String s3 = ConstString("11111111111111111111");
|
String s3 = ConstString("11111111111111111111");
|
||||||
|
|
||||||
Assert(FindChar(s1, 'x').Str == nullptr);
|
Assert(FindChar(s1, 'x').Str == NULL);
|
||||||
Assert(FindChar(s2, 'y').Str == nullptr);
|
Assert(FindChar(s2, 'y').Str == NULL);
|
||||||
Assert(FindChar(s2, 'a').Str - s2.Str == 0);
|
Assert(FindChar(s2, 'a').Str - s2.Str == 0);
|
||||||
Assert(FindChar(s2, 'd').Str - s2.Str == 3);
|
Assert(FindChar(s2, 'd').Str - s2.Str == 3);
|
||||||
Assert(FindChar(s2, 'f').Str - s2.Str == 5);
|
Assert(FindChar(s2, 'f').Str - s2.Str == 5);
|
||||||
Assert(FindChar(s3, '1').Str - s3.Str == 0);
|
Assert(FindChar(s3, '1').Str - s3.Str == 0);
|
||||||
}
|
}
|
||||||
} // namespace UnitTest
|
|
||||||
#endif
|
#endif
|
||||||
@@ -2,125 +2,102 @@
|
|||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
#include <Core/Common/CRC32.h>
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
#include <Core/HAL/IO/IOStream.h>
|
#include <Core/HAL/IO/IOStream.h>
|
||||||
|
#include <Core/Math/Vector.h>
|
||||||
|
|
||||||
// .jasset
|
typedef struct IOStream IOStream;
|
||||||
// AssetFile ::= { CommentLine | EmptyLine | PropertyDeclaration } ;
|
typedef struct Arena Arena;
|
||||||
// CommentLine ::= ( "#" | "//" ) { Character } LineEnding ;
|
typedef struct ArchivePropertyNode ArchivePropertyNode;
|
||||||
// EmptyLine ::= { Whitespace } LineEnding ;
|
typedef struct ParsedArchive ParsedArchive;
|
||||||
// PropertyDeclaration ::= KeyHeader LineEnding ValueBlock ;
|
typedef struct Archive Archive;
|
||||||
// KeyHeader ::= ";" { Whitespace } Identifier ;
|
|
||||||
// ValueBlock ::= { ValueLine LineEnding } ;
|
|
||||||
// ValueLine ::= { Whitespace } ValueString { Whitespace } ;
|
|
||||||
// LineEnding ::= "\r\n" | "\n" ;
|
|
||||||
// Identifier ::= [a-zA-Z_][a-zA-Z0-9_]* ;
|
|
||||||
|
|
||||||
struct Vector4;
|
|
||||||
struct IOStream;
|
|
||||||
struct Arena;
|
|
||||||
|
|
||||||
struct ArchivePropertyNode
|
struct ArchivePropertyNode
|
||||||
{
|
{
|
||||||
String key;
|
String key;
|
||||||
String value;
|
String value;
|
||||||
uint32 key_crc;
|
uint32 key_crc;
|
||||||
bool consumed;
|
bool8 consumed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ParsedArchive
|
struct ParsedArchive
|
||||||
{
|
{
|
||||||
ArchivePropertyNode* nodes = nullptr;
|
ArchivePropertyNode* nodes;
|
||||||
uint32 property_count = 0;
|
uint32 property_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Archive
|
struct Archive
|
||||||
{
|
{
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
bool loading;
|
bool8 loading;
|
||||||
ParsedArchive base = {};
|
ParsedArchive base;
|
||||||
IOStream* stream = nullptr;
|
IOStream* stream;
|
||||||
|
|
||||||
// to remove
|
void* base_ptr;
|
||||||
void* base_ptr = nullptr;
|
index_t offset;
|
||||||
index_t offset = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JULIET_API void serialize(Archive& ar, void* data, size_t size);
|
JULIET_API void serialize_bytes(Archive* ar, void* data, size_t size);
|
||||||
|
|
||||||
#define serialize_elem(ar, val) serialize((ar), &(val), sizeof(val))
|
#define serialize_elem(ar, val) serialize_bytes((ar), &(val), sizeof(val))
|
||||||
|
|
||||||
JULIET_API ParsedArchive tokenize_archive(NonNullPtr<Arena> arena, ByteBuffer file_buffer);
|
JULIET_API ParsedArchive tokenize_archive(Arena* arena, ByteBuffer file_buffer);
|
||||||
JULIET_API ArchivePropertyNode* find_property(NonNullPtr<ParsedArchive> archive, uint32 property_crc);
|
JULIET_API ArchivePropertyNode* find_property(ParsedArchive* archive, uint32 property_crc);
|
||||||
JULIET_API void write_property_header(Archive& archive, String property_name);
|
JULIET_API void write_property_header(Archive* archive, String property_name);
|
||||||
|
|
||||||
JULIET_API bool read_prop(Archive& ar, String value_raw, String& value);
|
JULIET_API bool8 read_prop_str(Archive* ar, String value_raw, String* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, String value);
|
JULIET_API void write_str(IOStream* stream, String value);
|
||||||
JULIET_API bool read(const char* buffer, float& value, const char** end = nullptr);
|
JULIET_API bool8 read_f32(const char* buffer, float* value, const char** end);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, float value);
|
JULIET_API void write_f32(IOStream* stream, float value);
|
||||||
JULIET_API bool read(const char* buffer, int8& value);
|
JULIET_API bool8 read_i8(const char* buffer, int8* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, int8 value);
|
JULIET_API void write_i8(IOStream* stream, int8 value);
|
||||||
JULIET_API bool read(const char* buffer, int16& value);
|
JULIET_API bool8 read_i16(const char* buffer, int16* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, int16 value);
|
JULIET_API void write_i16(IOStream* stream, int16 value);
|
||||||
JULIET_API bool read(const char* buffer, int32& value);
|
JULIET_API bool8 read_i32(const char* buffer, int32* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, int32 value);
|
JULIET_API void write_i32(IOStream* stream, int32 value);
|
||||||
JULIET_API bool read(const char* buffer, int64& value);
|
JULIET_API bool8 read_i64(const char* buffer, int64* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, int64 value);
|
JULIET_API void write_i64(IOStream* stream, int64 value);
|
||||||
JULIET_API bool read(const char* buffer, uint8& value);
|
JULIET_API bool8 read_u8(const char* buffer, uint8* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, uint8 value);
|
JULIET_API void write_u8(IOStream* stream, uint8 value);
|
||||||
JULIET_API bool read(const char* buffer, uint16& value);
|
JULIET_API bool8 read_u16(const char* buffer, uint16* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, uint16 value);
|
JULIET_API void write_u16(IOStream* stream, uint16 value);
|
||||||
JULIET_API bool read(const char* buffer, uint32& value);
|
JULIET_API bool8 read_u32(const char* buffer, uint32* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, uint32 value);
|
JULIET_API void write_u32(IOStream* stream, uint32 value);
|
||||||
JULIET_API bool read(const char* buffer, uint64& value);
|
JULIET_API bool8 read_u64(const char* buffer, uint64* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, uint64 value);
|
JULIET_API void write_u64(IOStream* stream, uint64 value);
|
||||||
JULIET_API bool read(const char* buffer, bool& value);
|
JULIET_API bool8 read_b8(const char* buffer, bool8* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, bool value);
|
JULIET_API void write_b8(IOStream* stream, bool8 value);
|
||||||
JULIET_API bool read(const char* buffer, Vector4& value);
|
JULIET_API bool8 read_vec4(const char* buffer, Vector4* value);
|
||||||
JULIET_API void write(NonNullPtr<IOStream> stream, Vector4 value);
|
JULIET_API void write_vec4(IOStream* stream, Vector4 value);
|
||||||
|
|
||||||
// For primitives not needing archive nor allocation
|
JULIET_API bool8 serialize_str(Archive* ar, String property_name, String* value);
|
||||||
template <typename Type>
|
JULIET_API bool8 serialize_f32(Archive* ar, String property_name, float* value);
|
||||||
bool read_prop(Archive& /*ar*/, String value_raw, Type& value)
|
JULIET_API bool8 serialize_i8(Archive* ar, String property_name, int8* value);
|
||||||
{
|
JULIET_API bool8 serialize_i16(Archive* ar, String property_name, int16* value);
|
||||||
char buffer[64];
|
JULIET_API bool8 serialize_i32(Archive* ar, String property_name, int32* value);
|
||||||
size_t cpy_size = Min(value_raw.Size, sizeof(buffer) - 1);
|
JULIET_API bool8 serialize_i64(Archive* ar, String property_name, int64* value);
|
||||||
MemCopy(buffer, value_raw.Str, cpy_size);
|
JULIET_API bool8 serialize_u8(Archive* ar, String property_name, uint8* value);
|
||||||
buffer[cpy_size] = '\0';
|
JULIET_API bool8 serialize_u16(Archive* ar, String property_name, uint16* value);
|
||||||
|
JULIET_API bool8 serialize_u32(Archive* ar, String property_name, uint32* value);
|
||||||
|
JULIET_API bool8 serialize_u64(Archive* ar, String property_name, uint64* value);
|
||||||
|
JULIET_API bool8 serialize_b8(Archive* ar, String property_name, bool8* value);
|
||||||
|
JULIET_API bool8 serialize_vec4(Archive* ar, String property_name, Vector4* value);
|
||||||
|
|
||||||
return read(buffer, value);
|
#define SERIALIZE_STR(ar, name, var_ptr) serialize_str((ar), ConstString(#name), (var_ptr))
|
||||||
}
|
#define SERIALIZE_F32(ar, name, var_ptr) serialize_f32((ar), ConstString(#name), (var_ptr))
|
||||||
|
#define SERIALIZE_I8(ar, name, var_ptr) serialize_i8((ar), ConstString(#name), (var_ptr))
|
||||||
#define SERIALIZE(ar, name, var) serialize((ar), ConstString(#name), #name##_crc32, (var))
|
#define SERIALIZE_I16(ar, name, var_ptr) serialize_i16((ar), ConstString(#name), (var_ptr))
|
||||||
#define SERIALIZE_SIMPLE(ar, var) SERIALIZE(ar, var, var)
|
#define SERIALIZE_I32(ar, name, var_ptr) serialize_i32((ar), ConstString(#name), (var_ptr))
|
||||||
|
#define SERIALIZE_I64(ar, name, var_ptr) serialize_i64((ar), ConstString(#name), (var_ptr))
|
||||||
template <typename Type>
|
#define SERIALIZE_U8(ar, name, var_ptr) serialize_u8((ar), ConstString(#name), (var_ptr))
|
||||||
bool serialize(Archive& ar, String property_name, uint32 property_crc, Type& value)
|
#define SERIALIZE_U16(ar, name, var_ptr) serialize_u16((ar), ConstString(#name), (var_ptr))
|
||||||
{
|
#define SERIALIZE_U32(ar, name, var_ptr) serialize_u32((ar), ConstString(#name), (var_ptr))
|
||||||
Assert(IsValid(property_name));
|
#define SERIALIZE_U64(ar, name, var_ptr) serialize_u64((ar), ConstString(#name), (var_ptr))
|
||||||
|
#define SERIALIZE_B8(ar, name, var_ptr) serialize_b8((ar), ConstString(#name), (var_ptr))
|
||||||
bool result = false;
|
#define SERIALIZE_BOOL(ar, name, var_ptr) serialize_b8((ar), ConstString(#name), (var_ptr))
|
||||||
if (ar.loading)
|
#define SERIALIZE_VEC4(ar, name, var_ptr) serialize_vec4((ar), ConstString(#name), (var_ptr))
|
||||||
{
|
|
||||||
if (auto* prop = find_property(&ar.base, property_crc))
|
|
||||||
{
|
|
||||||
if (read_prop(ar, prop->value, value))
|
|
||||||
{
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Save
|
|
||||||
write_property_header(ar, property_name);
|
|
||||||
write(ar.stream, value);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
JULIET_API void audit_unconsumed_properties(NonNullPtr<ParsedArchive> archive, String context_name);
|
JULIET_API void audit_unconsumed_properties(ParsedArchive* archive, String context_name);
|
||||||
#endif
|
#endif
|
||||||
@@ -1,211 +1,232 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
#include <Core/Memory/Utils.h>
|
||||||
|
|
||||||
template <typename Type, size_t ReserveSize = 16>
|
typedef struct VectorArena VectorArena;
|
||||||
struct VectorArena
|
struct VectorArena
|
||||||
{
|
{
|
||||||
void Create(NonNullPtr<Arena> arena JULIET_DEBUG_PARAM(const char* name = nullptr))
|
Arena* Arena;
|
||||||
|
void* DataFirst;
|
||||||
|
void* DataLast;
|
||||||
|
void* Data;
|
||||||
|
union
|
||||||
{
|
{
|
||||||
Assert(!Arena);
|
size_t Count;
|
||||||
|
size_t Size;
|
||||||
|
};
|
||||||
|
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;
|
static inline void vector_arena_reserve(VectorArena* vec, size_t new_capacity)
|
||||||
Count = 0;
|
{
|
||||||
Capacity = 0;
|
Assert(vec != NULL);
|
||||||
Arena = arena;
|
Assert(vec->Arena != NULL);
|
||||||
|
Assert(new_capacity <= vec->ReserveSize && "VectorArena capacity should be <= ReserveSize.");
|
||||||
|
|
||||||
Reserve(ReserveSize);
|
if (vec->Data == NULL)
|
||||||
}
|
|
||||||
|
|
||||||
void Destroy()
|
|
||||||
{
|
{
|
||||||
DataFirst = DataLast = Data = nullptr;
|
vec->Data = ArenaPush(vec->Arena, new_capacity * vec->ElemSize, Max(8ull, (uint64)vec->ElemAlign),
|
||||||
Count = 0;
|
true JULIET_DEBUG_PARAM(vec->Name));
|
||||||
Capacity = 0;
|
vec->Capacity = new_capacity;
|
||||||
Arena = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reserve(size_t newCapacity)
|
|
||||||
{
|
|
||||||
Assert(Arena);
|
|
||||||
Assert(newCapacity <= ReserveSize && "VectorArena capacity should be <= ReserveSize.");
|
|
||||||
|
|
||||||
if (Data == nullptr)
|
|
||||||
{
|
|
||||||
Data = ArenaPushArray<Type>(Arena, newCapacity JULIET_DEBUG_PARAM(Name));
|
|
||||||
Capacity = newCapacity;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Unimplemented();
|
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);
|
result = (const Byte*)vec->DataFirst + (vec->Count * vec->ElemSize);
|
||||||
if (newCount == Count)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
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;
|
vec->DataFirst = vec->Data;
|
||||||
Reserve(initialCapacity);
|
vec->DataLast = (Byte*)vec->Data + ((vec->Count - 1) * vec->ElemSize);
|
||||||
}
|
|
||||||
|
|
||||||
Assert(newCount <= Capacity && "VectorArena capacity exceeded!");
|
|
||||||
Count = newCount;
|
|
||||||
|
|
||||||
if (Count > 0)
|
|
||||||
{
|
|
||||||
DataFirst = Data;
|
|
||||||
DataLast = Data + Count - 1;
|
|
||||||
}
|
}
|
||||||
else
|
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);
|
vec->DataFirst = vec->Data;
|
||||||
Assert(buffer || amount == 0);
|
}
|
||||||
|
|
||||||
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;
|
Byte* dst = (Byte*)vec->DataFirst + (index * vec->ElemSize);
|
||||||
Reserve(initialCapacity);
|
Byte* src = (Byte*)vec->DataFirst + (last_idx * vec->ElemSize);
|
||||||
|
MemCopy(dst, src, vec->ElemSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(Count + amount <= Capacity && "VectorArena capacity exceeded!");
|
vec->Count -= 1;
|
||||||
|
if (vec->Count == 0)
|
||||||
Type* dst = Data + Count;
|
|
||||||
MemCopy(dst, buffer, amount * sizeof(Type));
|
|
||||||
|
|
||||||
if (Count == 0)
|
|
||||||
{
|
{
|
||||||
DataFirst = dst;
|
vec->DataFirst = NULL;
|
||||||
|
vec->DataLast = NULL;
|
||||||
}
|
}
|
||||||
DataLast = dst + amount - 1;
|
else
|
||||||
Count += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushBack(const Type& value)
|
|
||||||
{
|
{
|
||||||
Assert(Arena);
|
vec->DataLast = (Byte*)vec->DataFirst + ((vec->Count - 1) * vec->ElemSize);
|
||||||
|
|
||||||
if (Data == nullptr)
|
|
||||||
{
|
|
||||||
Reserve(ReserveSize);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
static inline bool8 vector_arena_is_empty(const VectorArena* vec)
|
||||||
*entry = value;
|
{
|
||||||
|
Assert(vec != NULL);
|
||||||
|
return vec->Count == 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (Count == 0)
|
static inline size_t vector_arena_size(const VectorArena* vec)
|
||||||
{
|
{
|
||||||
DataFirst = entry;
|
Assert(vec != NULL);
|
||||||
}
|
return vec->Count;
|
||||||
DataLast = entry;
|
}
|
||||||
++Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushBack(Type&& value)
|
#define VectorArenaCreate(vec, Type, arena, ...) \
|
||||||
{
|
vector_arena_create((vec), (arena), sizeof(Type), AlignOf(Type), __VA_ARGS__)
|
||||||
Assert(Arena);
|
|
||||||
|
|
||||||
if (Data == nullptr)
|
#define VectorArenaAt(Type, vec, idx) (((Type*)((vec)->DataFirst))[idx])
|
||||||
{
|
#define VectorArenaData(Type, vec) ((Type*)((vec)->Data))
|
||||||
Reserve(ReserveSize);
|
#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))
|
||||||
Assert(Count + 1 <= Capacity && "VectorArena capacity exceeded!");
|
#define VectorArenaBack(Type, vec) ((Type*)((vec)->DataLast))
|
||||||
|
#define VectorArenaPushPtr(Type, vec, ptr) vector_arena_push_elem((vec), (ptr))
|
||||||
Type* entry = Data + Count;
|
#define VectorArenaPushVal(Type, vec, val) \
|
||||||
*entry = std::move(value);
|
do \
|
||||||
|
{ \
|
||||||
if (Count == 0)
|
Type _vec_tmp_val = (val); \
|
||||||
{
|
vector_arena_push_elem((vec), &_vec_tmp_val); \
|
||||||
DataFirst = entry;
|
} \
|
||||||
}
|
while (0)
|
||||||
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).");
|
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
struct Window;
|
typedef struct Window Window;
|
||||||
|
|
||||||
using WindowID = uint8;
|
typedef uint8 WindowID;
|
||||||
extern JULIET_API Window* CreatePlatformWindow(const char* title, uint16 width, uint16 height, int flags = 0 /* unused */);
|
|
||||||
extern JULIET_API void DestroyPlatformWindow(NonNullPtr<Window> window);
|
|
||||||
|
|
||||||
extern JULIET_API void ShowWindow(NonNullPtr<Window> window);
|
extern JULIET_API Window* CreatePlatformWindow(const char* title, uint16 width, uint16 height, int flags);
|
||||||
extern JULIET_API void HideWindow(NonNullPtr<Window> window);
|
extern JULIET_API void DestroyPlatformWindow(Window* window);
|
||||||
|
|
||||||
extern JULIET_API WindowID GetWindowID(NonNullPtr<Window> window);
|
extern JULIET_API void ShowPlatformWindow(Window* window);
|
||||||
extern JULIET_API void SetWindowTitle(NonNullPtr<Window> window, String title);
|
extern JULIET_API void HidePlatformWindow(Window* window);
|
||||||
|
|
||||||
|
extern JULIET_API WindowID GetWindowID(Window* window);
|
||||||
|
extern JULIET_API void SetWindowTitle(Window* window, String title);
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
struct DynamicLibrary;
|
typedef struct DynamicLibrary DynamicLibrary;
|
||||||
|
|
||||||
extern JULIET_API DynamicLibrary* LoadDynamicLibrary(const char* filename);
|
extern JULIET_API DynamicLibrary* LoadDynamicLibrary(const char* filename);
|
||||||
extern JULIET_API FunctionPtr LoadFunction(NonNullPtr<DynamicLibrary> lib, const char* functionName);
|
extern JULIET_API FunctionPtr LoadFunction(DynamicLibrary* lib, const char* functionName);
|
||||||
extern JULIET_API void UnloadDynamicLibrary(NonNullPtr<DynamicLibrary> lib);
|
extern JULIET_API void UnloadDynamicLibrary(DynamicLibrary* lib);
|
||||||
@@ -1,53 +1,57 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/HAL/Display/Display.h>
|
#include <Core/HAL/Display/Display.h>
|
||||||
#include <Core/HAL/Keyboard/Keyboard.h>
|
#include <Core/HAL/Keyboard/Keyboard.h>
|
||||||
#include <Core/HAL/Keyboard/KeyCode.h>
|
#include <Core/HAL/Keyboard/KeyCode.h>
|
||||||
#include <Core/HAL/Mouse/Mouse.h>
|
#include <Core/HAL/Mouse/Mouse.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
// Handles all events from systems handling the Hardware
|
typedef uint32 EventType;
|
||||||
// Very inspired by SDL3
|
enum
|
||||||
|
|
||||||
enum class EventType : uint32
|
|
||||||
{
|
{
|
||||||
None = 0,
|
EventType_None = 0,
|
||||||
First = None,
|
EventType_First = EventType_None,
|
||||||
|
|
||||||
// Application Events
|
// Application Events
|
||||||
// User querying an exit
|
EventType_Application_Exit = 100,
|
||||||
Application_Exit = 100,
|
EventType_Application_OS_Terminate = 101,
|
||||||
// OS terminating the application
|
EventType_Application_Begin = EventType_Application_Exit,
|
||||||
Application_OS_Terminate,
|
EventType_Application_End = EventType_Application_OS_Terminate,
|
||||||
Application_Begin = Application_Exit,
|
|
||||||
Application_End = Application_OS_Terminate,
|
|
||||||
|
|
||||||
// Window Events
|
// Window Events
|
||||||
Window_Close_Request = 200,
|
EventType_Window_Close_Request = 200,
|
||||||
Window_Begin = Window_Close_Request,
|
EventType_Window_Begin = EventType_Window_Close_Request,
|
||||||
Window_End = Window_Close_Request,
|
EventType_Window_End = EventType_Window_Close_Request,
|
||||||
|
|
||||||
// Keyboard Event
|
// Keyboard Event
|
||||||
Key_Down = 300,
|
EventType_Key_Down = 300,
|
||||||
Key_Up,
|
EventType_Key_Up = 301,
|
||||||
Keyboard_Begin = Key_Down,
|
EventType_Keyboard_Begin = EventType_Key_Down,
|
||||||
Keyboard_End = Key_Up,
|
EventType_Keyboard_End = EventType_Key_Up,
|
||||||
|
|
||||||
// Mouse Event
|
// Mouse Event
|
||||||
Mouse_Move = 400,
|
EventType_Mouse_Move = 400,
|
||||||
Mouse_ButtonPressed,
|
EventType_Mouse_ButtonPressed = 401,
|
||||||
Mouse_ButtonReleased,
|
EventType_Mouse_ButtonReleased = 402,
|
||||||
|
|
||||||
Mouse_Begin = Mouse_Move,
|
EventType_Mouse_Begin = EventType_Mouse_Move,
|
||||||
Mouse_End = Mouse_ButtonReleased,
|
EventType_Mouse_End = EventType_Mouse_ButtonReleased,
|
||||||
|
|
||||||
Last // Get value from the previous one
|
EventType_Last
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct WindowEvent WindowEvent;
|
||||||
|
typedef struct KeyboardEvent KeyboardEvent;
|
||||||
|
typedef struct MouseMovementEvent MouseMovementEvent;
|
||||||
|
typedef struct MouseButtonEvent MouseButtonEvent;
|
||||||
|
typedef union AllSystemEventUnion AllSystemEventUnion;
|
||||||
|
typedef struct SystemEvent SystemEvent;
|
||||||
|
|
||||||
struct WindowEvent
|
struct WindowEvent
|
||||||
{
|
{
|
||||||
WindowID AssociatedWindowID;
|
WindowID AssociatedWindowID;
|
||||||
uint32 DataPadding[2]; // TODO : define how much data param we need
|
uint32 DataPadding[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KeyboardEvent
|
struct KeyboardEvent
|
||||||
@@ -59,9 +63,6 @@ struct KeyboardEvent
|
|||||||
KeyMod KeyModeState;
|
KeyMod KeyModeState;
|
||||||
};
|
};
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// Mouse Events
|
|
||||||
// =====================================================
|
|
||||||
struct MouseMovementEvent
|
struct MouseMovementEvent
|
||||||
{
|
{
|
||||||
MouseID AssociatedMouseID;
|
MouseID AssociatedMouseID;
|
||||||
@@ -80,20 +81,18 @@ struct MouseButtonEvent
|
|||||||
float X;
|
float X;
|
||||||
float Y;
|
float Y;
|
||||||
MouseButton ButtonState;
|
MouseButton ButtonState;
|
||||||
bool IsPressed : 1;
|
bool8 IsPressed;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Tagged union representing ALL possible system events + a bit of data for custom event if needed
|
|
||||||
union AllSystemEventUnion
|
union AllSystemEventUnion
|
||||||
{
|
{
|
||||||
WindowEvent Window;
|
WindowEvent Window;
|
||||||
KeyboardEvent Keyboard;
|
KeyboardEvent Keyboard;
|
||||||
MouseMovementEvent MouseMovement;
|
MouseMovementEvent MouseMovement;
|
||||||
MouseButtonEvent MouseButton;
|
MouseButtonEvent MouseButton;
|
||||||
uint8 Padding[128]; // Make sure that the union is fixed in size and big enough on all platforms.
|
uint8 Padding[128];
|
||||||
};
|
};
|
||||||
// Make sure we do not bust the union size
|
StaticAssert(sizeof(AllSystemEventUnion) == 128, SystemEventUnionSizeCheck);
|
||||||
static_assert(sizeof(AllSystemEventUnion) == sizeof(((AllSystemEventUnion*)nullptr)->Padding));
|
|
||||||
|
|
||||||
struct SystemEvent
|
struct SystemEvent
|
||||||
{
|
{
|
||||||
@@ -102,19 +101,7 @@ struct SystemEvent
|
|||||||
AllSystemEventUnion Data;
|
AllSystemEventUnion Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Poll for any event, return false if no event is available.
|
extern JULIET_API bool8 GetEvent(SystemEvent* event);
|
||||||
// Equivalent to WaitEvent(event, 0);
|
extern JULIET_API bool8 WaitEvent(SystemEvent* event, int32 timeoutInNS);
|
||||||
// Will not block
|
extern JULIET_API bool8 AddEvent(SystemEvent* event);
|
||||||
extern JULIET_API bool GetEvent(SystemEvent& event);
|
|
||||||
|
|
||||||
// TODO : use chrono to tag the timeout correctly with nanosec
|
|
||||||
// timeout == -1 means wait for any event before pursuing
|
|
||||||
// timeout == 0 means checking once for the frame and getting out
|
|
||||||
// timeout > 0 means wait until time is out
|
|
||||||
extern JULIET_API bool WaitEvent(SystemEvent& event, int32 timeoutInNS = -1);
|
|
||||||
|
|
||||||
// Add an event onto the event queue.
|
|
||||||
// TODO : support array of events
|
|
||||||
extern JULIET_API bool AddEvent(SystemEvent& event);
|
|
||||||
|
|
||||||
extern void Events_NewFrame(float deltaTime);
|
extern void Events_NewFrame(float deltaTime);
|
||||||
@@ -2,41 +2,43 @@
|
|||||||
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
enum class AssetType
|
typedef uint32 AssetType;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
JAsset,
|
AssetType_JAsset = 0,
|
||||||
Shader,
|
AssetType_Shader = 1,
|
||||||
Config,
|
AssetType_Config = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct Path Path;
|
||||||
struct Path
|
struct Path
|
||||||
{
|
{
|
||||||
String Directories;
|
String Directories;
|
||||||
String FullPath;
|
String FullPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
JULIET_API bool IsValid(Path path);
|
JULIET_API bool8 IsValidPath(Path path);
|
||||||
|
|
||||||
// Returns the path to the application directory
|
// Returns the path to the application directory
|
||||||
JULIET_API Path GetBasePath();
|
JULIET_API Path GetBasePath(void);
|
||||||
|
|
||||||
// Path to the /Assets/ folder
|
// Path to the /Assets/ folder
|
||||||
JULIET_API Path GetAssetBasePath();
|
JULIET_API Path GetAssetBasePath(void);
|
||||||
|
|
||||||
// Builds a full path to an asset file given its filename (e.g. "Triangle.vert.dxil").
|
// Builds a full path to an asset file given its filename (e.g. "Triangle.vert.dxil").
|
||||||
JULIET_API Path GetAssetPath(NonNullPtr<Arena> arena, AssetType type, String filename);
|
JULIET_API Path GetAssetPath(Arena* arena, AssetType type, String filename);
|
||||||
|
|
||||||
JULIET_API bool IsAbsolutePath(String path);
|
JULIET_API bool8 IsAbsolutePath(String path);
|
||||||
|
|
||||||
JULIET_API Path fs_create_clean_path(NonNullPtr<Arena> arena, String path);
|
JULIET_API Path fs_create_clean_path(Arena* arena, String path);
|
||||||
|
|
||||||
JULIET_API bool fs_create_directory(String path, bool recursive);
|
JULIET_API bool8 fs_create_directory(String path, bool8 recursive);
|
||||||
|
|
||||||
JULIET_API bool fs_path_exists(String path);
|
JULIET_API bool8 fs_path_exists(String path);
|
||||||
|
|
||||||
JULIET_API bool fs_move_file(Path old_path, Path new_path);
|
JULIET_API bool8 fs_move_file(Path old_path, Path new_path);
|
||||||
|
|
||||||
JULIET_API bool fs_delete_file(String path);
|
JULIET_API bool8 fs_delete_file(String path);
|
||||||
|
|
||||||
using fs_iterate_director_callback = void (*)(Path path, bool is_director, void* user_payload);
|
typedef void (*fs_iterate_director_callback)(Path path, bool8 is_director, void* user_payload);
|
||||||
JULIET_API void fs_iterate_directory(Path directory_path, String extension, void* user_payload, fs_iterate_director_callback callback);
|
JULIET_API void fs_iterate_directory(Path directory_path, String extension, void* user_payload, fs_iterate_director_callback callback);
|
||||||
@@ -1,69 +1,69 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
#include <Core/HAL/Filesystem/Filesystem.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
#include "Core/HAL/Filesystem/Filesystem.h"
|
|
||||||
|
|
||||||
// Opaque type
|
// Opaque type
|
||||||
struct IOStream;
|
typedef struct IOStream IOStream;
|
||||||
|
typedef struct IOStreamDataPayload IOStreamDataPayload;
|
||||||
|
|
||||||
struct IOStreamDataPayload
|
struct IOStreamDataPayload
|
||||||
{
|
{
|
||||||
|
uint8 unused;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IOStreamStatus : uint8
|
typedef uint8 IOStreamStatus;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Ready,
|
IOStreamStatus_Ready = 0,
|
||||||
Error,
|
IOStreamStatus_Error,
|
||||||
EndOfFile,
|
IOStreamStatus_EndOfFile,
|
||||||
NotReady,
|
IOStreamStatus_NotReady,
|
||||||
ReadOnly,
|
IOStreamStatus_ReadOnly,
|
||||||
WriteOnly
|
IOStreamStatus_WriteOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IOStreamSeekPivot : uint8
|
typedef uint8 IOStreamSeekPivot;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Begin,
|
IOStreamSeekPivot_Begin = 0,
|
||||||
Current,
|
IOStreamSeekPivot_Current,
|
||||||
End,
|
IOStreamSeekPivot_End,
|
||||||
Count
|
IOStreamSeekPivot_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
// IOStream can be opened on a file or memory, or anything else.
|
typedef struct IOStreamInterface IOStreamInterface;
|
||||||
// Use the interface to make it transparent to the user.
|
|
||||||
struct IOStreamInterface
|
struct IOStreamInterface
|
||||||
{
|
{
|
||||||
uint32 Version;
|
uint32 Version;
|
||||||
|
|
||||||
int64 (*Size)(NonNullPtr<IOStreamDataPayload> data);
|
int64 (*Size)(IOStreamDataPayload* data);
|
||||||
|
|
||||||
int64 (*Seek)(NonNullPtr<IOStreamDataPayload> data, int64 offset, IOStreamSeekPivot pivot);
|
int64 (*Seek)(IOStreamDataPayload* data, int64 offset, IOStreamSeekPivot pivot);
|
||||||
size_t (*Read)(NonNullPtr<IOStreamDataPayload> data, void* outBuffer, size_t size, NonNullPtr<IOStreamStatus> status);
|
size_t (*Read)(IOStreamDataPayload* data, void* outBuffer, size_t size, IOStreamStatus* status);
|
||||||
size_t (*Write)(NonNullPtr<IOStreamDataPayload> data, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status);
|
size_t (*Write)(IOStreamDataPayload* data, ByteBuffer inBuffer, IOStreamStatus* status);
|
||||||
bool (*Flush)(NonNullPtr<IOStreamDataPayload> data, NonNullPtr<IOStreamStatus> status);
|
bool8 (*Flush)(IOStreamDataPayload* data, IOStreamStatus* status);
|
||||||
|
|
||||||
bool (*Close)(NonNullPtr<IOStreamDataPayload> data);
|
bool8 (*Close)(IOStreamDataPayload* data);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JULIET_API IOStream* IOFromFile(NonNullPtr<Arena> arena, String filename, String mode);
|
extern JULIET_API IOStream* IOFromFile(Arena* arena, String filename, String mode);
|
||||||
|
|
||||||
// Let you use an interface to open any io. Is used internally by IOFromFile
|
extern JULIET_API IOStream* IOFromInterface(Arena* arena, const IOStreamInterface* streamInterface,
|
||||||
extern JULIET_API IOStream* IOFromInterface(NonNullPtr<Arena> arena, NonNullPtr<const IOStreamInterface> streamInterface,
|
IOStreamDataPayload* payload);
|
||||||
NonNullPtr<IOStreamDataPayload> payload);
|
|
||||||
|
|
||||||
// Write formatted string into the stream.
|
JULIET_API size_t IOPrintf(IOStream* stream, const char* format, ...);
|
||||||
JULIET_API size_t IOPrintf(NonNullPtr<IOStream> stream, _Printf_format_string_ const char* format, ...);
|
JULIET_API size_t IOWrite(IOStream* stream, ByteBuffer inBuffer);
|
||||||
JULIET_API size_t IOWrite(NonNullPtr<IOStream> stream, ByteBuffer inBuffer);
|
|
||||||
|
|
||||||
JULIET_API size_t IORead(NonNullPtr<IOStream> stream, void* ptr, size_t size);
|
JULIET_API size_t IORead(IOStream* stream, void* ptr, size_t size);
|
||||||
JULIET_API int64 IOSeek(NonNullPtr<IOStream> stream, int64 offset, IOStreamSeekPivot pivot);
|
JULIET_API int64 IOSeek(IOStream* stream, int64 offset, IOStreamSeekPivot pivot);
|
||||||
|
|
||||||
JULIET_API int64 IOSize(NonNullPtr<IOStream> stream);
|
JULIET_API int64 IOSize(IOStream* stream);
|
||||||
|
|
||||||
JULIET_API ByteBuffer LoadFile(NonNullPtr<Arena> arena, String filename);
|
JULIET_API ByteBuffer LoadFile(Arena* arena, String filename);
|
||||||
JULIET_API ByteBuffer LoadFile(NonNullPtr<Arena> arena, NonNullPtr<IOStream> stream, bool closeStreamWhenDone);
|
JULIET_API ByteBuffer LoadFileFromStream(Arena* arena, IOStream* stream, bool8 closeStreamWhenDone);
|
||||||
|
|
||||||
JULIET_API size_t IO_atomic_file_write(Path filepath, ByteBuffer file_content);
|
JULIET_API size_t IO_atomic_file_write(Path filepath, ByteBuffer file_content);
|
||||||
|
|
||||||
JULIET_API bool IOClose(NonNullPtr<IOStream> stream);
|
JULIET_API bool8 IOClose(IOStream* stream);
|
||||||
@@ -1,188 +1,183 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Represents a Virtual Key corresponding to the Physical key, but localized using the keyboard layout
|
#include <Core/Common/CoreTypes.h>
|
||||||
// ScanCode reprensent US ASCII Keyboard
|
|
||||||
// WASD Scan codes are ZQSD in KeyCode for French keyboard
|
typedef uint32 KeyCode;
|
||||||
// We use the ASCII value of the generated character as value, when possible.
|
enum
|
||||||
// Keys that do not produce a character are converted to an abritrary value high enough to not conflict
|
|
||||||
// Reference: https://www.asciitable.com/
|
|
||||||
// Reference: https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-6.0/aa299374(v=vs.60)
|
|
||||||
enum class KeyCode : uint32
|
|
||||||
{
|
{
|
||||||
Unknown = 0x0, // 0
|
KeyCode_Unknown = 0x0u,
|
||||||
Unsupported = 0x0, // 0
|
KeyCode_Unsupported = 0x0u,
|
||||||
Return = 0X0Du, // '\r'
|
KeyCode_Return = 0x0Du,
|
||||||
Escape = 0X1Bu, // '\X1B'
|
KeyCode_Escape = 0x1Bu,
|
||||||
Backspace = 0X08u, // '\b'
|
KeyCode_Backspace = 0x08u,
|
||||||
Tab = 0X09u, // '\t'
|
KeyCode_Tab = 0x09u,
|
||||||
Space = 0X20u, // ' '
|
KeyCode_Space = 0x20u,
|
||||||
ExclamationPoint = 0X21u, // '!'
|
KeyCode_ExclamationPoint = 0x21u,
|
||||||
DoubleApostrophe = 0X22u, // '"'
|
KeyCode_DoubleApostrophe = 0x22u,
|
||||||
Hash = 0X23u, // '#'
|
KeyCode_Hash = 0x23u,
|
||||||
Dollar = 0X24u, // '$'
|
KeyCode_Dollar = 0x24u,
|
||||||
Percent = 0X25u, // '%'
|
KeyCode_Percent = 0x25u,
|
||||||
Ampersand = 0X26u, // '&'
|
KeyCode_Ampersand = 0x26u,
|
||||||
Apostrophe = 0X27u, // '\''
|
KeyCode_Apostrophe = 0x27u,
|
||||||
LeftParenthesis = 0X28u, // '('
|
KeyCode_LeftParenthesis = 0x28u,
|
||||||
RightParenthesis = 0X29u, // ')'
|
KeyCode_RightParenthesis = 0x29u,
|
||||||
Asterisk = 0X2Au, // '*'
|
KeyCode_Asterisk = 0x2Au,
|
||||||
Plus = 0X2Bu, // '+'
|
KeyCode_Plus = 0x2Bu,
|
||||||
Comma = 0X2Cu, // ','
|
KeyCode_Comma = 0x2Cu,
|
||||||
Minus = 0X2Du, // '-'
|
KeyCode_Minus = 0x2Du,
|
||||||
Period = 0X2Eu, // '.'
|
KeyCode_Period = 0x2Eu,
|
||||||
Slash = 0X2Fu, // '/'
|
KeyCode_Slash = 0x2Fu,
|
||||||
Num0 = 0X30u, // '0'
|
KeyCode_Num0 = 0x30u,
|
||||||
Num1 = 0X31u, // '1'
|
KeyCode_Num1 = 0x31u,
|
||||||
Num2 = 0X32u, // '2'
|
KeyCode_Num2 = 0x32u,
|
||||||
Num3 = 0X33u, // '3'
|
KeyCode_Num3 = 0x33u,
|
||||||
Num4 = 0X34u, // '4'
|
KeyCode_Num4 = 0x34u,
|
||||||
Num5 = 0X35u, // '5'
|
KeyCode_Num5 = 0x35u,
|
||||||
Num6 = 0X36u, // '6'
|
KeyCode_Num6 = 0x36u,
|
||||||
Num7 = 0X37u, // '7'
|
KeyCode_Num7 = 0x37u,
|
||||||
Num8 = 0X38u, // '8'
|
KeyCode_Num8 = 0x38u,
|
||||||
Num9 = 0X39u, // '9'
|
KeyCode_Num9 = 0x39u,
|
||||||
Colon = 0X3Au, // ':'
|
KeyCode_Colon = 0x3Au,
|
||||||
Semicolon = 0X3Bu, // ';'
|
KeyCode_Semicolon = 0x3Bu,
|
||||||
LessThan = 0X3Cu, // '<'
|
KeyCode_LessThan = 0x3Cu,
|
||||||
Equals = 0X3Du, // '='
|
KeyCode_Equals = 0x3Du,
|
||||||
GreaterThan = 0X3Eu, // '>'
|
KeyCode_GreaterThan = 0x3Eu,
|
||||||
QuestionMark = 0X3Fu, // '?'
|
KeyCode_QuestionMark = 0x3Fu,
|
||||||
CommercialAt = 0x40u, // '@'
|
KeyCode_CommercialAt = 0x40u,
|
||||||
LeftBracket = 0X5Bu, // '['
|
KeyCode_LeftBracket = 0x5Bu,
|
||||||
Backslash = 0X5Cu, // '\\'
|
KeyCode_Backslash = 0x5Cu,
|
||||||
RightBracket = 0X5DU, // ']'
|
KeyCode_RightBracket = 0x5Du,
|
||||||
Caret = 0X5Eu, // '^'
|
KeyCode_Caret = 0x5Eu,
|
||||||
Underscore = 0X5Fu, // '_'
|
KeyCode_Underscore = 0x5Fu,
|
||||||
GraveAccent = 0X60u, // '`'
|
KeyCode_GraveAccent = 0x60u,
|
||||||
A = 0x61u, // 'a'
|
KeyCode_A = 0x61u,
|
||||||
B = 0x62u, // 'b'
|
KeyCode_B = 0x62u,
|
||||||
C = 0x63u, // 'c'
|
KeyCode_C = 0x63u,
|
||||||
D = 0x64u, // 'd'
|
KeyCode_D = 0x64u,
|
||||||
E = 0x65u, // 'e'
|
KeyCode_E = 0x65u,
|
||||||
F = 0x66u, // 'f'
|
KeyCode_F = 0x66u,
|
||||||
G = 0x67u, // 'g'
|
KeyCode_G = 0x67u,
|
||||||
H = 0x68u, // 'h'
|
KeyCode_H = 0x68u,
|
||||||
I = 0x69u, // 'i'
|
KeyCode_I = 0x69u,
|
||||||
J = 0x6Au, // 'j'
|
KeyCode_J = 0x6Au,
|
||||||
K = 0x6Bu, // 'k'
|
KeyCode_K = 0x6Bu,
|
||||||
L = 0x6CU, // 'l'
|
KeyCode_L = 0x6Cu,
|
||||||
M = 0x6DU, // 'm'
|
KeyCode_M = 0x6Du,
|
||||||
N = 0x6Eu, // 'n'
|
KeyCode_N = 0x6Eu,
|
||||||
O = 0x6Fu, // 'o'
|
KeyCode_O = 0x6Fu,
|
||||||
P = 0x70u, // 'p'
|
KeyCode_P = 0x70u,
|
||||||
Q = 0x71u, // 'q'
|
KeyCode_Q = 0x71u,
|
||||||
R = 0x72u, // 'r'
|
KeyCode_R = 0x72u,
|
||||||
S = 0x73u, // 's'
|
KeyCode_S = 0x73u,
|
||||||
T = 0x74u, // 't'
|
KeyCode_T = 0x74u,
|
||||||
U = 0x75u, // 'y'
|
KeyCode_U = 0x75u,
|
||||||
V = 0x76u, // 'v'
|
KeyCode_V = 0x76u,
|
||||||
W = 0x77u, // 'w'
|
KeyCode_W = 0x77u,
|
||||||
X = 0x78u, // 'x'
|
KeyCode_X = 0x78u,
|
||||||
Y = 0x79u, // 'y'
|
KeyCode_Y = 0x79u,
|
||||||
Z = 0x7Au, // 'z'
|
KeyCode_Z = 0x7Au,
|
||||||
LeftBrace = 0x7BU, // '{'
|
KeyCode_LeftBrace = 0x7Bu,
|
||||||
Pipe = 0x7CU, // '|'
|
KeyCode_Pipe = 0x7Cu,
|
||||||
RightBrace = 0x7DU, // '}'
|
KeyCode_RightBrace = 0x7Du,
|
||||||
Tilde = 0x7Eu, // '~'
|
KeyCode_Tilde = 0x7Eu,
|
||||||
Delete = 0x7Fu, // '\x7F'
|
KeyCode_Delete = 0x7Fu,
|
||||||
PlusMinus = 0xb1u, // '\xB1'
|
KeyCode_PlusMinus = 0xb1u,
|
||||||
|
|
||||||
// Keys not producing a character
|
KeyCode_CapsLock = 0x40000039u,
|
||||||
// Based on SDL Algo: ScanCode | 0x40000000
|
KeyCode_F1 = 0x4000003Au,
|
||||||
CapsLock = 0x40000039u,
|
KeyCode_F2 = 0x4000003Bu,
|
||||||
F1 = 0x4000003Au,
|
KeyCode_F3 = 0x4000003Cu,
|
||||||
F2 = 0x4000003Bu,
|
KeyCode_F4 = 0x4000003Du,
|
||||||
F3 = 0x4000003CU,
|
KeyCode_F5 = 0x4000003Eu,
|
||||||
F4 = 0x4000003DU,
|
KeyCode_F6 = 0x4000003Fu,
|
||||||
F5 = 0x4000003Eu,
|
KeyCode_F7 = 0x40000040u,
|
||||||
F6 = 0x4000003Fu,
|
KeyCode_F8 = 0x40000041u,
|
||||||
F7 = 0x40000040u,
|
KeyCode_F9 = 0x40000042u,
|
||||||
F8 = 0x40000041u,
|
KeyCode_F10 = 0x40000043u,
|
||||||
F9 = 0x40000042u,
|
KeyCode_F11 = 0x40000044u,
|
||||||
F10 = 0x40000043u,
|
KeyCode_F12 = 0x40000045u,
|
||||||
F11 = 0x40000044u,
|
KeyCode_PrintScreen = 0x40000046u,
|
||||||
F12 = 0x40000045u,
|
KeyCode_ScrollLock = 0x40000047u,
|
||||||
PrintScreen = 0x40000046u,
|
KeyCode_Pause = 0x40000048u,
|
||||||
ScrollLock = 0x40000047u,
|
KeyCode_Insert = 0x40000049u,
|
||||||
Pause = 0x40000048u,
|
KeyCode_Home = 0x4000004Au,
|
||||||
Insert = 0x40000049u,
|
KeyCode_PageUp = 0x4000004Bu,
|
||||||
Home = 0x4000004Au,
|
KeyCode_End = 0x4000004Du,
|
||||||
PageUp = 0x4000004Bu,
|
KeyCode_PageDown = 0x4000004Eu,
|
||||||
End = 0x4000004DU,
|
KeyCode_RightArrow = 0x4000004Fu,
|
||||||
PageDown = 0x4000004Eu,
|
KeyCode_LeftArrow = 0x40000050u,
|
||||||
RightArrow = 0x4000004Fu,
|
KeyCode_DownArrow = 0x40000051u,
|
||||||
LeftArrow = 0x40000050u,
|
KeyCode_UpArrow = 0x40000052u,
|
||||||
DownArrow = 0x40000051u,
|
KeyCode_NumlockClear = 0x40000053u,
|
||||||
UpArrow = 0x40000052u,
|
KeyCode_KeyPad_Divide = 0x40000054u,
|
||||||
NumlockClear = 0x40000053u,
|
KeyCode_KeyPad_Multiply = 0x40000055u,
|
||||||
KeyPad_Divide = 0x40000054u,
|
KeyCode_KeyPad_Minus = 0x40000056u,
|
||||||
KeyPad_Multiply = 0x40000055u,
|
KeyCode_KeyPad_Plus = 0x40000057u,
|
||||||
KeyPad_Minus = 0x40000056u,
|
KeyCode_KeyPad_Enter = 0x40000058u,
|
||||||
KeyPad_Plus = 0x40000057u,
|
KeyCode_KeyPad_Num1 = 0x40000059u,
|
||||||
KeyPad_Enter = 0x40000058u,
|
KeyCode_KeyPad_Num2 = 0x4000005Au,
|
||||||
KeyPad_Num1 = 0x40000059u,
|
KeyCode_KeyPad_Num3 = 0x4000005Bu,
|
||||||
KeyPad_Num2 = 0x4000005Au,
|
KeyCode_KeyPad_Num4 = 0x4000005Cu,
|
||||||
KeyPad_Num3 = 0x4000005Bu,
|
KeyCode_KeyPad_Num5 = 0x4000005Du,
|
||||||
KeyPad_Num4 = 0x4000005Cu,
|
KeyCode_KeyPad_Num6 = 0x4000005Eu,
|
||||||
KeyPad_Num5 = 0x4000005Du,
|
KeyCode_KeyPad_Num7 = 0x4000005Fu,
|
||||||
KeyPad_Num6 = 0x4000005Eu,
|
KeyCode_KeyPad_Num8 = 0x40000060u,
|
||||||
KeyPad_Num7 = 0x4000005Fu,
|
KeyCode_KeyPad_Num9 = 0x40000061u,
|
||||||
KeyPad_Num8 = 0x40000060u,
|
KeyCode_KeyPad_Num0 = 0x40000062u,
|
||||||
KeyPad_Num9 = 0x40000061u,
|
KeyCode_KeyPad_Period = 0x40000063u,
|
||||||
KeyPad_Num0 = 0x40000062u,
|
KeyCode_Power = 0x40000066u,
|
||||||
KeyPad_Period = 0x40000063u,
|
KeyCode_KeyPad_Equals = 0x40000067u,
|
||||||
Power = 0x40000066u,
|
KeyCode_F13 = 0x40000068u,
|
||||||
KeyPad_Equals = 0x40000067u,
|
KeyCode_F14 = 0x40000069u,
|
||||||
F13 = 0x40000068u,
|
KeyCode_F15 = 0x4000006Au,
|
||||||
F14 = 0x40000069u,
|
KeyCode_F16 = 0x4000006Bu,
|
||||||
F15 = 0x4000006Au,
|
KeyCode_F17 = 0x4000006Cu,
|
||||||
F16 = 0x4000006Bu,
|
KeyCode_F18 = 0x4000006Du,
|
||||||
F17 = 0x4000006Cu,
|
KeyCode_F19 = 0x4000006Eu,
|
||||||
F18 = 0x4000006Du,
|
KeyCode_F20 = 0x4000006Fu,
|
||||||
F19 = 0x4000006Eu,
|
KeyCode_F21 = 0x40000070u,
|
||||||
F20 = 0x4000006Fu,
|
KeyCode_F22 = 0x40000071u,
|
||||||
F21 = 0x40000070u,
|
KeyCode_F23 = 0x40000072u,
|
||||||
F22 = 0x40000071u,
|
KeyCode_F24 = 0x40000073u,
|
||||||
F23 = 0x40000072u,
|
KeyCode_Mute = 0x4000007Fu,
|
||||||
F24 = 0x40000073u,
|
KeyCode_VolumeUp = 0x40000080u,
|
||||||
Mute = 0x4000007Fu,
|
KeyCode_VolumeDown = 0x40000081u,
|
||||||
VolumeUp = 0x40000080u,
|
KeyCode_KeyPad_Comma = 0x40000085u,
|
||||||
VolumeDown = 0x40000081u,
|
KeyCode_LeftControl = 0x400000E0u,
|
||||||
KeyPad_Comma = 0x40000085u,
|
KeyCode_LeftShift = 0x400000E1u,
|
||||||
LeftControl = 0x400000E0u,
|
KeyCode_LeftAlt = 0x400000E2u,
|
||||||
LeftShift = 0x400000E1u,
|
KeyCode_LeftOSCommand = 0x400000E3u,
|
||||||
LeftAlt = 0x400000E2u,
|
KeyCode_RightControl = 0x400000E4u,
|
||||||
LeftOSCommand = 0x400000E3u,
|
KeyCode_RightShift = 0x400000E5u,
|
||||||
RightControl = 0x400000E4u,
|
KeyCode_RightAlt = 0x400000E6u,
|
||||||
RightShift = 0x400000E5u,
|
KeyCode_RightOSCommand = 0x400000E7u,
|
||||||
RightAlt = 0x400000E6u,
|
KeyCode_Sleep = 0x40000102u,
|
||||||
RightOSCommand = 0x400000E7u,
|
KeyCode_WakeUp = 0x40000103u,
|
||||||
Sleep = 0x40000102u,
|
KeyCode_Media_NextTrack = 0x4000010Bu,
|
||||||
WakeUp = 0x40000103u,
|
KeyCode_Media_PreviousTrack = 0x4000010Cu,
|
||||||
Media_NextTrack = 0x4000010Bu,
|
KeyCode_Media_Stop = 0x4000010Du,
|
||||||
Media_PreviousTrack = 0x4000010Cu,
|
KeyCode_Media_Eject = 0x4000010Eu,
|
||||||
Media_Stop = 0x4000010Du,
|
KeyCode_Media_PlayPause = 0x4000010Fu,
|
||||||
Media_Eject = 0x4000010Eu,
|
KeyCode_Media_Select = 0x40000110u,
|
||||||
Media_PlayPause = 0x4000010Fu,
|
|
||||||
Media_Select = 0x40000110u,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class KeyMod : uint16
|
typedef uint16 KeyMod;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
None = 0b0,
|
KeyMod_None = 0x0000u,
|
||||||
LeftShift = 0b0000'0000'0001u,
|
KeyMod_LeftShift = 0x0001u,
|
||||||
RightShift = 0b0000'0000'0010u,
|
KeyMod_RightShift = 0x0002u,
|
||||||
LeftControl = 0b0000'0000'0100u,
|
KeyMod_LeftControl = 0x0004u,
|
||||||
RightControl = 0b0000'0000'1000u,
|
KeyMod_RightControl = 0x0008u,
|
||||||
LeftAlt = 0b0000'0001'000u,
|
KeyMod_LeftAlt = 0x0010u,
|
||||||
RightAlt = 0b0000'0010'0000u,
|
KeyMod_RightAlt = 0x0020u,
|
||||||
LeftOSCommand = 0b0000'0100'0000u,
|
KeyMod_LeftOSCommand = 0x0040u,
|
||||||
RightOSCommand = 0b0000'1000'0000u,
|
KeyMod_RightOSCommand = 0x0080u,
|
||||||
NumLock = 0b0001'0000'0000u,
|
KeyMod_NumLock = 0x0100u,
|
||||||
CapsLock = 0b0010'0000'0000u,
|
KeyMod_CapsLock = 0x0200u,
|
||||||
ScrollLock = 0b0100'0000'0000u,
|
KeyMod_ScrollLock = 0x0400u,
|
||||||
Control = LeftControl | RightControl,
|
KeyMod_Control = KeyMod_LeftControl | KeyMod_RightControl,
|
||||||
Shift = LeftShift | RightShift,
|
KeyMod_Shift = KeyMod_LeftShift | KeyMod_RightShift,
|
||||||
Alt = LeftAlt | RightAlt,
|
KeyMod_Alt = KeyMod_LeftAlt | KeyMod_RightAlt,
|
||||||
OSCommand = LeftOSCommand | RightOSCommand,
|
KeyMod_OSCommand = KeyMod_LeftOSCommand | KeyMod_RightOSCommand,
|
||||||
};
|
};
|
||||||
@@ -1,23 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/HAL/Keyboard/KeyCode.h>
|
#include <Core/HAL/Keyboard/KeyCode.h>
|
||||||
#include <Core/HAL/Keyboard/ScanCode.h>
|
#include <Core/HAL/Keyboard/ScanCode.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
using KeyboardID = uint8;
|
typedef uint8 KeyboardID;
|
||||||
|
|
||||||
enum class KeyPosition : bool
|
typedef bool8 KeyPosition;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Up = false,
|
KeyPosition_Up = false,
|
||||||
Down = true
|
KeyPosition_Down = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct KeyState KeyState;
|
||||||
struct KeyState
|
struct KeyState
|
||||||
{
|
{
|
||||||
KeyPosition Position;
|
KeyPosition Position;
|
||||||
float Time;
|
float Time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct Key Key;
|
||||||
struct Key
|
struct Key
|
||||||
{
|
{
|
||||||
ScanCode ScanCode;
|
ScanCode ScanCode;
|
||||||
@@ -25,8 +28,8 @@ struct Key
|
|||||||
uint16 Raw;
|
uint16 Raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JULIET_API bool IsKeyDown(ScanCode scanCode);
|
extern JULIET_API bool8 IsKeyDown(ScanCode scanCode);
|
||||||
extern JULIET_API bool IsKeyPressed(ScanCode scanCode);
|
extern JULIET_API bool8 IsKeyPressed(ScanCode scanCode);
|
||||||
|
|
||||||
extern JULIET_API KeyMod GetKeyModState();
|
extern JULIET_API KeyMod GetKeyModState(void);
|
||||||
extern JULIET_API KeyCode GetKeyCodeFromScanCode(ScanCode scanCode, KeyMod keyModState);
|
extern JULIET_API KeyCode GetKeyCodeFromScanCode(ScanCode scanCode, KeyMod keyModState);
|
||||||
@@ -1,183 +1,180 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Follow the HID Usage page for USB
|
#include <Core/Common/CoreTypes.h>
|
||||||
// https://usb.org/sites/default/files/hut1_5.pdf
|
|
||||||
// 0 to 256 Is dedicated to Keyboard Usage Page (0x07)
|
typedef uint16 ScanCode;
|
||||||
// 257 to 286 Is dedicated to Consumer Usage Page (0xC)
|
enum
|
||||||
// 287 to 511 Is not implemented. Could be used for Mobile or Consoles
|
|
||||||
// ScanCode reprensent Physical Keys and Buttons
|
|
||||||
enum class ScanCode : uint16
|
|
||||||
{
|
{
|
||||||
Unknown = 0,
|
ScanCode_Unknown = 0,
|
||||||
Unsupported = 0,
|
ScanCode_Unsupported = 0,
|
||||||
|
|
||||||
A = 4,
|
ScanCode_A = 4,
|
||||||
B = 5,
|
ScanCode_B = 5,
|
||||||
C = 6,
|
ScanCode_C = 6,
|
||||||
D = 7,
|
ScanCode_D = 7,
|
||||||
E = 8,
|
ScanCode_E = 8,
|
||||||
F = 9,
|
ScanCode_F = 9,
|
||||||
G = 10,
|
ScanCode_G = 10,
|
||||||
H = 11,
|
ScanCode_H = 11,
|
||||||
I = 12,
|
ScanCode_I = 12,
|
||||||
J = 13,
|
ScanCode_J = 13,
|
||||||
K = 14,
|
ScanCode_K = 14,
|
||||||
L = 15,
|
ScanCode_L = 15,
|
||||||
M = 16,
|
ScanCode_M = 16,
|
||||||
N = 17,
|
ScanCode_N = 17,
|
||||||
O = 18,
|
ScanCode_O = 18,
|
||||||
P = 19,
|
ScanCode_P = 19,
|
||||||
Q = 20,
|
ScanCode_Q = 20,
|
||||||
R = 21,
|
ScanCode_R = 21,
|
||||||
S = 22,
|
ScanCode_S = 22,
|
||||||
T = 23,
|
ScanCode_T = 23,
|
||||||
U = 24,
|
ScanCode_U = 24,
|
||||||
V = 25,
|
ScanCode_V = 25,
|
||||||
W = 26,
|
ScanCode_W = 26,
|
||||||
X = 27,
|
ScanCode_X = 27,
|
||||||
Y = 28,
|
ScanCode_Y = 28,
|
||||||
Z = 29,
|
ScanCode_Z = 29,
|
||||||
|
|
||||||
Num1 = 30,
|
ScanCode_Num1 = 30,
|
||||||
Num2 = 31,
|
ScanCode_Num2 = 31,
|
||||||
Num3 = 32,
|
ScanCode_Num3 = 32,
|
||||||
Num4 = 33,
|
ScanCode_Num4 = 33,
|
||||||
Num5 = 34,
|
ScanCode_Num5 = 34,
|
||||||
Num6 = 35,
|
ScanCode_Num6 = 35,
|
||||||
Num7 = 36,
|
ScanCode_Num7 = 36,
|
||||||
Num8 = 37,
|
ScanCode_Num8 = 37,
|
||||||
Num9 = 38,
|
ScanCode_Num9 = 38,
|
||||||
Num0 = 39,
|
ScanCode_Num0 = 39,
|
||||||
|
|
||||||
Return = 40,
|
ScanCode_Return = 40,
|
||||||
Escape = 41,
|
ScanCode_Escape = 41,
|
||||||
Backspace = 42,
|
ScanCode_Backspace = 42,
|
||||||
Tab = 43,
|
ScanCode_Tab = 43,
|
||||||
Space = 44,
|
ScanCode_Space = 44,
|
||||||
|
|
||||||
Minus = 45,
|
ScanCode_Minus = 45,
|
||||||
Equals = 46,
|
ScanCode_Equals = 46,
|
||||||
LeftBracket = 47,
|
ScanCode_LeftBracket = 47,
|
||||||
RightBracket = 48,
|
ScanCode_RightBracket = 48,
|
||||||
Backslash = 49,
|
ScanCode_Backslash = 49,
|
||||||
NonUSHash = 50, // Same as 49 but for ISO keyboards
|
ScanCode_NonUSHash = 50,
|
||||||
Semicolon = 51,
|
ScanCode_Semicolon = 51,
|
||||||
Apostrophe = 52,
|
ScanCode_Apostrophe = 52,
|
||||||
GraveAccent = 53,
|
ScanCode_GraveAccent = 53,
|
||||||
Comma = 54,
|
ScanCode_Comma = 54,
|
||||||
Period = 55,
|
ScanCode_Period = 55,
|
||||||
Slash = 56,
|
ScanCode_Slash = 56,
|
||||||
CapsLock = 57,
|
ScanCode_CapsLock = 57,
|
||||||
|
|
||||||
F1 = 58,
|
ScanCode_F1 = 58,
|
||||||
F2 = 59,
|
ScanCode_F2 = 59,
|
||||||
F3 = 60,
|
ScanCode_F3 = 60,
|
||||||
F4 = 61,
|
ScanCode_F4 = 61,
|
||||||
F5 = 62,
|
ScanCode_F5 = 62,
|
||||||
F6 = 63,
|
ScanCode_F6 = 63,
|
||||||
F7 = 64,
|
ScanCode_F7 = 64,
|
||||||
F8 = 65,
|
ScanCode_F8 = 65,
|
||||||
F9 = 66,
|
ScanCode_F9 = 66,
|
||||||
F10 = 67,
|
ScanCode_F10 = 67,
|
||||||
F11 = 68,
|
ScanCode_F11 = 68,
|
||||||
F12 = 69,
|
ScanCode_F12 = 69,
|
||||||
|
|
||||||
PrintScreen = 70,
|
ScanCode_PrintScreen = 70,
|
||||||
ScrollLock = 71,
|
ScanCode_ScrollLock = 71,
|
||||||
Pause = 72,
|
ScanCode_Pause = 72,
|
||||||
Insert = 73,
|
ScanCode_Insert = 73,
|
||||||
|
|
||||||
Home = 74,
|
ScanCode_Home = 74,
|
||||||
PageUp = 75,
|
ScanCode_PageUp = 75,
|
||||||
Delete = 76,
|
ScanCode_Delete = 76,
|
||||||
End = 77,
|
ScanCode_End = 77,
|
||||||
PageDown = 78,
|
ScanCode_PageDown = 78,
|
||||||
RightArrow = 79,
|
ScanCode_RightArrow = 79,
|
||||||
LeftArrow = 80,
|
ScanCode_LeftArrow = 80,
|
||||||
DownArrow = 81,
|
ScanCode_DownArrow = 81,
|
||||||
UpArrow = 82,
|
ScanCode_UpArrow = 82,
|
||||||
|
|
||||||
NumlockClear = 83, // Pc = Numlock / Mac = Clear
|
ScanCode_NumlockClear = 83,
|
||||||
|
|
||||||
KeyPad_Divide = 84,
|
ScanCode_KeyPad_Divide = 84,
|
||||||
KeyPad_Multiply = 85,
|
ScanCode_KeyPad_Multiply = 85,
|
||||||
KeyPad_Minus = 86,
|
ScanCode_KeyPad_Minus = 86,
|
||||||
KeyPad_Plus = 87,
|
ScanCode_KeyPad_Plus = 87,
|
||||||
KeyPad_Enter = 88,
|
ScanCode_KeyPad_Enter = 88,
|
||||||
KeyPad_Num1 = 89,
|
ScanCode_KeyPad_Num1 = 89,
|
||||||
KeyPad_Num2 = 90,
|
ScanCode_KeyPad_Num2 = 90,
|
||||||
KeyPad_Num3 = 91,
|
ScanCode_KeyPad_Num3 = 91,
|
||||||
KeyPad_Num4 = 92,
|
ScanCode_KeyPad_Num4 = 92,
|
||||||
KeyPad_Num5 = 93,
|
ScanCode_KeyPad_Num5 = 93,
|
||||||
KeyPad_Num6 = 94,
|
ScanCode_KeyPad_Num6 = 94,
|
||||||
KeyPad_Num7 = 95,
|
ScanCode_KeyPad_Num7 = 95,
|
||||||
KeyPad_Num8 = 96,
|
ScanCode_KeyPad_Num8 = 96,
|
||||||
KeyPad_Num9 = 97,
|
ScanCode_KeyPad_Num9 = 97,
|
||||||
KeyPad_Num0 = 98,
|
ScanCode_KeyPad_Num0 = 98,
|
||||||
KeyPad_Period = 99,
|
ScanCode_KeyPad_Period = 99,
|
||||||
|
|
||||||
NonUSBackslash = 100, // ISO keyboards only
|
ScanCode_NonUSBackslash = 100,
|
||||||
Power = 102, // Some mac have a Power key
|
ScanCode_Power = 102,
|
||||||
|
|
||||||
KeyPad_Equals = 103,
|
ScanCode_KeyPad_Equals = 103,
|
||||||
F13 = 104,
|
ScanCode_F13 = 104,
|
||||||
F14 = 105,
|
ScanCode_F14 = 105,
|
||||||
F15 = 106,
|
ScanCode_F15 = 106,
|
||||||
F16 = 107,
|
ScanCode_F16 = 107,
|
||||||
F17 = 108,
|
ScanCode_F17 = 108,
|
||||||
F18 = 109,
|
ScanCode_F18 = 109,
|
||||||
F19 = 110,
|
ScanCode_F19 = 110,
|
||||||
F20 = 111,
|
ScanCode_F20 = 111,
|
||||||
F21 = 112,
|
ScanCode_F21 = 112,
|
||||||
F22 = 113,
|
ScanCode_F22 = 113,
|
||||||
F23 = 114,
|
ScanCode_F23 = 114,
|
||||||
F24 = 115,
|
ScanCode_F24 = 115,
|
||||||
|
|
||||||
Mute = 127,
|
ScanCode_Mute = 127,
|
||||||
VolumeUp = 128,
|
ScanCode_VolumeUp = 128,
|
||||||
VolumeDown = 129,
|
ScanCode_VolumeDown = 129,
|
||||||
|
|
||||||
KeyPad_Comma = 133,
|
ScanCode_KeyPad_Comma = 133,
|
||||||
|
|
||||||
International1 = 135, // Mostly used on Asian keyboards
|
ScanCode_International1 = 135,
|
||||||
International2 = 136,
|
ScanCode_International2 = 136,
|
||||||
International3 = 137, // Yen Symbol
|
ScanCode_International3 = 137,
|
||||||
International4 = 138,
|
ScanCode_International4 = 138,
|
||||||
International5 = 139,
|
ScanCode_International5 = 139,
|
||||||
International6 = 140,
|
ScanCode_International6 = 140,
|
||||||
International7 = 141,
|
ScanCode_International7 = 141,
|
||||||
International8 = 142,
|
ScanCode_International8 = 142,
|
||||||
International9 = 143,
|
ScanCode_International9 = 143,
|
||||||
Lang1 = 144, // Hangul (Korean)
|
ScanCode_Lang1 = 144,
|
||||||
Lang2 = 145, // Hanja (Korean)
|
ScanCode_Lang2 = 145,
|
||||||
Lang3 = 146, // Katakana (Japanese)
|
ScanCode_Lang3 = 146,
|
||||||
Lang4 = 147, // Hiragana (Japanese)
|
ScanCode_Lang4 = 147,
|
||||||
Lang5 = 148, // Zenkaku/Hankaku (Japanese)
|
ScanCode_Lang5 = 148,
|
||||||
Lang6 = 149, // Unused
|
ScanCode_Lang6 = 149,
|
||||||
Lang7 = 150, // Unused
|
ScanCode_Lang7 = 150,
|
||||||
Lang8 = 151, // Unused
|
ScanCode_Lang8 = 151,
|
||||||
Lang9 = 152, // Unused
|
ScanCode_Lang9 = 152,
|
||||||
|
|
||||||
LeftControl = 224,
|
ScanCode_LeftControl = 224,
|
||||||
LeftShift = 225,
|
ScanCode_LeftShift = 225,
|
||||||
LeftAlt = 226, // Alt for PC, Option for Mac
|
ScanCode_LeftAlt = 226,
|
||||||
LeftOSCommand = 227, // Window key for PC, Command for Mac
|
ScanCode_LeftOSCommand = 227,
|
||||||
RightControl = 228,
|
ScanCode_RightControl = 228,
|
||||||
RightShift = 229,
|
ScanCode_RightShift = 229,
|
||||||
RightAlt = 230, // Alt Gr for PC, Option for Mac
|
ScanCode_RightAlt = 230,
|
||||||
RightOSCommand = 231, // Window key for PC, Command for Mac
|
ScanCode_RightOSCommand = 231,
|
||||||
|
|
||||||
Sleep = 258,
|
ScanCode_Sleep = 258,
|
||||||
WakeUp = 259,
|
ScanCode_WakeUp = 259,
|
||||||
|
|
||||||
Media_NextTrack = 267,
|
ScanCode_Media_NextTrack = 267,
|
||||||
Media_PreviousTrack = 268,
|
ScanCode_Media_PreviousTrack = 268,
|
||||||
Media_Stop = 269,
|
ScanCode_Media_Stop = 269,
|
||||||
Media_Eject = 270,
|
ScanCode_Media_Eject = 270,
|
||||||
Media_PlayPause = 271,
|
ScanCode_Media_PlayPause = 271,
|
||||||
Media_Select = 272,
|
ScanCode_Media_Select = 272,
|
||||||
|
|
||||||
Reserved = 287,
|
ScanCode_Reserved = 287,
|
||||||
|
|
||||||
Count = 512
|
ScanCode_Count = 512
|
||||||
};
|
};
|
||||||
@@ -1,25 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
using MouseID = uint8;
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
enum class MouseButton : uint8
|
typedef uint8 MouseID;
|
||||||
|
|
||||||
|
typedef uint8 MouseButton;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
None = 0,
|
MouseButton_None = 0,
|
||||||
Left = 1 << 0,
|
MouseButton_Left = 1 << 0,
|
||||||
Right = 1 << 1,
|
MouseButton_Right = 1 << 1,
|
||||||
Middle = 1 << 2,
|
MouseButton_Middle = 1 << 2,
|
||||||
Button1 = 1 << 3,
|
MouseButton_Button1 = 1 << 3,
|
||||||
Button2 = 1 << 4,
|
MouseButton_Button2 = 1 << 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO : Replace by Vector2f
|
typedef struct MousePosition MousePosition;
|
||||||
struct MousePosition
|
struct MousePosition
|
||||||
{
|
{
|
||||||
float X;
|
float X;
|
||||||
float Y;
|
float Y;
|
||||||
};
|
};
|
||||||
|
|
||||||
JULIET_API extern bool IsMouseButtonDown(MouseButton button);
|
JULIET_API extern bool8 IsMouseButtonDown(MouseButton button);
|
||||||
JULIET_API extern MousePosition GetMousePosition();
|
JULIET_API extern MousePosition GetMousePosition(void);
|
||||||
JULIET_API extern MousePosition GetMouseDelta();
|
JULIET_API extern MousePosition GetMouseDelta(void);
|
||||||
JULIET_API extern MouseButton GetMouseButtonState();
|
JULIET_API extern MouseButton GetMouseButtonState(void);
|
||||||
@@ -1,52 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
|
||||||
namespace Memory
|
Byte* OS_Reserve(size_t size);
|
||||||
{
|
bool8 OS_Commit(void* ptr, size_t size);
|
||||||
Byte* OS_Reserve(size_t size);
|
void OS_Release(void* ptr, size_t size);
|
||||||
bool OS_Commit(Byte* ptr, size_t size);
|
|
||||||
void OS_Release(Byte* ptr, size_t size);
|
|
||||||
|
|
||||||
template <typename Type>
|
uint64 Time_Timestamp(void);
|
||||||
Type* OS_Reserve(size_t size)
|
void Time_ComputeDeltaTime(void);
|
||||||
{
|
float Time_GetDeltaTime(void);
|
||||||
return reinterpret_cast<Type*>(OS_Reserve(size));
|
uint64 Time_GetFrameNumber(void);
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
JULIET_API bool8 Debug_IsDebuggerPresent(void);
|
||||||
bool OS_Commit(Type* ptr, size_t size)
|
|
||||||
{
|
|
||||||
return OS_Commit(reinterpret_cast<Byte*>(ptr), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
String os_get_env_var(Arena* arena, String name);
|
||||||
void OS_Release(Type* ptr, size_t size)
|
void os_set_env_var(String name, String value);
|
||||||
{
|
|
||||||
OS_Release(reinterpret_cast<Byte*>(ptr), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Memory
|
String os_get_username(Arena* arena);
|
||||||
|
|
||||||
namespace Time
|
typedef int (*EntryPointFunc)(int, wchar_t**);
|
||||||
{
|
|
||||||
uint64 Timestamp();
|
|
||||||
void ComputeDeltaTime();
|
|
||||||
float GetDeltaTime();
|
|
||||||
uint64 GetFrameNumber();
|
|
||||||
} // namespace Time
|
|
||||||
|
|
||||||
namespace Debug
|
|
||||||
{
|
|
||||||
JULIET_API bool IsDebuggerPresent();
|
|
||||||
} // namespace Debug
|
|
||||||
|
|
||||||
String os_get_env_var(NonNullPtr<Arena> arena, const String& name);
|
|
||||||
void os_set_env_var(const String& name, const String& value);
|
|
||||||
|
|
||||||
String os_get_username(NonNullPtr<Arena> arena);
|
|
||||||
|
|
||||||
using EntryPointFunc = int (*)(int, wchar_t**);
|
|
||||||
JULIET_API int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
|
JULIET_API int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
// Fwd Declare
|
typedef struct DynamicLibrary DynamicLibrary;
|
||||||
struct DynamicLibrary;
|
typedef struct HotReloadCode HotReloadCode;
|
||||||
|
|
||||||
struct HotReloadCode
|
struct HotReloadCode
|
||||||
{
|
{
|
||||||
@@ -21,15 +21,15 @@ struct HotReloadCode
|
|||||||
|
|
||||||
uint32 UniqueID;
|
uint32 UniqueID;
|
||||||
|
|
||||||
bool IsValid : 1;
|
bool8 IsValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JULIET_API void InitHotReloadCode(NonNullPtr<Arena> arena, HotReloadCode& code, String dllName,
|
extern JULIET_API void InitHotReloadCode(Arena* arena, HotReloadCode* code, String dllName,
|
||||||
String transientDllName, String lockFilename);
|
String transientDllName, String lockFilename);
|
||||||
extern JULIET_API void ShutdownHotReloadCode(HotReloadCode& code);
|
extern JULIET_API void ShutdownHotReloadCode(HotReloadCode* code);
|
||||||
|
|
||||||
extern JULIET_API void LoadCode(HotReloadCode& code);
|
extern JULIET_API void LoadCode(HotReloadCode* code);
|
||||||
extern JULIET_API void UnloadCode(HotReloadCode& code);
|
extern JULIET_API void UnloadCode(HotReloadCode* code);
|
||||||
|
|
||||||
extern JULIET_API void ReloadCode(HotReloadCode& code);
|
extern JULIET_API void ReloadCode(HotReloadCode* code);
|
||||||
extern JULIET_API bool ShouldReloadCode(const HotReloadCode& code);
|
extern JULIET_API bool8 ShouldReloadCode(const HotReloadCode* code);
|
||||||
@@ -1,27 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
#ifdef JULIET_ENABLE_IMGUI
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
|
|
||||||
struct ImGuiContext;
|
typedef struct ImGuiContext ImGuiContext;
|
||||||
|
typedef struct Window Window;
|
||||||
|
typedef struct GraphicsDevice GraphicsDevice;
|
||||||
|
|
||||||
struct Window;
|
JULIET_API void ImGuiService_Initialize(Window* window);
|
||||||
struct GraphicsDevice;
|
JULIET_API void ImGuiService_Shutdown(void);
|
||||||
|
|
||||||
namespace ImGuiService
|
JULIET_API void ImGuiService_NewFrame(void);
|
||||||
{
|
JULIET_API void ImGuiService_Render(void);
|
||||||
JULIET_API void Initialize(NonNullPtr<Window> window);
|
|
||||||
JULIET_API void Shutdown();
|
|
||||||
|
|
||||||
JULIET_API void NewFrame();
|
JULIET_API bool8 ImGuiService_IsInitialized(void);
|
||||||
JULIET_API void Render();
|
JULIET_API ImGuiContext* ImGuiService_GetContext(void);
|
||||||
|
|
||||||
JULIET_API bool IsInitialized();
|
// Run internal unit tests
|
||||||
JULIET_API ImGuiContext* GetContext();
|
JULIET_API void ImGuiService_RunTests(void);
|
||||||
|
|
||||||
// Run internal unit tests
|
|
||||||
JULIET_API void RunTests();
|
|
||||||
} // namespace ImGuiService
|
|
||||||
|
|
||||||
#endif // JULIET_ENABLE_IMGUI
|
#endif // JULIET_ENABLE_IMGUI
|
||||||
@@ -1,12 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/HAL/Display/Window.h>
|
|
||||||
#include <Graphics/GraphicsDevice.h>
|
|
||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
namespace UnitTest
|
void UnitTest_TestImGui(void);
|
||||||
{
|
|
||||||
void TestImGui();
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum class JulietInit_Flags : uint8
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
typedef uint8 JulietInit_Flags;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
None = 0,
|
JulietInit_Flags_None = 0,
|
||||||
Display = 1 << 0,
|
JulietInit_Flags_Display = 1 << 0,
|
||||||
Audio = 1 << 1,
|
JulietInit_Flags_Audio = 1 << 1,
|
||||||
Count = Audio,
|
JulietInit_Flags_Count = JulietInit_Flags_Audio,
|
||||||
All = 0xFb
|
JulietInit_Flags_All = 0xFbu
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Arena;
|
typedef struct Arena Arena;
|
||||||
|
typedef struct GameState GameState;
|
||||||
|
typedef struct GameData GameData;
|
||||||
|
|
||||||
struct GameData
|
struct GameData
|
||||||
{
|
{
|
||||||
struct GameState* GameState;
|
GameState* GameState;
|
||||||
Arena* ScratchArena;
|
Arena* ScratchArena;
|
||||||
};
|
};
|
||||||
|
|
||||||
void JulietInit(JulietInit_Flags flags);
|
void JulietInit(JulietInit_Flags flags);
|
||||||
void JulietShutdown();
|
void JulietShutdown(void);
|
||||||
@@ -1,21 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Logging/LogTypes.h>
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
|
||||||
// TODO : Juliet strings
|
extern void JULIET_API InitializeLogManager(void);
|
||||||
// TODO Juliet Containers + Allocators...
|
extern void JULIET_API ShutdownLogManager(void);
|
||||||
// TODO: Juliet chrono, because it prevents me from doing #define global static
|
|
||||||
|
|
||||||
enum class LogLevel : uint8;
|
extern void JULIET_API LogScopeBegin(void);
|
||||||
enum class LogCategory : uint8;
|
extern void JULIET_API LogScopeEnd(void);
|
||||||
|
|
||||||
extern void JULIET_API InitializeLogManager();
|
|
||||||
extern void JULIET_API ShutdownLogManager();
|
|
||||||
|
|
||||||
extern void JULIET_API LogScopeBegin();
|
|
||||||
// TODO everything that happened in there to export them to file or something
|
|
||||||
extern void JULIET_API LogScopeEnd();
|
|
||||||
|
|
||||||
extern void JULIET_API Log(LogLevel level, LogCategory category, const char* fmt, ...);
|
extern void JULIET_API Log(LogLevel level, LogCategory category, const char* fmt, ...);
|
||||||
extern void JULIET_API LogDebug(LogCategory category, const char* fmt, ...);
|
extern void JULIET_API LogDebug(LogCategory category, const char* fmt, ...);
|
||||||
|
|||||||
@@ -1,19 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum class LogLevel : uint8
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
typedef uint8 LogLevel;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Debug = 0,
|
LogLevel_Debug = 0,
|
||||||
Message = 1,
|
LogLevel_Message = 1,
|
||||||
Warning = 2,
|
LogLevel_Warning = 2,
|
||||||
Error = 3,
|
LogLevel_Error = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class LogCategory : uint8
|
typedef uint8 LogCategory;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
Core = 0,
|
LogCategory_Core = 0,
|
||||||
Graphics = 1,
|
LogCategory_Graphics = 1,
|
||||||
Networking = 2,
|
LogCategory_Networking = 2,
|
||||||
Engine = 3,
|
LogCategory_Engine = 3,
|
||||||
Tool = 4,
|
LogCategory_Tool = 4,
|
||||||
Game = 5,
|
LogCategory_Game = 5,
|
||||||
};
|
};
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/HAL/OS/OS.h>
|
#include <Core/HAL/OS/OS.h>
|
||||||
|
|
||||||
extern int JulietMain(int, wchar_t**);
|
extern int JulietMain(int argc, wchar_t** argv);
|
||||||
|
|
||||||
#if JULIET_WIN32
|
#if JULIET_WIN32
|
||||||
#ifndef WINAPI
|
#ifndef WINAPI
|
||||||
@@ -17,12 +17,10 @@ int wmain(int argc, wchar_t** argv)
|
|||||||
#else
|
#else
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
return Bootstrap(JulietMain, argc, argv);
|
return Bootstrap(JulietMain, argc, (wchar_t**)argv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
typedef struct HINSTANCE__* HINSTANCE;
|
typedef struct HINSTANCE__* HINSTANCE;
|
||||||
typedef char* LPSTR;
|
typedef char* LPSTR;
|
||||||
typedef wchar_t* PWSTR;
|
typedef wchar_t* PWSTR;
|
||||||
@@ -40,7 +38,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
|
|||||||
|
|
||||||
return Bootstrap(JulietMain, __argc, __wargv);
|
return Bootstrap(JulietMain, __argc, __wargv);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
#error "Only windows main is implemented"
|
#error "Only windows main is implemented"
|
||||||
#endif
|
#endif
|
||||||
@@ -1,46 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Juliet.h>
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
extern JULIET_API float RoundF(float value);
|
extern JULIET_API float RoundF(float value);
|
||||||
|
|
||||||
inline int32 LRoundF(float value)
|
static inline int32 LRoundF(float value)
|
||||||
{
|
{
|
||||||
return static_cast<int32>(RoundF(value));
|
return (int32)RoundF(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
#define Min(lhs, rhs) (((rhs) < (lhs)) ? (rhs) : (lhs))
|
||||||
constexpr Type Min(Type lhs, Type rhs)
|
#define Max(lhs, rhs) (((lhs) < (rhs)) ? (rhs) : (lhs))
|
||||||
{
|
#define ClampTop(value, X) Min((value), (X))
|
||||||
return rhs < lhs ? rhs : lhs;
|
#define ClampBottom(value, X) Max((value), (X))
|
||||||
}
|
#define Clamp(val, min_v, max_v) (((val) < (min_v)) ? (min_v) : (((val) > (max_v)) ? (max_v) : (val)))
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
constexpr Type Max(Type lhs, Type rhs)
|
|
||||||
{
|
|
||||||
return lhs < rhs ? rhs : lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
constexpr Type ClampTop(Type value, Type X)
|
|
||||||
{
|
|
||||||
return Min(value, X);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
constexpr Type ClampBottom(Type value, Type X)
|
|
||||||
{
|
|
||||||
return Max(value, X);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
constexpr Type Clamp(Type val, Type min, Type max)
|
|
||||||
{
|
|
||||||
if (val < min)
|
|
||||||
{
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
if (val > max)
|
|
||||||
{
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Math/Vector.h>
|
#include <Core/Math/Vector.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
typedef struct Matrix Matrix;
|
||||||
struct Matrix
|
struct Matrix
|
||||||
{
|
{
|
||||||
float m[4][4];
|
float m[4][4];
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixIdentity()
|
static inline Matrix MatrixIdentity(void)
|
||||||
{
|
{
|
||||||
Matrix result = {};
|
Matrix result = { 0 };
|
||||||
result.m[0][0] = 1.0f;
|
result.m[0][0] = 1.0f;
|
||||||
result.m[1][1] = 1.0f;
|
result.m[1][1] = 1.0f;
|
||||||
result.m[2][2] = 1.0f;
|
result.m[2][2] = 1.0f;
|
||||||
@@ -18,9 +19,9 @@ struct Matrix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix operator*(const Matrix& lhs, const Matrix& rhs)
|
static inline Matrix MatrixMultiply(Matrix lhs, Matrix rhs)
|
||||||
{
|
{
|
||||||
Matrix result = {};
|
Matrix result = { 0 };
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 4; ++j)
|
for (int j = 0; j < 4; ++j)
|
||||||
@@ -34,7 +35,7 @@ struct Matrix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixTranslation(float x, float y, float z)
|
static inline Matrix MatrixTranslation(float x, float y, float z)
|
||||||
{
|
{
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
result.m[0][3] = x;
|
result.m[0][3] = x;
|
||||||
@@ -43,7 +44,7 @@ struct Matrix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixScale(float x, float y, float z)
|
static inline Matrix MatrixScale(float x, float y, float z)
|
||||||
{
|
{
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
result.m[0][0] = x;
|
result.m[0][0] = x;
|
||||||
@@ -52,7 +53,7 @@ struct Matrix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixRotationX(float radians)
|
static inline Matrix MatrixRotationX(float radians)
|
||||||
{
|
{
|
||||||
float c = cosf(radians);
|
float c = cosf(radians);
|
||||||
float s = sinf(radians);
|
float s = sinf(radians);
|
||||||
@@ -64,7 +65,7 @@ struct Matrix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixRotationY(float radians)
|
static inline Matrix MatrixRotationY(float radians)
|
||||||
{
|
{
|
||||||
float c = cosf(radians);
|
float c = cosf(radians);
|
||||||
float s = sinf(radians);
|
float s = sinf(radians);
|
||||||
@@ -76,7 +77,7 @@ struct Matrix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixRotationZ(float radians)
|
static inline Matrix MatrixRotationZ(float radians)
|
||||||
{
|
{
|
||||||
float c = cosf(radians);
|
float c = cosf(radians);
|
||||||
float s = sinf(radians);
|
float s = sinf(radians);
|
||||||
@@ -88,26 +89,26 @@ struct Matrix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MatrixTranslate(Matrix& m, const Vector3& v)
|
static inline void MatrixTranslate(Matrix* m, Vector3 v)
|
||||||
{
|
{
|
||||||
m.m[0][3] += v.x;
|
m->m[0][3] += v.x;
|
||||||
m.m[1][3] += v.y;
|
m->m[1][3] += v.y;
|
||||||
m.m[2][3] += v.z;
|
m->m[2][3] += v.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixRotation(float x, float y, float z)
|
static inline Matrix MatrixRotation(float x, float y, float z)
|
||||||
{
|
{
|
||||||
return MatrixRotationX(x) * MatrixRotationY(y) * MatrixRotationZ(z);
|
return MatrixMultiply(MatrixMultiply(MatrixRotationX(x), MatrixRotationY(y)), MatrixRotationZ(z));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& up)
|
static inline Matrix LookAt(Vector3 eye, Vector3 target, Vector3 up)
|
||||||
{
|
{
|
||||||
// Left-Handed convention
|
// Left-Handed convention
|
||||||
Vector3 zaxis = Normalize(target - eye); // Forward is +z
|
Vector3 zaxis = Normalize(Vector3Sub(target, eye)); // Forward is +z
|
||||||
Vector3 xaxis = Normalize(Cross(up, zaxis));
|
Vector3 xaxis = Normalize(Cross(up, zaxis));
|
||||||
Vector3 yaxis = Cross(zaxis, xaxis);
|
Vector3 yaxis = Cross(zaxis, xaxis);
|
||||||
|
|
||||||
Matrix result = {};
|
Matrix result = { 0 };
|
||||||
// Row 0
|
// Row 0
|
||||||
result.m[0][0] = xaxis.x;
|
result.m[0][0] = xaxis.x;
|
||||||
result.m[0][1] = xaxis.y;
|
result.m[0][1] = xaxis.y;
|
||||||
@@ -132,13 +133,13 @@ inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& u
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float farZ)
|
static inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float farZ)
|
||||||
{
|
{
|
||||||
// Left-Handed Perspective
|
// Left-Handed Perspective
|
||||||
float yScale = 1.0f / tanf(fovY * 0.5f);
|
float yScale = 1.0f / tanf(fovY * 0.5f);
|
||||||
float xScale = yScale / aspectRatio;
|
float xScale = yScale / aspectRatio;
|
||||||
|
|
||||||
Matrix result = {};
|
Matrix result = { 0 };
|
||||||
result.m[0][0] = xScale;
|
result.m[0][0] = xScale;
|
||||||
result.m[1][1] = yScale;
|
result.m[1][1] = yScale;
|
||||||
result.m[2][2] = farZ / (farZ - nearZ);
|
result.m[2][2] = farZ / (farZ - nearZ);
|
||||||
@@ -148,9 +149,9 @@ inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float f
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixInverse(const Matrix& m)
|
static inline Matrix MatrixInverse(Matrix m)
|
||||||
{
|
{
|
||||||
Matrix out = {};
|
Matrix out = { 0 };
|
||||||
|
|
||||||
float m00 = m.m[0][0], m01 = m.m[0][1], m02 = m.m[0][2], m03 = m.m[0][3];
|
float m00 = m.m[0][0], m01 = m.m[0][1], m02 = m.m[0][2], m03 = m.m[0][3];
|
||||||
float m10 = m.m[1][0], m11 = m.m[1][1], m12 = m.m[1][2], m13 = m.m[1][3];
|
float m10 = m.m[1][0], m11 = m.m[1][1], m12 = m.m[1][2], m13 = m.m[1][3];
|
||||||
@@ -183,9 +184,13 @@ inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float f
|
|||||||
{
|
{
|
||||||
float invDet = 1.0f / det;
|
float invDet = 1.0f / det;
|
||||||
for (int r = 0; r < 4; ++r)
|
for (int r = 0; r < 4; ++r)
|
||||||
|
{
|
||||||
for (int c = 0; c < 4; ++c)
|
for (int c = 0; c < 4; ++c)
|
||||||
|
{
|
||||||
out.m[r][c] *= invDet;
|
out.m[r][c] *= invDet;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct Rectangle
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
#define Rectangle JulietRectangle
|
||||||
|
|
||||||
|
typedef struct JulietRectangle JulietRectangle;
|
||||||
|
struct JulietRectangle
|
||||||
{
|
{
|
||||||
int32 X;
|
int32 X;
|
||||||
int32 Y;
|
int32 Y;
|
||||||
|
|||||||
@@ -1,38 +1,62 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
typedef struct Vector3 Vector3;
|
||||||
struct Vector3
|
struct Vector3
|
||||||
{
|
{
|
||||||
float x, y, z;
|
float x;
|
||||||
|
float y;
|
||||||
Vector3 operator+(const Vector3& rhs) const { return { x + rhs.x, y + rhs.y, z + rhs.z }; }
|
float z;
|
||||||
Vector3 operator-(const Vector3& rhs) const { return { x - rhs.x, y - rhs.y, z - rhs.z }; }
|
|
||||||
Vector3 operator*(float s) const { return { x * s, y * s, z * s }; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct Vector4 Vector4;
|
||||||
struct Vector4
|
struct Vector4
|
||||||
{
|
{
|
||||||
float x = 0.f;
|
float x;
|
||||||
float y = 0.f;
|
float y;
|
||||||
float z = 0.f;
|
float z;
|
||||||
float w = 0.f;
|
float w;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Vector3 Normalize(const Vector3& v)
|
static inline Vector3 Vector3Add(Vector3 lhs, Vector3 rhs)
|
||||||
{
|
{
|
||||||
|
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);
|
float len = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||||
if (len > 0.0001f)
|
if (len > 0.0001f)
|
||||||
{
|
{
|
||||||
return { v.x / len, v.y / len, v.z / len };
|
result.x = v.x / len;
|
||||||
|
result.y = v.y / len;
|
||||||
|
result.z = v.z / len;
|
||||||
}
|
}
|
||||||
return v;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Vector3 Cross(const Vector3& a, const Vector3& b)
|
static inline Vector3 Cross(Vector3 a, Vector3 b)
|
||||||
{
|
{
|
||||||
return { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x };
|
Vector3 res = { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x };
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float Dot(const Vector3& a, const Vector3& b)
|
static inline float Dot(Vector3 a, Vector3 b)
|
||||||
{
|
{
|
||||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
#include <Core/Common/CoreUtils.h>
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
// Uninitialized allocation
|
// Uninitialized allocation
|
||||||
JULIET_API void* Malloc(size_t elem_size);
|
JULIET_API void* Malloc(size_t elem_size);
|
||||||
@@ -9,20 +10,19 @@ JULIET_API void* Malloc(size_t elem_size);
|
|||||||
JULIET_API void* Calloc(size_t nb_elem, size_t elem_size);
|
JULIET_API void* Calloc(size_t nb_elem, size_t elem_size);
|
||||||
JULIET_API void* Realloc(void* memory, size_t newSize);
|
JULIET_API void* Realloc(void* memory, size_t newSize);
|
||||||
|
|
||||||
// Free
|
static inline void FreeMemory(void* memory)
|
||||||
template <typename Type>
|
|
||||||
void Free(Type* memory)
|
|
||||||
{
|
{
|
||||||
Assert(memory);
|
Assert(memory != NULL);
|
||||||
::free(memory);
|
free(memory);
|
||||||
}
|
|
||||||
// Free and Set the ptr to nullptr
|
|
||||||
template <typename Type>
|
|
||||||
void SafeFree(Type*& memory)
|
|
||||||
{
|
|
||||||
if (memory)
|
|
||||||
{
|
|
||||||
::free(memory);
|
|
||||||
memory = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SafeFree(memory_ptr) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if ((memory_ptr) != NULL) \
|
||||||
|
{ \
|
||||||
|
free((void*)(memory_ptr)); \
|
||||||
|
(memory_ptr) = NULL; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
@@ -1,21 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/CoreUtils.h>
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
#include <Core/Memory/MemoryArenaDebug.h>
|
#include <Core/Memory/MemoryArenaDebug.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr global uint64 g_Arena_Default_Reserve_Size = Megabytes(64);
|
#define g_Arena_Default_Reserve_Size Megabytes(64)
|
||||||
constexpr global uint64 g_Arena_Default_Commit_Size = Kilobytes(64);
|
#define g_Arena_Default_Commit_Size Kilobytes(64)
|
||||||
constexpr global uint64 k_ArenaHeaderSize = 128;
|
#define k_ArenaHeaderSize ((uint64)128)
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
typedef struct Arena Arena;
|
||||||
struct ArenaDebugInfo;
|
typedef struct TempArena TempArena;
|
||||||
JULIET_API String FormatDebugTagV(const char* formatStr, std::format_args args);
|
typedef struct ArenaParams ArenaParams;
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Arena
|
struct Arena
|
||||||
{
|
{
|
||||||
@@ -35,14 +33,14 @@ struct Arena
|
|||||||
Arena* FreeBlockLast;
|
Arena* FreeBlockLast;
|
||||||
|
|
||||||
JULIET_DEBUG_ONLY(uint16 LostNodeCount;)
|
JULIET_DEBUG_ONLY(uint16 LostNodeCount;)
|
||||||
JULIET_DEBUG_ONLY(bool CanReserveMore : 1;)
|
JULIET_DEBUG_ONLY(bool8 CanReserveMore;)
|
||||||
|
|
||||||
JULIET_DEBUG_ONLY(Arena* GlobalNext;)
|
JULIET_DEBUG_ONLY(Arena* GlobalNext;)
|
||||||
JULIET_DEBUG_ONLY(Arena* GlobalPrev;)
|
JULIET_DEBUG_ONLY(Arena* GlobalPrev;)
|
||||||
JULIET_DEBUG_ONLY(ArenaDebugInfo* FirstDebugInfo;)
|
JULIET_DEBUG_ONLY(ArenaDebugInfo* FirstDebugInfo;)
|
||||||
const char* Name;
|
const char* Name;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Arena) <= k_ArenaHeaderSize);
|
StaticAssert(sizeof(Arena) <= k_ArenaHeaderSize, ArenaHeaderSizeCheck);
|
||||||
|
|
||||||
struct TempArena
|
struct TempArena
|
||||||
{
|
{
|
||||||
@@ -52,74 +50,54 @@ struct TempArena
|
|||||||
|
|
||||||
struct ArenaParams
|
struct ArenaParams
|
||||||
{
|
{
|
||||||
uint64 ReserveSize = g_Arena_Default_Reserve_Size;
|
uint64 ReserveSize;
|
||||||
uint64 CommitSize = g_Arena_Default_Commit_Size;
|
uint64 CommitSize;
|
||||||
|
|
||||||
const char* Name;
|
const char* Name;
|
||||||
|
JULIET_DEBUG_ONLY(bool8 DoNotReserveMore;)
|
||||||
// When false, will assert if a new block is reserved.
|
|
||||||
JULIET_DEBUG_ONLY(bool CanReserveMore : 1 = true;)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] JULIET_API Arena* ArenaAllocate(const ArenaParams& params,
|
JULIET_API Arena* ArenaAllocateImpl(ArenaParams params, const char* file, uint32 line);
|
||||||
const std::source_location& loc = std::source_location::current());
|
#define ArenaAllocate(...) ArenaAllocateImpl(__VA_ARGS__, __FILE__, (uint32)__LINE__)
|
||||||
JULIET_API void ArenaRelease(NonNullPtr<Arena> arena);
|
|
||||||
|
|
||||||
// Raw Push, can be used but templated helpers exists below
|
JULIET_API void ArenaRelease(Arena* arena);
|
||||||
[[nodiscard]] JULIET_API void* ArenaPush(NonNullPtr<Arena> arena, size_t size, size_t align,
|
|
||||||
bool shouldBeZeroed JULIET_DEBUG_PARAM(const char* tag));
|
// Raw Push, can be used or macros below
|
||||||
JULIET_API void ArenaPopTo(NonNullPtr<Arena> arena, size_t position);
|
JULIET_API void* ArenaPush(Arena* arena, size_t size, size_t align,
|
||||||
JULIET_API void ArenaPop(NonNullPtr<Arena> arena, size_t amount);
|
bool8 shouldBeZeroed JULIET_DEBUG_PARAM(const char* tag));
|
||||||
JULIET_API void ArenaClear(NonNullPtr<Arena> arena);
|
JULIET_API void ArenaPopTo(Arena* arena, size_t position);
|
||||||
[[nodiscard]] JULIET_API size_t ArenaPos(NonNullPtr<Arena> arena);
|
JULIET_API void ArenaPop(Arena* arena, size_t amount);
|
||||||
|
JULIET_API void ArenaClear(Arena* arena);
|
||||||
|
JULIET_API size_t ArenaPos(Arena* arena);
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
template <typename FirstDebugArg, typename... DebugArgs>
|
#define ArenaPushSize(...) ArenaPush(__VA_ARGS__)
|
||||||
|
#define ArenaPushStruct(arena, Type) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true, #Type))
|
||||||
|
#define ArenaPushStructTag(arena, Type, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true, (tag)))
|
||||||
|
#define ArenaPushArray(arena, Type, count) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true, #Type))
|
||||||
|
#define ArenaPushArrayTag(arena, Type, count, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true, (tag)))
|
||||||
|
#define ArenaPushArrayNoZero(arena, Type, count) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false, #Type))
|
||||||
|
#define ArenaPushArrayNoZeroTag(arena, Type, count, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false, (tag)))
|
||||||
|
#else
|
||||||
|
#define ArenaPushSize(...) ArenaPush(__VA_ARGS__)
|
||||||
|
#define ArenaPushStruct(arena, Type) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true))
|
||||||
|
#define ArenaPushStructTag(arena, Type, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true))
|
||||||
|
#define ArenaPushArray(arena, Type, count) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true))
|
||||||
|
#define ArenaPushArrayTag(arena, Type, count, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true))
|
||||||
|
#define ArenaPushArrayNoZero(arena, Type, count) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false))
|
||||||
|
#define ArenaPushArrayNoZeroTag(arena, Type, count, tag) \
|
||||||
|
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false))
|
||||||
#endif
|
#endif
|
||||||
[[nodiscard]] inline void* ArenaPushSize(NonNullPtr<Arena> arena, size_t size, size_t align,
|
|
||||||
bool shouldBeZeroed JULIET_DEBUG_PARAM(FirstDebugArg&& firstDebugArg, DebugArgs&&... debugArgs))
|
|
||||||
{
|
|
||||||
return ArenaPush(arena, size, align,
|
|
||||||
shouldBeZeroed JULIET_DEBUG_PARAM(
|
|
||||||
[&]() -> const char*
|
|
||||||
{
|
|
||||||
return Format(GetDebugInfoArena(), std::forward<FirstDebugArg>(firstDebugArg),
|
|
||||||
std::forward<DebugArgs>(debugArgs)...)
|
|
||||||
.Str;
|
|
||||||
}()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type JULIET_DEBUG_ONLY(, typename... DebugArgs)>
|
TempArena ArenaTempBegin(Arena* arena);
|
||||||
[[nodiscard]] Type* ArenaPushStruct(NonNullPtr<Arena> arena JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs))
|
|
||||||
{
|
|
||||||
return static_cast<Type*>(
|
|
||||||
ArenaPush(arena, sizeof(Type) * 1, AlignOf(Type),
|
|
||||||
true JULIET_DEBUG_PARAM(
|
|
||||||
[&]() -> const char*
|
|
||||||
{
|
|
||||||
if constexpr (sizeof...(DebugArgs) > 0)
|
|
||||||
{
|
|
||||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
|
|
||||||
}
|
|
||||||
return GetTypeName<Type>();
|
|
||||||
}())));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type, bool shouldZero = true JULIET_DEBUG_ONLY(, typename... DebugArgs)>
|
|
||||||
[[nodiscard]] Type* ArenaPushArray(NonNullPtr<Arena> arena, size_t count JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs))
|
|
||||||
{
|
|
||||||
return static_cast<Type*>(
|
|
||||||
ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)),
|
|
||||||
shouldZero JULIET_DEBUG_PARAM(
|
|
||||||
[&]() -> const char*
|
|
||||||
{
|
|
||||||
if constexpr (sizeof...(DebugArgs) > 0)
|
|
||||||
{
|
|
||||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
|
|
||||||
}
|
|
||||||
return GetTypeName<Type>();
|
|
||||||
}())));
|
|
||||||
}
|
|
||||||
|
|
||||||
TempArena ArenaTempBegin(NonNullPtr<Arena> arena);
|
|
||||||
void ArenaTempEnd(TempArena temp);
|
void ArenaTempEnd(TempArena temp);
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
|
|
||||||
struct Arena;
|
typedef struct Arena Arena;
|
||||||
struct MemoryBlock;
|
typedef struct MemoryBlock MemoryBlock;
|
||||||
|
typedef struct ArenaDebugInfo ArenaDebugInfo;
|
||||||
|
typedef struct ArenaAllocation ArenaAllocation;
|
||||||
|
|
||||||
// Arena (Struct)
|
// Arena (Struct)
|
||||||
struct ArenaDebugInfo
|
struct ArenaDebugInfo
|
||||||
@@ -27,20 +28,16 @@ struct ArenaAllocation
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Arena (Struct)
|
// Arena (Struct)
|
||||||
void DebugRegisterArena(NonNullPtr<Arena> arena);
|
void DebugRegisterArena(Arena* arena);
|
||||||
void DebugUnregisterArena(NonNullPtr<Arena> arena);
|
void DebugUnregisterArena(Arena* arena);
|
||||||
void DebugArenaSetDebugName(NonNullPtr<Arena> arena, const char* name);
|
void DebugArenaSetDebugName(Arena* arena, const char* name);
|
||||||
bool IsDebugInfoArena(const Arena* arena); // To prevent recursion
|
bool8 IsDebugInfoArena(const Arena* arena); // To prevent recursion
|
||||||
void DebugArenaFreeBlock(Arena* block); // To clear all debug infos in a block
|
void DebugArenaFreeBlock(Arena* block); // To clear all debug infos in a block
|
||||||
void DebugArenaRemoveAllocation(Arena* block, size_t oldOffset);
|
void DebugArenaRemoveAllocation(Arena* block, size_t oldOffset);
|
||||||
void DebugArenaPopTo(Arena* block, size_t newPosition);
|
void DebugArenaPopTo(Arena* block, size_t newPosition);
|
||||||
void DebugArenaAddDebugInfo(Arena* block, size_t size, size_t offset, const char* tag);
|
void DebugArenaAddDebugInfo(Arena* block, size_t size, size_t offset, const char* tag);
|
||||||
|
|
||||||
// MemoryArena (Pool-based)
|
JULIET_API Arena* GetDebugInfoArena(void);
|
||||||
void DebugFreeArenaAllocations(MemoryBlock* blk);
|
JULIET_API Arena* GetGlobalArenaListHead(void);
|
||||||
void DebugArenaAddAllocation(MemoryBlock* blk, size_t size, size_t offset, String tag);
|
|
||||||
void DebugArenaRemoveLastAllocation(MemoryBlock* blk);
|
|
||||||
|
|
||||||
JULIET_API Arena* GetDebugInfoArena();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,63 +1,68 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ArraySize(array) (sizeof(array) / sizeof(array[0]))
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
inline int32 MemCompare(const void* leftValue, const void* rightValue, size_t size)
|
#define ArraySize(array) (sizeof(array) / sizeof((array)[0]))
|
||||||
|
|
||||||
|
static inline int32 MemCompare(const void* left_value, const void* right_value, size_t size)
|
||||||
{
|
{
|
||||||
auto left = static_cast<const unsigned char*>(leftValue);
|
const unsigned char* left = (const unsigned char*)left_value;
|
||||||
auto right = static_cast<const unsigned char*>(rightValue);
|
const unsigned char* right = (const unsigned char*)right_value;
|
||||||
while (size && *left == *right)
|
while (size && *left == *right)
|
||||||
{
|
{
|
||||||
++left;
|
++left;
|
||||||
++right;
|
++right;
|
||||||
--size;
|
--size;
|
||||||
}
|
}
|
||||||
return size ? *left - *right : 0;
|
return size ? ((int32)(*left) - (int32)(*right)) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single linked list
|
// Single linked list macros
|
||||||
void SingleLinkedListPushNext(auto*& stackTop, auto* node)
|
#define SingleLinkedListPushNext(stackTop, node) \
|
||||||
{
|
do \
|
||||||
node->Next = stackTop;
|
{ \
|
||||||
stackTop = node;
|
(node)->Next = (stackTop); \
|
||||||
}
|
(stackTop) = (node); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
void SingleLinkedListPushPrevious(auto*& stackTop, auto* node)
|
#define SingleLinkedListPushPrevious(stackTop, node) \
|
||||||
{
|
do \
|
||||||
node->Previous = stackTop;
|
{ \
|
||||||
stackTop = node;
|
(node)->Previous = (stackTop); \
|
||||||
}
|
(stackTop) = (node); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
void SingleLinkedListPopNext(auto*& stackTop)
|
#define SingleLinkedListPopNext(stackTop) \
|
||||||
{
|
do \
|
||||||
stackTop = stackTop->Next;
|
{ \
|
||||||
}
|
(stackTop) = (stackTop)->Next; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
// Double linked list
|
// Double linked list queue macro
|
||||||
template <typename QueueType, typename QueueTypeNode>
|
#define Enqueue(queue, node) \
|
||||||
void Enqueue(QueueType& queue, QueueTypeNode* node)
|
do \
|
||||||
{
|
{ \
|
||||||
if (queue.First == nullptr)
|
if ((queue).First == NULL) \
|
||||||
{
|
{ \
|
||||||
queue.First = queue.Last = node;
|
(queue).First = (queue).Last = (node); \
|
||||||
node->Next = nullptr;
|
(node)->Next = NULL; \
|
||||||
}
|
} \
|
||||||
else
|
else \
|
||||||
{
|
{ \
|
||||||
queue.Last->Next = node, queue.Last = node;
|
(queue).Last->Next = (node); \
|
||||||
node->Next = nullptr;
|
(queue).Last = (node); \
|
||||||
}
|
(node)->Next = NULL; \
|
||||||
|
} \
|
||||||
queue.Nodecount += 1;
|
(queue).Nodecount += 1; \
|
||||||
}
|
} \
|
||||||
|
while (0)
|
||||||
template <typename QueueType>
|
|
||||||
struct QueueNode
|
|
||||||
{
|
|
||||||
QueueType* Next;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DECLARE_QUEUE(type) \
|
#define DECLARE_QUEUE(type) \
|
||||||
|
typedef struct type##Queue type##Queue; \
|
||||||
struct type##Queue \
|
struct type##Queue \
|
||||||
{ \
|
{ \
|
||||||
type* First; \
|
type* First; \
|
||||||
@@ -66,8 +71,7 @@ struct QueueNode
|
|||||||
size_t Size; \
|
size_t Size; \
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: homemade versions
|
|
||||||
#define MemSet memset
|
#define MemSet memset
|
||||||
#define MemCopy memcpy
|
#define MemCopy memcpy
|
||||||
|
#define MemoryZero(dst, size) MemSet((dst), 0, (size))
|
||||||
#define MemoryZero(dst, size) MemSet(dst, 0, size)
|
#define MemZeroStruct(ptr) MemoryZero((ptr), sizeof(*(ptr)))
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// TODO : Do something better.
|
|
||||||
constexpr uint32 kLocalhost = (127 << 3) | (0 << 2) | (0 << 1) | 1;
|
|
||||||
constexpr uint32 kAnyIp = 0;
|
|
||||||
constexpr uint32 kBroadcastIp = (255 << 3) | (255 << 2) | (255 << 1) | 255;
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Container/Vector.h>
|
|
||||||
|
|
||||||
class NetworkPacket
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NetworkPacket();
|
|
||||||
NetworkPacket(Arena& arena);
|
|
||||||
virtual ~NetworkPacket();
|
|
||||||
NetworkPacket(NetworkPacket&);
|
|
||||||
NetworkPacket& operator=(const NetworkPacket&);
|
|
||||||
NetworkPacket(NetworkPacket&&) noexcept;
|
|
||||||
NetworkPacket& operator=(NetworkPacket&&) noexcept;
|
|
||||||
|
|
||||||
void Create(Arena& arena);
|
|
||||||
|
|
||||||
[[nodiscard]] ByteBuffer GetRawData();
|
|
||||||
|
|
||||||
// Pack
|
|
||||||
NetworkPacket& operator<<(uint32 value);
|
|
||||||
NetworkPacket& operator<<(char* data);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void Append(ByteBuffer buffer);
|
|
||||||
|
|
||||||
friend class TcpSocket;
|
|
||||||
|
|
||||||
private:
|
|
||||||
VectorArena<Byte, 4096> Data;
|
|
||||||
size_t PartialSendIndex = 0;
|
|
||||||
};
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Networking/SocketHandle.h>
|
|
||||||
|
|
||||||
class Socket
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~Socket();
|
|
||||||
|
|
||||||
Socket(Socket&& other) noexcept;
|
|
||||||
Socket& operator=(Socket&& socket) noexcept;
|
|
||||||
|
|
||||||
Socket(const Socket&) = delete;
|
|
||||||
Socket& operator=(const Socket&) = delete;
|
|
||||||
|
|
||||||
bool IsValid() const;
|
|
||||||
|
|
||||||
enum class Status : uint8
|
|
||||||
{
|
|
||||||
Done,
|
|
||||||
Partial,
|
|
||||||
Ready,
|
|
||||||
NotReady,
|
|
||||||
Disconnected,
|
|
||||||
Error
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
enum class Protocol : uint8
|
|
||||||
{
|
|
||||||
TCP,
|
|
||||||
UDP
|
|
||||||
};
|
|
||||||
|
|
||||||
// To store the result of a send/receive on the socket
|
|
||||||
struct RequestStatus
|
|
||||||
{
|
|
||||||
Status Status = Status::Done;
|
|
||||||
size_t Length = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit Socket(Protocol protocol);
|
|
||||||
|
|
||||||
SocketHandle GetHandle() const { return Handle; }
|
|
||||||
|
|
||||||
void Create();
|
|
||||||
void CreateFromHandle(SocketHandle handle);
|
|
||||||
void Close();
|
|
||||||
|
|
||||||
private:
|
|
||||||
SocketHandle Handle;
|
|
||||||
Protocol ProtocolType;
|
|
||||||
};
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#if JULIET_WIN32
|
|
||||||
#include <basetsd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if JULIET_WIN32
|
|
||||||
using SocketHandle = UINT_PTR;
|
|
||||||
#else
|
|
||||||
using SocketHandle = int;
|
|
||||||
#endif
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Networking/IPAddress.h>
|
|
||||||
#include <Core/Networking/Socket.h>
|
|
||||||
#include <Core/Networking/TcpSocket.h>
|
|
||||||
|
|
||||||
class TcpListener : public Socket
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TcpListener();
|
|
||||||
|
|
||||||
TcpListener(const TcpListener&) = delete;
|
|
||||||
TcpListener& operator=(const TcpListener&) = delete;
|
|
||||||
|
|
||||||
Status Listen(uint16 port, uint32 address = kAnyIp);
|
|
||||||
Status Accept(TcpSocket& socket);
|
|
||||||
void Close();
|
|
||||||
};
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Core/Networking/Socket.h>
|
|
||||||
|
|
||||||
class NetworkPacket;
|
|
||||||
|
|
||||||
class TcpSocket : public Socket
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TcpSocket();
|
|
||||||
|
|
||||||
TcpSocket(const TcpSocket&) = delete;
|
|
||||||
TcpSocket& operator=(const TcpSocket&) = delete;
|
|
||||||
|
|
||||||
RequestStatus Send(NetworkPacket& packet);
|
|
||||||
RequestStatus Send(ByteBuffer buffer);
|
|
||||||
Status Receive(NetworkPacket& outPacket);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class TcpListener;
|
|
||||||
};
|
|
||||||
+14
-29
@@ -1,33 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <assert.h>
|
||||||
#include <bit>
|
#include <float.h>
|
||||||
#include <cassert>
|
#include <inttypes.h>
|
||||||
#include <cfloat>
|
#include <limits.h>
|
||||||
#include <chrono>
|
#include <math.h>
|
||||||
#include <cinttypes>
|
#include <stdarg.h>
|
||||||
#include <cmath>
|
#include <stddef.h>
|
||||||
#include <concepts>
|
#include <stdint.h>
|
||||||
#include <cstdarg>
|
#include <stdio.h>
|
||||||
#include <cstddef>
|
#include <stdlib.h>
|
||||||
#include <cstdint>
|
#include <string.h>
|
||||||
#include <cstdio>
|
#include <time.h>
|
||||||
#include <cstdlib>
|
#include <wchar.h>
|
||||||
#include <cstring>
|
|
||||||
#include <format>
|
|
||||||
#include <forward_list>
|
|
||||||
#include <ios>
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <limits>
|
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <queue>
|
|
||||||
#include <source_location>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
using Mutex = std::mutex;
|
|
||||||
using LockGuard = std::lock_guard<Mutex>;
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
uint32 thread_id();
|
uint32 thread_id(void);
|
||||||
|
|
||||||
void set_thread_name(String name);
|
void set_thread_name(String name);
|
||||||
|
|
||||||
// TODO : Proper wait
|
static inline void wait_ms(int milliseconds)
|
||||||
inline void wait_ms(int milliseconds)
|
|
||||||
{
|
{
|
||||||
clock_t start_time = clock();
|
clock_t start_time = clock();
|
||||||
while (clock() < start_time + milliseconds)
|
while (clock() < start_time + milliseconds)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
|
||||||
|
typedef struct thread_context thread_context;
|
||||||
struct thread_context
|
struct thread_context
|
||||||
{
|
{
|
||||||
Arena* ScratchArenas[2];
|
Arena* ScratchArenas[2];
|
||||||
@@ -10,10 +11,10 @@ struct thread_context
|
|||||||
uint8 ThreadNameSize;
|
uint8 ThreadNameSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
thread_context* thread_context_alloc();
|
thread_context* thread_context_alloc(void);
|
||||||
void thread_context_release(NonNullPtr<thread_context> ctx);
|
void thread_context_release(thread_context* ctx);
|
||||||
void thread_context_select(NonNullPtr<thread_context> ctx);
|
void thread_context_select(thread_context* ctx);
|
||||||
thread_context* thread_context_current();
|
thread_context* thread_context_current(void);
|
||||||
|
|
||||||
Arena* thread_context_get_scratch(Arena** conflicts, size_t count);
|
Arena* thread_context_get_scratch(Arena** conflicts, size_t count);
|
||||||
JULIET_API TempArena scratch_begin(Arena** conflicts, size_t count);
|
JULIET_API TempArena scratch_begin(Arena** conflicts, size_t count);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
#include <Graphics/MeshRenderer.h>
|
#include <Graphics/MeshRenderer.h>
|
||||||
|
|||||||
@@ -5,31 +5,15 @@
|
|||||||
#include <Core/Common/CRC32.h>
|
#include <Core/Common/CRC32.h>
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
struct Archive;
|
typedef struct Archive Archive;
|
||||||
|
typedef struct Class Class;
|
||||||
|
|
||||||
using serialize_fct_type = void(Archive&, uint16 version, void* payload);
|
typedef void (*serialize_fct_ptr)(Archive* ar, uint16 version, void* payload);
|
||||||
using serialize_fct_ptr = serialize_fct_type*;
|
typedef void (*initialize_fct_ptr)(void* payload);
|
||||||
|
|
||||||
using initialize_fct_type = void(void* payload);
|
|
||||||
using initialize_fct_ptr = initialize_fct_type*;
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
void serialize_thunk(Archive& ar, uint16 version, void* payload)
|
|
||||||
{
|
|
||||||
Assert(payload);
|
|
||||||
serialize(ar, version, *((Type*)payload));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
void initialize_thunk(void* payload)
|
|
||||||
{
|
|
||||||
auto& typed_val = *(Type*)payload;
|
|
||||||
typed_val = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Class
|
struct Class
|
||||||
{
|
{
|
||||||
uint32 CRC;
|
String Name;
|
||||||
uint8 kind;
|
uint8 kind;
|
||||||
uint16 version;
|
uint16 version;
|
||||||
const Class* base_class;
|
const Class* base_class;
|
||||||
@@ -37,45 +21,32 @@ struct Class
|
|||||||
serialize_fct_ptr serialize_fct;
|
serialize_fct_ptr serialize_fct;
|
||||||
size_t size_of;
|
size_t size_of;
|
||||||
size_t alignment;
|
size_t alignment;
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
|
||||||
String Name;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DECLARE_CLASS() static Class* kind;
|
#define DECLARE_CLASS(cls) extern const Class class_kind_##cls;
|
||||||
|
|
||||||
#define DEFINE_CLASS_VERSIONED(cls, version, base_class) \
|
#define DEFINE_CLASS_VERSIONED(cls, version_num, base_class_ptr) \
|
||||||
constexpr Class class_kind_##cls = MakeClass(ConstString(#cls), 0, (version), (base_class), sizeof(cls), \
|
const Class class_kind_##cls = { \
|
||||||
alignof(cls), (&initialize_thunk<cls>), (&serialize_thunk<cls>)); \
|
.Name = ConstString(#cls), \
|
||||||
Class* cls::kind = const_cast<Class*>(&class_kind_##cls);
|
.kind = 0, \
|
||||||
|
.version = (version_num), \
|
||||||
|
.base_class = (base_class_ptr), \
|
||||||
|
.initialize_fct = init_##cls, \
|
||||||
|
.serialize_fct = serialize_##cls, \
|
||||||
|
.size_of = sizeof(cls), \
|
||||||
|
.alignment = AlignOf(cls) \
|
||||||
|
};
|
||||||
|
|
||||||
consteval Class MakeClass(String name, uint8 kind, uint16 version, const Class* base_class, size_t size, size_t align,
|
#define ClassKind(cls) (&class_kind_##cls)
|
||||||
initialize_fct_ptr init_fct, serialize_fct_ptr serde_fct)
|
|
||||||
|
static inline uint32 class_get_crc(const Class* cls)
|
||||||
{
|
{
|
||||||
Class cls = {};
|
Assert(cls != NULL);
|
||||||
cls.CRC = crc32(name.Str, name.Size);
|
return crc32_str(cls->Name);
|
||||||
cls.kind = kind;
|
|
||||||
cls.version = version;
|
|
||||||
cls.base_class = base_class;
|
|
||||||
cls.size_of = size;
|
|
||||||
cls.alignment = align;
|
|
||||||
cls.initialize_fct = init_fct;
|
|
||||||
cls.serialize_fct = serde_fct;
|
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
|
||||||
cls.Name = name;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return cls;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsA(const Class& query, const Class* target);
|
JULIET_API bool8 IsA(const Class* query, const Class* target);
|
||||||
|
|
||||||
template <typename type>
|
#define IsClassA(cls_ptr, target_type) IsA((cls_ptr), ClassKind(target_type))
|
||||||
bool IsA(const Class& cls)
|
|
||||||
{
|
|
||||||
return IsA(cls, type::kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
JULIET_API void serialize(Archive& ar, NonNullPtr<const Class> cls, void* instance);
|
JULIET_API void serialize_class(Archive* ar, const Class* cls, void* instance);
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
|
|
||||||
namespace Debug
|
JULIET_API void Debug_DebugDrawMemoryArena(void);
|
||||||
{
|
|
||||||
JULIET_API void DebugDrawMemoryArena();
|
|
||||||
} // namespace Debug
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,22 +1,35 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Application/IApplication.h>
|
#include <Core/JulietInit.h>
|
||||||
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
#include <Graphics/Graphics.h>
|
||||||
|
#include <Graphics/RenderPass.h>
|
||||||
|
|
||||||
enum class JulietInit_Flags : uint8;
|
typedef struct ApplicationCallbacks ApplicationCallbacks;
|
||||||
|
struct ApplicationCallbacks
|
||||||
struct Engine
|
|
||||||
{
|
{
|
||||||
IApplication* Application = nullptr;
|
void (*Init)(Arena* platformArena);
|
||||||
Arena* PlatformArena = nullptr;
|
void (*Shutdown)(void);
|
||||||
Arena* AssetArena = nullptr;
|
void (*Update)(float deltaTime);
|
||||||
|
bool8 (*IsRunning)(void);
|
||||||
|
Window* (*GetPlatformWindow)(void);
|
||||||
|
GraphicsDevice* (*GetGraphicsDevice)(void);
|
||||||
|
ColorTargetInfo (*GetColorTargetInfo)(Texture* swapchainTexture);
|
||||||
|
DepthStencilTargetInfo* (*GetDepthTargetInfo)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitializeEngine(JulietInit_Flags flags);
|
typedef struct Engine Engine;
|
||||||
void ShutdownEngine();
|
struct Engine
|
||||||
|
{
|
||||||
|
ApplicationCallbacks Application;
|
||||||
|
Arena* PlatformArena;
|
||||||
|
Arena* AssetArena;
|
||||||
|
};
|
||||||
|
|
||||||
void LoadApplication(IApplication& app);
|
JULIET_API void StartApplication(ApplicationCallbacks app, JulietInit_Flags flags);
|
||||||
void UnloadApplication();
|
JULIET_API void InitializeEngine(JulietInit_Flags flags);
|
||||||
|
JULIET_API void ShutdownEngine(void);
|
||||||
void RunEngine();
|
JULIET_API void LoadApplication(ApplicationCallbacks app);
|
||||||
|
JULIET_API void UnloadApplication(void);
|
||||||
extern Arena* GetPlatformArena();
|
JULIET_API void RunEngine(void);
|
||||||
|
JULIET_API Arena* GetPlatformArena(void);
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
using UserID = uint8;
|
#include <Juliet.h>
|
||||||
|
|
||||||
void initialize_user_system();
|
typedef uint8 UserID;
|
||||||
void shutdown_user_system();
|
|
||||||
|
|
||||||
JULIET_API uint8 get_local_user_id();
|
void initialize_user_system(void);
|
||||||
|
void shutdown_user_system(void);
|
||||||
|
|
||||||
|
JULIET_API uint8 get_local_user_id(void);
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
#include <Core/Math/Matrix.h>
|
#include <Core/Math/Matrix.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
typedef struct Camera Camera;
|
||||||
struct Camera
|
struct Camera
|
||||||
{
|
{
|
||||||
index_t Index;
|
index_t Index;
|
||||||
@@ -15,21 +17,26 @@ struct Camera
|
|||||||
float FarPlane;
|
float FarPlane;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Matrix Camera_GetViewMatrix(const Camera& cam)
|
static inline Matrix Camera_GetViewMatrix(const Camera* cam)
|
||||||
{
|
{
|
||||||
return LookAt(cam.Position, cam.Target, cam.Up);
|
Assert(cam != NULL);
|
||||||
|
return LookAt(cam->Position, cam->Target, cam->Up);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Matrix Camera_GetProjectionMatrix(const Camera& cam)
|
static inline Matrix Camera_GetProjectionMatrix(const Camera* cam)
|
||||||
{
|
{
|
||||||
return PerspectiveFov(cam.FOV, cam.AspectRatio, cam.NearPlane, cam.FarPlane);
|
Assert(cam != NULL);
|
||||||
|
return PerspectiveFov(cam->FOV, cam->AspectRatio, cam->NearPlane, cam->FarPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Matrix Camera_GetViewProjectionMatrix(const Camera& cam)
|
static inline Matrix Camera_GetViewProjectionMatrix(const Camera* cam)
|
||||||
{
|
{
|
||||||
return Camera_GetProjectionMatrix(cam) * Camera_GetViewMatrix(cam);
|
Assert(cam != NULL);
|
||||||
|
Matrix proj = Camera_GetProjectionMatrix(cam);
|
||||||
|
Matrix view = Camera_GetViewMatrix(cam);
|
||||||
|
return MatrixMultiply(proj, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
JULIET_API extern void ReserveCamera(size_t amount);
|
JULIET_API extern void ReserveCamera(size_t amount);
|
||||||
JULIET_API extern Camera* GetCurrentCamera();
|
JULIET_API extern Camera* GetCurrentCamera(void);
|
||||||
JULIET_API extern void SetCurrentCamera(index_t index);
|
JULIET_API extern void SetCurrentCamera(index_t index);
|
||||||
@@ -1,13 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
template <typename Type>
|
#include <Core/Common/CoreTypes.h>
|
||||||
struct ColorType
|
|
||||||
|
typedef struct FColor FColor;
|
||||||
|
struct FColor
|
||||||
{
|
{
|
||||||
Type R;
|
float R;
|
||||||
Type G;
|
float G;
|
||||||
Type B;
|
float B;
|
||||||
Type A;
|
float A;
|
||||||
};
|
};
|
||||||
|
|
||||||
using FColor = ColorType<float>;
|
typedef struct Color Color;
|
||||||
using Color = ColorType<uint8>;
|
struct Color
|
||||||
|
{
|
||||||
|
uint8 R;
|
||||||
|
uint8 G;
|
||||||
|
uint8 B;
|
||||||
|
uint8 A;
|
||||||
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Math/Vector.h>
|
#include <Core/Math/Vector.h>
|
||||||
#include <Graphics/Camera.h>
|
#include <Graphics/Camera.h>
|
||||||
@@ -6,9 +6,9 @@
|
|||||||
#include <Graphics/Graphics.h>
|
#include <Graphics/Graphics.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
extern JULIET_API void DebugDisplay_Initialize(NonNullPtr<Arena> arena, GraphicsDevice* device);
|
extern JULIET_API void DebugDisplay_Initialize(Arena* arena, GraphicsDevice* device);
|
||||||
extern JULIET_API void DebugDisplay_Shutdown(GraphicsDevice* device);
|
extern JULIET_API void DebugDisplay_Shutdown(GraphicsDevice* device);
|
||||||
extern JULIET_API void DebugDisplay_DrawLine(const Vector3& start, const Vector3& end, const FColor& color, bool overlay);
|
extern JULIET_API void DebugDisplay_DrawLine(Vector3 start, Vector3 end, FColor color, bool8 overlay);
|
||||||
extern JULIET_API void DebugDisplay_DrawSphere(const Vector3& center, float radius, const FColor& color, bool overlay);
|
extern JULIET_API void DebugDisplay_DrawSphere(Vector3 center, float radius, FColor color, bool8 overlay);
|
||||||
extern JULIET_API void DebugDisplay_Prepare(CommandList* cmdList);
|
extern JULIET_API void DebugDisplay_Prepare(CommandList* cmdList);
|
||||||
extern JULIET_API void DebugDisplay_Flush(CommandList* cmdList, RenderPass* renderPass, const Camera& camera);
|
extern JULIET_API void DebugDisplay_Flush(CommandList* cmdList, RenderPass* renderPass, const Camera* camera);
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
#include <Core/HAL/Display/Display.h>
|
#include <Core/HAL/Display/Display.h>
|
||||||
#include <Core/Math/Shape.h>
|
#include <Core/Math/Shape.h>
|
||||||
@@ -13,11 +12,12 @@
|
|||||||
|
|
||||||
// Graphics Interface
|
// Graphics Interface
|
||||||
// Opaque types
|
// Opaque types
|
||||||
struct CommandList;
|
typedef struct CommandList CommandList;
|
||||||
struct GraphicsDevice;
|
typedef struct GraphicsDevice GraphicsDevice;
|
||||||
struct Fence;
|
typedef struct Fence Fence;
|
||||||
|
|
||||||
// Parameters of an indirect draw command
|
// Parameters of an indirect draw command
|
||||||
|
typedef struct IndirectDrawCommand IndirectDrawCommand;
|
||||||
struct IndirectDrawCommand
|
struct IndirectDrawCommand
|
||||||
{
|
{
|
||||||
uint32 VertexCount; // Number of vertices to draw
|
uint32 VertexCount; // Number of vertices to draw
|
||||||
@@ -27,6 +27,7 @@ struct IndirectDrawCommand
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Parameters of an INDEXED indirect draw command
|
// Parameters of an INDEXED indirect draw command
|
||||||
|
typedef struct IndexedIndirectDrawCommand IndexedIndirectDrawCommand;
|
||||||
struct IndexedIndirectDrawCommand
|
struct IndexedIndirectDrawCommand
|
||||||
{
|
{
|
||||||
uint32 VertexCount; // Number of vertices to draw
|
uint32 VertexCount; // Number of vertices to draw
|
||||||
@@ -37,6 +38,7 @@ struct IndexedIndirectDrawCommand
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Parameters of an INDEXED Indirect Dispatch Command
|
// Parameters of an INDEXED Indirect Dispatch Command
|
||||||
|
typedef struct IndirectDispatchCommand IndirectDispatchCommand;
|
||||||
struct IndirectDispatchCommand
|
struct IndirectDispatchCommand
|
||||||
{
|
{
|
||||||
uint32 X_WorkGroupCount; // Number of Workgroup to dispatch on dimension X
|
uint32 X_WorkGroupCount; // Number of Workgroup to dispatch on dimension X
|
||||||
@@ -44,39 +46,44 @@ struct IndirectDispatchCommand
|
|||||||
uint32 Z_WorkGroupCount; // Number of Workgroup to dispatch on dimension Z
|
uint32 Z_WorkGroupCount; // Number of Workgroup to dispatch on dimension Z
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class QueueType : uint8
|
typedef uint8 QueueType;
|
||||||
|
enum QueueType_Enum
|
||||||
{
|
{
|
||||||
Graphics = 0,
|
QueueType_Graphics = 0,
|
||||||
Compute,
|
QueueType_Compute,
|
||||||
Copy,
|
QueueType_Copy,
|
||||||
Count
|
QueueType_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IndexFormat : uint8
|
typedef uint8 IndexFormat;
|
||||||
|
enum IndexFormat_Enum
|
||||||
{
|
{
|
||||||
UInt16,
|
IndexFormat_UInt16,
|
||||||
UInt32
|
IndexFormat_UInt32
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct SwapChainComposition : uint8
|
typedef uint8 SwapChainComposition;
|
||||||
|
enum SwapChainComposition_Enum
|
||||||
{
|
{
|
||||||
SDR,
|
SwapChainComposition_SDR,
|
||||||
SDR_LINEAR,
|
SwapChainComposition_SDR_LINEAR,
|
||||||
HDR_EXTENDED_LINEAR,
|
SwapChainComposition_HDR_EXTENDED_LINEAR,
|
||||||
HDR10_ST2084
|
SwapChainComposition_HDR10_ST2084
|
||||||
};
|
};
|
||||||
|
|
||||||
// PresentMode from highest to lowest latency
|
// PresentMode from highest to lowest latency
|
||||||
// Vsync prevents tearing. Enqueue ready images.
|
// Vsync prevents tearing. Enqueue ready images.
|
||||||
// Mailbox prevents tearing. When image is ready, replace any pending image
|
// Mailbox prevents tearing. When image is ready, replace any pending image
|
||||||
// Immediate replace current image as soon as possible. Can cause tearing
|
// Immediate replace current image as soon as possible. Can cause tearing
|
||||||
enum struct PresentMode : uint8
|
typedef uint8 PresentMode;
|
||||||
|
enum PresentMode_Enum
|
||||||
{
|
{
|
||||||
VSync,
|
PresentMode_VSync,
|
||||||
Mailbox,
|
PresentMode_Mailbox,
|
||||||
Immediate
|
PresentMode_Immediate
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct GraphicsViewPort GraphicsViewPort;
|
||||||
struct GraphicsViewPort
|
struct GraphicsViewPort
|
||||||
{
|
{
|
||||||
float X;
|
float X;
|
||||||
@@ -88,87 +95,85 @@ struct GraphicsViewPort
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern JULIET_API GraphicsDevice* CreateGraphicsDevice(GraphicsConfig config);
|
extern JULIET_API GraphicsDevice* CreateGraphicsDevice(GraphicsConfig config);
|
||||||
extern JULIET_API void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device);
|
extern JULIET_API void DestroyGraphicsDevice(GraphicsDevice* device);
|
||||||
|
|
||||||
// Attach To Window
|
// Attach To Window
|
||||||
extern JULIET_API bool AttachToWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
extern JULIET_API bool8 AttachToWindow(GraphicsDevice* device, Window* window);
|
||||||
extern JULIET_API void DetachFromWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
extern JULIET_API void DetachFromWindow(GraphicsDevice* device, Window* window);
|
||||||
|
|
||||||
// SwapChain
|
// SwapChain
|
||||||
extern JULIET_API bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window,
|
extern JULIET_API bool8 AcquireSwapChainTexture(CommandList* commandList, Window* window, Texture** swapChainTexture);
|
||||||
Texture** swapChainTexture);
|
extern JULIET_API bool8 WaitAndAcquireSwapChainTexture(CommandList* commandList, Window* window, Texture** swapChainTexture);
|
||||||
extern JULIET_API bool WaitAndAcquireSwapChainTexture(NonNullPtr<CommandList> commandList,
|
extern JULIET_API bool8 WaitForSwapchain(GraphicsDevice* device, Window* window);
|
||||||
NonNullPtr<Window> window, Texture** swapChainTexture);
|
extern JULIET_API TextureFormat GetSwapChainTextureFormat(GraphicsDevice* device, Window* window);
|
||||||
extern JULIET_API bool WaitForSwapchain(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
|
||||||
extern JULIET_API TextureFormat GetSwapChainTextureFormat(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
|
||||||
|
|
||||||
// Textures
|
// Textures
|
||||||
extern JULIET_API Texture* CreateTexture(NonNullPtr<GraphicsDevice> device, const TextureCreateInfo& createInfo);
|
extern JULIET_API Texture* CreateTexture(GraphicsDevice* device, const TextureCreateInfo* createInfo);
|
||||||
extern JULIET_API void DestroyTexture(NonNullPtr<GraphicsDevice> device, NonNullPtr<Texture> texture);
|
extern JULIET_API void DestroyTexture(GraphicsDevice* device, Texture* texture);
|
||||||
|
|
||||||
// Command List
|
// Command List
|
||||||
extern JULIET_API CommandList* AcquireCommandList(NonNullPtr<GraphicsDevice> device, QueueType queueType = QueueType::Graphics);
|
extern JULIET_API CommandList* AcquireCommandList(GraphicsDevice* device, QueueType queueType);
|
||||||
extern JULIET_API void SubmitCommandLists(NonNullPtr<CommandList> commandList);
|
extern JULIET_API void SubmitCommandLists(CommandList* commandList);
|
||||||
|
|
||||||
// RenderPass
|
// RenderPass
|
||||||
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, ColorTargetInfo& colorTargetInfo,
|
extern JULIET_API RenderPass* BeginRenderPass(CommandList* commandList, const ColorTargetInfo* colorTargetInfo,
|
||||||
DepthStencilTargetInfo* depthStencilTargetInfo = nullptr);
|
DepthStencilTargetInfo* depthStencilTargetInfo);
|
||||||
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList,
|
extern JULIET_API RenderPass* BeginRenderPassTargets(CommandList* commandList,
|
||||||
NonNullPtr<const ColorTargetInfo> colorTargetInfos, uint32 colorTargetInfoCount,
|
const ColorTargetInfo* colorTargetInfos, uint32 colorTargetInfoCount,
|
||||||
DepthStencilTargetInfo* depthStencilTargetInfo = nullptr);
|
DepthStencilTargetInfo* depthStencilTargetInfo);
|
||||||
extern JULIET_API void EndRenderPass(NonNullPtr<RenderPass> renderPass);
|
extern JULIET_API void EndRenderPass(RenderPass* renderPass);
|
||||||
|
|
||||||
extern JULIET_API void SetGraphicsViewPort(NonNullPtr<RenderPass> renderPass, const GraphicsViewPort& viewPort);
|
extern JULIET_API void SetGraphicsViewPort(RenderPass* renderPass, const GraphicsViewPort* viewPort);
|
||||||
extern JULIET_API void SetScissorRect(NonNullPtr<RenderPass> renderPass, const struct Rectangle& rectangle);
|
extern JULIET_API void SetScissorRect(RenderPass* renderPass, const struct Rectangle* rectangle);
|
||||||
extern JULIET_API void SetBlendConstants(NonNullPtr<RenderPass> renderPass, FColor blendConstants);
|
extern JULIET_API void SetBlendConstants(RenderPass* renderPass, FColor blendConstants);
|
||||||
extern JULIET_API void SetStencilReference(NonNullPtr<RenderPass> renderPass, uint8 reference);
|
extern JULIET_API void SetStencilReference(RenderPass* renderPass, uint8 reference);
|
||||||
|
|
||||||
extern JULIET_API void BindGraphicsPipeline(NonNullPtr<RenderPass> renderPass, NonNullPtr<GraphicsPipeline> graphicsPipeline);
|
extern JULIET_API void BindGraphicsPipeline(RenderPass* renderPass, GraphicsPipeline* graphicsPipeline);
|
||||||
extern JULIET_API void DrawPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numVertices, uint32 numInstances,
|
extern JULIET_API void DrawPrimitives(RenderPass* renderPass, uint32 numVertices, uint32 numInstances,
|
||||||
uint32 firstVertex, uint32 firstInstance);
|
uint32 firstVertex, uint32 firstInstance);
|
||||||
extern JULIET_API void DrawIndexedPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numIndices, uint32 numInstances,
|
extern JULIET_API void DrawIndexedPrimitives(RenderPass* renderPass, uint32 numIndices, uint32 numInstances,
|
||||||
uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance);
|
uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance);
|
||||||
|
|
||||||
extern JULIET_API void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer,
|
extern JULIET_API void SetIndexBuffer(CommandList* commandList, GraphicsBuffer* buffer,
|
||||||
IndexFormat format, size_t indexCount, index_t offset);
|
IndexFormat format, size_t indexCount, index_t offset);
|
||||||
|
|
||||||
extern JULIET_API void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage,
|
extern JULIET_API void SetPushConstants(CommandList* commandList, ShaderStage stage,
|
||||||
uint32 rootParameterIndex, uint32 numConstants, const void* constants);
|
uint32 rootParameterIndex, uint32 numConstants, const void* constants);
|
||||||
|
|
||||||
// Fences
|
// Fences
|
||||||
extern JULIET_API bool WaitUntilGPUIsIdle(NonNullPtr<GraphicsDevice> device);
|
extern JULIET_API bool8 WaitUntilGPUIsIdle(GraphicsDevice* device);
|
||||||
|
|
||||||
// Shaders
|
// Shaders
|
||||||
extern JULIET_API Shader* CreateShader(NonNullPtr<GraphicsDevice> device, String filename, ShaderCreateInfo& shaderCreateInfo);
|
extern JULIET_API Shader* CreateShader(GraphicsDevice* device, String filename, ShaderCreateInfo* shaderCreateInfo);
|
||||||
extern JULIET_API void DestroyShader(NonNullPtr<GraphicsDevice> device, NonNullPtr<Shader> shader);
|
extern JULIET_API void DestroyShader(GraphicsDevice* device, Shader* shader);
|
||||||
|
|
||||||
// Pipelines
|
// Pipelines
|
||||||
extern JULIET_API GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GraphicsDevice> device,
|
extern JULIET_API GraphicsPipeline* CreateGraphicsPipeline(GraphicsDevice* device,
|
||||||
const GraphicsPipelineCreateInfo& createInfo);
|
const GraphicsPipelineCreateInfo* createInfo);
|
||||||
extern JULIET_API void DestroyGraphicsPipeline(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsPipeline> graphicsPipeline);
|
extern JULIET_API void DestroyGraphicsPipeline(GraphicsDevice* device, GraphicsPipeline* graphicsPipeline);
|
||||||
#if ALLOW_SHADER_HOT_RELOAD
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
// Allows updating the graphics pipeline shaders. Can update either one or both shaders.
|
// Allows updating the graphics pipeline shaders. Can update either one or both shaders.
|
||||||
extern JULIET_API bool UpdateGraphicsPipelineShaders(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsPipeline> graphicsPipeline,
|
extern JULIET_API bool8 UpdateGraphicsPipelineShaders(GraphicsDevice* device, GraphicsPipeline* graphicsPipeline,
|
||||||
Shader* optional_vertexShader, Shader* optional_fragmentShader);
|
Shader* optional_vertexShader, Shader* optional_fragmentShader);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Buffers
|
// Buffers
|
||||||
extern JULIET_API GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo);
|
extern JULIET_API GraphicsBuffer* CreateGraphicsBuffer(GraphicsDevice* device, const BufferCreateInfo* createInfo);
|
||||||
extern JULIET_API GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device,
|
extern JULIET_API GraphicsTransferBuffer* CreateGraphicsTransferBuffer(GraphicsDevice* device,
|
||||||
const TransferBufferCreateInfo& createInfo);
|
const TransferBufferCreateInfo* createInfo);
|
||||||
extern JULIET_API void* MapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
|
extern JULIET_API void* MapGraphicsBuffer(GraphicsDevice* device, GraphicsBuffer* buffer);
|
||||||
extern JULIET_API void UnmapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
|
extern JULIET_API void UnmapGraphicsBuffer(GraphicsDevice* device, GraphicsBuffer* buffer);
|
||||||
extern JULIET_API void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
extern JULIET_API void* MapGraphicsTransferBuffer(GraphicsDevice* device, GraphicsTransferBuffer* buffer);
|
||||||
extern JULIET_API void UnmapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
extern JULIET_API void UnmapGraphicsTransferBuffer(GraphicsDevice* device, GraphicsTransferBuffer* buffer);
|
||||||
extern JULIET_API void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
extern JULIET_API void CopyBuffer(CommandList* commandList, GraphicsBuffer* dst,
|
||||||
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset = 0,
|
GraphicsTransferBuffer* src, size_t size, size_t dstOffset,
|
||||||
size_t srcOffset = 0);
|
size_t srcOffset);
|
||||||
extern JULIET_API void CopyBufferToTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Texture> dst,
|
extern JULIET_API void CopyBufferToTexture(CommandList* commandList, Texture* dst,
|
||||||
NonNullPtr<GraphicsTransferBuffer> src);
|
GraphicsTransferBuffer* src);
|
||||||
|
|
||||||
extern JULIET_API void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer);
|
extern JULIET_API void TransitionBufferToReadable(CommandList* commandList, GraphicsBuffer* buffer);
|
||||||
extern JULIET_API uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
|
extern JULIET_API uint32 GetBufferDescriptorIndex(GraphicsDevice* device, GraphicsBuffer* buffer);
|
||||||
extern JULIET_API uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<Texture> texture);
|
extern JULIET_API uint32 GetTextureDescriptorIndex(GraphicsDevice* device, Texture* texture);
|
||||||
|
|
||||||
extern JULIET_API void DestroyGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
|
extern JULIET_API void DestroyGraphicsBuffer(GraphicsDevice* device, GraphicsBuffer* buffer);
|
||||||
extern JULIET_API void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
extern JULIET_API void DestroyGraphicsTransferBuffer(GraphicsDevice* device, GraphicsTransferBuffer* buffer);
|
||||||
@@ -1,27 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum class BufferUsage : uint8
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
typedef uint8 BufferUsage;
|
||||||
|
enum BufferUsage_Enum
|
||||||
{
|
{
|
||||||
None = 0,
|
BufferUsage_None = 0,
|
||||||
IndexBuffer = 1 << 0,
|
BufferUsage_IndexBuffer = 1 << 0,
|
||||||
ConstantBuffer = 1 << 1,
|
BufferUsage_ConstantBuffer = 1 << 1,
|
||||||
StructuredBuffer = 1 << 2,
|
BufferUsage_StructuredBuffer = 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TransferBufferUsage : uint8
|
typedef uint8 TransferBufferUsage;
|
||||||
|
enum TransferBufferUsage_Enum
|
||||||
{
|
{
|
||||||
Download,
|
TransferBufferUsage_Download,
|
||||||
Upload
|
TransferBufferUsage_Upload
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct BufferCreateInfo BufferCreateInfo;
|
||||||
struct BufferCreateInfo
|
struct BufferCreateInfo
|
||||||
{
|
{
|
||||||
size_t Size;
|
size_t Size;
|
||||||
size_t Stride;
|
size_t Stride;
|
||||||
BufferUsage Usage;
|
BufferUsage Usage;
|
||||||
bool IsDynamic;
|
bool8 IsDynamic;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct TransferBufferCreateInfo TransferBufferCreateInfo;
|
||||||
struct TransferBufferCreateInfo
|
struct TransferBufferCreateInfo
|
||||||
{
|
{
|
||||||
size_t Size;
|
size_t Size;
|
||||||
@@ -29,5 +35,5 @@ struct TransferBufferCreateInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Opaque
|
// Opaque
|
||||||
struct GraphicsBuffer;
|
typedef struct GraphicsBuffer GraphicsBuffer;
|
||||||
struct GraphicsTransferBuffer;
|
typedef struct GraphicsTransferBuffer GraphicsTransferBuffer;
|
||||||
@@ -1,19 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
#define ALLOW_SHADER_HOT_RELOAD 1
|
#define ALLOW_SHADER_HOT_RELOAD 1
|
||||||
#else
|
#else
|
||||||
#define ALLOW_SHADER_HOT_RELOAD 0
|
#define ALLOW_SHADER_HOT_RELOAD 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum class GraphicsDriverType : uint8
|
typedef uint8 GraphicsDriverType;
|
||||||
|
enum GraphicsDriverType_Enum
|
||||||
{
|
{
|
||||||
Any = 0,
|
GraphicsDriverType_Any = 0,
|
||||||
DX12 = 1,
|
GraphicsDriverType_DX12 = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct GraphicsConfig GraphicsConfig;
|
||||||
struct GraphicsConfig
|
struct GraphicsConfig
|
||||||
{
|
{
|
||||||
GraphicsDriverType PreferredDriver = GraphicsDriverType::DX12;
|
GraphicsDriverType PreferredDriver;
|
||||||
bool EnableDebug;
|
bool8 EnableDebug;
|
||||||
};
|
};
|
||||||
@@ -1,42 +1,47 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Graphics/Shader.h>
|
#include <Graphics/Shader.h>
|
||||||
#include <Graphics/Texture.h>
|
#include <Graphics/Texture.h>
|
||||||
|
|
||||||
// Forward Declare
|
// Forward Declare
|
||||||
struct ColorTargetDescription;
|
typedef struct ColorTargetDescription ColorTargetDescription;
|
||||||
|
|
||||||
enum class FillMode : uint8
|
typedef uint8 FillMode;
|
||||||
|
enum FillMode_Enum
|
||||||
{
|
{
|
||||||
Solid,
|
FillMode_Solid,
|
||||||
Wireframe,
|
FillMode_Wireframe,
|
||||||
Count
|
FillMode_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CullMode : uint8
|
typedef uint8 CullMode;
|
||||||
|
enum CullMode_Enum
|
||||||
{
|
{
|
||||||
None,
|
CullMode_None,
|
||||||
Front,
|
CullMode_Front,
|
||||||
Back,
|
CullMode_Back,
|
||||||
Count
|
CullMode_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class FrontFace : uint8
|
typedef uint8 FrontFace;
|
||||||
|
enum FrontFace_Enum
|
||||||
{
|
{
|
||||||
CounterClockwise,
|
FrontFace_CounterClockwise,
|
||||||
Clockwise,
|
FrontFace_Clockwise,
|
||||||
Count
|
FrontFace_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PrimitiveType : uint8
|
typedef uint8 PrimitiveType;
|
||||||
|
enum PrimitiveType_Enum
|
||||||
{
|
{
|
||||||
TriangleList,
|
PrimitiveType_TriangleList,
|
||||||
TriangleStrip,
|
PrimitiveType_TriangleStrip,
|
||||||
LineList,
|
PrimitiveType_LineList,
|
||||||
LineStrip,
|
PrimitiveType_LineStrip,
|
||||||
PointList,
|
PrimitiveType_PointList,
|
||||||
Count
|
PrimitiveType_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct RasterizerState RasterizerState;
|
||||||
struct RasterizerState
|
struct RasterizerState
|
||||||
{
|
{
|
||||||
FillMode FillMode;
|
FillMode FillMode;
|
||||||
@@ -46,17 +51,19 @@ struct RasterizerState
|
|||||||
float DepthBiasConstantFactor; // How much depth value is added to each fragment
|
float DepthBiasConstantFactor; // How much depth value is added to each fragment
|
||||||
float DepthBiasClamp; // Maximum depth bias
|
float DepthBiasClamp; // Maximum depth bias
|
||||||
float DepthBiasSlopeFactor; // Scalar applied to Fragment's slope
|
float DepthBiasSlopeFactor; // Scalar applied to Fragment's slope
|
||||||
bool EnableDepthBias; // Bias fragment depth values
|
bool8 EnableDepthBias; // Bias fragment depth values
|
||||||
bool EnableDepthClip; // True to clip, false to clamp
|
bool8 EnableDepthClip; // True to clip, false to clamp
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class VertexInputRate : uint8
|
typedef uint8 VertexInputRate;
|
||||||
|
enum VertexInputRate_Enum
|
||||||
{
|
{
|
||||||
Vertex, // Use vertex index
|
VertexInputRate_Vertex, // Use vertex index
|
||||||
Instance, // Use instance index
|
VertexInputRate_Instance, // Use instance index
|
||||||
Count
|
VertexInputRate_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct VertexBufferDescription VertexBufferDescription;
|
||||||
struct VertexBufferDescription
|
struct VertexBufferDescription
|
||||||
{
|
{
|
||||||
uint32 Slot; // Binding Slot
|
uint32 Slot; // Binding Slot
|
||||||
@@ -65,68 +72,69 @@ struct VertexBufferDescription
|
|||||||
uint32 InstanceStepRate; // Only used when input rate == Instance. Number of instances to draw before advancing in the instance buffer by 1
|
uint32 InstanceStepRate; // Only used when input rate == Instance. Number of instances to draw before advancing in the instance buffer by 1
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class VertexElementFormat : uint8
|
typedef uint8 VertexElementFormat;
|
||||||
|
enum VertexElementFormat_Enum
|
||||||
{
|
{
|
||||||
Invalid,
|
VertexElementFormat_Invalid,
|
||||||
|
|
||||||
/* 32-bit Signed Integers */
|
/* 32-bit Signed Integers */
|
||||||
Int,
|
VertexElementFormat_Int,
|
||||||
Int2,
|
VertexElementFormat_Int2,
|
||||||
Int3,
|
VertexElementFormat_Int3,
|
||||||
Int4,
|
VertexElementFormat_Int4,
|
||||||
|
|
||||||
/* 32-bit Unsigned Integers */
|
/* 32-bit Unsigned Integers */
|
||||||
UInt,
|
VertexElementFormat_UInt,
|
||||||
UInt2,
|
VertexElementFormat_UInt2,
|
||||||
UInt3,
|
VertexElementFormat_UInt3,
|
||||||
UInt4,
|
VertexElementFormat_UInt4,
|
||||||
|
|
||||||
/* 32-bit Floats */
|
/* 32-bit Floats */
|
||||||
Float,
|
VertexElementFormat_Float,
|
||||||
Float2,
|
VertexElementFormat_Float2,
|
||||||
Float3,
|
VertexElementFormat_Float3,
|
||||||
Float4,
|
VertexElementFormat_Float4,
|
||||||
|
|
||||||
/* 8-bit Signed Integers */
|
/* 8-bit Signed Integers */
|
||||||
Byte2,
|
VertexElementFormat_Byte2,
|
||||||
Byte4,
|
VertexElementFormat_Byte4,
|
||||||
|
|
||||||
/* 8-bit Unsigned Integers */
|
/* 8-bit Unsigned Integers */
|
||||||
UByte2,
|
VertexElementFormat_UByte2,
|
||||||
UByte4,
|
VertexElementFormat_UByte4,
|
||||||
|
|
||||||
/* 8-bit Signed Normalized */
|
/* 8-bit Signed Normalized */
|
||||||
Byte2_Norm,
|
VertexElementFormat_Byte2_Norm,
|
||||||
Byte4_Norm,
|
VertexElementFormat_Byte4_Norm,
|
||||||
|
|
||||||
/* 8-bit Unsigned Normalized */
|
/* 8-bit Unsigned Normalized */
|
||||||
UByte2_Norm,
|
VertexElementFormat_UByte2_Norm,
|
||||||
UByte4_Norm,
|
VertexElementFormat_UByte4_Norm,
|
||||||
|
|
||||||
/* 16-bit Signed Integers */
|
/* 16-bit Signed Integers */
|
||||||
Short2,
|
VertexElementFormat_Short2,
|
||||||
Short4,
|
VertexElementFormat_Short4,
|
||||||
|
|
||||||
/* 16-bit Unsigned Integers */
|
/* 16-bit Unsigned Integers */
|
||||||
UShort2,
|
VertexElementFormat_UShort2,
|
||||||
UShort4,
|
VertexElementFormat_UShort4,
|
||||||
|
|
||||||
/* 16-bit Signed Normalized */
|
/* 16-bit Signed Normalized */
|
||||||
Short2_Norm,
|
VertexElementFormat_Short2_Norm,
|
||||||
Short4_Norm,
|
VertexElementFormat_Short4_Norm,
|
||||||
|
|
||||||
/* 16-bit Unsigned Normalized */
|
/* 16-bit Unsigned Normalized */
|
||||||
UShort2_Norm,
|
VertexElementFormat_UShort2_Norm,
|
||||||
UShort4_Norm,
|
VertexElementFormat_UShort4_Norm,
|
||||||
|
|
||||||
/* 16-bit Floats */
|
/* 16-bit Floats */
|
||||||
Half2,
|
VertexElementFormat_Half2,
|
||||||
Half4,
|
VertexElementFormat_Half4,
|
||||||
|
|
||||||
//
|
VertexElementFormat_Count
|
||||||
Count
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct VertexAttribute VertexAttribute;
|
||||||
struct VertexAttribute
|
struct VertexAttribute
|
||||||
{
|
{
|
||||||
uint32 Location; // Shader input location index
|
uint32 Location; // Shader input location index
|
||||||
@@ -135,6 +143,7 @@ struct VertexAttribute
|
|||||||
uint32 Offset; // Offset of this attribute relative to the start of the vertex element
|
uint32 Offset; // Offset of this attribute relative to the start of the vertex element
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct VertexInputState VertexInputState;
|
||||||
struct VertexInputState
|
struct VertexInputState
|
||||||
{
|
{
|
||||||
const VertexBufferDescription* VertexBufferDescriptions;
|
const VertexBufferDescription* VertexBufferDescriptions;
|
||||||
@@ -143,42 +152,46 @@ struct VertexInputState
|
|||||||
uint32 NumVertexAttributes;
|
uint32 NumVertexAttributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct GraphicsPipelineTargetInfo GraphicsPipelineTargetInfo;
|
||||||
struct GraphicsPipelineTargetInfo
|
struct GraphicsPipelineTargetInfo
|
||||||
{
|
{
|
||||||
const ColorTargetDescription* ColorTargetDescriptions;
|
const ColorTargetDescription* ColorTargetDescriptions;
|
||||||
size_t NumColorTargets;
|
size_t NumColorTargets;
|
||||||
TextureFormat DepthStencilFormat;
|
TextureFormat DepthStencilFormat;
|
||||||
bool HasDepthStencilTarget;
|
bool8 HasDepthStencilTarget;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CompareOperation : uint8
|
typedef uint8 CompareOperation;
|
||||||
|
enum CompareOperation_Enum
|
||||||
{
|
{
|
||||||
Invalid,
|
CompareOperation_Invalid,
|
||||||
Never, // The comparison always evaluates false.
|
CompareOperation_Never, // The comparison always evaluates false.
|
||||||
Less, // The comparison evaluates reference < test.
|
CompareOperation_Less, // The comparison evaluates reference < test.
|
||||||
Equal, // The comparison evaluates reference == test.
|
CompareOperation_Equal, // The comparison evaluates reference == test.
|
||||||
LessOrEqual, // The comparison evaluates reference <= test.
|
CompareOperation_LessOrEqual, // The comparison evaluates reference <= test.
|
||||||
Greater, // The comparison evaluates reference > test.
|
CompareOperation_Greater, // The comparison evaluates reference > test.
|
||||||
NotEqual, // The comparison evaluates reference != test.
|
CompareOperation_NotEqual, // The comparison evaluates reference != test.
|
||||||
GreaterOrEqual, // The comparison evalutes reference >= test.
|
CompareOperation_GreaterOrEqual, // The comparison evalutes reference >= test.
|
||||||
Always, // The comparison always evaluates true.
|
CompareOperation_Always, // The comparison always evaluates true.
|
||||||
Count
|
CompareOperation_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class StencilOperation : uint8
|
typedef uint8 StencilOperation;
|
||||||
|
enum StencilOperation_Enum
|
||||||
{
|
{
|
||||||
Invalid,
|
StencilOperation_Invalid,
|
||||||
Keep, // Keeps the current value.
|
StencilOperation_Keep, // Keeps the current value.
|
||||||
Zero, // Sets the value to 0.
|
StencilOperation_Zero, // Sets the value to 0.
|
||||||
Replace, // Sets the value to reference.
|
StencilOperation_Replace, // Sets the value to reference.
|
||||||
IncrementAndClamp, // Increments the current value and clamps to the maximum value.
|
StencilOperation_IncrementAndClamp, // Increments the current value and clamps to the maximum value.
|
||||||
DecrementAndClamp, // Decrements the current value and clamps to 0.
|
StencilOperation_DecrementAndClamp, // Decrements the current value and clamps to 0.
|
||||||
Invert, // Bitwise-inverts the current value.
|
StencilOperation_Invert, // Bitwise-inverts the current value.
|
||||||
IncrementAndWrap, // Increments the current value and wraps back to 0.
|
StencilOperation_IncrementAndWrap, // Increments the current value and wraps back to 0.
|
||||||
DecrementAndWrap, // Decrements the current value and wraps to the maximum value.
|
StencilOperation_DecrementAndWrap, // Decrements the current value and wraps to the maximum value.
|
||||||
Count
|
StencilOperation_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct StencilOperationState StencilOperationState;
|
||||||
struct StencilOperationState
|
struct StencilOperationState
|
||||||
{
|
{
|
||||||
StencilOperation FailOperation; // The action performed on samples that fail the stencil test.
|
StencilOperation FailOperation; // The action performed on samples that fail the stencil test.
|
||||||
@@ -187,6 +200,7 @@ struct StencilOperationState
|
|||||||
StencilOperation CompareOperation; // The comparison operator used in the stencil test.
|
StencilOperation CompareOperation; // The comparison operator used in the stencil test.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct DepthStencilState DepthStencilState;
|
||||||
struct DepthStencilState
|
struct DepthStencilState
|
||||||
{
|
{
|
||||||
CompareOperation CompareOperation; // The comparison operator used for depth testing.
|
CompareOperation CompareOperation; // The comparison operator used for depth testing.
|
||||||
@@ -194,18 +208,20 @@ struct DepthStencilState
|
|||||||
StencilOperationState FrontStencilState; // The stencil op state for front-facing triangles.
|
StencilOperationState FrontStencilState; // The stencil op state for front-facing triangles.
|
||||||
uint8 CompareMask; // Selects the bits of the stencil values participating in the stencil test.
|
uint8 CompareMask; // Selects the bits of the stencil values participating in the stencil test.
|
||||||
uint8 WriteMask; // Selects the bits of the stencil values updated by the stencil test.
|
uint8 WriteMask; // Selects the bits of the stencil values updated by the stencil test.
|
||||||
bool EnableDepthTest : 1; // true enables the depth test.
|
bool8 EnableDepthTest : 1; // true enables the depth test.
|
||||||
bool EnableDepthWrite : 1; // true enables depth writes. Depth writes are always disabled when enable_depth_test is false.
|
bool8 EnableDepthWrite : 1; // true enables depth writes. Depth writes are always disabled when enable_depth_test is false.
|
||||||
bool EnableStencilTest : 1; // true enables the stencil test.
|
bool8 EnableStencilTest : 1; // true enables the stencil test.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct MultisampleState MultisampleState;
|
||||||
struct MultisampleState
|
struct MultisampleState
|
||||||
{
|
{
|
||||||
TextureSampleCount SampleCount;
|
TextureSampleCount SampleCount;
|
||||||
uint32 SampleMask; // Which sample should be updated. If Enabled mask == false -> 0xFFFFFFFF
|
uint32 SampleMask; // Which sample should be updated. If Enabled mask == false -> 0xFFFFFFFF
|
||||||
bool EnableMask;
|
bool8 EnableMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct GraphicsPipelineCreateInfo GraphicsPipelineCreateInfo;
|
||||||
struct GraphicsPipelineCreateInfo
|
struct GraphicsPipelineCreateInfo
|
||||||
{
|
{
|
||||||
Shader* VertexShader;
|
Shader* VertexShader;
|
||||||
@@ -219,4 +235,4 @@ struct GraphicsPipelineCreateInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Opaque type
|
// Opaque type
|
||||||
struct GraphicsPipeline;
|
typedef struct GraphicsPipeline GraphicsPipeline;
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Graphics/Graphics.h>
|
#include <Graphics/Graphics.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
extern bool ImGuiRenderer_Initialize(GraphicsDevice* device);
|
extern bool8 ImGuiRenderer_Initialize(GraphicsDevice* device);
|
||||||
extern void ImGuiRenderer_Shutdown(GraphicsDevice* device);
|
extern void ImGuiRenderer_Shutdown(GraphicsDevice* device);
|
||||||
extern void ImGuiRenderer_NewFrame();
|
extern void ImGuiRenderer_NewFrame(void);
|
||||||
extern JULIET_API void ImGuiRenderer_Render(CommandList* cmdList, RenderPass* renderPass);
|
extern JULIET_API void ImGuiRenderer_Render(CommandList* cmdList, RenderPass* renderPass);
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Juliet.h>
|
|
||||||
#include <Core/Math/Vector.h>
|
#include <Core/Math/Vector.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
typedef struct PointLight PointLight;
|
||||||
struct PointLight
|
struct PointLight
|
||||||
{
|
{
|
||||||
Vector3 Position;
|
Vector3 Position;
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
#include <Core/Math/Matrix.h>
|
#include <Core/Math/Matrix.h>
|
||||||
#include <Core/Math/Vector.h>
|
#include <Core/Math/Vector.h>
|
||||||
|
|
||||||
struct Arena;
|
typedef struct Arena Arena;
|
||||||
struct Vertex;
|
typedef struct Vertex Vertex;
|
||||||
|
|
||||||
using MeshAssetID = index_t;
|
typedef index_t MeshAssetID;
|
||||||
using MaterialAssetID = index_t;
|
typedef index_t MaterialAssetID;
|
||||||
using MeshInstanceID = index_t;
|
typedef index_t MeshInstanceID;
|
||||||
|
|
||||||
|
typedef struct MeshAsset MeshAsset;
|
||||||
struct MeshAsset
|
struct MeshAsset
|
||||||
{
|
{
|
||||||
String Name;
|
String Name;
|
||||||
@@ -22,14 +22,16 @@ struct MeshAsset
|
|||||||
index_t IndexOffset;
|
index_t IndexOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct MaterialAsset MaterialAsset;
|
||||||
struct MaterialAsset
|
struct MaterialAsset
|
||||||
{
|
{
|
||||||
Vector4 AlbedoColor = { 1.0f, 1.0f, 1.0f, 1.0f };
|
Vector4 AlbedoColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct MeshInstance MeshInstance;
|
||||||
struct MeshInstance
|
struct MeshInstance
|
||||||
{
|
{
|
||||||
MeshAssetID MeshAsset;
|
MeshAssetID MeshAsset;
|
||||||
MaterialAssetID MaterialAsset;
|
MaterialAssetID MaterialAsset;
|
||||||
Matrix Transform = MatrixIdentity();
|
Matrix Transform;
|
||||||
};
|
};
|
||||||
@@ -1,57 +1,56 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Container/Vector.h>
|
#include <Core/Container/Vector.h>
|
||||||
#include <Core/Math/Matrix.h>
|
#include <Core/Math/Matrix.h>
|
||||||
#include <Graphics/GraphicsConfig.h>
|
#include <Graphics/GraphicsConfig.h>
|
||||||
#include <Graphics/Lighting.h>
|
#include <Graphics/Lighting.h>
|
||||||
|
#include <Graphics/Mesh.h>
|
||||||
#include <Graphics/PushConstants.h>
|
#include <Graphics/PushConstants.h>
|
||||||
#include <Graphics/VertexData.h>
|
#include <Graphics/VertexData.h>
|
||||||
#include <Graphics/Mesh.h>
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
struct GraphicsTransferBuffer;
|
typedef struct GraphicsTransferBuffer GraphicsTransferBuffer;
|
||||||
struct RenderPass;
|
typedef struct RenderPass RenderPass;
|
||||||
struct CommandList;
|
typedef struct CommandList CommandList;
|
||||||
struct GraphicsBuffer;
|
typedef struct GraphicsBuffer GraphicsBuffer;
|
||||||
struct Window;
|
typedef struct Window Window;
|
||||||
struct GraphicsPipeline;
|
typedef struct GraphicsPipeline GraphicsPipeline;
|
||||||
struct GraphicsDevice;
|
typedef struct GraphicsDevice GraphicsDevice;
|
||||||
using LightID = index_t;
|
typedef index_t LightID;
|
||||||
|
|
||||||
constexpr size_t kGeometryPage = Megabytes(64);
|
#define kGeometryPage Megabytes(64)
|
||||||
constexpr size_t kIndexPage = Megabytes(32);
|
#define kIndexPage Megabytes(32)
|
||||||
constexpr size_t kDefaultMeshNumber = 500;
|
#define kDefaultMeshNumber ((size_t)500)
|
||||||
constexpr size_t kDefaultVertexCount = 2'000'000; // Fit less than one geometry page
|
#define kDefaultVertexCount ((size_t)2000000)
|
||||||
constexpr size_t kDefaultIndexCount = 16'000'000; // Fit less than one index page
|
#define kDefaultIndexCount ((size_t)16000000)
|
||||||
constexpr size_t kDefaultLightCount = 1024;
|
#define kDefaultLightCount ((size_t)1024)
|
||||||
|
|
||||||
JULIET_API void InitializeMeshRenderer(NonNullPtr<Arena> assetArena, NonNullPtr<Arena> instanceArena);
|
JULIET_API void InitializeMeshRenderer(Arena* assetArena, Arena* instanceArena);
|
||||||
[[nodiscard]] JULIET_API bool InitializeMeshRendererGraphics(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
JULIET_API bool8 InitializeMeshRendererGraphics(GraphicsDevice* device, Window* window);
|
||||||
JULIET_API void ShutdownMeshRendererGraphics();
|
JULIET_API void ShutdownMeshRendererGraphics(void);
|
||||||
JULIET_API void ShutdownMeshRenderer();
|
JULIET_API void ShutdownMeshRenderer(void);
|
||||||
JULIET_API void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList);
|
JULIET_API void LoadMeshesOnGPU(CommandList* cmdList);
|
||||||
JULIET_API void RenderMeshes(NonNullPtr<CommandList> cmdList, NonNullPtr<RenderPass> pass, const Matrix& viewProjection);
|
JULIET_API void RenderMeshes(CommandList* cmdList, RenderPass* pass, const Matrix* viewProjection);
|
||||||
|
|
||||||
// Lights
|
// Lights
|
||||||
[[nodiscard]] JULIET_API LightID AddPointLight(const PointLight& light);
|
JULIET_API LightID AddPointLight(const PointLight* light);
|
||||||
JULIET_API void SetPointLightPosition(LightID id, const Vector3& position);
|
JULIET_API void SetPointLightPosition(LightID id, Vector3 position);
|
||||||
JULIET_API void SetPointLightColor(LightID id, const Vector3& color);
|
JULIET_API void SetPointLightColor(LightID id, Vector3 color);
|
||||||
JULIET_API void SetPointLightRadius(LightID id, float radius);
|
JULIET_API void SetPointLightRadius(LightID id, float radius);
|
||||||
JULIET_API void SetPointLightIntensity(LightID id, float intensity);
|
JULIET_API void SetPointLightIntensity(LightID id, float intensity);
|
||||||
JULIET_API void ClearPointLights();
|
JULIET_API void ClearPointLights(void);
|
||||||
JULIET_API void SetGlobalLight(const Vector3& direction, const Vector3& color, float ambientIntensity);
|
JULIET_API void SetGlobalLight(Vector3 direction, Vector3 color, float ambientIntensity);
|
||||||
|
|
||||||
// Assets & Instances
|
// Assets & Instances
|
||||||
[[nodiscard]] JULIET_API MeshAssetID GetOrCreateMeshAsset(String name);
|
JULIET_API MeshAssetID GetOrCreateMeshAsset(String name);
|
||||||
[[nodiscard]] JULIET_API MeshInstanceID CreateMeshInstance(MeshAssetID meshAsset, MaterialAssetID materialAsset, const Matrix& transform);
|
JULIET_API MeshInstanceID CreateMeshInstance(MeshAssetID meshAsset, MaterialAssetID materialAsset, const Matrix* transform);
|
||||||
JULIET_API void SetMeshInstanceTransform(MeshInstanceID id, const Matrix& transform);
|
JULIET_API void SetMeshInstanceTransform(MeshInstanceID id, const Matrix* transform);
|
||||||
|
|
||||||
// Primitives
|
// Primitives
|
||||||
JULIET_API MeshAssetID GetCubePrimitiveMeshAssetID();
|
JULIET_API MeshAssetID GetCubePrimitiveMeshAssetID(void);
|
||||||
JULIET_API MeshAssetID GetQuadPrimitiveMeshAssetID();
|
JULIET_API MeshAssetID GetQuadPrimitiveMeshAssetID(void);
|
||||||
JULIET_API MeshAssetID GetSpherePrimitiveMeshAssetID();
|
JULIET_API MeshAssetID GetSpherePrimitiveMeshAssetID(void);
|
||||||
|
|
||||||
#if ALLOW_SHADER_HOT_RELOAD
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
JULIET_API void ReloadMeshRendererShaders();
|
JULIET_API void ReloadMeshRendererShaders(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Math/Matrix.h>
|
#include <Core/Math/Matrix.h>
|
||||||
#include <Core/Math/Vector.h>
|
#include <Core/Math/Vector.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
typedef struct PushData PushData;
|
||||||
struct PushData
|
struct PushData
|
||||||
{
|
{
|
||||||
Matrix ViewProjection;
|
Matrix ViewProjection;
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Graphics/Colors.h>
|
#include <Graphics/Colors.h>
|
||||||
#include <Graphics/Texture.h>
|
#include <Graphics/Texture.h>
|
||||||
|
|
||||||
enum struct LoadOperation : uint8
|
typedef uint8 LoadOperation;
|
||||||
|
enum LoadOperation_Enum
|
||||||
{
|
{
|
||||||
Load, // Load the texture from memory (preserve)
|
LoadOperation_Load, // Load the texture from memory (preserve)
|
||||||
Clear, // Clear the texture
|
LoadOperation_Clear, // Clear the texture
|
||||||
Ignore // Ignore the content of the texture (undefined)
|
LoadOperation_Ignore // Ignore the content of the texture (undefined)
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct StoreOperation : uint8
|
typedef uint8 StoreOperation;
|
||||||
|
enum StoreOperation_Enum
|
||||||
{
|
{
|
||||||
Store, // Store the result of the render pass into memory
|
StoreOperation_Store, // Store the result of the render pass into memory
|
||||||
Ignore, // Whatever is generated is ignored (undefined)
|
StoreOperation_Ignore, // Whatever is generated is ignored (undefined)
|
||||||
Resolve, // Resolve MipMaps into non mip map texture. Discard MipMap content
|
StoreOperation_Resolve, // Resolve MipMaps into non mip map texture. Discard MipMap content
|
||||||
ResolveAndStore // Same but store the MipMap content to memory
|
StoreOperation_ResolveAndStore // Same but store the MipMap content to memory
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct ColorTargetInfo ColorTargetInfo;
|
||||||
struct ColorTargetInfo
|
struct ColorTargetInfo
|
||||||
{
|
{
|
||||||
Texture* TargetTexture;
|
Texture* TargetTexture;
|
||||||
@@ -27,18 +30,19 @@ struct ColorTargetInfo
|
|||||||
uint32 DepthPlane;
|
uint32 DepthPlane;
|
||||||
uint32 LayerIndex;
|
uint32 LayerIndex;
|
||||||
};
|
};
|
||||||
bool CycleTexture; // Whether the texture should be cycled if already bound (and load operation != LOAD)
|
bool8 CycleTexture; // Whether the texture should be cycled if already bound (and load operation != LOAD)
|
||||||
|
|
||||||
Texture* ResolveTexture;
|
Texture* ResolveTexture;
|
||||||
uint32 ResolveMipLevel;
|
uint32 ResolveMipLevel;
|
||||||
uint32 ResolveLayerIndex;
|
uint32 ResolveLayerIndex;
|
||||||
bool CycleResolveTexture;
|
bool8 CycleResolveTexture;
|
||||||
|
|
||||||
FColor ClearColor;
|
FColor ClearColor;
|
||||||
LoadOperation LoadOperation;
|
LoadOperation LoadOperation;
|
||||||
StoreOperation StoreOperation;
|
StoreOperation StoreOperation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct DepthStencilTargetInfo DepthStencilTargetInfo;
|
||||||
struct DepthStencilTargetInfo
|
struct DepthStencilTargetInfo
|
||||||
{
|
{
|
||||||
Texture* TargetTexture;
|
Texture* TargetTexture;
|
||||||
@@ -51,44 +55,48 @@ struct DepthStencilTargetInfo
|
|||||||
StoreOperation StoreOperation;
|
StoreOperation StoreOperation;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BlendFactor : uint8
|
typedef uint8 BlendFactor;
|
||||||
|
enum BlendFactor_Enum
|
||||||
{
|
{
|
||||||
Invalid,
|
BlendFactor_Invalid,
|
||||||
Zero,
|
BlendFactor_Zero,
|
||||||
One,
|
BlendFactor_One,
|
||||||
Src_Color,
|
BlendFactor_Src_Color,
|
||||||
One_Minus_Src_Color,
|
BlendFactor_One_Minus_Src_Color,
|
||||||
Dst_Color,
|
BlendFactor_Dst_Color,
|
||||||
One_Minus_Dst_Color,
|
BlendFactor_One_Minus_Dst_Color,
|
||||||
Src_Alpha,
|
BlendFactor_Src_Alpha,
|
||||||
One_Minus_Src_Alpha,
|
BlendFactor_One_Minus_Src_Alpha,
|
||||||
Dst_Alpha,
|
BlendFactor_Dst_Alpha,
|
||||||
One_Minus_Dst_Alpha,
|
BlendFactor_One_Minus_Dst_Alpha,
|
||||||
Constant_Color,
|
BlendFactor_Constant_Color,
|
||||||
One_MINUS_Constant_Color,
|
BlendFactor_One_MINUS_Constant_Color,
|
||||||
Src_Alpha_Saturate, // min(source alpha, 1 - destination alpha)
|
BlendFactor_Src_Alpha_Saturate, // min(source alpha, 1 - destination alpha)
|
||||||
Count
|
BlendFactor_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BlendOperation : uint8
|
typedef uint8 BlendOperation;
|
||||||
|
enum BlendOperation_Enum
|
||||||
{
|
{
|
||||||
Invalid,
|
BlendOperation_Invalid,
|
||||||
Add, // (source * source_factor) + (destination * destination_factor)
|
BlendOperation_Add, // (source * source_factor) + (destination * destination_factor)
|
||||||
Subtract, // (source * source_factor) - (destination * destination_factor)
|
BlendOperation_Subtract, // (source * source_factor) - (destination * destination_factor)
|
||||||
ReverseSubtract, // (destination * destination_factor) - (source * source_factor)
|
BlendOperation_ReverseSubtract, // (destination * destination_factor) - (source * source_factor)
|
||||||
Min, // min(source, destination)
|
BlendOperation_Min, // min(source, destination)
|
||||||
Max, // max(source, destination)
|
BlendOperation_Max, // max(source, destination)
|
||||||
Count
|
BlendOperation_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ColorComponentFlags : uint8
|
typedef uint8 ColorComponentFlags;
|
||||||
|
enum ColorComponentFlags_Enum
|
||||||
{
|
{
|
||||||
R = 1u << 0,
|
ColorComponentFlags_R = 1u << 0,
|
||||||
G = 1u << 1,
|
ColorComponentFlags_G = 1u << 1,
|
||||||
B = 1u << 2,
|
ColorComponentFlags_B = 1u << 2,
|
||||||
A = 1u << 3
|
ColorComponentFlags_A = 1u << 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct ColorTargetBlendState ColorTargetBlendState;
|
||||||
struct ColorTargetBlendState
|
struct ColorTargetBlendState
|
||||||
{
|
{
|
||||||
BlendFactor SourceColorBlendFactor; // The value to be multiplied by the source RGB value.
|
BlendFactor SourceColorBlendFactor; // The value to be multiplied by the source RGB value.
|
||||||
@@ -98,10 +106,11 @@ struct ColorTargetBlendState
|
|||||||
BlendFactor DestinationAlphaBlendFactor; // The value to be multiplied by the destination alpha.
|
BlendFactor DestinationAlphaBlendFactor; // The value to be multiplied by the destination alpha.
|
||||||
BlendOperation AlphaBlendOperation; // The blend operation for the alpha component.
|
BlendOperation AlphaBlendOperation; // The blend operation for the alpha component.
|
||||||
ColorComponentFlags ColorWriteMask; // A bitmask specifying which of the RGBA components are enabled for writing. Writes to all channels if enable_color_write_mask is false.
|
ColorComponentFlags ColorWriteMask; // A bitmask specifying which of the RGBA components are enabled for writing. Writes to all channels if enable_color_write_mask is false.
|
||||||
bool EnableBlend : 1; // Whether blending is enabled for the color target.
|
bool8 EnableBlend : 1; // Whether blending is enabled for the color target.
|
||||||
bool EnableColorWriteMask : 1; // Whether the color write mask is enabled.
|
bool8 EnableColorWriteMask : 1; // Whether the color write mask is enabled.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct ColorTargetDescription ColorTargetDescription;
|
||||||
struct ColorTargetDescription
|
struct ColorTargetDescription
|
||||||
{
|
{
|
||||||
TextureFormat Format;
|
TextureFormat Format;
|
||||||
@@ -109,4 +118,4 @@ struct ColorTargetDescription
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Opaque Type
|
// Opaque Type
|
||||||
struct RenderPass;
|
typedef struct RenderPass RenderPass;
|
||||||
@@ -1,20 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
// Opaque type
|
// Opaque type
|
||||||
struct Shader;
|
typedef struct Shader Shader;
|
||||||
|
|
||||||
enum class ShaderStage : uint8
|
typedef uint8 ShaderStage;
|
||||||
|
enum ShaderStage_Enum
|
||||||
{
|
{
|
||||||
Vertex,
|
ShaderStage_Vertex,
|
||||||
Fragment,
|
ShaderStage_Fragment,
|
||||||
Compute
|
ShaderStage_Compute
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct ShaderCreateInfo ShaderCreateInfo;
|
||||||
struct ShaderCreateInfo
|
struct ShaderCreateInfo
|
||||||
{
|
{
|
||||||
ShaderStage Stage;
|
ShaderStage Stage;
|
||||||
String EntryPoint;
|
String EntryPoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,28 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Core/Math/Matrix.h>
|
#include <Core/Math/Matrix.h>
|
||||||
#include <Graphics/GraphicsConfig.h>
|
#include <Graphics/GraphicsConfig.h>
|
||||||
|
|
||||||
struct RenderPass;
|
typedef struct RenderPass RenderPass;
|
||||||
struct CommandList;
|
typedef struct CommandList CommandList;
|
||||||
struct Window;
|
typedef struct Window Window;
|
||||||
struct GraphicsPipeline;
|
typedef struct GraphicsPipeline GraphicsPipeline;
|
||||||
struct GraphicsDevice;
|
typedef struct GraphicsDevice GraphicsDevice;
|
||||||
|
|
||||||
|
typedef struct SkyboxRenderer SkyboxRenderer;
|
||||||
struct SkyboxRenderer
|
struct SkyboxRenderer
|
||||||
{
|
{
|
||||||
GraphicsDevice* Device;
|
GraphicsDevice* Device;
|
||||||
GraphicsPipeline* Pipeline;
|
GraphicsPipeline* Pipeline;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] JULIET_API bool InitializeSkyboxRenderer(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
JULIET_API bool8 InitializeSkyboxRenderer(GraphicsDevice* device, Window* window);
|
||||||
JULIET_API void ShutdownSkyboxRenderer();
|
JULIET_API void ShutdownSkyboxRenderer(void);
|
||||||
JULIET_API void RenderSkybox(NonNullPtr<CommandList> cmdList, NonNullPtr<RenderPass> pass, const Matrix& viewProjection);
|
JULIET_API void RenderSkybox(CommandList* cmdList, RenderPass* pass, const Matrix* viewProjection);
|
||||||
|
|
||||||
#if ALLOW_SHADER_HOT_RELOAD
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
JULIET_API void ReloadSkyboxShaders();
|
JULIET_API void ReloadSkyboxShaders(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
+137
-131
@@ -1,164 +1,170 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum struct TextureFormat : uint8
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
typedef uint8 TextureFormat;
|
||||||
|
enum TextureFormat_Enum
|
||||||
{
|
{
|
||||||
Invalid,
|
TextureFormat_Invalid,
|
||||||
|
|
||||||
/* Unsigned Normalized Float Color Formats */
|
/* Unsigned Normalized Float Color Formats */
|
||||||
A8_UNORM,
|
TextureFormat_A8_UNORM,
|
||||||
R8_UNORM,
|
TextureFormat_R8_UNORM,
|
||||||
R8G8_UNORM,
|
TextureFormat_R8G8_UNORM,
|
||||||
R8G8B8A8_UNORM,
|
TextureFormat_R8G8B8A8_UNORM,
|
||||||
R16_UNORM,
|
TextureFormat_R16_UNORM,
|
||||||
R16G16_UNORM,
|
TextureFormat_R16G16_UNORM,
|
||||||
R16G16B16A16_UNORM,
|
TextureFormat_R16G16B16A16_UNORM,
|
||||||
R10G10B10A2_UNORM,
|
TextureFormat_R10G10B10A2_UNORM,
|
||||||
B5G6R5_UNORM,
|
TextureFormat_B5G6R5_UNORM,
|
||||||
B5G5R5A1_UNORM,
|
TextureFormat_B5G5R5A1_UNORM,
|
||||||
B4G4R4A4_UNORM,
|
TextureFormat_B4G4R4A4_UNORM,
|
||||||
B8G8R8A8_UNORM,
|
TextureFormat_B8G8R8A8_UNORM,
|
||||||
/* Compressed Unsigned Normalized Float Color Formats */
|
/* Compressed Unsigned Normalized Float Color Formats */
|
||||||
BC1_RGBA_UNORM,
|
TextureFormat_BC1_RGBA_UNORM,
|
||||||
BC2_RGBA_UNORM,
|
TextureFormat_BC2_RGBA_UNORM,
|
||||||
BC3_RGBA_UNORM,
|
TextureFormat_BC3_RGBA_UNORM,
|
||||||
BC4_R_UNORM,
|
TextureFormat_BC4_R_UNORM,
|
||||||
BC5_RG_UNORM,
|
TextureFormat_BC5_RG_UNORM,
|
||||||
BC7_RGBA_UNORM,
|
TextureFormat_BC7_RGBA_UNORM,
|
||||||
/* Compressed Signed Float Color Formats */
|
/* Compressed Signed Float Color Formats */
|
||||||
BC6H_RGB_FLOAT,
|
TextureFormat_BC6H_RGB_FLOAT,
|
||||||
/* Compressed Unsigned Float Color Formats */
|
/* Compressed Unsigned Float Color Formats */
|
||||||
BC6H_RGB_UFLOAT,
|
TextureFormat_BC6H_RGB_UFLOAT,
|
||||||
/* Signed Normalized Float Color Formats */
|
/* Signed Normalized Float Color Formats */
|
||||||
R8_SNORM,
|
TextureFormat_R8_SNORM,
|
||||||
R8G8_SNORM,
|
TextureFormat_R8G8_SNORM,
|
||||||
R8G8B8A8_SNORM,
|
TextureFormat_R8G8B8A8_SNORM,
|
||||||
R16_SNORM,
|
TextureFormat_R16_SNORM,
|
||||||
R16G16_SNORM,
|
TextureFormat_R16G16_SNORM,
|
||||||
R16G16B16A16_SNORM,
|
TextureFormat_R16G16B16A16_SNORM,
|
||||||
/* Signed Float Color Formats */
|
/* Signed Float Color Formats */
|
||||||
R16_FLOAT,
|
TextureFormat_R16_FLOAT,
|
||||||
R16G16_FLOAT,
|
TextureFormat_R16G16_FLOAT,
|
||||||
R16G16B16A16_FLOAT,
|
TextureFormat_R16G16B16A16_FLOAT,
|
||||||
R32_FLOAT,
|
TextureFormat_R32_FLOAT,
|
||||||
R32G32_FLOAT,
|
TextureFormat_R32G32_FLOAT,
|
||||||
R32G32B32A32_FLOAT,
|
TextureFormat_R32G32B32A32_FLOAT,
|
||||||
/* Unsigned Float Color Formats */
|
/* Unsigned Float Color Formats */
|
||||||
R11G11B10_UFLOAT,
|
TextureFormat_R11G11B10_UFLOAT,
|
||||||
/* Unsigned Integer Color Formats */
|
/* Unsigned Integer Color Formats */
|
||||||
R8_UINT,
|
TextureFormat_R8_UINT,
|
||||||
R8G8_UINT,
|
TextureFormat_R8G8_UINT,
|
||||||
R8G8B8A8_UINT,
|
TextureFormat_R8G8B8A8_UINT,
|
||||||
R16_UINT,
|
TextureFormat_R16_UINT,
|
||||||
R16G16_UINT,
|
TextureFormat_R16G16_UINT,
|
||||||
R16G16B16A16_UINT,
|
TextureFormat_R16G16B16A16_UINT,
|
||||||
R32_UINT,
|
TextureFormat_R32_UINT,
|
||||||
R32G32_UINT,
|
TextureFormat_R32G32_UINT,
|
||||||
R32G32B32A32_UINT,
|
TextureFormat_R32G32B32A32_UINT,
|
||||||
/* Signed Integer Color Formats */
|
/* Signed Integer Color Formats */
|
||||||
R8_INT,
|
TextureFormat_R8_INT,
|
||||||
R8G8_INT,
|
TextureFormat_R8G8_INT,
|
||||||
R8G8B8A8_INT,
|
TextureFormat_R8G8B8A8_INT,
|
||||||
R16_INT,
|
TextureFormat_R16_INT,
|
||||||
R16G16_INT,
|
TextureFormat_R16G16_INT,
|
||||||
R16G16B16A16_INT,
|
TextureFormat_R16G16B16A16_INT,
|
||||||
R32_INT,
|
TextureFormat_R32_INT,
|
||||||
R32G32_INT,
|
TextureFormat_R32G32_INT,
|
||||||
R32G32B32A32_INT,
|
TextureFormat_R32G32B32A32_INT,
|
||||||
/* SRGB Unsigned Normalized Color Formats */
|
/* SRGB Unsigned Normalized Color Formats */
|
||||||
R8G8B8A8_UNORM_SRGB,
|
TextureFormat_R8G8B8A8_UNORM_SRGB,
|
||||||
B8G8R8A8_UNORM_SRGB,
|
TextureFormat_B8G8R8A8_UNORM_SRGB,
|
||||||
/* Compressed SRGB Unsigned Normalized Color Formats */
|
/* Compressed SRGB Unsigned Normalized Color Formats */
|
||||||
BC1_RGBA_UNORM_SRGB,
|
TextureFormat_BC1_RGBA_UNORM_SRGB,
|
||||||
BC2_RGBA_UNORM_SRGB,
|
TextureFormat_BC2_RGBA_UNORM_SRGB,
|
||||||
BC3_RGBA_UNORM_SRGB,
|
TextureFormat_BC3_RGBA_UNORM_SRGB,
|
||||||
BC7_RGBA_UNORM_SRGB,
|
TextureFormat_BC7_RGBA_UNORM_SRGB,
|
||||||
/* Depth Formats */
|
/* Depth Formats */
|
||||||
D16_UNORM,
|
TextureFormat_D16_UNORM,
|
||||||
D24_UNORM,
|
TextureFormat_D24_UNORM,
|
||||||
D32_FLOAT,
|
TextureFormat_D32_FLOAT,
|
||||||
D24_UNORM_S8_UINT,
|
TextureFormat_D24_UNORM_S8_UINT,
|
||||||
D32_FLOAT_S8_UINT,
|
TextureFormat_D32_FLOAT_S8_UINT,
|
||||||
/* Compressed ASTC Normalized Float Color Formats*/
|
/* Compressed ASTC Normalized Float Color Formats*/
|
||||||
ASTC_4x4_UNORM,
|
TextureFormat_ASTC_4x4_UNORM,
|
||||||
ASTC_5x4_UNORM,
|
TextureFormat_ASTC_5x4_UNORM,
|
||||||
ASTC_5x5_UNORM,
|
TextureFormat_ASTC_5x5_UNORM,
|
||||||
ASTC_6x5_UNORM,
|
TextureFormat_ASTC_6x5_UNORM,
|
||||||
ASTC_6x6_UNORM,
|
TextureFormat_ASTC_6x6_UNORM,
|
||||||
ASTC_8x5_UNORM,
|
TextureFormat_ASTC_8x5_UNORM,
|
||||||
ASTC_8x6_UNORM,
|
TextureFormat_ASTC_8x6_UNORM,
|
||||||
ASTC_8x8_UNORM,
|
TextureFormat_ASTC_8x8_UNORM,
|
||||||
ASTC_10x5_UNORM,
|
TextureFormat_ASTC_10x5_UNORM,
|
||||||
ASTC_10x6_UNORM,
|
TextureFormat_ASTC_10x6_UNORM,
|
||||||
ASTC_10x8_UNORM,
|
TextureFormat_ASTC_10x8_UNORM,
|
||||||
ASTC_10x10_UNORM,
|
TextureFormat_ASTC_10x10_UNORM,
|
||||||
ASTC_12x10_UNORM,
|
TextureFormat_ASTC_12x10_UNORM,
|
||||||
ASTC_12x12_UNORM,
|
TextureFormat_ASTC_12x12_UNORM,
|
||||||
/* Compressed SRGB ASTC Normalized Float Color Formats*/
|
/* Compressed SRGB ASTC Normalized Float Color Formats*/
|
||||||
ASTC_4x4_UNORM_SRGB,
|
TextureFormat_ASTC_4x4_UNORM_SRGB,
|
||||||
ASTC_5x4_UNORM_SRGB,
|
TextureFormat_ASTC_5x4_UNORM_SRGB,
|
||||||
ASTC_5x5_UNORM_SRGB,
|
TextureFormat_ASTC_5x5_UNORM_SRGB,
|
||||||
ASTC_6x5_UNORM_SRGB,
|
TextureFormat_ASTC_6x5_UNORM_SRGB,
|
||||||
ASTC_6x6_UNORM_SRGB,
|
TextureFormat_ASTC_6x6_UNORM_SRGB,
|
||||||
ASTC_8x5_UNORM_SRGB,
|
TextureFormat_ASTC_8x5_UNORM_SRGB,
|
||||||
ASTC_8x6_UNORM_SRGB,
|
TextureFormat_ASTC_8x6_UNORM_SRGB,
|
||||||
ASTC_8x8_UNORM_SRGB,
|
TextureFormat_ASTC_8x8_UNORM_SRGB,
|
||||||
ASTC_10x5_UNORM_SRGB,
|
TextureFormat_ASTC_10x5_UNORM_SRGB,
|
||||||
ASTC_10x6_UNORM_SRGB,
|
TextureFormat_ASTC_10x6_UNORM_SRGB,
|
||||||
ASTC_10x8_UNORM_SRGB,
|
TextureFormat_ASTC_10x8_UNORM_SRGB,
|
||||||
ASTC_10x10_UNORM_SRGB,
|
TextureFormat_ASTC_10x10_UNORM_SRGB,
|
||||||
ASTC_12x10_UNORM_SRGB,
|
TextureFormat_ASTC_12x10_UNORM_SRGB,
|
||||||
ASTC_12x12_UNORM_SRGB,
|
TextureFormat_ASTC_12x12_UNORM_SRGB,
|
||||||
/* Compressed ASTC Signed Float Color Formats*/
|
/* Compressed ASTC Signed Float Color Formats*/
|
||||||
ASTC_4x4_FLOAT,
|
TextureFormat_ASTC_4x4_FLOAT,
|
||||||
ASTC_5x4_FLOAT,
|
TextureFormat_ASTC_5x4_FLOAT,
|
||||||
ASTC_5x5_FLOAT,
|
TextureFormat_ASTC_5x5_FLOAT,
|
||||||
ASTC_6x5_FLOAT,
|
TextureFormat_ASTC_6x5_FLOAT,
|
||||||
ASTC_6x6_FLOAT,
|
TextureFormat_ASTC_6x6_FLOAT,
|
||||||
ASTC_8x5_FLOAT,
|
TextureFormat_ASTC_8x5_FLOAT,
|
||||||
ASTC_8x6_FLOAT,
|
TextureFormat_ASTC_8x6_FLOAT,
|
||||||
ASTC_8x8_FLOAT,
|
TextureFormat_ASTC_8x8_FLOAT,
|
||||||
ASTC_10x5_FLOAT,
|
TextureFormat_ASTC_10x5_FLOAT,
|
||||||
ASTC_10x6_FLOAT,
|
TextureFormat_ASTC_10x6_FLOAT,
|
||||||
ASTC_10x8_FLOAT,
|
TextureFormat_ASTC_10x8_FLOAT,
|
||||||
ASTC_10x10_FLOAT,
|
TextureFormat_ASTC_10x10_FLOAT,
|
||||||
ASTC_12x10_FLOAT,
|
TextureFormat_ASTC_12x10_FLOAT,
|
||||||
ASTC_12x12_FLOAT,
|
TextureFormat_ASTC_12x12_FLOAT,
|
||||||
|
|
||||||
Count
|
TextureFormat_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct TextureUsageFlag : uint8
|
typedef uint8 TextureUsageFlag;
|
||||||
|
enum TextureUsageFlag_Enum
|
||||||
{
|
{
|
||||||
None = 0,
|
TextureUsageFlag_None = 0,
|
||||||
Sampler = 1 << 0, // Textures supports sampling
|
TextureUsageFlag_Sampler = 1 << 0,
|
||||||
ColorTarget = 1 << 1, // Texture is color render target
|
TextureUsageFlag_ColorTarget = 1 << 1,
|
||||||
DepthStencilTarget = 1 << 2, // Texture is depth stencil target
|
TextureUsageFlag_DepthStencilTarget = 1 << 2,
|
||||||
GraphicsStorageRead = 1 << 3, // Support Storage read at graphics stage
|
TextureUsageFlag_GraphicsStorageRead = 1 << 3,
|
||||||
ComputeStorageRead = 1 << 4, // Support Storage read at compute stage
|
TextureUsageFlag_ComputeStorageRead = 1 << 4,
|
||||||
ComputeStorageWrite = 1 << 5, // Support Storage Write at compute stage
|
TextureUsageFlag_ComputeStorageWrite = 1 << 5,
|
||||||
ComputeStorageSimultaneousReadWrite =
|
TextureUsageFlag_ComputeStorageSimultaneousReadWrite = 1 << 6,
|
||||||
1 << 6, // Supports reads and writes in the same compute shader. Not equivalent to ComputeStorageRead | ComputeStorageWrite
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct TextureType : uint8
|
typedef uint8 TextureType;
|
||||||
|
enum TextureType_Enum
|
||||||
{
|
{
|
||||||
Texture_2D,
|
TextureType_2D,
|
||||||
Texture_2DArray,
|
TextureType_2DArray,
|
||||||
Texture_3D,
|
TextureType_3D,
|
||||||
Texture_3DArray,
|
TextureType_3DArray,
|
||||||
Texture_Cube,
|
TextureType_Cube,
|
||||||
Texture_CubeArray,
|
TextureType_CubeArray,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct TextureSampleCount : uint8
|
typedef uint8 TextureSampleCount;
|
||||||
|
enum TextureSampleCount_Enum
|
||||||
{
|
{
|
||||||
One,
|
TextureSampleCount_One,
|
||||||
Two,
|
TextureSampleCount_Two,
|
||||||
Four,
|
TextureSampleCount_Four,
|
||||||
Eight,
|
TextureSampleCount_Eight,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create Information structs
|
// Create Information structs
|
||||||
|
typedef struct TextureCreateInfo TextureCreateInfo;
|
||||||
struct TextureCreateInfo
|
struct TextureCreateInfo
|
||||||
{
|
{
|
||||||
TextureType Type;
|
TextureType Type;
|
||||||
@@ -177,4 +183,4 @@ struct TextureCreateInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Opaque Type
|
// Opaque Type
|
||||||
struct Texture;
|
typedef struct Texture Texture;
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
typedef struct Vertex Vertex;
|
||||||
struct Vertex
|
struct Vertex
|
||||||
{
|
{
|
||||||
float Position[3];
|
float Position[3];
|
||||||
@@ -7,4 +10,4 @@ struct Vertex
|
|||||||
float Color[4];
|
float Color[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
using Index = uint16;
|
typedef uint16 Index;
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#define JULIET_API
|
#define JULIET_API
|
||||||
# endif
|
# endif
|
||||||
# else
|
# else
|
||||||
# define JULIET_API (void) // Only Win32 is supported for now
|
# define JULIET_API
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
#include <Core/Application/ApplicationManager.h>
|
|
||||||
#include <Core/JulietInit.h>
|
|
||||||
|
|
||||||
#include <Engine/Engine.h>
|
|
||||||
|
|
||||||
void StartApplication(IApplication& app, JulietInit_Flags flags)
|
|
||||||
{
|
|
||||||
InitializeEngine(flags);
|
|
||||||
|
|
||||||
LoadApplication(app);
|
|
||||||
|
|
||||||
RunEngine();
|
|
||||||
|
|
||||||
UnloadApplication();
|
|
||||||
|
|
||||||
ShutdownEngine();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <Core/HAL/Win32.h>
|
||||||
|
#include <Core/Logging/LogManager.h>
|
||||||
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Core/Memory/Allocator.h>
|
||||||
|
|
||||||
|
#include <intrin.h>
|
||||||
|
|
||||||
|
void JulietAssert(const char* expression, const char* message, const char* file, const char* function, uint32 line,
|
||||||
|
long handle_result)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Error, LogCategory_Core, "--- ASSERTION FAILED ---");
|
||||||
|
Log(LogLevel_Error, LogCategory_Core, "Expression: %s", expression);
|
||||||
|
Log(LogLevel_Error, LogCategory_Core, "Message: %s", message);
|
||||||
|
Log(LogLevel_Error, LogCategory_Core, "Location: %s(%u): %s", file, line, function);
|
||||||
|
|
||||||
|
if (handle_result < 0)
|
||||||
|
{
|
||||||
|
char msg_buf[512] = { 0 };
|
||||||
|
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)handle_result,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), msg_buf, (DWORD)(sizeof(msg_buf) - 1), NULL);
|
||||||
|
Log(LogLevel_Error, LogCategory_Graphics, "HRESULT: 0x%08X (%s)", (uint32)handle_result, msg_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(LogLevel_Error, LogCategory_Core, "-------------------------");
|
||||||
|
|
||||||
|
JULIET_PLATFORM_BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeByteBuffer(ByteBuffer* buffer)
|
||||||
|
{
|
||||||
|
Assert(buffer != NULL);
|
||||||
|
if (buffer->Data != NULL)
|
||||||
|
{
|
||||||
|
FreeMemory(buffer->Data);
|
||||||
|
}
|
||||||
|
buffer->Data = NULL;
|
||||||
|
buffer->Size = 0;
|
||||||
|
}
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#include <Core/Logging/LogManager.h>
|
|
||||||
#include <Core/Logging/LogTypes.h>
|
|
||||||
#include <Core/Memory/Allocator.h>
|
|
||||||
|
|
||||||
#include <comdef.h> // For _com_error to decode HRESULTs
|
|
||||||
#include <intrin.h> // For __debugbreak
|
|
||||||
|
|
||||||
void JulietAssert(const char* expression, const char* message, std::source_location location, long handleResult)
|
|
||||||
{
|
|
||||||
Log(LogLevel::Error, LogCategory::Core, "--- ASSERTION FAILED ---");
|
|
||||||
Log(LogLevel::Error, LogCategory::Core, "Expression: %s", expression);
|
|
||||||
Log(LogLevel::Error, LogCategory::Core, "Message: %s", message);
|
|
||||||
Log(LogLevel::Error, LogCategory::Core, "Location: %s(%u): %s", location.file_name(), location.line(),
|
|
||||||
location.function_name());
|
|
||||||
|
|
||||||
if (handleResult < 0)
|
|
||||||
{
|
|
||||||
_com_error err(handleResult);
|
|
||||||
// Using %ls because ErrorMessage() returns a wide string (wchar_t*)
|
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "HRESULT: 0x%08X (%ls)", handleResult, err.ErrorMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
Log(LogLevel::Error, LogCategory::Core, "-------------------------");
|
|
||||||
|
|
||||||
JULIET_PLATFORM_BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Free(ByteBuffer& buffer)
|
|
||||||
{
|
|
||||||
if (buffer.Data)
|
|
||||||
{
|
|
||||||
Free(buffer.Data);
|
|
||||||
}
|
|
||||||
buffer = {};
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,699 @@
|
|||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <Core/Common/String.h>
|
||||||
|
#include <Core/Logging/LogManager.h>
|
||||||
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
#include <Core/Memory/Utils.h>
|
||||||
|
|
||||||
|
#define kUnknown_UNICODE 0xFFFD
|
||||||
|
|
||||||
|
typedef struct EncodingEntry EncodingEntry;
|
||||||
|
struct EncodingEntry
|
||||||
|
{
|
||||||
|
String Name;
|
||||||
|
StringEncoding Format;
|
||||||
|
};
|
||||||
|
|
||||||
|
global const EncodingEntry g_encodings[] = {
|
||||||
|
{ ConstStringInit("ASCII"), StringEncoding_ASCII },
|
||||||
|
{ ConstStringInit("US-ASCII"), StringEncoding_ASCII },
|
||||||
|
{ ConstStringInit("8859-1"), StringEncoding_LATIN1 },
|
||||||
|
{ ConstStringInit("ISO-8859-1"), StringEncoding_LATIN1 },
|
||||||
|
#if defined(JULIET_WIN32)
|
||||||
|
{ ConstStringInit("WCHAR_T"), StringEncoding_UTF16 },
|
||||||
|
#else
|
||||||
|
{ ConstStringInit("WCHAR_T"), StringEncoding_UCS4 },
|
||||||
|
#endif
|
||||||
|
{ ConstStringInit("UTF8"), StringEncoding_UTF8 },
|
||||||
|
{ ConstStringInit("UTF-8"), StringEncoding_UTF8 },
|
||||||
|
{ ConstStringInit("UTF16"), StringEncoding_UTF16 },
|
||||||
|
{ ConstStringInit("UTF-16"), StringEncoding_UTF16 },
|
||||||
|
{ ConstStringInit("UTF32"), StringEncoding_UTF32 },
|
||||||
|
{ ConstStringInit("UTF-32"), StringEncoding_UTF32 },
|
||||||
|
{ ConstStringInit("UCS2"), StringEncoding_UCS2 },
|
||||||
|
{ ConstStringInit("UCS-2"), StringEncoding_UCS2 },
|
||||||
|
{ ConstStringInit("UCS-2-INTERNAL"), StringEncoding_UCS2 },
|
||||||
|
{ ConstStringInit("UCS4"), StringEncoding_UCS4 },
|
||||||
|
{ ConstStringInit("UCS-4"), StringEncoding_UCS4 },
|
||||||
|
{ ConstStringInit("UCS-4-INTERNAL"), StringEncoding_UCS4 },
|
||||||
|
};
|
||||||
|
|
||||||
|
internal int8 CaseFoldUnicode(uint32 from, uint32* to)
|
||||||
|
{
|
||||||
|
Assert(to != NULL);
|
||||||
|
if (from < 128 && (from >= 'A') && (from <= 'Z'))
|
||||||
|
{
|
||||||
|
*to = 'a' + (from - 'A');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*to = from;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 StepUTF8(String* inStr)
|
||||||
|
{
|
||||||
|
Assert(inStr != NULL);
|
||||||
|
|
||||||
|
uint32 codepoint = 0;
|
||||||
|
|
||||||
|
if (inStr->Size > 0)
|
||||||
|
{
|
||||||
|
const uint8* str = (const uint8*)CStr(*inStr);
|
||||||
|
const uint32 octet = *str;
|
||||||
|
bool8 isOverlong = false;
|
||||||
|
bool8 isInvalid = false;
|
||||||
|
bool8 isUTF16Surrogate = false;
|
||||||
|
bool8 decoded = false;
|
||||||
|
|
||||||
|
if (octet == 0)
|
||||||
|
{
|
||||||
|
codepoint = 0;
|
||||||
|
decoded = true;
|
||||||
|
}
|
||||||
|
else if ((octet & 0x80u) == 0x0u)
|
||||||
|
{
|
||||||
|
inStr->Str += 1;
|
||||||
|
inStr->Size -= 1;
|
||||||
|
codepoint = octet;
|
||||||
|
decoded = true;
|
||||||
|
}
|
||||||
|
else if ((octet & 0xE0u) == 0xC0u)
|
||||||
|
{
|
||||||
|
const uint8 secondByte = str[1];
|
||||||
|
if ((secondByte & 0xC0u) == 0x80u)
|
||||||
|
{
|
||||||
|
const uint32 result = ((octet & 0x1Fu) << 6) | (secondByte & 0x3Fu);
|
||||||
|
if (result >= 0x80u)
|
||||||
|
{
|
||||||
|
inStr->Str += 2;
|
||||||
|
inStr->Size -= 1;
|
||||||
|
codepoint = result;
|
||||||
|
decoded = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isOverlong = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isInvalid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((octet & 0xF0u) == 0xE0u)
|
||||||
|
{
|
||||||
|
const uint8 secondByte = str[1];
|
||||||
|
const uint8 thirdByte = str[2];
|
||||||
|
if (((secondByte & 0xC0u) == 0x80u) && ((thirdByte & 0xC0u) == 0x80u))
|
||||||
|
{
|
||||||
|
const uint32 secondOctet = (uint32)(secondByte & 0x3Fu) << 6;
|
||||||
|
const uint32 thirdOctet = (uint32)(thirdByte & 0x3Fu);
|
||||||
|
const uint32 result = ((octet & 0x0Fu) << 12) | secondOctet | thirdOctet;
|
||||||
|
if (result >= 0x0800u)
|
||||||
|
{
|
||||||
|
if ((result < 0xD800u) || (result > 0xDFFFu))
|
||||||
|
{
|
||||||
|
inStr->Str += 3;
|
||||||
|
inStr->Size -= 1;
|
||||||
|
codepoint = result;
|
||||||
|
decoded = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isUTF16Surrogate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isOverlong = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isInvalid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((octet & 0xF8u) == 0xF0u)
|
||||||
|
{
|
||||||
|
const uint8 secondByte = str[1];
|
||||||
|
const uint8 thirdByte = str[2];
|
||||||
|
const uint8 fourthByte = str[3];
|
||||||
|
if (((secondByte & 0xC0u) == 0x80u) && ((thirdByte & 0xC0u) == 0x80u) && ((fourthByte & 0xC0u) == 0x80u))
|
||||||
|
{
|
||||||
|
const uint32 secondOctet = (uint32)(secondByte & 0x1Fu) << 12;
|
||||||
|
const uint32 thirdOctet = (uint32)(thirdByte & 0x3Fu) << 6;
|
||||||
|
const uint32 fourthOctet = (uint32)(fourthByte & 0x3Fu);
|
||||||
|
const uint32 result = ((octet & 0x07u) << 18) | secondOctet | thirdOctet | fourthOctet;
|
||||||
|
if (result >= 0x10000u)
|
||||||
|
{
|
||||||
|
inStr->Str += 4;
|
||||||
|
inStr->Size -= 1;
|
||||||
|
codepoint = result;
|
||||||
|
decoded = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isOverlong = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isInvalid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!decoded)
|
||||||
|
{
|
||||||
|
LogError(LogCategory_Core,
|
||||||
|
"StepUTF8: Non supported codepoint. IsOverlong: %s. IsInvalid %s. IsUTF16Surrogate %s",
|
||||||
|
isOverlong ? "true" : "false", isInvalid ? "true" : "false", isUTF16Surrogate ? "true" : "false");
|
||||||
|
inStr->Str += 1;
|
||||||
|
codepoint = kInvalidUTF8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return codepoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
String FindString(String haystack, String needle)
|
||||||
|
{
|
||||||
|
String result = { 0 };
|
||||||
|
if (!IsValidString(needle))
|
||||||
|
{
|
||||||
|
result = haystack;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (; IsValidString(haystack); StepUTF8(&haystack))
|
||||||
|
{
|
||||||
|
String tempHaystack = haystack;
|
||||||
|
String testNeedle = needle;
|
||||||
|
|
||||||
|
while (IsValidString(tempHaystack) && IsValidString(testNeedle))
|
||||||
|
{
|
||||||
|
uint32 codepointHaystack = StepUTF8(&tempHaystack);
|
||||||
|
uint32 codepointNeedle = StepUTF8(&testNeedle);
|
||||||
|
if (codepointHaystack != codepointNeedle)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsValidString(testNeedle))
|
||||||
|
{
|
||||||
|
result = haystack;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8 StringCompareCaseInsensitive(String str1, String str2)
|
||||||
|
{
|
||||||
|
int8 result = 0;
|
||||||
|
uint32 left = 0;
|
||||||
|
uint32 right = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
uint32 leftFolded[3];
|
||||||
|
int8 num_folded = CaseFoldUnicode(StepUTF8(&str1), leftFolded);
|
||||||
|
Assert(num_folded == 1);
|
||||||
|
(void)num_folded;
|
||||||
|
left = leftFolded[0];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
uint32 rightFolded[3];
|
||||||
|
int8 num_folded = CaseFoldUnicode(StepUTF8(&str2), rightFolded);
|
||||||
|
Assert(num_folded == 1);
|
||||||
|
(void)num_folded;
|
||||||
|
right = rightFolded[0];
|
||||||
|
}
|
||||||
|
if (left < right)
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (left > right)
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (left == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer* dst, bool8 nullTerminate)
|
||||||
|
{
|
||||||
|
Assert(IsValidString(src));
|
||||||
|
Assert(dst != NULL);
|
||||||
|
|
||||||
|
bool8 result = true;
|
||||||
|
const char* srcStr = src.Str;
|
||||||
|
char* dstStr = dst->Str;
|
||||||
|
size_t remainingCapacity = dst->Capacity;
|
||||||
|
|
||||||
|
uint32 character = 0;
|
||||||
|
while (src.Size > 0 && result)
|
||||||
|
{
|
||||||
|
switch (from)
|
||||||
|
{
|
||||||
|
case StringEncoding_UTF8:
|
||||||
|
{
|
||||||
|
const uint8* p = (const uint8*)srcStr;
|
||||||
|
size_t left = 0;
|
||||||
|
bool8 overlong = false;
|
||||||
|
if (p[0] >= 0xF0u)
|
||||||
|
{
|
||||||
|
if ((p[0] & 0xF8u) != 0xF0u)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p[0] == 0xF0u && src.Size > 1 && (p[1] & 0xF0u) == 0x80u)
|
||||||
|
{
|
||||||
|
overlong = true;
|
||||||
|
}
|
||||||
|
character = (uint32)(p[0] & 0x07u);
|
||||||
|
left = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p[0] >= 0xE0u)
|
||||||
|
{
|
||||||
|
if ((p[0] & 0xF0u) != 0xE0u)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p[0] == 0xE0u && src.Size > 1 && (p[1] & 0xE0u) == 0x80u)
|
||||||
|
{
|
||||||
|
overlong = true;
|
||||||
|
}
|
||||||
|
character = (uint32)(p[0] & 0x0Fu);
|
||||||
|
left = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p[0] >= 0xC0u)
|
||||||
|
{
|
||||||
|
if ((p[0] & 0xE0u) != 0xC0u)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((p[0] & 0xDEu) == 0xC0u)
|
||||||
|
{
|
||||||
|
overlong = true;
|
||||||
|
}
|
||||||
|
character = (uint32)(p[0] & 0x1Fu);
|
||||||
|
left = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p[0] & 0x80u)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character = (uint32)(p[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++srcStr;
|
||||||
|
--src.Size;
|
||||||
|
if (src.Size < left)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Error, LogCategory_Core,
|
||||||
|
"ConvertString: Failed to convert string. Incomplete input sequence");
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (left--)
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
if ((p[0] & 0xC0u) != 0x80u)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
character <<= 6;
|
||||||
|
character |= (p[0] & 0x3Fu);
|
||||||
|
++srcStr;
|
||||||
|
--src.Size;
|
||||||
|
}
|
||||||
|
if (overlong)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
if ((character >= 0xD800u && character <= 0xDFFFu) ||
|
||||||
|
(character == 0xFFFEu || character == 0xFFFFu) || character > 0x10FFFFu)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StringEncoding_Unknown:
|
||||||
|
{
|
||||||
|
Assert(false, "ConvertString: Invalid Source Format: Unknown");
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Assert(false, "ConvertString: Unsupported Source Format");
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
switch (to)
|
||||||
|
{
|
||||||
|
case StringEncoding_UTF16:
|
||||||
|
{
|
||||||
|
uint8* p = (uint8*)dstStr;
|
||||||
|
if (character > 0x10FFFFu)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
if (character < 0x10000u)
|
||||||
|
{
|
||||||
|
if (remainingCapacity < 2)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Error, LogCategory_Core,
|
||||||
|
"ConvertString: Destination buffer too short to fit UTF16");
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p[1] = (uint8)(character >> 8);
|
||||||
|
p[0] = (uint8)(character);
|
||||||
|
|
||||||
|
dstStr += 2;
|
||||||
|
dst->Size += 1;
|
||||||
|
remainingCapacity -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (remainingCapacity < 4)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Error, LogCategory_Core,
|
||||||
|
"ConvertString: Destination buffer too short to fit UTF16");
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character = character - 0x10000u;
|
||||||
|
uint16 word1 = 0xD800u | (uint16)((character >> 10) & 0x3FFu);
|
||||||
|
uint16 word2 = 0xDC00u | (uint16)(character & 0x3FFu);
|
||||||
|
p[1] = (uint8)(word1 >> 8);
|
||||||
|
p[0] = (uint8)(word1);
|
||||||
|
p[3] = (uint8)(word2 >> 8);
|
||||||
|
p[2] = (uint8)(word2);
|
||||||
|
|
||||||
|
dstStr += 4;
|
||||||
|
dst->Size += 1;
|
||||||
|
remainingCapacity -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StringEncoding_Unknown:
|
||||||
|
{
|
||||||
|
Assert(false, "ConvertString: Invalid Source Format: Unknown");
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Assert(false, "ConvertString: Unsupported Destination Format");
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result && nullTerminate)
|
||||||
|
{
|
||||||
|
switch (to)
|
||||||
|
{
|
||||||
|
case StringEncoding_UTF16:
|
||||||
|
{
|
||||||
|
if (remainingCapacity < 2)
|
||||||
|
{
|
||||||
|
Log(LogLevel_Error, LogCategory_Core,
|
||||||
|
"ConvertString: Destination buffer too short to add null terminator into UTF16 buffer");
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstStr[0] = 0;
|
||||||
|
dstStr[1] = 0;
|
||||||
|
remainingCapacity -= 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StringEncoding_Unknown:
|
||||||
|
{
|
||||||
|
Assert(false, "ConvertString: Invalid Source Format: Unknown");
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Assert(false, "ConvertString: Unsupported Destination Format");
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool8 ConvertStringByName(String from, String to, String src, StringBuffer* dst, bool8 nullTerminate)
|
||||||
|
{
|
||||||
|
Assert(IsValidString(from));
|
||||||
|
Assert(IsValidString(to));
|
||||||
|
Assert(dst != NULL);
|
||||||
|
|
||||||
|
bool8 result = false;
|
||||||
|
StringEncoding sourceFormat = StringEncoding_Unknown;
|
||||||
|
StringEncoding destFormat = StringEncoding_Unknown;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ArraySize(g_encodings); ++i)
|
||||||
|
{
|
||||||
|
if (StringCompareCaseInsensitive(from, g_encodings[i].Name) == 0)
|
||||||
|
{
|
||||||
|
sourceFormat = g_encodings[i].Format;
|
||||||
|
if (destFormat != StringEncoding_Unknown)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StringCompareCaseInsensitive(to, g_encodings[i].Name) == 0)
|
||||||
|
{
|
||||||
|
destFormat = g_encodings[i].Format;
|
||||||
|
if (sourceFormat != StringEncoding_Unknown)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceFormat != StringEncoding_Unknown && destFormat != StringEncoding_Unknown)
|
||||||
|
{
|
||||||
|
result = ConvertString(sourceFormat, destFormat, src, dst, nullTerminate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
global const uint8 g_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, size_t max)
|
||||||
|
{
|
||||||
|
UnicodeDecode result = { 1, uint32Max };
|
||||||
|
uint8 byte = str[0];
|
||||||
|
uint8 byte_class = g_utf8_class[byte >> 3];
|
||||||
|
switch (byte_class)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
result.Codepoint = byte;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if (1 < max)
|
||||||
|
{
|
||||||
|
uint8 next_byte = str[1];
|
||||||
|
if (g_utf8_class[next_byte >> 3] == 0)
|
||||||
|
{
|
||||||
|
result.Codepoint = (byte & bitmask5) << 6;
|
||||||
|
result.Codepoint |= (next_byte & bitmask6);
|
||||||
|
result.Increment = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if (2 < max)
|
||||||
|
{
|
||||||
|
uint8 next_byte[2] = { str[1], str[2] };
|
||||||
|
if (g_utf8_class[next_byte[0] >> 3] == 0 && g_utf8_class[next_byte[1] >> 3] == 0)
|
||||||
|
{
|
||||||
|
result.Codepoint = (byte & bitmask4) << 12;
|
||||||
|
result.Codepoint |= ((next_byte[0] & bitmask6) << 6);
|
||||||
|
result.Codepoint |= (next_byte[1] & bitmask6);
|
||||||
|
result.Increment = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
if (3 < max)
|
||||||
|
{
|
||||||
|
uint8 next_byte[3] = { str[1], str[2], str[3] };
|
||||||
|
if (g_utf8_class[next_byte[0] >> 3] == 0 && g_utf8_class[next_byte[1] >> 3] == 0 &&
|
||||||
|
g_utf8_class[next_byte[2] >> 3] == 0)
|
||||||
|
{
|
||||||
|
result.Codepoint = (byte & bitmask3) << 18;
|
||||||
|
result.Codepoint |= ((next_byte[0] & bitmask6) << 12);
|
||||||
|
result.Codepoint |= ((next_byte[1] & bitmask6) << 6);
|
||||||
|
result.Codepoint |= (next_byte[2] & bitmask6);
|
||||||
|
result.Increment = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint32 utf16_encode(uint16* str, uint32 codepoint)
|
||||||
|
{
|
||||||
|
Assert(str != NULL);
|
||||||
|
uint32 increment = 1;
|
||||||
|
if (codepoint == uint32Max)
|
||||||
|
{
|
||||||
|
str[0] = '?';
|
||||||
|
}
|
||||||
|
else if (codepoint < 0x10000u)
|
||||||
|
{
|
||||||
|
str[0] = (uint16)codepoint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32 var = codepoint - 0x10000u;
|
||||||
|
str[0] = safe_cast_uint16(0xD800u + (var >> 10));
|
||||||
|
str[1] = safe_cast_uint16(0xDC00u + (var & bitmask10));
|
||||||
|
increment = 2;
|
||||||
|
}
|
||||||
|
return increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
String StringCopy(Arena* arena, String str)
|
||||||
|
{
|
||||||
|
Assert(arena != NULL);
|
||||||
|
String result = { 0 };
|
||||||
|
result.Size = str.Size;
|
||||||
|
result.Str = (char*)ArenaPush(arena, str.Size + 1, AlignOf(char), true JULIET_DEBUG_PARAM("String"));
|
||||||
|
if (str.Size > 0 && str.Str != NULL)
|
||||||
|
{
|
||||||
|
MemCopy(result.Str, str.Str, str.Size);
|
||||||
|
}
|
||||||
|
result.Str[result.Size] = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String16 str16_from_8(Arena* arena, String8 in)
|
||||||
|
{
|
||||||
|
Assert(arena != NULL);
|
||||||
|
String16 result = { 0 };
|
||||||
|
if (in.Size > 0)
|
||||||
|
{
|
||||||
|
size_t neededCapacity = in.Size * 2;
|
||||||
|
uint16* str = ArenaPushArrayNoZero(arena, uint16, neededCapacity + 1);
|
||||||
|
uint8* inStr = (uint8*)in.Str;
|
||||||
|
uint8* inStrEnd = inStr + in.Size;
|
||||||
|
|
||||||
|
UnicodeDecode consumed = { 0 };
|
||||||
|
uint64 size = 0;
|
||||||
|
for (; inStr < inStrEnd; inStr += consumed.Increment)
|
||||||
|
{
|
||||||
|
consumed = utf8_decode(inStr, (size_t)(inStrEnd - inStr));
|
||||||
|
size += utf16_encode(str + size, consumed.Codepoint);
|
||||||
|
}
|
||||||
|
str[size] = 0;
|
||||||
|
ArenaPop(arena, (neededCapacity - size) * 2);
|
||||||
|
result.Str = str;
|
||||||
|
result.Size = size;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String trim_whitespace(String str)
|
||||||
|
{
|
||||||
|
while (str.Size > 0 && (*str.Str == ' ' || *str.Str == '\t' || *str.Str == '\r' || *str.Str == '\n'))
|
||||||
|
{
|
||||||
|
str.Str++;
|
||||||
|
str.Size--;
|
||||||
|
}
|
||||||
|
while (str.Size > 0 && (str.Str[str.Size - 1] == ' ' || str.Str[str.Size - 1] == '\t' ||
|
||||||
|
str.Str[str.Size - 1] == '\r' || str.Str[str.Size - 1] == '\n'))
|
||||||
|
{
|
||||||
|
str.Size--;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
String StringFormatV(Arena* arena, const char* formatStr, va_list args)
|
||||||
|
{
|
||||||
|
Assert(arena != NULL);
|
||||||
|
Assert(formatStr != NULL);
|
||||||
|
|
||||||
|
va_list args_copy;
|
||||||
|
va_copy(args_copy, args);
|
||||||
|
int needed = vsnprintf(NULL, 0, formatStr, args_copy);
|
||||||
|
va_end(args_copy);
|
||||||
|
|
||||||
|
String result = { 0 };
|
||||||
|
if (needed >= 0)
|
||||||
|
{
|
||||||
|
result.Size = (size_t)needed;
|
||||||
|
result.Str = (char*)ArenaPush(arena, result.Size + 1, AlignOf(char), true JULIET_DEBUG_PARAM("StringFormat"));
|
||||||
|
vsnprintf(result.Str, result.Size + 1, formatStr, args);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String StringFormat(Arena* arena, const char* formatStr, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, formatStr);
|
||||||
|
String result = StringFormatV(arena, formatStr, args);
|
||||||
|
va_end(args);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -1,641 +0,0 @@
|
|||||||
#include <Core/Common/CoreUtils.h>
|
|
||||||
#include <Core/Common/String.h>
|
|
||||||
#include <Core/Logging/LogManager.h>
|
|
||||||
#include <Core/Logging/LogTypes.h>
|
|
||||||
#include <Core/Memory/MemoryArena.h>
|
|
||||||
#include <Core/Memory/Utils.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
constexpr int32 kUnknown_UNICODE = 0xFFFD;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
String Name;
|
|
||||||
StringEncoding Format;
|
|
||||||
} Encodings[] = {
|
|
||||||
/* *INDENT-OFF* */ // clang-format off
|
|
||||||
{ ConstString("ASCII"), StringEncoding::ASCII },
|
|
||||||
{ ConstString("US-ASCII"), StringEncoding::ASCII },
|
|
||||||
{ ConstString("8859-1"), StringEncoding::LATIN1 },
|
|
||||||
{ ConstString("ISO-8859-1"), StringEncoding::LATIN1 },
|
|
||||||
#if defined(JULIET_WIN32)
|
|
||||||
{ ConstString("WCHAR_T"), StringEncoding::UTF16 },
|
|
||||||
#else
|
|
||||||
{ ConstString("WCHAR_T"), StringEncoding::UCS4 },
|
|
||||||
#endif
|
|
||||||
{ ConstString("UTF8"), StringEncoding::UTF8 },
|
|
||||||
{ ConstString("UTF-8"), StringEncoding::UTF8 },
|
|
||||||
{ ConstString("UTF16"), StringEncoding::UTF16 },
|
|
||||||
{ ConstString("UTF-16"), StringEncoding::UTF16 },
|
|
||||||
{ ConstString("UTF32"), StringEncoding::UTF32 },
|
|
||||||
{ ConstString("UTF-32"), StringEncoding::UTF32 },
|
|
||||||
{ ConstString("UCS2"), StringEncoding::UCS2 },
|
|
||||||
{ ConstString("UCS-2"), StringEncoding::UCS2 },
|
|
||||||
{ ConstString("UCS-2-INTERNAL"), StringEncoding::UCS2 },
|
|
||||||
{ ConstString("UCS4"), StringEncoding::UCS4 },
|
|
||||||
{ ConstString("UCS-4"), StringEncoding::UCS4 },
|
|
||||||
{ ConstString("UCS-4-INTERNAL"), StringEncoding::UCS4 },
|
|
||||||
/* *INDENT-ON* */ // clang-format on
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns the number of codepoint case folded (lowercase equivalent in the language)
|
|
||||||
// Takes an UTF-8 codepoint (uint32) and codefold it to up to 3 uint32
|
|
||||||
// TODO Supports more than low ASCI :)
|
|
||||||
int8 CaseFoldUnicode(uint32 from, uint32* to)
|
|
||||||
{
|
|
||||||
if (from < 128)
|
|
||||||
{
|
|
||||||
// low-ASCII, easy!
|
|
||||||
if ((from >= 'A') && (from <= 'Z'))
|
|
||||||
{
|
|
||||||
*to = 'a' + (from - 'A');
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*to = from;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// TODO: remove this as we convert to simple unicode decode / encode at the bottom
|
|
||||||
uint32 StepUTF8(String& inStr)
|
|
||||||
{
|
|
||||||
// From rfc3629, the UTF-8 spec:
|
|
||||||
// https://www.ietf.org/rfc/rfc3629.txt
|
|
||||||
//
|
|
||||||
// Char. number range | UTF-8 octet sequence
|
|
||||||
// (hexadecimal) | (binary)
|
|
||||||
// --------------------+---------------------------------------------
|
|
||||||
// 0000 0000-0000 007F | 0xxxxxxx
|
|
||||||
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
|
||||||
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
|
||||||
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
||||||
//
|
|
||||||
// The function checks character validity and overlong (using too many bytes to encode the character) and return invalid utf8 char if detected.
|
|
||||||
|
|
||||||
// If string is empty then it's done.
|
|
||||||
if (inStr.Size == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto str = reinterpret_cast<const uint8*>(CStr(inStr));
|
|
||||||
const uint32 octet = *str;
|
|
||||||
bool isOverlong = false;
|
|
||||||
bool isInvalid = false;
|
|
||||||
bool isUTF16Surrogate = false;
|
|
||||||
if (octet == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ((octet & 0x80) == 0x0) // One byte code point: 0xxxxxxx
|
|
||||||
{
|
|
||||||
inStr.Str += 1;
|
|
||||||
inStr.Size -= 1;
|
|
||||||
return octet;
|
|
||||||
}
|
|
||||||
else if ((octet & 0xE0) == 0xC0) // Two bytes code point: 110xxxxx 10xxxxxx
|
|
||||||
{
|
|
||||||
const uint8 secondByte = str[1];
|
|
||||||
if ((secondByte & 0xC0) == 0x80) // Make sure the trailing byte is correct
|
|
||||||
{
|
|
||||||
const uint32 result = ((octet & 0x1F) << 6) | (secondByte & 0x3F);
|
|
||||||
if (result >= 0x80) // If the result is smaller than 0x80 its an overlong!
|
|
||||||
{
|
|
||||||
inStr.Str += 2;
|
|
||||||
inStr.Size -= 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isOverlong = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isInvalid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (((octet & 0xF0) == 0xE0)) // Three bytes code point: 1110xxxx 10xxxxxx 10xxxxxx
|
|
||||||
{
|
|
||||||
const uint8 secondByte = str[1];
|
|
||||||
const uint8 thirdByte = str[2];
|
|
||||||
if (((secondByte & 0xC0) == 0x80) && ((thirdByte & 0xC0) == 0x80)) // Make sure the trailing bytes are correct
|
|
||||||
{
|
|
||||||
const uint32 secondOctet = static_cast<uint32>(secondByte & 0x3F) << 6;
|
|
||||||
const uint32 thirdOctet = static_cast<uint32>(thirdByte & 0x3F);
|
|
||||||
const uint32 result = ((octet & 0x0F) << 12) | secondOctet | thirdOctet;
|
|
||||||
if (result >= 0x0800) // if the result is smaller its an overlong.
|
|
||||||
{
|
|
||||||
if ((result < 0xD800) || (result > 0xDFFF)) // If out of range its an UTF-16 surrogate
|
|
||||||
{
|
|
||||||
inStr.Str += 3;
|
|
||||||
inStr.Size -= 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isUTF16Surrogate = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isOverlong = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isInvalid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (((octet & 0xF8) == 0xF0))
|
|
||||||
{ // Four bytes code point: 11110xxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
||||||
const uint8 secondByte = str[1];
|
|
||||||
const uint8 thirdByte = str[2];
|
|
||||||
const uint8 fourthByte = str[3];
|
|
||||||
if (((secondByte & 0xC0) == 0x80) && ((thirdByte & 0xC0) == 0x80) &&
|
|
||||||
((fourthByte & 0xC0) == 0x80)) // // Make sure the trailing bytes are correct
|
|
||||||
{
|
|
||||||
const uint32 secondOctet = static_cast<uint32>(secondByte & 0x1F) << 12;
|
|
||||||
const uint32 thirdOctet = static_cast<uint32>(thirdByte & 0x3F) << 6;
|
|
||||||
const uint32 fourthOctet = static_cast<uint32>(fourthByte & 0x3F);
|
|
||||||
const uint32 result = ((octet & 0x07) << 18) | secondOctet | thirdOctet | fourthOctet;
|
|
||||||
if (result >= 0x10000) // If smaller its an overlong
|
|
||||||
{
|
|
||||||
inStr.Str += 4;
|
|
||||||
inStr.Size -= 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isOverlong = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isInvalid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogError(LogCategory::Core, "StepUTF8: Non supported codepoint. IsOverlong: %s. IsInvalid %s. IsUTF16Surrogate %s",
|
|
||||||
isOverlong ? "true" : "false", isInvalid ? "true" : "false", isUTF16Surrogate ? "true" : "false");
|
|
||||||
inStr.Str += 1;
|
|
||||||
return kInvalidUTF8;
|
|
||||||
}
|
|
||||||
|
|
||||||
String FindString(String haystack, String needle)
|
|
||||||
{
|
|
||||||
if (!IsValid(needle))
|
|
||||||
{
|
|
||||||
return haystack;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; IsValid(haystack); StepUTF8(haystack))
|
|
||||||
{
|
|
||||||
String tempHaystack = haystack;
|
|
||||||
String testNeedle = needle;
|
|
||||||
|
|
||||||
while (IsValid(tempHaystack) && IsValid(testNeedle))
|
|
||||||
{
|
|
||||||
uint32 codepointHaystack = StepUTF8(tempHaystack);
|
|
||||||
uint32 codepointNeedle = StepUTF8(testNeedle);
|
|
||||||
if (codepointHaystack != codepointNeedle)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValid(testNeedle))
|
|
||||||
{
|
|
||||||
return haystack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
int8 StringCompareCaseInsensitive(String str1, String str2)
|
|
||||||
{
|
|
||||||
// TODO: Support UTF8. For now ASCII only.
|
|
||||||
uint32 left = 0;
|
|
||||||
uint32 right = 0;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
uint32 leftFolded[3];
|
|
||||||
[[maybe_unused]] int8 num_folded = CaseFoldUnicode(StepUTF8(str1), leftFolded);
|
|
||||||
Assert(num_folded == 1); // Only one uint32 codepoint supported for now (low ascii)
|
|
||||||
left = leftFolded[0];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
uint32 rightFolded[3];
|
|
||||||
[[maybe_unused]] int8 num_folded = CaseFoldUnicode(StepUTF8(str2), rightFolded);
|
|
||||||
Assert(num_folded == 1); // Only one uint32 codepoint supported for now (low ascii)
|
|
||||||
right = rightFolded[0];
|
|
||||||
}
|
|
||||||
if (left < right)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (left > right)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (left == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst, bool nullTerminate)
|
|
||||||
{
|
|
||||||
Assert(IsValid(src));
|
|
||||||
|
|
||||||
const char* srcStr = src.Str;
|
|
||||||
char* dstStr = dst.Str;
|
|
||||||
size_t remainingCapacity = dst.Capacity;
|
|
||||||
|
|
||||||
uint32 character = 0;
|
|
||||||
while (src.Size > 0)
|
|
||||||
{
|
|
||||||
// Decode in character
|
|
||||||
switch (from)
|
|
||||||
{
|
|
||||||
case StringEncoding::UTF8: // Uses RFC 3629
|
|
||||||
{
|
|
||||||
auto p = reinterpret_cast<const uint8*>(srcStr);
|
|
||||||
size_t left = 0;
|
|
||||||
bool overlong = false;
|
|
||||||
if (p[0] >= 0xF0)
|
|
||||||
{
|
|
||||||
if ((p[0] & 0xF8) != 0xF0)
|
|
||||||
{
|
|
||||||
character = kUnknown_UNICODE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (p[0] == 0xF0 && src.Size > 1 && (p[1] & 0xF0) == 0x80)
|
|
||||||
{
|
|
||||||
overlong = true;
|
|
||||||
}
|
|
||||||
character = static_cast<uint32>(p[0] & 0x07);
|
|
||||||
left = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (p[0] >= 0xE0)
|
|
||||||
{
|
|
||||||
if ((p[0] & 0xF0) != 0xE0)
|
|
||||||
{
|
|
||||||
character = kUnknown_UNICODE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (p[0] == 0xE0 && src.Size > 1 && (p[1] & 0xE0) == 0x80)
|
|
||||||
{
|
|
||||||
overlong = true;
|
|
||||||
}
|
|
||||||
character = static_cast<uint32>(p[0] & 0x0F);
|
|
||||||
left = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (p[0] >= 0xC0)
|
|
||||||
{
|
|
||||||
if ((p[0] & 0xE0) != 0xC0)
|
|
||||||
{
|
|
||||||
character = kUnknown_UNICODE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((p[0] & 0xDE) == 0xC0)
|
|
||||||
{
|
|
||||||
overlong = true;
|
|
||||||
}
|
|
||||||
character = static_cast<uint32>(p[0] & 0x1F);
|
|
||||||
left = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (p[0] & 0x80)
|
|
||||||
{
|
|
||||||
character = kUnknown_UNICODE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
character = static_cast<uint32>(p[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++srcStr;
|
|
||||||
--src.Size;
|
|
||||||
if (src.Size < left)
|
|
||||||
{
|
|
||||||
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Failed to convert string. Incomplete input sequence");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
while (left--)
|
|
||||||
{
|
|
||||||
++p;
|
|
||||||
if ((p[0] & 0xC0) != 0x80)
|
|
||||||
{
|
|
||||||
character = kUnknown_UNICODE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
character <<= 6;
|
|
||||||
character |= (p[0] & 0x3F);
|
|
||||||
++srcStr;
|
|
||||||
--src.Size;
|
|
||||||
}
|
|
||||||
if (overlong)
|
|
||||||
{
|
|
||||||
character = kUnknown_UNICODE;
|
|
||||||
}
|
|
||||||
if ((character >= 0xD800 && character <= 0xDFFF) || (character == 0xFFFE || character == 0xFFFF) || character > 0x10FFFF)
|
|
||||||
{
|
|
||||||
character = kUnknown_UNICODE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case StringEncoding::Unknown: Assert(false, "ConvertString: Invalid Source Format: Unknown"); break;
|
|
||||||
case StringEncoding::ASCII:
|
|
||||||
case StringEncoding::LATIN1:
|
|
||||||
case StringEncoding::UTF16:
|
|
||||||
case StringEncoding::UTF32:
|
|
||||||
case StringEncoding::UCS2:
|
|
||||||
case StringEncoding::UCS4: Assert(false, "ConvertString: Unsupported Source Format"); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode out character
|
|
||||||
switch (to)
|
|
||||||
{
|
|
||||||
case StringEncoding::UTF16: // RFC 2781
|
|
||||||
{
|
|
||||||
auto p = reinterpret_cast<uint8*>(dstStr);
|
|
||||||
if (character > 0x10FFFF)
|
|
||||||
{
|
|
||||||
character = kUnknown_UNICODE;
|
|
||||||
}
|
|
||||||
if (character < 0x10000)
|
|
||||||
{
|
|
||||||
if (remainingCapacity < 2)
|
|
||||||
{
|
|
||||||
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Destination buffer too short to fit UTF16");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
p[1] = static_cast<uint8>(character >> 8);
|
|
||||||
p[0] = static_cast<uint8>(character);
|
|
||||||
|
|
||||||
dstStr += 2;
|
|
||||||
dst.Size += 1;
|
|
||||||
remainingCapacity -= 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (remainingCapacity < 4)
|
|
||||||
{
|
|
||||||
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Destination buffer too short to fit UTF16");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
character = character - 0x10000;
|
|
||||||
uint16 word1 = 0xD800U | static_cast<uint16>((character >> 10) & 0x3FF);
|
|
||||||
uint16 word2 = 0xDC00U | static_cast<uint16>(character & 0x3FF);
|
|
||||||
p[1] = static_cast<uint8>(word1 >> 8);
|
|
||||||
p[0] = static_cast<uint8>(word1);
|
|
||||||
p[3] = static_cast<uint8>(word2 >> 8);
|
|
||||||
p[2] = static_cast<uint8>(word2);
|
|
||||||
|
|
||||||
dstStr += 4;
|
|
||||||
dst.Size += 1;
|
|
||||||
remainingCapacity -= 4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case StringEncoding::Unknown: Assert(false, "ConvertString: Invalid Source Format: Unknown"); break;
|
|
||||||
case StringEncoding::ASCII:
|
|
||||||
case StringEncoding::LATIN1:
|
|
||||||
case StringEncoding::UTF8:
|
|
||||||
case StringEncoding::UTF32:
|
|
||||||
case StringEncoding::UCS2:
|
|
||||||
case StringEncoding::UCS4: Assert(false, "ConvertString: Unsupported Destination Format"); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nullTerminate)
|
|
||||||
{
|
|
||||||
switch (to)
|
|
||||||
{
|
|
||||||
case StringEncoding::UTF16:
|
|
||||||
{
|
|
||||||
if (remainingCapacity < 2)
|
|
||||||
{
|
|
||||||
Log(LogLevel::Error, LogCategory::Core,
|
|
||||||
"ConvertString: Destination buffer too short to add null terminator into UTF16 buffer");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
dstStr[0] = 0;
|
|
||||||
dstStr[1] = 0;
|
|
||||||
remainingCapacity -= 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case StringEncoding::Unknown: Assert(false, "ConvertString: Invalid Source Format: Unknown"); break;
|
|
||||||
case StringEncoding::ASCII:
|
|
||||||
case StringEncoding::LATIN1:
|
|
||||||
case StringEncoding::UTF8:
|
|
||||||
case StringEncoding::UTF32:
|
|
||||||
case StringEncoding::UCS2:
|
|
||||||
case StringEncoding::UCS4: Assert(false, "ConvertString: Unsupported Destination Format"); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ConvertString(String from, String to, String src, StringBuffer& dst, bool nullTerminate)
|
|
||||||
{
|
|
||||||
Assert(IsValid(from));
|
|
||||||
Assert(IsValid(to));
|
|
||||||
|
|
||||||
// First find the encoding of the strings
|
|
||||||
auto sourceFormat = StringEncoding::Unknown;
|
|
||||||
auto destFormat = StringEncoding::Unknown;
|
|
||||||
for (auto& encoding : Encodings)
|
|
||||||
{
|
|
||||||
if (StringCompareCaseInsensitive(from, encoding.Name) == 0)
|
|
||||||
{
|
|
||||||
sourceFormat = encoding.Format;
|
|
||||||
if (destFormat != StringEncoding::Unknown)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (StringCompareCaseInsensitive(to, encoding.Name) == 0)
|
|
||||||
{
|
|
||||||
destFormat = encoding.Format;
|
|
||||||
if (sourceFormat != StringEncoding::Unknown)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sourceFormat == StringEncoding::Unknown || destFormat == StringEncoding::Unknown)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConvertString(sourceFormat, destFormat, src, dst, nullTerminate);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
UnicodeDecode utf8_decode(uint8* str, size_t max)
|
|
||||||
{
|
|
||||||
// From rfc3629, the UTF-8 spec:
|
|
||||||
// https://www.ietf.org/rfc/rfc3629.txt
|
|
||||||
//
|
|
||||||
// Char. number range | UTF-8 octet sequence
|
|
||||||
// (hexadecimal) | (binary)
|
|
||||||
// --------------------+---------------------------------------------
|
|
||||||
// 0000 0000-0000 007F | 0xxxxxxx
|
|
||||||
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
|
||||||
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
|
||||||
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
||||||
UnicodeDecode result = { 1, uint32Max };
|
|
||||||
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 next_byte = str[1];
|
|
||||||
if (utf8_class[next_byte >> 3] == 0)
|
|
||||||
{
|
|
||||||
result.Codepoint = (byte & bitmask5) << 6;
|
|
||||||
result.Codepoint |= (next_byte & bitmask6);
|
|
||||||
result.Increment = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
if (2 < max)
|
|
||||||
{
|
|
||||||
uint8 next_byte[2] = { str[1], str[2] };
|
|
||||||
if (utf8_class[next_byte[0] >> 3] == 0 && utf8_class[next_byte[1] >> 3] == 0)
|
|
||||||
{
|
|
||||||
result.Codepoint = (byte & bitmask4) << 12;
|
|
||||||
result.Codepoint |= ((next_byte[0] & bitmask6) << 6);
|
|
||||||
result.Codepoint |= (next_byte[1] & bitmask6);
|
|
||||||
result.Increment = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
if (3 < max)
|
|
||||||
{
|
|
||||||
uint8 next_byte[3] = { str[1], str[2], str[3] };
|
|
||||||
if (utf8_class[next_byte[0] >> 3] == 0 && utf8_class[next_byte[1] >> 3] == 0 &&
|
|
||||||
utf8_class[next_byte[2] >> 3] == 0)
|
|
||||||
{
|
|
||||||
result.Codepoint = (byte & bitmask3) << 18;
|
|
||||||
result.Codepoint |= ((next_byte[0] & bitmask6) << 12);
|
|
||||||
result.Codepoint |= ((next_byte[1] & bitmask6) << 6);
|
|
||||||
result.Codepoint |= (next_byte[2] & bitmask6);
|
|
||||||
result.Increment = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 utf16_encode(uint16* str, uint32 codepoint)
|
|
||||||
{
|
|
||||||
Assert(str);
|
|
||||||
uint32 increment = 1;
|
|
||||||
if (codepoint == uint32Max)
|
|
||||||
{
|
|
||||||
str[0] = '?';
|
|
||||||
}
|
|
||||||
else if (codepoint < 0x10000)
|
|
||||||
{
|
|
||||||
str[0] = (uint16)codepoint;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32 var = codepoint - 0x10000;
|
|
||||||
str[0] = safe_cast_uint16(0xD800 + (var >> 10));
|
|
||||||
str[1] = safe_cast_uint16(0xDC00 + (var & bitmask10));
|
|
||||||
increment = 2;
|
|
||||||
}
|
|
||||||
return increment;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
String StringCopy(NonNullPtr<Arena> arena, String str)
|
|
||||||
{
|
|
||||||
String result;
|
|
||||||
result.Size = str.Size;
|
|
||||||
result.Str = static_cast<char*>(ArenaPush(arena, str.Size + 1, alignof(char), true JULIET_DEBUG_PARAM("String")));
|
|
||||||
MemCopy(result.Str, str.Str, str.Size);
|
|
||||||
result.Str[result.Size] = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
String16 str16_from_8(NonNullPtr<Arena> arena, String8 in)
|
|
||||||
{
|
|
||||||
String16 result = {};
|
|
||||||
if (in.Size > 0)
|
|
||||||
{
|
|
||||||
size_t neededCapacity = in.Size * 2;
|
|
||||||
uint16* str = ArenaPushArray<uint16, false>(arena, neededCapacity + 1);
|
|
||||||
uint8* inStr = (uint8*)in.Str;
|
|
||||||
uint8* inStrEnd = inStr + in.Size;
|
|
||||||
|
|
||||||
UnicodeDecode consumed;
|
|
||||||
uint64 size = 0;
|
|
||||||
for (; inStr < inStrEnd; inStr += consumed.Increment)
|
|
||||||
{
|
|
||||||
consumed = utf8_decode(inStr, inStrEnd - inStr);
|
|
||||||
size += utf16_encode(str + size, consumed.Codepoint);
|
|
||||||
}
|
|
||||||
str[size] = 0;
|
|
||||||
ArenaPop(arena, (neededCapacity - size) * 2);
|
|
||||||
result = { str, size };
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
String trim_whitespace(String str)
|
|
||||||
{
|
|
||||||
// Handles windos and unix kind of whitespaces
|
|
||||||
// Remove any whitespace at the begin of the string
|
|
||||||
while (str.Size > 0 && (*str.Str == ' ' || *str.Str == '\t' || *str.Str == '\r' || *str.Str == '\n'))
|
|
||||||
{
|
|
||||||
str.Str++;
|
|
||||||
str.Size--;
|
|
||||||
}
|
|
||||||
// Remove any whitespace at the end of the string.
|
|
||||||
while (str.Size > 0 && (str.Str[str.Size - 1] == ' ' || str.Str[str.Size - 1] == '\t' ||
|
|
||||||
str.Str[str.Size - 1] == '\r' || str.Str[str.Size - 1] == '\n'))
|
|
||||||
{
|
|
||||||
str.Size--;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
Loaded 100 of 369 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user