diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 446d871..55eb6a2 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -74,7 +74,9 @@ v2 FooterMin = PanelMin; v2 PanelViewMax = PanelMax; panel_definition Definition = GlobalPanelDefs[Panel->PanelDefinitionIndex]; - Definition.Render(*Panel, PanelMin, PanelMax, RenderBuffer, State, Context, Mouse); + + +Definition.Render(*Panel, PanelMin, PanelMax, RenderBuffer, State, Context, Mouse); PushRenderOrthographic(RenderBuffer, WindowMin.x, WindowMin.y, WindowMax.x, WindowMax.y); DrawPanelFooter(Panel, RenderBuffer, FooterMin, FooterMax, State->Interface, Mouse); @@ -136,55 +138,6 @@ SACNSendDMXBufferListJob (s32 ThreadID, void* JobData) } } -internal void -LoadAssembly (app_state* State, context Context, char* Path) -{ - platform_memory_result TestAssemblyFile = Context.PlatformReadEntireFile(Path); - Assert(TestAssemblyFile.Size > 0); - - assembly_definition AssemblyDefinition = ParseAssemblyFile(TestAssemblyFile.Base, TestAssemblyFile.Size, &State->Transient); - - Context.PlatformFree(TestAssemblyFile.Base, TestAssemblyFile.Size); - - string PathString = MakeStringLiteral(Path); - s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(PathString.Memory, PathString.Length, '\\'); - string FileName = Substring(PathString, IndexOfLastSlash + 1); - - r32 Scale = 100; - memory_arena AssemblyArena = {}; - AssemblyArena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; - AssemblyArena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; - - assembly NewAssembly = ConstructAssemblyFromDefinition(AssemblyDefinition, - FileName, - v3{0, 0, 0}, - Scale, - AssemblyArena); - array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList); - PushElement(NewAssemblyHandle, &State->ActiveAssemblyIndecies); - - State->TotalLEDsCount += NewAssembly.LEDCount; -} - -internal void -UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context) -{ - assembly* Assembly = GetElementAtIndex(AssemblyIndex, State->AssemblyList); - State->TotalLEDsCount -= Assembly->LEDCount; - FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree); - - RemoveElementAtIndex(AssemblyIndex, &State->AssemblyList); - for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) - { - array_entry_handle Handle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); - if (Handle.Index == AssemblyIndex) - { - RemoveElementAtIndex(i, &State->ActiveAssemblyIndecies); - break; - } - } -} - //////////////////////////////////////////////////////////////////////// RELOAD_STATIC_DATA(ReloadStaticData) @@ -197,8 +150,6 @@ RELOAD_STATIC_DATA(ReloadStaticData) if (State->DefaultInputCommandRegistry.Size > 0) { - RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_MouseLeftButton, Command_Began, KeyCode_Invalid, - Begin3DViewMouseRotate); RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_U, Command_Began, KeyCode_Invalid, OpenUniverseView); RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_X, Command_Ended, KeyCode_Invalid, DeleteAnimationBlock); } @@ -534,56 +485,6 @@ PushRenderOrthographic(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHe if (Context.WindowIsVisible) { #if 0 - State->Camera.AspectRatio = (r32)Context.WindowWidth / (r32)Context.WindowHeight; - - m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera); - m44 ProjectionMatrix = GetCameraPerspectiveProjectionMatrix(State->Camera); - - r32 LEDHalfWidth = .5f; - - PushRenderPerspective(RenderBuffer, 0, 0, Context.WindowWidth / 2, Context.WindowHeight, State->Camera); - PushRenderClearScreen(RenderBuffer); - - // TODO(Peter): Pretty sure this isn't working right now - m44 FaceCameraMatrix = GetLookAtMatrix(v4{0, 0, 0, 1}, V4(State->Camera.Position, 1)); - FaceCameraMatrix = FaceCameraMatrix; - - DEBUG_IF(GlobalDebugServices->Interface.RenderSculpture) // DebugServices RenderSculpture Toggle - { - DEBUG_TRACK_SCOPE(RenderSculpture); - - s32 MaxLEDsPerJob = 2048; - render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount); - - for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) - { - array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); - assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); - s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob); - - for (s32 Job = 0; Job < JobsNeeded; Job++) - { - draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data); - JobData->LEDs = Assembly.LEDs; - JobData->Colors = Assembly.Colors; - JobData->StartIndex = Job * MaxLEDsPerJob; - JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, Assembly.LEDCount); - JobData->Batch = &RenderLEDsBatch; - JobData->FaceCameraMatrix; - JobData->ModelViewMatrix = ModelViewMatrix; - JobData->LEDHalfWidth = LEDHalfWidth; - - Context.GeneralWorkQueue->PushWorkOnQueue( - Context.GeneralWorkQueue, - DrawLEDsInBufferRangeJob, - JobData); - } - } - - Context.GeneralWorkQueue->DoQueueWorkUntilDone(Context.GeneralWorkQueue, 0); - Context.GeneralWorkQueue->ResetWorkQueue(Context.GeneralWorkQueue); - } - /////////////////////////////////////// // Interface ////////////////////////////////////// diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index bfad4dd..1318f21 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -181,18 +181,10 @@ typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); #define PANEL_RENDER_PROC(name) void name(panel Panel, v2 PanelMin, v2 PanelMax, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) typedef PANEL_RENDER_PROC(panel_render_proc); -struct panel_definition -{ - char* PanelName; - s32 PanelNameLength; - panel_init_proc* Init; - panel_cleanup_proc* Cleanup; - panel_render_proc* Render; -}; - #include "panels/foldhaus_panel_sculpture_view.h" #include "panels/foldhaus_panel_profiler.h" #include "panels/foldhaus_panel_dmx_view.h" #include "panels/foldhaus_panel_animation_timeline.h" +#include "panels/foldhaus_panel_hierarchy.h" #include "generated/foldhaus_panels_generated.h" diff --git a/src/foldhaus_assembly.cpp b/src/foldhaus_assembly.cpp index 8d59332..f9c700f 100644 --- a/src/foldhaus_assembly.cpp +++ b/src/foldhaus_assembly.cpp @@ -62,3 +62,52 @@ ConstructAssemblyFromDefinition (assembly_definition Definition, Assert(Assembly.LEDCount == Definition.TotalLEDCount); return Assembly; } + +internal void +LoadAssembly (app_state* State, context Context, char* Path) +{ + platform_memory_result TestAssemblyFile = Context.PlatformReadEntireFile(Path); + Assert(TestAssemblyFile.Size > 0); + + assembly_definition AssemblyDefinition = ParseAssemblyFile(TestAssemblyFile.Base, TestAssemblyFile.Size, &State->Transient); + + Context.PlatformFree(TestAssemblyFile.Base, TestAssemblyFile.Size); + + string PathString = MakeStringLiteral(Path); + s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(PathString.Memory, PathString.Length, '\\'); + string FileName = Substring(PathString, IndexOfLastSlash + 1); + + r32 Scale = 100; + memory_arena AssemblyArena = {}; + AssemblyArena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; + AssemblyArena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + + assembly NewAssembly = ConstructAssemblyFromDefinition(AssemblyDefinition, + FileName, + v3{0, 0, 0}, + Scale, + AssemblyArena); + array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList); + PushElement(NewAssemblyHandle, &State->ActiveAssemblyIndecies); + + State->TotalLEDsCount += NewAssembly.LEDCount; +} + +internal void +UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context) +{ + assembly* Assembly = GetElementAtIndex(AssemblyIndex, State->AssemblyList); + State->TotalLEDsCount -= Assembly->LEDCount; + FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree); + + RemoveElementAtIndex(AssemblyIndex, &State->AssemblyList); + for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) + { + array_entry_handle Handle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + if (Handle.Index == AssemblyIndex) + { + RemoveElementAtIndex(i, &State->ActiveAssemblyIndecies); + break; + } + } +} diff --git a/src/foldhaus_panel.cpp b/src/foldhaus_panel.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/foldhaus_panel.h b/src/foldhaus_panel.h index ee56081..10dd69c 100644 --- a/src/foldhaus_panel.h +++ b/src/foldhaus_panel.h @@ -290,11 +290,14 @@ DrawPanelOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, v2 WindowMin, v2 Wind if (Panel->SplitDirection == PanelSplit_NoSplit) { RenderPanel(Panel, PanelMin, PanelMax, WindowMin, WindowMax, RenderBuffer, State, Context, Mouse); - v4 BorderColor = v4{0, 1, 1, 1}; + v4 BorderColor = v4{0, 0, 0, 1}; + + #if 0 if (PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) { BorderColor = v4{1, 0, 1, 1}; } +#endif PushRenderOrthographic(RenderBuffer, WindowMin.x, WindowMin.y, WindowMax.x, WindowMax.y); DrawPanelBorder(*Panel, PanelMin, PanelMax, BorderColor, RenderBuffer); diff --git a/src/generated/foldhaus_panels_generated.h b/src/generated/foldhaus_panels_generated.h index fc7847a..6679244 100644 --- a/src/generated/foldhaus_panels_generated.h +++ b/src/generated/foldhaus_panels_generated.h @@ -1,7 +1,18 @@ -global_variable s32 GlobalPanelDefsCount = 4; +struct panel_definition +{ + char* PanelName; + s32 PanelNameLength; + panel_init_proc* Init; + panel_cleanup_proc* Cleanup; + panel_render_proc* Render; + input_command* InputCommands; +}; + +global_variable s32 GlobalPanelDefsCount = 5; global_variable panel_definition GlobalPanelDefs[] = { - { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render }, - { "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render }, - { "DMX View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render }, - { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render }, + { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands}, + { "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, 0 }, + { "DMX View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, 0 }, + { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, 0 }, + { "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, 0 }, }; \ No newline at end of file diff --git a/src/gs_language.h b/src/gs_language.h deleted file mode 100644 index d1b233a..0000000 --- a/src/gs_language.h +++ /dev/null @@ -1,423 +0,0 @@ -#ifndef GS_LANGUAGE_H - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) -#include -#include - -// TODO(Peter): Get rid of stdio and math.h -#include -#include - -#elif defined(__APPLE__) && defined(__MAC__) -// TODO(Peter): - -#else // Std lib -#include - -#endif - -#define internal static -#define local_persist static -#define global_variable static - - -#if !defined(GS_TYPES) - -#define GSINT64(s) (s) ## L -#define GSUINT64(s) (s) ## UL - -typedef signed char b8; -typedef short int b16; -typedef int b32; -typedef long long int b64; - -typedef unsigned char u8; -typedef unsigned short int u16; -typedef unsigned int u32; -typedef unsigned long long int u64; - -typedef signed char s8; -typedef short int s16; -typedef int s32; -typedef long long int s64; - -typedef float r32; -typedef double r64; - -#define INT8_MIN (-128) -#define INT16_MIN (-32767-1) -#define INT32_MIN (-2147483647-1) -#define INT64_MIN (-GSINT64(9223372036854775807)-1) - -#define INT8_MAX (127) -#define INT16_MAX (32767) -#define INT32_MAX (2147483647) -#define INT64_MAX (GSINT64(9223372036854775807)) - -#define UINT8_MAX (255) -#define UINT16_MAX (65535) -#define UINT32_MAX (4294967295U) -#define UINT64_MAX (GSUINT64(18446744073709551615)) - -#define FLOAT_MIN (1.175494351e-38F) -#define FLOAT_MAX (3.402823466e+38F) -#define DOUBLE_MIN (2.2250738585072014e-308) -#define DOUBLE_MAX (1.7976931348623158e+308) - -#define Kilobytes(Value) ((Value) * 1024) -#define Megabytes(Value) (Kilobytes(Value) * 1024) -#define Gigabytes(Value) (Megabytes(Value) * 1024) -#define Terabytes(Value) (Gigabytes(Value) * 1024) - -#define PI 3.14159265359 -#define PI_OVER_180 0.01745329251f - -#define GS_TYPES -#endif - - -#ifdef DEBUG - -static void DebugPrint(char* Format, ...); - -#if !defined(Assert) -// NOTE(peter): this writes to address 0 which is always illegal and will cause a crash -#define Assert(expression) if(!(expression)){ *((int *)0) = 5; } -#endif - -#define DEBUG_IF(condition) if (condition) - -#define InvalidCodePath Assert(0) -#define InvalidDefaultCase default: { Assert(0); } -#define DebugBreak __debugbreak() - -#define STBI_ASSERT(x) Assert(x) - -#ifdef GS_TEST_SUTE -#define TestClean(v, c) SuccessCount += Test(v, c, &TestCount) -internal s32 -Test(b32 Result, char* Description, s32* Count) -{ - char* Passed = (Result ? "Success" : "Failed"); - if (!Result) - DebugPrint("%s:\n................................................%s\n\n", Description, Passed); - - *Count = *Count + 1; - return (Result ? 1 : 0); -} -#endif // GS_TEST_SUTE - -#else - -#define Assert(expression) -#define InvalidCodePath -#define DEBUG_IF(condition) - -//#define DEBUG_TRACK_SCOPE(a) - -#endif // DEBUG - -#ifndef GS_LANGUAGE_MATH - -#define GSZeroStruct(data) GSZeroMemory_((u8*)(&(data)), sizeof(data)) -#define GSZeroMemory(mem, size) GSZeroMemory_((u8*)(mem), (size)) -static void -GSZeroMemory_ (u8* Memory, s32 Size) -{ - for (int i = 0; i < Size; i++) { Memory[i] = 0; } -} - -#define GSMemCopy(from, to, size) GSMemCopy_((u8*)from, (u8*)to, size) -static void -GSMemCopy_ (u8* From, u8* To, s32 Size) -{ - for (int i = 0; i < Size; i++) { To[i] = From[i]; } -} - -#define GSMemSet(buffer, value, size) GSMemSet_((u8*)buffer, value, size) -internal void -GSMemSet_ (u8* Buffer, u8 Value, s32 Length) -{ - u8* Cursor = Buffer; - for (s32 i = 0; i < Length; i++) - { - *Cursor++ = Value; - } -} - -#define GSMinDef(type) static type GSMin(type A, type B) { return (A < B ? A : B); } -GSMinDef(s8) -GSMinDef(s16) -GSMinDef(s32) -GSMinDef(s64) -GSMinDef(u8) -GSMinDef(u16) -GSMinDef(u32) -GSMinDef(u64) -GSMinDef(r32) -GSMinDef(r64) -#undef GSMinDef - -#define GSMaxDef(type) static type GSMax(type A, type B) { return (A > B ? A : B); } -GSMaxDef(s8) -GSMaxDef(s16) -GSMaxDef(s32) -GSMaxDef(s64) -GSMaxDef(u8) -GSMaxDef(u16) -GSMaxDef(u32) -GSMaxDef(u64) -GSMaxDef(r32) -GSMaxDef(r64) -#undef GSMaxDef - -inline b32 XOR(b32 A, b32 B) -{ - b32 Result = (A == !B); - return Result; -} -#define GSClampDef(type) static type GSClamp(type Min, type V, type Max) { \ - type Result = V; \ - if (V < Min) { Result = Min; } \ - if (V > Max) { Result = Max; } \ - return Result; \ -} -GSClampDef(s8) -GSClampDef(s16) -GSClampDef(s32) -GSClampDef(s64) -GSClampDef(u8) -GSClampDef(u16) -GSClampDef(u32) -GSClampDef(u64) -GSClampDef(r32) -GSClampDef(r64) -#undef GSClampDef - -#define GSClamp01Def(type) static type GSClamp01(type V) { \ - type Min = 0; type Max = 1; \ - type Result = V; \ - if (V < Min) { Result = Min; } \ - if (V > Max) { Result = Max; } \ - return Result; \ -} -GSClamp01Def(r32) -GSClamp01Def(r64) -#undef GSClamp01Def - -#define GSAbsDef(type) static type GSAbs(type A) { return (A < 0 ? -A : A); } -GSAbsDef(s8) -GSAbsDef(s16) -GSAbsDef(s32) -GSAbsDef(s64) -GSAbsDef(r32) -GSAbsDef(r64) -#undef GSAbsDef - -#define GSPowDef(type) static type GSPow(type N, s32 Power) { \ - type Result = N; \ - for(s32 i = 1; i < Power; i++) { Result *= N; } \ - return Result; \ -} -GSPowDef(s8) -GSPowDef(s16) -GSPowDef(s32) -GSPowDef(s64) -GSPowDef(u8) -GSPowDef(u16) -GSPowDef(u32) -GSPowDef(u64) -GSPowDef(r32) -GSPowDef(r64) -#undef GSPowDef - - -#define GSLerpDef(type) type GSLerp(type A, type B, type Percent) { return (A * (1.0f - Percent))+(B * Percent);} -GSLerpDef(r32) -GSLerpDef(r64) -#undef GSLerpDef - -static r32 GSSqrt(r32 V) -{ - r32 Result = _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); - return Result; -} -#if 0 -// TODO(Peter): Need a way to split the input into two f32's to supply to _mm_sqrt_sd -static r64 GSSqrt(r64 V) -{ - r64 Result = _mm_cvtsd_f64(_mm_sqrt_sd(_mm_set_sd(V))); - return Result; -} -#endif - -static r32 DegreesToRadians (r32 Degrees) { return Degrees * PI_OVER_180; } -static r64 DegreesToRadians (r64 Degrees) { return Degrees * PI_OVER_180; } - -#define GSIsPowerOfTwoDef(type) static type IsPowerOfTwo(type V) { return (V & (V - 1)) == 0; } -GSIsPowerOfTwoDef(u8); -GSIsPowerOfTwoDef(u16); -GSIsPowerOfTwoDef(u32); -GSIsPowerOfTwoDef(u64); -#undef GSIsPowerOfTwoDef - -#define GSIsOddDef(type) inline type IsOdd(type V) { return (V & 1); } -GSIsOddDef(u8); -GSIsOddDef(u16); -GSIsOddDef(u32); -GSIsOddDef(u64); -GSIsOddDef(s8); -GSIsOddDef(s16); -GSIsOddDef(s32); -GSIsOddDef(s64); -#undef GSIsOddDef - -#define GSIntDivideRoundUpDef(type) static type IntegerDivideRoundUp (type A, type B) { r32 Result = (r32)A / (r32)B; Result += .99999f; return (type)Result; } -GSIntDivideRoundUpDef(u8); -GSIntDivideRoundUpDef(u16); -GSIntDivideRoundUpDef(u32); -GSIntDivideRoundUpDef(u64); -GSIntDivideRoundUpDef(s8); -GSIntDivideRoundUpDef(s16); -GSIntDivideRoundUpDef(s32); -GSIntDivideRoundUpDef(s64); -#undef GSIntDivideRoundUpDef - -#define GSRemapDef(type) \ -static type GSRemap(type Value, type OldMin, type OldMax, type NewMin, type NewMax) { \ - type Result = (Value - OldMin) / (OldMax - OldMin); \ - Result = (Result * (NewMax - NewMin)) + NewMin; \ - return Result; \ -} -GSRemapDef(u8); -GSRemapDef(u16); -GSRemapDef(u32); -GSRemapDef(u64); -GSRemapDef(s8); -GSRemapDef(s16); -GSRemapDef(s32); -GSRemapDef(s64); -GSRemapDef(r32); -GSRemapDef(r64); -#undef GSRemapDef - -#define GSTrigFunctionDef(name, type, func) static type name(type V) { return func(V); } -GSTrigFunctionDef(GSSin, r32, sinf); -GSTrigFunctionDef(GSSin, r64, sin); -GSTrigFunctionDef(GSCos, r32, cosf); -GSTrigFunctionDef(GSCos, r64, cos); -GSTrigFunctionDef(GSTan, r32, tanf); -GSTrigFunctionDef(GSTan, r64, tan); -#undef GSTrigFunctionDef - -static u8 -RoundToNearestPowerOfTwo (u8 V) -{ - u8 Result = 0; - - if (IsPowerOfTwo(V)) - { - Result = V; - } - else - { - Result = V - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result += 1; - } - - return Result; -} - -static u16 -RoundToNearestPowerOfTwo (u16 V) -{ - u16 Result = 0; - - if (IsPowerOfTwo(V)) - { - Result = V; - } - else - { - Result = V - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result |= Result >> 8; - Result += 1; - } - - return Result; -} - -static u32 -RoundToNearestPowerOfTwo (u32 V) -{ - u32 Result = 0; - - if (IsPowerOfTwo(V)) - { - Result = V; - } - else - { - Result = V - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result |= Result >> 8; - Result |= Result >> 16; - Result += 1; - } - - return Result; -} - -static u64 -RoundToNearestPowerOfTwo (u64 V) -{ - u64 Result = 0; - - if (IsPowerOfTwo(V)) - { - Result = V; - } - else - { - Result = V - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result |= Result >> 8; - Result |= Result >> 16; - Result |= Result >> 32; - Result += 1; - } - - return Result; -} - -#define GS_LANGUAGE_MATH -#endif // GS_LANGUAGE_MATH - -static u32 -HostToNetU32(u32 In) -{ - unsigned char *s = (unsigned char *)&In; - u32 Result = (u32)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); - return Result; -} - -static u16 -HostToNetU16(u16 In) -{ - unsigned char *s = (unsigned char *)&In; - u16 Result = (u16)(s[0] << 8 | s[1]); - return Result; -} - -#define GS_LANGUAGE_H -#endif diff --git a/src/gs_memory_arena.h b/src/gs_memory_arena.h deleted file mode 100644 index 7cf08f3..0000000 --- a/src/gs_memory_arena.h +++ /dev/null @@ -1,613 +0,0 @@ -// File: gs_memory_arena.h -// Description: Single header file library that defines a push-only memory arena -// Author: Peter Slattery -// Date Created: 2019-12-22 -// -// -// ----------------- -// Set Up -// ----------------- -// -// Include 'gs_memory_arena.h' in a file and start using it! (Simple! Nice!) -// -// ----------------- -// Usage -// ----------------- -// Simply create a memory_arena and use PushSize, PushStruct, or PushArray -// to allocate out of it. -// See Example Program below. -// -// While there are options you can set (see Options below), the library adheres -// to a 'zero-is-initialization' policy, that is, a memory_arena initialized to -// zero, under all default options, will 'just work'. -// -// Alignment: -// By default, the Push functions use 4 byte alignment -// If you need to control the alignment of an allocation, there are variants of the -// Push functions that allow for this: PushSizeAligned, PushStructAligned, and PushArrayAligned -// These functions simply take a final parameter which specifies the alignment. -// Note: Alignment must be a power of two -// -// ----------------- -// Options -// ----------------- -// -// DEBUG: -// Define DEBUG for debug functionality. -// -// To override the default assert function define GSMem_Assert(expression) -// before inluding this file. -// -// GS_MEMORY_NO_STD_LIBS: -// if you don't want stdlib.h to be included, define GS_MEMORY_NO_STD_LIBS -// before including this file. -// Note that if you do this, zero-is-initialization will no longer work for -// memory_arenas. You must either: -// 1. Set each memory_arena's Alloc and Realloc so they can grow fields -// 2. Set each memory_arena's ExpansionRule to ExpansionRule_Disallowed -// If DEBUG is defined, the program will assert if one of the 2 rules above -// aren't followed. -// -// memory_arena.Alloc and memory_arena.Realloc -// By default, memory_arena's will use malloc and realloc to grow. -// You can override this by setting the Alloc and Realloc function pointers -// of a memory_arena. See the example program below for an implementation of this. -// -// GS_MEMORY_BUFFER_SIZE: -// This defines the minimum buffer size for memory_arena's. If an arena doesn't have -// room to fit an allocation, it will allocate a new buffer no smaller than GS_MEMORY_BUFFER_SIZE -// and place the allocation in the new buffer. -// By default this is 4096 bytes. To override, define GS_MEMORY_BUFFER_SIZE before including -// this file -// -// GS_MEMORY_TRACK_ALLOCATIONS: -// If you want to keep records of each allocation performed in every arena, define -// GS_MEMORY_TRACK_ALLOCATIONS before including this file. -// When defined, memory arenas gain fields that allow them to keep a list of every -// allocation they contain. It also adds a footer on the end of each allocation that -// can be checked to ensure there are no writes to allocations that overflow their bounds -// Note that calling ClearArena also clears this list -// You can then call AssertAllocationsNoOverflow occasionally throughout your program -// to check that no allocations have been written beyond their boundaries -// -// -// Example Program -// (this compiles - copy it into its own file though) -#if 0 -#include "gs_memory_arena.h" - -// Places the characters 'gs' at the end of each allocation. This would allow for an external -// function to check that we haven't written past the end of an allocation -void* MallocWrapper(gs_mem_u32 Size) -{ - int SizeWithFooter = Size + (sizeof(char) * 2); - void* Result = malloc(SizeWithFooter); - char* Footer = (char*)(Result + Size); - Footer[0] = 'g'; - Footer[1] = 's'; - return Result; -} - -void* ReallocWrapper(void* Address, gs_mem_u32 Size) -{ - return realloc(Address, Size); -} - -int -main(int ArgCount, char** Args) -{ - memory_arena Arena = {}; -// Uncomment these lines for an example of how you can implement custom allocation functions - // Arena.Alloc = MallocWrapper; - // Arena.Realloc = ReallocWrapper; - - int ArrayLength = 10; - -int* A = PushArray(&Arena, int, ArrayLength); - int* B = PushArray(&Arena, int, ArrayLength); - int* C = PushArray(&Arena, int, ArrayLength); - int* D = PushArrayAligned(&Arena, int, ArrayLength, 8); - int* E = PushArrayAligned(&Arena, int, ArrayLength, 16); - - // Just ensure that we can actually write to each address of each array - for (s32 i = 0; i < ArrayLength; i++) - { - A[i] = i; - B[i] = i; - C[i] = i; - D[i] = i; - E[i] = i; - } - - ClearArena(&Arena); - - A = PushArray(&Arena, int, ArrayLength); -for (s32 i = 0; i < ArrayLength; i++) - { - A[i] = i; - } - - return 0; -} -#endif - -// ------------------- -// Begin Library -// ------------------- -#ifndef GS_MEMORY_ARENA_H - -#ifndef GS_MEMORY_NO_STD_LIBS - -// NOTE(Peter): We use this so that we can fall back on malloc and realloc -// in the event that a memory_arena needs to grow but doesn't have a -// alloc or realloc function pointer assigned to it. -// -// See GrowArena to see where this is used -// -#include - -#endif - -typedef unsigned char gs_mem_u8; -typedef unsigned int gs_mem_u32; -typedef unsigned long long int gs_mem_u64; - -#ifdef DEBUG -#if !defined(GSMem_Assert) -#define GSMem_Assert(expression) \ -if(!(expression)) { \ -*((int *)0) = 5; \ -} - -#endif -#else -#define GSMem_Assert(expression) -#endif - -enum gs_memory_expansion_rule -{ - MemoryExpansion_Allowed, // Zero is initialization lets the memory grow on its own - MemoryExpansion_OnlyIfFunctionsProvided, - MemoryExpansion_Disallowed, - MemoryExpansion_Count, -}; - -// NOTE(Peter): -// This rule is only here to allow for taking arena snapshots. The problem this solves -// is if you take a snapshot while there are 'holes' in memory_buffers behind the -// most recently added memory_buffer, take a snapshot of that arena, then push something -// on that fits in one of those holes, we will fill the hole and be unable to track/free -// that addition via the snapshot construct. -// -// By requiring that allocations in a buffer only come from the most recent memory_buffer -// we can very easily rewind the buffer to the correct location. -// Hence FindAddress_InLastBufferOnly -enum gs_memory_find_address_rule -{ - FindAddress_InAnyBuffer, - FindAddress_InLastBufferOnly, - FindAddress_Count, -}; - -typedef void* gs_memory_alloc(gs_mem_u32 Size); -typedef void* gs_memory_realloc(void* Address, gs_mem_u32 OldSize, gs_mem_u32 NewSize); -typedef void gs_memory_free(void* Address, gs_mem_u32 Size); - -#ifndef GS_MEMORY_BUFFER_SIZE -#define GS_MEMORY_BUFFER_SIZE 1024 -#endif - -#define GS_MEMORY_FOOTER_SIZE 4 -#define GS_MEMORY_FOOTER_0 'g' -#define GS_MEMORY_FOOTER_1 's' -#define GS_MEMORY_FOOTER_2 'p' -#define GS_MEMORY_FOOTER_3 's' - -struct tracked_allocation -{ -gs_mem_u8* Head; - gs_mem_u8* Footer; - char* File; - gs_mem_u32 LineNumber; -}; - -#define GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE 512 -struct tracked_allocation_buffer -{ - tracked_allocation Buffer[GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE]; -}; - -struct memory_buffer -{ - gs_mem_u8* Buffer; - gs_mem_u32 Size; - gs_mem_u32 Used; -}; - -struct memory_arena -{ - memory_buffer* Buffers; - gs_mem_u32 BuffersCount; - - gs_mem_u32 TotalUsed; - gs_mem_u32 TotalSize; - - gs_memory_find_address_rule FindAddressRule; - gs_memory_expansion_rule ExpansionRule; - gs_memory_alloc* Alloc; - gs_memory_realloc* Realloc; - -#ifdef GS_MEMORY_TRACK_ALLOCATIONS - tracked_allocation_buffer** AllocationBuffers; - gs_mem_u32 AllocationBuffersCount; - gs_mem_u32 AllocationsUsed; - #endif -}; - -struct address_and_buffer -{ - memory_buffer* Buffer; - gs_mem_u64 Address; - gs_mem_u32 SizeWithAlignment; -}; - -struct arena_snapshot -{ - gs_mem_u32 ArenaUsedAtSnapshot; - gs_mem_u32 HeadBufferUsedAtSnapshot; - gs_mem_u32 HeadBufferAtSnapshot; - memory_arena* Arena; - -#ifdef GS_MEMORY_TRACK_ALLOCATIONS - gs_mem_u32 AllocationsUsedAtSnapshot; - #endif -}; - -static void -FreeMemoryArena(memory_arena* Arena, gs_memory_free* Free) -{ - if (Free) - { -for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) - { - memory_buffer* Buffer = Arena->Buffers + i; - Free(Buffer->Buffer, Buffer->Size); - } - Free(Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount); - } - else - { -#ifdef GS_MEMORY_NO_STD_LIBS - GSMem_Assert(0); -#else - for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) - { - memory_buffer* Buffer = Arena->Buffers + i; - free(Buffer->Buffer); - } - free(Arena->Buffers); - #endif - } -} - -#define IsPowerOfTwo(v) ((v != 0) && ((v & (v - 1)) == 0)) - -inline gs_mem_u32 -GetAlignmentOffset (gs_mem_u64 Address, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) -{ - gs_mem_u32 AlignmentOffset = 0; -if (Address & AlignmentMask) - { - AlignmentOffset = Alignment - (Address & AlignmentMask); - } - return AlignmentOffset; -} - -static address_and_buffer -GetAlignedAddressInBuffer(memory_buffer* Buffer, gs_mem_u32 Size, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) -{ - address_and_buffer Result = {}; - - gs_mem_u64 HeadAddress = (gs_mem_u64)Buffer->Buffer + Buffer->Used; - gs_mem_u32 AlignmentOffset = GetAlignmentOffset(HeadAddress, Alignment, AlignmentMask); - gs_mem_u64 AlignedAddress = HeadAddress + AlignmentOffset; - -if (Buffer->Used + AlignmentOffset + Size <= Buffer->Size) - { - Result.Buffer = Buffer; - Result.Address = AlignedAddress; - Result.SizeWithAlignment = Size + AlignmentOffset; - } - - return Result; -} - -static address_and_buffer -FindAlignedAddressInBufferWithRoom(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) -{ -address_and_buffer Result = {}; - for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) - { - memory_buffer* At = Arena->Buffers + i; - GSMem_Assert(At); - - address_and_buffer AddressInCurrentBuffer = GetAlignedAddressInBuffer(At, Size, Alignment, AlignmentMask); - if (AddressInCurrentBuffer.Address != 0) - { - Result = AddressInCurrentBuffer; - break; - } - } - return Result; -} - -static gs_mem_u8* -ArenaAlloc(memory_arena* Arena, gs_mem_u32 Size) -{ - gs_mem_u8* Result = 0; - -if (Arena->Alloc) - { - Result = (gs_mem_u8*)Arena->Alloc(sizeof(gs_mem_u8) * Size); - } - else - { -#ifdef GS_MEMORY_NO_STD_LIBS - // NOTE(Peter): If you specify no std libs AND don't supply a allocation function - // we should assert as this is an invalid codepath - GSMem_Assert(0); -#else - Result = (gs_mem_u8*)malloc(sizeof(gs_mem_u8) * Size); - #endif - } - - return Result; -} - -static gs_mem_u8* -ArenaRealloc(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 OldSize, gs_mem_u32 NewSize) -{ - gs_mem_u8* Result = 0; - - if (Arena->Realloc != 0) - { - Result = (gs_mem_u8*)Arena->Realloc(Head, OldSize, NewSize); - } - else - { -#ifdef GS_MEMORY_NO_STD_LIBS - // NOTE(Peter): If you specify no std libs AND don't supply a reallocation function - // we should assert as this is an invalid codepath - GSMem_Assert(0); - #else - Result = (gs_mem_u8*)realloc(Head, NewSize); - #endif - } - - return Result; -} - -static memory_buffer* -GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded) -{ - GSMem_Assert(Arena->ExpansionRule != MemoryExpansion_Disallowed); - if (Arena->ExpansionRule == MemoryExpansion_OnlyIfFunctionsProvided) - { - GSMem_Assert((Arena->Alloc != 0) && (Arena->Realloc != 0)); - } - - gs_mem_u32 NewBuffersCount = (Arena->BuffersCount + 1); - gs_mem_u32 OldBuffersSize = sizeof(memory_buffer) * Arena->BuffersCount; - gs_mem_u32 NewBuffersSize = sizeof(memory_buffer) * NewBuffersCount; - Arena->Buffers = (memory_buffer*)ArenaRealloc(Arena, (gs_mem_u8*)Arena->Buffers, OldBuffersSize, NewBuffersSize); - Arena->BuffersCount = NewBuffersCount; - - memory_buffer* NewBuffer = Arena->Buffers + (Arena->BuffersCount - 1); - NewBuffer->Size = GS_MEMORY_BUFFER_SIZE; - if (SizeNeeded > NewBuffer->Size) - { - NewBuffer->Size = SizeNeeded; - } - - NewBuffer->Buffer = ArenaAlloc(Arena, sizeof(gs_mem_u8) * NewBuffer->Size); - NewBuffer->Used = 0; - - Arena->TotalSize += NewBuffer->Size; - return NewBuffer; -} - -#ifdef GS_MEMORY_TRACK_ALLOCATIONS - -#define DetermineAllocationSize(size) (size) + GS_MEMORY_FOOTER_SIZE -#define ClearAllocationsUsed(arena) (arena)->AllocationsUsed = 0 -#define ClearAllocationsUsedToSnapshot(arena, snapshot) \ -(arena)->AllocationsUsed = (snapshot).AllocationsUsedAtSnapshot; - -static void -TrackAllocation(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 Size, char* Filename, gs_mem_u32 LineNumber) -{ -gs_mem_u32 AllocationsMax = Arena->AllocationBuffersCount * GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - if (Arena->AllocationsUsed >= AllocationsMax) - { - gs_mem_u32 NewAllocationBuffersCount = Arena->AllocationBuffersCount + 1; - Arena->AllocationBuffers = (tracked_allocation_buffer**)ArenaRealloc(Arena, - (gs_mem_u8*)Arena->AllocationBuffers, - Arena->AllocationBuffersCount * sizeof(void*), -NewAllocationBuffersCount * sizeof(void*)); - Arena->AllocationBuffersCount = NewAllocationBuffersCount; - - gs_mem_u32 NewBufferIndex = Arena->AllocationBuffersCount - 1; - Arena->AllocationBuffers[NewBufferIndex] = (tracked_allocation_buffer*)ArenaAlloc(Arena, sizeof(tracked_allocation_buffer)); - } - - gs_mem_u32 AllocationIndex = Arena->AllocationsUsed++; - gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - gs_mem_u32 IndexInBuffer = AllocationIndex % GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - tracked_allocation_buffer* Buffer = Arena->AllocationBuffers[BufferIndex]; - tracked_allocation* NewAllocationTracker = Buffer->Buffer + IndexInBuffer; - - NewAllocationTracker->Head = Head; - -NewAllocationTracker->Footer = Head + Size - GS_MEMORY_FOOTER_SIZE; - NewAllocationTracker->Footer[0] = GS_MEMORY_FOOTER_0; -NewAllocationTracker->Footer[1] = GS_MEMORY_FOOTER_1; -NewAllocationTracker->Footer[2] = GS_MEMORY_FOOTER_2; -NewAllocationTracker->Footer[3] = GS_MEMORY_FOOTER_3; - - NewAllocationTracker->File = Filename; - NewAllocationTracker->LineNumber = LineNumber; -} - - inline bool -VerifyAllocationNoOverflow (tracked_allocation Allocation) -{ - bool Result = ((Allocation.Footer[0] == GS_MEMORY_FOOTER_0) && -(Allocation.Footer[1] == GS_MEMORY_FOOTER_1) && -(Allocation.Footer[2] == GS_MEMORY_FOOTER_2) && - (Allocation.Footer[3] == GS_MEMORY_FOOTER_3)); - return Result; -} - - static void -AssertAllocationsNoOverflow (memory_arena Arena) -{ - for (gs_mem_u32 AllocationIndex = 0; - AllocationIndex< Arena.AllocationsUsed; - AllocationIndex++) - { - gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - gs_mem_u32 IndexInBuffer = AllocationIndex % GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - - tracked_allocation_buffer* Buffer = Arena.AllocationBuffers[BufferIndex]; - tracked_allocation Allocation = Buffer->Buffer[IndexInBuffer]; - -GSMem_Assert(VerifyAllocationNoOverflow(Allocation)); - } -} - -#define PushSize(arena, size) PushSize_((arena), (size), 4, __FILE__, __LINE__) -#define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length, 4, __FILE__, __LINE__) -#define PushStruct(arena, type) (type*)PushSize_((arena), sizeof(type), 4, __FILE__, __LINE__) -#define PushSizeAligned(arena, size, alignment) PushSize_((arena), (size), (alignment), __FILE__, __LINE__) -#define PushArrayAligned(arena, type, length, alignment) (type*)PushSize_((arena), sizeof(type) * length, (alignment), __FILE__, __LINE__) -#define PushStructAligned(arena, type, alignment) (type*)PushSize_((arena), sizeof(type), (alignment), __FILE__, __LINE__) - -#else // GS_MEMORY_TRACK_ALLOCATIONS - -#define AssertAllocationsNoOverflow(arena) -#define DetermineAllocationSize(size) size -#define ClearAllocationsUsed(arena) -#define ClearAllocationsUsedToSnapshot(arena, snapshot) - -#define TrackAllocation(arena, head, size, filename, linenumber) - -#define PushSize(arena, size) PushSize_((arena), (size)) -#define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length) -#define PushStruct(arena, type) (type*)PushSize_((arena), sizeof(type)) -#define PushSizeAligned(arena, size, alignment) PushSize_((arena), (size), (alignment)) -#define PushArrayAligned(arena, type, length, alignment) (type*)PushSize_((arena), sizeof(type) * length, (alignment)) -#define PushStructAligned(arena, type, alignment) (type*)PushSize_((arena), sizeof(type), (alignment)) - -#endif // GS_MEMORY_TRACK_ALLOCATIONS - -static gs_mem_u8* -PushSize_(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment = 4, char* Filename = 0, gs_mem_u32 LineNumber = 0) -{ - // ie. Alignment = 4 = 100 (binary) - // 4 - 1 = 3 - // 100 - 1 = 011 which is a mask of the bits we don't want set in the start address - GSMem_Assert(IsPowerOfTwo(Alignment)); -gs_mem_u32 AlignmentMask = Alignment - 1; - - gs_mem_u32 AllocationSize = DetermineAllocationSize(Size); - - address_and_buffer ResultAddress = {}; - if (Arena->FindAddressRule == FindAddress_InAnyBuffer) - { - ResultAddress = FindAlignedAddressInBufferWithRoom(Arena, AllocationSize, Alignment, AlignmentMask); - } - else if (Arena->FindAddressRule == FindAddress_InLastBufferOnly - && Arena->BuffersCount > 0) - { - memory_buffer* LastBuffer = Arena->Buffers + Arena->BuffersCount - 1; - ResultAddress = GetAlignedAddressInBuffer(LastBuffer, Size, Alignment, AlignmentMask); - } - - if (ResultAddress.Address == 0) - { - memory_buffer* Buffer = GrowArena(Arena, AllocationSize); - ResultAddress = GetAlignedAddressInBuffer(Buffer, AllocationSize, Alignment, AlignmentMask); - } - GSMem_Assert(ResultAddress.Address != 0); -GSMem_Assert((ResultAddress.Address & AlignmentMask) == 0); - - gs_mem_u8* Result = (gs_mem_u8*)ResultAddress.Address; - ResultAddress.Buffer->Used += ResultAddress.SizeWithAlignment; - Arena->TotalUsed += ResultAddress.SizeWithAlignment; - - TrackAllocation(Arena, Result, AllocationSize, Filename, LineNumber); - - return Result; -} - -static void -ClearArena(memory_arena* Arena) -{ - for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) - { - memory_buffer* At = Arena->Buffers + i; - At->Used = 0; - } - - Arena->TotalUsed = 0; - ClearAllocationsUsed(Arena); -} - -static arena_snapshot -TakeSnapshotOfArena(memory_arena* Arena) -{ - Assert(Arena->FindAddressRule == FindAddress_InLastBufferOnly); - -arena_snapshot Result = {}; - Result.Arena = Arena; - Result.ArenaUsedAtSnapshot = Arena->TotalUsed; - if (Arena->BuffersCount > 0) - { - Result.HeadBufferAtSnapshot = Arena->BuffersCount - 1; - } - else - { - Result.HeadBufferAtSnapshot = 0; - } - - memory_buffer* HeadBuffer = Arena->Buffers + Result.HeadBufferAtSnapshot; - if (HeadBuffer) - { - Result.HeadBufferUsedAtSnapshot = HeadBuffer->Used; - } - -return Result; -} - -static void -ClearArenaToSnapshot(memory_arena* Arena, arena_snapshot Snapshot) -{ - Assert(Arena == Snapshot.Arena); - - memory_buffer* HeadBufferAtSnapshot = Arena->Buffers + Snapshot.HeadBufferAtSnapshot; - if (HeadBufferAtSnapshot) - { - HeadBufferAtSnapshot->Used = Snapshot.HeadBufferUsedAtSnapshot; - - for (gs_mem_u32 i = Snapshot.HeadBufferAtSnapshot + 1; i < Arena->BuffersCount; i++) - { - memory_buffer* Buffer = Arena->Buffers + i; - Buffer->Used = 0; - } - } - - Arena->TotalUsed = Snapshot.ArenaUsedAtSnapshot; - ClearAllocationsUsedToSnapshot(Arena, Snapshot); -} -#define GS_MEMORY_ARENA_H -#endif // GS_MEMORY_ARENA_H \ No newline at end of file diff --git a/src/gs_string.h b/src/gs_string.h deleted file mode 100644 index 2cd8158..0000000 --- a/src/gs_string.h +++ /dev/null @@ -1,2206 +0,0 @@ -#ifndef GS_STRING_H -//////////////////////////////////////////////////////////////// -// String -//////////////////////////////////////////////////////////////// - -struct string -{ - char* Memory; - s32 Length; - s32 Max; -}; - -//////////////////////////////////////////////////////////////// -// String Tokenizing -//////////////////////////////////////////////////////////////// - -struct tokenizer -{ - char* At; - char* Memory; - s32 MemoryLength; -}; - - -enum token_type -{ - Token_Error, - - Token_LeftParen, - Token_RightParen, - Token_LeftSquareBracket, - Token_RightSquareBracket, - Token_LeftCurlyBracket, - Token_RightCurlyBracket, - Token_Semicolon, - Token_Operator, - Token_Comma, - Token_Period, - Token_PointerReference, - - Token_PoundDefine, - Token_PoundUndef, - Token_PoundInclude, - Token_PoundIfDef, - Token_PoundIfNDef, - Token_PoundIf, - Token_PoundElif, - Token_PoundElse, - Token_PoundEndif, - Token_PoundError, - Token_PoundPragma, - - Token_Number, - Token_Char, - Token_String, - Token_Identifier, - - Token_Comment, - Token_MultilineComment, - - Token_Unknown, - Token_EndOfStream, -}; - -char* TokenNames[] = { - "Token_Error ", - "Token_LeftParen ", - "Token_RightParen ", - "Token_LeftSquareBracket ", - "Token_RightSquareBracket ", - "Token_LeftCurlyBracket ", - "Token_RightCurlyBracket ", - "Token_Semicolon ", - "Token_Operator ", - "Token_Comma ", - "Token_Period ", - "Token_PointerReference ", - "Token_PoundDefine ", - "Token_PoundUndef ", - "Token_PoundInclude ", - "Token_PoundIfDef ", - "Token_PoundIfNDef ", - "Token_PoundIf ", - "Token_PoundElif ", - "Token_PoundElse ", - "Token_PoundEndif ", - "Token_PoundError ", - "Token_PoundPragma ", - "Token_Number ", - "Token_Char ", - "Token_String ", - "Token_Identifier ", - "Token_Comment ", - "Token_MultilineComment ", - "Token_Unknown ", - "Token_EndOfStream ", -}; - -struct token -{ - token_type Type; - string Text; - token* Next; -}; - -//////////////////////////////////////////////////////////////// -// String Memory -//////////////////////////////////////////////////////////////// - -struct slot_header -{ - slot_header* Next; - s32 Size; -}; - -struct slot_arena -{ - u8* Memory; - s32 SlotSize; - s32 SlotCount; - slot_header* FreeList; -}; - -struct contiguous_slot_count_result -{ - s32 Count; - slot_header* LastContiguousSlot; -}; - - -//////////////////////////////////////////////////////////////// -// String Function Declarations -//////////////////////////////////////////////////////////////// - -// Utility -#if !defined GS_LANGUAGE_H - -static void GSZeroMemory (u8* Memory, s32 Size); -static s32 GSMin (s32 A, s32 B); -static s32 GSAbs (s32 A); -static float GSAbsF (float A); -static float GSPowF (float N, s32 Power); - -#endif - -// Setup - -#ifdef GS_MEMORY_H -#define PushString(str, arena, size) (str)->Memory = PushArray(arena, char, size); (str)->Length = 0; (str)->Max = size; -#endif - -static void InitializeEmptyString (string* String, char* Data, s32 DataSize); -static void InitializeString(string* String, char* Data, s32 Used, s32 Max); -static string InitializeEmptyString (char* Data, s32 DataSize); -static string InitializeString (char* Data, s32 Used, s32 Max); -static void ClearString (string* String); - -// Character Values -static bool IsSlash (char C); -static bool IsNewline (char C); -static bool IsWhitespace (char C); -static bool IsAlpha (char C); -static bool IsUpper (char C); -static bool IsLower (char C); -static char ToUpper (char C); -static char ToLower (char C); -static bool IsNumeric (char C); -static bool IsNumericExtended (char C); -static bool IsAlphaNumeric (char C); -static bool IsOperator (char C); -static bool CharsEqualCaseInsensitive(char A, char B); - -// Tokenizing -static b32 AtValidPosition(tokenizer Tokenizer); -static b32 AtValidToken(tokenizer Tokenizer); -static char* EatToNewLine(char* C); -static void EatToNewLine(tokenizer* T); -static char* EatWhitespace(char* C); -static void EatWhitespace(tokenizer* T); -static char* EatToWhitespace(char* C); -static void EatToWhitespace(tokenizer* T); -static char* EatToCharacter(char* C, char Char); -static void EatToCharacter(tokenizer* T, char Char); -static char* EatPastCharacter(char* C, char Char); -static void EatPastCharacter(tokenizer* T, char Char); -static char* EatNumber(char* C); -static void EatNumber(tokenizer* T); - -// Char/Char Array -static u32 CharToUInt (char C); -static s32 CharArrayLength (char* CharArray); -static bool CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength); -static bool CharArraysEqualUnsafe (char* A, char* B); -static void ReverseCharArray (char* Array, s32 Length); -#define FirstIndexOfCharInCharArray(array, find) IndexOfChar(array, 0, find) -static s32 IndexOfChar (char* Array, s32 Start, char Find); -#define FastLastIndexOfCharInCharArray(array, len, find) FastReverseIndexOfChar(array, len, 0, find) -static s32 FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find); -#define LastIndexOfCharInCharArray(array, find) ReverseIndexOfChar(array, 0, find) -static s32 ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find); -static b32 CharArrayContains(char* Array, char* CheckFor); -static b32 CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength); - -// String - -#define MakeStringBuffer(name, size) \ -char name##Backbuffer[(size)]; \ -string name = MakeString(name##Backbuffer, size); - -static string MakeString (char* Array, s32 Length, s32 Max); -static string MakeString (char* Array, s32 Length); -static string MakeString (char* Array); -static string MakeStringLiteral(char* Data); - -static bool StringsEqual (string A, string B); -static bool StringEqualsCharArray (string String, char* CharArray); -static bool StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength); -static s32 FindFirstChar (string String, char C); - -static void SetStringToChar (string* Dest, char C, s32 Count); -static void SetStringToCharArray (string* Dest, char* Source); - -static void ConcatString (string Source, string* Dest); -static void ConcatString (string Source, s32 Length, string* Dest); -static void ConcatCharToString(string* Dest, char C); -static void ConcatCharArrayToString (char* Source, string* Dest); -static void ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest); - -static void CopyStringTo (string Source, string* Dest); -static s32 CopyStringToCharArray (string Source, char* Dest, s32 DestLength); -static void CopyCharArrayToString (char* Src, string* Dest); -static void CopyCharArrayToString (char* Src, s32 SrcLength, string* Dest); -static s32 CopyCharArray (char* Source, char* Dest, s32 DestLength); -static s32 CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset); - -static void InsertChar (string* String, char Char, s32 Index); -static void InsertStringAt (string* Dest, string Source, s32 At); -static void RemoveCharAt (string* String, s32 Index); - -static s32 IndexOfChar(string String, char C); -static s32 LastIndexOfChar(string String, char C); -static string Substring (string* String, s32 Start, s32 End); -static string Substring (string* String, s32 Start); - -static b32 StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength); -static b32 StringContainsString(string SearchIn, string SearchFor); -static b32 StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength); -static b32 StringContainsStringCaseInsensitive(string SearchIn, string SearchFor); - -static void NullTerminate (string* String); - - -// Parsing -enum parse_type -{ - ParseType_UnsignedInt, - ParseType_SignedInt, - ParseType_Float, -}; - -struct parse_result -{ - parse_type Type; - char* OnePastLast; - union - { - u32 UnsignedIntValue; - s32 SignedIntValue; - r32 FloatValue; - }; -}; - -enum format_flags -{ - FormatFlags_LeftJustify = 0x1, - FormatFlags_ForceSign = 0x2, - FormatFlags_ForceSpaceInsteadOfSign = 0x4, - FormatFlags_ForceDecimalOrPrependOx = 0x8, - FormatFlags_PadWithZeroesInsteadOfSpaces = 0x16, -}; - -static parse_result ParseUnsignedInt (char* String, s32 Length); -static parse_result ParseSignedInt (char* String, s32 Length); -static parse_result ParseFloat (char* String, s32 Length); - -// PrintF -static void PrintFArgList(char* Dest, s32 DestMax, char* Format, va_list Args); -static void PrintF(string* String, char* Format, ...); - -//////////////////////////////////////////////////////////////// -// String Memory Function Declarations -//////////////////////////////////////////////////////////////// - -static s32 CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize); -static bool SlotsAreContiguous (slot_header* First, slot_header* Second); -static contiguous_slot_count_result CountContiguousSlots (slot_header* First); -static slot_header* GetSlotAtOffset(slot_header* First, s32 Offset); -static slot_header* InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart); -static void AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage); -static string AllocStringFromStringArena (s32 Size, slot_arena* Storage); -static void FreeToStringArena (string* String, slot_arena* Storage); -static void ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage); - -//////////////////////////////////////////////////////////////// -// String Utility Functions -//////////////////////////////////////////////////////////////// - -#if !defined GS_LANGUAGE_H - -static void -GSZeroMemory (u8* Memory, s32 Size) -{ - for (int i = 0; i < Size; i++) { Memory[i] = 0; } -} - -static s32 -GSMin (s32 A, s32 B) -{ - return (A < B ? A : B); -} - -static s32 -GSAbs (s32 A) -{ - return (A < 0 ? -A : A); -} - -static float -GSAbs (float A) -{ - return (A < 0 ? -A : A); -} - -static float -GSPow (float N, s32 Power) -{ - float Result = N; - for(s32 i = 1; i < Power; i++) { Result *= N; } - return Result; -} - -#endif - -//////////////////////////////////////////////////////////////// -// Init and Clear -//////////////////////////////////////////////////////////////// - -static void -InitializeEmptyString (string* String, char* Data, s32 DataSize) -{ - String->Memory = Data; - String->Max = DataSize; - String->Length = 0; -} - -static void -InitializeString(string* String, char* Data, s32 Used, s32 Max) -{ - String->Memory = Data; - String->Max = Max; - String->Length = Used; -} - -static string -InitializeEmptyString (char* Data, s32 DataSize) -{ - string Result = {}; - Result.Memory = Data; - Result.Max = DataSize; - Result.Length = 0; - return Result; -} - -static string -InitializeString (char* Data, s32 Used, s32 Max) -{ - string Result = {}; - Result.Memory = Data; - Result.Max = Max; - Result.Length = Used; - return Result; -} - -static void -ClearString (string* String) -{ - String->Memory = 0; - String->Max = 0; - String->Length = 0; -} - -//////////////////////////////////////////////////////////////// -// Char Value Types -//////////////////////////////////////////////////////////////// - -static bool IsSlash (char C) { return ((C == '\\') || (C == '/')); } -static bool IsNewline (char C) { return (C == '\n') || (C == '\r'); } -static bool IsWhitespace (char C) { return (C == ' ') || (C == '\t') || IsNewline(C); } -static bool IsAlpha (char C) -{ - // TODO(Peter): support UTF8 chars - return ((C >= 'A') && (C <= 'Z')) || ((C >= 'a') && (C <= 'z')) || (C == '_'); -} -static bool IsUpper (char C) -{ - return ((C >= 'A') && (C <= 'Z')); -} -static bool IsLower (char C) -{ - return ((C >= 'a') && (C <= 'z')); -} -static bool IsNumeric (char C) -{ - return (C >= '0') && (C <= '9'); -} -static bool IsNumericExtended (char C) -{ - return (IsNumeric(C) || (C == 'x') || (C == 'f') || (C == '.')); -} -static bool IsAlphaNumeric (char C) -{ - return IsAlpha(C) || IsNumeric(C); -} -static bool IsOperator (char C) -{ - return ((C == '+') || - (C == '-') || - (C == '*') || - (C == '/') || - (C == '=') || - (C == '%') || - (C == '<') || - (C == '>')); -} -static char ToUpper (char A) -{ - char Result = A; - if (IsLower(A)) - { - Result += 'A' - 'a'; - } - return Result; -} -static char ToLower (char A) -{ - char Result = A; - if (IsUpper(A)) - { - Result -= 'A' - 'a'; - } - return Result; -} -static bool CharsEqualCaseInsensitive (char A, char B) -{ - b32 Result = (ToLower(A) == ToLower(B)); - return Result; -} - -//////////////////////////////////////////////////////////////// -// Tokenizing -//////////////////////////////////////////////////////////////// - -static b32 -AtValidPosition (tokenizer Tokenizer) -{ - b32 Result = (Tokenizer.At - Tokenizer.Memory) <= Tokenizer.MemoryLength; - return Result; -} - -static b32 -AtValidToken(tokenizer Tokenizer) -{ - b32 Result = *Tokenizer.At && Tokenizer.At < (Tokenizer.Memory + Tokenizer.MemoryLength); - return Result; -} - -static char* -EatToNewLine(char* C) -{ - char* Result = C; - while (*Result && !IsNewline(*Result)) { Result++; } - if (*Result) { Result++; } // NOTE(Peter): eat past the newline character - return Result; -} - -static void -EatToNewLine(tokenizer* T) -{ - while (*T->At && !IsNewline(*T->At)) { T->At++; } - if (*T->At) { T->At++; } // NOTE(Peter): eat past the newline character -} - -static char* -EatWhitespace(char* C) -{ - char* Result = C; - while (*Result && IsWhitespace(*Result)) { Result++; } - return Result; -} - -static void -EatWhitespace(tokenizer* T) -{ - while (*T->At && IsWhitespace(*T->At)) { T->At++; } -} - -static char* -EatToWhitespace(char* C) -{ - char* Result = C; - while (*Result && !IsWhitespace(*Result)) { Result++; } - return Result; -} - -static void -EatToWhitespace(tokenizer* T) -{ - while (*T->At && !IsWhitespace(*T->At)) { T->At++; } -} - -static char* -EatToCharacter(char* C, char Char) -{ - char* Result = C; - while (*Result && *Result != Char) { Result++; } - return Result; -} - -static void -EatToCharacter(tokenizer* T, char Char) -{ - while (*T->At && *T->At != Char) { T->At++; } -} - -static char* -EatPastCharacter(char* C, char Char) -{ - char* Result = EatToCharacter(C, Char); - if (*Result && *Result == Char) { Result++; } - return Result; -} - -static void -EatPastCharacter(tokenizer* T, char Char) -{ - EatToCharacter(T, Char); - if (*T->At && *T->At == Char) { T->At++; } -} - -static char* -EatNumber(char* C) -{ - char* Result = C; - while (*Result && IsNumericExtended(*Result)) { Result++; } - return Result; -} - -static void -EatNumber(tokenizer* T) -{ - while (*T->At && IsNumericExtended(*T->At)) { T->At++; } -} - -//////////////////////////////////////////////////////////////// -// Basic Char Operations -//////////////////////////////////////////////////////////////// - -static u32 CharToUInt (char C) { - u32 Result = (C - '0'); - return Result; -} - -static s32 -CharArrayLength (char* Array) -{ - char* C = Array; - s32 Result = 0; - while (*C) - { - *C++; - Result++; - } - return Result; -} - -static s32 -NullTerminatedCharArrayLength (char* CharArray) -{ - char* Iter = CharArray; - while (*Iter) - { - *Iter++; - } - return (Iter - CharArray); -} - -static bool -CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength) -{ - bool Result = false; - if (ALength == BLength) - { - Result = true; - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < ALength; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - return Result; -} - -static bool -CharArraysEqualUnsafe (char* A, char* B) -{ - bool Result = true; - - char* AIter = A; - char* BIter = B; - while(*AIter && *BIter) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - if((*AIter && !*BIter) || (!*AIter && *BIter)) - { - Result = false; - } - - return Result; -} - -static bool -CharArraysEqualUpToLength (char* A, char* B, s32 Length) -{ - bool Result = true; - - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < Length; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - return Result; -} - -static void -ReverseCharArray (char* Array, s32 Length) -{ - char* ForwardIter = Array; - char* BackwardIter = Array + Length - 1; - for (s32 i = 0; i < (Length / 2); i++) - { - char F = *ForwardIter; - char B = *BackwardIter; - *ForwardIter++ = B; - *BackwardIter-- = F; - } -} - -static s32 -IndexOfChar (char* Array, s32 After, char Find) -{ - s32 Result = -1; - - s32 Counter = After; - char* Iter = Array + After; - while (*Iter) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - Counter++; - *Iter++; - } - - return Result; -} - -static s32 -FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find) -{ - s32 Result = -1; - - s32 Counter = Length - OffsetFromEnd; - char* Iter = Array + Length - OffsetFromEnd; - for (int i = 0; i < (Length - OffsetFromEnd); i++) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - - *Iter--; - Counter--; - } - - return Result; -} - -static s32 -ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find) -{ - s32 StringLength = NullTerminatedCharArrayLength(Array); - return FastReverseIndexOfChar(Array, StringLength, OffsetFromEnd, Find); -} - -static b32 -CharArrayContains(char* Array, char* CheckFor) -{ - b32 Result = false; - - char* Src = Array; - while (*Src) - { - if (*Src == *CheckFor) - { - char* A = CheckFor; - char* B = Src; - while (*B && *A && *A == *B) - { - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - - return Result; -} - -static b32 -CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength) -{ - b32 Result = false; - - if (ArrayLength >= CheckForLength) - { - char* Src = Array; - for (s32 s = 0; s < ArrayLength; s++) - { - if (*Src == *CheckFor && (s + CheckForLength <= ArrayLength)) - { - char* A = CheckFor; - char* B = Src; - for (s32 d = 0; d < CheckForLength; d++) - { - if (*B != *A) { break; } - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - } - - return Result; -} - -//////////////////////////////////////////////////////////////// -// Basic String Operations -//////////////////////////////////////////////////////////////// - -static bool -StringsEqual (string A, string B) -{ - bool Result = false; - - if (A.Length == B.Length) - { - Result = true; - char* AIter = A.Memory; - char* BIter = B.Memory; - for (s32 i = 0; i < A.Length; i++) - { - if (*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - - return Result; -} - -static string -MakeString (char* Array, s32 Length, s32 Max) -{ - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Max; - return Result; -} - -static string -MakeString (char* Array, s32 Length) -{ - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Length; - return Result; -} - -static string -MakeString (char* Array) -{ - s32 Length = CharArrayLength (Array); - return MakeString(Array, Length); -} - -static string -MakeStringLiteral (char* String) -{ - string Result = {}; - Result.Memory = String; - Result.Max = CharArrayLength(String); - Result.Length = Result.Max; - return Result; -} - -static bool -StringEqualsCharArray (string String, char* CharArray) -{ - bool Result = true; - - char* S = String.Memory; - char* C = CharArray; - - s32 Count = 0; - while (*C && Count < String.Length) - { - if (*C++ != *S++) - { - Result = false; - break; - } - Count++; - } - - return Result; -} - -static bool -StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength) -{ - bool Result = false; - - if (CharArrayLength == String.Length) - { - Result = true; - - char* S = String.Memory; - char* C = CharArray; - for (s32 i = 0; i < String.Length; i++) - { - if (*C++ != *S++) - { - Result = false; - break; - } - } - } - - return Result; -} - -static s32 -FindFirstChar (string String, char C) -{ - s32 Result = -1; - - char* Iter = String.Memory; - for (int i = 0; i < String.Length; i++) - { - if (*Iter++ == C) - { - Result = i; - break; - } - } - - return Result; -} - -static void -SetStringToChar (string* Dest, char C, s32 Count) -{ - Assert(Count <= Dest->Max); - - char* Iter = Dest->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = C; - } - Dest->Length = Count; -} - -static void -SetStringToCharArray (string* Dest, char* Source) -{ - Dest->Length = 0; - - char* Src = Source; - char* Dst = Dest->Memory; - while (*Src && Dest->Length < Dest->Max) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatString (string Source, string* Dest) -{ - Assert((Dest->Length + Source.Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Source.Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatString (string Source, s32 Length, string* Dest) -{ - Assert(Length < Source.Length); - Assert((Dest->Length + Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatCharToString (string* Dest, char C) -{ - Assert(Dest->Length + 1 <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - *Dst = C; - Dest->Length++; -} - -static void -ConcatCharArrayToString (char* Source, string* Dest) -{ - Assert(CharArrayLength(Source) + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - while (Dest->Length < Dest->Max && - *Src) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest) -{ - Assert(SourceLength + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - for (int i = 0; i < SourceLength && Dest->Length < Dest->Max; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -CopyStringTo (string Source, string* Dest) -{ - char* Src = Source.Memory; - char* Dst = Dest->Memory; - s32 CopyLength = GSMin(Source.Length, Dest->Max); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - Dest->Length = Source.Length; -} - -static s32 -CopyStringToCharArray (string Source, char* Dest, s32 DestLength) -{ - char* Src = Source.Memory; - char* Dst = Dest; - s32 CopyLength = GSMin(Source.Length, DestLength); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - return CopyLength; -} - -static void -CopyCharArrayToString (char* Source, string* Dest) -{ - char* Src = Source; - char* Dst = Dest->Memory; - s32 Copied = 0; - while (*Src && Copied < Dest->Max) - { - *Dst++ = *Src++; - Copied++; - } - *Dst++ = 0; - Dest->Length = Copied; -} - -static void -CopyCharArrayToString (char* Source, s32 SourceLength, string* Dest) -{ - Assert(SourceLength <= Dest->Max); - - char* Src = Source; - char* Dst = Dest->Memory; - for (s32 i = 0; i < SourceLength; i++) - { - *Dst++ = *Src++; - } - *Dst++ = 0; - Dest->Length = SourceLength; -} - -static s32 -CopyCharArray (char* Source, char* Dest, s32 DestLength) -{ - char* Src = Source; - char* Dst = Dest; - s32 i = 0; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i; -} - -static s32 -CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset) -{ - Assert(Offset < DestLength); - - char* Src = Source; - char* Dst = Dest + Offset; - s32 i = Offset; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i - Offset; -} - -static void -InsertChar (string* String, char Char, s32 Index) -{ - Assert(Index >= 0 && Index < String->Max); - Assert(String->Length < String->Max); - - char* Src = String->Memory + String->Length - 1; - char* Dst = Src + 1; - for (int i = String->Length - 1; i >= Index; i--) - { - *Dst-- = *Src--; - } - - *(String->Memory + Index) = Char; - String->Length++; -} - -static void -RemoveCharAt (string* String, s32 Index) -{ - Assert(Index >= 0 && Index < String->Max); - - char* Dst = String->Memory + Index; - char* Src = Dst + 1; - for (int i = Index; i < String->Length; i++) - { - *Dst++ = *Src++; - } - *Dst = 0; - String->Length--; -} - -static s32 -IndexOfChar(string String, char C) -{ - s32 Result = -1; - char* At = String.Memory; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = i; - break; - } - At++; - } - return Result; -} - -static s32 -LastIndexOfChar(string String, char C) -{ - s32 Result = -1; - char* At = String.Memory + String.Length - 1; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = String.Length - i; - break; - } - At--; - } - return Result; -} - -static string -Substring (string String, s32 Start, s32 End) -{ - Assert(Start >= 0 && End > Start && End <= String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = End - Start; - return Result; -} - -static string -Substring (string String, s32 Start) -{ - Assert(Start >= 0 && Start < String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = String.Length - Start; - return Result; -} - -static b32 -StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength) -{ - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (*InAt == *ForAt) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; -} - -static b32 -StringContainsString(string SearchIn, string SearchFor) -{ - return StringContainsCharArray(SearchIn, SearchFor.Memory, SearchFor.Length); -} - -static b32 -StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength) -{ - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (CharsEqualCaseInsensitive(*InAt, *ForAt)) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; -} - -static b32 -StringContainsStringCaseInsensitive(string SearchIn, string SearchFor) -{ - return StringContainsCharArrayCaseInsensitive(SearchIn, SearchFor.Memory, SearchFor.Length); -} - -static void -NullTerminate (string* String) -{ - Assert(String->Length + 1 <= String->Max); - *(String->Memory + String->Length) = 0; - String->Length++; -} - -static void -InsertStringAt (string* Dest, string Source, s32 At) -{ - Assert(At + Source.Length < Dest->Max); - Assert(At < Dest->Length); - - char* Src = Dest->Memory + Dest->Length; - char* Dst = Dest->Memory + Source.Length + Dest->Length; - for (s32 i = Dest->Length - 1; i >= At; i--) - { - *--Dst = *--Src; - } - - Src = Source.Memory; - Dst = Dest->Memory + At; - for (s32 j = 0; j < Source.Length; j++) - { - *Dst++ = *Src++; - } - - Dest->Length += Source.Length; -} - -//////////////////////////////////////////////////////////////// -// String Parsing -//////////////////////////////////////////////////////////////// - -static parse_result -ParseUnsignedInt (char* String, s32 Length) -{ - Assert(IsNumeric(*String)); - parse_result Result = {}; - Result.Type = ParseType_UnsignedInt; - - char* Iter = String; - u32 ResultValue = 0; - for (s32 i = 0; i < Length; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - Result.UnsignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseUnsignedIntUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseUnsignedInt(String, End - Start); -} - -static parse_result -ParseSignedInt (char* String, s32 Length) -{ - Assert(Length > 0); - parse_result Result = {}; - Result.Type = ParseType_SignedInt; - - s32 Negative = 1; - s32 LengthRemaining = Length; - s32 ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - ResultValue *= Negative; - - Result.SignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseSignedIntUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseSignedInt(String, End - Start); -} - -static parse_result -ParseFloat (char* String, s32 Length) -{ - parse_result Result = {}; - Result.Type = ParseType_Float; - - s32 Negative = 1; - s32 LengthRemaining = Length; - float ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - ResultValue = (float)CharToUInt(*Iter++) + (ResultValue * 10); - } - else if (*Iter == '.' || *Iter == 0) - { - LengthRemaining -= i; - break; - } - } - - if (*Iter == '.') - { - *Iter++; - float AfterPoint = 0; - s32 PlacesAfterPoint = 0; - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - AfterPoint = (float)CharToUInt(*Iter++) + (AfterPoint * 10); - PlacesAfterPoint++; - } - else - { - break; - } - } - - AfterPoint = AfterPoint / GSPow(10, PlacesAfterPoint); - ResultValue += AfterPoint; - } - - ResultValue *= Negative; - - Result.FloatValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseFloatUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseFloat(String, End - Start); -} - -static s32 -UIntToString (u32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) -{ - s32 Remaining = Int; - char* Iter = String; - while (Remaining > 0 && (Iter - String) < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - } - s32 CharsCopied = Iter - String; - ReverseCharArray(String, CharsCopied); - return CharsCopied; -} - -static s32 -IntToString (s32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) -{ - s32 Remaining = Int; - s32 CharsCopied = 0; - - char* Iter = String; - - bool Negative = Remaining < 0; - Remaining = GSAbs(Remaining); - - if (Remaining > 0) - { - while (Remaining > 0 && CharsCopied < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - CharsCopied++; - } - } - else if (Remaining == 0) - { - *Iter++ = '0'; - } - - if (Negative) - { - *Iter++ = '-'; - CharsCopied++; - } - - ReverseCharArray(String, CharsCopied); - return CharsCopied; -} - -static s32 -IntToString (s32 Int, char* String, s32 MaxLength, s32 Offset, b32 FormatFlags = 0, s32 MinimumWidth = 0) -{ - char* StringStart = String + Offset; - s32 LengthWritten = IntToString(Int, StringStart, MaxLength - Offset); - return LengthWritten; -} - -static s32 -FloatToString(float Float, char *String, s32 MaxLength, s32 AfterPoint = 0, b32 FormatFlags = 0, s32 MinimumWidth = 0) -{ - s32 IPart = (s32)Float; - float FPart = GSAbs(Float - (float)IPart); - - s32 i = IntToString(IPart, String, MaxLength); - - if (AfterPoint > 1) - { - String[i++] = '.'; - - s32 FPartInt = FPart * GSPow(10, AfterPoint); - i += IntToString(FPartInt, String, MaxLength, i, 0, 0); - } - - return i; -} - -//////////////////////////////////////////////////////////////// -// PrintF -//////////////////////////////////////////////////////////////// - -static void -OutChar (string* String, char C) -{ - if (String->Length < String->Max) - { - String->Memory[String->Length] = C; - String->Length++; - } -} - -char OctalDigits[] = "01234567"; -char DecimalDigits[] = "0123456789"; -char HexDigits[] = "0123456789ABCDEF"; - -static void -U64ToASCII (string* String, u64 Value, s32 Base, char* Digits) -{ - u64 ValueRemaining = Value; - char* Start = String->Memory + String->Length; - do { - s32 DigitsIndex = ValueRemaining % Base; - char Digit = Digits[DigitsIndex]; - OutChar(String, Digit); - ValueRemaining /= Base; - }while (ValueRemaining); - char* End = String->Memory + String->Length; - - while (Start < End) - { - End--; - char Temp = *End; - *End = *Start; - *Start = Temp; - *Start++; - } -} - -static void -F64ToASCII (string* String, r64 Value, s32 Precision) -{ - if (Value < 0) - { - OutChar(String, '-'); - Value = -Value; - } - - u64 IntegerPart = (u64)Value; - Value -= IntegerPart; - - U64ToASCII(String, IntegerPart, 10, DecimalDigits); - - OutChar(String, '.'); - - for (s32 i = 0; i < Precision; i++) - { - Value *= 10.f; - u32 DecimalPlace = Value; - Value -= DecimalPlace; - OutChar(String, DecimalDigits[DecimalPlace]); - } -} - -internal s64 -ReadVarArgsSignedInteger (s32 Width, va_list* Args) -{ - s64 Result = 0; - switch (Width) - { - case 1: { Result = (s64)va_arg(*Args, s8); } break; - case 2: { Result = (s64)va_arg(*Args, s16); } break; - case 4: { Result = (s64)va_arg(*Args, s32); } break; - case 8: { Result = (s64)va_arg(*Args, s64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal r64 -ReadVarArgsUnsignedInteger (s32 Width, va_list* Args) -{ - u64 Result = 0; - switch (Width) - { - case 1: { Result = (u64)va_arg(*Args, u8); } break; - case 2: { Result = (u64)va_arg(*Args, u16); } break; - case 4: { Result = (u64)va_arg(*Args, u32); } break; - case 8: { Result = (u64)va_arg(*Args, u64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal r64 -ReadVarArgsFloat (s32 Width, va_list* Args) -{ - r64 Result = 0; - switch (Width) - { - case 4: { Result = (r64)va_arg(*Args, r64); } break; - case 8: { Result = (r64)va_arg(*Args, r64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal s32 -PrintFArgsList (char* Dest, s32 DestMax, char* Format, va_list Args) -{ - char* DestAt = Dest; - - char* FormatAt = Format; - while (*FormatAt) - { - if (FormatAt[0] != '%') - { - *DestAt++ = *FormatAt++; - } - else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol - { - *DestAt++ = *FormatAt++; - } - else - { - FormatAt++; - - // Flags - if (FormatAt[0] == '-') - { - FormatAt++; - } - else if (FormatAt[0] == '+') - { - FormatAt++; - } - else if (FormatAt[0] == ' ') - { - FormatAt++; - } - else if (FormatAt[0] == '#') - { - FormatAt++; - } - else if (FormatAt[0] == '0') - { - FormatAt++; - } - - // Width - b32 WidthSpecified = false; - s32 Width = 0; - - if (IsNumeric(FormatAt[0])) - { - WidthSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Width = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - WidthSpecified = true; - Width = va_arg(Args, s32); - Assert(Width >= 0); - FormatAt++; - } - - // Precision - b32 PrecisionSpecified = false; - s32 Precision = 0; - - if (FormatAt[0] == '.') - { - FormatAt++; - if (IsNumeric(FormatAt[0])) - { - PrecisionSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Precision = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - PrecisionSpecified = true; - Precision = va_arg(Args, s32); - Assert(Precision >= 0); - FormatAt++; - } - } - - // Length - b32 LengthSpecified = false; - s32 Length = 4; - - if (FormatAt[0] == 'h' && FormatAt[1] == 'h') - { - LengthSpecified = true; - LengthSpecified = 1; - FormatAt += 2; - } - else if (FormatAt[0] == 'h') - { - LengthSpecified = true; - LengthSpecified = 2; - FormatAt++; - } - else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt += 2; - } - else if (FormatAt[0] == 'l') - { - LengthSpecified = true; - LengthSpecified = 4; - FormatAt++; - } - else if (FormatAt[0] == 'j') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt++; - } - else if (FormatAt[0] == 'z') - { - FormatAt++; - } - else if (FormatAt[0] == 't') - { - FormatAt++; - } - else if (FormatAt[0] == 'L') - { - FormatAt++; - } - - // Format Specifier - s32 DestLengthRemaining = DestMax - (DestAt - Dest); - - char Temp[64]; - string TempDest = MakeString(Temp, 0, 64); - - if (FormatAt[0] == 'd' || FormatAt[0] == 'i') - { - s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); - if (SignedInt < 0) - { - OutChar(&TempDest, '-'); - SignedInt *= -1; - } - U64ToASCII(&TempDest, (u64)SignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'u') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'o') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 8, OctalDigits); - } - else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 16, HexDigits); - } - else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') - { - r64 Float = ReadVarArgsFloat(Length, &Args); - s32 AfterPoint = 6; - if (PrecisionSpecified) - { - AfterPoint = Precision; - } - F64ToASCII(&TempDest, Float, AfterPoint); - } - else if (FormatAt[0] == 'c') - { - char InsertChar = va_arg(Args, char); - OutChar(&TempDest, InsertChar); - } - else if (FormatAt[0] == 's') - { - char* InsertString = va_arg(Args, char*); - - s32 InsertStringLength = CharArrayLength(InsertString); - if (PrecisionSpecified) - { - InsertStringLength = GSMin(InsertStringLength, Precision); - } - InsertStringLength = GSMin(DestLengthRemaining, InsertStringLength); - - for (s32 c = 0; c < InsertStringLength; c++) - { - OutChar(&TempDest, *InsertString++); - } - } - else if (FormatAt[0] == 'p') - { - // TODO(Peter): Pointer Address - } - else - { - // NOTE(Peter): Non-specifier character found - InvalidCodePath; - } - - for (s32 i = 0; i < TempDest.Length; i++) - { - *DestAt++ = TempDest.Memory[i]; - } - - *FormatAt++; - } - } - - s32 FormattedLength = DestAt - Dest; - return FormattedLength; -} - -internal void -PrintF (string* String, char* Format, ...) -{ - va_list Args; - va_start(Args, Format); - String->Length = PrintFArgsList(String->Memory, String->Max, Format, Args); - va_end(Args); -} - - -//////////////////////////////////////////////////////////////// -// String Memory Function Definitions -//////////////////////////////////////////////////////////////// - -static s32 -CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize) -{ - s32 SlotCount = RequestedSize / SlotSize; - if (SlotCount * SlotSize < RequestedSize) - { - SlotCount += 1; - } - return SlotCount; -} - -static bool -SlotsAreContiguous (slot_header* First, slot_header* Second) -{ - bool Result = false; - u8* FirstSlotNextAddress = (u8*)First + First->Size; - u8* SecondAddress = (u8*)Second; - Result = FirstSlotNextAddress == SecondAddress; - return Result; -} - -static contiguous_slot_count_result -CountContiguousSlots (slot_header* First) -{ - Assert(First != 0); - - contiguous_slot_count_result Result = {}; - Result.Count = 1; - - slot_header* IterPrev = First; - slot_header* Iter = First->Next; - while (Iter && SlotsAreContiguous(IterPrev, Iter)) - { - Result.Count++; - IterPrev = Iter; - Iter = Iter->Next; - } - - Result.LastContiguousSlot = IterPrev; - return Result; -} - -static slot_header* -GetSlotAtOffset(slot_header* First, s32 Offset) -{ - slot_header* Iter = First; - s32 Count = 0; - while (Count < Offset && Iter) - { - Iter = Iter->Next; - Count++; - } - return Iter; -} - -static slot_header* -InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart) -{ - slot_header* List = ListStart; - if (NewSlot < List) - { - NewSlot->Next = List; - List = NewSlot; - } - else - { - slot_header* PrevIter = List; - slot_header* Iter = List->Next; - while (Iter && NewSlot > Iter) - { - PrevIter = Iter; - Iter = Iter->Next; - } - - Assert(PrevIter); - if (PrevIter) - { - PrevIter->Next = NewSlot; - } - - if (Iter) - { - NewSlot->Next = Iter; - } - } - return List; -} - -static void -AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage) -{ - s32 SlotCount = CalculateSlotCountFromSize(Size, Storage->SlotSize); - slot_header* Slot = Storage->FreeList; - slot_header* PrevSlot = 0; - while (Slot) - { - contiguous_slot_count_result ContiguousSlots = CountContiguousSlots(Slot); - if (ContiguousSlots.Count >= SlotCount) - { - slot_header* NextStartSlot = GetSlotAtOffset(Slot, SlotCount); - if (PrevSlot) - { - PrevSlot->Next = NextStartSlot; - } - else - { - Storage->FreeList = NextStartSlot; - } - break; - } - else - { - PrevSlot = Slot; - Slot = Slot->Next; - } - } - - if (Slot) - { - String->Memory = (char*)Slot; - GSZeroMemory((u8*)String->Memory, SlotCount * Storage->SlotSize); - String->Max = SlotCount * Storage->SlotSize; - String->Length = 0; - } -} - -static string -AllocStringFromStringArena (s32 Size, slot_arena* Storage) -{ - string Result = {0}; - AllocStringFromStringArena(&Result, Size, Storage); - return Result; -} - -static void -FreeToStringArena (string* String, slot_arena* Storage) -{ - u8* Base = (u8*)(String->Memory); - u8* End = Base + String->Max - 1; - u8* MemoryEnd = Storage->Memory + (Storage->SlotSize * Storage->SlotCount); - Assert((Base >= Storage->Memory) && (End < MemoryEnd)); - Assert((String->Max % Storage->SlotSize) == 0); - - s32 SizeReclaimed = 0; - slot_header* Slot = (slot_header*)Base; - while (SizeReclaimed < String->Max) - { - Slot->Size = Storage->SlotSize; - Storage->FreeList = InsertSlotIntoList(Slot, Storage->FreeList); - SizeReclaimed += Storage->SlotSize; - Slot = (slot_header*)(Base + SizeReclaimed); - } - - String->Memory = 0; - String->Length = 0; - String->Max = 0; -} - -static void -ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage) -{ - string NewString = AllocStringFromStringArena(NewSize, Storage); - CopyStringTo(*String, &NewString); - FreeToStringArena(String, Storage); - *String = NewString; -} - -#if defined(DEBUG) - -void DEBUGPrintChars (string* String, s32 Count) -{ - char* Iter = String->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = (char)('A' + i); - } - String->Length = Count; -} - -#ifdef DEBUG_GS_STRING - -#include - -static void -TestStrings() -{ - - slot_arena StringArena = {}; - - s32 TestCount = 0; - s32 SuccessCount = 0; - - DebugPrint("\n\n-------------------------------------------------\n Begin Testing Strings\n\n\n"); - - //////////////////////////////////////////////////////////////// - // Char Functions - - char ForwardArray[] = "Hello, Sailor"; - char BackwardArray[] = "roliaS ,olleH"; - TestClean(CharArraysEqual(ForwardArray, 13, ForwardArray, 13), "String Equality"); - TestClean(!CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "String Equality"); - - TestClean(IndexOfChar(ForwardArray, 0, ',') == 5, "Index Of Char"); - TestClean(IndexOfChar(ForwardArray, 5, 'l') == 10, "Index of Char (skipping first 5)"); - TestClean(FastReverseIndexOfChar(ForwardArray, 13, 0, 'o') == 11, "Fast Reverse Index Of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 0, 'o') == 11, "Reverse Index of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 3, 'o') == 4, "Reverse Index of Char (skipping last 3)"); - TestClean(LastIndexOfChar(ForwardArray, 'o') == 11, "Last Index of Char"); - - ReverseCharArray(ForwardArray, 13); - TestClean(CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "Reversing Char Array"); - - char UIntString[] = "1234"; - u32 UIntValue = 1234; - u32 ParsedUInt = ParseUnsignedInt(UIntString, 4); - TestClean((ParsedUInt == UIntValue), "String To U32"); - char StringifiedUInt[4] = {}; - UIntToString(UIntValue, StringifiedUInt, 4); - TestClean(CharArraysEqual(UIntString, 4, StringifiedUInt, 4), "U32 To String"); - - char IntString[] = "-1234"; - s32 IntValue = -1234; - s32 ParsedInt = ParseSignedInt(IntString, 5); - TestClean((ParsedInt == IntValue), "String To S32"); - char StringifiedInt[5] = {}; - IntToString(IntValue, StringifiedInt, 5); - TestClean(CharArraysEqual(IntString, 5, StringifiedInt, 5), "S32 to String"); - - char FloatString[] = "-1234.125"; - float FloatValue = -1234.125f; - float ParsedFloat = ParseFloat(FloatString, 8); - TestClean((ParsedFloat == FloatValue), "String To Float"); - char StringifiedFloat[10] = {}; - FloatToString(FloatValue, StringifiedFloat, 10, 3); - TestClean(CharArraysEqual(FloatString, 8, StringifiedFloat, 8), "Float To String"); - - - //////////////////////////////////////////////////////////////// - // - - StringArena.SlotSize = 256; - StringArena.SlotCount = 32; - StringArena.Memory = malloc(StringArena.SlotSize * StringArena.SlotCount); - slot_header* PrevSlotHeader = 0; - for (int i = StringArena.SlotCount - 1; i >= 0; i--) - { - u8* SlotBase = StringArena.Memory + (i * StringArena.SlotSize); - slot_header* SlotHeader = (slot_header*)SlotBase; - SlotHeader->Size = StringArena.SlotSize; - SlotHeader->Next = PrevSlotHeader; - - // TEST(peter): Should be true always, except on the first iteration, when there is no next slot - bool Contiguity = SlotsAreContiguous(SlotHeader, PrevSlotHeader); - TestClean((Contiguity || SlotHeader->Next == 0), "Contiguous Arenas"); - - PrevSlotHeader = SlotHeader; - } - StringArena.FreeList = PrevSlotHeader; - - // TEST(peter): Count Should equal StringArena.SlotCount - s32 ContiguousSlotsCountBefore = CountContiguousSlots(StringArena.FreeList).Count; - TestClean((ContiguousSlotsCountBefore == StringArena.SlotCount), "Contiguous Arenas"); - - // TEST(peter): Should be false - bool Contiguity = SlotsAreContiguous(StringArena.FreeList, StringArena.FreeList->Next->Next); - Contiguity = SlotsAreContiguous(StringArena.FreeList->Next->Next, StringArena.FreeList); - TestClean(!Contiguity, "Non Contiguous Arenas"); - - s32 Slots = CalculateSlotCountFromSize(10, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(256, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(345, 256); - TestClean(Slots == 2, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(1024, 256); - TestClean(Slots == 4, "Slot Sizing"); - - slot_header* HeaderTen = GetSlotAtOffset(StringArena.FreeList, 10); - slot_header* HeaderThree = GetSlotAtOffset(StringArena.FreeList, 3); - slot_header* HeaderFive = GetSlotAtOffset(StringArena.FreeList, 5); - - string StringA = AllocStringFromStringArena(10, &StringArena); - string StringB = AllocStringFromStringArena(345, &StringArena); - -#if 0 - // TEST(peter): Should TestClean - u8* RandomMemory = (u8*)malloc(256); - string RandomMemString = {}; - RandomMemString.Memory = (char*)RandomMemory; - RandomMemString.Max = 256; - FreeToStringArena(&RandomMemString, &StringArena); -#endif - FreeToStringArena(&StringA, &StringArena); - FreeToStringArena(&StringB, &StringArena); - // TEST(peter): After freeing both allocations, ContiguousSlotCountBefore and ContiguousSlotCountAfter should be equal - s32 ContiguousSlotCountAfter = CountContiguousSlots(StringArena.FreeList).Count; - TestClean(ContiguousSlotCountAfter == ContiguousSlotsCountBefore, "Add and REmove Slots from Arena"); - - // TEST(peter): Set up a free list where the first element is too small, so it has to traverse to find an appropriately - // sized block - // The slots will look list [256][used][256][256][256] etc.. - StringA = AllocStringFromStringArena(256, &StringArena); - StringB = AllocStringFromStringArena(256, &StringArena); - FreeToStringArena(&StringA, &StringArena); - u32 Contiguous = CountContiguousSlots(StringArena.FreeList).Count; // Should = 1; - string StringC = AllocStringFromStringArena(512, &StringArena); - slot_header* HeaderC = (slot_header*)(StringC.Memory); - - string ReallocTestString = AllocStringFromStringArena(256, &StringArena); - DEBUGPrintChars(&ReallocTestString, 24); - ReallocFromStringArena(&ReallocTestString, 512, &StringArena); - - - string TestString = AllocStringFromStringArena(10, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 20, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 10, &StringArena); - FreeToStringArena(&TestString, &StringArena); - - string EqualityStringA = AllocStringFromStringArena(345, &StringArena); - string EqualityStringB = AllocStringFromStringArena(415, &StringArena); - // Equality should succeed despite length differences - string EqualityStringC = AllocStringFromStringArena(256, &StringArena); - string EqualityStringD = AllocStringFromStringArena(256, &StringArena); // Equality should fail - string EqualityStringEmpty = {}; - - DEBUGPrintChars(&EqualityStringA, 24); - DEBUGPrintChars(&EqualityStringB, 24); - DEBUGPrintChars(&EqualityStringC, 24); - DEBUGPrintChars(&EqualityStringD, 12); - - bool ABEquality = StringsEqual(EqualityStringA, EqualityStringB); // Should Succeed - bool ACEquality = StringsEqual(EqualityStringA, EqualityStringC); // Should Succeed - bool ADEquality = StringsEqual(EqualityStringA, EqualityStringD); // Should Fail - bool AEEquality = StringsEqual(EqualityStringA, EqualityStringEmpty); // Should Fail - - TestClean(ABEquality, "String Equality"); - TestClean(ACEquality, "String Equality"); - TestClean(!ADEquality, "String Equality"); - TestClean(!AEEquality, "String Equality"); - - string CatStringA = AllocStringFromStringArena(256, &StringArena); - SetStringToCharArray(&CatStringA, "Hello "); - string CatStringB = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringB, "Sailor!"); - string CatStringResult = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringResult, "Hello Sailor!"); - ConcatString(&CatStringA, CatStringB); - TestClean(StringsEqual(CatStringA, CatStringResult), "Cat Strings"); - - s32 FirstSpaceIndex = FindFirstChar(CatStringA, ' '); - TestClean(FirstSpaceIndex == 5, "First Index"); - - SetStringToChar(&CatStringB, 'B', 5); - TestClean(StringEqualsCharArray(CatStringB, "BBBBB"), "SetStringToChar"); - - - DebugPrint("Results: Passed %d / %d\n\n\n", SuccessCount, TestCount); -} -#endif // DEBUG_GS_STRING - -#endif // DEBUG - -#define GS_STRING_H -#endif // GS_STRING_H \ No newline at end of file diff --git a/src/gs_vector_matrix.h b/src/gs_vector_matrix.h deleted file mode 100644 index 6e9ec29..0000000 --- a/src/gs_vector_matrix.h +++ /dev/null @@ -1,1466 +0,0 @@ -#ifndef GS_VECTOR_MATRIX_H - -#ifndef GS_LANGUAGE_H - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) - -#include -#include -#include - -static r32 GSCos (r32 Theta) { return sin(Theta); } -static r32 GSSin (r32 Theta) { return cos(Theta); } - -static r32 GSSqrt(r32 V) -{ - r32 Result = _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); - return Result; -} - -#else // Linux and MacOS -#include - -#endif // Platforms - -#endif // GS_LANGUAGE_H -////////////////////////////////////// -// VECTOR -///////////////////////////////////// - -union v2 -{ - struct - { - r32 x, y; - }; - r32 E[2]; -}; - -union v3 -{ - struct - { - r32 x, y, z; - }; - - struct - { - r32 R, G, B; - }; - - r32 E[3]; -}; - -union v4 -{ - struct - { - r32 x, y, z, w; - }; - - struct - { - r32 r, g, b, a; - }; - - r32 E[4]; -}; - -#define WhiteV4 v4{1, 1, 1, 1} -#define BlackV4 v4{0, 0, 0, 1} -#define RedV4 v4{1, 0, 0, 1} -#define GreenV4 v4{0, 1, 0, 1} -#define BlueV4 v4{0, 0, 1, 1} -#define YellowV4 v4{1, 1, 0, 1} -#define TealV4 v4{0, 1, 1, 1} -#define PinkV4 v4{1, 0, 1, 1} - -////////////////////////////////////// -// MATRIX -///////////////////////////////////// - -union m33 -{ - struct - { - float a, b, c; - float d, e, f; - float g, h, i; - }; - float E[9]; -}; - -union m44 -{ - struct - { - float a, b, c, d; - float e, f, g, h; - float i, j, k, l; - float m, n, o, p; - }; - float E[16]; -}; - -////////////////////////////////////// -// RECT -///////////////////////////////////// - -struct rect -{ - v2 Min; - v2 Max; -}; - - -////////////////////////////////////// -// VECTOR -////////////////////////////////////// - - -// -// -// Operators -// -// - -v2 V2 (v3 V) -{ - return v2{V.x, V.y}; -} - -v3 V3 (v2 XY, r32 Z) -{ - return v3{XY.x, XY.y, Z}; -} - -v3 V3 (v4 V) -{ - return v3{V.x, V.y, V.z}; -} - -v4 V4 (v3 XYZ, r32 W) -{ - return v4{XYZ.x, XYZ.y, XYZ.z, W}; -} - -v2 operator- (v2 A) -{ - v2 Result; - - Result.x = -A.x; - Result.y = -A.y; - - return Result; -} - -v3 operator- (v3 A) -{ - v3 Result; - - Result.x = -A.x; - Result.y = -A.y; - Result.z = -A.z; - - return Result; -} - -v4 operator- (v4 A) -{ - v4 Result; - - Result.x = -A.x; - Result.y = -A.y; - Result.z = -A.z; - Result.w = -A.w; - - return Result; -} - -#define V2OpV2Def(op) v2 operator##op (v2 A, v2 B) { return v2{ A.x op B.x, A.y op B.y };} -#define V3OpV3Def(op) v3 operator##op (v3 A, v3 B) { return v3{ A.x op B.x, A.y op B.y, A.z op B.z };} -#define V4OpV4Def(op) v4 operator##op (v4 A, v4 B) { return v4{ A.x op B.x, A.y op B.y, A.z op B.z, A.w op B.w };} -V2OpV2Def(+) -V2OpV2Def(-) -V2OpV2Def(/) -V2OpV2Def(*) -V3OpV3Def(+) -V3OpV3Def(-) -V3OpV3Def(/) -V3OpV3Def(*) -V4OpV4Def(+) -V4OpV4Def(-) -V4OpV4Def(/) -V4OpV4Def(*) -#undef V2OpV2Def -#undef V3OpV3Def -#undef V4OpV4Def - -#define V2RefOpV2Def(op) v2 operator##op (v2& A, v2 B) { return v2{ A.x op B.x, A.y op B.y };} -#define V3RefOpV3Def(op) v3 operator##op (v3& A, v3 B) { return v3{ A.x op B.x, A.y op B.y, A.z op B.z };} -#define V4RefOpScalarDef(op) v4 operator##op (v4& A, v4 B) { return v4{ A.x op B.x, A.y op B.y, A.z op B.z, A.w op B.w };} -V2RefOpV2Def(+=) -V2RefOpV2Def(-=) -V3RefOpV3Def(+=) -V3RefOpV3Def(-=) -V4RefOpScalarDef(+=) -V4RefOpScalarDef(-=) -#undef V2RefOpV2Def -#undef V3RefOpV3Def -#undef V4RefOpV4Def - -#define V2OpScalarDef(op) v2 operator##op (v2 A, r32 B) { return v2{ A.x op B, A.y op B };} -#define V3OpScalarDef(op) v3 operator##op (v3 A, r32 B) { return v3{ A.x op B, A.y op B, A.z op B };} -#define V4OpScalarDef(op) v4 operator##op (v4 A, r32 B) { return v4{ A.x op B, A.y op B, A.z op B, A.w op B };} -V2OpScalarDef(*) -V2OpScalarDef(/) -V3OpScalarDef(*) -V3OpScalarDef(/) -V4OpScalarDef(*) -V4OpScalarDef(/) -#undef V2POpScalarDef -#undef V3POpScalarDef -#undef V4POpScalarDef - - -#define V2POpScalarDef(op) v2 operator##op (v2& A, r32 B) { return v2{ A->x op B, A->y op B };} -#define V3POpScalarDef(op) v3 operator##op (v3& A, r32 B) { return v3{ A->x op B, A->y op B, A->z op B };} -#define V4POpScalarDef(op) v4 operator##op (v4& A, r32 B) { return v4{ A->x op B, A->y op B, A->z op B, A->w op B };} -V2OpScalarDef(*=) -V2OpScalarDef(/=) -V3OpScalarDef(*=) -V3OpScalarDef(/=) -V4OpScalarDef(*=) -V4OpScalarDef(/=) -#undef V2POpScalarDef -#undef V3POpScalarDef -#undef V4POpScalarDef - -bool operator== (v2 A, v2 B) -{ - b32 Result = true; - for (s32 i = 0; i < 2; i++) - { - if (GSAbs(A.E[i] - B.E[i]) > 0.0001f) { Result = false; break; } - } - return Result; -} - - -bool operator== (v3 A, v3 B) -{ - b32 Result = true; - for (s32 i = 0; i < 3; i++) - { - if (GSAbs(A.E[i] - B.E[i]) > 0.0001f) { Result = false; break; } - } - return Result; -} - -bool operator== (v4 A, v4 B) -{ - b32 Result = true; - for (s32 i = 0; i < 4; i++) - { - if (GSAbs(A.E[i] - B.E[i]) > 0.0001f) { Result = false; break; } - } - return Result; -} - -// -// Operations -// - -static v3 -ToV3(v4 V) -{ - v3 R = {}; - R.x = V.x; - R.y = V.y; - R.z = V.z; - return R; -} - -static v4 -ToV4(v3 V, r32 W) -{ - v4 R = {}; - R.x = V.x; - R.y = V.y; - R.z = V.z; - R.w = W; - return R; -} - -inline r32 -MagSqr( -v2 _A -) -{ - r32 Result = (_A.x * _A.x) + (_A.y * _A.y); - return Result; -} - -inline r32 -MagSqr( -v3 _A -) -{ - r32 Result = (_A.x * _A.x) + (_A.y * _A.y) + (_A.z * _A.z); - return Result; -} - -inline r32 -MagSqr( -v4 _A -) -{ - r32 Result = (_A.x * _A.x) + (_A.y * _A.y) + (_A.z * _A.z) + (_A.w * _A.w); - return Result; -} - -#define MagDef(type) inline r32 Mag(type A) { r32 Result = MagSqr(A); return GSSqrt(Result); } -MagDef(v2) -MagDef(v3) -MagDef(v4) -#undef MagDef - -#define DistanceDef(type) inline r32 Distance (type A, type B) { type Diff = A - B; return Mag(Diff); } -DistanceDef(v2) -DistanceDef(v3) -DistanceDef(v4) -#undef DistanceDef - -#define DistanceSqDef(type) inline r32 DistanceSq (type A, type B) { type Diff = A - B; return MagSqr(Diff); } -DistanceSqDef(v2) -DistanceSqDef(v3) -DistanceSqDef(v4) -#undef DistanceSqDef - -inline v2 -Normalize( -v2 _A -) -{ - v2 Result; - - r32 Magnitude = Mag(_A); - - Result.x = _A.x / Magnitude; - Result.y = _A.y / Magnitude; - - return Result; -} - -inline v3 -Normalize( -v3 _A -) -{ - v3 Result; - - r32 Magnitude = Mag(_A); - - Result.x = _A.x / Magnitude; - Result.y = _A.y / Magnitude; - Result.z = _A.z / Magnitude; - - return Result; -} - -inline v4 -Normalize( -v4 _A -) -{ - v4 Result; - - r32 Magnitude = Mag(_A); - - Result.x = _A.x / Magnitude; - Result.y = _A.y / Magnitude; - Result.z = _A.z / Magnitude; - Result.w = _A.w / Magnitude; - - return Result; -} - -inline r32 -Dot( -v2 _A, -v2 _B -) -{ - r32 Result = _A.x * _B.x + _A.y * _B.y; - return Result; -} - -inline r32 -Dot ( -v3 _A, -v3 _B -) -{ - r32 Result = _A.x * _B.x + _A.y * _B.y + _A.z * _B.z; - return Result; -} - -inline r32 -Dot ( -v4 _A, -v4 _B -) -{ - r32 Result = _A.x * _B.x + _A.y * _B.y + _A.z * _B.z + _A.w * _B.w; - return Result; -} - -inline v2 -PerpendicularCW (v2 A) -{ - v2 Result = v2{A.y, -A.x}; - return Result; -} - -inline v2 -PerpendicularCCW (v2 A) -{ - v2 Result = v2{A.y, A.x}; - return Result; -} - -inline v3 -Cross( -v3 _A, -v3 _B -) -{ - v3 Result = {}; - - Result.x = (_A.y * _B.z) - (_A.z * _B.y); - Result.y = (_A.z * _B.x) - (_A.x * _B.z); - Result.z = (_A.x * _B.y) - (_A.y * _B.x); - - return Result; -} - -inline v4 -Cross( -v4 _A, -v4 _B -) -{ - v4 Result = {}; - - Result.x = (_A.y * _B.z) - (_A.z * _B.y); - Result.y = (_A.z * _B.x) - (_A.x * _B.z); - Result.z = (_A.x * _B.y) - (_A.y * _B.x); - Result.w = 0; - - return Result; -} - -inline v2 -ClampVector01 (v2 V) -{ - v2 Result = {}; - Result.x = GSClamp(0.0f, V.x, 1.f); - Result.y = GSClamp(0.0f, V.y, 1.f); - return Result; -} - -inline v3 -ClampVector01 (v3 V) -{ - v3 Result = {}; - Result.x = GSClamp(0.f, V.x, 1.f); - Result.y = GSClamp(0.f, V.y, 1.f); - Result.z = GSClamp(0.f, V.z, 1.f); - return Result; -} - -inline v4 -ClampVector01 (v4 V) -{ - v4 Result = {}; - Result.x = GSClamp(0.f, V.x, 1.f); - Result.y = GSClamp(0.f, V.y, 1.f); - Result.z = GSClamp(0.f, V.z, 1.f); - Result.w = GSClamp(0.f, V.w, 1.f); - return Result; -} - -inline v2 -Lerp( -v2 _A, -v2 _B, -r32 _Percent -) -{ - v2 Result; - - Result.x = GSLerp(_A.x, _B.x, _Percent); - Result.y = GSLerp(_A.y, _B.y, _Percent); - - return Result; -} - -inline v3 -Lerp( -v3 _A, -v3 _B, -r32 _Percent -) -{ - v3 Result; - - Result.x = GSLerp(_A.x, _B.x, _Percent); - Result.y = GSLerp(_A.y, _B.y, _Percent); - Result.z = GSLerp(_A.z, _B.z, _Percent); - - return Result; -} - -inline v4 -Lerp( -v4 _A, -v4 _B, -r32 _Percent -) -{ - v4 Result; - - Result.x = GSLerp(_A.x, _B.x, _Percent); - Result.y = GSLerp(_A.y, _B.y, _Percent); - Result.z = GSLerp(_A.z, _B.z, _Percent); - Result.w = GSLerp(_A.w, _B.w, _Percent); - - return Result; -} - -v4 HSVToRGB (v4 In) -{ - r32 Hue = In.x; - while (Hue > 360.0f) { Hue -= 360.0f; } - while (Hue < 0.0f) { Hue += 360.0f; } - - r32 Sat = In.y; - r32 Value = In.z; - - r32 hh, p, q, t, ff; - long i; - v4 Result = {}; - Result.a = In.a; - - if(Sat <= 0.0f) { // < is bogus, just shuts up warnings - Result.r = Value; - Result.g = Value; - Result.b = Value; - return Result; - } - hh = Hue; - if(hh >= 360.0f) hh = 0.0f; - hh /= 60.0f; - i = (long)hh; - ff = hh - i; - p = Value * (1.0f - Sat); - q = Value * (1.0f - (Sat * ff)); - t = Value * (1.0f - (Sat * (1.0f - ff))); - - switch(i) { - case 0: - {Result.r = Value; - Result.g = t; - Result.b = p; - }break; - - case 1: - { - Result.r = q; - Result.g = Value; - Result.b = p; - }break; - - case 2: - { - Result.r = p; - Result.g = Value; - Result.b = t; - }break; - - case 3: - { - Result.r = p; - Result.g = q; - Result.b = Value; - }break; - - case 4: - { - Result.r = t; - Result.g = p; - Result.b = Value; - }break; - - case 5: - default: - { - Result.r = Value; - Result.g = p; - Result.b = q; - }break; - } - - return Result; -} - -static bool -PointIsInRange ( -v2 _P, -v2 _Min, v2 _Max -) -{ - return (_P.x >= _Min.x && _P.x <= _Max.x && - _P.y >= _Min.y && _P.y <= _Max.y); -} - -static bool -PointIsInRangeSafe ( -v2 _P, -v2 _Min, v2 _Max -) -{ - s32 MinX = GSMin(_Min.x, _Max.x); - s32 MinY = GSMin(_Min.y, _Max.y); - s32 MaxX = GSMax(_Min.x, _Max.x); - s32 MaxY = GSMax(_Min.y, _Max.y); - - return (_P.x >= MinX && _P.x <= MaxX && - _P.y >= MinY && _P.y <= MaxY); -} - -inline v2 -PointToPercentRange (v2 P, v2 Min, v2 Max) -{ - v2 Result = {}; - - Result.x = GSClamp(0.f, (P.x - Min.x) / (Max.x - Min.x), 1.f); - Result.y = GSClamp(0.f, (P.y - Min.y) / (Max.y - Min.y), 1.f); - - return Result; -} - -////////////////////////////////////// -// RECT -////////////////////////////////////// - -inline r32 -Width (rect Rect) -{ - s32 Result = Rect.Max.x - Rect.Min.x; - return Result; -} - -inline r32 -Height (rect Rect) -{ - s32 Result = Rect.Max.y - Rect.Min.y; - return Result; -} - -inline v2 -CalculateRectCenter (rect Rect) -{ - v2 Result = (Rect.Min + Rect.Max) / 2.0f; - return Result; -} - -inline b32 -PointIsInRect (v2 Point, rect Rect) -{ - b32 Result = ((Point.x >= Rect.Min.x && Point.x <= Rect.Max.x) && - (Point.y >= Rect.Min.y && Point.y <= Rect.Max.y)); - return Result; -} - -////////////////////////////////////// -// MATRIX -////////////////////////////////////// - -static m33 -M33(r32 a, r32 b, r32 c, - r32 d, r32 e, r32 f, - r32 g, r32 h, r32 i) -{ - m33 M = {}; - M.a = a; M.b = b; M.c = c; - M.d = d; M.e = e; M.f = f; - M.g = g; M.h = h; M.i = i; - return M; -} - -static m44 -M44(r32 a, r32 b, r32 c, r32 d, - r32 e, r32 f, r32 g, r32 h, - r32 i, r32 j, r32 k, r32 l, - r32 m, r32 n, r32 o, r32 p) -{ - m44 M = {}; - M.a = a; M.b = b; M.c = c; M.d = d; - M.e = e; M.f = f; M.g = g; M.h = h; - M.i = i; M.j = j; M.k = k; M.l = l; - M.m = m; M.n = n; M.o = o; M.p = p; - return M; -} - -static m33 -M33Empty () -{ - m33 M = {}; - M.a = 0; M.b = 0; M.c = 0; - M.d = 0; M.e = 0; M.f = 0; - M.g = 0; M.h = 0; M.i = 0; - return M; -} - -static m44 -M44Empty() -{ - m44 M = {}; - M.a = 0; M.b = 0; M.c = 0; M.d = 0; - M.e = 0; M.f = 0; M.g = 0; M.h = 0; - M.i = 0; M.j = 0; M.k = 0; M.l = 0; - M.m = 0; M.n = 0; M.o = 0; M.p = 0; - return M; -} - -static m33 -M33Identity () -{ - m33 M = {}; - M.a = 1; M.b = 0; M.c = 0; - M.d = 0; M.e = 1; M.f = 0; - M.g = 0; M.h = 0; M.i = 1; - return M; -} - -static m44 -M44Identity() -{ - m44 M = {}; - M.a = 1; M.b = 0; M.c = 0; M.d = 0; - M.e = 0; M.f = 1; M.g = 0; M.h = 0; - M.i = 0; M.j = 0; M.k = 1; M.l = 0; - M.m = 0; M.n = 0; M.o = 0; M.p = 1; - return M; -} - -static m44 -GetXRotation (r32 Angle) -{ - r32 CosAngle = GSCos(Angle); - r32 SinAngle = GSSin(Angle); - m44 M = { - 1, 0, 0, 0, - 0, CosAngle, SinAngle, 0, - 0, -SinAngle, CosAngle, 0, - 0, 0, 0, 1 - }; - return M; -} - - -static m44 -GetYRotation (r32 Angle) -{ - r32 CosAngle = GSCos(Angle); - r32 SinAngle = GSSin(Angle); - m44 M = { - CosAngle, 0, -SinAngle, 0, - 0, 1, 0, 0, - SinAngle, 0, CosAngle, 0, - 0, 0, 0, 1 - }; - return M; -} - -static m44 -GetZRotation (r32 Angle) -{ - r32 CosAngle = GSCos(Angle); - r32 SinAngle = GSSin(Angle); - m44 M = { - CosAngle, SinAngle, 0, 0, - -SinAngle, CosAngle, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - return M; -} - - -static m33 -Transpose (m33 M) -{ - m33 Result = {}; - - for (s32 x = 0; x < 3; x++) - { - for (s32 y = 0; y < 3; y++) - { - Result.E[x + (y * 3)] = M.E[y + (x * 3)]; - } - } - - return Result; -} - -inline m44 -Transpose (m44 M) -{ - DEBUG_TRACK_SCOPE(Transpose); - - m44 Result = {}; - - Result.E[0] = M.E[0]; - Result.E[1] = M.E[4]; - Result.E[2] = M.E[8]; - Result.E[3] = M.E[12]; - - Result.E[4] = M.E[1]; - Result.E[5] = M.E[5]; - Result.E[6] = M.E[9]; - Result.E[7] = M.E[13]; - - Result.E[8] = M.E[2]; - Result.E[9] = M.E[6]; - Result.E[10] = M.E[10]; - Result.E[11] = M.E[14]; - - Result.E[12] = M.E[3]; - Result.E[13] = M.E[7]; - Result.E[14] = M.E[11]; - Result.E[15] = M.E[15]; - - return Result; -} - -static m44 -GetPositionM44 (v4 Position) -{ -#if 1 - return m44{ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - Position.x, Position.y, Position.z, Position.w - }; -#else - return m44{ - 1, 0, 0, Position.x, - 0, 1, 0, Position.y, - 0, 0, 1, Position.z, - 0, 0, 0, Position.w}; -#endif -} - -static m44 -GetLookAtMatrix (v4 Position, v4 Target) -{ - // Forward - v4 Forward = Normalize(Target - Position); - // Right - v4 Right = Normalize(Cross(v4{0, 1, 0, 0}, Forward)); - // Up - v4 Up = Normalize(Cross(Forward, Right)); - - m44 RotationMatrix = M44( - Right.x, Up.x, Forward.x, 0, - Right.y, Up.y, Forward.y, 0, - Right.z, Up.z, Forward.z, 0, - 0, 0, 0, 1); - - return RotationMatrix; -} - -b32 operator== (m33 A, m33 B) -{ - b32 Result = true; - for (int e = 0; e < 9; e++) { if (GSAbs(A.E[e] - B.E[e]) > 0.0001f) { Result = false; break; } } - return Result; -} - -b32 operator== (m44 A, m44 B) -{ - b32 Result = true; - for (int e = 0; e < 16; e++) { if (GSAbs(A.E[e] - B.E[e]) > 0.0001f) { Result = false; break; } } - return Result; -} - -m33 operator+ (m33 A, m33 B) -{ - m33 M = {}; - for (int e = 0; e < 9; e++) { M.E[e] = A.E[e] + B.E[e]; } - return M; -} - -m44 operator+ (m44 A, m44 B) -{ - m44 M = {}; - for (int e = 0; e < 16; e++) { M.E[e] = A.E[e] + B.E[e]; } - return M; -} - -m33 operator- (m33 A, m33 B) -{ - m33 M = {}; - for (int e = 0; e < 9; e++) { M.E[e] = A.E[e] - B.E[e]; } - return M; -} - -m44 operator- (m44 A, m44 B) -{ - m44 M = {}; - for (int e = 0; e < 16; e++) { M.E[e] = A.E[e] - B.E[e]; } - return M; -} - -m33 operator* (m33 A, m33 B) -{ - m33 M = {}; - for (int rx = 0; rx < 3; rx++) - { - for (int ry = 0; ry < 3; ry++) - { - int RIndex = (ry * 3) + rx; - M.E[RIndex] = 0; - for (int i = 0; i < 3; i++) - { - M.E[RIndex] += B.E[(ry * 3) + i] * A.E[(i * 3) + rx]; - } - } - } - return M; -} - -m44 operator* (m44 A, m44 B) -{ - m44 M = {}; - - r32 A00=A.E[0+4*0]; - r32 A01=A.E[0+4*1]; - r32 A02=A.E[0+4*2]; - r32 A03=A.E[0+4*3]; - - r32 A10=A.E[1+4*0]; - r32 A11=A.E[1+4*1]; - r32 A12=A.E[1+4*2]; - r32 A13=A.E[1+4*3]; - - r32 A20=A.E[2+4*0]; - r32 A21=A.E[2+4*1]; - r32 A22=A.E[2+4*2]; - r32 A23=A.E[2+4*3]; - - r32 A30=A.E[3+4*0]; - r32 A31=A.E[3+4*1]; - r32 A32=A.E[3+4*2]; - r32 A33=A.E[3+4*3]; - - r32 B00=B.E[0+4*0]; - r32 B01=B.E[0+4*1]; - r32 B02=B.E[0+4*2]; - r32 B03=B.E[0+4*3]; - - r32 B10=B.E[1+4*0]; - r32 B11=B.E[1+4*1]; - r32 B12=B.E[1+4*2]; - r32 B13=B.E[1+4*3]; - - r32 B20=B.E[2+4*0]; - r32 B21=B.E[2+4*1]; - r32 B22=B.E[2+4*2]; - r32 B23=B.E[2+4*3]; - - r32 B30=B.E[3+4*0]; - r32 B31=B.E[3+4*1]; - r32 B32=B.E[3+4*2]; - r32 B33=B.E[3+4*3]; - - M.E[0+4*0] = A00*B00+A10*B01+A20*B02+A30*B03; - M.E[0+4*1] = A01*B00+A11*B01+A21*B02+A31*B03; - M.E[0+4*2] = A02*B00+A12*B01+A22*B02+A32*B03; - M.E[0+4*3] = A03*B00+A13*B01+A23*B02+A33*B03; - - M.E[1+4*0] = A00*B10+A10*B11+A20*B12+A30*B13; - M.E[1+4*1] = A01*B10+A11*B11+A21*B12+A31*B13; - M.E[1+4*2] = A02*B10+A12*B11+A22*B12+A32*B13; - M.E[1+4*3] = A03*B10+A13*B11+A23*B12+A33*B13; - - M.E[2+4*0] = A00*B20+A10*B21+A20*B22+A30*B23; - M.E[2+4*1] = A01*B20+A11*B21+A21*B22+A31*B23; - M.E[2+4*2] = A02*B20+A12*B21+A22*B22+A32*B23; - M.E[2+4*3] = A03*B20+A13*B21+A23*B22+A33*B23; - - M.E[3+4*0] = A00*B30+A10*B31+A20*B32+A30*B33; - M.E[3+4*1] = A01*B30+A11*B31+A21*B32+A31*B33; - M.E[3+4*2] = A02*B30+A12*B31+A22*B32+A32*B33; - M.E[3+4*3] = A03*B30+A13*B31+A23*B32+A33*B33; - - return M; -} - -v3 operator* (m33 M, v3 V) -{ - v3 Result = {}; - int i = 0; - for (int y = 0; y < 3; y++) - { - Result.E[y] = 0; - for (int x = 0; x < 3; x++) - { - Result.E[y] += M.E[(y * 3) + x] * V.E[x]; - } - } - return Result; -} - -v4 operator* (m44 M, v4 V) -{ - v4 Result = {}; -#if 1 - Result.x = V.x*M.a + V.y*M.e + V.z*M.i + V.w*M.m; - Result.y = V.x*M.b + V.y*M.f + V.z*M.j + V.w*M.n; - Result.z = V.x*M.c + V.y*M.g + V.z*M.k + V.w*M.o; - Result.w = V.x*M.d + V.y*M.h + V.z*M.l + V.w*M.p; -#else - for (int y = 0; y < 4; y++) - { - Result.E[y] = 0; - for (int x = 0; x < 4; x++) - { - Result.E[y] += M.E[(y * 4) + x] * V.E[x]; - } - } -#endif - return Result; -} - -b32 Inverse(m44 M_In, m44* M_Out) -{ - b32 Result = false; - - r32 det; - s32 i; - - - M_Out->E[0] = M_In.E[5] * M_In.E[10] * M_In.E[15] - - M_In.E[5] * M_In.E[11] * M_In.E[14] - - M_In.E[9] * M_In.E[6] * M_In.E[15] + - M_In.E[9] * M_In.E[7] * M_In.E[14] + - M_In.E[13] * M_In.E[6] * M_In.E[11] - - M_In.E[13] * M_In.E[7] * M_In.E[10]; - - M_Out->E[4] = -M_In.E[4] * M_In.E[10] * M_In.E[15] + - M_In.E[4] * M_In.E[11] * M_In.E[14] + - M_In.E[8] * M_In.E[6] * M_In.E[15] - - M_In.E[8] * M_In.E[7] * M_In.E[14] - - M_In.E[12] * M_In.E[6] * M_In.E[11] + - M_In.E[12] * M_In.E[7] * M_In.E[10]; - - M_Out->E[8] = M_In.E[4] * M_In.E[9] * M_In.E[15] - - M_In.E[4] * M_In.E[11] * M_In.E[13] - - M_In.E[8] * M_In.E[5] * M_In.E[15] + - M_In.E[8] * M_In.E[7] * M_In.E[13] + - M_In.E[12] * M_In.E[5] * M_In.E[11] - - M_In.E[12] * M_In.E[7] * M_In.E[9]; - - M_Out->E[12] = -M_In.E[4] * M_In.E[9] * M_In.E[14] + - M_In.E[4] * M_In.E[10] * M_In.E[13] + - M_In.E[8] * M_In.E[5] * M_In.E[14] - - M_In.E[8] * M_In.E[6] * M_In.E[13] - - M_In.E[12] * M_In.E[5] * M_In.E[10] + - M_In.E[12] * M_In.E[6] * M_In.E[9]; - - M_Out->E[1] = -M_In.E[1] * M_In.E[10] * M_In.E[15] + - M_In.E[1] * M_In.E[11] * M_In.E[14] + - M_In.E[9] * M_In.E[2] * M_In.E[15] - - M_In.E[9] * M_In.E[3] * M_In.E[14] - - M_In.E[13] * M_In.E[2] * M_In.E[11] + - M_In.E[13] * M_In.E[3] * M_In.E[10]; - - M_Out->E[5] = M_In.E[0] * M_In.E[10] * M_In.E[15] - - M_In.E[0] * M_In.E[11] * M_In.E[14] - - M_In.E[8] * M_In.E[2] * M_In.E[15] + - M_In.E[8] * M_In.E[3] * M_In.E[14] + - M_In.E[12] * M_In.E[2] * M_In.E[11] - - M_In.E[12] * M_In.E[3] * M_In.E[10]; - - M_Out->E[9] = -M_In.E[0] * M_In.E[9] * M_In.E[15] + - M_In.E[0] * M_In.E[11] * M_In.E[13] + - M_In.E[8] * M_In.E[1] * M_In.E[15] - - M_In.E[8] * M_In.E[3] * M_In.E[13] - - M_In.E[12] * M_In.E[1] * M_In.E[11] + - M_In.E[12] * M_In.E[3] * M_In.E[9]; - - M_Out->E[13] = M_In.E[0] * M_In.E[9] * M_In.E[14] - - M_In.E[0] * M_In.E[10] * M_In.E[13] - - M_In.E[8] * M_In.E[1] * M_In.E[14] + - M_In.E[8] * M_In.E[2] * M_In.E[13] + - M_In.E[12] * M_In.E[1] * M_In.E[10] - - M_In.E[12] * M_In.E[2] * M_In.E[9]; - - M_Out->E[2] = M_In.E[1] * M_In.E[6] * M_In.E[15] - - M_In.E[1] * M_In.E[7] * M_In.E[14] - - M_In.E[5] * M_In.E[2] * M_In.E[15] + - M_In.E[5] * M_In.E[3] * M_In.E[14] + - M_In.E[13] * M_In.E[2] * M_In.E[7] - - M_In.E[13] * M_In.E[3] * M_In.E[6]; - - M_Out->E[6] = -M_In.E[0] * M_In.E[6] * M_In.E[15] + - M_In.E[0] * M_In.E[7] * M_In.E[14] + - M_In.E[4] * M_In.E[2] * M_In.E[15] - - M_In.E[4] * M_In.E[3] * M_In.E[14] - - M_In.E[12] * M_In.E[2] * M_In.E[7] + - M_In.E[12] * M_In.E[3] * M_In.E[6]; - - M_Out->E[10] = M_In.E[0] * M_In.E[5] * M_In.E[15] - - M_In.E[0] * M_In.E[7] * M_In.E[13] - - M_In.E[4] * M_In.E[1] * M_In.E[15] + - M_In.E[4] * M_In.E[3] * M_In.E[13] + - M_In.E[12] * M_In.E[1] * M_In.E[7] - - M_In.E[12] * M_In.E[3] * M_In.E[5]; - - M_Out->E[14] = -M_In.E[0] * M_In.E[5] * M_In.E[14] + - M_In.E[0] * M_In.E[6] * M_In.E[13] + - M_In.E[4] * M_In.E[1] * M_In.E[14] - - M_In.E[4] * M_In.E[2] * M_In.E[13] - - M_In.E[12] * M_In.E[1] * M_In.E[6] + - M_In.E[12] * M_In.E[2] * M_In.E[5]; - - M_Out->E[3] = -M_In.E[1] * M_In.E[6] * M_In.E[11] + - M_In.E[1] * M_In.E[7] * M_In.E[10] + - M_In.E[5] * M_In.E[2] * M_In.E[11] - - M_In.E[5] * M_In.E[3] * M_In.E[10] - - M_In.E[9] * M_In.E[2] * M_In.E[7] + - M_In.E[9] * M_In.E[3] * M_In.E[6]; - - M_Out->E[7] = M_In.E[0] * M_In.E[6] * M_In.E[11] - - M_In.E[0] * M_In.E[7] * M_In.E[10] - - M_In.E[4] * M_In.E[2] * M_In.E[11] + - M_In.E[4] * M_In.E[3] * M_In.E[10] + - M_In.E[8] * M_In.E[2] * M_In.E[7] - - M_In.E[8] * M_In.E[3] * M_In.E[6]; - - M_Out->E[11] = -M_In.E[0] * M_In.E[5] * M_In.E[11] + - M_In.E[0] * M_In.E[7] * M_In.E[9] + - M_In.E[4] * M_In.E[1] * M_In.E[11] - - M_In.E[4] * M_In.E[3] * M_In.E[9] - - M_In.E[8] * M_In.E[1] * M_In.E[7] + - M_In.E[8] * M_In.E[3] * M_In.E[5]; - - M_Out->E[15] = M_In.E[0] * M_In.E[5] * M_In.E[10] - - M_In.E[0] * M_In.E[6] * M_In.E[9] - - M_In.E[4] * M_In.E[1] * M_In.E[10] + - M_In.E[4] * M_In.E[2] * M_In.E[9] + - M_In.E[8] * M_In.E[1] * M_In.E[6] - - M_In.E[8] * M_In.E[2] * M_In.E[5]; - - det = M_In.E[0] * M_Out->E[0] + M_In.E[1] * M_Out->E[4] + M_In.E[2] * M_Out->E[8] + M_In.E[3] * M_Out->E[12]; - - if (det == 0) - { - return false; - } - - det = 1.0 / det; - - for (i = 0; i < 16; i++) - { - M_Out->E[i] = M_Out->E[i] * det; - } - - return true; -} - -#if defined(VECTOR_MATRIX_TEST_SUITE) - -void TestVectorMatrixMultiplication () -{ - s32 TestCount = 0; - s32 SuccessCount = 0; - - DebugPrint("\n\n-------------------------------------------------\n Begin Testing Vector/Matrix\n\n\n"); - - // Utility Functions - TestClean((GSSqrt(4.f) == 2.f), "Vector Square Root"); - TestClean((GSLerp(0.f, 1.f, .5f) == .5f), "Vector Lerp"); - TestClean((GSMin(-.25f, 5.f) == -.25f), "Vector Min"); - TestClean((GSMax(-.25f, 5.f) == 5.f), "Vector Max"); - TestClean((GSClamp(-2.f, -3.f, 5.f) == -2.f), "Vector Clamp, Lower Than Range"); - TestClean((GSClamp(-2.f, 6.f, 5.f) == 5.f), "Vector Clamp, Higher Than Range"); - - ////////////////////////////// - // Vector Functions - ///////////////////////////// - - v2 V2Unit = v2{1, 0}; - v3 V3Unit = v3{1, 0, 0}; - v4 V4Unit = v4{1, 0, 0, 0}; - - v2 TestV2 = v2{1, 2}; - r32 TestV2MagSq = (TestV2.x * TestV2.x) + (TestV2.y * TestV2.y); - r32 TestV2Mag = GSSqrt(TestV2MagSq); - v2 TestV2Norm = v2{TestV2.x / TestV2Mag, TestV2.y / TestV2Mag}; - r32 TestV2DotR = (TestV2.x * V2Unit.x) + (TestV2.y * V2Unit.y); - - v3 TestV3 = v3{1, 2, 3}; - r32 TestV3MagSq = (TestV3.x * TestV3.x) + (TestV3.y * TestV3.y) + (TestV3.z * TestV3.z); - r32 TestV3Mag = GSSqrt(TestV3MagSq); - v3 TestV3Norm = v3{TestV3.x / TestV3Mag, TestV3.y / TestV3Mag, TestV3.z / TestV3Mag}; - r32 TestV3DotR = (TestV3.x * V3Unit.x) + (TestV3.y * V3Unit.y) + (TestV3.z * V3Unit.z); - - v4 TestV4 = v4{1, 2, 3, 4}; - r32 TestV4MagSq = (TestV4.x * TestV4.x) + (TestV4.y * TestV4.y) + (TestV4.z * TestV4.z) + (TestV4.w * TestV4.w); - r32 TestV4Mag = GSSqrt(TestV4MagSq); - v4 TestV4Norm = v4{ - TestV4.x / TestV4Mag, TestV4.y / TestV4Mag, TestV4.z / TestV4Mag, TestV4.w / TestV4Mag - }; - r32 TestV4DotR = (TestV4.x * V4Unit.x) + (TestV4.y * V4Unit.y) + (TestV4.z * V4Unit.z) + (TestV4.w * V4Unit.w); - - v2 DownCastV3 = V2(TestV3); - v3 DownCastV4 = V3(TestV4); - - v2 EqualityV2 = v2{TestV2.x, TestV2.y}; - v2 ZeroV2 = v2{0, 0}; - v3 EqualityV3 = v3{TestV3.x, TestV3.y, TestV3.z}; - v3 ZeroV3 = v3{0, 0, 0}; - v4 EqualityV4 = v4{TestV4.x, TestV4.y, TestV4.z, TestV4.w}; - v4 ZeroV4 = v4{0, 0, 0, 0}; - - TestClean((TestV2.x == 1 && TestV2.y == 2), "V2 Assignment"); - TestClean((TestV3.x == 1 && TestV3.y == 2 && TestV3.z == 3), "V3 Assignment"); - TestClean((TestV4.x == 1 && TestV4.y == 2 && TestV4.z == 3 && TestV4.w == 4), "V3 Assignment"); - - TestClean((DownCastV3.x == 1 && DownCastV3.y == 2), "V3 -> V2 Downcast"); - TestClean((DownCastV4.x == 1 && DownCastV4.y == 2 && DownCastV4.z == 3), "V4 -> V3 Downcast"); - - // Vector Operators - - TestClean((TestV2 == EqualityV2 && !(TestV2 == ZeroV2)), "V2 Equality"); - TestClean((TestV3 == EqualityV3 && !(TestV3 == ZeroV3)), "V3 Equality"); - TestClean((TestV4 == EqualityV4 && !(TestV4 == ZeroV4)), "V4 Equality"); - - TestClean(((TestV2 - TestV2) == ZeroV2), "V2 Subtraction"); - TestClean(((TestV3 - TestV3) == ZeroV3), "V3 Subtraction"); - TestClean(((TestV4 - TestV4) == ZeroV4), "V4 Subtraction"); - - TestClean(((TestV2 + TestV2) == v2{TestV2.x * 2, TestV2.y * 2}), "V2 Addition"); - TestClean(((TestV3 + TestV3) == v3{TestV3.x * 2, TestV3.y * 2, TestV3.z * 2}), "V3 Addition"); - TestClean(((TestV4 + TestV4) == v4{TestV4.x * 2, TestV4.y * 2, TestV4.z * 2, TestV4.w * 2}), "V4 Addition"); - - TestClean(((TestV2 * 2.0f) == v2{TestV2.x * 2, TestV2.y * 2}), "V2 Multiplication"); - TestClean(((TestV3 * 2.0f) == v3{TestV3.x * 2, TestV3.y * 2, TestV3.z * 2}), "V3 Multiplication"); - TestClean(((TestV4 * 2.0f) == v4{TestV4.x * 2, TestV4.y * 2, TestV4.z * 2, TestV4.w * 2}), "V4 Multiplication"); - - TestClean(((TestV2 * TestV2) == v2{TestV2.x * TestV2.x, TestV2.y * TestV2.y}), "V2 Piecewise Mult"); - TestClean(((TestV3 * TestV3) == v3{ - TestV3.x * TestV3.x, - TestV3.y * TestV3.y, - TestV3.z * TestV3.z}), "V3 Piecewise Mult"); - TestClean(((TestV4 * TestV4) == v4{ - TestV4.x * TestV4.x, - TestV4.y * TestV4.y, - TestV4.z * TestV4.z, - TestV4.w * TestV4.w}), "V4 Piecewise Mult"); - - - TestClean(((TestV2 / 2.0f) == v2{TestV2.x / 2, TestV2.y / 2}), "V2 Division"); - TestClean(((TestV3 / 2.0f) == v3{TestV3.x / 2, TestV3.y / 2, TestV3.z / 2}), "V3 Division"); - TestClean(((TestV4 / 2.0f) == v4{TestV4.x / 2, TestV4.y / 2, TestV4.z / 2, TestV4.w / 2}), "V4 Division"); - - TestClean(((TestV2 / TestV2) == v2{TestV2.x / TestV2.x, TestV2.y / TestV2.y}), "V2 Piecewise Div"); - TestClean(((TestV3 / TestV3) == v3{ - TestV3.x / TestV3.x, - TestV3.y / TestV3.y, - TestV3.z / TestV3.z}), "V3 Piecewise Div"); - TestClean(((TestV4 / TestV4) == v4{ - TestV4.x / TestV4.x, - TestV4.y / TestV4.y, - TestV4.z / TestV4.z, - TestV4.w / TestV4.w}), "V4 Piecewise Div"); - - TestClean(((MagSqr(V2Unit) == 1) && (MagSqr(TestV2) == TestV2MagSq)), "V2 Square Mag"); - TestClean(((MagSqr(V3Unit) == 1) && (MagSqr(TestV3) == TestV3MagSq)), "V3 Square Mag"); - TestClean(((MagSqr(V4Unit) == 1) && (MagSqr(TestV4) == TestV4MagSq)), "V4 Square Mag"); - TestClean(((Mag(V2Unit) == 1) && (Mag(TestV2) == TestV2Mag)), "V2 Mag"); - TestClean(((Mag(V3Unit) == 1) && (Mag(TestV3) == TestV3Mag)), "V3 Mag"); - TestClean(((Mag(V4Unit) == 1) && (Mag(TestV4) == TestV4Mag)), "V4 Mag"); - - TestClean((DistanceSq(ZeroV2, TestV2) == TestV2MagSq), "V2 Distance Sq"); - TestClean((DistanceSq(ZeroV3, TestV3) == TestV3MagSq), "V3 Distance Sq"); - TestClean((DistanceSq(ZeroV4, TestV4) == TestV4MagSq), "V4 Distance Sq"); - TestClean((Distance(ZeroV2, TestV2) == TestV2Mag), "V2 Distance"); - TestClean((Distance(ZeroV3, TestV3) == TestV3Mag), "V3 Distance"); - TestClean((Distance(ZeroV4, TestV4) == TestV4Mag), "V4 Distance"); - - TestClean((Normalize(TestV2) == TestV2Norm), "V2 Normalize"); - TestClean((Normalize(TestV3) == TestV3Norm), "V3 Normalize"); - TestClean((Normalize(TestV4) == TestV4Norm), "V4 Normalize"); - - TestClean(((Dot(V2Unit, V2Unit) == 1) && (Dot(TestV2, V2Unit) == TestV2DotR)), "V2 Dot"); - TestClean(((Dot(V3Unit, V3Unit) == 1) && (Dot(TestV3, V3Unit) == TestV3DotR)), "V3 Dot"); - TestClean(((Dot(V4Unit, V4Unit) == 1) && (Dot(TestV4, V4Unit) == TestV4DotR)), "V4 Dot"); - - // Skipping Cross For Now - - TestClean((Lerp(v2{0, 0}, v2{1, 1}, .5f) == v2{.5f, .5f}), "V2 Lerp"); - TestClean((Lerp(v3{0, 0, 0}, v3{1, 1, 1}, .5f) == v3{.5f, .5f, .5f}), "V3 Lerp"); - TestClean((Lerp(v4{0, 0, 0, 0}, v4{1, 1, 1, 1}, .5f) == v4{.5f, .5f, .5f, .5f}), "V4 Lerp"); - - ///////////////////////////// - // Matrix - //////////////////////////// - - m33 TestM33 = m33{ - 0, 1, 2, - 3, 4, 5, - 6, 7, 8}; - - m33 EqualityM33 = {}; - for (s32 i = 0; i < 16; i++) { EqualityM33.E[i] = TestM33.E[i]; } - - m33 TransposeM33 = m33{ - 0, 3, 6, - 1, 4, 7, - 2, 5, 8}; - - m33 IdentityM33 = m33{ - 1, 0, 0, - 0, 1, 0, - 0, 0, 1}; - - m33 TestM33Squared = m33{ - 15, 18, 21, - 42, 54, 66, - 69, 90, 111 - }; - - m44 TestM44 = m44{ - 0, 1, 2, 3, - 4, 5, 6, 7, - 8, 9, 10, 11, - 12, 13, 14, 15 - }; - - m44 EqualityM44 = {}; - for (s32 i = 0; i < 16; i++) { EqualityM44.E[i] = TestM44.E[i]; } - - m44 TransposeM44 = m44{ - 0, 4, 8, 12, - 1, 5, 9, 13, - 2, 6, 10, 14, - 3, 7, 11, 15 - }; - - m44 IdentityM44 = m44{ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - - m44 TestM44Squared = m44{ - 56, 62, 68, 74, - 152, 174, 196, 218, - 248, 286, 324, 362, - 344, 398, 452, 506, - }; - - TestClean(((IdentityM33 == IdentityM33) && (TestM33 == EqualityM33)), "M33 Equality"); - TestClean(((IdentityM44 == IdentityM44) && (TestM44 == EqualityM44)), "M44 Equality"); - - TestClean(((Transpose(IdentityM33) == IdentityM33) && - (Transpose(TestM33) == TransposeM33)), "M33 Transpose"); - TestClean(((Transpose(IdentityM44) == IdentityM44) && - (Transpose(TestM44) == TransposeM44)), "M44 Transpose"); - - TestClean(((TestM33 * IdentityM33) == TestM33), "M33 Identity Mult"); - TestClean(((TestM44 * IdentityM44) == TestM44), "M44 Identity Mult"); - TestClean(((TestM33 * TestM33) == TestM33Squared), "M33 Mult"); - TestClean(((TestM44 * TestM44) == TestM44Squared), "M44 Mult"); - - - // Useful Tests - v4 Right = v4{1, 0, 0, 0}; - v4 Forward = v4{0, 0, 1, 0}; - v4 Up = v4{0, 1, 0, 0}; - v4 Left = v4{-1, 0, 0, 0}; - v4 Back = v4{0, 0, -1, 0}; - v4 Down = v4{0, -1, 0, 0}; - - m44 NinetyDegreesAboutX = GetXRotation(M_PI / 2); - v4 Rotated = NinetyDegreesAboutX * Forward; - TestClean((Rotated == Up), "Rotation About X"); - - m44 NinetyDegreesAboutY = GetYRotation(M_PI / 2); - Rotated = NinetyDegreesAboutY * Right; - TestClean((Rotated == Forward), "Rotation About Y"); - - m44 NinetyDegreesAboutZ = GetZRotation(M_PI / 2); - Rotated = NinetyDegreesAboutZ * Right; - TestClean((Rotated == Down), "Rotation About Z"); - - - v4 A = v4{1, 2, 3, 4}; - m44 B = m44{ - 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 1, 2, 3, - 4, 5, 6, 7}; - v4 VTest = v4{30, 70, 29, 60}; - TestClean(((B * A) == VTest), "V4 M44 Multiplication"); - - m44 C = m44{ - 9, 8, 7, 6, - 5, 4, 3, 2, - 1, 0, 9, 8, - 7, 6, 5, 4 - }; - m44 MResult = B * C; - m44 MTest = m44{ - 50, 40, 60, 50, - 138, 112, 156, 130, - 109, 94, 99, 84, - 116, 94, 132, 110 - }; - TestClean(((B * C) == MTest), "M44 Mult Test 2"); - - m44 Identity = M44Identity(); - m44 InvIdentity = {}; - Inverse(Identity, &InvIdentity); - TestClean((Identity == InvIdentity), "Inverse Identity"); - - m44 Test = m44{ - 2, 4, 6, 7, - 5, 1, 8, 8, - 1, 7, 3, 1, - 3, 9, 2, 4 - }; - m44 PreCalcTestInv = m44{ - -0.3904761904761904762f, 0.26190476190476190475f, -0.02857142857142857139f, 0.16666666666666666668f, - 0.022222222222222222212f, -0.055555555555555555549f, 0.06666666666666666667f, 0.055555555555555555547f, - -0.00317460317460317458f, 0.07936507936507936506f, 0.27619047619047619045f, -0.2222222222222222222f, - 0.24444444444444444444f, -0.1111111111111111111f, -0.26666666666666666667f, 0.1111111111111111111f - }; - m44 InvTest = {}; - Inverse(Test, &InvTest); - //TestClean((PreCalcTestInv == InvTest), "Inverse M44"); - - DebugPrint("Results: Passed %d / %d\n\n\no", SuccessCount, TestCount); -} - -#endif - -#define GS_VECTOR_MATRIX_H -#endif \ No newline at end of file diff --git a/src/panels/foldhaus_panel_hierarchy.h b/src/panels/foldhaus_panel_hierarchy.h new file mode 100644 index 0000000..4adc49b --- /dev/null +++ b/src/panels/foldhaus_panel_hierarchy.h @@ -0,0 +1,78 @@ +PANEL_INIT_PROC(HierarchyView_Init) +{ + +} + +PANEL_CLEANUP_PROC(HierarchyView_Cleanup) +{ + +} + +PANEL_RENDER_PROC(HierarchyView_Render) +{ + r32 PanelWidth = PanelMax.x - PanelMin.x; + r32 PanelHeight = PanelMax.y - PanelMin.y; + + s32 LineBGColorsCount = 2; +v4 LineBGColors[] = { + { .16f, .16f, .16f, 1.f }, + { .18f, .18f, .18f, 1.f }, + }; + v4 LineBGHoverColor = { .22f, .22f, .22f, 1.f }; + + r32 LineHeight = State->Interface.Font->PixelHeight + 8; + v2 LineMin = v2{PanelMin.x + State->Interface.Margin.x, PanelMax.y - LineHeight}; + v2 LineMax = LineMin + v2{PanelWidth, LineHeight}; + v2 TextOffset = v2{10, 4}; + string TempString = MakeString(PushArray(&State->Transient, char, 256), 256); + + s32 LineCount = (s32)(PanelHeight / LineHeight) + 1; + for (s32 i = 0; i < LineCount; i++) + { + v4 Color = LineBGColors[i % LineBGColorsCount]; + if (PointIsInRange(Mouse.Pos, LineMin, LineMax)) + { + Color = LineBGHoverColor; + } +PushRenderQuad2D(RenderBuffer, LineMin, LineMax, Color); + if (i < State->ActiveAssemblyIndecies.Used) + { +array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); + PrintF(&TempString, "%S", Assembly.Name); + + DrawString(RenderBuffer, TempString, State->Interface.Font, LineMin + TextOffset, WhiteV4); + + PrintF(&TempString, "X"); + + v2 XLowerRight = v2{LineMax.x - 25, LineMin.y + TextOffset.y}; + v2 XLowerLeft = DrawString(RenderBuffer, TempString, State->Interface.Font, XLowerRight, WhiteV4, Align_Right); + + if (MouseButtonTransitionedUp(Mouse.LeftButtonState) + && PointIsInRange(Mouse.Pos, XLowerLeft, LineMax)) + { + UnloadAssembly(i, State, Context); + } + } + else if (i == State->ActiveAssemblyIndecies.Used) + { + PrintF(&TempString, "+ Add Assembly"); + v2 TextMinX = LineMin + TextOffset; + DrawString(RenderBuffer, TempString, State->Interface.Font, TextMinX, WhiteV4); + + if (MouseButtonTransitionedUp(Mouse.LeftButtonState) + && PointIsInRange(Mouse.Pos, LineMin, LineMax)) + { + char FilePath[256]; + b32 Success = Context.PlatformGetFilePath(FilePath, 256, "Foldhaus Files\0*.fold\0\0"); + if (Success) + { + LoadAssembly(State, Context, FilePath); + } + } + } + + LineMin.y = GSMax(PanelMin.y, LineMin.y - LineHeight); + LineMax.y = GSMax(PanelMin.y, LineMax.y - LineHeight); + } +} \ No newline at end of file diff --git a/src/panels/foldhaus_panel_sculpture_view.h b/src/panels/foldhaus_panel_sculpture_view.h index 1200313..3c6d72e 100644 --- a/src/panels/foldhaus_panel_sculpture_view.h +++ b/src/panels/foldhaus_panel_sculpture_view.h @@ -1,3 +1,7 @@ +input_command SculptureView_Commands[] = { + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, Begin3DViewMouseRotate }, +}; + PANEL_INIT_PROC(SculptureView_Init) {