conversion to c by gemini 4 argon #3

Merged
Patedam merged 1 commits from convert-to-c99 into main 2026-10-17 17:19:10 -04:00
369 changed files with 17929 additions and 107489 deletions

No files matched your search

+4 -2
View File
@@ -1,4 +1,6 @@
#pragma once
constexpr index_t kPlayCamera = 0;
constexpr index_t kDebugCamera = 1;
#include <Juliet.h>
#define kPlayCamera ((index_t)0)
#define kDebugCamera ((index_t)1)
+163
View File
@@ -0,0 +1,163 @@
#include <Controller/DebugCameraController.h>
#include <Controller/ControllerUtils.h>
#include <Core/Common/CoreUtils.h>
#include <Core/HAL/Keyboard/Keyboard.h>
#include <Core/HAL/Mouse/Mouse.h>
#include <Core/Memory/MemoryArena.h>
#include <Graphics/Camera.h>
#include <dcimgui.h>
#include <math.h>
global bool8 gIsDebugCameraActive = false;
global index_t gPreviousCameraIndex = 0;
global float gPitch = 0.0f;
global float gYaw = 0.0f;
global bool8 gFirstUpdate = true;
global bool8 gIsFpsModeActive = false;
global bool8 gWasRightMouseButtonDown = false;
void ActivateDebugController(void)
{
Assert(gIsDebugCameraActive == false);
Camera* currentCam = GetCurrentCamera();
gPreviousCameraIndex = currentCam->Index;
SetCurrentCamera(kDebugCamera);
gIsDebugCameraActive = true;
gFirstUpdate = true;
gIsFpsModeActive = false;
gWasRightMouseButtonDown = false;
}
void DeactivateDebugController(void)
{
Assert(gIsDebugCameraActive);
gIsDebugCameraActive = false;
SetCurrentCamera(gPreviousCameraIndex);
}
bool8 IsDebugControllerActive(void)
{
return gIsDebugCameraActive;
}
void UpdateDebugController(float dt)
{
Camera* currentCam = GetCurrentCamera();
if (gFirstUpdate)
{
Vector3 origin = { 0.0f, 0.0f, 0.0f };
Vector3 dir = Vector3Sub(origin, currentCam->Position);
dir = Normalize(dir);
gPitch = asinf(dir.z);
gYaw = atan2f(dir.y, dir.x);
gFirstUpdate = false;
Vector3 forward = { cosf(gPitch) * cosf(gYaw), cosf(gPitch) * sinf(gYaw), sinf(gPitch) };
Vector3 worldUp = { 0.0f, 0.0f, 1.0f };
Vector3 right = Normalize(Cross(worldUp, forward));
currentCam->Target = Vector3Add(currentCam->Position, forward);
currentCam->Up = Cross(forward, right);
}
bool8 isRightMouseButtonDown = IsMouseButtonDown(MouseButton_Right);
if (isRightMouseButtonDown && !gWasRightMouseButtonDown)
{
gIsFpsModeActive = !gIsFpsModeActive;
}
gWasRightMouseButtonDown = isRightMouseButtonDown;
if (gIsFpsModeActive)
{
MousePosition mouseDelta = GetMouseDelta();
float sensitivity = 0.005f;
gYaw += (float)mouseDelta.X * sensitivity;
gPitch -= (float)mouseDelta.Y * sensitivity;
gPitch = Min(gPitch, 1.5f);
gPitch = Max(gPitch, -1.5f);
if (IsKeyDown(ScanCode_Q))
{
gYaw -= 2.0f * dt;
}
if (IsKeyDown(ScanCode_E))
{
gYaw += 2.0f * dt;
}
Vector3 forward = { cosf(gPitch) * cosf(gYaw), cosf(gPitch) * sinf(gYaw), sinf(gPitch) };
Vector3 worldUp = { 0.0f, 0.0f, 1.0f };
Vector3 right = Normalize(Cross(worldUp, forward));
Vector3 defaultUp = Cross(forward, right);
const float kMovementPerFrame = 10.f; // 10m/s
float speedPerFrame = kMovementPerFrame;
if (IsKeyDown(ScanCode_LeftShift))
{
speedPerFrame *= 10.f; // 100m/s
}
if (IsKeyDown(ScanCode_W))
{
currentCam->Position = Vector3Add(currentCam->Position, Vector3Scale(forward, speedPerFrame * dt));
}
if (IsKeyDown(ScanCode_S))
{
currentCam->Position = Vector3Sub(currentCam->Position, Vector3Scale(forward, speedPerFrame * dt));
}
if (IsKeyDown(ScanCode_D))
{
currentCam->Position = Vector3Add(currentCam->Position, Vector3Scale(right, speedPerFrame * dt));
}
if (IsKeyDown(ScanCode_A))
{
currentCam->Position = Vector3Sub(currentCam->Position, Vector3Scale(right, speedPerFrame * dt));
}
if (IsKeyDown(ScanCode_Space))
{
currentCam->Position = Vector3Add(currentCam->Position, Vector3Scale(defaultUp, speedPerFrame * dt));
}
if (IsKeyDown(ScanCode_LeftControl))
{
currentCam->Position = Vector3Sub(currentCam->Position, Vector3Scale(defaultUp, speedPerFrame * dt));
}
currentCam->Target = Vector3Add(currentCam->Position, forward);
currentCam->Up = defaultUp;
}
}
#if JULIET_DEBUG
void RenderImGuiDebugController(float dt)
{
Camera* currentCam = GetCurrentCamera();
ImGui_Text("Delta time: %f", (double)dt);
ImGui_Text("Camera:");
ImGui_Indent();
ImGui_BulletText("Index: %zu", (size_t)currentCam->Index);
ImGui_BulletText("Position: (%.3f, %.3f, %.3f)", (double)currentCam->Position.x, (double)currentCam->Position.y,
(double)currentCam->Position.z);
ImGui_BulletText("Target: (%.3f, %.3f, %.3f)", (double)currentCam->Target.x, (double)currentCam->Target.y,
(double)currentCam->Target.z);
ImGui_BulletText("Up: (%.3f, %.3f, %.3f)", (double)currentCam->Up.x, (double)currentCam->Up.y,
(double)currentCam->Up.z);
ImGui_BulletText("FOV: %.3f rad", (double)currentCam->FOV);
ImGui_BulletText("AspectRatio: %.3f", (double)currentCam->AspectRatio);
ImGui_BulletText("NearPlane: %.3f", (double)currentCam->NearPlane);
ImGui_BulletText("FarPlane: %.3f", (double)currentCam->FarPlane);
ImGui_BulletText("Pitch: %.3f, Yaw: %.3f", (double)gPitch, (double)gYaw);
ImGui_BulletText("FPS Mode: %s", gIsFpsModeActive ? "Active" : "Inactive");
ImGui_Unindent();
}
#endif
-170
View File
@@ -1,170 +0,0 @@
#include <Controller/DebugCameraController.h>
#include <Controller/ControllerUtils.h>
#include <Core/Common/CoreUtils.h>
#include <Core/HAL/Keyboard/Keyboard.h>
#include <Core/HAL/Mouse/Mouse.h>
#include <Graphics/Camera.h>
#include <imgui.h>
namespace
{
bool gIsDebugCameraActive = false;
index_t gPreviousCameraIndex = 0;
float gPitch = 0.0f;
float gYaw = 0.0f;
bool gFirstUpdate = true;
bool gIsFpsModeActive = false;
bool gWasRightMouseButtonDown = false;
} // namespace
void ActivateDebugController()
{
Assert(gIsDebugCameraActive == false);
Camera* currentCam = GetCurrentCamera();
gPreviousCameraIndex = currentCam->Index;
SetCurrentCamera(kDebugCamera);
gIsDebugCameraActive = true;
gFirstUpdate = true;
gIsFpsModeActive = false;
gWasRightMouseButtonDown = false;
}
void DeactivateDebugController()
{
Assert(gIsDebugCameraActive);
gIsDebugCameraActive = false;
SetCurrentCamera(gPreviousCameraIndex);
}
bool IsDebugControllerActive()
{
return gIsDebugCameraActive;
}
void UpdateDebugController(float dt)
{
Camera* currentCam = GetCurrentCamera();
if (gFirstUpdate)
{
Vector3 dir = Vector3{ 0.0f, 0.0f, 0.0f } - currentCam->Position;
dir = Normalize(dir);
gPitch = asinf(dir.z);
gYaw = atan2f(dir.y, dir.x);
gFirstUpdate = false;
Vector3 forward;
forward.x = cosf(gPitch) * cosf(gYaw);
forward.y = cosf(gPitch) * sinf(gYaw);
forward.z = sinf(gPitch);
Vector3 right = Normalize(Cross(Vector3{ 0.0f, 0.0f, 1.0f }, forward));
currentCam->Target = currentCam->Position + forward;
currentCam->Up = Cross(forward, right);
}
bool isRightMouseButtonDown = IsMouseButtonDown(MouseButton::Right);
if (isRightMouseButtonDown && !gWasRightMouseButtonDown)
{
gIsFpsModeActive = !gIsFpsModeActive;
}
gWasRightMouseButtonDown = isRightMouseButtonDown;
if (!gIsFpsModeActive)
{
return;
}
MousePosition mouseDelta = GetMouseDelta();
float sensitivity = 0.005f;
gYaw += mouseDelta.X * sensitivity;
gPitch -= mouseDelta.Y * sensitivity;
gPitch = std::min(gPitch, 1.5f);
gPitch = std::max(gPitch, -1.5f);
if (IsKeyDown(ScanCode::Q))
{
gYaw -= 2.0f * dt;
}
if (IsKeyDown(ScanCode::E))
{
gYaw += 2.0f * dt;
}
Vector3 forward;
forward.x = cosf(gPitch) * cosf(gYaw);
forward.y = cosf(gPitch) * sinf(gYaw);
forward.z = sinf(gPitch);
Vector3 right = Normalize(Cross(Vector3{ 0.0f, 0.0f, 1.0f }, forward));
Vector3 defaultUp = Cross(forward, right);
static const float kMovementPerFrame = 10.f; // 10m/s
float speedPerFrame = kMovementPerFrame;
if (IsKeyDown(ScanCode::LeftShift))
{
speedPerFrame *= 10.f; // 100m/s
}
if (IsKeyDown(ScanCode::W))
{
currentCam->Position = currentCam->Position + forward * (speedPerFrame * dt);
}
if (IsKeyDown(ScanCode::S))
{
currentCam->Position = currentCam->Position - forward * (speedPerFrame * dt);
}
if (IsKeyDown(ScanCode::D))
{
currentCam->Position = currentCam->Position + right * (speedPerFrame * dt);
}
if (IsKeyDown(ScanCode::A))
{
currentCam->Position = currentCam->Position - right * (speedPerFrame * dt);
}
if (IsKeyDown(ScanCode::Space))
{
currentCam->Position = currentCam->Position + defaultUp * (speedPerFrame * dt);
}
if (IsKeyDown(ScanCode::LeftControl))
{
currentCam->Position = currentCam->Position - defaultUp * (speedPerFrame * dt);
}
currentCam->Target = currentCam->Position + forward;
currentCam->Up = defaultUp;
}
#if JULIET_DEBUG
void RenderImGuiDebugController(float dt)
{
Camera* currentCam = GetCurrentCamera();
ImGui::Text("Delta time: %f", dt);
ImGui::Text("Camera:");
ImGui::Indent();
ImGui::BulletText("Index: %zu", (size_t)currentCam->Index);
ImGui::BulletText("Position: (%.3f, %.3f, %.3f)", currentCam->Position.x, currentCam->Position.y,
currentCam->Position.z);
ImGui::BulletText("Target: (%.3f, %.3f, %.3f)", currentCam->Target.x, currentCam->Target.y, currentCam->Target.z);
ImGui::BulletText("Up: (%.3f, %.3f, %.3f)", currentCam->Up.x, currentCam->Up.y, currentCam->Up.z);
ImGui::BulletText("FOV: %.3f rad", currentCam->FOV);
ImGui::BulletText("AspectRatio: %.3f", currentCam->AspectRatio);
ImGui::BulletText("NearPlane: %.3f", currentCam->NearPlane);
ImGui::BulletText("FarPlane: %.3f", currentCam->FarPlane);
ImGui::BulletText("Pitch: %.3f, Yaw: %.3f", gPitch, gYaw);
ImGui::BulletText("FPS Mode: %s", gIsFpsModeActive ? "Active" : "Inactive");
ImGui::Unindent();
}
#endif
+5 -3
View File
@@ -1,10 +1,12 @@
#pragma once
#include <Juliet.h>
// TODO : Should support Debug/Profile/Release properly.
// I think debug profile should have this controller but not release
void ActivateDebugController();
void DeactivateDebugController();
bool IsDebugControllerActive();
void ActivateDebugController(void);
void DeactivateDebugController(void);
bool8 IsDebugControllerActive(void);
void UpdateDebugController(float dt);
#if JULIET_DEBUG
+140
View File
@@ -0,0 +1,140 @@
#include <Data/World.h>
#include <Core/Common/CoreUtils.h>
#include <Core/Common/serialization.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/HAL/IO/IOStream.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Thread/ThreadContext.h>
#include <Entity/EntityManager.h>
#include <Graphics/MeshRenderer.h>
#ifdef JULIET_ENABLE_IMGUI
#include <dcimgui.h>
#endif
void InitWorld(World* world, Arena* arena)
{
Assert(world != NULL);
Assert(arena != NULL);
world->WorldArena = arena;
}
void ShutdownWorld(World* world)
{
Assert(world != NULL);
world->WorldArena = NULL;
}
void AddToWorld(World* world, Entity* entity)
{
(void)world;
(void)entity;
}
void RemoveWorldEntity(World* world, size_t index)
{
(void)world;
(void)index;
}
void SerializeWorld(Archive* ar, World* world, String filename)
{
(void)world;
Assert(ar != NULL);
Assert(IsValidString(filename));
EntityManager* entityManager = GetEntityManager();
if (ar->loading)
{
// Load
ByteBuffer fileBuffer = LoadFile(ar->arena, filename);
// TEST SERIALIZATION
ParsedArchive archive = tokenize_archive(ar->arena, fileBuffer);
#if JULIET_DEBUG
audit_unconsumed_properties(&archive, ConstString("World"));
#else
(void)archive;
#endif
}
else
{
// Save
IOStream* stream = IOFromFile(ar->arena, filename, WrapString("wb"));
index_t beginPos = ArenaPos(ar->arena);
// Headers
WorldFileHeader* header = ArenaPushStruct(ar->arena, WorldFileHeader);
header->Magic = kWorldMagic;
// TODO : Move to a one file per entity model
for (uint8 i = 0; i < ENTITY(Count); ++i)
{
typed_entity_array* type = &entityManager->by_type[i];
serialize_elem(ar, type->count);
if (type->count > 0 && type->array != NULL)
{
EntityTemplate* element = type->array;
uint8* rawElement = (uint8*)element;
size_t stride = element->base->derived_kind->size_of;
for (index_t idx = 0; idx < type->count; ++idx)
{
Entity* entity = ((EntityTemplate*)(rawElement + (idx * stride)))->base;
serialize_entity(ar, entity);
}
}
}
// Write
index_t endPos = ArenaPos(ar->arena);
ByteBuffer writeBuffer = { .Data = (Byte*)header, .Size = endPos - beginPos };
size_t written = IOWrite(stream, writeBuffer);
Assert(writeBuffer.Size == written);
IOClose(stream);
}
}
bool8 LoadWorld(World* world, String filename)
{
(void)world;
Assert(IsValidString(filename));
return true;
}
#ifdef JULIET_EDITOR
void RenderWorldEditorUI(World* world)
{
Assert(world != NULL);
if (ImGui_Begin("World Editor", NULL, ImGuiWindowFlags_None))
{
TempArena temp = scratch_begin(NULL, 0);
static char worldFilePath[256] = "/world.bin";
ImGui_InputText("World File", worldFilePath, sizeof(worldFilePath));
Path path = GetAssetPath(temp.Arena, AssetType_JAsset, WrapString(worldFilePath));
if (ImGui_Button("Save World"))
{
Archive data = { .arena = temp.Arena, .loading = false };
SerializeWorld(&data, world, path.FullPath);
}
ImGui_SameLine(0.0f, -1.0f);
if (ImGui_Button("Load World"))
{
Archive data = { .arena = temp.Arena, .loading = true };
SerializeWorld(&data, world, path.FullPath);
}
scratch_end(temp);
}
ImGui_End();
}
#endif
-322
View File
@@ -1,322 +0,0 @@
#include <Data/World.h>
#include <Core/Common/CoreUtils.h>
#include <Core/Common/serialization.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/HAL/IO/IOStream.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Thread/ThreadContext.h>
#include <Entity/EntityManager.h>
#include <Graphics/MeshRenderer.h>
#ifdef JULIET_ENABLE_IMGUI
#include <imgui.h>
#endif
void InitWorld(NonNullPtr<World> world, NonNullPtr<Arena> arena)
{
world->WorldArena = arena.Get();
}
void ShutdownWorld(NonNullPtr<World> world)
{
world->WorldArena = nullptr;
}
void AddToWorld(NonNullPtr<World> /*world*/, NonNullPtr<Entity> /*entity*/)
{
// RegisterEntity(*world->EntityManager, entity.Get());
}
void RemoveWorldEntity(World& /*world*/, size_t /*index*/) {}
void Serialize(Archive& ar, World& /*world*/, String filename)
{
Assert(IsValid(filename));
auto& entityManager = GetEntityManager();
if (ar.loading)
{
// Load
ByteBuffer fileBuffer = LoadFile(ar.arena, filename);
// TEST SERIALIZATION
ParsedArchive archive = tokenize_archive(ar.arena, fileBuffer);
// ArchivePropertyNode* property = find_property(&archive, "Position"_crc32);
audit_unconsumed_properties(&archive, ConstString("World"));
// if (fileBuffer.Size >= sizeof(WorldFileHeader))
// {
// ar.base_ptr = fileBuffer.Data;
//
// WorldFileHeader header;
// serialize_elem(ar, header);
// Assert(header.Magic == kWorldMagic);
//
// for (typed_entity_array& type : entityManager.by_type)
// {
// serialize_elem(ar, type.count);
//
// if (type.count > 0)
// {
//
// // Unserialize the base entity to get informations
// Entity entity;
// // serialize(ar, &entity);
// }
// }
// }
}
else
{
// Save
IOStream* stream = IOFromFile(ar.arena, filename, WrapString("wb"));
index_t beginPos = ArenaPos(ar.arena);
// Headers
auto* header = ArenaPushStruct<WorldFileHeader>(ar.arena);
header->Magic = kWorldMagic;
ar.base_ptr = header;
// TODO : Move to a one file per entity model
for (typed_entity_array& type : entityManager.by_type)
{
serialize_elem(ar, type.count);
auto* element = type.array;
uint8* rawElement = reinterpret_cast<uint8*>(element);
size_t stride = element->base->derived_kind->size_of;
for (index_t idx = 0; idx < type.count; ++idx)
{
// Todo : utils
// Get base entity from type
Entity* entity = reinterpret_cast<EntityTemplate*>(rawElement + (idx * stride))->base;
serialize(ar, entity);
}
}
// Write
index_t endPos = ArenaPos(ar.arena);
ByteBuffer writeBuffer = { .Data = reinterpret_cast<Byte*>(header), .Size = endPos - beginPos };
size_t written = IOWrite(stream, writeBuffer);
Assert(writeBuffer.Size == written);
IOClose(stream);
}
//
// uint32 entityCount = static_cast<uint32>(world.Entities.Size());
// size_t totalBytes = sizeof(WorldFileHeader) + static_cast<size_t>(entityCount) * sizeof(WorldEntityDiskRecord);
//
// ArenaParams tempParams = { .ReserveSize = Megabytes(1), .Name = "WorldSaveArena" };
// Arena* tempArena = ArenaAllocate(tempParams);
// if (!tempArena)
// {
// LogError(LogCategory::Game, "SaveWorld: Failed to allocate memory for saving world.");
// return false;
// }
//
// auto deferRelease = Defer([&]() { ArenaRelease(tempArena); });
//
// uint8* bufferData = ArenaPushArray<uint8, false>(tempArena, totalBytes);
// if (!bufferData)
// {
// LogError(LogCategory::Game, "SaveWorld: Failed to allocate buffer in arena.");
// return false;
// }
//
// auto* header = reinterpret_cast<WorldFileHeader*>(bufferData);
// header->Magic = kWorldMagic;
// header->Version = kWorldVersion;
// header->EntityCount = entityCount;
// header->Reserved = 0;
//
// auto* records = reinterpret_cast<WorldEntityDiskRecord*>(bufferData + sizeof(WorldFileHeader));
// for (size_t i = 0; i < entityCount; ++i)
// {
// const Entity& ent = world.Entities[i];
// records[i].X = ent.X;
// records[i].Y = ent.Y;
// records[i].Z = ent.Z;
// }
//
// IOStream* stream = IOFromFile(tempArena, filename, WrapString("wb"));
// if (!stream)
// {
// LogError(LogCategory::Game, "SaveWorld: Failed to open file for writing: %s", CStr(filename));
// return false;
// }
//
// ByteBuffer writeBuffer = { .Data = reinterpret_cast<Byte*>(bufferData), .Size = totalBytes };
//
// size_t written = IOWrite(stream, writeBuffer);
// IOClose(stream);
//
// if (written != totalBytes)
// {
// LogError(LogCategory::Game, "SaveWorld: Failed to write complete world data to %s (wrote %zu / %zu bytes)",
// CStr(filename), written, totalBytes);
// return false;
// }
//
// LogMessage(LogCategory::Game, "World successfully saved to %s (%u entities)", CStr(filename), entityCount);
// return true;
}
[[nodiscard]] bool LoadWorld(World& /*world*/, String filename)
{
Assert(IsValid(filename));
// Assert(world.WorldArena != nullptr);
//
// TempArena loadArena = scratch_begin(nullptr, 0);
//
// ByteBuffer fileBuffer = LoadFile(loadArena.Arena, filename);
// if (fileBuffer.Data && fileBuffer.Size < sizeof(WorldFileHeader))
// {
// const WorldFileHeader* header = reinterpret_cast<const WorldFileHeader*>(fileBuffer.Data);
// const bool invalidMagicNum = header->Magic != kWorldMagic;
// const bool invalidVersion = header->Version != kWorldVersion;
// if (invalidMagicNum)
// {
// LogError(LogCategory::Game, "LoadWorld: Invalid magic in world file: %s (expected 0x%08X, got 0x%08X)",
// CStr(filename), kWorldMagic, header->Magic);
// }
//
// if (invalidVersion)
// {
// LogError(LogCategory::Game, "LoadWorld: Unsupported world file version: %u in %s", header->Version, CStr(filename));
// }
//
// size_t expectedSize = sizeof(WorldFileHeader) + static_cast<size_t>(header->EntityCount) * sizeof(WorldEntityDiskRecord);
// const bool invalidSize = fileBuffer.Size < expectedSize;
// if (invalidSize)
// {
// LogError(LogCategory::Game, "LoadWorld: Corrupted file %s: size %zu < expected %zu for %u entities",
// CStr(filename), fileBuffer.Size, expectedSize, header->EntityCount);
// }
//
// if (!invalidMagicNum && !invalidVersion && !invalidSize)
// {
//
// // world.Entities.Clear();
// //
// // const auto* records = reinterpret_cast<const WorldEntityDiskRecord*>(
// // reinterpret_cast<const uint8*>(fileBuffer.Data) + sizeof(WorldFileHeader));
// //
// // for (uint32 i = 0; i < header->EntityCount; ++i)
// // {
// // Entity ent;
// // (void)AddWorldEntity(world, records[i].X, records[i].Y, records[i].Z);
// // }
//
// LogMessage(LogCategory::Game, "World successfully loaded from %s (%u entities)", CStr(filename), header->EntityCount);
// }
// }
// else
// {
// LogError(LogCategory::Game, "LoadWorld: Failed to read world file or file is too small: %s", CStr(filename));
// }
//
// scratch_end(loadArena);
return true;
}
#ifdef JULIET_EDITOR
void RenderWorldEditorUI(World& world)
{
if (ImGui::Begin("World Editor"))
{
TempArena temp = scratch_begin(nullptr, 0);
static char worldFilePath[256] = "/world.bin";
ImGui::InputText("World File", worldFilePath, sizeof(worldFilePath));
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
View File
@@ -1,38 +1,39 @@
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#include <Core/Container/Vector.h>
#include <Core/Memory/MemoryArena.h>
#include <Entity/Entity.h>
struct Archive;
struct EntityManager;
typedef struct Archive Archive;
typedef struct EntityManager EntityManager;
#pragma pack(push, 1)
typedef struct WorldFileHeader WorldFileHeader;
struct WorldFileHeader
{
uint32 Magic = 0x444C574A; // 'JWLD' in little-endian
uint32 Magic; // 0x444C574A ('JWLD' in little-endian)
};
#pragma pack(pop)
constexpr uint32 kWorldMagic = 0x444C574A; // 'JWLD'
constexpr uint32 kWorldVersion = 1;
#define kWorldMagic ((uint32)0x444C574A) // 'JWLD'
#define kWorldVersion ((uint32)1)
typedef struct World World;
struct World
{
Arena* WorldArena = nullptr;
EntityManager* EntityManager = nullptr;
Arena* WorldArena;
EntityManager* EntityManager;
};
void InitWorld(NonNullPtr<World> world, NonNullPtr<Arena> arena);
void ShutdownWorld(NonNullPtr<World> world);
void InitWorld(World* world, Arena* arena);
void ShutdownWorld(World* world);
void AddToWorld(NonNullPtr<World> world, NonNullPtr<Entity> entity);
void RemoveWorldEntity(World& world, size_t index);
void AddToWorld(World* world, Entity* entity);
void RemoveWorldEntity(World* world, size_t index);
void Serialize(Archive& data, World& world, String filename);
void SerializeWorld(Archive* data, World* world, String filename);
#if JULIET_EDITOR
void RenderWorldEditorUI(World& world);
void RenderWorldEditorUI(World* world);
#endif
+63
View File
@@ -0,0 +1,63 @@
#include <Debug/DebugTopBar.h>
#if JULIET_DEBUG
#include <game.h>
#include <dcimgui.h>
#include <stdio.h>
internal String GetGameModeName(GameMode gameMode)
{
String result = WrapString("Unknown ERROR");
if (gameMode == GameMode_Editor)
{
result = WrapString("Editor");
}
else if (gameMode == GameMode_Play)
{
result = WrapString("Play");
}
else if (gameMode == GameMode_Debug)
{
result = WrapString("Debug");
}
return result;
}
void DrawTopBar(void)
{
GameState* gameState = GetGameState();
ImVec2_c viewportPos = ImGui_GetMainViewportPos();
ImVec2_c viewportSize = ImGui_GetMainViewportSize();
ImGui_SetNextWindowPos(viewportPos);
ImVec2_c barSize = { viewportSize.x, 10.0f };
ImGui_SetNextWindowSize(barSize);
ImGuiWindowFlags_c flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing |
ImGuiWindowFlags_NoNav;
ImVec4_c bgCol = { 0.0f, 0.0f, 0.0f, 0.6f };
ImVec2_c padding = { 10.0f, 5.0f };
ImGui_PushStyleColor(ImGuiCol_WindowBg, bgCol);
ImGui_PushStyleVarVec2(ImGuiStyleVar_WindowPadding, padding);
if (ImGui_Begin("TopBarOverlay", NULL, flags))
{
ImGui_Text("Game Mode: %s", CStr(GetGameModeName(gameState->Mode)));
float framerate = ImGuiIO_GetFramerate();
char fps_text[32];
snprintf(fps_text, sizeof(fps_text), "FPS: %.1f (%.2f ms)", (double)framerate, (double)(1000.0f / framerate));
float text_width = ImGui_CalcTextSize(fps_text, NULL).x;
ImGui_SameLine(viewportSize.x - text_width - 15.0f, -1.0f); // 15px right padding
// Render FPS text
ImGui_Text("%s", fps_text);
}
ImGui_End();
ImGui_PopStyleVar(1);
ImGui_PopStyleColor(1);
}
#endif
-49
View File
@@ -1,49 +0,0 @@
#include <Debug/DebugTopBar.h>
#include <game.h>
#include <imgui.h>
namespace
{
String GetGameModeName(GameMode gameMode)
{
switch (gameMode)
{
case GameMode::Editor: return WrapString("Editor");
case GameMode::Play: return WrapString("Play");
case GameMode::Debug: return WrapString("Debug");
default: return WrapString("Unknown ERROR");
}
}
} // namespace
void DrawTopBar()
{
auto* gameState = GetGameState();
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, 10.0f));
ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.6f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 5.0f));
if (ImGui::Begin("TopBarOverlay", nullptr, flags))
{
ImGui::Text("Game Mode: %s", CStr(GetGameModeName(gameState->Mode)));
char fps_text[32];
snprintf(fps_text, sizeof(fps_text), "FPS: %.1f (%.2f ms)", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate);
float text_width = ImGui::CalcTextSize(fps_text).x;
ImGui::SameLine(viewport->Size.x - text_width - 15.0f); // 15px right padding
// Render FPS text
ImGui::Text("%s", fps_text);
}
ImGui::End();
ImGui::PopStyleVar();
ImGui::PopStyleColor();
}
+3 -1
View File
@@ -1,5 +1,7 @@
#pragma once
#include <Juliet.h>
#if JULIET_DEBUG
void DrawTopBar();
void DrawTopBar(void);
#endif
+115
View File
@@ -0,0 +1,115 @@
#include <Entity/Entity.h>
#include <Core/Common/serialization.h>
#include <Core/Memory/Utils.h>
#include <stdlib.h>
void serialize_entity(Archive* ar, Entity* entity)
{
Assert(ar != NULL);
Assert(entity != NULL);
// Entity fields
serialize_class(ar, ClassKind(Entity), entity);
// Derived fields
if (entity->derived_kind != NULL && entity->derived != NULL)
{
serialize_class(ar, entity->derived_kind, entity->derived);
}
}
internal void init_Entity(void* payload)
{
Assert(payload != NULL);
Entity* entity = (Entity*)payload;
MemZeroStruct(entity);
}
internal void serialize_Entity(Archive* ar, uint16 version, void* payload)
{
(void)version;
Assert(ar != NULL);
Assert(payload != NULL);
Entity* entity = (Entity*)payload;
SERIALIZE_U64(ar, id, &entity->ID);
SERIALIZE_VEC4(ar, position, &entity->position);
}
DEFINE_CLASS_VERSIONED(Entity, 1, NULL)
String format_entity_id(Arena* arena, EntityID entity_id)
{
Assert(arena != NULL);
// Format:
// U = UserID
// LC = Local Entity Counter
// UU_LCLCLCLCLCLCLC
uint8 user_id = get_user_id(entity_id);
uint64 counter = get_local_counter(entity_id);
const size_t kBufferSize = 18;
char* buffer = ArenaPushArray(arena, char, kBufferSize);
Assert(buffer != NULL);
juliet_snprintf(buffer, kBufferSize, "%02X_%014llX", (unsigned int)user_id, (unsigned long long)counter);
String result = { .Str = buffer, .Size = kBufferSize - 1 };
return result;
}
bool8 parse_entity_id(String str, EntityID* out_id)
{
Assert(out_id != NULL);
bool8 result = false;
*out_id = kInvalid_entity_id;
if (!(str.Size != 17 || str.Str == NULL || str.Str[2] != '_'))
{
char user_hex[3] = { str.Str[0], str.Str[1], '\0' };
char* end = user_hex;
uint8 user_id = (uint8)strtoul(user_hex, &end, 16);
if (end != user_hex && user_id != kInvalid_user_id)
{
char* counter_hex = str.Str + 3;
end = counter_hex;
uint64 counter = strtoull(counter_hex, &end, 16);
if (end != counter_hex && counter < kEntityID_user_id_mask)
{
*out_id = make_entity_id(user_id, counter);
result = true;
}
}
}
return result;
}
const Class* resolve_entity_class(uint8 kind, uint32 crc)
{
Assert(kind <= ENTITY(Count));
const Class* class_ptr = kEntity_type_class_ptr[kind];
Assert(class_ptr != NULL);
Assert(class_get_crc(class_ptr) == crc);
return class_ptr;
}
const Class* find_class_by_name(String name)
{
Assert(IsValidString(name));
const Class* result = NULL;
const uint32 name_crc = crc32_bytes(name.Str, name.Size);
for (uint8 kind = 0; kind < ENTITY(Count); ++kind)
{
const Class* class_ptr = resolve_entity_class(kind, name_crc);
if (class_ptr != NULL)
{
result = class_ptr;
break;
}
}
return result;
}
-92
View File
@@ -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
View File
@@ -6,98 +6,95 @@
#include <Entity/entity_common.h>
#include <Entity/EntityManager.h>
struct Entity final
typedef struct Entity Entity;
struct Entity
{
DECLARE_CLASS()
EntityID ID = 0;
const Class* derived_kind = nullptr;
DerivedType derived = nullptr;
Vector4 position = {};
bool is_dirty = false;
EntityID ID;
const Class* derived_kind;
DerivedType derived;
Vector4 position;
bool8 is_dirty;
};
DECLARE_CLASS(Entity)
// Can reinterpret cast to this to have the offset of Base and Kind for any entity
// Can cast to this to have the offset of base for any entity
typedef struct EntityTemplate EntityTemplate;
struct EntityTemplate
{
DECLARE_ENTITY();
DECLARE_ENTITY()
};
//
template <typename EntityType>
concept EntityConcept = requires(EntityType entity) {
{ EntityType::kind } -> std::convertible_to<const Class*>;
requires std::same_as<decltype(entity.base), Entity*>;
};
inline constexpr EntityID make_entity_id(uint8 user_id, uint64 local_counter)
static inline EntityID make_entity_id(uint8 user_id, uint64 local_counter)
{
Assert(user_id != kInvalid_user_id);
Assert((local_counter & kEntityID_user_id_mask) == kInvalid_entity_id);
EntityID result = kInvalid_user_id;
result = ((EntityID)user_id << kEntityID_user_id_shift) | (local_counter & kEntityID_user_id_mask);
EntityID result = ((EntityID)user_id << kEntityID_user_id_shift) | (local_counter & kEntityID_user_id_mask);
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;
}
template <typename EntityType>
requires EntityConcept<EntityType>
[[nodiscard]] bool IsA(const Entity* entity)
static inline bool8 IsEntityA(const Entity* entity, const Class* kind)
{
Assert(entity != nullptr);
return entity->derived_kind == EntityType::kind;
Assert(entity != NULL);
return entity->derived_kind == kind;
}
template <typename 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);
#define IsEntityOfType(entity_ptr, EntityType) IsEntityA((entity_ptr), ClassKind(EntityType))
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.y = y;
base_ptr->position.z = z;
base_ptr->position.w = 1.0f;
return (EntityType*)base_ptr->derived;
return base_ptr->derived;
}
template <typename EntityType>
requires EntityConcept<EntityType>
[[nodiscard]] EntityType* DownCast(Entity* entity)
#define MakeEntity(EntityType, manager_ptr, x, y, z) \
((EntityType*)make_entity_by_class((manager_ptr), ClassKind(EntityType), (x), (y), (z)))
static inline void* down_cast_entity(Entity* entity, const Class* kind)
{
Assert(entity != nullptr);
Assert(IsA<EntityType>(entity));
return static_cast<EntityType*>(entity->derived);
Assert(entity != NULL);
Assert(IsEntityA(entity, kind));
return entity->derived;
}
void serialize(Archive& ar, NonNullPtr<Entity> entity);
#define DownCastEntity(EntityType, entity_ptr) ((EntityType*)down_cast_entity((entity_ptr), ClassKind(EntityType)))
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);
+190
View File
@@ -0,0 +1,190 @@
#include <Entity/EntityManager.h>
#include <Core/Common/serialization.h>
#include <Core/Memory/Utils.h>
#include <Data/World.h>
#include <Engine/user.h>
#include <Entity/Entity.h>
#include <Entity/entity_types.h>
#include <game.h>
#include <Graphics/MeshRenderer.h>
EntityID g_entity_manager_id = 0;
void InitEntityManager(World* world)
{
Assert(world != NULL);
EntityManager* newManager = ArenaPushStruct(world->WorldArena, EntityManager);
newManager->next_local_counter = 1ULL;
world->EntityManager = newManager;
VectorArenaCreate(&newManager->Entities, Entity, world->WorldArena, 100000 JULIET_DEBUG_PARAM("Entities"));
ArenaParams by_type_params = { .ReserveSize = Kilobytes(1),
.CommitSize = Kilobytes(1),
.Name = "" JULIET_DEBUG_ONLY(, .DoNotReserveMore = true) };
for (uint8 i = 0; i < ENTITY(Count); ++i)
{
by_type_params.Name = kEntity_type_names[i];
newManager->by_type[i].arena = ArenaAllocate(by_type_params);
newManager->by_type[i].array = NULL;
newManager->by_type[i].count = 0;
}
}
void ShutdownEntityManager(void)
{
EntityManager* manager = GetEntityManager();
for (uint8 i = 0; i < ENTITY(Count); ++i)
{
ArenaRelease(manager->by_type[i].arena);
}
vector_arena_destroy(&manager->Entities);
}
EntityManager* GetEntityManager(void)
{
EntityManager* entityManager = GetGameState()->World->EntityManager;
Assert(entityManager != NULL);
return entityManager;
}
EntityID generate_next_entity_id(EntityManager* manager)
{
Assert(manager != NULL);
UserID user = get_local_user_id();
Assert(user != kInvalid_user_id);
Assert(manager->next_local_counter != kEntityID_user_id_mask);
EntityID new_id = make_entity_id(user, manager->next_local_counter);
manager->next_local_counter += 1ULL;
return new_id;
}
EntityTemplate* RegisterEntity(EntityManager* manager, Entity* base, DerivedType entity)
{
Assert(manager != NULL);
Assert(base != NULL);
base->ID = g_entity_manager_id++;
base->derived = entity;
VectorArenaPushPtr(Entity, &manager->Entities, base);
EntityTemplate* ptr = (EntityTemplate*)ArenaPushSize(
manager->by_type[base->derived_kind->kind].arena, base->derived_kind->size_of, base->derived_kind->alignment,
false JULIET_DEBUG_PARAM(kEntity_type_names[base->derived_kind->kind]));
MemCopy(ptr, entity, base->derived_kind->size_of);
manager->by_type[base->derived_kind->kind].count += 1;
ptr->base = VectorArenaBack(Entity, &manager->Entities);
if (manager->by_type[base->derived_kind->kind].array == NULL)
{
manager->by_type[base->derived_kind->kind].array = ptr;
}
return ptr;
}
Entity* allocate_entity(EntityManager* manager, const Class* derived_type_class)
{
Assert(manager != NULL);
Assert(derived_type_class != NULL);
Assert(derived_type_class->kind < ENTITY(Count));
Assert(derived_type_class->size_of >= sizeof(EntityTemplate));
Assert(derived_type_class->alignment > 0);
Assert(derived_type_class->initialize_fct != NULL);
Entity base_template = { 0 };
base_template.derived_kind = derived_type_class;
base_template.is_dirty = true;
VectorArenaPushPtr(Entity, &manager->Entities, &base_template);
Entity* base_ptr = VectorArenaBack(Entity, &manager->Entities);
Assert(base_ptr != NULL);
typed_entity_array* typed_array = &manager->by_type[derived_type_class->kind];
Assert(typed_array->arena != NULL);
void* derived = ArenaPushSize(typed_array->arena, derived_type_class->size_of, derived_type_class->alignment,
false JULIET_DEBUG_PARAM(kEntity_type_names[derived_type_class->kind]));
Assert(derived != NULL);
derived_type_class->initialize_fct(derived);
EntityTemplate* derived_template = (EntityTemplate*)derived;
base_ptr->derived = derived;
derived_template->base = base_ptr;
if (typed_array->array == NULL)
{
typed_array->array = derived_template;
}
typed_array->count += 1;
return base_ptr;
}
void UpdateEntityManager(EntityManager* manager)
{
Assert(manager != NULL);
// Todo : inert by definition dont move, but this is for test
typed_entity_array* by_type = &manager->by_type[ENTITY(Inert)];
for (index_t i = 0; i < by_type->count; ++i)
{
Inert* inert = ((Inert*)by_type->array) + i;
if (inert->MeshInstance != indexMax)
{
Matrix transform =
MatrixTranslation(inert->base->position.x, inert->base->position.y, inert->base->position.z);
SetMeshInstanceTransform(inert->MeshInstance, &transform);
}
}
}
Entity* deserialize_entity(Archive* ar, EntityManager* manager)
{
Assert(ar != NULL);
Assert(manager != NULL);
Assert(ar->loading);
String class_name = { 0 };
SERIALIZE_STR(ar, Class, &class_name);
const Class* class_ptr = find_class_by_name(class_name);
Assert(class_ptr != NULL);
Entity* entity_base = allocate_entity(manager, class_ptr);
Assert(entity_base != NULL);
serialize_entity(ar, entity_base);
if (entity_base->ID >= g_entity_manager_id)
{
g_entity_manager_id = entity_base->ID + 1;
}
entity_base->is_dirty = false;
return entity_base;
}
void update_local_counter(EntityManager* manager, EntityID entity_id)
{
Assert(manager != NULL);
uint8 user_id = get_local_user_id();
if (get_user_id(entity_id) == user_id)
{
uint64 counter = get_local_counter(entity_id);
if (counter >= manager->next_local_counter)
{
manager->next_local_counter = counter + 1ULL;
}
}
}
-170
View File
@@ -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
View File
@@ -3,11 +3,13 @@
#include <Core/Container/Vector.h>
#include <Entity/entity_common.h>
struct World;
struct EntityTemplate;
struct Entity;
struct Class;
typedef struct World World;
typedef struct EntityTemplate EntityTemplate;
typedef struct Entity Entity;
typedef struct Class Class;
typedef struct Archive Archive;
typedef struct typed_entity_array typed_entity_array;
struct typed_entity_array
{
Arena* arena;
@@ -15,22 +17,24 @@ struct typed_entity_array
size_t count;
};
typedef struct EntityManager EntityManager;
struct EntityManager
{
static EntityID ID;
uint64 next_local_counter = 1ULL;
uint64 next_local_counter;
// TODO: Should be a pool
VectorArena<Entity, 100'000> Entities;
VectorArena Entities;
typed_entity_array by_type[ENTITY(Count)];
typed_entity_array by_type[Entity_Type_Count];
};
void InitEntityManager(NonNullPtr<World> world);
void ShutdownEntityManager();
EntityManager& GetEntityManager();
EntityTemplate* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity);
[[nodiscard]] Entity* allocate_entity(EntityManager& manager, NonNullPtr<const Class> derived_type_class);
void UpdateEntityManager(EntityManager& manager);
[[nodiscard]] Entity* deserialize_entity(Archive& archive, EntityManager& manager);
void update_local_counter(EntityManager& manager, EntityID entity_id);
extern EntityID g_entity_manager_id;
void InitEntityManager(World* world);
void ShutdownEntityManager(void);
EntityManager* GetEntityManager(void);
EntityTemplate* RegisterEntity(EntityManager* manager, Entity* base, DerivedType entity);
Entity* allocate_entity(EntityManager* manager, const Class* derived_type_class);
void UpdateEntityManager(EntityManager* manager);
Entity* deserialize_entity(Archive* archive, EntityManager* manager);
void update_local_counter(EntityManager* manager, EntityID entity_id);
@@ -5,17 +5,16 @@
// clang-format off
#define AS_STR(name) #name
const char* kEntity_type_names[] = {
const char* kEntity_type_names[] = {
ENTITY_TYPE_LIST(AS_STR)
"Count"
};
#undef AS_STR
#define AS_CLASS(name) name::kind
const Class* kEntity_type_class_ptr[]
{
#define AS_CLASS(name) &class_kind_##name
const Class* kEntity_type_class_ptr[] = {
ENTITY_TYPE_LIST(AS_CLASS)
nullptr
NULL
};
#undef AS_CLASS
// clang-format on
+25 -23
View File
@@ -1,46 +1,48 @@
#pragma once
#include <Core/Common/EnumUtils.h>
#include <Engine/Class.h>
struct Class;
using DerivedType = void*;
using EntityID = uint64_t;
typedef void* DerivedType;
typedef uint64 EntityID;
constexpr uint8 kInvalid_user_id = 0U;
constexpr EntityID kInvalid_entity_id = 0ULL;
constexpr EntityID kEntityID_user_id_shift = 56ULL;
constexpr EntityID kEntityID_user_id_mask = 0xFF00'0000'0000'0000ULL;
#define kInvalid_user_id ((uint8)0U)
#define kInvalid_entity_id ((EntityID)0ULL)
#define kEntityID_user_id_shift ((EntityID)56ULL)
#define kEntityID_user_id_mask ((EntityID)0xFF00000000000000ULL)
// clang-format off
#define ENTITY_TYPE_LIST(X) X(Inert),
#define AS_ENUM(name) name
enum class Entity_Type : uint8
typedef uint8 Entity_Type;
#define AS_ENUM(name) Entity_Type_##name
enum
{
ENTITY_TYPE_LIST(AS_ENUM)
Count
Entity_Type_Count
};
#undef AS_ENUM
extern const char* kEntity_type_names[];
extern const Class* kEntity_type_class_ptr[];
#define ENTITY(kind) ToUnderlying(Entity_Type::kind)
#define ENTITY(kind) ((uint8)Entity_Type_##kind)
// clang-format on
struct Entity;
typedef struct Entity Entity;
#define DECLARE_ENTITY() \
Entity* base; \
DECLARE_CLASS()
#define DECLARE_ENTITY() Entity* base;
#define DEFINE_ENTITY_VERSIONED(entity, version) \
constexpr Class entityKind##entity = \
MakeClass(ConstString(#entity), (uint8)Entity_Type::entity, (version), &class_kind_Entity, sizeof(entity), \
alignof(entity), (&initialize_thunk<entity>), (&serialize_thunk<entity>)); \
Class* entity::kind = const_cast<Class*>(&entityKind##entity);
#define DEFINE_ENTITY_VERSIONED(entity, version_num) \
const Class class_kind_##entity = { \
.Name = ConstString(#entity), \
.kind = (uint8)Entity_Type_##entity, \
.version = (version_num), \
.base_class = &class_kind_Entity, \
.initialize_fct = init_##entity, \
.serialize_fct = serialize_##entity, \
.size_of = sizeof(entity), \
.alignment = AlignOf(entity) \
};
// Note: Needed by every classes see define above
// Note: Needed by every entity class (see define above)
extern const Class class_kind_Entity;
+22
View File
@@ -0,0 +1,22 @@
#include <Entity/entity_types.h>
#include <Core/Common/serialization.h>
internal void init_Inert(void* payload)
{
Assert(payload != NULL);
Inert* inert = (Inert*)payload;
inert->base = NULL;
inert->MeshInstance = indexMax;
}
internal void serialize_Inert(Archive* ar, uint16 version, void* payload)
{
(void)version;
Assert(ar != NULL);
Assert(payload != NULL);
Inert* inert = (Inert*)payload;
SERIALIZE_U64(ar, MeshInstance, &inert->MeshInstance);
}
DEFINE_ENTITY_VERSIONED(Inert, 1)
-9
View File
@@ -1,9 +0,0 @@
#include <Entity/entity_types.h>
#include <Core/Common/serialization.h>
DEFINE_ENTITY_VERSIONED(Inert, 1)
internal void serialize(Archive& ar, uint16 /*version*/, Inert& inert)
{
SERIALIZE(ar, MeshInstance, inert.MeshInstance);
}
+3 -1
View File
@@ -2,9 +2,11 @@
#include <Entity/entity_common.h>
typedef struct Inert Inert;
struct Inert
{
DECLARE_ENTITY()
index_t MeshInstance = indexMax;
index_t MeshInstance;
};
DECLARE_CLASS(Inert)
+171
View File
@@ -0,0 +1,171 @@
#include <UnitTest/WorldUnitTest.h>
#if JULIET_DEBUG
#include <Core/Common/CoreUtils.h>
#include <Core/Common/serialization.h>
#include <Core/HAL/IO/IOStream.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Memory/MemoryArena.h>
#include <Core/Thread/ThreadContext.h>
#include <Data/World.h>
#include <Entity/Entity.h>
#include <Entity/entity_types.h>
#include <game.h>
internal void TestEntityAllocationAndWiring(void)
{
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestEntityAllocationAndWiring...");
TempArena tempArena = scratch_begin(NULL, 0);
GameState* gameState = GetGameState();
World testWorld = { 0 };
gameState->World = &testWorld;
InitWorld(&testWorld, tempArena.Arena);
InitEntityManager(&testWorld);
EntityManager* manager = testWorld.EntityManager;
// 1. Allocate Inert Entity via allocate_entity
Entity* base_entity = allocate_entity(manager, ClassKind(Inert));
Assert(base_entity != NULL);
Assert(base_entity->ID == 0); // Pure memory allocator leaves ID unassigned (0) until MakeEntity or deserialization
base_entity->ID = ++g_entity_manager_id;
Assert(base_entity->ID > 0);
Assert(base_entity->derived_kind == ClassKind(Inert));
Assert(base_entity->derived != NULL);
Assert(base_entity->is_dirty == true);
// 2. Validate mutual back-pointer wiring
EntityTemplate* derived = (EntityTemplate*)base_entity->derived;
Assert(derived->base == base_entity);
// 3. DownCast verification
Inert* inert = DownCastEntity(Inert, base_entity);
Assert(inert != NULL);
Assert(inert->base == base_entity);
// 4. Validate typed array tracking
typed_entity_array* inert_array = &manager->by_type[ENTITY(Inert)];
Assert(inert_array->count == 1);
Assert(inert_array->array == derived);
ShutdownEntityManager();
ShutdownWorld(&testWorld);
gameState->World = NULL;
scratch_end(tempArena);
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestEntityAllocationAndWiring");
}
internal void TestInPlaceDeserialization(void)
{
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestInPlaceDeserialization...");
TempArena tempArena = scratch_begin(NULL, 0);
GameState* gameState = GetGameState();
World testWorld = { 0 };
gameState->World = &testWorld;
InitWorld(&testWorld, tempArena.Arena);
InitEntityManager(&testWorld);
EntityManager* manager = testWorld.EntityManager;
// 1. In-memory .jasset text fixture (no streams or files needed)
String asset_content = ConstString("; Class\n"
"Inert\n"
"; version\n"
"1\n"
"; class_version\n"
"1\n"
"; id\n"
"42\n"
"; position\n"
"12.5 -44.0 108.2 1.0\n"
"; MeshInstance\n"
"42\n");
ByteBuffer buffer = { .Data = (Byte*)asset_content.Str, .Size = asset_content.Size };
// 2. Tokenize into Archive
Archive load_ar = { 0 };
load_ar.arena = tempArena.Arena;
load_ar.loading = true;
load_ar.base = tokenize_archive(tempArena.Arena, buffer);
// 3. Deserialize in-place
Entity* loaded_base = deserialize_entity(&load_ar, manager);
// 4. Verify in-place allocations and values
Assert(loaded_base != NULL);
Assert(loaded_base->ID == 42);
Assert(g_entity_manager_id > 42); // Generator counter advanced past loaded ID
Assert(loaded_base->position.x == 12.5f);
Assert(loaded_base->position.y == -44.0f);
Assert(loaded_base->position.z == 108.2f);
Assert(loaded_base->is_dirty == false);
Inert* loaded_inert = DownCastEntity(Inert, loaded_base);
Assert(loaded_inert != NULL);
Assert(loaded_inert->base == loaded_base);
Assert(loaded_inert->MeshInstance == 42);
ShutdownEntityManager();
ShutdownWorld(&testWorld);
gameState->World = NULL;
scratch_end(tempArena);
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestInPlaceDeserialization");
}
internal void TestDirtyTrackingLifecycle(void)
{
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestDirtyTrackingLifecycle...");
TempArena tempArena = scratch_begin(NULL, 0);
GameState* gameState = GetGameState();
World testWorld = { 0 };
gameState->World = &testWorld;
InitWorld(&testWorld, tempArena.Arena);
InitEntityManager(&testWorld);
EntityManager* manager = testWorld.EntityManager;
Entity* entity = allocate_entity(manager, ClassKind(Inert));
Assert(entity->is_dirty == true);
// TODO : proper save and mutation
// Simulate save
entity->is_dirty = false;
Assert(entity->is_dirty == false);
// Simulate mutation
entity->position.x += 1.0f;
entity->is_dirty = true;
Assert(entity->is_dirty == true);
ShutdownEntityManager();
ShutdownWorld(&testWorld);
gameState->World = NULL;
scratch_end(tempArena);
Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestDirtyTrackingLifecycle");
}
void UnitTest_WorldUnitTest(void)
{
Log(LogLevel_Message, LogCategory_Game, "==================================================");
Log(LogLevel_Message, LogCategory_Game, "Starting Entity Allocation & Lifecycle Unit Tests");
Log(LogLevel_Message, LogCategory_Game, "==================================================");
TestEntityAllocationAndWiring();
TestInPlaceDeserialization();
// TestSwapAndPopPointerFixup(); // Deferred to Entity_Removal_Brainstorm.md
TestDirtyTrackingLifecycle();
Log(LogLevel_Message, LogCategory_Game, "==================================================");
Log(LogLevel_Message, LogCategory_Game, "All Entity Lifecycle Unit Tests PASSED Successfully");
Log(LogLevel_Message, LogCategory_Game, "==================================================");
}
#endif
-173
View File
@@ -1,173 +0,0 @@
#include <UnitTest/WorldUnitTest.h>
#if JULIET_DEBUG
#include <Core/Common/CoreUtils.h>
#include <Core/Common/serialization.h>
#include <Core/HAL/IO/IOStream.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Memory/MemoryArena.h>
#include <Core/Thread/ThreadContext.h>
#include <Data/World.h>
#include <Entity/entity_types.h>
#include <game.h>
namespace UnitTest
{
internal void TestEntityAllocationAndWiring()
{
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestEntityAllocationAndWiring...");
TempArena tempArena = scratch_begin(nullptr, 0);
GameState* gameState = GetGameState();
World testWorld{};
gameState->World = &testWorld;
InitWorld(&testWorld, tempArena.Arena);
InitEntityManager(&testWorld);
EntityManager& manager = *testWorld.EntityManager;
// 1. Allocate Inert Entity via AllocateEntity
Entity* base_entity = allocate_entity(manager, Inert::kind);
Assert(base_entity != nullptr);
Assert(base_entity->ID == 0); // Pure memory allocator leaves ID unassigned (0) until MakeEntity or deserialization
base_entity->ID = ++EntityManager::ID;
Assert(base_entity->ID > 0);
Assert(base_entity->derived_kind == Inert::kind);
Assert(base_entity->derived != nullptr);
Assert(base_entity->is_dirty == true);
// 2. Validate mutual back-pointer wiring
auto* derived = reinterpret_cast<EntityTemplate*>(base_entity->derived);
Assert(derived->base == base_entity);
// 3. DownCast verification
Inert* inert = DownCast<Inert>(base_entity);
Assert(inert != nullptr);
Assert(inert->base == base_entity);
// 4. Validate typed array tracking
typed_entity_array& inert_array = manager.by_type[ENTITY(Inert)];
Assert(inert_array.count == 1);
Assert(inert_array.array == derived);
ShutdownEntityManager();
ShutdownWorld(&testWorld);
gameState->World = nullptr;
scratch_end(tempArena);
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestEntityAllocationAndWiring");
}
internal void TestInPlaceDeserialization()
{
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestInPlaceDeserialization...");
TempArena tempArena = scratch_begin(nullptr, 0);
GameState* gameState = GetGameState();
World testWorld{};
gameState->World = &testWorld;
InitWorld(&testWorld, tempArena.Arena);
InitEntityManager(&testWorld);
EntityManager& manager = *testWorld.EntityManager;
// 1. In-memory .jasset text fixture (no streams or files needed)
String asset_content = ConstString("; Class\n"
"Inert\n"
"; version\n"
"1\n"
"; class_version\n"
"1\n"
"; id\n"
"42\n"
"; position\n"
"12.5 -44.0 108.2 1.0\n"
"; MeshInstance\n"
"42\n");
ByteBuffer buffer = { .Data = reinterpret_cast<Byte*>(asset_content.Str), .Size = asset_content.Size };
// 2. Tokenize into Archive
Archive load_ar = {};
load_ar.arena = tempArena.Arena;
load_ar.loading = true;
load_ar.base = tokenize_archive(tempArena.Arena, buffer);
// 3. Deserialize in-place
Entity* loaded_base = deserialize_entity(load_ar, manager);
// 4. Verify in-place allocations and values
Assert(loaded_base != nullptr);
Assert(loaded_base->ID == 42);
Assert(EntityManager::ID > 42); // Generator counter advanced past loaded ID
Assert(loaded_base->position.x == 12.5f);
Assert(loaded_base->position.y == -44.0f);
Assert(loaded_base->position.z == 108.2f);
Assert(loaded_base->is_dirty == false);
Inert* loaded_inert = DownCast<Inert>(loaded_base);
Assert(loaded_inert != nullptr);
Assert(loaded_inert->base == loaded_base);
Assert(loaded_inert->MeshInstance == 42);
ShutdownEntityManager();
ShutdownWorld(&testWorld);
gameState->World = nullptr;
scratch_end(tempArena);
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestInPlaceDeserialization");
}
internal void TestDirtyTrackingLifecycle()
{
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestDirtyTrackingLifecycle...");
TempArena tempArena = scratch_begin(nullptr, 0);
GameState* gameState = GetGameState();
World testWorld{};
gameState->World = &testWorld;
InitWorld(&testWorld, tempArena.Arena);
InitEntityManager(&testWorld);
EntityManager& manager = *testWorld.EntityManager;
Entity* entity = allocate_entity(manager, Inert::kind);
Assert(entity->is_dirty == true);
// TODO : proper save and mutation
// Simulate save
entity->is_dirty = false;
Assert(entity->is_dirty == false);
// Simulate mutation
entity->position.x += 1.0f;
entity->is_dirty = true;
Assert(entity->is_dirty == true);
ShutdownEntityManager();
ShutdownWorld(&testWorld);
gameState->World = nullptr;
scratch_end(tempArena);
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestDirtyTrackingLifecycle");
}
void WorldUnitTest()
{
Log(LogLevel::Message, LogCategory::Game, "==================================================");
Log(LogLevel::Message, LogCategory::Game, "Starting Entity Allocation & Lifecycle Unit Tests");
Log(LogLevel::Message, LogCategory::Game, "==================================================");
TestEntityAllocationAndWiring();
TestInPlaceDeserialization();
// TestSwapAndPopPointerFixup(); // Deferred to Entity_Removal_Brainstorm.md
TestDirtyTrackingLifecycle();
Log(LogLevel::Message, LogCategory::Game, "==================================================");
Log(LogLevel::Message, LogCategory::Game, "All Entity Lifecycle Unit Tests PASSED Successfully");
Log(LogLevel::Message, LogCategory::Game, "==================================================");
}
} // namespace UnitTest
#endif
+1 -4
View File
@@ -4,9 +4,6 @@
#if JULIET_DEBUG
namespace UnitTest
{
void WorldUnitTest();
} // namespace UnitTest
void UnitTest_WorldUnitTest(void);
#endif
+47 -41
View File
@@ -13,28 +13,26 @@
#include <Entity/EntityManager.h>
#include <Graphics/Camera.h>
#include <Graphics/MeshRenderer.h>
#include <imgui.h>
#include <dcimgui.h>
#include <stdio.h>
#if JULIET_DEBUG
#include <Debug/DebugTopBar.h>
#include <UnitTest/WorldUnitTest.h>
#endif
namespace
{
GameState* gGameState = nullptr;
}
global GameState* gGameState = NULL;
GameState* GetGameState()
GameState* GetGameState(void)
{
return gGameState;
}
extern "C" JULIET_API void __cdecl GameShutdown()
JULIET_API void __cdecl GameShutdown(void)
{
printf("Shutting down game...\n");
if (gGameState && gGameState->World)
if (gGameState != NULL && gGameState->World != NULL)
{
ShutdownWorld(gGameState->World);
}
@@ -42,47 +40,55 @@ extern "C" JULIET_API void __cdecl GameShutdown()
ShutdownEntityManager();
}
extern "C" JULIET_API void __cdecl GameUpdate(GameData* params, [[maybe_unused]] float deltaTime)
JULIET_API void __cdecl GameUpdate(GameData* params, float deltaTime)
{
Assert(params != NULL);
gGameState = params->GameState;
if (!gGameState)
if (gGameState == NULL)
{
Arena* gameStateArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "Game Total Arena" });
auto* gameState = ArenaPushStruct<GameState>(gameStateArena);
ArenaParams gameStateParams = { .ReserveSize = Megabytes(1), .Name = "Game Total Arena" };
Arena* gameStateArena = ArenaAllocate(gameStateParams);
GameState* gameState = ArenaPushStruct(gameStateArena, GameState);
gGameState = params->GameState = gameState;
gameState->TotalArena = gameStateArena;
gameState->Mode = GameMode_Editor;
gameState->TotalTime = 0.0f;
gameState->Score = 0;
printf("Game Arena Allocated: %p\n", static_cast<void*>(gameState));
printf("Game Arena Allocated: %p\n", (void*)gameState);
// Reserve cameras. Lets go with 4 for now
ReserveCamera(4);
#if JULIET_DEBUG
UnitTest::WorldUnitTest();
UnitTest_WorldUnitTest();
#endif
// Bootstrap world
auto* worldArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "World Arena" });
World* world = ArenaPushStruct<World>(worldArena JULIET_DEBUG_PARAM("World"));
ArenaParams worldParams = { .ReserveSize = Megabytes(1), .Name = "World Arena" };
Arena* worldArena = ArenaAllocate(worldParams);
World* world = ArenaPushStructTag(worldArena, World, "World");
gameState->World = world;
InitWorld(gameState->World, worldArena);
// Entity Use case
InitEntityManager(gameState->World);
auto& manager = GetEntityManager();
EntityManager* manager = GetEntityManager();
NonNullPtr mesh = MakeEntity<Inert>(manager, 1.f, 2.f, 0.f);
Inert* mesh = MakeEntity(Inert, manager, 1.f, 2.f, 0.f);
Assert(mesh != NULL);
MeshAssetID cubeAsset = GetCubePrimitiveMeshAssetID();
MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, MatrixIdentity());
Matrix identity = MatrixIdentity();
MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, &identity);
mesh->MeshInstance = meshInst;
NonNullPtr mesh2 = MakeEntity<Inert>(manager, 4.f, 0.f, 2.f);
Inert* mesh2 = MakeEntity(Inert, manager, 4.f, 0.f, 2.f);
Assert(mesh2 != NULL);
MeshInstanceID meshInst2 = CreateMeshInstance(cubeAsset, 0, MatrixIdentity());
MeshInstanceID meshInst2 = CreateMeshInstance(cubeAsset, 0, &identity);
mesh2->MeshInstance = meshInst2;
// Summer at 2pm lighting
@@ -97,64 +103,64 @@ extern "C" JULIET_API void __cdecl GameUpdate(GameData* params, [[maybe_unused]]
#endif
GameMode previousFrameMode = gGameState->Mode;
if (IsKeyPressed(ScanCode::F1))
if (IsKeyPressed(ScanCode_F1))
{
if (previousFrameMode == GameMode::Play)
if (previousFrameMode == GameMode_Play)
{
gGameState->Mode = GameMode::Debug;
gGameState->Mode = GameMode_Debug;
}
else if (previousFrameMode == GameMode::Debug)
else if (previousFrameMode == GameMode_Debug)
{
gGameState->Mode = GameMode::Play;
gGameState->Mode = GameMode_Play;
}
}
if (gGameState->Mode == GameMode::Editor)
if (gGameState->Mode == GameMode_Editor)
{
if (IsKeyPressed(ScanCode::F5))
if (IsKeyPressed(ScanCode_F5))
{
gGameState->Mode = GameMode::Play;
gGameState->Mode = GameMode_Play;
}
#if JULIET_EDITOR
RenderWorldEditorUI(*gGameState->World);
RenderWorldEditorUI(gGameState->World);
#endif
}
if (gGameState->Mode == GameMode::Play)
if (gGameState->Mode == GameMode_Play)
{
if (IsKeyPressed(ScanCode::Escape))
if (IsKeyPressed(ScanCode_Escape))
{
gGameState->Mode = GameMode::Editor;
gGameState->Mode = GameMode_Editor;
}
// update game
}
auto& manager = GetEntityManager();
EntityManager* manager = GetEntityManager();
UpdateEntityManager(manager);
if (gGameState->Mode == GameMode::Debug)
if (gGameState->Mode == GameMode_Debug)
{
if (previousFrameMode == GameMode::Play)
if (previousFrameMode == GameMode_Play)
{
ActivateDebugController();
}
if (IsKeyPressed(ScanCode::Escape))
if (IsKeyPressed(ScanCode_Escape))
{
gGameState->Mode = GameMode::Editor;
gGameState->Mode = GameMode_Editor;
}
UpdateDebugController(deltaTime);
#if JULIET_DEBUG
ImGui::Begin("Debug");
ImGui_Begin("Debug", NULL, ImGuiWindowFlags_None);
RenderImGuiDebugController(deltaTime);
ImGui::End();
ImGui_End();
#endif
}
if (gGameState->Mode != GameMode::Debug && previousFrameMode == GameMode::Debug)
if (gGameState->Mode != GameMode_Debug && previousFrameMode == GameMode_Debug)
{
DeactivateDebugController();
}
+13 -11
View File
@@ -3,25 +3,27 @@
#include <Core/Memory/MemoryArena.h>
#include <Data/World.h>
struct EntityManager;
typedef struct EntityManager EntityManager;
enum class GameMode
typedef uint32 GameMode;
enum
{
Editor,
Play,
Debug
GameMode_Editor = 0,
GameMode_Play,
GameMode_Debug
};
typedef struct GameState GameState;
struct GameState
{
Arena* TotalArena = nullptr;
Arena* TotalArena;
World* World = nullptr;
World* World;
GameMode Mode = GameMode::Editor;
GameMode Mode;
float TotalTime = 0.0f;
int Score = 0;
float TotalTime;
int Score;
};
[[nodiscard]] extern GameState* GetGameState();
extern GameState* GetGameState(void);
-658
View File
@@ -1,658 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
</Filter>
<Filter Include="src\Core">
</Filter>
<Filter Include="src\Core\Application">
</Filter>
<Filter Include="src\Core\Common">
</Filter>
<Filter Include="src\Core\Container">
</Filter>
<Filter Include="src\Core\HAL">
</Filter>
<Filter Include="src\Core\HAL\Display">
</Filter>
<Filter Include="src\Core\HAL\Display\Win32">
</Filter>
<Filter Include="src\Core\HAL\DynLib">
</Filter>
<Filter Include="src\Core\HAL\DynLib\Win32">
</Filter>
<Filter Include="src\Core\HAL\Event">
</Filter>
<Filter Include="src\Core\HAL\Filesystem">
</Filter>
<Filter Include="src\Core\HAL\Filesystem\Win32">
</Filter>
<Filter Include="src\Core\HAL\IO">
</Filter>
<Filter Include="src\Core\HAL\IO\Win32">
</Filter>
<Filter Include="src\Core\HAL\OS">
</Filter>
<Filter Include="src\Core\HAL\OS\Win32">
</Filter>
<Filter Include="src\Core\HotReload">
</Filter>
<Filter Include="src\Core\HotReload\Win32">
</Filter>
<Filter Include="src\Core\ImGui">
</Filter>
<Filter Include="src\Core\Logging">
</Filter>
<Filter Include="src\Core\Math">
</Filter>
<Filter Include="src\Core\Memory">
</Filter>
<Filter Include="src\Core\Networking">
</Filter>
<Filter Include="src\Core\Networking\Win32">
</Filter>
<Filter Include="src\Engine">
</Filter>
<Filter Include="src\Engine\Debug">
</Filter>
<Filter Include="src\Graphics">
</Filter>
<Filter Include="src\Graphics\D3D12">
</Filter>
<Filter Include="src\Graphics\D3D12\AgilitySDK">
</Filter>
<Filter Include="src\Graphics\D3D12\AgilitySDK\d3dx12">
</Filter>
<Filter Include="src\UnitTest">
</Filter>
<Filter Include="src\UnitTest\Container">
</Filter>
<Filter Include="include">
</Filter>
<Filter Include="include\Core">
</Filter>
<Filter Include="include\Core\Application">
</Filter>
<Filter Include="include\Core\Common">
</Filter>
<Filter Include="include\Core\Container">
</Filter>
<Filter Include="include\Core\HAL">
</Filter>
<Filter Include="include\Core\HAL\Display">
</Filter>
<Filter Include="include\Core\HAL\DynLib">
</Filter>
<Filter Include="include\Core\HAL\Event">
</Filter>
<Filter Include="include\Core\HAL\Filesystem">
</Filter>
<Filter Include="include\Core\HAL\IO">
</Filter>
<Filter Include="include\Core\HAL\Keyboard">
</Filter>
<Filter Include="include\Core\HAL\Mouse">
</Filter>
<Filter Include="include\Core\HAL\OS">
</Filter>
<Filter Include="include\Core\HotReload">
</Filter>
<Filter Include="include\Core\ImGui">
</Filter>
<Filter Include="include\Core\Logging">
</Filter>
<Filter Include="include\Core\Math">
</Filter>
<Filter Include="include\Core\Memory">
</Filter>
<Filter Include="include\Core\Networking">
</Filter>
<Filter Include="include\Core\Thread">
</Filter>
<Filter Include="include\Engine">
</Filter>
<Filter Include="include\Engine\Debug">
</Filter>
<Filter Include="include\Graphics">
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Core\Application\ApplicationManager.cpp">
<Filter>src\Core\Application</Filter>
</ClCompile>
<ClCompile Include="src\Core\Common\CoreUtils.cpp">
<Filter>src\Core\Common</Filter>
</ClCompile>
<ClCompile Include="src\Core\Common\String.cpp">
<Filter>src\Core\Common</Filter>
</ClCompile>
<ClCompile Include="src\Core\Container\Vector.cpp">
<Filter>src\Core\Container</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Display\Display.cpp">
<Filter>src\Core\HAL\Display</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayDevice.cpp">
<Filter>src\Core\HAL\Display\Win32</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.cpp">
<Filter>src\Core\HAL\Display\Win32</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Display\Win32\Win32Window.cpp">
<Filter>src\Core\HAL\Display\Win32</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\DynLib\Win32\DynamicLibrary.cpp">
<Filter>src\Core\HAL\DynLib\Win32</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Event\Keyboard.cpp">
<Filter>src\Core\HAL\Event</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Event\KeyboardMapping.cpp">
<Filter>src\Core\HAL\Event</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Event\Mouse.cpp">
<Filter>src\Core\HAL\Event</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Event\SystemEvent.cpp">
<Filter>src\Core\HAL\Event</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Event\WindowEvent.cpp">
<Filter>src\Core\HAL\Event</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Filesystem\Filesystem.cpp">
<Filter>src\Core\HAL\Filesystem</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\Filesystem\Win32\Win32Filesystem.cpp">
<Filter>src\Core\HAL\Filesystem\Win32</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\IO\IOStream.cpp">
<Filter>src\Core\HAL\IO</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\IO\Win32\Win32IOStream.cpp">
<Filter>src\Core\HAL\IO\Win32</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\OS\OS.cpp">
<Filter>src\Core\HAL\OS</Filter>
</ClCompile>
<ClCompile Include="src\Core\HAL\OS\Win32\Win32OS.cpp">
<Filter>src\Core\HAL\OS\Win32</Filter>
</ClCompile>
<ClCompile Include="src\Core\HotReload\HotReload.cpp">
<Filter>src\Core\HotReload</Filter>
</ClCompile>
<ClCompile Include="src\Core\HotReload\Win32\Win32HotReload.cpp">
<Filter>src\Core\HotReload\Win32</Filter>
</ClCompile>
<ClCompile Include="src\Core\ImGui\ImGuiService.cpp">
<Filter>src\Core\ImGui</Filter>
</ClCompile>
<ClCompile Include="src\Core\ImGui\ImGuiTests.cpp">
<Filter>src\Core\ImGui</Filter>
</ClCompile>
<ClCompile Include="src\Core\Juliet.cpp">
<Filter>src\Core</Filter>
</ClCompile>
<ClCompile Include="src\Core\Logging\LogManager.cpp">
<Filter>src\Core\Logging</Filter>
</ClCompile>
<ClCompile Include="src\Core\Math\MathRound.cpp">
<Filter>src\Core\Math</Filter>
</ClCompile>
<ClCompile Include="src\Core\Memory\Allocator.cpp">
<Filter>src\Core\Memory</Filter>
</ClCompile>
<ClCompile Include="src\Core\Memory\MemoryArena.cpp">
<Filter>src\Core\Memory</Filter>
</ClCompile>
<ClCompile Include="src\Core\Memory\MemoryArenaDebug.cpp">
<Filter>src\Core\Memory</Filter>
</ClCompile>
<ClCompile Include="src\Core\Memory\MemoryArenaTests.cpp">
<Filter>src\Core\Memory</Filter>
</ClCompile>
<ClCompile Include="src\Core\Memory\ScratchArena.cpp">
<Filter>src\Core\Memory</Filter>
</ClCompile>
<ClCompile Include="src\Core\Networking\NetworkPacket.cpp">
<Filter>src\Core\Networking</Filter>
</ClCompile>
<ClCompile Include="src\Core\Networking\Socket.cpp">
<Filter>src\Core\Networking</Filter>
</ClCompile>
<ClCompile Include="src\Core\Networking\TcpListener.cpp">
<Filter>src\Core\Networking</Filter>
</ClCompile>
<ClCompile Include="src\Core\Networking\TcpSocket.cpp">
<Filter>src\Core\Networking</Filter>
</ClCompile>
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp">
<Filter>src\Core\Networking\Win32</Filter>
</ClCompile>
<ClCompile Include="src\Core\PCH.cpp">
<Filter>src\Core</Filter>
</ClCompile>
<ClCompile Include="src\Engine\Debug\MemoryDebugger.cpp">
<Filter>src\Engine\Debug</Filter>
</ClCompile>
<ClCompile Include="src\Engine\Engine.cpp">
<Filter>src\Engine</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_property_format_table.cpp">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12Buffer.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12CommandList.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12Common.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12DescriptorHeap.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12GraphicsDevice.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12GraphicsPipeline.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12InternalTests.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12RenderPass.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12Shader.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12SwapChain.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12Synchronization.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12Texture.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\D3D12\D3D12Utils.cpp">
<Filter>src\Graphics\D3D12</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\DebugDisplayRenderer.cpp">
<Filter>src\Graphics</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\Graphics.cpp">
<Filter>src\Graphics</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\ImGuiRenderer.cpp">
<Filter>src\Graphics</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\Mesh.cpp">
<Filter>src\Graphics</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\MeshRenderer.cpp">
<Filter>src\Graphics</Filter>
</ClCompile>
<ClCompile Include="src\Graphics\SkyboxRenderer.cpp">
<Filter>src\Graphics</Filter>
</ClCompile>
<ClCompile Include="src\UnitTest\Container\VectorUnitTest.cpp">
<Filter>src\UnitTest\Container</Filter>
</ClCompile>
<ClCompile Include="src\UnitTest\RunUnitTests.cpp">
<Filter>src\UnitTest</Filter>
</ClCompile>
<ClInclude Include="include\Core\Application\ApplicationManager.h">
<Filter>include\Core\Application</Filter>
</ClInclude>
<ClInclude Include="include\Core\Application\IApplication.h">
<Filter>include\Core\Application</Filter>
</ClInclude>
<ClInclude Include="include\Core\Common\CoreTypes.h">
<Filter>include\Core\Common</Filter>
</ClInclude>
<ClInclude Include="include\Core\Common\CoreUtils.h">
<Filter>include\Core\Common</Filter>
</ClInclude>
<ClInclude Include="include\Core\Common\CRC32.h">
<Filter>include\Core\Common</Filter>
</ClInclude>
<ClInclude Include="include\Core\Common\EnumUtils.h">
<Filter>include\Core\Common</Filter>
</ClInclude>
<ClInclude Include="include\Core\Common\NonNullPtr.h">
<Filter>include\Core\Common</Filter>
</ClInclude>
<ClInclude Include="include\Core\Common\String.h">
<Filter>include\Core\Common</Filter>
</ClInclude>
<ClInclude Include="include\Core\Container\Vector.h">
<Filter>include\Core\Container</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\Display\Display.h">
<Filter>include\Core\HAL\Display</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\DynLib\DynamicLibrary.h">
<Filter>include\Core\HAL\DynLib</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\Event\SystemEvent.h">
<Filter>include\Core\HAL\Event</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\Filesystem\Filesystem.h">
<Filter>include\Core\HAL\Filesystem</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\IO\IOStream.h">
<Filter>include\Core\HAL\IO</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\Keyboard\Keyboard.h">
<Filter>include\Core\HAL\Keyboard</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\Keyboard\KeyCode.h">
<Filter>include\Core\HAL\Keyboard</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\Keyboard\ScanCode.h">
<Filter>include\Core\HAL\Keyboard</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\Mouse\Mouse.h">
<Filter>include\Core\HAL\Mouse</Filter>
</ClInclude>
<ClInclude Include="include\Core\HAL\OS\OS.h">
<Filter>include\Core\HAL\OS</Filter>
</ClInclude>
<ClInclude Include="include\Core\HotReload\HotReload.h">
<Filter>include\Core\HotReload</Filter>
</ClInclude>
<ClInclude Include="include\Core\ImGui\ImGuiService.h">
<Filter>include\Core\ImGui</Filter>
</ClInclude>
<ClInclude Include="include\Core\ImGui\ImGuiTests.h">
<Filter>include\Core\ImGui</Filter>
</ClInclude>
<ClInclude Include="include\Core\JulietInit.h">
<Filter>include\Core</Filter>
</ClInclude>
<ClInclude Include="include\Core\Logging\LogManager.h">
<Filter>include\Core\Logging</Filter>
</ClInclude>
<ClInclude Include="include\Core\Logging\LogTypes.h">
<Filter>include\Core\Logging</Filter>
</ClInclude>
<ClInclude Include="include\Core\Main.h">
<Filter>include\Core</Filter>
</ClInclude>
<ClInclude Include="include\Core\Math\MathUtils.h">
<Filter>include\Core\Math</Filter>
</ClInclude>
<ClInclude Include="include\Core\Math\Matrix.h">
<Filter>include\Core\Math</Filter>
</ClInclude>
<ClInclude Include="include\Core\Math\Shape.h">
<Filter>include\Core\Math</Filter>
</ClInclude>
<ClInclude Include="include\Core\Math\Vector.h">
<Filter>include\Core\Math</Filter>
</ClInclude>
<ClInclude Include="include\Core\Memory\Allocator.h">
<Filter>include\Core\Memory</Filter>
</ClInclude>
<ClInclude Include="include\Core\Memory\MemoryArena.h">
<Filter>include\Core\Memory</Filter>
</ClInclude>
<ClInclude Include="include\Core\Memory\MemoryArenaDebug.h">
<Filter>include\Core\Memory</Filter>
</ClInclude>
<ClInclude Include="include\Core\Memory\ScratchArena.h">
<Filter>include\Core\Memory</Filter>
</ClInclude>
<ClInclude Include="include\Core\Memory\Utils.h">
<Filter>include\Core\Memory</Filter>
</ClInclude>
<ClInclude Include="include\Core\Networking\IPAddress.h">
<Filter>include\Core\Networking</Filter>
</ClInclude>
<ClInclude Include="include\Core\Networking\NetworkPacket.h">
<Filter>include\Core\Networking</Filter>
</ClInclude>
<ClInclude Include="include\Core\Networking\Socket.h">
<Filter>include\Core\Networking</Filter>
</ClInclude>
<ClInclude Include="include\Core\Networking\SocketHandle.h">
<Filter>include\Core\Networking</Filter>
</ClInclude>
<ClInclude Include="include\Core\Networking\TcpListener.h">
<Filter>include\Core\Networking</Filter>
</ClInclude>
<ClInclude Include="include\Core\Networking\TcpSocket.h">
<Filter>include\Core\Networking</Filter>
</ClInclude>
<ClInclude Include="include\Core\PCH.h">
<Filter>include\Core</Filter>
</ClInclude>
<ClInclude Include="include\Core\Thread\Mutex.h">
<Filter>include\Core\Thread</Filter>
</ClInclude>
<ClInclude Include="include\Core\Thread\Thread.h">
<Filter>include\Core\Thread</Filter>
</ClInclude>
<ClInclude Include="include\Engine\Class.h">
<Filter>include\Engine</Filter>
</ClInclude>
<ClInclude Include="include\Engine\Debug\MemoryDebugger.h">
<Filter>include\Engine\Debug</Filter>
</ClInclude>
<ClInclude Include="include\Engine\Engine.h">
<Filter>include\Engine</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\Camera.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\Colors.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\DebugDisplay.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\Graphics.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\GraphicsBuffer.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\GraphicsConfig.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\GraphicsPipeline.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\ImGuiRenderer.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\Lighting.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\Mesh.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\MeshRenderer.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\PushConstants.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\RenderPass.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\Shader.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\SkyboxRenderer.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\Texture.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Graphics\VertexData.h">
<Filter>include\Graphics</Filter>
</ClInclude>
<ClInclude Include="include\Juliet.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Display\DisplayDevice.h">
<Filter>src\Core\HAL\Display</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Display\Display_Private.h">
<Filter>src\Core\HAL\Display</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.h">
<Filter>src\Core\HAL\Display\Win32</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Display\Win32\Win32Window.h">
<Filter>src\Core\HAL\Display\Win32</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Display\Window.h">
<Filter>src\Core\HAL\Display</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Event\KeyboardMapping.h">
<Filter>src\Core\HAL\Event</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Event\Keyboard_Private.h">
<Filter>src\Core\HAL\Event</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Event\Mouse_Private.h">
<Filter>src\Core\HAL\Event</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Event\Win32ScanCode.h">
<Filter>src\Core\HAL\Event</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h">
<Filter>src\Core\HAL\Event</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Platform.h">
<Filter>src\Core\HAL\Filesystem</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Private.h">
<Filter>src\Core\HAL\Filesystem</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\IO\IOStream_Private.h">
<Filter>src\Core\HAL\IO</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\OS\OS_Private.h">
<Filter>src\Core\HAL\OS</Filter>
</ClInclude>
<ClInclude Include="src\Core\HAL\Win32.h">
<Filter>src\Core\HAL</Filter>
</ClInclude>
<ClInclude Include="src\Core\Math\Math_Private.h">
<Filter>src\Core\Math</Filter>
</ClInclude>
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h">
<Filter>src\Core\Networking</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12.h">
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12compatibility.h">
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12sdklayers.h">
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12shader.h">
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3d12video.h">
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dcommon.h">
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_barriers.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_check_feature_support.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_core.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_default.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_pipeline_state_stream.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_property_format_table.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_render_pass.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_resource_helpers.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_root_signature.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\d3dx12\d3dx12_state_object.h">
<Filter>src\Graphics\D3D12\AgilitySDK\d3dx12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\dxgiformat.h">
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12Buffer.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12CommandList.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12Common.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12DescriptorHeap.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12GraphicsDevice.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12GraphicsPipeline.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12Includes.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12InternalTests.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12RenderPass.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12Shader.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12SwapChain.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12Synchronization.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12Texture.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\D3D12Utils.h">
<Filter>src\Graphics\D3D12</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\GraphicsDevice.h">
<Filter>src\Graphics</Filter>
</ClInclude>
<ClInclude Include="src\UnitTest\VectorTestHelper.h">
<Filter>src\UnitTest</Filter>
</ClInclude>
<ClInclude Include="src\Graphics\D3D12\AgilitySDK\D3D12TokenizedProgramFormat.hpp">
<Filter>src\Graphics\D3D12\AgilitySDK</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -1,9 +0,0 @@
#pragma once
#include <Core/Application/IApplication.h>
#include <Juliet.h>
enum class JulietInit_Flags : uint8;
struct Arena;
extern JULIET_API void StartApplication(IApplication& app, JulietInit_Flags flags);
@@ -1,29 +0,0 @@
#pragma once
#include <Core/Common/NonNullPtr.h>
struct Camera;
struct RenderPass;
struct CommandList;
struct Texture;
struct ColorTargetInfo;
struct DepthStencilTargetInfo;
struct Arena;
class IApplication
{
public:
virtual ~IApplication() = default;
virtual void Init(NonNullPtr<Arena> arena) = 0;
virtual void Shutdown() = 0;
virtual void Update(float deltaTime) = 0;
virtual bool IsRunning() = 0;
// Accessors for Engine Systems
virtual struct Window* GetPlatformWindow() = 0;
virtual struct GraphicsDevice* GetGraphicsDevice() = 0;
// Render Lifecycle (Engine-Managed Render Loop)
virtual ColorTargetInfo GetColorTargetInfo(Texture* swapchainTexture) = 0;
virtual DepthStencilTargetInfo* GetDepthTargetInfo() = 0;
};
+41 -43
View File
@@ -1,62 +1,60 @@
#pragma once
#pragma once
#include <Core/Common/CoreUtils.h>
#include <Core/Common/String.h>
// From https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
namespace details
{
constexpr uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a,
0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074,
0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525,
0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76,
0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6,
0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7,
0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330,
0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
}
global const uint32 g_crc32_tab[256] = {
0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u, 0x0edb8832u,
0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u, 0x1db71064u, 0x6ab020f2u,
0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u, 0x136c9856u, 0x646ba8c0u, 0xfd62f97au,
0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u, 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u,
0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu, 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u,
0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u, 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u,
0xcfba9599u, 0xb8bda50fu, 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu,
0xb6662d3du, 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u,
0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u, 0x6b6b51f4u,
0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u, 0x65b0d9c6u, 0x12b7e950u,
0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u, 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u,
0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu, 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u,
0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u, 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u,
0x206f85b3u, 0xb966d409u, 0xce61e49fu, 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u,
0xb7bd5c3bu, 0xc0ba6cadu, 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u,
0x73dc1683u, 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u, 0xfed41b76u,
0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u, 0xd6d6a3e8u, 0xa1d1937eu,
0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu, 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u,
0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u, 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u,
0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu, 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u,
0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du, 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu,
0x72076785u, 0x05005713u, 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u,
0x0bdbdf21u, 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u, 0xa00ae278u,
0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu, 0xaed16a4au, 0xd9d65adcu,
0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u, 0xbdbdf21cu, 0xcabac28au, 0x53b39330u,
0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu, 0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u,
0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du
};
constexpr uint32 crc32(const char* str, size_t length)
static inline uint32 crc32_bytes(const char* str, size_t length)
{
Assert(str && length > 0);
Assert(str != NULL && length > 0);
const char* p = str;
uint32_t crc = ~0U;
uint32 crc = ~0U;
while (length--)
{
crc = details::crc32_tab[(crc ^ static_cast<uint8>(*p++)) & 0xFF] ^ (crc >> 8);
crc = g_crc32_tab[(crc ^ (uint8)(*p++)) & 0xFFu] ^ (crc >> 8);
}
return crc ^ ~0U;
}
constexpr uint32 crc32(String str)
static inline uint32 crc32_str(String str)
{
return crc32(str.Str, str.Size);
return crc32_bytes(str.Str, str.Size);
}
consteval uint32 operator""_crc32(const char* str, size_t length)
static inline uint32 crc32_cstr(const char* str)
{
return crc32(str, length);
return crc32_bytes(str, StringLengthCStr(str));
}
+49 -46
View File
@@ -1,65 +1,68 @@
#pragma once
using uint8 = uint8_t;
using uint16 = uint16_t;
using uint32 = uint32_t;
using uint64 = uint64_t;
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
using int8 = int8_t;
using int16 = int16_t;
using int32 = int32_t;
using int64 = int64_t;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
using Byte = std::byte;
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
using size_t = std::size_t;
using index_t = size_t;
typedef uint8 bool8;
typedef uint16 bool16;
typedef uint32 bool32;
typedef uint64 bool64;
#ifndef __cplusplus
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#endif
typedef uint8 Byte;
typedef size_t index_t;
typedef struct ByteBuffer ByteBuffer;
struct ByteBuffer
{
Byte* Data;
size_t Size;
};
using ptrdiff_t = decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr));
typedef void (*FunctionPtr)(void);
using FunctionPtr = auto (*)(void) -> void;
#define uint8Max ((uint8)0xFFu)
#define uint16Max ((uint16)0xFFFFu)
#define uint32Max ((uint32)0xFFFFFFFFu)
#define uint64Max ((uint64)0xFFFFFFFFFFFFFFFFull)
// Limits
template <typename Type>
consteval Type MaxValueOf()
{
return std::numeric_limits<Type>::max();
}
constexpr uint8 uint8Max = MaxValueOf<uint8>();
constexpr uint16 uint16Max = MaxValueOf<uint16>();
constexpr uint32 uint32Max = MaxValueOf<uint32>();
constexpr uint64 uint64Max = MaxValueOf<uint64>();
#define int8Max ((int8)0x7F)
#define int16Max ((int16)0x7FFF)
#define int32Max ((int32)0x7FFFFFFF)
#define int64Max ((int64)0x7FFFFFFFFFFFFFFFll)
constexpr int8 int8Max = MaxValueOf<int8>();
constexpr int16 int16Max = MaxValueOf<int16>();
constexpr int32 int32Max = MaxValueOf<int32>();
constexpr int64 int64Max = MaxValueOf<int64>();
#define indexMax ((index_t)SIZE_MAX)
constexpr index_t indexMax = MaxValueOf<index_t>();
#define uint8Min ((uint8)0u)
#define uint16Min ((uint16)0u)
#define uint32Min ((uint32)0u)
#define uint64Min ((uint64)0ull)
template <typename Type>
consteval Type MinValueOf()
{
return std::numeric_limits<Type>::lowest();
}
#define int8Min ((int8)(-128))
#define int16Min ((int16)(-32768))
#define int32Min ((int32)(-2147483647 - 1))
#define int64Min ((int64)(-9223372036854775807ll - 1ll))
constexpr uint8 uint8Min = MinValueOf<uint8>();
constexpr uint16 uint16Min = MinValueOf<uint16>();
constexpr uint32 uint32Min = MinValueOf<uint32>();
constexpr uint64 uint64Min = MinValueOf<uint64>();
#define indexMin ((index_t)0u)
constexpr int8 int8Min = MinValueOf<int8>();
constexpr int16 int16Min = MinValueOf<int16>();
constexpr int32 int32Min = MinValueOf<int32>();
constexpr int64 int64Min = MinValueOf<int64>();
constexpr index_t indexMin = MinValueOf<index_t>();
#define Kilobytes(value) value * 1024
#define Megabytes(value) Kilobytes(value) * 1024
#define Kilobytes(value) ((uint64)(value) * 1024ull)
#define Megabytes(value) (Kilobytes(value) * 1024ull)
+57 -92
View File
@@ -1,10 +1,15 @@
#pragma once
#pragma once
#include <Juliet.h>
#include <Core/Common/CoreTypes.h>
#define global static
#define internal static
#define Glue_(A, B) A##B
#define Glue(A, B) Glue_(A, B)
#define StaticAssert(C, ID) global uint8 Glue(ID, __LINE__)[(C) ? 1 : -1]
// 1. Stringify helpers
#define JULIET_STR(x) #x
#define JULIET_TOSTRING(x) JULIET_STR(x)
@@ -37,10 +42,8 @@
#endif
#if defined(_MSC_VER)
// MSVC specific intrinsic
#define JULIET_PLATFORM_BREAK() (__nop(), __debugbreak())
#elif defined(__clang__) || defined(__GNUC__)
// Clang/GCC specific intrinsic
#define JULIET_PLATFORM_BREAK() __builtin_trap()
#else
#include <signal.h>
@@ -49,18 +52,14 @@
#if JULIET_DEBUG
#define JULIET_ASSERT_INTERNAL(expression, message) \
JULIET_WARNING_PUSH \
JULIET_SUPPRESS_CLANG("-Wextra-semi-stmt") \
JULIET_SUPPRESS_MSVC(4127) \
JULIET_SUPPRESS_MSVC(4548) \
do \
{ \
if (!(expression)) [[unlikely]] \
if (!(expression)) \
{ \
JulietAssert(#expression, message); \
JulietAssert(#expression, message, __FILE__, __func__, (uint32)__LINE__, 0); \
} \
} \
JULIET_WARNING_POP \
static_assert(true, "")
while (0)
#define AssertHR(hr_expression, message) \
do \
@@ -68,7 +67,7 @@
long hr_val = (hr_expression); \
if (hr_val < 0) \
{ \
JulietAssert(#hr_expression, message, std::source_location::current(), hr_val); \
JulietAssert(#hr_expression, message, __FILE__, __func__, (uint32)__LINE__, hr_val); \
} \
} \
while (0)
@@ -80,7 +79,7 @@
#define Unimplemented() \
do \
{ \
JulietAssert("UNIMPLEMENTED", "This code path is not yet functional."); \
JulietAssert("UNIMPLEMENTED", "This code path is not yet functional.", __FILE__, __func__, (uint32)__LINE__, 0); \
} \
while (0)
@@ -90,85 +89,60 @@
#define Unimplemented() ((void)0)
#endif
JULIET_API extern void JulietAssert(const char* expression, const char* message,
std::source_location location = std::source_location::current(), long handleResult = 0);
JULIET_API extern void JulietAssert(const char* expression, const char* message, const char* file, const char* function,
uint32 line, long handle_result);
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
inline void ZeroSize(size_t size, void* ptr)
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), (Pointer))
static inline void ZeroSize(size_t size, void* ptr)
{
auto Byte = (uint8*)ptr;
uint8* byte_ptr = (uint8*)ptr;
while (size--)
{
*Byte++ = 0;
*byte_ptr++ = 0;
}
}
#define Restrict __restrict
template <class Function>
class DeferredFunction
static inline bool8 IsValidByteBuffer(ByteBuffer buffer)
{
public:
explicit DeferredFunction(const Function& otherFct) noexcept
: Callback(otherFct)
{
}
explicit DeferredFunction(Function&& otherFct) noexcept
: Callback(std::move(otherFct))
{
}
~DeferredFunction() noexcept { Callback(); }
DeferredFunction(const DeferredFunction&) = delete;
DeferredFunction(const DeferredFunction&&) = delete;
void operator=(const DeferredFunction&) = delete;
void operator=(DeferredFunction&&) = delete;
private:
Function Callback;
};
template <class Function>
auto Defer(Function&& fct) noexcept
{
return DeferredFunction<std::decay_t<Function>>{ std::forward<Function>(fct) };
return (buffer.Size > 0 && buffer.Data != NULL);
}
inline bool IsValid(ByteBuffer buffer)
extern JULIET_API void FreeByteBuffer(ByteBuffer* buffer);
static inline bool8 IsPow2(uint64 x)
{
return buffer.Size > 0 && buffer.Data;
return (x != 0) && ((x & (x - 1)) == 0);
}
extern JULIET_API void Free(ByteBuffer& buffer);
template <std::integral T>
[[nodiscard]] constexpr T AlignPow2(T x, T alignment)
static inline uint64 AlignPow2(uint64 x, uint64 alignment)
{
// Safety Check:
Assert(std::has_single_bit(static_cast<size_t>(alignment)));
Assert(IsPow2(alignment));
return (x + alignment - 1) & ~(alignment - 1);
}
template <typename T>
inline void Swap(T* Restrict a, T* Restrict b)
static inline void SwapMemory(void* Restrict a, void* Restrict b, size_t elem_size)
{
T temp = std::move(*a);
*a = std::move(*b);
*b = std::move(temp);
uint8* pa = (uint8*)a;
uint8* pb = (uint8*)b;
for (size_t i = 0; i < elem_size; ++i)
{
uint8 tmp = pa[i];
pa[i] = pb[i];
pb[i] = tmp;
}
}
// Move to another file dedicated to those
#if defined(__clang__)
#define COMPILER_CLANG 1
#elif defined(_MSC_VER)
#define COMPILER_MSVC 1
#endif
// Undef anything not defined
#if !defined(COMPILER_CLANG)
#define COMPILER_CLANG 0
#endif
@@ -186,42 +160,33 @@ inline void Swap(T* Restrict a, T* Restrict b)
#error AlignOf not defined for this compiler.
#endif
template <typename T>
[[nodiscard]] constexpr const char* GetTypeName()
{
#if COMPILER_CLANG
return __PRETTY_FUNCTION__;
#elif COMPILER_MSVC
return __FUNCSIG__;
#elif COMPILER_GCC
return __PRETTY_FUNCTION__;
#if COMPILER_MSVC || (COMPILER_CLANG && defined(_MSC_VER))
#define ThreadLocal __declspec(thread)
#else
return "UnknownType";
#define ThreadLocal __thread
#endif
}
inline uint16 safe_cast_uint16(uint32 value)
static inline uint16 safe_cast_uint16(uint32 value)
{
Assert(value <= uint16Max);
uint16 result = (uint16)value;
return result;
}
const uint32 bitmask1 = 0b0000'0001;
const uint32 bitmask2 = 0b0000'0011;
const uint32 bitmask3 = 0b0000'0111;
const uint32 bitmask4 = 0b0000'1111;
const uint32 bitmask5 = 0b0001'1111;
const uint32 bitmask6 = 0b0011'1111;
const uint32 bitmask7 = 0b0111'1111;
const uint32 bitmask8 = 0b1111'1111;
const uint32 bitmask9 = 0x0000'01ff;
const uint32 bitmask10 = 0x0000'03ff;
const uint32 bitmask11 = 0x0000'07ff;
const uint32 bitmask12 = 0x0000'0fff;
const uint32 bitmask13 = 0x0000'1fff;
const uint32 bitmask14 = 0x0000'3fff;
const uint32 bitmask15 = 0x0000'7fff;
const uint32 bitmask16 = 0x0000'ffff;
// ...
const uint32 bitmask32 = 0xffff'ffff;
#define bitmask1 0x00000001u
#define bitmask2 0x00000003u
#define bitmask3 0x00000007u
#define bitmask4 0x0000000fu
#define bitmask5 0x0000001fu
#define bitmask6 0x0000003fu
#define bitmask7 0x0000007fu
#define bitmask8 0x000000ffu
#define bitmask9 0x000001ffu
#define bitmask10 0x000003ffu
#define bitmask11 0x000007ffu
#define bitmask12 0x00000fffu
#define bitmask13 0x00001fffu
#define bitmask14 0x00003fffu
#define bitmask15 0x00007fffu
#define bitmask16 0x0000ffffu
#define bitmask32 0xffffffffu
-86
View File
@@ -1,86 +0,0 @@
#pragma once
template <typename T>
concept IsEnum = std::is_enum_v<T>;
template <IsEnum E>
constexpr E operator~(E lhs) noexcept
{
return static_cast<E>(~static_cast<std::underlying_type_t<E>>(lhs));
}
template <IsEnum E>
constexpr E operator|(E lhs, E rhs) noexcept
{
return static_cast<E>(static_cast<std::underlying_type_t<E>>(lhs) | static_cast<std::underlying_type_t<E>>(rhs));
}
template <IsEnum E>
constexpr E& operator|=(E& lhs, E rhs) noexcept
{
return lhs = (lhs | rhs);
}
template <IsEnum E>
constexpr E operator&(E lhs, E rhs) noexcept
{
return static_cast<E>(static_cast<std::underlying_type_t<E>>(lhs) & static_cast<std::underlying_type_t<E>>(rhs));
}
template <IsEnum E>
constexpr E& operator&=(E& lhs, E rhs) noexcept
{
return lhs = (lhs & rhs);
}
template <IsEnum E>
constexpr E operator^(E lhs, E rhs) noexcept
{
return static_cast<E>(static_cast<std::underlying_type_t<E>>(lhs) ^ static_cast<std::underlying_type_t<E>>(rhs));
}
template <IsEnum E>
constexpr E& operator^=(E& lhs, E rhs) noexcept
{
return lhs = (lhs ^ rhs);
}
template <IsEnum E>
constexpr std::underlying_type_t<E> operator-(E lhs, E rhs) noexcept
{
using T = std::underlying_type_t<E>;
return static_cast<T>(static_cast<T>(lhs) - static_cast<T>(rhs));
}
template <IsEnum E>
constexpr std::underlying_type_t<E> operator+(E lhs, E rhs) noexcept
{
using T = std::underlying_type_t<E>;
return static_cast<T>(static_cast<T>(lhs) + static_cast<T>(rhs));
}
template <IsEnum E>
constexpr E operator-(E lhs, std::underlying_type_t<E> rhs) noexcept
{
using T = std::underlying_type_t<E>;
return static_cast<E>(static_cast<T>(static_cast<T>(lhs) - rhs));
}
template <IsEnum E>
constexpr E operator+(E lhs, std::underlying_type_t<E> rhs) noexcept
{
using T = std::underlying_type_t<E>;
return static_cast<E>(static_cast<T>(static_cast<T>(lhs) + rhs));
}
template <IsEnum E>
constexpr std::underlying_type_t<E> ToUnderlying(E enm) noexcept
{
return static_cast<std::underlying_type_t<E>>(enm);
}
template <IsEnum E>
constexpr E ToEnum(std::underlying_type_t<E> value) noexcept
{
return static_cast<E>(value);
}
-110
View File
@@ -1,110 +0,0 @@
#pragma once
#include <Core/Common/CoreUtils.h>
template <typename Type, typename OtherType>
concept NonNullPtr_Convertible = std::is_convertible_v<OtherType*, Type*>;
template <typename Type, typename OtherType>
concept NonNullPtr_SameType = std::is_same_v<OtherType*, Type*>;
template <typename Type>
class NonNullPtr
{
public:
constexpr NonNullPtr(Type* ptr)
: InternalPtr(ptr)
{
Assert(ptr, "Tried to initialize a NonNullPtr with a null pointer");
}
template <typename OtherType>
requires NonNullPtr_Convertible<OtherType*, Type*>
constexpr NonNullPtr(const NonNullPtr<OtherType>& otherPtr)
: InternalPtr(otherPtr.Get())
{
Assert(InternalPtr, "Fatal Error: Assigned a non null ptr using another NonNullPtr but its was null.");
}
// Assignment
[[nodiscard]] constexpr NonNullPtr& operator=(Type* ptr)
{
Assert(ptr, "Tried to assign a null pointer to a NonNullPtr!");
InternalPtr = ptr;
return *this;
}
template <typename OtherType>
requires NonNullPtr_Convertible<OtherType*, Type*>
[[nodiscard]] constexpr NonNullPtr& operator=(const NonNullPtr<OtherType>& otherPtr)
{
InternalPtr = otherPtr.Get();
return *this;
}
// Accessors
[[nodiscard]] constexpr operator Type*() const
{
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
return InternalPtr;
}
[[nodiscard]] constexpr Type* Get() const
{
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
return InternalPtr;
}
[[nodiscard]] constexpr Type& operator*() const
{
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
return *InternalPtr;
}
[[nodiscard]] constexpr Type* operator->() const
{
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
return InternalPtr;
}
// Comparisons
[[nodiscard]] constexpr bool operator==(const NonNullPtr& otherPtr) const
{
return InternalPtr == otherPtr.InternalPtr;
}
template <typename OtherType>
requires NonNullPtr_SameType<Type, OtherType>
[[nodiscard]] constexpr bool operator==(OtherType* otherRawPtr) const
{
return InternalPtr == otherRawPtr;
}
template <typename OtherType>
requires NonNullPtr_SameType<Type, OtherType>
[[nodiscard]] constexpr friend bool operator==(OtherType* otherRawPtr, const NonNullPtr& nonNullPtr)
{
return otherRawPtr == nonNullPtr.InternalPtr;
}
// Forbid assigning a nullptr at compile time
constexpr NonNullPtr(std::nullptr_t)
: InternalPtr(nullptr)
{
static_assert(sizeof(Type) == 0, "Trying to initialize a NonNullPtr with a nullptr value");
}
[[nodiscard]] constexpr NonNullPtr& operator=(std::nullptr_t)
{
static_assert(sizeof(Type) == 0, "Trying to assign a NonNullPtr with a nullptr value");
return *this;
}
[[nodiscard]] constexpr explicit operator bool() const { return InternalPtr != nullptr; }
private:
Type* InternalPtr;
};
template <typename T>
NonNullPtr(T*) -> NonNullPtr<T>;
+68 -78
View File
@@ -1,22 +1,14 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/CoreTypes.h>
#include <Core/Common/CoreUtils.h>
#include <Core/Math/MathUtils.h>
#include <Core/Memory/Utils.h>
#ifdef global
#undef global
#define RESTORE_GLOBAL
#endif
typedef struct Arena Arena;
#ifdef RESTORE_GLOBAL
#define global static
#undef RESTORE_GLOBAL
#endif
struct Arena;
#define ConstString(str) { const_cast<char*>((str)), sizeof(str) - 1 }
#define ConstString(str) ((String){ (char*)(str), sizeof(str) - 1 })
#define ConstStringInit(str) { (char*)(str), sizeof(str) - 1 }
#define CStr(str) ((str).Str)
#define InplaceString(name, size) \
char name##_[size]; \
@@ -24,55 +16,69 @@ struct Arena;
String name = { name##_, 0 }
// Everything is Little Endian
enum class StringEncoding : uint8
typedef uint8 StringEncoding;
enum
{
Unknown = 0,
ASCII,
LATIN1,
UTF8,
UTF16,
UTF32,
UCS2,
UCS4,
StringEncoding_Unknown = 0,
StringEncoding_ASCII,
StringEncoding_LATIN1,
StringEncoding_UTF8,
StringEncoding_UTF16,
StringEncoding_UTF32,
StringEncoding_UCS2,
StringEncoding_UCS4,
};
// Represents a UTF-8 String.
// Not null terminated.
typedef struct String8 String8;
struct String8
{
char* Str;
size_t Size;
};
using String = String8;
typedef String8 String;
typedef struct String16 String16;
struct String16
{
uint16* Str;
size_t Size;
};
struct StringBuffer : String
typedef struct StringBuffer StringBuffer;
struct StringBuffer
{
union
{
String8 str8;
struct
{
char* Str;
size_t Size;
};
};
size_t Capacity;
};
typedef struct UnicodeDecode UnicodeDecode;
struct UnicodeDecode
{
uint32 Increment;
uint32 Codepoint;
};
constexpr uint32 kInvalidUTF8 = 0xFFFD;
#define kInvalidUTF8 ((uint32)0xFFFDu)
inline size_t StringLength(String str)
static inline size_t StringLength(String str)
{
return str.Size;
}
inline size_t StringLength(const char* str)
static inline size_t StringLengthCStr(const char* str)
{
size_t length = 0;
if (str)
if (str != NULL)
{
while (*str)
{
@@ -84,47 +90,46 @@ inline size_t StringLength(const char* str)
return length;
}
inline bool IsValid(String str)
static inline bool8 IsValidString(String str)
{
return str.Size > 0 && str.Str != nullptr && *str.Str;
return (str.Size > 0 && str.Str != NULL && *str.Str != '\0');
}
inline String WrapString(const char* str)
static inline String WrapString(const char* str)
{
String result = {};
result.Str = const_cast<char*>(str);
result.Size = str ? strlen(str) : 0;
String result = { 0 };
result.Str = (char*)str;
result.Size = (str != NULL) ? strlen(str) : 0;
return result;
}
inline String FindChar(String str, char c)
static inline String FindChar(String str, char c)
{
String result = str;
while (result.Size)
String result = { 0 };
String cursor = str;
while (cursor.Size > 0)
{
if (*result.Str != c)
if (*cursor.Str == c)
{
++result.Str;
--result.Size;
result = cursor;
break;
}
++cursor.Str;
--cursor.Size;
}
else
{
return result;
}
}
return {};
}
inline bool ContainsChar(String str, char c)
static inline bool8 ContainsChar(String str, char c)
{
return IsValid(FindChar(str, c));
return IsValidString(FindChar(str, c));
}
// Return:
// - < 0 if str1 < str2
// - = 0 : Both strings are equals
// - > 0 if str1 > str2
inline int32 StringCompare(String str1, String str2)
static inline int32 StringCompare(String str1, String str2)
{
size_t len1 = StringLength(str1);
size_t len2 = StringLength(str2);
@@ -134,62 +139,47 @@ inline int32 StringCompare(String str1, String str2)
{
if (len1 > len2)
{
return 1;
result = 1;
}
if (len1 < len2)
else if (len1 < len2)
{
return -1;
result = -1;
}
return 0;
}
return result;
}
JULIET_API uint32 StepUTF8(String& inStr);
JULIET_API uint32 StepUTF8(String* inStr);
JULIET_API String FindString(String strLeft, String strRight);
// Case insensitive compare. Supports ASCII only
// TODO: Support UNICODE
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
// Do not allocate anything, you must allocate your out buffer yourself
// TODO: Version taking arena that can allocate
// Do not take String type because we dont know the string encoding we are going from/to
// src and dst will be casted based on the encoding.
// size will correspond to the number of characters
// Will convert \0 character if present.
extern JULIET_API bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst, bool nullTerminate);
extern JULIET_API bool ConvertString(String from, String to, String src, StringBuffer& dst, bool nullTerminate);
extern JULIET_API bool8 ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer* dst, bool8 nullTerminate);
extern JULIET_API bool8 ConvertStringByName(String from, String to, String src, StringBuffer* dst, bool8 nullTerminate);
JULIET_API String StringCopy(NonNullPtr<Arena> arena, String str);
JULIET_API String16 str16_from_8(NonNullPtr<Arena> arena, String8 str);
JULIET_API String StringCopy(Arena* arena, String str);
JULIET_API String16 str16_from_8(Arena* arena, String8 str);
String trim_whitespace(String str);
template <typename... Args>
String Format(NonNullPtr<Arena> arena, const char* formatStr, Args&&... args)
{
std::string result = std::vformat(formatStr, std::make_format_args(args...));
return StringCopy(arena, WrapString(result.c_str()));
}
JULIET_API String StringFormatV(Arena* arena, const char* formatStr, va_list args);
JULIET_API String StringFormat(Arena* arena, const char* formatStr, ...);
#define juliet_snprintf snprintf
#ifdef UNIT_TEST
namespace UnitTest
static inline void UnitTest_TestFindChar(void)
{
inline void TestFindChar()
{
String s1 = ConstString("");
String s2 = ConstString("abcdefabcdef");
String s3 = ConstString("11111111111111111111");
Assert(FindChar(s1, 'x').Str == nullptr);
Assert(FindChar(s2, 'y').Str == nullptr);
Assert(FindChar(s1, 'x').Str == NULL);
Assert(FindChar(s2, 'y').Str == NULL);
Assert(FindChar(s2, 'a').Str - s2.Str == 0);
Assert(FindChar(s2, 'd').Str - s2.Str == 3);
Assert(FindChar(s2, 'f').Str - s2.Str == 5);
Assert(FindChar(s3, '1').Str - s3.Str == 0);
}
} // namespace UnitTest
}
#endif
+70 -93
View File
@@ -2,125 +2,102 @@
#include <Juliet.h>
#include <Core/Common/CRC32.h>
#include <Core/Common/String.h>
#include <Core/HAL/IO/IOStream.h>
#include <Core/Math/Vector.h>
// .jasset
// AssetFile ::= { CommentLine | EmptyLine | PropertyDeclaration } ;
// CommentLine ::= ( "#" | "//" ) { Character } LineEnding ;
// EmptyLine ::= { Whitespace } LineEnding ;
// PropertyDeclaration ::= KeyHeader LineEnding ValueBlock ;
// KeyHeader ::= ";" { Whitespace } Identifier ;
// ValueBlock ::= { ValueLine LineEnding } ;
// ValueLine ::= { Whitespace } ValueString { Whitespace } ;
// LineEnding ::= "\r\n" | "\n" ;
// Identifier ::= [a-zA-Z_][a-zA-Z0-9_]* ;
struct Vector4;
struct IOStream;
struct Arena;
typedef struct IOStream IOStream;
typedef struct Arena Arena;
typedef struct ArchivePropertyNode ArchivePropertyNode;
typedef struct ParsedArchive ParsedArchive;
typedef struct Archive Archive;
struct ArchivePropertyNode
{
String key;
String value;
uint32 key_crc;
bool consumed;
bool8 consumed;
};
struct ParsedArchive
{
ArchivePropertyNode* nodes = nullptr;
uint32 property_count = 0;
ArchivePropertyNode* nodes;
uint32 property_count;
};
struct Archive
{
Arena* arena;
bool loading;
ParsedArchive base = {};
IOStream* stream = nullptr;
bool8 loading;
ParsedArchive base;
IOStream* stream;
// to remove
void* base_ptr = nullptr;
index_t offset = 0;
void* base_ptr;
index_t offset;
};
JULIET_API void serialize(Archive& ar, void* data, size_t size);
JULIET_API void serialize_bytes(Archive* ar, void* data, size_t size);
#define serialize_elem(ar, val) serialize((ar), &(val), sizeof(val))
#define serialize_elem(ar, val) serialize_bytes((ar), &(val), sizeof(val))
JULIET_API ParsedArchive tokenize_archive(NonNullPtr<Arena> arena, ByteBuffer file_buffer);
JULIET_API ArchivePropertyNode* find_property(NonNullPtr<ParsedArchive> archive, uint32 property_crc);
JULIET_API void write_property_header(Archive& archive, String property_name);
JULIET_API ParsedArchive tokenize_archive(Arena* arena, ByteBuffer file_buffer);
JULIET_API ArchivePropertyNode* find_property(ParsedArchive* archive, uint32 property_crc);
JULIET_API void write_property_header(Archive* archive, String property_name);
JULIET_API bool read_prop(Archive& ar, String value_raw, String& value);
JULIET_API void write(NonNullPtr<IOStream> stream, String value);
JULIET_API bool read(const char* buffer, float& value, const char** end = nullptr);
JULIET_API void write(NonNullPtr<IOStream> stream, float value);
JULIET_API bool read(const char* buffer, int8& value);
JULIET_API void write(NonNullPtr<IOStream> stream, int8 value);
JULIET_API bool read(const char* buffer, int16& value);
JULIET_API void write(NonNullPtr<IOStream> stream, int16 value);
JULIET_API bool read(const char* buffer, int32& value);
JULIET_API void write(NonNullPtr<IOStream> stream, int32 value);
JULIET_API bool read(const char* buffer, int64& value);
JULIET_API void write(NonNullPtr<IOStream> stream, int64 value);
JULIET_API bool read(const char* buffer, uint8& value);
JULIET_API void write(NonNullPtr<IOStream> stream, uint8 value);
JULIET_API bool read(const char* buffer, uint16& value);
JULIET_API void write(NonNullPtr<IOStream> stream, uint16 value);
JULIET_API bool read(const char* buffer, uint32& value);
JULIET_API void write(NonNullPtr<IOStream> stream, uint32 value);
JULIET_API bool read(const char* buffer, uint64& value);
JULIET_API void write(NonNullPtr<IOStream> stream, uint64 value);
JULIET_API bool read(const char* buffer, bool& value);
JULIET_API void write(NonNullPtr<IOStream> stream, bool value);
JULIET_API bool read(const char* buffer, Vector4& value);
JULIET_API void write(NonNullPtr<IOStream> stream, Vector4 value);
JULIET_API bool8 read_prop_str(Archive* ar, String value_raw, String* value);
JULIET_API void write_str(IOStream* stream, String value);
JULIET_API bool8 read_f32(const char* buffer, float* value, const char** end);
JULIET_API void write_f32(IOStream* stream, float value);
JULIET_API bool8 read_i8(const char* buffer, int8* value);
JULIET_API void write_i8(IOStream* stream, int8 value);
JULIET_API bool8 read_i16(const char* buffer, int16* value);
JULIET_API void write_i16(IOStream* stream, int16 value);
JULIET_API bool8 read_i32(const char* buffer, int32* value);
JULIET_API void write_i32(IOStream* stream, int32 value);
JULIET_API bool8 read_i64(const char* buffer, int64* value);
JULIET_API void write_i64(IOStream* stream, int64 value);
JULIET_API bool8 read_u8(const char* buffer, uint8* value);
JULIET_API void write_u8(IOStream* stream, uint8 value);
JULIET_API bool8 read_u16(const char* buffer, uint16* value);
JULIET_API void write_u16(IOStream* stream, uint16 value);
JULIET_API bool8 read_u32(const char* buffer, uint32* value);
JULIET_API void write_u32(IOStream* stream, uint32 value);
JULIET_API bool8 read_u64(const char* buffer, uint64* value);
JULIET_API void write_u64(IOStream* stream, uint64 value);
JULIET_API bool8 read_b8(const char* buffer, bool8* value);
JULIET_API void write_b8(IOStream* stream, bool8 value);
JULIET_API bool8 read_vec4(const char* buffer, Vector4* value);
JULIET_API void write_vec4(IOStream* stream, Vector4 value);
// For primitives not needing archive nor allocation
template <typename Type>
bool read_prop(Archive& /*ar*/, String value_raw, Type& value)
{
char buffer[64];
size_t cpy_size = Min(value_raw.Size, sizeof(buffer) - 1);
MemCopy(buffer, value_raw.Str, cpy_size);
buffer[cpy_size] = '\0';
JULIET_API bool8 serialize_str(Archive* ar, String property_name, String* value);
JULIET_API bool8 serialize_f32(Archive* ar, String property_name, float* value);
JULIET_API bool8 serialize_i8(Archive* ar, String property_name, int8* value);
JULIET_API bool8 serialize_i16(Archive* ar, String property_name, int16* value);
JULIET_API bool8 serialize_i32(Archive* ar, String property_name, int32* value);
JULIET_API bool8 serialize_i64(Archive* ar, String property_name, int64* value);
JULIET_API bool8 serialize_u8(Archive* ar, String property_name, uint8* value);
JULIET_API bool8 serialize_u16(Archive* ar, String property_name, uint16* value);
JULIET_API bool8 serialize_u32(Archive* ar, String property_name, uint32* value);
JULIET_API bool8 serialize_u64(Archive* ar, String property_name, uint64* value);
JULIET_API bool8 serialize_b8(Archive* ar, String property_name, bool8* value);
JULIET_API bool8 serialize_vec4(Archive* ar, String property_name, Vector4* value);
return read(buffer, value);
}
#define SERIALIZE(ar, name, var) serialize((ar), ConstString(#name), #name##_crc32, (var))
#define SERIALIZE_SIMPLE(ar, var) SERIALIZE(ar, var, var)
template <typename Type>
bool serialize(Archive& ar, String property_name, uint32 property_crc, Type& value)
{
Assert(IsValid(property_name));
bool result = false;
if (ar.loading)
{
if (auto* prop = find_property(&ar.base, property_crc))
{
if (read_prop(ar, prop->value, value))
{
result = true;
}
}
}
else
{
// Save
write_property_header(ar, property_name);
write(ar.stream, value);
result = true;
}
return result;
}
#define SERIALIZE_STR(ar, name, var_ptr) serialize_str((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_F32(ar, name, var_ptr) serialize_f32((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_I8(ar, name, var_ptr) serialize_i8((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_I16(ar, name, var_ptr) serialize_i16((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_I32(ar, name, var_ptr) serialize_i32((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_I64(ar, name, var_ptr) serialize_i64((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_U8(ar, name, var_ptr) serialize_u8((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_U16(ar, name, var_ptr) serialize_u16((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_U32(ar, name, var_ptr) serialize_u32((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_U64(ar, name, var_ptr) serialize_u64((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_B8(ar, name, var_ptr) serialize_b8((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_BOOL(ar, name, var_ptr) serialize_b8((ar), ConstString(#name), (var_ptr))
#define SERIALIZE_VEC4(ar, name, var_ptr) serialize_vec4((ar), ConstString(#name), (var_ptr))
#if JULIET_DEBUG
JULIET_API void audit_unconsumed_properties(NonNullPtr<ParsedArchive> archive, String context_name);
JULIET_API void audit_unconsumed_properties(ParsedArchive* archive, String context_name);
#endif
+189 -168
View File
@@ -1,211 +1,232 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/CoreUtils.h>
#include <Core/Memory/MemoryArena.h>
#include <Core/Memory/Utils.h>
template <typename Type, size_t ReserveSize = 16>
typedef struct VectorArena VectorArena;
struct VectorArena
{
void Create(NonNullPtr<Arena> arena JULIET_DEBUG_PARAM(const char* name = nullptr))
Arena* Arena;
void* DataFirst;
void* DataLast;
void* Data;
union
{
Assert(!Arena);
size_t Count;
size_t Size;
};
size_t Capacity;
size_t ElemSize;
size_t ElemAlign;
size_t ReserveSize;
JULIET_DEBUG_ONLY(const char* Name;)
};
JULIET_DEBUG_ONLY(Name = name ? name : Name;)
#define kDefaultVectorReserveSize ((size_t)16)
#define kVectorArenaDefaultReserveSize ((size_t)16)
DataFirst = DataLast = Data = nullptr;
Count = 0;
Capacity = 0;
Arena = arena;
static inline void vector_arena_reserve(VectorArena* vec, size_t new_capacity)
{
Assert(vec != NULL);
Assert(vec->Arena != NULL);
Assert(new_capacity <= vec->ReserveSize && "VectorArena capacity should be <= ReserveSize.");
Reserve(ReserveSize);
}
void Destroy()
if (vec->Data == NULL)
{
DataFirst = DataLast = Data = nullptr;
Count = 0;
Capacity = 0;
Arena = nullptr;
}
void Reserve(size_t newCapacity)
{
Assert(Arena);
Assert(newCapacity <= ReserveSize && "VectorArena capacity should be <= ReserveSize.");
if (Data == nullptr)
{
Data = ArenaPushArray<Type>(Arena, newCapacity JULIET_DEBUG_PARAM(Name));
Capacity = newCapacity;
vec->Data = ArenaPush(vec->Arena, new_capacity * vec->ElemSize, Max(8ull, (uint64)vec->ElemAlign),
true JULIET_DEBUG_PARAM(vec->Name));
vec->Capacity = new_capacity;
}
else
{
Unimplemented();
}
}
static inline void vector_arena_create(VectorArena* vec, Arena* arena, size_t elem_size, size_t elem_align,
size_t reserve_size JULIET_DEBUG_PARAM(const char* name))
{
Assert(vec != NULL);
Assert(arena != NULL);
Assert(vec->Arena == NULL);
Assert(elem_size > 0);
JULIET_DEBUG_ONLY(vec->Name = (name != NULL) ? name : "VectorArena";)
vec->DataFirst = NULL;
vec->DataLast = NULL;
vec->Data = NULL;
vec->Count = 0;
vec->Capacity = 0;
vec->ElemSize = elem_size;
vec->ElemAlign = elem_align;
vec->ReserveSize = (reserve_size > 0) ? reserve_size : 16;
vec->Arena = arena;
vector_arena_reserve(vec, vec->ReserveSize);
}
static inline void vector_arena_destroy(VectorArena* vec)
{
Assert(vec != NULL);
vec->DataFirst = NULL;
vec->DataLast = NULL;
vec->Data = NULL;
vec->Count = 0;
vec->Capacity = 0;
vec->Arena = NULL;
}
static inline void* vector_arena_begin(VectorArena* vec)
{
Assert(vec != NULL);
return vec->DataFirst;
}
static inline const void* vector_arena_begin_const(const VectorArena* vec)
{
Assert(vec != NULL);
return vec->DataFirst;
}
static inline void* vector_arena_end(VectorArena* vec)
{
Assert(vec != NULL);
void* result = NULL;
if (vec->DataFirst != NULL)
{
result = (Byte*)vec->DataFirst + (vec->Count * vec->ElemSize);
}
return result;
}
void Resize(size_t newCount)
static inline const void* vector_arena_end_const(const VectorArena* vec)
{
Assert(vec != NULL);
const void* result = NULL;
if (vec->DataFirst != NULL)
{
Assert(Arena);
if (newCount == Count)
{
return;
result = (const Byte*)vec->DataFirst + (vec->Count * vec->ElemSize);
}
return result;
}
if (Data == nullptr)
static inline void vector_arena_resize(VectorArena* vec, size_t new_size)
{
Assert(vec != NULL);
Assert(new_size <= vec->Capacity);
vec->Count = new_size;
if (vec->Count > 0)
{
size_t initialCapacity = newCount > ReserveSize ? newCount : ReserveSize;
Reserve(initialCapacity);
}
Assert(newCount <= Capacity && "VectorArena capacity exceeded!");
Count = newCount;
if (Count > 0)
{
DataFirst = Data;
DataLast = Data + Count - 1;
vec->DataFirst = vec->Data;
vec->DataLast = (Byte*)vec->Data + ((vec->Count - 1) * vec->ElemSize);
}
else
{
DataFirst = DataLast = nullptr;
}
vec->DataFirst = NULL;
vec->DataLast = NULL;
}
}
void PushBack(const Type* buffer, size_t amount)
static inline void vector_arena_push_buffer(VectorArena* vec, const void* buffer, size_t amount)
{
Assert(vec != NULL);
Assert(buffer != NULL);
Assert(amount > 0);
Assert(vec->Count + amount <= vec->Capacity && "VectorArena capacity exceeded!");
Byte* dest = (Byte*)vec->Data + (vec->Count * vec->ElemSize);
MemCopy(dest, buffer, amount * vec->ElemSize);
if (vec->DataFirst == NULL)
{
Assert(Arena);
Assert(buffer || amount == 0);
vec->DataFirst = vec->Data;
}
if (amount == 0)
vec->Count += amount;
vec->DataLast = (Byte*)vec->Data + ((vec->Count - 1) * vec->ElemSize);
}
#define vector_arena_push_array vector_arena_push_buffer
static inline void vector_arena_push_elem(VectorArena* vec, const void* value_ptr)
{
Assert(vec != NULL);
Assert(value_ptr != NULL);
Assert(vec->Count + 1 <= vec->Capacity && "VectorArena capacity exceeded!");
Byte* dest = (Byte*)vec->Data + (vec->Count * vec->ElemSize);
MemCopy(dest, value_ptr, vec->ElemSize);
if (vec->DataFirst == NULL)
{
return;
vec->DataFirst = vec->Data;
}
if (Data == nullptr)
vec->Count += 1;
vec->DataLast = dest;
}
static inline void vector_arena_remove_at_fast(VectorArena* vec, index_t index)
{
Assert(vec != NULL);
Assert(index < vec->Count);
size_t last_idx = vec->Count - 1;
if (index != last_idx)
{
size_t initialCapacity = amount > ReserveSize ? amount : ReserveSize;
Reserve(initialCapacity);
Byte* dst = (Byte*)vec->DataFirst + (index * vec->ElemSize);
Byte* src = (Byte*)vec->DataFirst + (last_idx * vec->ElemSize);
MemCopy(dst, src, vec->ElemSize);
}
Assert(Count + amount <= Capacity && "VectorArena capacity exceeded!");
Type* dst = Data + Count;
MemCopy(dst, buffer, amount * sizeof(Type));
if (Count == 0)
vec->Count -= 1;
if (vec->Count == 0)
{
DataFirst = dst;
vec->DataFirst = NULL;
vec->DataLast = NULL;
}
DataLast = dst + amount - 1;
Count += amount;
}
void PushBack(const Type& value)
else
{
Assert(Arena);
if (Data == nullptr)
{
Reserve(ReserveSize);
vec->DataLast = (Byte*)vec->DataFirst + ((vec->Count - 1) * vec->ElemSize);
}
}
Assert(Count + 1 <= Capacity && "VectorArena capacity exceeded!");
static inline void vector_arena_clear(VectorArena* vec)
{
Assert(vec != NULL);
vec->DataFirst = NULL;
vec->DataLast = NULL;
vec->Count = 0;
}
Type* entry = Data + Count;
*entry = value;
static inline bool8 vector_arena_is_empty(const VectorArena* vec)
{
Assert(vec != NULL);
return vec->Count == 0;
}
if (Count == 0)
{
DataFirst = entry;
}
DataLast = entry;
++Count;
}
static inline size_t vector_arena_size(const VectorArena* vec)
{
Assert(vec != NULL);
return vec->Count;
}
void PushBack(Type&& value)
{
Assert(Arena);
#define VectorArenaCreate(vec, Type, arena, ...) \
vector_arena_create((vec), (arena), sizeof(Type), AlignOf(Type), __VA_ARGS__)
if (Data == nullptr)
{
Reserve(ReserveSize);
}
Assert(Count + 1 <= Capacity && "VectorArena capacity exceeded!");
Type* entry = Data + Count;
*entry = std::move(value);
if (Count == 0)
{
DataFirst = entry;
}
DataLast = entry;
++Count;
}
void RemoveAtFast(index_t index)
{
Assert(Arena);
Assert(index < Count);
Assert(Count > 0);
Type* elementAdr = DataFirst + index;
// Swap DataLast and element
if (DataLast != elementAdr)
{
Swap(DataLast, elementAdr);
}
--DataLast;
--Count;
if (Count == 0)
{
DataFirst = DataLast = nullptr;
}
}
void Clear()
{
Assert(Arena);
DataFirst = DataLast = nullptr;
Count = 0;
}
[[nodiscard]] bool IsEmpty() const { return Count == 0; }
// C++ Accessors for loop supports and Index based access
[[nodiscard]] Type& operator[](size_t index) { return DataFirst[index]; }
[[nodiscard]] const Type& operator[](size_t index) const { return DataFirst[index]; }
[[nodiscard]] Type* begin() { return DataFirst; }
[[nodiscard]] Type* end() { return DataFirst + Count; }
[[nodiscard]] const Type* begin() const { return DataFirst; }
[[nodiscard]] const Type* end() const { return DataFirst + Count; }
[[nodiscard]] Type* First() { return DataFirst; }
[[nodiscard]] Type* Front() { return DataFirst; }
[[nodiscard]] Type* Last() { return DataLast; }
[[nodiscard]] Type* Back() { return DataLast; }
[[nodiscard]] Type* DataPtr() { return Data; }
[[nodiscard]] const Type* DataPtr() const { return Data; }
[[nodiscard]] size_t Size() const { return Count; }
Arena* Arena = nullptr;
Type* DataFirst = nullptr;
Type* DataLast = nullptr;
Type* Data = nullptr;
size_t Count = 0;
size_t Capacity = 0;
JULIET_DEBUG_ONLY(const char* Name = "VectorArena";)
};
static_assert(std::is_standard_layout_v<VectorArena<int>>,
"VectorArena must have a standard layout to remain POD-like.");
static_assert(std::is_trivially_copyable_v<VectorArena<int>>,
"VectorArena must be trivially copyable (no custom destructors/assignment).");
#define VectorArenaAt(Type, vec, idx) (((Type*)((vec)->DataFirst))[idx])
#define VectorArenaData(Type, vec) ((Type*)((vec)->Data))
#define VectorArenaBegin(Type, vec) ((Type*)((vec)->DataFirst))
#define VectorArenaEnd(Type, vec) (((vec)->DataFirst != NULL) ? (((Type*)((vec)->DataFirst)) + (vec)->Count) : NULL)
#define VectorArenaLast(Type, vec) ((Type*)((vec)->DataLast))
#define VectorArenaBack(Type, vec) ((Type*)((vec)->DataLast))
#define VectorArenaPushPtr(Type, vec, ptr) vector_arena_push_elem((vec), (ptr))
#define VectorArenaPushVal(Type, vec, val) \
do \
{ \
Type _vec_tmp_val = (val); \
vector_arena_push_elem((vec), &_vec_tmp_val); \
} \
while (0)
+10 -10
View File
@@ -1,16 +1,16 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
struct Window;
typedef struct Window Window;
using WindowID = uint8;
extern JULIET_API Window* CreatePlatformWindow(const char* title, uint16 width, uint16 height, int flags = 0 /* unused */);
extern JULIET_API void DestroyPlatformWindow(NonNullPtr<Window> window);
typedef uint8 WindowID;
extern JULIET_API void ShowWindow(NonNullPtr<Window> window);
extern JULIET_API void HideWindow(NonNullPtr<Window> window);
extern JULIET_API Window* CreatePlatformWindow(const char* title, uint16 width, uint16 height, int flags);
extern JULIET_API void DestroyPlatformWindow(Window* window);
extern JULIET_API WindowID GetWindowID(NonNullPtr<Window> window);
extern JULIET_API void SetWindowTitle(NonNullPtr<Window> window, String title);
extern JULIET_API void ShowPlatformWindow(Window* window);
extern JULIET_API void HidePlatformWindow(Window* window);
extern JULIET_API WindowID GetWindowID(Window* window);
extern JULIET_API void SetWindowTitle(Window* window, String title);
@@ -1,9 +1,10 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/CoreTypes.h>
#include <Juliet.h>
struct DynamicLibrary;
typedef struct DynamicLibrary DynamicLibrary;
extern JULIET_API DynamicLibrary* LoadDynamicLibrary(const char* filename);
extern JULIET_API FunctionPtr LoadFunction(NonNullPtr<DynamicLibrary> lib, const char* functionName);
extern JULIET_API void UnloadDynamicLibrary(NonNullPtr<DynamicLibrary> lib);
extern JULIET_API FunctionPtr LoadFunction(DynamicLibrary* lib, const char* functionName);
extern JULIET_API void UnloadDynamicLibrary(DynamicLibrary* lib);
+37 -50
View File
@@ -1,53 +1,57 @@
#pragma once
#pragma once
#include <Core/Common/CoreUtils.h>
#include <Core/HAL/Display/Display.h>
#include <Core/HAL/Keyboard/Keyboard.h>
#include <Core/HAL/Keyboard/KeyCode.h>
#include <Core/HAL/Mouse/Mouse.h>
#include <Juliet.h>
// Handles all events from systems handling the Hardware
// Very inspired by SDL3
enum class EventType : uint32
typedef uint32 EventType;
enum
{
None = 0,
First = None,
EventType_None = 0,
EventType_First = EventType_None,
// Application Events
// User querying an exit
Application_Exit = 100,
// OS terminating the application
Application_OS_Terminate,
Application_Begin = Application_Exit,
Application_End = Application_OS_Terminate,
EventType_Application_Exit = 100,
EventType_Application_OS_Terminate = 101,
EventType_Application_Begin = EventType_Application_Exit,
EventType_Application_End = EventType_Application_OS_Terminate,
// Window Events
Window_Close_Request = 200,
Window_Begin = Window_Close_Request,
Window_End = Window_Close_Request,
EventType_Window_Close_Request = 200,
EventType_Window_Begin = EventType_Window_Close_Request,
EventType_Window_End = EventType_Window_Close_Request,
// Keyboard Event
Key_Down = 300,
Key_Up,
Keyboard_Begin = Key_Down,
Keyboard_End = Key_Up,
EventType_Key_Down = 300,
EventType_Key_Up = 301,
EventType_Keyboard_Begin = EventType_Key_Down,
EventType_Keyboard_End = EventType_Key_Up,
// Mouse Event
Mouse_Move = 400,
Mouse_ButtonPressed,
Mouse_ButtonReleased,
EventType_Mouse_Move = 400,
EventType_Mouse_ButtonPressed = 401,
EventType_Mouse_ButtonReleased = 402,
Mouse_Begin = Mouse_Move,
Mouse_End = Mouse_ButtonReleased,
EventType_Mouse_Begin = EventType_Mouse_Move,
EventType_Mouse_End = EventType_Mouse_ButtonReleased,
Last // Get value from the previous one
EventType_Last
};
typedef struct WindowEvent WindowEvent;
typedef struct KeyboardEvent KeyboardEvent;
typedef struct MouseMovementEvent MouseMovementEvent;
typedef struct MouseButtonEvent MouseButtonEvent;
typedef union AllSystemEventUnion AllSystemEventUnion;
typedef struct SystemEvent SystemEvent;
struct WindowEvent
{
WindowID AssociatedWindowID;
uint32 DataPadding[2]; // TODO : define how much data param we need
uint32 DataPadding[2];
};
struct KeyboardEvent
@@ -59,9 +63,6 @@ struct KeyboardEvent
KeyMod KeyModeState;
};
// =====================================================
// Mouse Events
// =====================================================
struct MouseMovementEvent
{
MouseID AssociatedMouseID;
@@ -80,20 +81,18 @@ struct MouseButtonEvent
float X;
float Y;
MouseButton ButtonState;
bool IsPressed : 1;
bool8 IsPressed;
};
// Tagged union representing ALL possible system events + a bit of data for custom event if needed
union AllSystemEventUnion
{
WindowEvent Window;
KeyboardEvent Keyboard;
MouseMovementEvent MouseMovement;
MouseButtonEvent MouseButton;
uint8 Padding[128]; // Make sure that the union is fixed in size and big enough on all platforms.
uint8 Padding[128];
};
// Make sure we do not bust the union size
static_assert(sizeof(AllSystemEventUnion) == sizeof(((AllSystemEventUnion*)nullptr)->Padding));
StaticAssert(sizeof(AllSystemEventUnion) == 128, SystemEventUnionSizeCheck);
struct SystemEvent
{
@@ -102,19 +101,7 @@ struct SystemEvent
AllSystemEventUnion Data;
};
// Poll for any event, return false if no event is available.
// Equivalent to WaitEvent(event, 0);
// Will not block
extern JULIET_API bool GetEvent(SystemEvent& event);
// TODO : use chrono to tag the timeout correctly with nanosec
// timeout == -1 means wait for any event before pursuing
// timeout == 0 means checking once for the frame and getting out
// timeout > 0 means wait until time is out
extern JULIET_API bool WaitEvent(SystemEvent& event, int32 timeoutInNS = -1);
// Add an event onto the event queue.
// TODO : support array of events
extern JULIET_API bool AddEvent(SystemEvent& event);
extern JULIET_API bool8 GetEvent(SystemEvent* event);
extern JULIET_API bool8 WaitEvent(SystemEvent* event, int32 timeoutInNS);
extern JULIET_API bool8 AddEvent(SystemEvent* event);
extern void Events_NewFrame(float deltaTime);
+17 -15
View File
@@ -2,41 +2,43 @@
#include <Core/Common/String.h>
enum class AssetType
typedef uint32 AssetType;
enum
{
JAsset,
Shader,
Config,
AssetType_JAsset = 0,
AssetType_Shader = 1,
AssetType_Config = 2,
};
typedef struct Path Path;
struct Path
{
String Directories;
String FullPath;
};
JULIET_API bool IsValid(Path path);
JULIET_API bool8 IsValidPath(Path path);
// Returns the path to the application directory
JULIET_API Path GetBasePath();
JULIET_API Path GetBasePath(void);
// 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").
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);
+37 -37
View File
@@ -1,69 +1,69 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Juliet.h>
#include "Core/HAL/Filesystem/Filesystem.h"
// Opaque type
struct IOStream;
typedef struct IOStream IOStream;
typedef struct IOStreamDataPayload IOStreamDataPayload;
struct IOStreamDataPayload
{
uint8 unused;
};
enum class IOStreamStatus : uint8
typedef uint8 IOStreamStatus;
enum
{
Ready,
Error,
EndOfFile,
NotReady,
ReadOnly,
WriteOnly
IOStreamStatus_Ready = 0,
IOStreamStatus_Error,
IOStreamStatus_EndOfFile,
IOStreamStatus_NotReady,
IOStreamStatus_ReadOnly,
IOStreamStatus_WriteOnly
};
enum class IOStreamSeekPivot : uint8
typedef uint8 IOStreamSeekPivot;
enum
{
Begin,
Current,
End,
Count
IOStreamSeekPivot_Begin = 0,
IOStreamSeekPivot_Current,
IOStreamSeekPivot_End,
IOStreamSeekPivot_Count
};
// IOStream can be opened on a file or memory, or anything else.
// Use the interface to make it transparent to the user.
typedef struct IOStreamInterface IOStreamInterface;
struct IOStreamInterface
{
uint32 Version;
int64 (*Size)(NonNullPtr<IOStreamDataPayload> data);
int64 (*Size)(IOStreamDataPayload* data);
int64 (*Seek)(NonNullPtr<IOStreamDataPayload> data, int64 offset, IOStreamSeekPivot pivot);
size_t (*Read)(NonNullPtr<IOStreamDataPayload> data, void* outBuffer, size_t size, NonNullPtr<IOStreamStatus> status);
size_t (*Write)(NonNullPtr<IOStreamDataPayload> data, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status);
bool (*Flush)(NonNullPtr<IOStreamDataPayload> data, NonNullPtr<IOStreamStatus> status);
int64 (*Seek)(IOStreamDataPayload* data, int64 offset, IOStreamSeekPivot pivot);
size_t (*Read)(IOStreamDataPayload* data, void* outBuffer, size_t size, IOStreamStatus* status);
size_t (*Write)(IOStreamDataPayload* data, ByteBuffer inBuffer, IOStreamStatus* status);
bool8 (*Flush)(IOStreamDataPayload* data, IOStreamStatus* status);
bool (*Close)(NonNullPtr<IOStreamDataPayload> data);
bool8 (*Close)(IOStreamDataPayload* data);
};
extern JULIET_API IOStream* IOFromFile(NonNullPtr<Arena> arena, String filename, String mode);
extern JULIET_API IOStream* IOFromFile(Arena* arena, String filename, String mode);
// Let you use an interface to open any io. Is used internally by IOFromFile
extern JULIET_API IOStream* IOFromInterface(NonNullPtr<Arena> arena, NonNullPtr<const IOStreamInterface> streamInterface,
NonNullPtr<IOStreamDataPayload> payload);
extern JULIET_API IOStream* IOFromInterface(Arena* arena, const IOStreamInterface* streamInterface,
IOStreamDataPayload* payload);
// Write formatted string into the stream.
JULIET_API size_t IOPrintf(NonNullPtr<IOStream> stream, _Printf_format_string_ const char* format, ...);
JULIET_API size_t IOWrite(NonNullPtr<IOStream> stream, ByteBuffer inBuffer);
JULIET_API size_t IOPrintf(IOStream* stream, const char* format, ...);
JULIET_API size_t IOWrite(IOStream* stream, ByteBuffer inBuffer);
JULIET_API size_t IORead(NonNullPtr<IOStream> stream, void* ptr, size_t size);
JULIET_API int64 IOSeek(NonNullPtr<IOStream> stream, int64 offset, IOStreamSeekPivot pivot);
JULIET_API size_t IORead(IOStream* stream, void* ptr, size_t size);
JULIET_API int64 IOSeek(IOStream* stream, int64 offset, IOStreamSeekPivot pivot);
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(NonNullPtr<Arena> arena, NonNullPtr<IOStream> stream, bool closeStreamWhenDone);
JULIET_API ByteBuffer LoadFile(Arena* arena, String filename);
JULIET_API ByteBuffer LoadFileFromStream(Arena* arena, IOStream* stream, bool8 closeStreamWhenDone);
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);
+176 -181
View File
@@ -1,188 +1,183 @@
#pragma once
#pragma once
// Represents a Virtual Key corresponding to the Physical key, but localized using the keyboard layout
// ScanCode reprensent US ASCII Keyboard
// WASD Scan codes are ZQSD in KeyCode for French keyboard
// We use the ASCII value of the generated character as value, when possible.
// Keys that do not produce a character are converted to an abritrary value high enough to not conflict
// Reference: https://www.asciitable.com/
// Reference: https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-6.0/aa299374(v=vs.60)
enum class KeyCode : uint32
#include <Core/Common/CoreTypes.h>
typedef uint32 KeyCode;
enum
{
Unknown = 0x0, // 0
Unsupported = 0x0, // 0
Return = 0X0Du, // '\r'
Escape = 0X1Bu, // '\X1B'
Backspace = 0X08u, // '\b'
Tab = 0X09u, // '\t'
Space = 0X20u, // ' '
ExclamationPoint = 0X21u, // '!'
DoubleApostrophe = 0X22u, // '"'
Hash = 0X23u, // '#'
Dollar = 0X24u, // '$'
Percent = 0X25u, // '%'
Ampersand = 0X26u, // '&'
Apostrophe = 0X27u, // '\''
LeftParenthesis = 0X28u, // '('
RightParenthesis = 0X29u, // ')'
Asterisk = 0X2Au, // '*'
Plus = 0X2Bu, // '+'
Comma = 0X2Cu, // ','
Minus = 0X2Du, // '-'
Period = 0X2Eu, // '.'
Slash = 0X2Fu, // '/'
Num0 = 0X30u, // '0'
Num1 = 0X31u, // '1'
Num2 = 0X32u, // '2'
Num3 = 0X33u, // '3'
Num4 = 0X34u, // '4'
Num5 = 0X35u, // '5'
Num6 = 0X36u, // '6'
Num7 = 0X37u, // '7'
Num8 = 0X38u, // '8'
Num9 = 0X39u, // '9'
Colon = 0X3Au, // ':'
Semicolon = 0X3Bu, // ';'
LessThan = 0X3Cu, // '<'
Equals = 0X3Du, // '='
GreaterThan = 0X3Eu, // '>'
QuestionMark = 0X3Fu, // '?'
CommercialAt = 0x40u, // '@'
LeftBracket = 0X5Bu, // '['
Backslash = 0X5Cu, // '\\'
RightBracket = 0X5DU, // ']'
Caret = 0X5Eu, // '^'
Underscore = 0X5Fu, // '_'
GraveAccent = 0X60u, // '`'
A = 0x61u, // 'a'
B = 0x62u, // 'b'
C = 0x63u, // 'c'
D = 0x64u, // 'd'
E = 0x65u, // 'e'
F = 0x66u, // 'f'
G = 0x67u, // 'g'
H = 0x68u, // 'h'
I = 0x69u, // 'i'
J = 0x6Au, // 'j'
K = 0x6Bu, // 'k'
L = 0x6CU, // 'l'
M = 0x6DU, // 'm'
N = 0x6Eu, // 'n'
O = 0x6Fu, // 'o'
P = 0x70u, // 'p'
Q = 0x71u, // 'q'
R = 0x72u, // 'r'
S = 0x73u, // 's'
T = 0x74u, // 't'
U = 0x75u, // 'y'
V = 0x76u, // 'v'
W = 0x77u, // 'w'
X = 0x78u, // 'x'
Y = 0x79u, // 'y'
Z = 0x7Au, // 'z'
LeftBrace = 0x7BU, // '{'
Pipe = 0x7CU, // '|'
RightBrace = 0x7DU, // '}'
Tilde = 0x7Eu, // '~'
Delete = 0x7Fu, // '\x7F'
PlusMinus = 0xb1u, // '\xB1'
KeyCode_Unknown = 0x0u,
KeyCode_Unsupported = 0x0u,
KeyCode_Return = 0x0Du,
KeyCode_Escape = 0x1Bu,
KeyCode_Backspace = 0x08u,
KeyCode_Tab = 0x09u,
KeyCode_Space = 0x20u,
KeyCode_ExclamationPoint = 0x21u,
KeyCode_DoubleApostrophe = 0x22u,
KeyCode_Hash = 0x23u,
KeyCode_Dollar = 0x24u,
KeyCode_Percent = 0x25u,
KeyCode_Ampersand = 0x26u,
KeyCode_Apostrophe = 0x27u,
KeyCode_LeftParenthesis = 0x28u,
KeyCode_RightParenthesis = 0x29u,
KeyCode_Asterisk = 0x2Au,
KeyCode_Plus = 0x2Bu,
KeyCode_Comma = 0x2Cu,
KeyCode_Minus = 0x2Du,
KeyCode_Period = 0x2Eu,
KeyCode_Slash = 0x2Fu,
KeyCode_Num0 = 0x30u,
KeyCode_Num1 = 0x31u,
KeyCode_Num2 = 0x32u,
KeyCode_Num3 = 0x33u,
KeyCode_Num4 = 0x34u,
KeyCode_Num5 = 0x35u,
KeyCode_Num6 = 0x36u,
KeyCode_Num7 = 0x37u,
KeyCode_Num8 = 0x38u,
KeyCode_Num9 = 0x39u,
KeyCode_Colon = 0x3Au,
KeyCode_Semicolon = 0x3Bu,
KeyCode_LessThan = 0x3Cu,
KeyCode_Equals = 0x3Du,
KeyCode_GreaterThan = 0x3Eu,
KeyCode_QuestionMark = 0x3Fu,
KeyCode_CommercialAt = 0x40u,
KeyCode_LeftBracket = 0x5Bu,
KeyCode_Backslash = 0x5Cu,
KeyCode_RightBracket = 0x5Du,
KeyCode_Caret = 0x5Eu,
KeyCode_Underscore = 0x5Fu,
KeyCode_GraveAccent = 0x60u,
KeyCode_A = 0x61u,
KeyCode_B = 0x62u,
KeyCode_C = 0x63u,
KeyCode_D = 0x64u,
KeyCode_E = 0x65u,
KeyCode_F = 0x66u,
KeyCode_G = 0x67u,
KeyCode_H = 0x68u,
KeyCode_I = 0x69u,
KeyCode_J = 0x6Au,
KeyCode_K = 0x6Bu,
KeyCode_L = 0x6Cu,
KeyCode_M = 0x6Du,
KeyCode_N = 0x6Eu,
KeyCode_O = 0x6Fu,
KeyCode_P = 0x70u,
KeyCode_Q = 0x71u,
KeyCode_R = 0x72u,
KeyCode_S = 0x73u,
KeyCode_T = 0x74u,
KeyCode_U = 0x75u,
KeyCode_V = 0x76u,
KeyCode_W = 0x77u,
KeyCode_X = 0x78u,
KeyCode_Y = 0x79u,
KeyCode_Z = 0x7Au,
KeyCode_LeftBrace = 0x7Bu,
KeyCode_Pipe = 0x7Cu,
KeyCode_RightBrace = 0x7Du,
KeyCode_Tilde = 0x7Eu,
KeyCode_Delete = 0x7Fu,
KeyCode_PlusMinus = 0xb1u,
// Keys not producing a character
// Based on SDL Algo: ScanCode | 0x40000000
CapsLock = 0x40000039u,
F1 = 0x4000003Au,
F2 = 0x4000003Bu,
F3 = 0x4000003CU,
F4 = 0x4000003DU,
F5 = 0x4000003Eu,
F6 = 0x4000003Fu,
F7 = 0x40000040u,
F8 = 0x40000041u,
F9 = 0x40000042u,
F10 = 0x40000043u,
F11 = 0x40000044u,
F12 = 0x40000045u,
PrintScreen = 0x40000046u,
ScrollLock = 0x40000047u,
Pause = 0x40000048u,
Insert = 0x40000049u,
Home = 0x4000004Au,
PageUp = 0x4000004Bu,
End = 0x4000004DU,
PageDown = 0x4000004Eu,
RightArrow = 0x4000004Fu,
LeftArrow = 0x40000050u,
DownArrow = 0x40000051u,
UpArrow = 0x40000052u,
NumlockClear = 0x40000053u,
KeyPad_Divide = 0x40000054u,
KeyPad_Multiply = 0x40000055u,
KeyPad_Minus = 0x40000056u,
KeyPad_Plus = 0x40000057u,
KeyPad_Enter = 0x40000058u,
KeyPad_Num1 = 0x40000059u,
KeyPad_Num2 = 0x4000005Au,
KeyPad_Num3 = 0x4000005Bu,
KeyPad_Num4 = 0x4000005Cu,
KeyPad_Num5 = 0x4000005Du,
KeyPad_Num6 = 0x4000005Eu,
KeyPad_Num7 = 0x4000005Fu,
KeyPad_Num8 = 0x40000060u,
KeyPad_Num9 = 0x40000061u,
KeyPad_Num0 = 0x40000062u,
KeyPad_Period = 0x40000063u,
Power = 0x40000066u,
KeyPad_Equals = 0x40000067u,
F13 = 0x40000068u,
F14 = 0x40000069u,
F15 = 0x4000006Au,
F16 = 0x4000006Bu,
F17 = 0x4000006Cu,
F18 = 0x4000006Du,
F19 = 0x4000006Eu,
F20 = 0x4000006Fu,
F21 = 0x40000070u,
F22 = 0x40000071u,
F23 = 0x40000072u,
F24 = 0x40000073u,
Mute = 0x4000007Fu,
VolumeUp = 0x40000080u,
VolumeDown = 0x40000081u,
KeyPad_Comma = 0x40000085u,
LeftControl = 0x400000E0u,
LeftShift = 0x400000E1u,
LeftAlt = 0x400000E2u,
LeftOSCommand = 0x400000E3u,
RightControl = 0x400000E4u,
RightShift = 0x400000E5u,
RightAlt = 0x400000E6u,
RightOSCommand = 0x400000E7u,
Sleep = 0x40000102u,
WakeUp = 0x40000103u,
Media_NextTrack = 0x4000010Bu,
Media_PreviousTrack = 0x4000010Cu,
Media_Stop = 0x4000010Du,
Media_Eject = 0x4000010Eu,
Media_PlayPause = 0x4000010Fu,
Media_Select = 0x40000110u,
KeyCode_CapsLock = 0x40000039u,
KeyCode_F1 = 0x4000003Au,
KeyCode_F2 = 0x4000003Bu,
KeyCode_F3 = 0x4000003Cu,
KeyCode_F4 = 0x4000003Du,
KeyCode_F5 = 0x4000003Eu,
KeyCode_F6 = 0x4000003Fu,
KeyCode_F7 = 0x40000040u,
KeyCode_F8 = 0x40000041u,
KeyCode_F9 = 0x40000042u,
KeyCode_F10 = 0x40000043u,
KeyCode_F11 = 0x40000044u,
KeyCode_F12 = 0x40000045u,
KeyCode_PrintScreen = 0x40000046u,
KeyCode_ScrollLock = 0x40000047u,
KeyCode_Pause = 0x40000048u,
KeyCode_Insert = 0x40000049u,
KeyCode_Home = 0x4000004Au,
KeyCode_PageUp = 0x4000004Bu,
KeyCode_End = 0x4000004Du,
KeyCode_PageDown = 0x4000004Eu,
KeyCode_RightArrow = 0x4000004Fu,
KeyCode_LeftArrow = 0x40000050u,
KeyCode_DownArrow = 0x40000051u,
KeyCode_UpArrow = 0x40000052u,
KeyCode_NumlockClear = 0x40000053u,
KeyCode_KeyPad_Divide = 0x40000054u,
KeyCode_KeyPad_Multiply = 0x40000055u,
KeyCode_KeyPad_Minus = 0x40000056u,
KeyCode_KeyPad_Plus = 0x40000057u,
KeyCode_KeyPad_Enter = 0x40000058u,
KeyCode_KeyPad_Num1 = 0x40000059u,
KeyCode_KeyPad_Num2 = 0x4000005Au,
KeyCode_KeyPad_Num3 = 0x4000005Bu,
KeyCode_KeyPad_Num4 = 0x4000005Cu,
KeyCode_KeyPad_Num5 = 0x4000005Du,
KeyCode_KeyPad_Num6 = 0x4000005Eu,
KeyCode_KeyPad_Num7 = 0x4000005Fu,
KeyCode_KeyPad_Num8 = 0x40000060u,
KeyCode_KeyPad_Num9 = 0x40000061u,
KeyCode_KeyPad_Num0 = 0x40000062u,
KeyCode_KeyPad_Period = 0x40000063u,
KeyCode_Power = 0x40000066u,
KeyCode_KeyPad_Equals = 0x40000067u,
KeyCode_F13 = 0x40000068u,
KeyCode_F14 = 0x40000069u,
KeyCode_F15 = 0x4000006Au,
KeyCode_F16 = 0x4000006Bu,
KeyCode_F17 = 0x4000006Cu,
KeyCode_F18 = 0x4000006Du,
KeyCode_F19 = 0x4000006Eu,
KeyCode_F20 = 0x4000006Fu,
KeyCode_F21 = 0x40000070u,
KeyCode_F22 = 0x40000071u,
KeyCode_F23 = 0x40000072u,
KeyCode_F24 = 0x40000073u,
KeyCode_Mute = 0x4000007Fu,
KeyCode_VolumeUp = 0x40000080u,
KeyCode_VolumeDown = 0x40000081u,
KeyCode_KeyPad_Comma = 0x40000085u,
KeyCode_LeftControl = 0x400000E0u,
KeyCode_LeftShift = 0x400000E1u,
KeyCode_LeftAlt = 0x400000E2u,
KeyCode_LeftOSCommand = 0x400000E3u,
KeyCode_RightControl = 0x400000E4u,
KeyCode_RightShift = 0x400000E5u,
KeyCode_RightAlt = 0x400000E6u,
KeyCode_RightOSCommand = 0x400000E7u,
KeyCode_Sleep = 0x40000102u,
KeyCode_WakeUp = 0x40000103u,
KeyCode_Media_NextTrack = 0x4000010Bu,
KeyCode_Media_PreviousTrack = 0x4000010Cu,
KeyCode_Media_Stop = 0x4000010Du,
KeyCode_Media_Eject = 0x4000010Eu,
KeyCode_Media_PlayPause = 0x4000010Fu,
KeyCode_Media_Select = 0x40000110u,
};
enum class KeyMod : uint16
typedef uint16 KeyMod;
enum
{
None = 0b0,
LeftShift = 0b0000'0000'0001u,
RightShift = 0b0000'0000'0010u,
LeftControl = 0b0000'0000'0100u,
RightControl = 0b0000'0000'1000u,
LeftAlt = 0b0000'0001'000u,
RightAlt = 0b0000'0010'0000u,
LeftOSCommand = 0b0000'0100'0000u,
RightOSCommand = 0b0000'1000'0000u,
NumLock = 0b0001'0000'0000u,
CapsLock = 0b0010'0000'0000u,
ScrollLock = 0b0100'0000'0000u,
Control = LeftControl | RightControl,
Shift = LeftShift | RightShift,
Alt = LeftAlt | RightAlt,
OSCommand = LeftOSCommand | RightOSCommand,
KeyMod_None = 0x0000u,
KeyMod_LeftShift = 0x0001u,
KeyMod_RightShift = 0x0002u,
KeyMod_LeftControl = 0x0004u,
KeyMod_RightControl = 0x0008u,
KeyMod_LeftAlt = 0x0010u,
KeyMod_RightAlt = 0x0020u,
KeyMod_LeftOSCommand = 0x0040u,
KeyMod_RightOSCommand = 0x0080u,
KeyMod_NumLock = 0x0100u,
KeyMod_CapsLock = 0x0200u,
KeyMod_ScrollLock = 0x0400u,
KeyMod_Control = KeyMod_LeftControl | KeyMod_RightControl,
KeyMod_Shift = KeyMod_LeftShift | KeyMod_RightShift,
KeyMod_Alt = KeyMod_LeftAlt | KeyMod_RightAlt,
KeyMod_OSCommand = KeyMod_LeftOSCommand | KeyMod_RightOSCommand,
};
+11 -8
View File
@@ -1,23 +1,26 @@
#pragma once
#pragma once
#include <Core/HAL/Keyboard/KeyCode.h>
#include <Core/HAL/Keyboard/ScanCode.h>
#include <Juliet.h>
using KeyboardID = uint8;
typedef uint8 KeyboardID;
enum class KeyPosition : bool
typedef bool8 KeyPosition;
enum
{
Up = false,
Down = true
KeyPosition_Up = false,
KeyPosition_Down = true
};
typedef struct KeyState KeyState;
struct KeyState
{
KeyPosition Position;
float Time;
};
typedef struct Key Key;
struct Key
{
ScanCode ScanCode;
@@ -25,8 +28,8 @@ struct Key
uint16 Raw;
};
extern JULIET_API bool IsKeyDown(ScanCode scanCode);
extern JULIET_API bool IsKeyPressed(ScanCode scanCode);
extern JULIET_API bool8 IsKeyDown(ScanCode scanCode);
extern JULIET_API bool8 IsKeyPressed(ScanCode scanCode);
extern JULIET_API KeyMod GetKeyModState();
extern JULIET_API KeyMod GetKeyModState(void);
extern JULIET_API KeyCode GetKeyCodeFromScanCode(ScanCode scanCode, KeyMod keyModState);
+158 -161
View File
@@ -1,183 +1,180 @@
#pragma once
#pragma once
// Follow the HID Usage page for USB
// https://usb.org/sites/default/files/hut1_5.pdf
// 0 to 256 Is dedicated to Keyboard Usage Page (0x07)
// 257 to 286 Is dedicated to Consumer Usage Page (0xC)
// 287 to 511 Is not implemented. Could be used for Mobile or Consoles
// ScanCode reprensent Physical Keys and Buttons
enum class ScanCode : uint16
#include <Core/Common/CoreTypes.h>
typedef uint16 ScanCode;
enum
{
Unknown = 0,
Unsupported = 0,
ScanCode_Unknown = 0,
ScanCode_Unsupported = 0,
A = 4,
B = 5,
C = 6,
D = 7,
E = 8,
F = 9,
G = 10,
H = 11,
I = 12,
J = 13,
K = 14,
L = 15,
M = 16,
N = 17,
O = 18,
P = 19,
Q = 20,
R = 21,
S = 22,
T = 23,
U = 24,
V = 25,
W = 26,
X = 27,
Y = 28,
Z = 29,
ScanCode_A = 4,
ScanCode_B = 5,
ScanCode_C = 6,
ScanCode_D = 7,
ScanCode_E = 8,
ScanCode_F = 9,
ScanCode_G = 10,
ScanCode_H = 11,
ScanCode_I = 12,
ScanCode_J = 13,
ScanCode_K = 14,
ScanCode_L = 15,
ScanCode_M = 16,
ScanCode_N = 17,
ScanCode_O = 18,
ScanCode_P = 19,
ScanCode_Q = 20,
ScanCode_R = 21,
ScanCode_S = 22,
ScanCode_T = 23,
ScanCode_U = 24,
ScanCode_V = 25,
ScanCode_W = 26,
ScanCode_X = 27,
ScanCode_Y = 28,
ScanCode_Z = 29,
Num1 = 30,
Num2 = 31,
Num3 = 32,
Num4 = 33,
Num5 = 34,
Num6 = 35,
Num7 = 36,
Num8 = 37,
Num9 = 38,
Num0 = 39,
ScanCode_Num1 = 30,
ScanCode_Num2 = 31,
ScanCode_Num3 = 32,
ScanCode_Num4 = 33,
ScanCode_Num5 = 34,
ScanCode_Num6 = 35,
ScanCode_Num7 = 36,
ScanCode_Num8 = 37,
ScanCode_Num9 = 38,
ScanCode_Num0 = 39,
Return = 40,
Escape = 41,
Backspace = 42,
Tab = 43,
Space = 44,
ScanCode_Return = 40,
ScanCode_Escape = 41,
ScanCode_Backspace = 42,
ScanCode_Tab = 43,
ScanCode_Space = 44,
Minus = 45,
Equals = 46,
LeftBracket = 47,
RightBracket = 48,
Backslash = 49,
NonUSHash = 50, // Same as 49 but for ISO keyboards
Semicolon = 51,
Apostrophe = 52,
GraveAccent = 53,
Comma = 54,
Period = 55,
Slash = 56,
CapsLock = 57,
ScanCode_Minus = 45,
ScanCode_Equals = 46,
ScanCode_LeftBracket = 47,
ScanCode_RightBracket = 48,
ScanCode_Backslash = 49,
ScanCode_NonUSHash = 50,
ScanCode_Semicolon = 51,
ScanCode_Apostrophe = 52,
ScanCode_GraveAccent = 53,
ScanCode_Comma = 54,
ScanCode_Period = 55,
ScanCode_Slash = 56,
ScanCode_CapsLock = 57,
F1 = 58,
F2 = 59,
F3 = 60,
F4 = 61,
F5 = 62,
F6 = 63,
F7 = 64,
F8 = 65,
F9 = 66,
F10 = 67,
F11 = 68,
F12 = 69,
ScanCode_F1 = 58,
ScanCode_F2 = 59,
ScanCode_F3 = 60,
ScanCode_F4 = 61,
ScanCode_F5 = 62,
ScanCode_F6 = 63,
ScanCode_F7 = 64,
ScanCode_F8 = 65,
ScanCode_F9 = 66,
ScanCode_F10 = 67,
ScanCode_F11 = 68,
ScanCode_F12 = 69,
PrintScreen = 70,
ScrollLock = 71,
Pause = 72,
Insert = 73,
ScanCode_PrintScreen = 70,
ScanCode_ScrollLock = 71,
ScanCode_Pause = 72,
ScanCode_Insert = 73,
Home = 74,
PageUp = 75,
Delete = 76,
End = 77,
PageDown = 78,
RightArrow = 79,
LeftArrow = 80,
DownArrow = 81,
UpArrow = 82,
ScanCode_Home = 74,
ScanCode_PageUp = 75,
ScanCode_Delete = 76,
ScanCode_End = 77,
ScanCode_PageDown = 78,
ScanCode_RightArrow = 79,
ScanCode_LeftArrow = 80,
ScanCode_DownArrow = 81,
ScanCode_UpArrow = 82,
NumlockClear = 83, // Pc = Numlock / Mac = Clear
ScanCode_NumlockClear = 83,
KeyPad_Divide = 84,
KeyPad_Multiply = 85,
KeyPad_Minus = 86,
KeyPad_Plus = 87,
KeyPad_Enter = 88,
KeyPad_Num1 = 89,
KeyPad_Num2 = 90,
KeyPad_Num3 = 91,
KeyPad_Num4 = 92,
KeyPad_Num5 = 93,
KeyPad_Num6 = 94,
KeyPad_Num7 = 95,
KeyPad_Num8 = 96,
KeyPad_Num9 = 97,
KeyPad_Num0 = 98,
KeyPad_Period = 99,
ScanCode_KeyPad_Divide = 84,
ScanCode_KeyPad_Multiply = 85,
ScanCode_KeyPad_Minus = 86,
ScanCode_KeyPad_Plus = 87,
ScanCode_KeyPad_Enter = 88,
ScanCode_KeyPad_Num1 = 89,
ScanCode_KeyPad_Num2 = 90,
ScanCode_KeyPad_Num3 = 91,
ScanCode_KeyPad_Num4 = 92,
ScanCode_KeyPad_Num5 = 93,
ScanCode_KeyPad_Num6 = 94,
ScanCode_KeyPad_Num7 = 95,
ScanCode_KeyPad_Num8 = 96,
ScanCode_KeyPad_Num9 = 97,
ScanCode_KeyPad_Num0 = 98,
ScanCode_KeyPad_Period = 99,
NonUSBackslash = 100, // ISO keyboards only
Power = 102, // Some mac have a Power key
ScanCode_NonUSBackslash = 100,
ScanCode_Power = 102,
KeyPad_Equals = 103,
F13 = 104,
F14 = 105,
F15 = 106,
F16 = 107,
F17 = 108,
F18 = 109,
F19 = 110,
F20 = 111,
F21 = 112,
F22 = 113,
F23 = 114,
F24 = 115,
ScanCode_KeyPad_Equals = 103,
ScanCode_F13 = 104,
ScanCode_F14 = 105,
ScanCode_F15 = 106,
ScanCode_F16 = 107,
ScanCode_F17 = 108,
ScanCode_F18 = 109,
ScanCode_F19 = 110,
ScanCode_F20 = 111,
ScanCode_F21 = 112,
ScanCode_F22 = 113,
ScanCode_F23 = 114,
ScanCode_F24 = 115,
Mute = 127,
VolumeUp = 128,
VolumeDown = 129,
ScanCode_Mute = 127,
ScanCode_VolumeUp = 128,
ScanCode_VolumeDown = 129,
KeyPad_Comma = 133,
ScanCode_KeyPad_Comma = 133,
International1 = 135, // Mostly used on Asian keyboards
International2 = 136,
International3 = 137, // Yen Symbol
International4 = 138,
International5 = 139,
International6 = 140,
International7 = 141,
International8 = 142,
International9 = 143,
Lang1 = 144, // Hangul (Korean)
Lang2 = 145, // Hanja (Korean)
Lang3 = 146, // Katakana (Japanese)
Lang4 = 147, // Hiragana (Japanese)
Lang5 = 148, // Zenkaku/Hankaku (Japanese)
Lang6 = 149, // Unused
Lang7 = 150, // Unused
Lang8 = 151, // Unused
Lang9 = 152, // Unused
ScanCode_International1 = 135,
ScanCode_International2 = 136,
ScanCode_International3 = 137,
ScanCode_International4 = 138,
ScanCode_International5 = 139,
ScanCode_International6 = 140,
ScanCode_International7 = 141,
ScanCode_International8 = 142,
ScanCode_International9 = 143,
ScanCode_Lang1 = 144,
ScanCode_Lang2 = 145,
ScanCode_Lang3 = 146,
ScanCode_Lang4 = 147,
ScanCode_Lang5 = 148,
ScanCode_Lang6 = 149,
ScanCode_Lang7 = 150,
ScanCode_Lang8 = 151,
ScanCode_Lang9 = 152,
LeftControl = 224,
LeftShift = 225,
LeftAlt = 226, // Alt for PC, Option for Mac
LeftOSCommand = 227, // Window key for PC, Command for Mac
RightControl = 228,
RightShift = 229,
RightAlt = 230, // Alt Gr for PC, Option for Mac
RightOSCommand = 231, // Window key for PC, Command for Mac
ScanCode_LeftControl = 224,
ScanCode_LeftShift = 225,
ScanCode_LeftAlt = 226,
ScanCode_LeftOSCommand = 227,
ScanCode_RightControl = 228,
ScanCode_RightShift = 229,
ScanCode_RightAlt = 230,
ScanCode_RightOSCommand = 231,
Sleep = 258,
WakeUp = 259,
ScanCode_Sleep = 258,
ScanCode_WakeUp = 259,
Media_NextTrack = 267,
Media_PreviousTrack = 268,
Media_Stop = 269,
Media_Eject = 270,
Media_PlayPause = 271,
Media_Select = 272,
ScanCode_Media_NextTrack = 267,
ScanCode_Media_PreviousTrack = 268,
ScanCode_Media_Stop = 269,
ScanCode_Media_Eject = 270,
ScanCode_Media_PlayPause = 271,
ScanCode_Media_Select = 272,
Reserved = 287,
ScanCode_Reserved = 287,
Count = 512
ScanCode_Count = 512
};
+18 -14
View File
@@ -1,25 +1,29 @@
#pragma once
#pragma once
using MouseID = uint8;
#include <Core/Common/CoreTypes.h>
#include <Juliet.h>
enum class MouseButton : uint8
typedef uint8 MouseID;
typedef uint8 MouseButton;
enum
{
None = 0,
Left = 1 << 0,
Right = 1 << 1,
Middle = 1 << 2,
Button1 = 1 << 3,
Button2 = 1 << 4,
MouseButton_None = 0,
MouseButton_Left = 1 << 0,
MouseButton_Right = 1 << 1,
MouseButton_Middle = 1 << 2,
MouseButton_Button1 = 1 << 3,
MouseButton_Button2 = 1 << 4,
};
// TODO : Replace by Vector2f
typedef struct MousePosition MousePosition;
struct MousePosition
{
float X;
float Y;
};
JULIET_API extern bool IsMouseButtonDown(MouseButton button);
JULIET_API extern MousePosition GetMousePosition();
JULIET_API extern MousePosition GetMouseDelta();
JULIET_API extern MouseButton GetMouseButtonState();
JULIET_API extern bool8 IsMouseButtonDown(MouseButton button);
JULIET_API extern MousePosition GetMousePosition(void);
JULIET_API extern MousePosition GetMouseDelta(void);
JULIET_API extern MouseButton GetMouseButtonState(void);
+13 -42
View File
@@ -1,52 +1,23 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#include <Core/Memory/MemoryArena.h>
namespace Memory
{
Byte* OS_Reserve(size_t size);
bool OS_Commit(Byte* ptr, size_t size);
void OS_Release(Byte* ptr, size_t size);
Byte* OS_Reserve(size_t size);
bool8 OS_Commit(void* ptr, size_t size);
void OS_Release(void* ptr, size_t size);
template <typename Type>
Type* OS_Reserve(size_t size)
{
return reinterpret_cast<Type*>(OS_Reserve(size));
}
uint64 Time_Timestamp(void);
void Time_ComputeDeltaTime(void);
float Time_GetDeltaTime(void);
uint64 Time_GetFrameNumber(void);
template <typename Type>
bool OS_Commit(Type* ptr, size_t size)
{
return OS_Commit(reinterpret_cast<Byte*>(ptr), size);
}
JULIET_API bool8 Debug_IsDebuggerPresent(void);
template <typename Type>
void OS_Release(Type* ptr, size_t size)
{
OS_Release(reinterpret_cast<Byte*>(ptr), size);
}
String os_get_env_var(Arena* arena, String name);
void os_set_env_var(String name, String value);
} // namespace Memory
String os_get_username(Arena* arena);
namespace Time
{
uint64 Timestamp();
void ComputeDeltaTime();
float GetDeltaTime();
uint64 GetFrameNumber();
} // namespace Time
namespace Debug
{
JULIET_API bool IsDebuggerPresent();
} // namespace Debug
String os_get_env_var(NonNullPtr<Arena> arena, const String& name);
void os_set_env_var(const String& name, const String& value);
String os_get_username(NonNullPtr<Arena> arena);
using EntryPointFunc = int (*)(int, wchar_t**);
typedef int (*EntryPointFunc)(int, wchar_t**);
JULIET_API int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
+10 -10
View File
@@ -1,9 +1,9 @@
#pragma once
#pragma once
#include <Core/Common/String.h>
// Fwd Declare
struct DynamicLibrary;
typedef struct DynamicLibrary DynamicLibrary;
typedef struct HotReloadCode HotReloadCode;
struct HotReloadCode
{
@@ -21,15 +21,15 @@ struct HotReloadCode
uint32 UniqueID;
bool IsValid : 1;
bool8 IsValid;
};
extern JULIET_API void InitHotReloadCode(NonNullPtr<Arena> arena, HotReloadCode& code, String dllName,
extern JULIET_API void InitHotReloadCode(Arena* arena, HotReloadCode* code, String dllName,
String transientDllName, String lockFilename);
extern JULIET_API void ShutdownHotReloadCode(HotReloadCode& code);
extern JULIET_API void ShutdownHotReloadCode(HotReloadCode* code);
extern JULIET_API void LoadCode(HotReloadCode& code);
extern JULIET_API void UnloadCode(HotReloadCode& code);
extern JULIET_API void LoadCode(HotReloadCode* code);
extern JULIET_API void UnloadCode(HotReloadCode* code);
extern JULIET_API void ReloadCode(HotReloadCode& code);
extern JULIET_API bool ShouldReloadCode(const HotReloadCode& code);
extern JULIET_API void ReloadCode(HotReloadCode* code);
extern JULIET_API bool8 ShouldReloadCode(const HotReloadCode* code);
+14 -17
View File
@@ -1,27 +1,24 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/CoreTypes.h>
#include <Juliet.h>
#ifdef JULIET_ENABLE_IMGUI
struct ImGuiContext;
typedef struct ImGuiContext ImGuiContext;
typedef struct Window Window;
typedef struct GraphicsDevice GraphicsDevice;
struct Window;
struct GraphicsDevice;
JULIET_API void ImGuiService_Initialize(Window* window);
JULIET_API void ImGuiService_Shutdown(void);
namespace ImGuiService
{
JULIET_API void Initialize(NonNullPtr<Window> window);
JULIET_API void Shutdown();
JULIET_API void ImGuiService_NewFrame(void);
JULIET_API void ImGuiService_Render(void);
JULIET_API void NewFrame();
JULIET_API void Render();
JULIET_API bool8 ImGuiService_IsInitialized(void);
JULIET_API ImGuiContext* ImGuiService_GetContext(void);
JULIET_API bool IsInitialized();
JULIET_API ImGuiContext* GetContext();
// Run internal unit tests
JULIET_API void RunTests();
} // namespace ImGuiService
// Run internal unit tests
JULIET_API void ImGuiService_RunTests(void);
#endif // JULIET_ENABLE_IMGUI
+2 -9
View File
@@ -1,12 +1,5 @@
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/HAL/Display/Window.h>
#include <Graphics/GraphicsDevice.h>
#pragma once
#include <Juliet.h>
namespace UnitTest
{
void TestImGui();
}
void UnitTest_TestImGui(void);
+15 -10
View File
@@ -1,21 +1,26 @@
#pragma once
#pragma once
enum class JulietInit_Flags : uint8
#include <Core/Common/CoreTypes.h>
typedef uint8 JulietInit_Flags;
enum
{
None = 0,
Display = 1 << 0,
Audio = 1 << 1,
Count = Audio,
All = 0xFb
JulietInit_Flags_None = 0,
JulietInit_Flags_Display = 1 << 0,
JulietInit_Flags_Audio = 1 << 1,
JulietInit_Flags_Count = JulietInit_Flags_Audio,
JulietInit_Flags_All = 0xFbu
};
struct Arena;
typedef struct Arena Arena;
typedef struct GameState GameState;
typedef struct GameData GameData;
struct GameData
{
struct GameState* GameState;
GameState* GameState;
Arena* ScratchArena;
};
void JulietInit(JulietInit_Flags flags);
void JulietShutdown();
void JulietShutdown(void);
+6 -14
View File
@@ -1,21 +1,13 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Memory/MemoryArena.h>
// TODO : Juliet strings
// TODO Juliet Containers + Allocators...
// TODO: Juliet chrono, because it prevents me from doing #define global static
extern void JULIET_API InitializeLogManager(void);
extern void JULIET_API ShutdownLogManager(void);
enum class LogLevel : uint8;
enum class LogCategory : uint8;
extern void JULIET_API InitializeLogManager();
extern void JULIET_API ShutdownLogManager();
extern void JULIET_API LogScopeBegin();
// TODO everything that happened in there to export them to file or something
extern void JULIET_API LogScopeEnd();
extern void JULIET_API LogScopeBegin(void);
extern void JULIET_API LogScopeEnd(void);
extern void JULIET_API Log(LogLevel level, LogCategory category, const char* fmt, ...);
extern void JULIET_API LogDebug(LogCategory category, const char* fmt, ...);
+17 -13
View File
@@ -1,19 +1,23 @@
#pragma once
#pragma once
enum class LogLevel : uint8
#include <Core/Common/CoreTypes.h>
typedef uint8 LogLevel;
enum
{
Debug = 0,
Message = 1,
Warning = 2,
Error = 3,
LogLevel_Debug = 0,
LogLevel_Message = 1,
LogLevel_Warning = 2,
LogLevel_Error = 3,
};
enum class LogCategory : uint8
typedef uint8 LogCategory;
enum
{
Core = 0,
Graphics = 1,
Networking = 2,
Engine = 3,
Tool = 4,
Game = 5,
LogCategory_Core = 0,
LogCategory_Graphics = 1,
LogCategory_Networking = 2,
LogCategory_Engine = 3,
LogCategory_Tool = 4,
LogCategory_Game = 5,
};
+3 -6
View File
@@ -1,8 +1,8 @@
#pragma once
#pragma once
#include <Core/HAL/OS/OS.h>
extern int JulietMain(int, wchar_t**);
extern int JulietMain(int argc, wchar_t** argv);
#if JULIET_WIN32
#ifndef WINAPI
@@ -17,12 +17,10 @@ int wmain(int argc, wchar_t** argv)
#else
int main(int argc, char** argv)
{
return Bootstrap(JulietMain, argc, argv);
return Bootstrap(JulietMain, argc, (wchar_t**)argv);
}
#endif
extern "C" {
typedef struct HINSTANCE__* HINSTANCE;
typedef char* LPSTR;
typedef wchar_t* PWSTR;
@@ -40,7 +38,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
return Bootstrap(JulietMain, __argc, __wargv);
}
}
#else
#error "Only windows main is implemented"
#endif
+11 -40
View File
@@ -1,46 +1,17 @@
#pragma once
#pragma once
#include <Juliet.h>
#include <Core/Common/CoreTypes.h>
extern JULIET_API float RoundF(float value);
inline int32 LRoundF(float value)
static inline int32 LRoundF(float value)
{
return static_cast<int32>(RoundF(value));
return (int32)RoundF(value);
}
template <typename Type>
constexpr Type Min(Type lhs, Type rhs)
{
return rhs < lhs ? rhs : lhs;
}
template <typename Type>
constexpr Type Max(Type lhs, Type rhs)
{
return lhs < rhs ? rhs : lhs;
}
template <typename Type>
constexpr Type ClampTop(Type value, Type X)
{
return Min(value, X);
}
template <typename Type>
constexpr Type ClampBottom(Type value, Type X)
{
return Max(value, X);
}
template <typename Type>
constexpr Type Clamp(Type val, Type min, Type max)
{
if (val < min)
{
return min;
}
if (val > max)
{
return max;
}
return val;
}
#define Min(lhs, rhs) (((rhs) < (lhs)) ? (rhs) : (lhs))
#define Max(lhs, rhs) (((lhs) < (rhs)) ? (rhs) : (lhs))
#define ClampTop(value, X) Min((value), (X))
#define ClampBottom(value, X) Max((value), (X))
#define Clamp(val, min_v, max_v) (((val) < (min_v)) ? (min_v) : (((val) > (max_v)) ? (max_v) : (val)))
+28 -23
View File
@@ -1,16 +1,17 @@
#pragma once
#pragma once
#include <Core/Math/Vector.h>
#include <math.h>
typedef struct Matrix Matrix;
struct Matrix
{
float m[4][4];
};
[[nodiscard]] inline Matrix MatrixIdentity()
static inline Matrix MatrixIdentity(void)
{
Matrix result = {};
Matrix result = { 0 };
result.m[0][0] = 1.0f;
result.m[1][1] = 1.0f;
result.m[2][2] = 1.0f;
@@ -18,9 +19,9 @@ struct Matrix
return result;
}
[[nodiscard]] inline Matrix operator*(const Matrix& lhs, const Matrix& rhs)
static inline Matrix MatrixMultiply(Matrix lhs, Matrix rhs)
{
Matrix result = {};
Matrix result = { 0 };
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
@@ -34,7 +35,7 @@ struct Matrix
return result;
}
[[nodiscard]] inline Matrix MatrixTranslation(float x, float y, float z)
static inline Matrix MatrixTranslation(float x, float y, float z)
{
Matrix result = MatrixIdentity();
result.m[0][3] = x;
@@ -43,7 +44,7 @@ struct Matrix
return result;
}
[[nodiscard]] inline Matrix MatrixScale(float x, float y, float z)
static inline Matrix MatrixScale(float x, float y, float z)
{
Matrix result = MatrixIdentity();
result.m[0][0] = x;
@@ -52,7 +53,7 @@ struct Matrix
return result;
}
[[nodiscard]] inline Matrix MatrixRotationX(float radians)
static inline Matrix MatrixRotationX(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
@@ -64,7 +65,7 @@ struct Matrix
return result;
}
[[nodiscard]] inline Matrix MatrixRotationY(float radians)
static inline Matrix MatrixRotationY(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
@@ -76,7 +77,7 @@ struct Matrix
return result;
}
[[nodiscard]] inline Matrix MatrixRotationZ(float radians)
static inline Matrix MatrixRotationZ(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
@@ -88,26 +89,26 @@ struct Matrix
return result;
}
inline void MatrixTranslate(Matrix& m, const Vector3& v)
static inline void MatrixTranslate(Matrix* m, Vector3 v)
{
m.m[0][3] += v.x;
m.m[1][3] += v.y;
m.m[2][3] += v.z;
m->m[0][3] += v.x;
m->m[1][3] += v.y;
m->m[2][3] += v.z;
}
[[nodiscard]] inline Matrix MatrixRotation(float x, float y, float z)
static inline Matrix MatrixRotation(float x, float y, float z)
{
return MatrixRotationX(x) * MatrixRotationY(y) * MatrixRotationZ(z);
return MatrixMultiply(MatrixMultiply(MatrixRotationX(x), MatrixRotationY(y)), MatrixRotationZ(z));
}
inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& up)
static inline Matrix LookAt(Vector3 eye, Vector3 target, Vector3 up)
{
// Left-Handed convention
Vector3 zaxis = Normalize(target - eye); // Forward is +z
Vector3 zaxis = Normalize(Vector3Sub(target, eye)); // Forward is +z
Vector3 xaxis = Normalize(Cross(up, zaxis));
Vector3 yaxis = Cross(zaxis, xaxis);
Matrix result = {};
Matrix result = { 0 };
// Row 0
result.m[0][0] = xaxis.x;
result.m[0][1] = xaxis.y;
@@ -132,13 +133,13 @@ inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& u
return result;
}
inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float farZ)
static inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float farZ)
{
// Left-Handed Perspective
float yScale = 1.0f / tanf(fovY * 0.5f);
float xScale = yScale / aspectRatio;
Matrix result = {};
Matrix result = { 0 };
result.m[0][0] = xScale;
result.m[1][1] = yScale;
result.m[2][2] = farZ / (farZ - nearZ);
@@ -148,9 +149,9 @@ inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float f
return result;
}
[[nodiscard]] inline Matrix MatrixInverse(const Matrix& m)
static inline Matrix MatrixInverse(Matrix m)
{
Matrix out = {};
Matrix out = { 0 };
float m00 = m.m[0][0], m01 = m.m[0][1], m02 = m.m[0][2], m03 = m.m[0][3];
float m10 = m.m[1][0], m11 = m.m[1][1], m12 = m.m[1][2], m13 = m.m[1][3];
@@ -183,9 +184,13 @@ inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float f
{
float invDet = 1.0f / det;
for (int r = 0; r < 4; ++r)
{
for (int c = 0; c < 4; ++c)
{
out.m[r][c] *= invDet;
}
}
}
return out;
}
+7 -2
View File
@@ -1,6 +1,11 @@
#pragma once
#pragma once
struct Rectangle
#include <Core/Common/CoreTypes.h>
#define Rectangle JulietRectangle
typedef struct JulietRectangle JulietRectangle;
struct JulietRectangle
{
int32 X;
int32 Y;
+40 -16
View File
@@ -1,38 +1,62 @@
#pragma once
#pragma once
#include <math.h>
typedef struct Vector3 Vector3;
struct Vector3
{
float x, y, z;
Vector3 operator+(const Vector3& rhs) const { return { x + rhs.x, y + rhs.y, z + rhs.z }; }
Vector3 operator-(const Vector3& rhs) const { return { x - rhs.x, y - rhs.y, z - rhs.z }; }
Vector3 operator*(float s) const { return { x * s, y * s, z * s }; }
float x;
float y;
float z;
};
typedef struct Vector4 Vector4;
struct Vector4
{
float x = 0.f;
float y = 0.f;
float z = 0.f;
float w = 0.f;
float x;
float y;
float z;
float w;
};
inline Vector3 Normalize(const Vector3& v)
static inline Vector3 Vector3Add(Vector3 lhs, Vector3 rhs)
{
Vector3 res = { lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z };
return res;
}
static inline Vector3 Vector3Sub(Vector3 lhs, Vector3 rhs)
{
Vector3 res = { lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z };
return res;
}
static inline Vector3 Vector3Scale(Vector3 v, float s)
{
Vector3 res = { v.x * s, v.y * s, v.z * s };
return res;
}
static inline Vector3 Normalize(Vector3 v)
{
Vector3 result = v;
float len = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
if (len > 0.0001f)
{
return { v.x / len, v.y / len, v.z / len };
result.x = v.x / len;
result.y = v.y / len;
result.z = v.z / len;
}
return v;
return result;
}
inline Vector3 Cross(const Vector3& a, const Vector3& b)
static inline Vector3 Cross(Vector3 a, Vector3 b)
{
return { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x };
Vector3 res = { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x };
return res;
}
inline float Dot(const Vector3& a, const Vector3& b)
static inline float Dot(Vector3 a, Vector3 b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
+16 -16
View File
@@ -1,7 +1,8 @@
#pragma once
#pragma once
#include <Juliet.h>
#include <Core/Common/CoreUtils.h>
#include <stdlib.h>
// Uninitialized allocation
JULIET_API void* Malloc(size_t elem_size);
@@ -9,20 +10,19 @@ JULIET_API void* Malloc(size_t elem_size);
JULIET_API void* Calloc(size_t nb_elem, size_t elem_size);
JULIET_API void* Realloc(void* memory, size_t newSize);
// Free
template <typename Type>
void Free(Type* memory)
static inline void FreeMemory(void* memory)
{
Assert(memory);
::free(memory);
}
// Free and Set the ptr to nullptr
template <typename Type>
void SafeFree(Type*& memory)
{
if (memory)
{
::free(memory);
memory = nullptr;
}
Assert(memory != NULL);
free(memory);
}
#define SafeFree(memory_ptr) \
do \
{ \
if ((memory_ptr) != NULL) \
{ \
free((void*)(memory_ptr)); \
(memory_ptr) = NULL; \
} \
} \
while (0)
+51 -73
View File
@@ -1,21 +1,19 @@
#pragma once
#pragma once
#include <Core/Common/CoreUtils.h>
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#if JULIET_DEBUG
#include <Core/Memory/MemoryArenaDebug.h>
#endif
constexpr global uint64 g_Arena_Default_Reserve_Size = Megabytes(64);
constexpr global uint64 g_Arena_Default_Commit_Size = Kilobytes(64);
constexpr global uint64 k_ArenaHeaderSize = 128;
#define g_Arena_Default_Reserve_Size Megabytes(64)
#define g_Arena_Default_Commit_Size Kilobytes(64)
#define k_ArenaHeaderSize ((uint64)128)
#if JULIET_DEBUG
struct ArenaDebugInfo;
JULIET_API String FormatDebugTagV(const char* formatStr, std::format_args args);
#endif
typedef struct Arena Arena;
typedef struct TempArena TempArena;
typedef struct ArenaParams ArenaParams;
struct Arena
{
@@ -35,14 +33,14 @@ struct Arena
Arena* FreeBlockLast;
JULIET_DEBUG_ONLY(uint16 LostNodeCount;)
JULIET_DEBUG_ONLY(bool CanReserveMore : 1;)
JULIET_DEBUG_ONLY(bool8 CanReserveMore;)
JULIET_DEBUG_ONLY(Arena* GlobalNext;)
JULIET_DEBUG_ONLY(Arena* GlobalPrev;)
JULIET_DEBUG_ONLY(ArenaDebugInfo* FirstDebugInfo;)
const char* Name;
};
static_assert(sizeof(Arena) <= k_ArenaHeaderSize);
StaticAssert(sizeof(Arena) <= k_ArenaHeaderSize, ArenaHeaderSizeCheck);
struct TempArena
{
@@ -52,74 +50,54 @@ struct TempArena
struct ArenaParams
{
uint64 ReserveSize = g_Arena_Default_Reserve_Size;
uint64 CommitSize = g_Arena_Default_Commit_Size;
uint64 ReserveSize;
uint64 CommitSize;
const char* Name;
// When false, will assert if a new block is reserved.
JULIET_DEBUG_ONLY(bool CanReserveMore : 1 = true;)
JULIET_DEBUG_ONLY(bool8 DoNotReserveMore;)
};
[[nodiscard]] JULIET_API Arena* ArenaAllocate(const ArenaParams& params,
const std::source_location& loc = std::source_location::current());
JULIET_API void ArenaRelease(NonNullPtr<Arena> arena);
JULIET_API Arena* ArenaAllocateImpl(ArenaParams params, const char* file, uint32 line);
#define ArenaAllocate(...) ArenaAllocateImpl(__VA_ARGS__, __FILE__, (uint32)__LINE__)
// Raw Push, can be used but templated helpers exists below
[[nodiscard]] JULIET_API void* ArenaPush(NonNullPtr<Arena> arena, size_t size, size_t align,
bool shouldBeZeroed JULIET_DEBUG_PARAM(const char* tag));
JULIET_API void ArenaPopTo(NonNullPtr<Arena> arena, size_t position);
JULIET_API void ArenaPop(NonNullPtr<Arena> arena, size_t amount);
JULIET_API void ArenaClear(NonNullPtr<Arena> arena);
[[nodiscard]] JULIET_API size_t ArenaPos(NonNullPtr<Arena> arena);
JULIET_API void ArenaRelease(Arena* arena);
// Raw Push, can be used or macros below
JULIET_API void* ArenaPush(Arena* arena, size_t size, size_t align,
bool8 shouldBeZeroed JULIET_DEBUG_PARAM(const char* tag));
JULIET_API void ArenaPopTo(Arena* arena, size_t position);
JULIET_API void ArenaPop(Arena* arena, size_t amount);
JULIET_API void ArenaClear(Arena* arena);
JULIET_API size_t ArenaPos(Arena* arena);
#if JULIET_DEBUG
template <typename FirstDebugArg, typename... DebugArgs>
#define ArenaPushSize(...) ArenaPush(__VA_ARGS__)
#define ArenaPushStruct(arena, Type) \
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true, #Type))
#define ArenaPushStructTag(arena, Type, tag) \
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true, (tag)))
#define ArenaPushArray(arena, Type, count) \
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true, #Type))
#define ArenaPushArrayTag(arena, Type, count, tag) \
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true, (tag)))
#define ArenaPushArrayNoZero(arena, Type, count) \
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false, #Type))
#define ArenaPushArrayNoZeroTag(arena, Type, count, tag) \
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false, (tag)))
#else
#define ArenaPushSize(...) ArenaPush(__VA_ARGS__)
#define ArenaPushStruct(arena, Type) \
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true))
#define ArenaPushStructTag(arena, Type, tag) \
((Type*)ArenaPush((arena), sizeof(Type), AlignOf(Type), true))
#define ArenaPushArray(arena, Type, count) \
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true))
#define ArenaPushArrayTag(arena, Type, count, tag) \
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), true))
#define ArenaPushArrayNoZero(arena, Type, count) \
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false))
#define ArenaPushArrayNoZeroTag(arena, Type, count, tag) \
((Type*)ArenaPush((arena), sizeof(Type) * (size_t)(count), Max(8ull, (uint64)AlignOf(Type)), false))
#endif
[[nodiscard]] inline void* ArenaPushSize(NonNullPtr<Arena> arena, size_t size, size_t align,
bool shouldBeZeroed JULIET_DEBUG_PARAM(FirstDebugArg&& firstDebugArg, DebugArgs&&... debugArgs))
{
return ArenaPush(arena, size, align,
shouldBeZeroed JULIET_DEBUG_PARAM(
[&]() -> const char*
{
return Format(GetDebugInfoArena(), std::forward<FirstDebugArg>(firstDebugArg),
std::forward<DebugArgs>(debugArgs)...)
.Str;
}()));
}
template <typename Type JULIET_DEBUG_ONLY(, typename... DebugArgs)>
[[nodiscard]] Type* ArenaPushStruct(NonNullPtr<Arena> arena JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs))
{
return static_cast<Type*>(
ArenaPush(arena, sizeof(Type) * 1, AlignOf(Type),
true JULIET_DEBUG_PARAM(
[&]() -> const char*
{
if constexpr (sizeof...(DebugArgs) > 0)
{
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
}
return GetTypeName<Type>();
}())));
}
template <typename Type, bool shouldZero = true JULIET_DEBUG_ONLY(, typename... DebugArgs)>
[[nodiscard]] Type* ArenaPushArray(NonNullPtr<Arena> arena, size_t count JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs))
{
return static_cast<Type*>(
ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)),
shouldZero JULIET_DEBUG_PARAM(
[&]() -> const char*
{
if constexpr (sizeof...(DebugArgs) > 0)
{
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
}
return GetTypeName<Type>();
}())));
}
TempArena ArenaTempBegin(NonNullPtr<Arena> arena);
TempArena ArenaTempBegin(Arena* arena);
void ArenaTempEnd(TempArena temp);
+11 -14
View File
@@ -1,12 +1,13 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#if JULIET_DEBUG
struct Arena;
struct MemoryBlock;
typedef struct Arena Arena;
typedef struct MemoryBlock MemoryBlock;
typedef struct ArenaDebugInfo ArenaDebugInfo;
typedef struct ArenaAllocation ArenaAllocation;
// Arena (Struct)
struct ArenaDebugInfo
@@ -27,20 +28,16 @@ struct ArenaAllocation
};
// Arena (Struct)
void DebugRegisterArena(NonNullPtr<Arena> arena);
void DebugUnregisterArena(NonNullPtr<Arena> arena);
void DebugArenaSetDebugName(NonNullPtr<Arena> arena, const char* name);
bool IsDebugInfoArena(const Arena* arena); // To prevent recursion
void DebugRegisterArena(Arena* arena);
void DebugUnregisterArena(Arena* arena);
void DebugArenaSetDebugName(Arena* arena, const char* name);
bool8 IsDebugInfoArena(const Arena* arena); // To prevent recursion
void DebugArenaFreeBlock(Arena* block); // To clear all debug infos in a block
void DebugArenaRemoveAllocation(Arena* block, size_t oldOffset);
void DebugArenaPopTo(Arena* block, size_t newPosition);
void DebugArenaAddDebugInfo(Arena* block, size_t size, size_t offset, const char* tag);
// MemoryArena (Pool-based)
void DebugFreeArenaAllocations(MemoryBlock* blk);
void DebugArenaAddAllocation(MemoryBlock* blk, size_t size, size_t offset, String tag);
void DebugArenaRemoveLastAllocation(MemoryBlock* blk);
JULIET_API Arena* GetDebugInfoArena();
JULIET_API Arena* GetDebugInfoArena(void);
JULIET_API Arena* GetGlobalArenaListHead(void);
#endif
+51 -47
View File
@@ -1,63 +1,68 @@
#pragma once
#pragma once
#define ArraySize(array) (sizeof(array) / sizeof(array[0]))
#include <Core/Common/CoreTypes.h>
#include <string.h>
inline int32 MemCompare(const void* leftValue, const void* rightValue, size_t size)
#define ArraySize(array) (sizeof(array) / sizeof((array)[0]))
static inline int32 MemCompare(const void* left_value, const void* right_value, size_t size)
{
auto left = static_cast<const unsigned char*>(leftValue);
auto right = static_cast<const unsigned char*>(rightValue);
const unsigned char* left = (const unsigned char*)left_value;
const unsigned char* right = (const unsigned char*)right_value;
while (size && *left == *right)
{
++left;
++right;
--size;
}
return size ? *left - *right : 0;
return size ? ((int32)(*left) - (int32)(*right)) : 0;
}
// Single linked list
void SingleLinkedListPushNext(auto*& stackTop, auto* node)
{
node->Next = stackTop;
stackTop = node;
}
// Single linked list macros
#define SingleLinkedListPushNext(stackTop, node) \
do \
{ \
(node)->Next = (stackTop); \
(stackTop) = (node); \
} \
while (0)
void SingleLinkedListPushPrevious(auto*& stackTop, auto* node)
{
node->Previous = stackTop;
stackTop = node;
}
#define SingleLinkedListPushPrevious(stackTop, node) \
do \
{ \
(node)->Previous = (stackTop); \
(stackTop) = (node); \
} \
while (0)
void SingleLinkedListPopNext(auto*& stackTop)
{
stackTop = stackTop->Next;
}
#define SingleLinkedListPopNext(stackTop) \
do \
{ \
(stackTop) = (stackTop)->Next; \
} \
while (0)
// Double linked list
template <typename QueueType, typename QueueTypeNode>
void Enqueue(QueueType& queue, QueueTypeNode* node)
{
if (queue.First == nullptr)
{
queue.First = queue.Last = node;
node->Next = nullptr;
}
else
{
queue.Last->Next = node, queue.Last = node;
node->Next = nullptr;
}
queue.Nodecount += 1;
}
template <typename QueueType>
struct QueueNode
{
QueueType* Next;
};
// Double linked list queue macro
#define Enqueue(queue, node) \
do \
{ \
if ((queue).First == NULL) \
{ \
(queue).First = (queue).Last = (node); \
(node)->Next = NULL; \
} \
else \
{ \
(queue).Last->Next = (node); \
(queue).Last = (node); \
(node)->Next = NULL; \
} \
(queue).Nodecount += 1; \
} \
while (0)
#define DECLARE_QUEUE(type) \
typedef struct type##Queue type##Queue; \
struct type##Queue \
{ \
type* First; \
@@ -66,8 +71,7 @@ struct QueueNode
size_t Size; \
};
// TODO: homemade versions
#define MemSet memset
#define MemCopy memcpy
#define MemoryZero(dst, size) MemSet(dst, 0, size)
#define MemoryZero(dst, size) MemSet((dst), 0, (size))
#define MemZeroStruct(ptr) MemoryZero((ptr), sizeof(*(ptr)))
@@ -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;
};
-53
View File
@@ -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
View File
@@ -1,33 +1,18 @@
#pragma once
#pragma once
#include <algorithm>
#include <bit>
#include <cassert>
#include <cfloat>
#include <chrono>
#include <cinttypes>
#include <cmath>
#include <concepts>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#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 <assert.h>
#include <float.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <Juliet.h>
-4
View File
@@ -1,4 +0,0 @@
#pragma once
using Mutex = std::mutex;
using LockGuard = std::lock_guard<Mutex>;
+4 -4
View File
@@ -1,13 +1,13 @@
#pragma once
#pragma once
#include <Core/Common/String.h>
#include <time.h>
uint32 thread_id();
uint32 thread_id(void);
void set_thread_name(String name);
// TODO : Proper wait
inline void wait_ms(int milliseconds)
static inline void wait_ms(int milliseconds)
{
clock_t start_time = clock();
while (clock() < start_time + milliseconds)
+6 -5
View File
@@ -1,7 +1,8 @@
#pragma once
#pragma once
#include <Core/Memory/MemoryArena.h>
typedef struct thread_context thread_context;
struct thread_context
{
Arena* ScratchArenas[2];
@@ -10,10 +11,10 @@ struct thread_context
uint8 ThreadNameSize;
};
thread_context* thread_context_alloc();
void thread_context_release(NonNullPtr<thread_context> ctx);
void thread_context_select(NonNullPtr<thread_context> ctx);
thread_context* thread_context_current();
thread_context* thread_context_alloc(void);
void thread_context_release(thread_context* ctx);
void thread_context_select(thread_context* ctx);
thread_context* thread_context_current(void);
Arena* thread_context_get_scratch(Arena** conflicts, size_t count);
JULIET_API TempArena scratch_begin(Arena** conflicts, size_t count);
+1 -1
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <Core/Common/String.h>
#include <Graphics/MeshRenderer.h>
+25 -54
View File
@@ -5,31 +5,15 @@
#include <Core/Common/CRC32.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);
using serialize_fct_ptr = serialize_fct_type*;
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 = {};
}
typedef void (*serialize_fct_ptr)(Archive* ar, uint16 version, void* payload);
typedef void (*initialize_fct_ptr)(void* payload);
struct Class
{
uint32 CRC;
String Name;
uint8 kind;
uint16 version;
const Class* base_class;
@@ -37,45 +21,32 @@ struct Class
serialize_fct_ptr serialize_fct;
size_t size_of;
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) \
constexpr Class class_kind_##cls = MakeClass(ConstString(#cls), 0, (version), (base_class), sizeof(cls), \
alignof(cls), (&initialize_thunk<cls>), (&serialize_thunk<cls>)); \
Class* cls::kind = const_cast<Class*>(&class_kind_##cls);
#define DEFINE_CLASS_VERSIONED(cls, version_num, base_class_ptr) \
const Class class_kind_##cls = { \
.Name = ConstString(#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,
initialize_fct_ptr init_fct, serialize_fct_ptr serde_fct)
#define ClassKind(cls) (&class_kind_##cls)
static inline uint32 class_get_crc(const Class* cls)
{
Class cls = {};
cls.CRC = crc32(name.Str, name.Size);
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;
Assert(cls != NULL);
return crc32_str(cls->Name);
}
bool IsA(const Class& query, const Class* target);
JULIET_API bool8 IsA(const Class* query, const Class* target);
template <typename type>
bool IsA(const Class& cls)
{
return IsA(cls, type::kind);
}
#define IsClassA(cls_ptr, target_type) IsA((cls_ptr), ClassKind(target_type))
JULIET_API void serialize(Archive& ar, NonNullPtr<const Class> cls, void* instance);
JULIET_API void serialize_class(Archive* ar, const Class* cls, void* instance);
+2 -5
View File
@@ -1,12 +1,9 @@
#pragma once
#pragma once
#include <Juliet.h>
#if JULIET_DEBUG
namespace Debug
{
JULIET_API void DebugDrawMemoryArena();
} // namespace Debug
JULIET_API void Debug_DebugDrawMemoryArena(void);
#endif
+29 -16
View File
@@ -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;
struct Engine
typedef struct ApplicationCallbacks ApplicationCallbacks;
struct ApplicationCallbacks
{
IApplication* Application = nullptr;
Arena* PlatformArena = nullptr;
Arena* AssetArena = nullptr;
void (*Init)(Arena* platformArena);
void (*Shutdown)(void);
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);
void ShutdownEngine();
typedef struct Engine Engine;
struct Engine
{
ApplicationCallbacks Application;
Arena* PlatformArena;
Arena* AssetArena;
};
void LoadApplication(IApplication& app);
void UnloadApplication();
void RunEngine();
extern Arena* GetPlatformArena();
JULIET_API void StartApplication(ApplicationCallbacks app, JulietInit_Flags flags);
JULIET_API void InitializeEngine(JulietInit_Flags flags);
JULIET_API void ShutdownEngine(void);
JULIET_API void LoadApplication(ApplicationCallbacks app);
JULIET_API void UnloadApplication(void);
JULIET_API void RunEngine(void);
JULIET_API Arena* GetPlatformArena(void);
+6 -4
View File
@@ -1,8 +1,10 @@
#pragma once
using UserID = uint8;
#include <Juliet.h>
void initialize_user_system();
void shutdown_user_system();
typedef uint8 UserID;
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);
+15 -8
View File
@@ -1,8 +1,10 @@
#pragma once
#pragma once
#include <Core/Common/CoreUtils.h>
#include <Core/Math/Matrix.h>
#include <Juliet.h>
typedef struct Camera Camera;
struct Camera
{
index_t Index;
@@ -15,21 +17,26 @@ struct Camera
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 Camera* GetCurrentCamera();
JULIET_API extern Camera* GetCurrentCamera(void);
JULIET_API extern void SetCurrentCamera(index_t index);
+17 -9
View File
@@ -1,13 +1,21 @@
#pragma once
#pragma once
template <typename Type>
struct ColorType
#include <Core/Common/CoreTypes.h>
typedef struct FColor FColor;
struct FColor
{
Type R;
Type G;
Type B;
Type A;
float R;
float G;
float B;
float A;
};
using FColor = ColorType<float>;
using Color = ColorType<uint8>;
typedef struct Color Color;
struct Color
{
uint8 R;
uint8 G;
uint8 B;
uint8 A;
};
+5 -5
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <Core/Math/Vector.h>
#include <Graphics/Camera.h>
@@ -6,9 +6,9 @@
#include <Graphics/Graphics.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_DrawLine(const Vector3& start, const Vector3& end, const FColor& color, bool overlay);
extern JULIET_API void DebugDisplay_DrawSphere(const Vector3& center, float radius, 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(Vector3 center, float radius, FColor color, bool8 overlay);
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);
+78 -73
View File
@@ -1,6 +1,5 @@
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#include <Core/HAL/Display/Display.h>
#include <Core/Math/Shape.h>
@@ -13,11 +12,12 @@
// Graphics Interface
// Opaque types
struct CommandList;
struct GraphicsDevice;
struct Fence;
typedef struct CommandList CommandList;
typedef struct GraphicsDevice GraphicsDevice;
typedef struct Fence Fence;
// Parameters of an indirect draw command
typedef struct IndirectDrawCommand IndirectDrawCommand;
struct IndirectDrawCommand
{
uint32 VertexCount; // Number of vertices to draw
@@ -27,6 +27,7 @@ struct IndirectDrawCommand
};
// Parameters of an INDEXED indirect draw command
typedef struct IndexedIndirectDrawCommand IndexedIndirectDrawCommand;
struct IndexedIndirectDrawCommand
{
uint32 VertexCount; // Number of vertices to draw
@@ -37,6 +38,7 @@ struct IndexedIndirectDrawCommand
};
// Parameters of an INDEXED Indirect Dispatch Command
typedef struct IndirectDispatchCommand IndirectDispatchCommand;
struct IndirectDispatchCommand
{
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
};
enum class QueueType : uint8
typedef uint8 QueueType;
enum QueueType_Enum
{
Graphics = 0,
Compute,
Copy,
Count
QueueType_Graphics = 0,
QueueType_Compute,
QueueType_Copy,
QueueType_Count
};
enum class IndexFormat : uint8
typedef uint8 IndexFormat;
enum IndexFormat_Enum
{
UInt16,
UInt32
IndexFormat_UInt16,
IndexFormat_UInt32
};
enum struct SwapChainComposition : uint8
typedef uint8 SwapChainComposition;
enum SwapChainComposition_Enum
{
SDR,
SDR_LINEAR,
HDR_EXTENDED_LINEAR,
HDR10_ST2084
SwapChainComposition_SDR,
SwapChainComposition_SDR_LINEAR,
SwapChainComposition_HDR_EXTENDED_LINEAR,
SwapChainComposition_HDR10_ST2084
};
// PresentMode from highest to lowest latency
// Vsync prevents tearing. Enqueue ready images.
// Mailbox prevents tearing. When image is ready, replace any pending image
// Immediate replace current image as soon as possible. Can cause tearing
enum struct PresentMode : uint8
typedef uint8 PresentMode;
enum PresentMode_Enum
{
VSync,
Mailbox,
Immediate
PresentMode_VSync,
PresentMode_Mailbox,
PresentMode_Immediate
};
typedef struct GraphicsViewPort GraphicsViewPort;
struct GraphicsViewPort
{
float X;
@@ -88,87 +95,85 @@ struct GraphicsViewPort
};
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
extern JULIET_API bool AttachToWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
extern JULIET_API void DetachFromWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
extern JULIET_API bool8 AttachToWindow(GraphicsDevice* device, Window* window);
extern JULIET_API void DetachFromWindow(GraphicsDevice* device, Window* window);
// SwapChain
extern JULIET_API bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window,
Texture** swapChainTexture);
extern JULIET_API bool WaitAndAcquireSwapChainTexture(NonNullPtr<CommandList> commandList,
NonNullPtr<Window> window, Texture** swapChainTexture);
extern JULIET_API bool WaitForSwapchain(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
extern JULIET_API TextureFormat GetSwapChainTextureFormat(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
extern JULIET_API bool8 AcquireSwapChainTexture(CommandList* commandList, Window* window, Texture** swapChainTexture);
extern JULIET_API bool8 WaitAndAcquireSwapChainTexture(CommandList* commandList, Window* window, Texture** swapChainTexture);
extern JULIET_API bool8 WaitForSwapchain(GraphicsDevice* device, Window* window);
extern JULIET_API TextureFormat GetSwapChainTextureFormat(GraphicsDevice* device, Window* window);
// Textures
extern JULIET_API Texture* CreateTexture(NonNullPtr<GraphicsDevice> device, const TextureCreateInfo& createInfo);
extern JULIET_API void DestroyTexture(NonNullPtr<GraphicsDevice> device, NonNullPtr<Texture> texture);
extern JULIET_API Texture* CreateTexture(GraphicsDevice* device, const TextureCreateInfo* createInfo);
extern JULIET_API void DestroyTexture(GraphicsDevice* device, Texture* texture);
// Command List
extern JULIET_API CommandList* AcquireCommandList(NonNullPtr<GraphicsDevice> device, QueueType queueType = QueueType::Graphics);
extern JULIET_API void SubmitCommandLists(NonNullPtr<CommandList> commandList);
extern JULIET_API CommandList* AcquireCommandList(GraphicsDevice* device, QueueType queueType);
extern JULIET_API void SubmitCommandLists(CommandList* commandList);
// RenderPass
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, ColorTargetInfo& colorTargetInfo,
DepthStencilTargetInfo* depthStencilTargetInfo = nullptr);
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList,
NonNullPtr<const ColorTargetInfo> colorTargetInfos, uint32 colorTargetInfoCount,
DepthStencilTargetInfo* depthStencilTargetInfo = nullptr);
extern JULIET_API void EndRenderPass(NonNullPtr<RenderPass> renderPass);
extern JULIET_API RenderPass* BeginRenderPass(CommandList* commandList, const ColorTargetInfo* colorTargetInfo,
DepthStencilTargetInfo* depthStencilTargetInfo);
extern JULIET_API RenderPass* BeginRenderPassTargets(CommandList* commandList,
const ColorTargetInfo* colorTargetInfos, uint32 colorTargetInfoCount,
DepthStencilTargetInfo* depthStencilTargetInfo);
extern JULIET_API void EndRenderPass(RenderPass* renderPass);
extern JULIET_API void SetGraphicsViewPort(NonNullPtr<RenderPass> renderPass, const GraphicsViewPort& viewPort);
extern JULIET_API void SetScissorRect(NonNullPtr<RenderPass> renderPass, const struct Rectangle& rectangle);
extern JULIET_API void SetBlendConstants(NonNullPtr<RenderPass> renderPass, FColor blendConstants);
extern JULIET_API void SetStencilReference(NonNullPtr<RenderPass> renderPass, uint8 reference);
extern JULIET_API void SetGraphicsViewPort(RenderPass* renderPass, const GraphicsViewPort* viewPort);
extern JULIET_API void SetScissorRect(RenderPass* renderPass, const struct Rectangle* rectangle);
extern JULIET_API void SetBlendConstants(RenderPass* renderPass, FColor blendConstants);
extern JULIET_API void SetStencilReference(RenderPass* renderPass, uint8 reference);
extern JULIET_API void BindGraphicsPipeline(NonNullPtr<RenderPass> renderPass, NonNullPtr<GraphicsPipeline> graphicsPipeline);
extern JULIET_API void DrawPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numVertices, uint32 numInstances,
extern JULIET_API void BindGraphicsPipeline(RenderPass* renderPass, GraphicsPipeline* graphicsPipeline);
extern JULIET_API void DrawPrimitives(RenderPass* renderPass, uint32 numVertices, uint32 numInstances,
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);
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);
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);
// Fences
extern JULIET_API bool WaitUntilGPUIsIdle(NonNullPtr<GraphicsDevice> device);
extern JULIET_API bool8 WaitUntilGPUIsIdle(GraphicsDevice* device);
// Shaders
extern JULIET_API Shader* CreateShader(NonNullPtr<GraphicsDevice> device, String filename, ShaderCreateInfo& shaderCreateInfo);
extern JULIET_API void DestroyShader(NonNullPtr<GraphicsDevice> device, NonNullPtr<Shader> shader);
extern JULIET_API Shader* CreateShader(GraphicsDevice* device, String filename, ShaderCreateInfo* shaderCreateInfo);
extern JULIET_API void DestroyShader(GraphicsDevice* device, Shader* shader);
// Pipelines
extern JULIET_API GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GraphicsDevice> device,
const GraphicsPipelineCreateInfo& createInfo);
extern JULIET_API void DestroyGraphicsPipeline(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsPipeline> graphicsPipeline);
extern JULIET_API GraphicsPipeline* CreateGraphicsPipeline(GraphicsDevice* device,
const GraphicsPipelineCreateInfo* createInfo);
extern JULIET_API void DestroyGraphicsPipeline(GraphicsDevice* device, GraphicsPipeline* graphicsPipeline);
#if ALLOW_SHADER_HOT_RELOAD
// 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);
#endif
// Buffers
extern JULIET_API GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo);
extern JULIET_API GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device,
const TransferBufferCreateInfo& createInfo);
extern JULIET_API void* MapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
extern JULIET_API void UnmapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
extern JULIET_API void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
extern JULIET_API void UnmapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
extern JULIET_API void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset = 0,
size_t srcOffset = 0);
extern JULIET_API void CopyBufferToTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Texture> dst,
NonNullPtr<GraphicsTransferBuffer> src);
extern JULIET_API GraphicsBuffer* CreateGraphicsBuffer(GraphicsDevice* device, const BufferCreateInfo* createInfo);
extern JULIET_API GraphicsTransferBuffer* CreateGraphicsTransferBuffer(GraphicsDevice* device,
const TransferBufferCreateInfo* createInfo);
extern JULIET_API void* MapGraphicsBuffer(GraphicsDevice* device, GraphicsBuffer* buffer);
extern JULIET_API void UnmapGraphicsBuffer(GraphicsDevice* device, GraphicsBuffer* buffer);
extern JULIET_API void* MapGraphicsTransferBuffer(GraphicsDevice* device, GraphicsTransferBuffer* buffer);
extern JULIET_API void UnmapGraphicsTransferBuffer(GraphicsDevice* device, GraphicsTransferBuffer* buffer);
extern JULIET_API void CopyBuffer(CommandList* commandList, GraphicsBuffer* dst,
GraphicsTransferBuffer* src, size_t size, size_t dstOffset,
size_t srcOffset);
extern JULIET_API void CopyBufferToTexture(CommandList* commandList, Texture* dst,
GraphicsTransferBuffer* src);
extern JULIET_API void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer);
extern JULIET_API uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
extern JULIET_API uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<Texture> texture);
extern JULIET_API void TransitionBufferToReadable(CommandList* commandList, GraphicsBuffer* buffer);
extern JULIET_API uint32 GetBufferDescriptorIndex(GraphicsDevice* device, GraphicsBuffer* buffer);
extern JULIET_API uint32 GetTextureDescriptorIndex(GraphicsDevice* device, Texture* texture);
extern JULIET_API void DestroyGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
extern JULIET_API void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
extern JULIET_API void DestroyGraphicsBuffer(GraphicsDevice* device, GraphicsBuffer* buffer);
extern JULIET_API void DestroyGraphicsTransferBuffer(GraphicsDevice* device, GraphicsTransferBuffer* buffer);
+18 -12
View File
@@ -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,
IndexBuffer = 1 << 0,
ConstantBuffer = 1 << 1,
StructuredBuffer = 1 << 2,
BufferUsage_None = 0,
BufferUsage_IndexBuffer = 1 << 0,
BufferUsage_ConstantBuffer = 1 << 1,
BufferUsage_StructuredBuffer = 1 << 2,
};
enum class TransferBufferUsage : uint8
typedef uint8 TransferBufferUsage;
enum TransferBufferUsage_Enum
{
Download,
Upload
TransferBufferUsage_Download,
TransferBufferUsage_Upload
};
typedef struct BufferCreateInfo BufferCreateInfo;
struct BufferCreateInfo
{
size_t Size;
size_t Stride;
BufferUsage Usage;
bool IsDynamic;
bool8 IsDynamic;
};
typedef struct TransferBufferCreateInfo TransferBufferCreateInfo;
struct TransferBufferCreateInfo
{
size_t Size;
@@ -29,5 +35,5 @@ struct TransferBufferCreateInfo
};
// Opaque
struct GraphicsBuffer;
struct GraphicsTransferBuffer;
typedef struct GraphicsBuffer GraphicsBuffer;
typedef struct GraphicsTransferBuffer GraphicsTransferBuffer;
+9 -5
View File
@@ -1,19 +1,23 @@
#pragma once
#include <Core/Common/CoreTypes.h>
#if JULIET_DEBUG
#define ALLOW_SHADER_HOT_RELOAD 1
#else
#define ALLOW_SHADER_HOT_RELOAD 0
#endif
enum class GraphicsDriverType : uint8
typedef uint8 GraphicsDriverType;
enum GraphicsDriverType_Enum
{
Any = 0,
DX12 = 1,
GraphicsDriverType_Any = 0,
GraphicsDriverType_DX12 = 1,
};
typedef struct GraphicsConfig GraphicsConfig;
struct GraphicsConfig
{
GraphicsDriverType PreferredDriver = GraphicsDriverType::DX12;
bool EnableDebug;
GraphicsDriverType PreferredDriver;
bool8 EnableDebug;
};
+106 -90
View File
@@ -1,42 +1,47 @@
#pragma once
#pragma once
#include <Graphics/Shader.h>
#include <Graphics/Texture.h>
// Forward Declare
struct ColorTargetDescription;
typedef struct ColorTargetDescription ColorTargetDescription;
enum class FillMode : uint8
typedef uint8 FillMode;
enum FillMode_Enum
{
Solid,
Wireframe,
Count
FillMode_Solid,
FillMode_Wireframe,
FillMode_Count
};
enum class CullMode : uint8
typedef uint8 CullMode;
enum CullMode_Enum
{
None,
Front,
Back,
Count
CullMode_None,
CullMode_Front,
CullMode_Back,
CullMode_Count
};
enum class FrontFace : uint8
typedef uint8 FrontFace;
enum FrontFace_Enum
{
CounterClockwise,
Clockwise,
Count
FrontFace_CounterClockwise,
FrontFace_Clockwise,
FrontFace_Count
};
enum class PrimitiveType : uint8
typedef uint8 PrimitiveType;
enum PrimitiveType_Enum
{
TriangleList,
TriangleStrip,
LineList,
LineStrip,
PointList,
Count
PrimitiveType_TriangleList,
PrimitiveType_TriangleStrip,
PrimitiveType_LineList,
PrimitiveType_LineStrip,
PrimitiveType_PointList,
PrimitiveType_Count
};
typedef struct RasterizerState RasterizerState;
struct RasterizerState
{
FillMode FillMode;
@@ -46,17 +51,19 @@ struct RasterizerState
float DepthBiasConstantFactor; // How much depth value is added to each fragment
float DepthBiasClamp; // Maximum depth bias
float DepthBiasSlopeFactor; // Scalar applied to Fragment's slope
bool EnableDepthBias; // Bias fragment depth values
bool EnableDepthClip; // True to clip, false to clamp
bool8 EnableDepthBias; // Bias fragment depth values
bool8 EnableDepthClip; // True to clip, false to clamp
};
enum class VertexInputRate : uint8
typedef uint8 VertexInputRate;
enum VertexInputRate_Enum
{
Vertex, // Use vertex index
Instance, // Use instance index
Count
VertexInputRate_Vertex, // Use vertex index
VertexInputRate_Instance, // Use instance index
VertexInputRate_Count
};
typedef struct VertexBufferDescription VertexBufferDescription;
struct VertexBufferDescription
{
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
};
enum class VertexElementFormat : uint8
typedef uint8 VertexElementFormat;
enum VertexElementFormat_Enum
{
Invalid,
VertexElementFormat_Invalid,
/* 32-bit Signed Integers */
Int,
Int2,
Int3,
Int4,
VertexElementFormat_Int,
VertexElementFormat_Int2,
VertexElementFormat_Int3,
VertexElementFormat_Int4,
/* 32-bit Unsigned Integers */
UInt,
UInt2,
UInt3,
UInt4,
VertexElementFormat_UInt,
VertexElementFormat_UInt2,
VertexElementFormat_UInt3,
VertexElementFormat_UInt4,
/* 32-bit Floats */
Float,
Float2,
Float3,
Float4,
VertexElementFormat_Float,
VertexElementFormat_Float2,
VertexElementFormat_Float3,
VertexElementFormat_Float4,
/* 8-bit Signed Integers */
Byte2,
Byte4,
VertexElementFormat_Byte2,
VertexElementFormat_Byte4,
/* 8-bit Unsigned Integers */
UByte2,
UByte4,
VertexElementFormat_UByte2,
VertexElementFormat_UByte4,
/* 8-bit Signed Normalized */
Byte2_Norm,
Byte4_Norm,
VertexElementFormat_Byte2_Norm,
VertexElementFormat_Byte4_Norm,
/* 8-bit Unsigned Normalized */
UByte2_Norm,
UByte4_Norm,
VertexElementFormat_UByte2_Norm,
VertexElementFormat_UByte4_Norm,
/* 16-bit Signed Integers */
Short2,
Short4,
VertexElementFormat_Short2,
VertexElementFormat_Short4,
/* 16-bit Unsigned Integers */
UShort2,
UShort4,
VertexElementFormat_UShort2,
VertexElementFormat_UShort4,
/* 16-bit Signed Normalized */
Short2_Norm,
Short4_Norm,
VertexElementFormat_Short2_Norm,
VertexElementFormat_Short4_Norm,
/* 16-bit Unsigned Normalized */
UShort2_Norm,
UShort4_Norm,
VertexElementFormat_UShort2_Norm,
VertexElementFormat_UShort4_Norm,
/* 16-bit Floats */
Half2,
Half4,
VertexElementFormat_Half2,
VertexElementFormat_Half4,
//
Count
VertexElementFormat_Count
};
typedef struct VertexAttribute VertexAttribute;
struct VertexAttribute
{
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
};
typedef struct VertexInputState VertexInputState;
struct VertexInputState
{
const VertexBufferDescription* VertexBufferDescriptions;
@@ -143,42 +152,46 @@ struct VertexInputState
uint32 NumVertexAttributes;
};
typedef struct GraphicsPipelineTargetInfo GraphicsPipelineTargetInfo;
struct GraphicsPipelineTargetInfo
{
const ColorTargetDescription* ColorTargetDescriptions;
size_t NumColorTargets;
TextureFormat DepthStencilFormat;
bool HasDepthStencilTarget;
bool8 HasDepthStencilTarget;
};
enum class CompareOperation : uint8
typedef uint8 CompareOperation;
enum CompareOperation_Enum
{
Invalid,
Never, // The comparison always evaluates false.
Less, // The comparison evaluates reference < test.
Equal, // The comparison evaluates reference == test.
LessOrEqual, // The comparison evaluates reference <= test.
Greater, // The comparison evaluates reference > test.
NotEqual, // The comparison evaluates reference != test.
GreaterOrEqual, // The comparison evalutes reference >= test.
Always, // The comparison always evaluates true.
Count
CompareOperation_Invalid,
CompareOperation_Never, // The comparison always evaluates false.
CompareOperation_Less, // The comparison evaluates reference < test.
CompareOperation_Equal, // The comparison evaluates reference == test.
CompareOperation_LessOrEqual, // The comparison evaluates reference <= test.
CompareOperation_Greater, // The comparison evaluates reference > test.
CompareOperation_NotEqual, // The comparison evaluates reference != test.
CompareOperation_GreaterOrEqual, // The comparison evalutes reference >= test.
CompareOperation_Always, // The comparison always evaluates true.
CompareOperation_Count
};
enum class StencilOperation : uint8
typedef uint8 StencilOperation;
enum StencilOperation_Enum
{
Invalid,
Keep, // Keeps the current value.
Zero, // Sets the value to 0.
Replace, // Sets the value to reference.
IncrementAndClamp, // Increments the current value and clamps to the maximum value.
DecrementAndClamp, // Decrements the current value and clamps to 0.
Invert, // Bitwise-inverts the current value.
IncrementAndWrap, // Increments the current value and wraps back to 0.
DecrementAndWrap, // Decrements the current value and wraps to the maximum value.
Count
StencilOperation_Invalid,
StencilOperation_Keep, // Keeps the current value.
StencilOperation_Zero, // Sets the value to 0.
StencilOperation_Replace, // Sets the value to reference.
StencilOperation_IncrementAndClamp, // Increments the current value and clamps to the maximum value.
StencilOperation_DecrementAndClamp, // Decrements the current value and clamps to 0.
StencilOperation_Invert, // Bitwise-inverts the current value.
StencilOperation_IncrementAndWrap, // Increments the current value and wraps back to 0.
StencilOperation_DecrementAndWrap, // Decrements the current value and wraps to the maximum value.
StencilOperation_Count
};
typedef struct StencilOperationState StencilOperationState;
struct StencilOperationState
{
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.
};
typedef struct DepthStencilState DepthStencilState;
struct DepthStencilState
{
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.
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.
bool 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.
bool EnableStencilTest : 1; // true enables the stencil test.
bool8 EnableDepthTest : 1; // true enables the depth test.
bool8 EnableDepthWrite : 1; // true enables depth writes. Depth writes are always disabled when enable_depth_test is false.
bool8 EnableStencilTest : 1; // true enables the stencil test.
};
typedef struct MultisampleState MultisampleState;
struct MultisampleState
{
TextureSampleCount SampleCount;
uint32 SampleMask; // Which sample should be updated. If Enabled mask == false -> 0xFFFFFFFF
bool EnableMask;
bool8 EnableMask;
};
typedef struct GraphicsPipelineCreateInfo GraphicsPipelineCreateInfo;
struct GraphicsPipelineCreateInfo
{
Shader* VertexShader;
@@ -219,4 +235,4 @@ struct GraphicsPipelineCreateInfo
};
// Opaque type
struct GraphicsPipeline;
typedef struct GraphicsPipeline GraphicsPipeline;
+3 -3
View File
@@ -1,9 +1,9 @@
#pragma once
#pragma once
#include <Graphics/Graphics.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_NewFrame();
extern void ImGuiRenderer_NewFrame(void);
extern JULIET_API void ImGuiRenderer_Render(CommandList* cmdList, RenderPass* renderPass);
+3 -2
View File
@@ -1,8 +1,9 @@
#pragma once
#pragma once
#include <Juliet.h>
#include <Core/Math/Vector.h>
#include <Juliet.h>
typedef struct PointLight PointLight;
struct PointLight
{
Vector3 Position;
+11 -9
View File
@@ -1,17 +1,17 @@
#pragma once
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#include <Core/Math/Matrix.h>
#include <Core/Math/Vector.h>
struct Arena;
struct Vertex;
typedef struct Arena Arena;
typedef struct Vertex Vertex;
using MeshAssetID = index_t;
using MaterialAssetID = index_t;
using MeshInstanceID = index_t;
typedef index_t MeshAssetID;
typedef index_t MaterialAssetID;
typedef index_t MeshInstanceID;
typedef struct MeshAsset MeshAsset;
struct MeshAsset
{
String Name;
@@ -22,14 +22,16 @@ struct MeshAsset
index_t IndexOffset;
};
typedef struct MaterialAsset MaterialAsset;
struct MaterialAsset
{
Vector4 AlbedoColor = { 1.0f, 1.0f, 1.0f, 1.0f };
Vector4 AlbedoColor;
};
typedef struct MeshInstance MeshInstance;
struct MeshInstance
{
MeshAssetID MeshAsset;
MaterialAssetID MaterialAsset;
Matrix Transform = MatrixIdentity();
Matrix Transform;
};
+34 -35
View File
@@ -1,57 +1,56 @@
#pragma once
#pragma once
#include <Core/Container/Vector.h>
#include <Core/Math/Matrix.h>
#include <Graphics/GraphicsConfig.h>
#include <Graphics/Lighting.h>
#include <Graphics/Mesh.h>
#include <Graphics/PushConstants.h>
#include <Graphics/VertexData.h>
#include <Graphics/Mesh.h>
#include <Juliet.h>
struct GraphicsTransferBuffer;
struct RenderPass;
struct CommandList;
struct GraphicsBuffer;
struct Window;
struct GraphicsPipeline;
struct GraphicsDevice;
using LightID = index_t;
typedef struct GraphicsTransferBuffer GraphicsTransferBuffer;
typedef struct RenderPass RenderPass;
typedef struct CommandList CommandList;
typedef struct GraphicsBuffer GraphicsBuffer;
typedef struct Window Window;
typedef struct GraphicsPipeline GraphicsPipeline;
typedef struct GraphicsDevice GraphicsDevice;
typedef index_t LightID;
constexpr size_t kGeometryPage = Megabytes(64);
constexpr size_t kIndexPage = Megabytes(32);
constexpr size_t kDefaultMeshNumber = 500;
constexpr size_t kDefaultVertexCount = 2'000'000; // Fit less than one geometry page
constexpr size_t kDefaultIndexCount = 16'000'000; // Fit less than one index page
constexpr size_t kDefaultLightCount = 1024;
#define kGeometryPage Megabytes(64)
#define kIndexPage Megabytes(32)
#define kDefaultMeshNumber ((size_t)500)
#define kDefaultVertexCount ((size_t)2000000)
#define kDefaultIndexCount ((size_t)16000000)
#define kDefaultLightCount ((size_t)1024)
JULIET_API void InitializeMeshRenderer(NonNullPtr<Arena> assetArena, NonNullPtr<Arena> instanceArena);
[[nodiscard]] JULIET_API bool InitializeMeshRendererGraphics(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
JULIET_API void ShutdownMeshRendererGraphics();
JULIET_API void ShutdownMeshRenderer();
JULIET_API void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList);
JULIET_API void RenderMeshes(NonNullPtr<CommandList> cmdList, NonNullPtr<RenderPass> pass, const Matrix& viewProjection);
JULIET_API void InitializeMeshRenderer(Arena* assetArena, Arena* instanceArena);
JULIET_API bool8 InitializeMeshRendererGraphics(GraphicsDevice* device, Window* window);
JULIET_API void ShutdownMeshRendererGraphics(void);
JULIET_API void ShutdownMeshRenderer(void);
JULIET_API void LoadMeshesOnGPU(CommandList* cmdList);
JULIET_API void RenderMeshes(CommandList* cmdList, RenderPass* pass, const Matrix* viewProjection);
// Lights
[[nodiscard]] JULIET_API LightID AddPointLight(const PointLight& light);
JULIET_API void SetPointLightPosition(LightID id, const Vector3& position);
JULIET_API void SetPointLightColor(LightID id, const Vector3& color);
JULIET_API LightID AddPointLight(const PointLight* light);
JULIET_API void SetPointLightPosition(LightID id, Vector3 position);
JULIET_API void SetPointLightColor(LightID id, Vector3 color);
JULIET_API void SetPointLightRadius(LightID id, float radius);
JULIET_API void SetPointLightIntensity(LightID id, float intensity);
JULIET_API void ClearPointLights();
JULIET_API void SetGlobalLight(const Vector3& direction, const Vector3& color, float ambientIntensity);
JULIET_API void ClearPointLights(void);
JULIET_API void SetGlobalLight(Vector3 direction, Vector3 color, float ambientIntensity);
// Assets & Instances
[[nodiscard]] JULIET_API MeshAssetID GetOrCreateMeshAsset(String name);
[[nodiscard]] JULIET_API MeshInstanceID CreateMeshInstance(MeshAssetID meshAsset, MaterialAssetID materialAsset, const Matrix& transform);
JULIET_API void SetMeshInstanceTransform(MeshInstanceID id, const Matrix& transform);
JULIET_API MeshAssetID GetOrCreateMeshAsset(String name);
JULIET_API MeshInstanceID CreateMeshInstance(MeshAssetID meshAsset, MaterialAssetID materialAsset, const Matrix* transform);
JULIET_API void SetMeshInstanceTransform(MeshInstanceID id, const Matrix* transform);
// Primitives
JULIET_API MeshAssetID GetCubePrimitiveMeshAssetID();
JULIET_API MeshAssetID GetQuadPrimitiveMeshAssetID();
JULIET_API MeshAssetID GetSpherePrimitiveMeshAssetID();
JULIET_API MeshAssetID GetCubePrimitiveMeshAssetID(void);
JULIET_API MeshAssetID GetQuadPrimitiveMeshAssetID(void);
JULIET_API MeshAssetID GetSpherePrimitiveMeshAssetID(void);
#if ALLOW_SHADER_HOT_RELOAD
JULIET_API void ReloadMeshRendererShaders();
JULIET_API void ReloadMeshRendererShaders(void);
#endif
+2 -1
View File
@@ -1,9 +1,10 @@
#pragma once
#pragma once
#include <Core/Math/Matrix.h>
#include <Core/Math/Vector.h>
#include <Juliet.h>
typedef struct PushData PushData;
struct PushData
{
Matrix ViewProjection;
+53 -44
View File
@@ -1,23 +1,26 @@
#pragma once
#pragma once
#include <Graphics/Colors.h>
#include <Graphics/Texture.h>
enum struct LoadOperation : uint8
typedef uint8 LoadOperation;
enum LoadOperation_Enum
{
Load, // Load the texture from memory (preserve)
Clear, // Clear the texture
Ignore // Ignore the content of the texture (undefined)
LoadOperation_Load, // Load the texture from memory (preserve)
LoadOperation_Clear, // Clear the texture
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
Ignore, // Whatever is generated is ignored (undefined)
Resolve, // Resolve MipMaps into non mip map texture. Discard MipMap content
ResolveAndStore // Same but store the MipMap content to memory
StoreOperation_Store, // Store the result of the render pass into memory
StoreOperation_Ignore, // Whatever is generated is ignored (undefined)
StoreOperation_Resolve, // Resolve MipMaps into non mip map texture. Discard MipMap content
StoreOperation_ResolveAndStore // Same but store the MipMap content to memory
};
typedef struct ColorTargetInfo ColorTargetInfo;
struct ColorTargetInfo
{
Texture* TargetTexture;
@@ -27,18 +30,19 @@ struct ColorTargetInfo
uint32 DepthPlane;
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;
uint32 ResolveMipLevel;
uint32 ResolveLayerIndex;
bool CycleResolveTexture;
bool8 CycleResolveTexture;
FColor ClearColor;
LoadOperation LoadOperation;
StoreOperation StoreOperation;
};
typedef struct DepthStencilTargetInfo DepthStencilTargetInfo;
struct DepthStencilTargetInfo
{
Texture* TargetTexture;
@@ -51,44 +55,48 @@ struct DepthStencilTargetInfo
StoreOperation StoreOperation;
};
enum class BlendFactor : uint8
typedef uint8 BlendFactor;
enum BlendFactor_Enum
{
Invalid,
Zero,
One,
Src_Color,
One_Minus_Src_Color,
Dst_Color,
One_Minus_Dst_Color,
Src_Alpha,
One_Minus_Src_Alpha,
Dst_Alpha,
One_Minus_Dst_Alpha,
Constant_Color,
One_MINUS_Constant_Color,
Src_Alpha_Saturate, // min(source alpha, 1 - destination alpha)
Count
BlendFactor_Invalid,
BlendFactor_Zero,
BlendFactor_One,
BlendFactor_Src_Color,
BlendFactor_One_Minus_Src_Color,
BlendFactor_Dst_Color,
BlendFactor_One_Minus_Dst_Color,
BlendFactor_Src_Alpha,
BlendFactor_One_Minus_Src_Alpha,
BlendFactor_Dst_Alpha,
BlendFactor_One_Minus_Dst_Alpha,
BlendFactor_Constant_Color,
BlendFactor_One_MINUS_Constant_Color,
BlendFactor_Src_Alpha_Saturate, // min(source alpha, 1 - destination alpha)
BlendFactor_Count
};
enum class BlendOperation : uint8
typedef uint8 BlendOperation;
enum BlendOperation_Enum
{
Invalid,
Add, // (source * source_factor) + (destination * destination_factor)
Subtract, // (source * source_factor) - (destination * destination_factor)
ReverseSubtract, // (destination * destination_factor) - (source * source_factor)
Min, // min(source, destination)
Max, // max(source, destination)
Count
BlendOperation_Invalid,
BlendOperation_Add, // (source * source_factor) + (destination * destination_factor)
BlendOperation_Subtract, // (source * source_factor) - (destination * destination_factor)
BlendOperation_ReverseSubtract, // (destination * destination_factor) - (source * source_factor)
BlendOperation_Min, // min(source, destination)
BlendOperation_Max, // max(source, destination)
BlendOperation_Count
};
enum class ColorComponentFlags : uint8
typedef uint8 ColorComponentFlags;
enum ColorComponentFlags_Enum
{
R = 1u << 0,
G = 1u << 1,
B = 1u << 2,
A = 1u << 3
ColorComponentFlags_R = 1u << 0,
ColorComponentFlags_G = 1u << 1,
ColorComponentFlags_B = 1u << 2,
ColorComponentFlags_A = 1u << 3
};
typedef struct ColorTargetBlendState ColorTargetBlendState;
struct ColorTargetBlendState
{
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.
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.
bool EnableBlend : 1; // Whether blending is enabled for the color target.
bool EnableColorWriteMask : 1; // Whether the color write mask is enabled.
bool8 EnableBlend : 1; // Whether blending is enabled for the color target.
bool8 EnableColorWriteMask : 1; // Whether the color write mask is enabled.
};
typedef struct ColorTargetDescription ColorTargetDescription;
struct ColorTargetDescription
{
TextureFormat Format;
@@ -109,4 +118,4 @@ struct ColorTargetDescription
};
// Opaque Type
struct RenderPass;
typedef struct RenderPass RenderPass;
+8 -7
View File
@@ -1,20 +1,21 @@
#pragma once
#pragma once
#include <Core/Common/String.h>
// Opaque type
struct Shader;
typedef struct Shader Shader;
enum class ShaderStage : uint8
typedef uint8 ShaderStage;
enum ShaderStage_Enum
{
Vertex,
Fragment,
Compute
ShaderStage_Vertex,
ShaderStage_Fragment,
ShaderStage_Compute
};
typedef struct ShaderCreateInfo ShaderCreateInfo;
struct ShaderCreateInfo
{
ShaderStage Stage;
String EntryPoint;
};
+11 -12
View File
@@ -1,28 +1,27 @@
#pragma once
#pragma once
#include <Juliet.h>
#include <Core/Common/NonNullPtr.h>
#include <Core/Math/Matrix.h>
#include <Graphics/GraphicsConfig.h>
struct RenderPass;
struct CommandList;
struct Window;
struct GraphicsPipeline;
struct GraphicsDevice;
typedef struct RenderPass RenderPass;
typedef struct CommandList CommandList;
typedef struct Window Window;
typedef struct GraphicsPipeline GraphicsPipeline;
typedef struct GraphicsDevice GraphicsDevice;
typedef struct SkyboxRenderer SkyboxRenderer;
struct SkyboxRenderer
{
GraphicsDevice* Device;
GraphicsPipeline* Pipeline;
};
[[nodiscard]] JULIET_API bool InitializeSkyboxRenderer(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
JULIET_API void ShutdownSkyboxRenderer();
JULIET_API void RenderSkybox(NonNullPtr<CommandList> cmdList, NonNullPtr<RenderPass> pass, const Matrix& viewProjection);
JULIET_API bool8 InitializeSkyboxRenderer(GraphicsDevice* device, Window* window);
JULIET_API void ShutdownSkyboxRenderer(void);
JULIET_API void RenderSkybox(CommandList* cmdList, RenderPass* pass, const Matrix* viewProjection);
#if ALLOW_SHADER_HOT_RELOAD
JULIET_API void ReloadSkyboxShaders();
JULIET_API void ReloadSkyboxShaders(void);
#endif
+137 -131
View File
@@ -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 */
A8_UNORM,
R8_UNORM,
R8G8_UNORM,
R8G8B8A8_UNORM,
R16_UNORM,
R16G16_UNORM,
R16G16B16A16_UNORM,
R10G10B10A2_UNORM,
B5G6R5_UNORM,
B5G5R5A1_UNORM,
B4G4R4A4_UNORM,
B8G8R8A8_UNORM,
TextureFormat_A8_UNORM,
TextureFormat_R8_UNORM,
TextureFormat_R8G8_UNORM,
TextureFormat_R8G8B8A8_UNORM,
TextureFormat_R16_UNORM,
TextureFormat_R16G16_UNORM,
TextureFormat_R16G16B16A16_UNORM,
TextureFormat_R10G10B10A2_UNORM,
TextureFormat_B5G6R5_UNORM,
TextureFormat_B5G5R5A1_UNORM,
TextureFormat_B4G4R4A4_UNORM,
TextureFormat_B8G8R8A8_UNORM,
/* Compressed Unsigned Normalized Float Color Formats */
BC1_RGBA_UNORM,
BC2_RGBA_UNORM,
BC3_RGBA_UNORM,
BC4_R_UNORM,
BC5_RG_UNORM,
BC7_RGBA_UNORM,
TextureFormat_BC1_RGBA_UNORM,
TextureFormat_BC2_RGBA_UNORM,
TextureFormat_BC3_RGBA_UNORM,
TextureFormat_BC4_R_UNORM,
TextureFormat_BC5_RG_UNORM,
TextureFormat_BC7_RGBA_UNORM,
/* Compressed Signed Float Color Formats */
BC6H_RGB_FLOAT,
TextureFormat_BC6H_RGB_FLOAT,
/* Compressed Unsigned Float Color Formats */
BC6H_RGB_UFLOAT,
TextureFormat_BC6H_RGB_UFLOAT,
/* Signed Normalized Float Color Formats */
R8_SNORM,
R8G8_SNORM,
R8G8B8A8_SNORM,
R16_SNORM,
R16G16_SNORM,
R16G16B16A16_SNORM,
TextureFormat_R8_SNORM,
TextureFormat_R8G8_SNORM,
TextureFormat_R8G8B8A8_SNORM,
TextureFormat_R16_SNORM,
TextureFormat_R16G16_SNORM,
TextureFormat_R16G16B16A16_SNORM,
/* Signed Float Color Formats */
R16_FLOAT,
R16G16_FLOAT,
R16G16B16A16_FLOAT,
R32_FLOAT,
R32G32_FLOAT,
R32G32B32A32_FLOAT,
TextureFormat_R16_FLOAT,
TextureFormat_R16G16_FLOAT,
TextureFormat_R16G16B16A16_FLOAT,
TextureFormat_R32_FLOAT,
TextureFormat_R32G32_FLOAT,
TextureFormat_R32G32B32A32_FLOAT,
/* Unsigned Float Color Formats */
R11G11B10_UFLOAT,
TextureFormat_R11G11B10_UFLOAT,
/* Unsigned Integer Color Formats */
R8_UINT,
R8G8_UINT,
R8G8B8A8_UINT,
R16_UINT,
R16G16_UINT,
R16G16B16A16_UINT,
R32_UINT,
R32G32_UINT,
R32G32B32A32_UINT,
TextureFormat_R8_UINT,
TextureFormat_R8G8_UINT,
TextureFormat_R8G8B8A8_UINT,
TextureFormat_R16_UINT,
TextureFormat_R16G16_UINT,
TextureFormat_R16G16B16A16_UINT,
TextureFormat_R32_UINT,
TextureFormat_R32G32_UINT,
TextureFormat_R32G32B32A32_UINT,
/* Signed Integer Color Formats */
R8_INT,
R8G8_INT,
R8G8B8A8_INT,
R16_INT,
R16G16_INT,
R16G16B16A16_INT,
R32_INT,
R32G32_INT,
R32G32B32A32_INT,
TextureFormat_R8_INT,
TextureFormat_R8G8_INT,
TextureFormat_R8G8B8A8_INT,
TextureFormat_R16_INT,
TextureFormat_R16G16_INT,
TextureFormat_R16G16B16A16_INT,
TextureFormat_R32_INT,
TextureFormat_R32G32_INT,
TextureFormat_R32G32B32A32_INT,
/* SRGB Unsigned Normalized Color Formats */
R8G8B8A8_UNORM_SRGB,
B8G8R8A8_UNORM_SRGB,
TextureFormat_R8G8B8A8_UNORM_SRGB,
TextureFormat_B8G8R8A8_UNORM_SRGB,
/* Compressed SRGB Unsigned Normalized Color Formats */
BC1_RGBA_UNORM_SRGB,
BC2_RGBA_UNORM_SRGB,
BC3_RGBA_UNORM_SRGB,
BC7_RGBA_UNORM_SRGB,
TextureFormat_BC1_RGBA_UNORM_SRGB,
TextureFormat_BC2_RGBA_UNORM_SRGB,
TextureFormat_BC3_RGBA_UNORM_SRGB,
TextureFormat_BC7_RGBA_UNORM_SRGB,
/* Depth Formats */
D16_UNORM,
D24_UNORM,
D32_FLOAT,
D24_UNORM_S8_UINT,
D32_FLOAT_S8_UINT,
TextureFormat_D16_UNORM,
TextureFormat_D24_UNORM,
TextureFormat_D32_FLOAT,
TextureFormat_D24_UNORM_S8_UINT,
TextureFormat_D32_FLOAT_S8_UINT,
/* Compressed ASTC Normalized Float Color Formats*/
ASTC_4x4_UNORM,
ASTC_5x4_UNORM,
ASTC_5x5_UNORM,
ASTC_6x5_UNORM,
ASTC_6x6_UNORM,
ASTC_8x5_UNORM,
ASTC_8x6_UNORM,
ASTC_8x8_UNORM,
ASTC_10x5_UNORM,
ASTC_10x6_UNORM,
ASTC_10x8_UNORM,
ASTC_10x10_UNORM,
ASTC_12x10_UNORM,
ASTC_12x12_UNORM,
TextureFormat_ASTC_4x4_UNORM,
TextureFormat_ASTC_5x4_UNORM,
TextureFormat_ASTC_5x5_UNORM,
TextureFormat_ASTC_6x5_UNORM,
TextureFormat_ASTC_6x6_UNORM,
TextureFormat_ASTC_8x5_UNORM,
TextureFormat_ASTC_8x6_UNORM,
TextureFormat_ASTC_8x8_UNORM,
TextureFormat_ASTC_10x5_UNORM,
TextureFormat_ASTC_10x6_UNORM,
TextureFormat_ASTC_10x8_UNORM,
TextureFormat_ASTC_10x10_UNORM,
TextureFormat_ASTC_12x10_UNORM,
TextureFormat_ASTC_12x12_UNORM,
/* Compressed SRGB ASTC Normalized Float Color Formats*/
ASTC_4x4_UNORM_SRGB,
ASTC_5x4_UNORM_SRGB,
ASTC_5x5_UNORM_SRGB,
ASTC_6x5_UNORM_SRGB,
ASTC_6x6_UNORM_SRGB,
ASTC_8x5_UNORM_SRGB,
ASTC_8x6_UNORM_SRGB,
ASTC_8x8_UNORM_SRGB,
ASTC_10x5_UNORM_SRGB,
ASTC_10x6_UNORM_SRGB,
ASTC_10x8_UNORM_SRGB,
ASTC_10x10_UNORM_SRGB,
ASTC_12x10_UNORM_SRGB,
ASTC_12x12_UNORM_SRGB,
TextureFormat_ASTC_4x4_UNORM_SRGB,
TextureFormat_ASTC_5x4_UNORM_SRGB,
TextureFormat_ASTC_5x5_UNORM_SRGB,
TextureFormat_ASTC_6x5_UNORM_SRGB,
TextureFormat_ASTC_6x6_UNORM_SRGB,
TextureFormat_ASTC_8x5_UNORM_SRGB,
TextureFormat_ASTC_8x6_UNORM_SRGB,
TextureFormat_ASTC_8x8_UNORM_SRGB,
TextureFormat_ASTC_10x5_UNORM_SRGB,
TextureFormat_ASTC_10x6_UNORM_SRGB,
TextureFormat_ASTC_10x8_UNORM_SRGB,
TextureFormat_ASTC_10x10_UNORM_SRGB,
TextureFormat_ASTC_12x10_UNORM_SRGB,
TextureFormat_ASTC_12x12_UNORM_SRGB,
/* Compressed ASTC Signed Float Color Formats*/
ASTC_4x4_FLOAT,
ASTC_5x4_FLOAT,
ASTC_5x5_FLOAT,
ASTC_6x5_FLOAT,
ASTC_6x6_FLOAT,
ASTC_8x5_FLOAT,
ASTC_8x6_FLOAT,
ASTC_8x8_FLOAT,
ASTC_10x5_FLOAT,
ASTC_10x6_FLOAT,
ASTC_10x8_FLOAT,
ASTC_10x10_FLOAT,
ASTC_12x10_FLOAT,
ASTC_12x12_FLOAT,
TextureFormat_ASTC_4x4_FLOAT,
TextureFormat_ASTC_5x4_FLOAT,
TextureFormat_ASTC_5x5_FLOAT,
TextureFormat_ASTC_6x5_FLOAT,
TextureFormat_ASTC_6x6_FLOAT,
TextureFormat_ASTC_8x5_FLOAT,
TextureFormat_ASTC_8x6_FLOAT,
TextureFormat_ASTC_8x8_FLOAT,
TextureFormat_ASTC_10x5_FLOAT,
TextureFormat_ASTC_10x6_FLOAT,
TextureFormat_ASTC_10x8_FLOAT,
TextureFormat_ASTC_10x10_FLOAT,
TextureFormat_ASTC_12x10_FLOAT,
TextureFormat_ASTC_12x12_FLOAT,
Count
TextureFormat_Count
};
enum struct TextureUsageFlag : uint8
typedef uint8 TextureUsageFlag;
enum TextureUsageFlag_Enum
{
None = 0,
Sampler = 1 << 0, // Textures supports sampling
ColorTarget = 1 << 1, // Texture is color render target
DepthStencilTarget = 1 << 2, // Texture is depth stencil target
GraphicsStorageRead = 1 << 3, // Support Storage read at graphics stage
ComputeStorageRead = 1 << 4, // Support Storage read at compute stage
ComputeStorageWrite = 1 << 5, // Support Storage Write at compute stage
ComputeStorageSimultaneousReadWrite =
1 << 6, // Supports reads and writes in the same compute shader. Not equivalent to ComputeStorageRead | ComputeStorageWrite
TextureUsageFlag_None = 0,
TextureUsageFlag_Sampler = 1 << 0,
TextureUsageFlag_ColorTarget = 1 << 1,
TextureUsageFlag_DepthStencilTarget = 1 << 2,
TextureUsageFlag_GraphicsStorageRead = 1 << 3,
TextureUsageFlag_ComputeStorageRead = 1 << 4,
TextureUsageFlag_ComputeStorageWrite = 1 << 5,
TextureUsageFlag_ComputeStorageSimultaneousReadWrite = 1 << 6,
};
enum struct TextureType : uint8
typedef uint8 TextureType;
enum TextureType_Enum
{
Texture_2D,
Texture_2DArray,
Texture_3D,
Texture_3DArray,
Texture_Cube,
Texture_CubeArray,
TextureType_2D,
TextureType_2DArray,
TextureType_3D,
TextureType_3DArray,
TextureType_Cube,
TextureType_CubeArray,
};
enum struct TextureSampleCount : uint8
typedef uint8 TextureSampleCount;
enum TextureSampleCount_Enum
{
One,
Two,
Four,
Eight,
TextureSampleCount_One,
TextureSampleCount_Two,
TextureSampleCount_Four,
TextureSampleCount_Eight,
};
// Create Information structs
typedef struct TextureCreateInfo TextureCreateInfo;
struct TextureCreateInfo
{
TextureType Type;
@@ -177,4 +183,4 @@ struct TextureCreateInfo
};
// Opaque Type
struct Texture;
typedef struct Texture Texture;
+5 -2
View File
@@ -1,5 +1,8 @@
#pragma once
#pragma once
#include <Core/Common/CoreTypes.h>
typedef struct Vertex Vertex;
struct Vertex
{
float Position[3];
@@ -7,4 +10,4 @@ struct Vertex
float Color[4];
};
using Index = uint16;
typedef uint16 Index;
+1 -1
View File
@@ -15,7 +15,7 @@
#define JULIET_API
# endif
# else
# define JULIET_API (void) // Only Win32 is supported for now
# define JULIET_API
# 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();
}
+39
View File
@@ -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;
}
-35
View File
@@ -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 = {};
}
+699
View File
@@ -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;
}
-641
View File
@@ -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