diff --git a/build/build_app_msvc_win32_debug.bat b/build/build_app_msvc_win32_debug.bat index 1997c89..2dafabf 100644 --- a/build/build_app_msvc_win32_debug.bat +++ b/build/build_app_msvc_win32_debug.bat @@ -6,7 +6,7 @@ SET MyPath=%MyPath:~0,-1% call %MyPath%\_prebuild_win32.bat app debug msvc call %MyPath%\setup_cl.bat -SET CommonCompilerFlags=-nologo -DDEBUG=1 -DPLATFORM_WINDOWS -FC -WX -W4 -Z7 -Oi -GR- -EHsc -EHa- -MTd -fp:fast -fp:except- -IC:\programs-dev\gs_libs\src +SET CommonCompilerFlags=-nologo -DDEBUG=0 -DPLATFORM_WINDOWS -FC -WX -W4 -Z7 -Oi -GR- -EHsc -EHa- -MTd -fp:fast -fp:except- -IC:\programs-dev\gs_libs\src SET CommonCompilerFlags=-wd4127 -wd4702 -wd4101 -wd4505 -wd4100 -wd4189 -wd4244 -wd4201 -wd4996 -I%CommonLibs% -Od %CommonCompilerFlags% diff --git a/src/app/editor/foldhaus_operation_mode.h b/src/app/editor/foldhaus_operation_mode.h index 46d5830..375d342 100644 --- a/src/app/editor/foldhaus_operation_mode.h +++ b/src/app/editor/foldhaus_operation_mode.h @@ -14,77 +14,77 @@ typedef OPERATION_RENDER_PROC(operation_render_proc); struct operation_mode { - input_command_registry Commands; - operation_render_proc* Render; - gs_memory_cursor Memory; - u8* OpStateMemory; + input_command_registry Commands; + operation_render_proc* Render; + gs_memory_cursor Memory; + u8* OpStateMemory; }; #define OPERATION_MODES_MAX 32 struct operation_mode_system { - s32 ActiveModesCount; - operation_mode ActiveModes[OPERATION_MODES_MAX]; - //arena_snapshot ModeMemorySnapshots[OPERATION_MODES_MAX]; - gs_data_array ModeMemoryPagesFreeList; - - // NOTE(Peter): This acts as mode scoped memory. When a mode gets activated, it can allocate - // temporary memory which then gets freed when the mode is deactivated - gs_memory_arena Arena; + s32 ActiveModesCount; + operation_mode ActiveModes[OPERATION_MODES_MAX]; + //arena_snapshot ModeMemorySnapshots[OPERATION_MODES_MAX]; + gs_data_array ModeMemoryPagesFreeList; + + // NOTE(Peter): This acts as mode scoped memory. When a mode gets activated, it can allocate + // temporary memory which then gets freed when the mode is deactivated + gs_memory_arena Arena; }; internal operation_mode_system OperationModeSystemInit(gs_memory_arena* Storage, gs_thread_context ThreadContext) { - operation_mode_system Result = {0}; - // TODO(Peter): Do we really need an arena? Can this just operate in constant memory footprint? - Result.Arena.Allocator = ThreadContext.Allocator; - - Result.ModeMemoryPagesFreeList.CountMax = 8; - Result.ModeMemoryPagesFreeList.Data = PushArray(Storage, gs_data, Result.ModeMemoryPagesFreeList.CountMax); - for (u32 Page = 0; Page < Result.ModeMemoryPagesFreeList.CountMax; Page++) - { - Result.ModeMemoryPagesFreeList.Data[Page] = PushSizeToData(Storage, KB(4)); - } - Result.ModeMemoryPagesFreeList.Count = Result.ModeMemoryPagesFreeList.CountMax; - - return Result; + operation_mode_system Result = {0}; + // TODO(Peter): Do we really need an arena? Can this just operate in constant memory footprint? + Result.Arena.Allocator = ThreadContext.Allocator; + + Result.ModeMemoryPagesFreeList.CountMax = 8; + Result.ModeMemoryPagesFreeList.Data = PushArray(Storage, gs_data, Result.ModeMemoryPagesFreeList.CountMax); + for (u32 Page = 0; Page < Result.ModeMemoryPagesFreeList.CountMax; Page++) + { + Result.ModeMemoryPagesFreeList.Data[Page] = PushSize(Storage, KB(4)); + } + Result.ModeMemoryPagesFreeList.Count = Result.ModeMemoryPagesFreeList.CountMax; + + return Result; } internal gs_data OperationModeTakeMemoryPage(operation_mode_system* System) { - Assert(System->ModeMemoryPagesFreeList.Count > 0); - gs_data Result = {0}; - System->ModeMemoryPagesFreeList.Count -= 1; - u64 LastIndex = System->ModeMemoryPagesFreeList.Count; - Result = System->ModeMemoryPagesFreeList.Data[LastIndex]; - return Result; + Assert(System->ModeMemoryPagesFreeList.Count > 0); + gs_data Result = {0}; + System->ModeMemoryPagesFreeList.Count -= 1; + u64 LastIndex = System->ModeMemoryPagesFreeList.Count; + Result = System->ModeMemoryPagesFreeList.Data[LastIndex]; + return Result; } internal void OperationModeFreeMemoryPage(operation_mode_system* System, gs_data Data) { - Assert(System->ModeMemoryPagesFreeList.Count < System->ModeMemoryPagesFreeList.CountMax); - u64 LastIndex = System->ModeMemoryPagesFreeList.Count; - System->ModeMemoryPagesFreeList.Count += 1; - System->ModeMemoryPagesFreeList.Data[LastIndex] = Data; + Assert(System->ModeMemoryPagesFreeList.Count < System->ModeMemoryPagesFreeList.CountMax); + u64 LastIndex = System->ModeMemoryPagesFreeList.Count; + System->ModeMemoryPagesFreeList.Count += 1; + System->ModeMemoryPagesFreeList.Data[LastIndex] = Data; } internal operation_mode* ActivateOperationMode (operation_mode_system* System, operation_render_proc* RenderProc) { - Assert(System->ActiveModesCount < OPERATION_MODES_MAX); - operation_mode* Result = 0; - s32 ModeIndex = System->ActiveModesCount++; - - //System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(&System->Arena); - - Result = &System->ActiveModes[ModeIndex]; - Result->Memory = CreateMemoryCursor(OperationModeTakeMemoryPage(System)); - Result->Render = RenderProc; - - return Result; + Assert(System->ActiveModesCount < OPERATION_MODES_MAX); + operation_mode* Result = 0; + s32 ModeIndex = System->ActiveModesCount++; + + //System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(&System->Arena); + + Result = &System->ActiveModes[ModeIndex]; + Result->Memory = MemoryCursorCreateFromData(OperationModeTakeMemoryPage(System)); + Result->Render = RenderProc; + + return Result; } #define ActivateOperationModeWithCommands(sys, cmds, render) \ @@ -93,30 +93,30 @@ ActivateOperationModeWithCommands_(sys, cmds, (s32)(sizeof(cmds) / sizeof(cmds[0 internal operation_mode* ActivateOperationModeWithCommands_(operation_mode_system* System, input_command* Commands, s32 CommandsCount, operation_render_proc* RenderProc) { - operation_mode* NewMode = ActivateOperationMode(System, RenderProc); - + operation_mode* NewMode = ActivateOperationMode(System, RenderProc); + #if 0 - InitializeInputCommandRegistry(&NewMode->Commands, CommandsCount, &System->Arena); - for (s32 i = 0; i < CommandsCount; i++) - { - input_command Command = Commands[i]; - RegisterKeyPressCommand(&NewMode->Commands, Command.Key, Command.Flags, Command.Mdfr, Command.Proc); - } + InitializeInputCommandRegistry(&NewMode->Commands, CommandsCount, &System->Arena); + for (s32 i = 0; i < CommandsCount; i++) + { + input_command Command = Commands[i]; + RegisterKeyPressCommand(&NewMode->Commands, Command.Key, Command.Flags, Command.Mdfr, Command.Proc); + } #else - NewMode->Commands.Commands = Commands; - NewMode->Commands.Size = CommandsCount; - NewMode->Commands.Used = CommandsCount; + NewMode->Commands.Commands = Commands; + NewMode->Commands.Size = CommandsCount; + NewMode->Commands.Used = CommandsCount; #endif - return NewMode; + return NewMode; } internal void DeactivateCurrentOperationMode (operation_mode_system* System) { - Assert(System->ActiveModesCount > 0); - s32 ModeIndex = --System->ActiveModesCount; - OperationModeFreeMemoryPage(System, System->ActiveModes[ModeIndex].Memory.Data); - //ClearArenaToSnapshot(&System->Arena, System->ModeMemorySnapshots[ModeIndex]); + Assert(System->ActiveModesCount > 0); + s32 ModeIndex = --System->ActiveModesCount; + OperationModeFreeMemoryPage(System, System->ActiveModes[ModeIndex].Memory.Data); + //ClearArenaToSnapshot(&System->Arena, System->ModeMemorySnapshots[ModeIndex]); } #define CreateOperationState(mode, modeSystem, stateType) \ @@ -129,12 +129,12 @@ DeactivateCurrentOperationMode (operation_mode_system* System) internal u8* CreateOperationState_ (operation_mode* Mode, operation_mode_system* System, s32 StateSize) { - // NOTE(Peter): This isn't a problem if this fires, it just means our page size is too small, - // and its time to make the pages dynamically sized - Assert(Mode->Memory.Data.Size >= StateSize); - u8* Result = PushSizeOnCursor(&Mode->Memory, StateSize).Memory; - Mode->OpStateMemory = Result; - return Result; + // NOTE(Peter): This isn't a problem if this fires, it just means our page size is too small, + // and its time to make the pages dynamically sized + Assert(Mode->Memory.Data.Size >= StateSize); + u8* Result = MemoryCursorPushSize(&Mode->Memory, StateSize).Memory; + Mode->OpStateMemory = Result; + return Result; } diff --git a/src/app/editor/interface.h b/src/app/editor/interface.h index 854c3dc..d618089 100644 --- a/src/app/editor/interface.h +++ b/src/app/editor/interface.h @@ -9,600 +9,600 @@ enum gs_string_alignment { - Align_Left, - Align_Center, - Align_Right, + Align_Left, + Align_Center, + Align_Right, }; internal void ClipUVRect(rect2* Bounds, rect2* UVs, rect2 ClippingBox) { - rect2 NewBounds = Rect2Union(*Bounds, ClippingBox); - - r32 OldWidth = Rect2Width(*Bounds); - r32 OldHeight = Rect2Height(*Bounds); - - v2 MinInsetPercent = v2{ - (NewBounds.Min.x - Bounds->Min.x) / OldWidth, - (NewBounds.Min.y - Bounds->Min.y) / OldHeight, - }; - - v2 MaxInsetPercent = v2{ - (NewBounds.Max.x - Bounds->Min.x) / OldWidth, - (NewBounds.Max.y - Bounds->Min.y) / OldHeight, - }; - - UVs->Min.x = LerpR32(MinInsetPercent.x, UVs->Min.x, UVs->Max.x); - UVs->Min.y = LerpR32(MinInsetPercent.y, UVs->Min.y, UVs->Max.y); - UVs->Max.x = LerpR32(MaxInsetPercent.x, UVs->Min.x, UVs->Max.x); - UVs->Max.y = LerpR32(MaxInsetPercent.y, UVs->Min.y, UVs->Max.y); - - *Bounds = NewBounds; + rect2 NewBounds = Rect2Union(*Bounds, ClippingBox); + + r32 OldWidth = Rect2Width(*Bounds); + r32 OldHeight = Rect2Height(*Bounds); + + v2 MinInsetPercent = v2{ + (NewBounds.Min.x - Bounds->Min.x) / OldWidth, + (NewBounds.Min.y - Bounds->Min.y) / OldHeight, + }; + + v2 MaxInsetPercent = v2{ + (NewBounds.Max.x - Bounds->Min.x) / OldWidth, + (NewBounds.Max.y - Bounds->Min.y) / OldHeight, + }; + + UVs->Min.x = LerpR32(MinInsetPercent.x, UVs->Min.x, UVs->Max.x); + UVs->Min.y = LerpR32(MinInsetPercent.y, UVs->Min.y, UVs->Max.y); + UVs->Max.x = LerpR32(MaxInsetPercent.x, UVs->Min.x, UVs->Max.x); + UVs->Max.y = LerpR32(MaxInsetPercent.y, UVs->Min.y, UVs->Max.y); + + *Bounds = NewBounds; } internal void DrawCharacter_ (render_quad_batch_constructor* BatchConstructor, r32 MinX, r32 MinY, codepoint_bitmap CodepointInfo, rect2 ClippingBox, v4 Color) { - rect2 Bounds = {}; - Bounds.Min.x = FloorR32(MinX); - Bounds.Min.y = FloorR32(MinY); - Bounds.Max.x = Bounds.Min.x + (CodepointInfo.Width); - Bounds.Max.y = Bounds.Min.y + (CodepointInfo.Height); - - rect2 UVBounds = {}; - UVBounds.Min = CodepointInfo.UVMin; - UVBounds.Max = CodepointInfo.UVMax; - - ClipUVRect(&Bounds, &UVBounds, ClippingBox); - - s32 AlignedMinX = (s32)(MinX); - s32 AlignedMinY = (s32)(MinY); - s32 AlignedMaxX = AlignedMinX + (CodepointInfo.Width); - s32 AlignedMaxY = AlignedMinY + (CodepointInfo.Height); - - PushQuad2DOnBatch(BatchConstructor, - Rect2BottomLeft(Bounds), Rect2BottomRight(Bounds), - Rect2TopRight(Bounds), Rect2TopLeft(Bounds), - UVBounds.Min, UVBounds.Max, - Color); + rect2 Bounds = {}; + Bounds.Min.x = FloorR32(MinX); + Bounds.Min.y = FloorR32(MinY); + Bounds.Max.x = Bounds.Min.x + (CodepointInfo.Width); + Bounds.Max.y = Bounds.Min.y + (CodepointInfo.Height); + + rect2 UVBounds = {}; + UVBounds.Min = CodepointInfo.UVMin; + UVBounds.Max = CodepointInfo.UVMax; + + ClipUVRect(&Bounds, &UVBounds, ClippingBox); + + s32 AlignedMinX = (s32)(MinX); + s32 AlignedMinY = (s32)(MinY); + s32 AlignedMaxX = AlignedMinX + (CodepointInfo.Width); + s32 AlignedMaxY = AlignedMinY + (CodepointInfo.Height); + + PushQuad2DOnBatch(BatchConstructor, + Rect2BottomLeft(Bounds), Rect2BottomRight(Bounds), + Rect2TopRight(Bounds), Rect2TopLeft(Bounds), + UVBounds.Min, UVBounds.Max, + Color); } internal v2 DrawCharacterLeftAligned (render_quad_batch_constructor* BatchConstructor, char C, bitmap_font Font, v2 Position, rect2 ClippingBox, v4 Color) { - s32 GlyphDataIndex = GetIndexForCodepoint(Font, C); - codepoint_bitmap CodepointInfo = Font.CodepointValues[GlyphDataIndex]; - - // NOTE(Peter): - r32 MinX = Position.x + CodepointInfo.XOffset; - r32 MinY = Position.y + CodepointInfo.YOffset; - DrawCharacter_(BatchConstructor, MinX, MinY, CodepointInfo, ClippingBox, Color); - - // NOTE(Peter): - v2 PointAfterCharacter = v2{Position.x + CodepointInfo.Width, Position.y}; - return PointAfterCharacter; + s32 GlyphDataIndex = GetIndexForCodepoint(Font, C); + codepoint_bitmap CodepointInfo = Font.CodepointValues[GlyphDataIndex]; + + // NOTE(Peter): + r32 MinX = Position.x + CodepointInfo.XOffset; + r32 MinY = Position.y + CodepointInfo.YOffset; + DrawCharacter_(BatchConstructor, MinX, MinY, CodepointInfo, ClippingBox, Color); + + // NOTE(Peter): + v2 PointAfterCharacter = v2{Position.x + CodepointInfo.Width, Position.y}; + return PointAfterCharacter; } internal v2 DrawCharacterRightAligned (render_quad_batch_constructor* BatchConstructor, char C, bitmap_font Font, v2 Position, rect2 ClippingBox, v4 Color) { - s32 GlyphDataIndex = GetIndexForCodepoint(Font, C); - codepoint_bitmap CodepointInfo = Font.CodepointValues[GlyphDataIndex]; - - // NOTE(Peter): - r32 MinX = Position.x - (CodepointInfo.XOffset + CodepointInfo.Width); - r32 MinY = Position.y + CodepointInfo.YOffset + CodepointInfo.YOffset; - DrawCharacter_(BatchConstructor, MinX, MinY, CodepointInfo, ClippingBox, Color); - - // NOTE(Peter): - v2 PointAfterCharacter = v2{Position.x-(CodepointInfo.Width + CodepointInfo.XOffset), Position.y}; - return PointAfterCharacter; + s32 GlyphDataIndex = GetIndexForCodepoint(Font, C); + codepoint_bitmap CodepointInfo = Font.CodepointValues[GlyphDataIndex]; + + // NOTE(Peter): + r32 MinX = Position.x - (CodepointInfo.XOffset + CodepointInfo.Width); + r32 MinY = Position.y + CodepointInfo.YOffset + CodepointInfo.YOffset; + DrawCharacter_(BatchConstructor, MinX, MinY, CodepointInfo, ClippingBox, Color); + + // NOTE(Peter): + v2 PointAfterCharacter = v2{Position.x-(CodepointInfo.Width + CodepointInfo.XOffset), Position.y}; + return PointAfterCharacter; } internal void DrawCursor (render_command_buffer* RenderBuffer, v2 RegisterPosition, bitmap_font* Font, v4 Color) { - rect2 CursorRect = {}; - CursorRect.Min = RegisterPosition; - CursorRect.Max = CursorRect.Min + v2{5, (r32)Font->Ascent}; - PushRenderQuad2D(RenderBuffer, CursorRect, Color); + rect2 CursorRect = {}; + CursorRect.Min = RegisterPosition; + CursorRect.Max = CursorRect.Min + v2{5, (r32)Font->Ascent}; + PushRenderQuad2D(RenderBuffer, CursorRect, Color); } internal v2 DrawStringLeftAligned (render_command_buffer* RenderBuffer, render_quad_batch_constructor* BatchConstructor, s32 Length, char* gs_string, v2 InitialRegisterPosition, bitmap_font* Font, rect2 ClippingBox, v4 Color, s32 CursorBeforeIndex, v4 CursorColor) { - v2 RegisterPosition = InitialRegisterPosition; - char* C = gs_string; - for (s32 i = 0; i < Length; i++) + v2 RegisterPosition = InitialRegisterPosition; + char* C = gs_string; + for (s32 i = 0; i < Length; i++) + { + if (i == CursorBeforeIndex) { - if (i == CursorBeforeIndex) - { - DrawCursor(RenderBuffer, RegisterPosition, Font, CursorColor); - } - - v2 PositionAfterCharacter = DrawCharacterLeftAligned(BatchConstructor, *C, *Font, RegisterPosition, ClippingBox, Color); - RegisterPosition.x = PositionAfterCharacter.x; - C++; + DrawCursor(RenderBuffer, RegisterPosition, Font, CursorColor); } - if (CursorBeforeIndex == Length) - { - DrawCursor(RenderBuffer, RegisterPosition, Font, CursorColor); - } - return RegisterPosition; + + v2 PositionAfterCharacter = DrawCharacterLeftAligned(BatchConstructor, *C, *Font, RegisterPosition, ClippingBox, Color); + RegisterPosition.x = PositionAfterCharacter.x; + C++; + } + if (CursorBeforeIndex == Length) + { + DrawCursor(RenderBuffer, RegisterPosition, Font, CursorColor); + } + return RegisterPosition; } internal v2 DrawStringRightAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* gs_string, v2 InitialRegisterPosition, bitmap_font* Font, rect2 ClippingBox, v4 Color) { - v2 RegisterPosition = InitialRegisterPosition; - char* C = gs_string + Length - 1; - for (s32 i = Length - 1; i >= 0; i--) - { - v2 PositionAfterCharacter = DrawCharacterRightAligned(BatchConstructor, *C, *Font, RegisterPosition, ClippingBox, Color); - RegisterPosition.x = PositionAfterCharacter.x; - C--; - } - return RegisterPosition; + v2 RegisterPosition = InitialRegisterPosition; + char* C = gs_string + Length - 1; + for (s32 i = Length - 1; i >= 0; i--) + { + v2 PositionAfterCharacter = DrawCharacterRightAligned(BatchConstructor, *C, *Font, RegisterPosition, ClippingBox, Color); + RegisterPosition.x = PositionAfterCharacter.x; + C--; + } + return RegisterPosition; } internal v2 DrawString(render_command_buffer* RenderBuffer, gs_string String, bitmap_font* Font, v2 Position, v4 Color, s32 CursorPosition, v4 CursorColor, gs_string_alignment Alignment = Align_Left) { - DEBUG_TRACK_FUNCTION; - v2 LowerRight = Position; - - render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length + 1, - Font->BitmapMemory, - Font->BitmapTextureHandle, - Font->BitmapWidth, - Font->BitmapHeight, - Font->BitmapBytesPerPixel, - Font->BitmapStride); - - // TODO(pjs): I don't like this solution but it'll do for now and I want to focus on other problems - // especially since I think this one will go away once I finish the ui overhaul - rect2 InfiniteClipBox = {}; - InfiniteClipBox.Min.x = -100000; - InfiniteClipBox.Min.y = -100000; - InfiniteClipBox.Max.x = 100000; - InfiniteClipBox.Max.y = 100000; - - v2 RegisterPosition = Position; - if (Alignment == Align_Left) - { - RegisterPosition = DrawStringLeftAligned(RenderBuffer, &BatchConstructor, StringExpand(String), RegisterPosition, Font, InfiniteClipBox, Color, CursorPosition, CursorColor); - } - else if (Alignment == Align_Right) - { - RegisterPosition = DrawStringRightAligned(&BatchConstructor, StringExpand(String), RegisterPosition, Font, InfiniteClipBox, Color); - } - else - { - InvalidCodePath; - } - - LowerRight.x = RegisterPosition.x; - - return LowerRight; + DEBUG_TRACK_FUNCTION; + v2 LowerRight = Position; + + render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length + 1, + Font->BitmapMemory, + Font->BitmapTextureHandle, + Font->BitmapWidth, + Font->BitmapHeight, + Font->BitmapBytesPerPixel, + Font->BitmapStride); + + // TODO(pjs): I don't like this solution but it'll do for now and I want to focus on other problems + // especially since I think this one will go away once I finish the ui overhaul + rect2 InfiniteClipBox = {}; + InfiniteClipBox.Min.x = -100000; + InfiniteClipBox.Min.y = -100000; + InfiniteClipBox.Max.x = 100000; + InfiniteClipBox.Max.y = 100000; + + v2 RegisterPosition = Position; + if (Alignment == Align_Left) + { + RegisterPosition = DrawStringLeftAligned(RenderBuffer, &BatchConstructor, StringExpand(String), RegisterPosition, Font, InfiniteClipBox, Color, CursorPosition, CursorColor); + } + else if (Alignment == Align_Right) + { + RegisterPosition = DrawStringRightAligned(&BatchConstructor, StringExpand(String), RegisterPosition, Font, InfiniteClipBox, Color); + } + else + { + InvalidCodePath; + } + + LowerRight.x = RegisterPosition.x; + + return LowerRight; } internal void DrawCursor (render_quad_batch_constructor* BatchConstructor, v2 Position, v4 Color, bitmap_font Font) { - v2 Min = Position; - v2 Max = Position + v2{(r32)Font.MaxCharWidth, (r32)(Font.Ascent + Font.Descent)}; - PushQuad2DOnBatch(BatchConstructor, Min, Max, Color); + v2 Min = Position; + v2 Max = Position + v2{(r32)Font.MaxCharWidth, (r32)(Font.Ascent + Font.Descent)}; + PushQuad2DOnBatch(BatchConstructor, Min, Max, Color); } #if 0 internal v2 DrawStringWithCursor (render_command_buffer* RenderBuffer, gs_string String, s32 CursorPosition, bitmap_font* Font, v2 Position, v4 Color, v4 CursorColor, gs_string_alignment Alignment = Align_Left) { - DEBUG_TRACK_FUNCTION; - v2 LowerRight = Position; - - // NOTE(Peter): We push this on first so that the cursor will be drawn underneath any character it may overlap with - render_quad_batch_constructor CursorBatch = PushRenderQuad2DBatch(RenderBuffer, 1); - render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length, - Font->BitmapMemory, - Font->BitmapTextureHandle, - Font->BitmapWidth, - Font->BitmapHeight, - Font->BitmapBytesPerPixel, - Font->BitmapStride); - - v2 RegisterPosition = Position; - if (Alignment == Align_Left) + DEBUG_TRACK_FUNCTION; + v2 LowerRight = Position; + + // NOTE(Peter): We push this on first so that the cursor will be drawn underneath any character it may overlap with + render_quad_batch_constructor CursorBatch = PushRenderQuad2DBatch(RenderBuffer, 1); + render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length, + Font->BitmapMemory, + Font->BitmapTextureHandle, + Font->BitmapWidth, + Font->BitmapHeight, + Font->BitmapBytesPerPixel, + Font->BitmapStride); + + v2 RegisterPosition = Position; + if (Alignment == Align_Left) + { + RegisterPosition = DrawStringLeftAligned(&BatchConstructor, StringExpand(String), RegisterPosition, Font, Color); + DrawCursor(&CursorBatch, RegisterPosition, GreenV4, *Font); + if (String.Length - CursorPosition > 0) { - RegisterPosition = DrawStringLeftAligned(&BatchConstructor, StringExpand(String), RegisterPosition, Font, Color); - DrawCursor(&CursorBatch, RegisterPosition, GreenV4, *Font); - if (String.Length - CursorPosition > 0) - { - RegisterPosition = DrawStringLeftAligned(&BatchConstructor, - String.Length - CursorPosition, - String.Str + CursorPosition, - RegisterPosition, Font, Color); - } + RegisterPosition = DrawStringLeftAligned(&BatchConstructor, + String.Length - CursorPosition, + String.Str + CursorPosition, + RegisterPosition, Font, Color); } - else if (Alignment == Align_Right) + } + else if (Alignment == Align_Right) + { + RegisterPosition = DrawStringRightAligned(&BatchConstructor, + CursorPosition, String.Str, + RegisterPosition, Font, Color); + DrawCursor(&CursorBatch, RegisterPosition, GreenV4, *Font); + if (String.Length - CursorPosition > 0) { - RegisterPosition = DrawStringRightAligned(&BatchConstructor, - CursorPosition, String.Str, - RegisterPosition, Font, Color); - DrawCursor(&CursorBatch, RegisterPosition, GreenV4, *Font); - if (String.Length - CursorPosition > 0) - { - RegisterPosition = DrawStringRightAligned(&BatchConstructor, - String.Length - CursorPosition, - String.Str + CursorPosition, - RegisterPosition, Font, Color); - } + RegisterPosition = DrawStringRightAligned(&BatchConstructor, + String.Length - CursorPosition, + String.Str + CursorPosition, + RegisterPosition, Font, Color); } - else - { - InvalidCodePath; - } - - LowerRight.x = RegisterPosition.x; - return LowerRight; + } + else + { + InvalidCodePath; + } + + LowerRight.x = RegisterPosition.x; + return LowerRight; } #endif enum ui_widget_flag { - UIWidgetFlag_ExpandsToFitChildren, - - UIWidgetFlag_DrawBackground, - UIWidgetFlag_DrawString, - UIWidgetFlag_DrawOutline, - UIWidgetFlag_DrawHorizontalFill, - UIWidgetFlag_DrawVerticalFill, - UIWidgetFlag_DrawFillReversed, - UIWidgetFlag_DrawFillAsHandle, - - UIWidgetFlag_Clickable, - UIWidgetFlag_Selectable, - UIWidgetFlag_Typable, + UIWidgetFlag_ExpandsToFitChildren, + + UIWidgetFlag_DrawBackground, + UIWidgetFlag_DrawString, + UIWidgetFlag_DrawOutline, + UIWidgetFlag_DrawHorizontalFill, + UIWidgetFlag_DrawVerticalFill, + UIWidgetFlag_DrawFillReversed, + UIWidgetFlag_DrawFillAsHandle, + + UIWidgetFlag_Clickable, + UIWidgetFlag_Selectable, + UIWidgetFlag_Typable, }; struct ui_widget_id { - u64 Id; - u64 ZIndex; + u64 Id; + u64 ZIndex; }; enum ui_layout_direction { - LayoutDirection_TopDown, - LayoutDirection_BottomUp, - LayoutDirection_Inherit, + LayoutDirection_TopDown, + LayoutDirection_BottomUp, + LayoutDirection_Inherit, }; struct ui_column { - r32 XMin; - r32 XMax; + r32 XMin; + r32 XMax; }; struct ui_widget { - ui_widget_id Id; - - gs_string String; - gs_string_alignment Alignment; - - rect2 Bounds; - u64 Flags; - - ui_widget* Next; - - // Slider - r32 FillPercent; - - // Layout - ui_widget* Parent; - - v2 Margin; - r32 RowHeight; - r32 RowYAt; - - ui_layout_direction FillDirection; - - ui_column* Columns; - u32 ColumnsCount; - u32 ColumnsFilled; - - // NOTE(pjs): I'm not sure this will stay but - // its here so that when we end things like a dropdown, - // we can check the retained state of that dropdown - ui_widget_id WidgetReference; - - u64 ChildZIndexOffset; - - ui_widget* ChildrenRoot; - ui_widget* ChildrenHead; - u32 ChildCount; + ui_widget_id Id; + + gs_string String; + gs_string_alignment Alignment; + + rect2 Bounds; + u64 Flags; + + ui_widget* Next; + + // Slider + r32 FillPercent; + + // Layout + ui_widget* Parent; + + v2 Margin; + r32 RowHeight; + r32 RowYAt; + + ui_layout_direction FillDirection; + + ui_column* Columns; + u32 ColumnsCount; + u32 ColumnsFilled; + + // NOTE(pjs): I'm not sure this will stay but + // its here so that when we end things like a dropdown, + // we can check the retained state of that dropdown + ui_widget_id WidgetReference; + + u64 ChildZIndexOffset; + + ui_widget* ChildrenRoot; + ui_widget* ChildrenHead; + u32 ChildCount; }; struct ui_eval_result { - bool Clicked; - bool Held; - v2 DragDelta; + bool Clicked; + bool Held; + v2 DragDelta; }; struct interface_config { - v4 PanelBG; - - // TODO(pjs): Turn these into _Default, _Hot, _Active - v4 ButtonColor_Inactive, ButtonColor_Active, ButtonColor_Selected; - - v4 TextColor; - + v4 PanelBG; + + // TODO(pjs): Turn these into _Default, _Hot, _Active + v4 ButtonColor_Inactive, ButtonColor_Active, ButtonColor_Selected; + + v4 TextColor; + #define LIST_BG_COLORS_COUNT 2 - v4 ListBGColors[LIST_BG_COLORS_COUNT]; - v4 ListBGHover; - v4 ListBGSelected; - - bitmap_font* Font; - r32 FontSize; - v2 Margin; - r32 RowHeight; + v4 ListBGColors[LIST_BG_COLORS_COUNT]; + v4 ListBGHover; + v4 ListBGSelected; + + bitmap_font* Font; + r32 FontSize; + v2 Margin; + r32 RowHeight; }; struct ui_widget_retained_state { - ui_widget_id Id; - bool Value; - r32 InitialValueR32; - u32 FramesSinceAccess; - - // For use in layouts that allow you to scroll / pan - v2 ChildrenDrawOffset; - - gs_string EditString; - - // For dropdowns and rows to be able to error check not closing - // a layout you open - u32 MaxChildren; + ui_widget_id Id; + bool Value; + r32 InitialValueR32; + u32 FramesSinceAccess; + + // For use in layouts that allow you to scroll / pan + v2 ChildrenDrawOffset; + + gs_string EditString; + + // For dropdowns and rows to be able to error check not closing + // a layout you open + u32 MaxChildren; }; struct ui_interface { - interface_config Style; - - mouse_state Mouse; - rect2 WindowBounds; - - // A per-frame string of the characters which have been typed - gs_const_string TempInputString; - u64 CursorPosition; - - render_command_buffer* RenderBuffer; - - ui_widget* Widgets; - u64 WidgetsCount; - u64 WidgetsCountMax; - - ui_widget* DrawOrderHead; - ui_widget* DrawOrderRoot; - - ui_widget_id HotWidget; - // This should really never get higher than 1 or 2 - u8 HotWidgetFramesSinceUpdate; - - ui_widget_id ActiveWidget; - ui_widget_id LastActiveWidget; - - ui_widget* ActiveLayout; - + interface_config Style; + + mouse_state Mouse; + rect2 WindowBounds; + + // A per-frame string of the characters which have been typed + gs_const_string TempInputString; + u64 CursorPosition; + + render_command_buffer* RenderBuffer; + + ui_widget* Widgets; + u64 WidgetsCount; + u64 WidgetsCountMax; + + ui_widget* DrawOrderHead; + ui_widget* DrawOrderRoot; + + ui_widget_id HotWidget; + // This should really never get higher than 1 or 2 + u8 HotWidgetFramesSinceUpdate; + + ui_widget_id ActiveWidget; + ui_widget_id LastActiveWidget; + + ui_widget* ActiveLayout; + #define RETAINED_STATE_MAX 128 - ui_widget_retained_state RetainedState[RETAINED_STATE_MAX]; - u64 RetainedStateCount; - - gs_memory_arena* PerFrameMemory; - - // TODO(pjs): DONT USE THIS - // Right now you only need this to create EditStrings for ui_widget_retained_state's - // and even for those, you eventually want a better solution than "create a string and it lives forever" - // TODO(pjs): Get rid of the need for this vvv - gs_memory_arena* Permanent; + ui_widget_retained_state RetainedState[RETAINED_STATE_MAX]; + u64 RetainedStateCount; + + gs_memory_arena* PerFrameMemory; + + // TODO(pjs): DONT USE THIS + // Right now you only need this to create EditStrings for ui_widget_retained_state's + // and even for those, you eventually want a better solution than "create a string and it lives forever" + // TODO(pjs): Get rid of the need for this vvv + gs_memory_arena* Permanent; }; internal void ui_InterfaceReset(ui_interface* Interface) { - Interface->WidgetsCount = 0; - Interface->DrawOrderHead = 0; - Interface->DrawOrderRoot = 0; - ClearArena(Interface->PerFrameMemory); - InterfaceAssert(Interface->PerFrameMemory); - - for (u32 i = 0; i < Interface->RetainedStateCount; i++) + Interface->WidgetsCount = 0; + Interface->DrawOrderHead = 0; + Interface->DrawOrderRoot = 0; + MemoryArenaClear(Interface->PerFrameMemory); + InterfaceAssert(Interface->PerFrameMemory); + + for (u32 i = 0; i < Interface->RetainedStateCount; i++) + { + Interface->RetainedState[i].FramesSinceAccess += 1; + if (Interface->RetainedState[i].FramesSinceAccess > 1) { - Interface->RetainedState[i].FramesSinceAccess += 1; - if (Interface->RetainedState[i].FramesSinceAccess > 1) - { - Interface->RetainedState[i].Id = {0}; - } + Interface->RetainedState[i].Id = {0}; } - - Interface->LastActiveWidget = Interface->ActiveWidget; + } + + Interface->LastActiveWidget = Interface->ActiveWidget; } internal bool ui_WidgetIdsEqual(ui_widget_id A, ui_widget_id B) { - bool Result = (A.Id == B.Id);// && (A.ParentId == B.ParentId); - return Result; + bool Result = (A.Id == B.Id);// && (A.ParentId == B.ParentId); + return Result; } internal void ui_WidgetSetFlag(ui_widget* Widget, u64 Flag) { - u64 Value = ((u64)1 << Flag); - Widget->Flags = Widget->Flags | Value; + u64 Value = ((u64)1 << Flag); + Widget->Flags = Widget->Flags | Value; } internal void ui_WidgetClearFlag(ui_widget* Widget, u64 Flag) { - u64 Value = ((u64)1 << Flag); - Widget->Flags = Widget->Flags & ~Value; + u64 Value = ((u64)1 << Flag); + Widget->Flags = Widget->Flags & ~Value; } internal bool ui_WidgetIsFlagSet(ui_widget Widget, u64 Flag) { - u64 Value = ((u64)1 << Flag); - bool Result = (Widget.Flags & Value); - return Result; + u64 Value = ((u64)1 << Flag); + bool Result = (Widget.Flags & Value); + return Result; } internal void ui_WidgetSetChildrenPopover(ui_widget* Widget) { - Widget->ChildZIndexOffset = 1000; + Widget->ChildZIndexOffset = 1000; } internal ui_widget* ui_WidgetGetWidgetWithId(ui_widget* Parent, ui_widget_id Id) { - ui_widget* Result = 0; - - if (ui_WidgetIdsEqual(Parent->Id, Id)) + ui_widget* Result = 0; + + if (ui_WidgetIdsEqual(Parent->Id, Id)) + { + Result = Parent; + } + else if (Parent->ChildrenRoot != 0) + { + for (ui_widget* At = Parent->ChildrenRoot; At != 0; At = At->Next) { - Result = Parent; + Result = ui_WidgetGetWidgetWithId(At, Id); + if (Result != 0) + { + break; + } } - else if (Parent->ChildrenRoot != 0) - { - for (ui_widget* At = Parent->ChildrenRoot; At != 0; At = At->Next) - { - Result = ui_WidgetGetWidgetWithId(At, Id); - if (Result != 0) - { - break; - } - } - } - - return Result; + } + + return Result; } internal ui_widget* ui_InterfaceGetWidgetWithId(ui_interface* Interface, ui_widget_id Id) { - ui_widget* Result = 0; - - for (ui_widget* At = Interface->DrawOrderRoot; At != 0; At = At->Next) + ui_widget* Result = 0; + + for (ui_widget* At = Interface->DrawOrderRoot; At != 0; At = At->Next) + { + Result = ui_WidgetGetWidgetWithId(At, Id); + if (Result != 0) { - Result = ui_WidgetGetWidgetWithId(At, Id); - if (Result != 0) - { - break; - } + break; } - - return Result; + } + + return Result; } internal ui_widget_retained_state* ui_GetRetainedState(ui_interface* Interface, ui_widget_id Id) { - ui_widget_retained_state* Result = 0; - for (u64 i = 0; i < Interface->RetainedStateCount; i++) + ui_widget_retained_state* Result = 0; + for (u64 i = 0; i < Interface->RetainedStateCount; i++) + { + if (ui_WidgetIdsEqual(Interface->RetainedState[i].Id, Id)) { - if (ui_WidgetIdsEqual(Interface->RetainedState[i].Id, Id)) - { - // NOTE(PS): If we are accessing a retained state, it shouldn't - // have been accessed longer ago than the last frame - //Assert(Interface->RetainedState[i].FramesSinceAccess <= 2); - Interface->RetainedState[i].FramesSinceAccess = 0; - Result = Interface->RetainedState + i; - break; - } + // NOTE(PS): If we are accessing a retained state, it shouldn't + // have been accessed longer ago than the last frame + //Assert(Interface->RetainedState[i].FramesSinceAccess <= 2); + Interface->RetainedState[i].FramesSinceAccess = 0; + Result = Interface->RetainedState + i; + break; } - return Result; + } + return Result; } internal ui_widget_retained_state* ui_CreateRetainedState(ui_interface* Interface, ui_widget* Widget) { - u64 Index = RETAINED_STATE_MAX; - if (Interface->RetainedStateCount >= RETAINED_STATE_MAX) + u64 Index = RETAINED_STATE_MAX; + if (Interface->RetainedStateCount >= RETAINED_STATE_MAX) + { + for (u32 i = 0; i < Interface->RetainedStateCount; i++) { - for (u32 i = 0; i < Interface->RetainedStateCount; i++) - { - if (Interface->RetainedState[i].FramesSinceAccess > 0) - { - Index = i; - break; - } - } - } else { - Index = Interface->RetainedStateCount++; + if (Interface->RetainedState[i].FramesSinceAccess > 0) + { + Index = i; + break; + } } - - Assert(Index < RETAINED_STATE_MAX); - ui_widget_retained_state* Result = Interface->RetainedState + Index; - Result->Id = Widget->Id; - if (Result->EditString.Size != 256) - { - Result->EditString = PushString(Interface->Permanent, 256); - } - return Result; + } else { + Index = Interface->RetainedStateCount++; + } + + Assert(Index < RETAINED_STATE_MAX); + ui_widget_retained_state* Result = Interface->RetainedState + Index; + Result->Id = Widget->Id; + if (Result->EditString.Size != 256) + { + Result->EditString = PushString(Interface->Permanent, 256); + } + return Result; } internal ui_widget_retained_state* ui_GetOrCreateRetainedState(ui_interface* Interface, ui_widget* Widget) { - ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); - if (!State) - { - State = ui_CreateRetainedState(Interface, Widget); - } - return State; + ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); + if (!State) + { + State = ui_CreateRetainedState(Interface, Widget); + } + return State; } internal ui_widget* ui_CreateWidget(ui_interface* Interface, gs_string String) { - InterfaceAssert(Interface->PerFrameMemory); - Assert(Interface->WidgetsCount < Interface->WidgetsCountMax); - u64 Index = Interface->WidgetsCount++; - ui_widget* Result = Interface->Widgets + Index; - ZeroStruct(Result); - - Result->Parent = Interface->ActiveLayout; - - u64 Id = HashDJB2ToU64(StringExpand(String)); - if (Result->Parent) - { - Id = HashAppendDJB2ToU32(Id, Result->Parent->Id.Id); - Id = HashAppendDJB2ToU32(Id, Result->Parent->ChildCount); - //Result->Id.ParentId = Result->Parent->Id.Id; - } - Result->Id.Id = Id; - - u64 ZIndex = Index + 1; - if (Result->Parent) - { - Result->ChildZIndexOffset += Result->Parent->ChildZIndexOffset; - ZIndex += Result->Parent->ChildZIndexOffset; - } - Result->Id.ZIndex = ZIndex; - - Result->String = PushStringCopy(Interface->PerFrameMemory, String.ConstString); - InterfaceAssert(Interface->PerFrameMemory); - Result->Alignment = Align_Left; - Result->Next = 0; - Result->ChildrenRoot = 0; - Result->ChildrenHead = 0; - Result->Flags = 0; - ui_WidgetSetFlag(Result, UIWidgetFlag_ExpandsToFitChildren); - - return Result; + InterfaceAssert(Interface->PerFrameMemory); + Assert(Interface->WidgetsCount < Interface->WidgetsCountMax); + u64 Index = Interface->WidgetsCount++; + ui_widget* Result = Interface->Widgets + Index; + ZeroStruct(Result); + + Result->Parent = Interface->ActiveLayout; + + u64 Id = HashDJB2ToU64(StringExpand(String)); + if (Result->Parent) + { + Id = HashAppendDJB2ToU32(Id, Result->Parent->Id.Id); + Id = HashAppendDJB2ToU32(Id, Result->Parent->ChildCount); + //Result->Id.ParentId = Result->Parent->Id.Id; + } + Result->Id.Id = Id; + + u64 ZIndex = Index + 1; + if (Result->Parent) + { + Result->ChildZIndexOffset += Result->Parent->ChildZIndexOffset; + ZIndex += Result->Parent->ChildZIndexOffset; + } + Result->Id.ZIndex = ZIndex; + + Result->String = PushStringCopy(Interface->PerFrameMemory, String.ConstString); + InterfaceAssert(Interface->PerFrameMemory); + Result->Alignment = Align_Left; + Result->Next = 0; + Result->ChildrenRoot = 0; + Result->ChildrenHead = 0; + Result->Flags = 0; + ui_WidgetSetFlag(Result, UIWidgetFlag_ExpandsToFitChildren); + + return Result; } // @@ -612,9 +612,9 @@ ui_CreateWidget(ui_interface* Interface, gs_string String) internal b32 ui_MouseClickedRect(ui_interface Interface, rect2 Rect) { - b32 Result = MouseButtonTransitionedDown(Interface.Mouse.LeftButtonState); - Result &= PointIsInRect(Rect, Interface.Mouse.Pos); - return Result; + b32 Result = MouseButtonTransitionedDown(Interface.Mouse.LeftButtonState); + Result &= PointIsInRect(Rect, Interface.Mouse.Pos); + return Result; } // Layout @@ -622,413 +622,413 @@ ui_MouseClickedRect(ui_interface Interface, rect2 Rect) static rect2 ui_ReserveBounds(ui_interface* Interface, ui_widget* Widget, bool Inset) { - Assert(Widget->ColumnsCount > 0); - rect2 Bounds = {0}; - u32 ColumnIndex = Widget->ChildCount % Widget->ColumnsCount; - - ui_column Column = Widget->Columns[ColumnIndex]; - Bounds.Min.x = Column.XMin; - Bounds.Min.y = Widget->RowYAt; - Bounds.Max.x = Column.XMax; - Bounds.Max.y = Bounds.Min.y + Widget->RowHeight; - - if (Inset) + Assert(Widget->ColumnsCount > 0); + rect2 Bounds = {0}; + u32 ColumnIndex = Widget->ChildCount % Widget->ColumnsCount; + + ui_column Column = Widget->Columns[ColumnIndex]; + Bounds.Min.x = Column.XMin; + Bounds.Min.y = Widget->RowYAt; + Bounds.Max.x = Column.XMax; + Bounds.Max.y = Bounds.Min.y + Widget->RowHeight; + + if (Inset) + { + Bounds.Min.x += Widget->Margin.x; + Bounds.Min.y += Widget->Margin.y; + Bounds.Max.x -= Widget->Margin.x; + Bounds.Max.y -= Widget->Margin.y; + } + + if (Widget->ChildCount == 0) + { + ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); + if (State) { - Bounds.Min.x += Widget->Margin.x; - Bounds.Min.y += Widget->Margin.y; - Bounds.Max.x -= Widget->Margin.x; - Bounds.Max.y -= Widget->Margin.y; + Bounds = Rect2Translate(Bounds, State->ChildrenDrawOffset); } - - if (Widget->ChildCount == 0) - { - ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); - if (State) - { - Bounds = Rect2Translate(Bounds, State->ChildrenDrawOffset); - } - } - - return Bounds; + } + + return Bounds; } internal void ui_CommitBounds(ui_widget* Parent, rect2 Bounds) { - u32 ColumnIndex = Parent->ChildCount % Parent->ColumnsCount; - if (ColumnIndex == 0) + u32 ColumnIndex = Parent->ChildCount % Parent->ColumnsCount; + if (ColumnIndex == 0) + { + switch (Parent->FillDirection) { - switch (Parent->FillDirection) + case LayoutDirection_BottomUp: + { + Parent->RowYAt = Bounds.Max.y; + if (ui_WidgetIsFlagSet(*Parent, UIWidgetFlag_ExpandsToFitChildren)) { - case LayoutDirection_BottomUp: - { - Parent->RowYAt = Bounds.Max.y; - if (ui_WidgetIsFlagSet(*Parent, UIWidgetFlag_ExpandsToFitChildren)) - { - Parent->Bounds.Max.y = Parent->RowYAt; - } - }break; - - case LayoutDirection_TopDown: - { - Parent->RowYAt = Bounds.Min.y - Parent->RowHeight; - if (ui_WidgetIsFlagSet(*Parent, UIWidgetFlag_ExpandsToFitChildren)) - { - Parent->Bounds.Min.y = Bounds.Min.y; - } - }break; + Parent->Bounds.Max.y = Parent->RowYAt; } + }break; + + case LayoutDirection_TopDown: + { + Parent->RowYAt = Bounds.Min.y - Parent->RowHeight; + if (ui_WidgetIsFlagSet(*Parent, UIWidgetFlag_ExpandsToFitChildren)) + { + Parent->Bounds.Min.y = Bounds.Min.y; + } + }break; } + } } internal void ui_ExpandParentToFit(ui_widget* Widget) { - ui_widget* Parent = Widget->Parent; - switch (Widget->FillDirection) + ui_widget* Parent = Widget->Parent; + switch (Widget->FillDirection) + { + case LayoutDirection_TopDown: { - case LayoutDirection_TopDown: - { - Parent->Bounds.Min.y = Min(Parent->Bounds.Min.y, Widget->Bounds.Min.y - Parent->Margin.y); - }break; - - case LayoutDirection_BottomUp: - { - Parent->Bounds.Max.y = Max(Parent->Bounds.Max.y, Widget->Bounds.Max.y + Parent->Margin.y); - }break; - - InvalidDefaultCase; - } + Parent->Bounds.Min.y = Min(Parent->Bounds.Min.y, Widget->Bounds.Min.y - Parent->Margin.y); + }break; + + case LayoutDirection_BottomUp: + { + Parent->Bounds.Max.y = Max(Parent->Bounds.Max.y, Widget->Bounds.Max.y + Parent->Margin.y); + }break; + + InvalidDefaultCase; + } } internal void ui_WidgetCreateColumns(ui_widget* Widget, u32 ColumnsCount, ui_interface* Interface) { - Widget->Columns = PushArray(Interface->PerFrameMemory, ui_column, ColumnsCount); - InterfaceAssert(Interface->PerFrameMemory); - Widget->ColumnsCount = ColumnsCount; - Widget->ColumnsFilled = 0; + Widget->Columns = PushArray(Interface->PerFrameMemory, ui_column, ColumnsCount); + InterfaceAssert(Interface->PerFrameMemory); + Widget->ColumnsCount = ColumnsCount; + Widget->ColumnsFilled = 0; } internal void ui_WidgetInitUniformColumns(ui_widget* Widget) { - r32 CurrentRowWidth = Rect2Width(Widget->Bounds); - r32 ColumnWidth = CurrentRowWidth / Widget->ColumnsCount; - for (u32 i = 0; i < Widget->ColumnsCount; i++) - { - ui_column* Column = Widget->Columns + i; - Column->XMin = Widget->Bounds.Min.x + (ColumnWidth * i); - Column->XMax = Column->XMin + ColumnWidth; - } + r32 CurrentRowWidth = Rect2Width(Widget->Bounds); + r32 ColumnWidth = CurrentRowWidth / Widget->ColumnsCount; + for (u32 i = 0; i < Widget->ColumnsCount; i++) + { + ui_column* Column = Widget->Columns + i; + Column->XMin = Widget->Bounds.Min.x + (ColumnWidth * i); + Column->XMax = Column->XMin + ColumnWidth; + } } internal ui_widget* ui_CreateLayoutWidget(ui_interface* Interface, rect2 Bounds, gs_string Name, ui_layout_direction FillDir = LayoutDirection_Inherit) { - ui_widget* Result = ui_CreateWidget(Interface, Name); - //ui_WidgetSetFlag(Result, UIWidgetFlag_DrawOutline); - - Result->Bounds = Bounds; - Result->Margin = Interface->Style.Margin; - Result->RowHeight = Interface->Style.RowHeight; - - // Single Column Layout - ui_WidgetCreateColumns(Result, 1, Interface); - ui_WidgetInitUniformColumns(Result); - - if (FillDir == LayoutDirection_Inherit && Result->Parent != 0) + ui_widget* Result = ui_CreateWidget(Interface, Name); + //ui_WidgetSetFlag(Result, UIWidgetFlag_DrawOutline); + + Result->Bounds = Bounds; + Result->Margin = Interface->Style.Margin; + Result->RowHeight = Interface->Style.RowHeight; + + // Single Column Layout + ui_WidgetCreateColumns(Result, 1, Interface); + ui_WidgetInitUniformColumns(Result); + + if (FillDir == LayoutDirection_Inherit && Result->Parent != 0) + { + Result->FillDirection = Result->Parent->FillDirection; + } + else + { + Result->FillDirection = FillDir; + } + + switch(Result->FillDirection) + { + case LayoutDirection_BottomUp: { - Result->FillDirection = Result->Parent->FillDirection; - } - else - { - Result->FillDirection = FillDir; - } + Result->RowYAt = Bounds.Min.y; + }break; - switch(Result->FillDirection) + case LayoutDirection_TopDown: { - case LayoutDirection_BottomUp: - { - Result->RowYAt = Bounds.Min.y; - }break; - - case LayoutDirection_TopDown: - { - Result->RowYAt = Bounds.Max.y - Result->RowHeight; - }break; - - InvalidDefaultCase; - } + Result->RowYAt = Bounds.Max.y - Result->RowHeight; + }break; - return Result; + InvalidDefaultCase; + } + + return Result; } static ui_widget* ui_PushOverlayLayout(ui_interface* Interface, rect2 Bounds, ui_layout_direction FillDir, gs_string Name) { - ui_widget* Result = ui_CreateLayoutWidget(Interface, Bounds, Name, FillDir); - SLLPushOrInit(Interface->DrawOrderRoot, Interface->DrawOrderHead, Result); - Interface->ActiveLayout = Result; - return Result; + ui_widget* Result = ui_CreateLayoutWidget(Interface, Bounds, Name, FillDir); + SLLPushOrInit(Interface->DrawOrderRoot, Interface->DrawOrderHead, Result); + Interface->ActiveLayout = Result; + return Result; } static gs_string ui_PushLayoutCategoryName(ui_interface* Interface, gs_string Category, u32 Value) { - gs_string Result = PushStringF(Interface->PerFrameMemory, - Category.Length + 25, - "%S%d", - Category.ConstString, - Value); - return Result; + gs_string Result = PushStringF(Interface->PerFrameMemory, + Category.Length + 25, + "%S%d", + Category.ConstString, + Value); + return Result; } static ui_widget* ui_PushLayout(ui_interface* Interface, rect2 Bounds, ui_layout_direction FillDir, gs_string Name) { - ui_widget* Result = ui_CreateLayoutWidget(Interface, Bounds, Name, FillDir); - - if (Interface->DrawOrderRoot) - { - SLLPushOrInit(Interface->ActiveLayout->ChildrenRoot, Interface->ActiveLayout->ChildrenHead, Result); - Interface->ActiveLayout->ChildCount++; - } - else - { - SLLPushOrInit(Interface->DrawOrderRoot, Interface->DrawOrderHead, Result); - } - - Interface->ActiveLayout = Result; - return Result; + ui_widget* Result = ui_CreateLayoutWidget(Interface, Bounds, Name, FillDir); + + if (Interface->DrawOrderRoot) + { + SLLPushOrInit(Interface->ActiveLayout->ChildrenRoot, Interface->ActiveLayout->ChildrenHead, Result); + Interface->ActiveLayout->ChildCount++; + } + else + { + SLLPushOrInit(Interface->DrawOrderRoot, Interface->DrawOrderHead, Result); + } + + Interface->ActiveLayout = Result; + return Result; } static ui_widget* ui_PushLayout(ui_interface* Interface, rect2 Bounds, ui_layout_direction FillDir, gs_string Category, u32 Value) { - gs_string Name = ui_PushLayoutCategoryName(Interface, Category, Value); - return ui_PushLayout(Interface, Bounds, FillDir, Name); + gs_string Name = ui_PushLayoutCategoryName(Interface, Category, Value); + return ui_PushLayout(Interface, Bounds, FillDir, Name); } static ui_widget* ui_PushLayout(ui_interface* Interface, gs_string Name, bool Inset = true) { - rect2 Bounds = {}; - ui_layout_direction Direction = LayoutDirection_TopDown; - if (Interface->ActiveLayout) + rect2 Bounds = {}; + ui_layout_direction Direction = LayoutDirection_TopDown; + if (Interface->ActiveLayout) + { + Bounds = ui_ReserveBounds(Interface, Interface->ActiveLayout, Inset); + Direction = Interface->ActiveLayout->FillDirection; + } + else + { + Bounds.Min.x = Interface->WindowBounds.Min.x; + Bounds.Min.y = Interface->WindowBounds.Max.y; + Bounds.Max.x = Interface->WindowBounds.Max.x; + Bounds.Max.y = Interface->WindowBounds.Max.y; + + if (Inset) { - Bounds = ui_ReserveBounds(Interface, Interface->ActiveLayout, Inset); - Direction = Interface->ActiveLayout->FillDirection; + Bounds.Min.x += Interface->Style.Margin.x; + Bounds.Max.x -= Interface->Style.Margin.x; } - else - { - Bounds.Min.x = Interface->WindowBounds.Min.x; - Bounds.Min.y = Interface->WindowBounds.Max.y; - Bounds.Max.x = Interface->WindowBounds.Max.x; - Bounds.Max.y = Interface->WindowBounds.Max.y; - - if (Inset) - { - Bounds.Min.x += Interface->Style.Margin.x; - Bounds.Max.x -= Interface->Style.Margin.x; - } - - Direction = LayoutDirection_TopDown; - } - return ui_PushLayout(Interface, Bounds, Direction, Name); + + Direction = LayoutDirection_TopDown; + } + return ui_PushLayout(Interface, Bounds, Direction, Name); } internal void ui_ExpandToFitChildren(ui_widget* Parent) { - if (!ui_WidgetIsFlagSet(*Parent, UIWidgetFlag_ExpandsToFitChildren)) { return; } - - v2 Extents = { Parent->Bounds.Max.y, Parent->Bounds.Min.y }; - for (ui_widget* Child = Parent->ChildrenRoot; Child != 0; Child = Child->Next) + if (!ui_WidgetIsFlagSet(*Parent, UIWidgetFlag_ExpandsToFitChildren)) { return; } + + v2 Extents = { Parent->Bounds.Max.y, Parent->Bounds.Min.y }; + for (ui_widget* Child = Parent->ChildrenRoot; Child != 0; Child = Child->Next) + { + Extents.x = Min(Extents.x, Child->Bounds.Min.y); + Extents.y = Max(Extents.y, Child->Bounds.Max.y); + } + + switch(Parent->FillDirection) + { + case LayoutDirection_BottomUp: { - Extents.x = Min(Extents.x, Child->Bounds.Min.y); - Extents.y = Max(Extents.y, Child->Bounds.Max.y); - } + Parent->Bounds.Max.y = Max(Extents.y + Parent->Margin.y, Parent->Bounds.Max.y); + }break; - switch(Parent->FillDirection) + case LayoutDirection_TopDown: { - case LayoutDirection_BottomUp: - { - Parent->Bounds.Max.y = Max(Extents.y + Parent->Margin.y, Parent->Bounds.Max.y); - }break; - - case LayoutDirection_TopDown: - { - Parent->Bounds.Min.y = Min(Extents.x - Parent->Margin.y, Parent->Bounds.Min.y); - }break; - - InvalidDefaultCase; - } + Parent->Bounds.Min.y = Min(Extents.x - Parent->Margin.y, Parent->Bounds.Min.y); + }break; + + InvalidDefaultCase; + } } static void ui_PopLayout(ui_interface* Interface, gs_string LayoutName) { - Assert(Interface->ActiveLayout != 0); - - ui_widget* Layout = Interface->ActiveLayout; - - // NOTE(pjs): If this isn't true then a layout was opened without being closed - // Go check for ui_PushLayout, ui_BeginDropdown, ui_BeginRow, etc that don't have - // a corresponding ui_Pop/ui_End* - // - // We use StringsEqualUpToLength here becuase its possible that - // the current layout used the Category + Identifier method - // for generating Layout->String. And if Identifier was a string - // that was edited within the scope of this layout, then - // Layout->String and LayoutName will no longer match. - // - // This is a compromise that will at least let us know if - // we aren't popping all our layouts correctly. - Assert(StringsEqualUpToLength(Layout->String, LayoutName, LayoutName.Length)); - - ui_ExpandToFitChildren(Layout); - - Interface->ActiveLayout = Interface->ActiveLayout->Parent; - - // NOTE(pjs): This indicates that the parent layout should - // expand to fit the layout that we just popped - if (Interface->ActiveLayout != 0 && - Interface->ActiveLayout->ChildrenHead == Layout) - { - ui_CommitBounds(Interface->ActiveLayout, Layout->Bounds); - } + Assert(Interface->ActiveLayout != 0); + + ui_widget* Layout = Interface->ActiveLayout; + + // NOTE(pjs): If this isn't true then a layout was opened without being closed + // Go check for ui_PushLayout, ui_BeginDropdown, ui_BeginRow, etc that don't have + // a corresponding ui_Pop/ui_End* + // + // We use StringsEqualUpToLength here becuase its possible that + // the current layout used the Category + Identifier method + // for generating Layout->String. And if Identifier was a string + // that was edited within the scope of this layout, then + // Layout->String and LayoutName will no longer match. + // + // This is a compromise that will at least let us know if + // we aren't popping all our layouts correctly. + Assert(StringsEqualUpToLength(Layout->String, LayoutName, LayoutName.Length)); + + ui_ExpandToFitChildren(Layout); + + Interface->ActiveLayout = Interface->ActiveLayout->Parent; + + // NOTE(pjs): This indicates that the parent layout should + // expand to fit the layout that we just popped + if (Interface->ActiveLayout != 0 && + Interface->ActiveLayout->ChildrenHead == Layout) + { + ui_CommitBounds(Interface->ActiveLayout, Layout->Bounds); + } } static void ui_PopLayout(ui_interface* Interface, gs_string Category, u32 Value) { - gs_string Name = ui_PushLayoutCategoryName(Interface, Category, Value); - ui_PopLayout(Interface, Name); + gs_string Name = ui_PushLayoutCategoryName(Interface, Category, Value); + ui_PopLayout(Interface, Name); } static ui_widget* ui_BeginRow(ui_interface* Interface, u32 ColumnsMax) { - ui_widget* Layout = ui_PushLayout(Interface, MakeString("Row"), false); - ui_WidgetCreateColumns(Layout, ColumnsMax, Interface); - ui_WidgetInitUniformColumns(Layout); - return Layout; + ui_widget* Layout = ui_PushLayout(Interface, MakeString("Row"), false); + ui_WidgetCreateColumns(Layout, ColumnsMax, Interface); + ui_WidgetInitUniformColumns(Layout); + return Layout; } enum ui_column_size_rule { - UIColumnSize_Fixed, - UIColumnSize_Percent, - UIColumnSize_Fill, - UIColumnSize_MaxWidth, + UIColumnSize_Fixed, + UIColumnSize_Percent, + UIColumnSize_Fill, + UIColumnSize_MaxWidth, }; struct ui_column_spec { - ui_column_size_rule Rule; - union - { - r32 Width; - r32 Percent; - }; + ui_column_size_rule Rule; + union + { + r32 Width; + r32 Percent; + }; }; static ui_widget* ui_BeginRow(ui_interface* Interface, u32 ColumnsMax, ui_column_spec* ColumnRules) { - ui_widget* Layout = ui_PushLayout(Interface, MakeString("Row"), false); - ui_WidgetCreateColumns(Layout, ColumnsMax, Interface); + ui_widget* Layout = ui_PushLayout(Interface, MakeString("Row"), false); + ui_WidgetCreateColumns(Layout, ColumnsMax, Interface); + + // First Pass, determine widths of each column, and how much space is left to be divided by the fill columns + // If a size is specified, it is stored in Column->XMax + r32 RowWidth = Rect2Width(Layout->Bounds); + r32 RemainingSpace = RowWidth; + u32 FillColumnsCount = 0; + for (u32 i = 0; i < Layout->ColumnsCount; i++) + { + ui_column_spec Spec = ColumnRules[i]; + ui_column* Column = Layout->Columns + i; - // First Pass, determine widths of each column, and how much space is left to be divided by the fill columns - // If a size is specified, it is stored in Column->XMax - r32 RowWidth = Rect2Width(Layout->Bounds); - r32 RemainingSpace = RowWidth; - u32 FillColumnsCount = 0; - for (u32 i = 0; i < Layout->ColumnsCount; i++) + switch (Spec.Rule) { - ui_column_spec Spec = ColumnRules[i]; - ui_column* Column = Layout->Columns + i; - - switch (Spec.Rule) + case UIColumnSize_Fixed: + { + Column->XMax = Spec.Width; + RemainingSpace -= Column->XMax; + }break; + + case UIColumnSize_Percent: + { + Column->XMax = Spec.Percent * RowWidth; + RemainingSpace -= Column->XMax; + }break; + + case UIColumnSize_Fill: + { + FillColumnsCount += 1; + }break; + + case UIColumnSize_MaxWidth: + { + if (RemainingSpace >= Spec.Width) { - case UIColumnSize_Fixed: - { - Column->XMax = Spec.Width; - RemainingSpace -= Column->XMax; - }break; - - case UIColumnSize_Percent: - { - Column->XMax = Spec.Percent * RowWidth; - RemainingSpace -= Column->XMax; - }break; - - case UIColumnSize_Fill: - { - FillColumnsCount += 1; - }break; - - case UIColumnSize_MaxWidth: - { - if (RemainingSpace >= Spec.Width) - { - Column->XMax = Spec.Width; - } - else - { - Column->XMax = RemainingSpace; - } - RemainingSpace -= Column->XMax; - }break; - - InvalidDefaultCase; + Column->XMax = Spec.Width; } + else + { + Column->XMax = RemainingSpace; + } + RemainingSpace -= Column->XMax; + }break; + + InvalidDefaultCase; + } + } + + r32 FillColumnWidth = RemainingSpace / FillColumnsCount; + + // Second Pass, specify the actual XMin and XMax of each column + r32 ColumnStartX = Layout->Bounds.Min.x; + for (u32 i = 0; i < Layout->ColumnsCount; i++) + { + ui_column_spec Spec = ColumnRules[i]; + ui_column* Column = Layout->Columns + i; + + r32 ColumnWidth = 0; + switch (Spec.Rule) + { + case UIColumnSize_Fixed: + case UIColumnSize_Percent: + case UIColumnSize_MaxWidth: + { + ColumnWidth = Column->XMax; + }break; + + case UIColumnSize_Fill: + { + ColumnWidth = FillColumnWidth; + }break; } - r32 FillColumnWidth = RemainingSpace / FillColumnsCount; - - // Second Pass, specify the actual XMin and XMax of each column - r32 ColumnStartX = Layout->Bounds.Min.x; - for (u32 i = 0; i < Layout->ColumnsCount; i++) - { - ui_column_spec Spec = ColumnRules[i]; - ui_column* Column = Layout->Columns + i; - - r32 ColumnWidth = 0; - switch (Spec.Rule) - { - case UIColumnSize_Fixed: - case UIColumnSize_Percent: - case UIColumnSize_MaxWidth: - { - ColumnWidth = Column->XMax; - }break; - - case UIColumnSize_Fill: - { - ColumnWidth = FillColumnWidth; - }break; - } - - Column->XMin = ColumnStartX ; - Column->XMax = Column->XMin + Max(0, ColumnWidth); - ColumnStartX = Column->XMax; - } - - return Layout; + Column->XMin = ColumnStartX ; + Column->XMax = Column->XMin + Max(0, ColumnWidth); + ColumnStartX = Column->XMax; + } + + return Layout; } static void ui_EndRow(ui_interface* Interface) { - ui_PopLayout(Interface, MakeString("Row")); + ui_PopLayout(Interface, MakeString("Row")); } static rect2 ui_LayoutRemaining(ui_widget Layout) { - rect2 Result = Layout.Bounds; - Result.Max.y = Layout.RowYAt; - return Result; + rect2 Result = Layout.Bounds; + Result.Max.y = Layout.RowYAt; + return Result; } // Widgets @@ -1036,89 +1036,89 @@ ui_LayoutRemaining(ui_widget Layout) internal ui_eval_result ui_EvaluateWidget(ui_interface* Interface, ui_widget* Widget, rect2 Bounds) { - ui_eval_result Result = {}; - - Widget->Bounds = Bounds; - SLLPushOrInit(Interface->ActiveLayout->ChildrenRoot, Interface->ActiveLayout->ChildrenHead, Widget); - Interface->ActiveLayout->ChildCount += 1; - ui_CommitBounds(Widget->Parent, Widget->Bounds); - - if (PointIsInRect(Widget->Parent->Bounds, Interface->Mouse.Pos) && - PointIsInRect(Widget->Bounds, Interface->Mouse.Pos)) + ui_eval_result Result = {}; + + Widget->Bounds = Bounds; + SLLPushOrInit(Interface->ActiveLayout->ChildrenRoot, Interface->ActiveLayout->ChildrenHead, Widget); + Interface->ActiveLayout->ChildCount += 1; + ui_CommitBounds(Widget->Parent, Widget->Bounds); + + if (PointIsInRect(Widget->Parent->Bounds, Interface->Mouse.Pos) && + PointIsInRect(Widget->Bounds, Interface->Mouse.Pos)) + { + if (MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState)) { - if (MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState)) - { - if (ui_WidgetIdsEqual(Interface->HotWidget, Widget->Id)) - { - Result.Clicked = true; - Interface->ActiveWidget = Widget->Id; - - if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Typable)) - { - Interface->CursorPosition = Widget->String.Length; - } - } - } + if (ui_WidgetIdsEqual(Interface->HotWidget, Widget->Id)) + { + Result.Clicked = true; + Interface->ActiveWidget = Widget->Id; - if (Interface->HotWidget.ZIndex == 0 || - Interface->HotWidget.ZIndex <= Widget->Id.ZIndex) + if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Typable)) { - Interface->HotWidget = Widget->Id; - Interface->HotWidgetFramesSinceUpdate = 0; - } - } - else - { - if (ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id) && - MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState)) - { - Interface->ActiveWidget = {}; + Interface->CursorPosition = Widget->String.Length; } + } } - if (ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id)) + if (Interface->HotWidget.ZIndex == 0 || + Interface->HotWidget.ZIndex <= Widget->Id.ZIndex) { - // click & drag - if (MouseButtonHeldDown(Interface->Mouse.LeftButtonState)) - { - Result.Held = true; - Result.DragDelta = Interface->Mouse.Pos - Interface->Mouse.DownPos; - } - - if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Typable) && - Interface->TempInputString.Length > 0) - { - ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); - - Interface->CursorPosition = Clamp(0, Interface->CursorPosition, State->EditString.Length); - for (u32 i = 0; i < Interface->TempInputString.Length; i++) - { - if (Interface->TempInputString.Str[i] == '\b') - { - if (Interface->CursorPosition > 0) - { - State->EditString.Length -= 1; - } - } - else - { - OutChar(&State->EditString, Interface->TempInputString.Str[i]); - Interface->CursorPosition += 1; - } - } - } + Interface->HotWidget = Widget->Id; + Interface->HotWidgetFramesSinceUpdate = 0; + } + } + else + { + if (ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id) && + MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState)) + { + Interface->ActiveWidget = {}; + } + } + + if (ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id)) + { + // click & drag + if (MouseButtonHeldDown(Interface->Mouse.LeftButtonState)) + { + Result.Held = true; + Result.DragDelta = Interface->Mouse.Pos - Interface->Mouse.DownPos; } - Assert(Widget->Parent != 0); - return Result; + if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Typable) && + Interface->TempInputString.Length > 0) + { + ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); + + Interface->CursorPosition = Clamp(0, Interface->CursorPosition, State->EditString.Length); + for (u32 i = 0; i < Interface->TempInputString.Length; i++) + { + if (Interface->TempInputString.Str[i] == '\b') + { + if (Interface->CursorPosition > 0) + { + State->EditString.Length -= 1; + } + } + else + { + OutChar(&State->EditString, Interface->TempInputString.Str[i]); + Interface->CursorPosition += 1; + } + } + } + } + + Assert(Widget->Parent != 0); + return Result; } internal ui_eval_result ui_EvaluateWidget(ui_interface* Interface, ui_widget* Widget) { - ui_widget* Layout = Interface->ActiveLayout; - rect2 Bounds = ui_ReserveBounds(Interface, Layout, true); - return ui_EvaluateWidget(Interface, Widget, Bounds); + ui_widget* Layout = Interface->ActiveLayout; + rect2 Bounds = ui_ReserveBounds(Interface, Layout, true); + return ui_EvaluateWidget(Interface, Widget, Bounds); } // @@ -1128,549 +1128,549 @@ ui_EvaluateWidget(ui_interface* Interface, ui_widget* Widget) static r32 ui_GetTextLineHeight(ui_interface Interface) { - r32 Result = Interface.Style.Font->PixelHeight + (2 * Interface.Style.Margin.y); - return Result; + r32 Result = Interface.Style.Font->PixelHeight + (2 * Interface.Style.Margin.y); + return Result; } static void ui_FillRect(ui_interface* Interface, rect2 Bounds, v4 Color) { - PushRenderQuad2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, Color); + PushRenderQuad2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, Color); } static void ui_OutlineRect(ui_interface* Interface, rect2 Bounds, r32 Thickness, v4 Color) { - PushRenderBoundingBox2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, Thickness, Color); + PushRenderBoundingBox2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, Thickness, Color); } internal void ui_Label(ui_interface* Interface, gs_string String, rect2 Bounds, gs_string_alignment Alignment = Align_Left) { - DEBUG_TRACK_FUNCTION; - ui_widget* Widget = ui_CreateWidget(Interface, String); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); - ui_EvaluateWidget(Interface, Widget, Bounds); + DEBUG_TRACK_FUNCTION; + ui_widget* Widget = ui_CreateWidget(Interface, String); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); + ui_EvaluateWidget(Interface, Widget, Bounds); } internal void ui_Label(ui_interface* Interface, gs_string String, gs_string_alignment Alignment = Align_Left) { - DEBUG_TRACK_FUNCTION; - ui_widget* Widget = ui_CreateWidget(Interface, String); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); - ui_EvaluateWidget(Interface, Widget); + DEBUG_TRACK_FUNCTION; + ui_widget* Widget = ui_CreateWidget(Interface, String); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); + ui_EvaluateWidget(Interface, Widget); } internal void ui_TextEntrySetFlags(ui_widget* Widget, gs_string EditString) { - Widget->String = EditString; - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Selectable); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Typable); + Widget->String = EditString; + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Selectable); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Typable); } internal bool ui_TextEntry(ui_interface* Interface, gs_string Identifier, gs_string* Value) { - ui_widget* Widget = ui_CreateWidget(Interface, Identifier); - ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); - if (!State) - { - State = ui_CreateRetainedState(Interface, Widget); - } - PrintF(&State->EditString, "%S", *Value); - - ui_TextEntrySetFlags(Widget, State->EditString); - - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); - bool StringEdited = !StringsEqual(*Value, State->EditString); - PrintF(Value, "%S", State->EditString); - - return StringEdited; + ui_widget* Widget = ui_CreateWidget(Interface, Identifier); + ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); + if (!State) + { + State = ui_CreateRetainedState(Interface, Widget); + } + PrintF(&State->EditString, "%S", *Value); + + ui_TextEntrySetFlags(Widget, State->EditString); + + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); + bool StringEdited = !StringsEqual(*Value, State->EditString); + PrintF(Value, "%S", State->EditString); + + return StringEdited; } internal u64 ui_TextEntryU64(ui_interface* Interface, gs_string String, u64 CurrentValue) { - ui_widget* Widget = ui_CreateWidget(Interface, String); - ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); - if (!State) - { - State = ui_CreateRetainedState(Interface, Widget); - PrintF(&State->EditString, "%u", CurrentValue); - } - ui_TextEntrySetFlags(Widget, State->EditString); - - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); - parse_uint_result ParseResult = ValidateAndParseUInt(State->EditString.ConstString); - u64 ValueResult = CurrentValue; - if (ParseResult.Success) - { - ValueResult = ParseResult.Value; - } - return ValueResult; + ui_widget* Widget = ui_CreateWidget(Interface, String); + ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); + if (!State) + { + State = ui_CreateRetainedState(Interface, Widget); + PrintF(&State->EditString, "%u", CurrentValue); + } + ui_TextEntrySetFlags(Widget, State->EditString); + + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); + parse_uint_result ParseResult = ValidateAndParseUInt(State->EditString.ConstString); + u64 ValueResult = CurrentValue; + if (ParseResult.Success) + { + ValueResult = ParseResult.Value; + } + return ValueResult; } internal r64 ui_TextEntryR64(ui_interface* Interface, gs_string String, r64 CurrentValue) { - ui_widget* Widget = ui_CreateWidget(Interface, String); - ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); - if (!State) - { - State = ui_CreateRetainedState(Interface, Widget); - PrintF(&State->EditString, "%f", CurrentValue); - } - ui_TextEntrySetFlags(Widget, State->EditString); - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); - parse_float_result ParseResult = ValidateAndParseFloat(State->EditString.ConstString); - r64 ValueResult = CurrentValue; - if (ParseResult.Success) - { - ValueResult = ParseResult.Value; - } - return ValueResult; + ui_widget* Widget = ui_CreateWidget(Interface, String); + ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); + if (!State) + { + State = ui_CreateRetainedState(Interface, Widget); + PrintF(&State->EditString, "%f", CurrentValue); + } + ui_TextEntrySetFlags(Widget, State->EditString); + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); + parse_float_result ParseResult = ValidateAndParseFloat(State->EditString.ConstString); + r64 ValueResult = CurrentValue; + if (ParseResult.Success) + { + ValueResult = ParseResult.Value; + } + return ValueResult; } internal ui_widget* ui_CreateButtonWidget(ui_interface* Interface, gs_string Text) { - ui_widget* Widget = ui_CreateWidget(Interface, Text); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); - return Widget; + ui_widget* Widget = ui_CreateWidget(Interface, Text); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); + return Widget; } internal b32 ui_Button(ui_interface* Interface, gs_string Text) { - ui_widget* Widget = ui_CreateButtonWidget(Interface, Text); - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); - return Result.Clicked; + ui_widget* Widget = ui_CreateButtonWidget(Interface, Text); + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); + return Result.Clicked; } internal b32 ui_Button(ui_interface* Interface, gs_string Text, rect2 Bounds) { - ui_widget* Widget = ui_CreateButtonWidget(Interface, Text); - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget, Bounds); - return Result.Clicked; + ui_widget* Widget = ui_CreateButtonWidget(Interface, Text); + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget, Bounds); + return Result.Clicked; } struct list_item_colors { - v4 Hover; - v4 Selected; - v4 BGColor; + v4 Hover; + v4 Selected; + v4 BGColor; }; inline v4 ui_GetListItemBGColor(interface_config Style, u32 ElementIndex) { - v4 Result = Style.ListBGColors[ElementIndex % LIST_BG_COLORS_COUNT]; - return Result; + v4 Result = Style.ListBGColors[ElementIndex % LIST_BG_COLORS_COUNT]; + return Result; } static list_item_colors ui_GetListItemColors(ui_interface* Interface, u32 ListItemIndex) { - list_item_colors Result = {}; - Result.Hover = Interface->Style.ListBGHover; - Result.Selected = Interface->Style.ListBGSelected; - Result.BGColor = ui_GetListItemBGColor(Interface->Style, ListItemIndex); - return Result; + list_item_colors Result = {}; + Result.Hover = Interface->Style.ListBGHover; + Result.Selected = Interface->Style.ListBGSelected; + Result.BGColor = ui_GetListItemBGColor(Interface->Style, ListItemIndex); + return Result; } static b32 ui_ListButton(ui_interface* Interface, gs_string Text, rect2 Bounds, u32 ListItemIndex) { - ui_widget* Widget = ui_CreateWidget(Interface, Text); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); - // TODO(pjs): Reimplement alternating color backgrounds - Widget->Bounds = Bounds; - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); - return Result.Clicked; + ui_widget* Widget = ui_CreateWidget(Interface, Text); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); + // TODO(pjs): Reimplement alternating color backgrounds + Widget->Bounds = Bounds; + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); + return Result.Clicked; } static b32 ui_LayoutListButton(ui_interface* Interface, gs_string Text, u32 ListItemIndex) { - // TODO(pjs): Reimplement alternating colors - return ui_Button(Interface, Text); + // TODO(pjs): Reimplement alternating colors + return ui_Button(Interface, Text); } internal bool ui_EvaluateDropdown(ui_interface* Interface, ui_widget* Widget, ui_eval_result EvalResult) { - ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); - if (!State) + ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id); + if (!State) + { + State = ui_CreateRetainedState(Interface, Widget); + } + + if (EvalResult.Clicked) + { + State->Value = !State->Value; + } + + if (State->Value) + { + ui_widget ParentLayout = *Interface->ActiveLayout; + + r32 SpaceAbove = Interface->WindowBounds.Max.y - Widget->Bounds.Max.y; + r32 SpaceBelow = Widget->Bounds.Min.y - Interface->WindowBounds.Min.y; + ui_layout_direction Direction = LayoutDirection_TopDown; + rect2 MenuBounds = {}; + + if (SpaceAbove > SpaceBelow) { - State = ui_CreateRetainedState(Interface, Widget); + r32 ParentLayoutMaxY = ParentLayout.Bounds.Max.y; + Direction = LayoutDirection_BottomUp; + MenuBounds = rect2{ + v2{ Widget->Bounds.Min.x - ParentLayout.Margin.x, Widget->Bounds.Max.y }, + v2{ Widget->Bounds.Max.x + ParentLayout.Margin.x, ParentLayoutMaxY } + }; + } + else + { + r32 ParentLayoutMinY = ParentLayout.Bounds.Min.y; + Direction = LayoutDirection_TopDown; + MenuBounds = rect2{ + v2{ Widget->Bounds.Min.x - ParentLayout.Margin.x, ParentLayoutMinY }, + v2{ Widget->Bounds.Max.x + ParentLayout.Margin.x, Widget->Bounds.Min.y } + }; } - if (EvalResult.Clicked) - { - State->Value = !State->Value; - } - - if (State->Value) - { - ui_widget ParentLayout = *Interface->ActiveLayout; - - r32 SpaceAbove = Interface->WindowBounds.Max.y - Widget->Bounds.Max.y; - r32 SpaceBelow = Widget->Bounds.Min.y - Interface->WindowBounds.Min.y; - ui_layout_direction Direction = LayoutDirection_TopDown; - rect2 MenuBounds = {}; - - if (SpaceAbove > SpaceBelow) - { - r32 ParentLayoutMaxY = ParentLayout.Bounds.Max.y; - Direction = LayoutDirection_BottomUp; - MenuBounds = rect2{ - v2{ Widget->Bounds.Min.x - ParentLayout.Margin.x, Widget->Bounds.Max.y }, - v2{ Widget->Bounds.Max.x + ParentLayout.Margin.x, ParentLayoutMaxY } - }; - } - else - { - r32 ParentLayoutMinY = ParentLayout.Bounds.Min.y; - Direction = LayoutDirection_TopDown; - MenuBounds = rect2{ - v2{ Widget->Bounds.Min.x - ParentLayout.Margin.x, ParentLayoutMinY }, - v2{ Widget->Bounds.Max.x + ParentLayout.Margin.x, Widget->Bounds.Min.y } - }; - } - - ui_widget* Layout = ui_PushOverlayLayout(Interface, MenuBounds, Direction, MakeString("DropdownLayout")); - Layout->Margin.y = 0; - Layout->WidgetReference = Widget->Id; - ui_WidgetClearFlag(Layout, UIWidgetFlag_DrawOutline); - ui_WidgetSetChildrenPopover(Layout); - } - - return State->Value; + ui_widget* Layout = ui_PushOverlayLayout(Interface, MenuBounds, Direction, MakeString("DropdownLayout")); + Layout->Margin.y = 0; + Layout->WidgetReference = Widget->Id; + ui_WidgetClearFlag(Layout, UIWidgetFlag_DrawOutline); + ui_WidgetSetChildrenPopover(Layout); + } + + return State->Value; } internal bool ui_BeginDropdown(ui_interface* Interface, gs_string Text, rect2 Bounds) { - ui_widget* Widget = ui_CreateWidget(Interface, Text); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); - - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget, Bounds); - return ui_EvaluateDropdown(Interface, Widget, Result); + ui_widget* Widget = ui_CreateWidget(Interface, Text); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); + + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget, Bounds); + return ui_EvaluateDropdown(Interface, Widget, Result); } internal bool ui_BeginDropdown(ui_interface* Interface, gs_string Text) { - ui_widget* Widget = ui_CreateWidget(Interface, Text); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); - return ui_EvaluateDropdown(Interface, Widget, Result); + ui_widget* Widget = ui_CreateWidget(Interface, Text); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); + return ui_EvaluateDropdown(Interface, Widget, Result); } internal void ui_EndDropdown(ui_interface* Interface) { - gs_string LayoutName = MakeString("DropdownLayout"); - ui_widget* Layout = Interface->ActiveLayout; - ui_widget_retained_state* State = ui_GetRetainedState(Interface, Layout->WidgetReference); - if (State) + gs_string LayoutName = MakeString("DropdownLayout"); + ui_widget* Layout = Interface->ActiveLayout; + ui_widget_retained_state* State = ui_GetRetainedState(Interface, Layout->WidgetReference); + if (State) + { + bool IsOpen = State->Value; + ui_widget* Widget = Interface->ActiveLayout; + bool IsStillHot = StringsEqualUpToLength(Widget->String, LayoutName, LayoutName.Length); + if (IsOpen && IsStillHot) { - bool IsOpen = State->Value; - ui_widget* Widget = Interface->ActiveLayout; - bool IsStillHot = StringsEqualUpToLength(Widget->String, LayoutName, LayoutName.Length); - if (IsOpen && IsStillHot) - { - ui_PopLayout(Interface, LayoutName); - } else if (IsOpen && !IsStillHot) - { - State->Value = false; - } + ui_PopLayout(Interface, LayoutName); + } else if (IsOpen && !IsStillHot) + { + State->Value = false; } + } } internal r32 ui_EvaluateRangeSlider(ui_interface* Interface, ui_widget* Widget, ui_eval_result EvalResult, r32 Value, r32 MinValue, r32 MaxValue) { - r32 NewValue = Value; - ui_widget_retained_state* State = ui_GetOrCreateRetainedState(Interface, Widget); - - if (EvalResult.Clicked) - { - State->InitialValueR32 = Value; - } - - if (EvalResult.Held) - { - r32 Percent = (Interface->Mouse.Pos.x - Widget->Bounds.Min.x) / Rect2Width(Widget->Bounds); - NewValue = LerpR32(Percent, MinValue, MaxValue); - } - - NewValue = Clamp(MinValue, NewValue, MaxValue); - Widget->FillPercent = RemapR32(NewValue, MinValue, MaxValue, 0, 1); - return NewValue; + r32 NewValue = Value; + ui_widget_retained_state* State = ui_GetOrCreateRetainedState(Interface, Widget); + + if (EvalResult.Clicked) + { + State->InitialValueR32 = Value; + } + + if (EvalResult.Held) + { + r32 Percent = (Interface->Mouse.Pos.x - Widget->Bounds.Min.x) / Rect2Width(Widget->Bounds); + NewValue = LerpR32(Percent, MinValue, MaxValue); + } + + NewValue = Clamp(MinValue, NewValue, MaxValue); + Widget->FillPercent = RemapR32(NewValue, MinValue, MaxValue, 0, 1); + return NewValue; } internal ui_widget* ui_CreateRangeSliderWidget(ui_interface* Interface, gs_string Text, r32 Value) { - ui_widget* Widget = ui_CreateWidget(Interface, Text); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawHorizontalFill); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); - Widget->String = PushStringF(Interface->PerFrameMemory, 128, "%f", Value); - InterfaceAssert(Interface->PerFrameMemory); - return Widget; + ui_widget* Widget = ui_CreateWidget(Interface, Text); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawHorizontalFill); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); + Widget->String = PushStringF(Interface->PerFrameMemory, 128, "%f", Value); + InterfaceAssert(Interface->PerFrameMemory); + return Widget; } internal r32 ui_RangeSlider(ui_interface* Interface, gs_string Text, r32 Value, r32 ValueMin, r32 ValueMax) { - ui_widget* Widget = ui_CreateRangeSliderWidget(Interface, Text, Value); - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); - return ui_EvaluateRangeSlider(Interface, Widget, Result, Value, ValueMin, ValueMax); - + ui_widget* Widget = ui_CreateRangeSliderWidget(Interface, Text, Value); + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget); + return ui_EvaluateRangeSlider(Interface, Widget, Result, Value, ValueMin, ValueMax); + } internal r32 ui_RangeSlider(ui_interface* Interface, gs_string Text, rect2 Bounds, r32 Value, r32 ValueMin, r32 ValueMax) { - ui_widget* Widget = ui_CreateRangeSliderWidget(Interface, Text, Value); - ui_eval_result Result = ui_EvaluateWidget(Interface, Widget, Bounds); - return ui_EvaluateRangeSlider(Interface, Widget, Result, Value, ValueMin, ValueMax); + ui_widget* Widget = ui_CreateRangeSliderWidget(Interface, Text, Value); + ui_eval_result Result = ui_EvaluateWidget(Interface, Widget, Bounds); + return ui_EvaluateRangeSlider(Interface, Widget, Result, Value, ValueMin, ValueMax); } internal bool ui_Toggle(ui_interface* Interface, gs_string Text, bool Value) { - ui_widget* Widget = ui_CreateWidget(Interface, Text); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawHorizontalFill); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); - ui_eval_result Eval = ui_EvaluateWidget(Interface, Widget); - - bool Result = Eval.Clicked ? !Value : Value; - Widget->FillPercent = Result ? 1.0f : 0.0f; - return Result; + ui_widget* Widget = ui_CreateWidget(Interface, Text); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawHorizontalFill); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); + ui_eval_result Eval = ui_EvaluateWidget(Interface, Widget); + + bool Result = Eval.Clicked ? !Value : Value; + Widget->FillPercent = Result ? 1.0f : 0.0f; + return Result; } internal bool ui_ToggleText(ui_interface* Interface, gs_string Text, bool Value) { - ui_widget* Widget = ui_CreateWidget(Interface, Text); - ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawHorizontalFill); - ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); - ui_eval_result Eval = ui_EvaluateWidget(Interface, Widget); - - bool Result = Eval.Clicked ? !Value : Value; - Widget->FillPercent = Result ? 1.0f : 0.0f; - return Result; + ui_widget* Widget = ui_CreateWidget(Interface, Text); + ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawHorizontalFill); + ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline); + ui_eval_result Eval = ui_EvaluateWidget(Interface, Widget); + + bool Result = Eval.Clicked ? !Value : Value; + Widget->FillPercent = Result ? 1.0f : 0.0f; + return Result; } internal void ui_BeginList(ui_interface* Interface, gs_string Text, u32 ViewportRows, u32 ElementCount) { - if (ElementCount < ViewportRows) + if (ElementCount < ViewportRows) + { + ViewportRows = ElementCount; + } + + ui_column_spec ColumnRules[] = { + { UIColumnSize_Fixed, 32 }, + { UIColumnSize_Fill, 0 }, + }; + ui_widget* Layout = ui_BeginRow(Interface, 2, ColumnRules); + ui_WidgetClearFlag(Layout, UIWidgetFlag_ExpandsToFitChildren); + + ui_widget_retained_state* State = ui_GetRetainedState(Interface, Layout->Id); + if (!State) + { + State = ui_CreateRetainedState(Interface, Layout); + State->InitialValueR32 = 1.0f; + } + + r32 LayoutHeight = Layout->RowHeight * ViewportRows; + switch (Layout->Parent->FillDirection) + { + case LayoutDirection_TopDown: { - ViewportRows = ElementCount; - } + Layout->Bounds.Min.y = Layout->Bounds.Max.y - LayoutHeight; + }break; - ui_column_spec ColumnRules[] = { - { UIColumnSize_Fixed, 32 }, - { UIColumnSize_Fill, 0 }, - }; - ui_widget* Layout = ui_BeginRow(Interface, 2, ColumnRules); - ui_WidgetClearFlag(Layout, UIWidgetFlag_ExpandsToFitChildren); - - ui_widget_retained_state* State = ui_GetRetainedState(Interface, Layout->Id); - if (!State) + case LayoutDirection_BottomUp: { - State = ui_CreateRetainedState(Interface, Layout); - State->InitialValueR32 = 1.0f; - } + Layout->Bounds.Max.y = Layout->Bounds.Min.y + LayoutHeight; + }break; - r32 LayoutHeight = Layout->RowHeight * ViewportRows; - switch (Layout->Parent->FillDirection) - { - case LayoutDirection_TopDown: - { - Layout->Bounds.Min.y = Layout->Bounds.Max.y - LayoutHeight; - }break; - - case LayoutDirection_BottomUp: - { - Layout->Bounds.Max.y = Layout->Bounds.Min.y + LayoutHeight; - }break; - - InvalidDefaultCase; - } - - // Create the scroll bar - // - // TODO(pjs): Maybe make this a vertical slider widget? - - ui_widget* SliderRegion = ui_CreateWidget(Interface, MakeString("Slider")); - ui_WidgetSetFlag(SliderRegion, UIWidgetFlag_DrawOutline); - ui_WidgetSetFlag(SliderRegion, UIWidgetFlag_DrawVerticalFill); - ui_WidgetSetFlag(SliderRegion, UIWidgetFlag_DrawFillAsHandle); - - ui_WidgetSetFlag(SliderRegion, UIWidgetFlag_Clickable); - - rect2 SliderBounds = ui_ReserveBounds(Interface, Layout, true); - SliderBounds.Min.y = Layout->Bounds.Min.y + Layout->Margin.y; - SliderBounds.Max.y = Layout->Bounds.Max.y - Layout->Margin.y; - - ui_eval_result SliderEval = ui_EvaluateWidget(Interface, SliderRegion, SliderBounds); - if (SliderEval.Clicked || SliderEval.Held) - { - r32 Percent = (Interface->Mouse.Pos.y - SliderRegion->Bounds.Min.y) / Rect2Height(SliderRegion->Bounds); - State->InitialValueR32 = Clamp01(Percent); - } - SliderRegion->FillPercent = State->InitialValueR32; - - // Create the viewport that offsets list contents (and at render time determines what is visible) - // - ui_widget* ViewportLayout = ui_PushLayout(Interface, MakeString("Contents")); - ui_WidgetSetFlag(ViewportLayout, UIWidgetFlag_DrawOutline); - ui_WidgetClearFlag(ViewportLayout, UIWidgetFlag_ExpandsToFitChildren); - ViewportLayout->FillDirection = LayoutDirection_TopDown; - - ViewportLayout->Bounds.Min.y = SliderBounds.Min.y; - ViewportLayout->Bounds.Max.y = SliderBounds.Max.y; - - s32 ScrollableElements = Max(0, ElementCount - ViewportRows); - ui_widget_retained_state* ViewportState = ui_GetOrCreateRetainedState(Interface, ViewportLayout); - ViewportState->ChildrenDrawOffset.x = 0; - r32 BaseOffset = 0; - r32 ScrollPct = 1.0 - State->InitialValueR32; - r32 RowsOffset = ScrollPct * ScrollableElements; - r32 ScrollOffset = (ViewportLayout->RowHeight - (Interface->Style.Margin.y)) * RowsOffset; - ViewportState->ChildrenDrawOffset.y = BaseOffset + ScrollOffset; + InvalidDefaultCase; + } + + // Create the scroll bar + // + // TODO(pjs): Maybe make this a vertical slider widget? + + ui_widget* SliderRegion = ui_CreateWidget(Interface, MakeString("Slider")); + ui_WidgetSetFlag(SliderRegion, UIWidgetFlag_DrawOutline); + ui_WidgetSetFlag(SliderRegion, UIWidgetFlag_DrawVerticalFill); + ui_WidgetSetFlag(SliderRegion, UIWidgetFlag_DrawFillAsHandle); + + ui_WidgetSetFlag(SliderRegion, UIWidgetFlag_Clickable); + + rect2 SliderBounds = ui_ReserveBounds(Interface, Layout, true); + SliderBounds.Min.y = Layout->Bounds.Min.y + Layout->Margin.y; + SliderBounds.Max.y = Layout->Bounds.Max.y - Layout->Margin.y; + + ui_eval_result SliderEval = ui_EvaluateWidget(Interface, SliderRegion, SliderBounds); + if (SliderEval.Clicked || SliderEval.Held) + { + r32 Percent = (Interface->Mouse.Pos.y - SliderRegion->Bounds.Min.y) / Rect2Height(SliderRegion->Bounds); + State->InitialValueR32 = Clamp01(Percent); + } + SliderRegion->FillPercent = State->InitialValueR32; + + // Create the viewport that offsets list contents (and at render time determines what is visible) + // + ui_widget* ViewportLayout = ui_PushLayout(Interface, MakeString("Contents")); + ui_WidgetSetFlag(ViewportLayout, UIWidgetFlag_DrawOutline); + ui_WidgetClearFlag(ViewportLayout, UIWidgetFlag_ExpandsToFitChildren); + ViewportLayout->FillDirection = LayoutDirection_TopDown; + + ViewportLayout->Bounds.Min.y = SliderBounds.Min.y; + ViewportLayout->Bounds.Max.y = SliderBounds.Max.y; + + s32 ScrollableElements = Max(0, ElementCount - ViewportRows); + ui_widget_retained_state* ViewportState = ui_GetOrCreateRetainedState(Interface, ViewportLayout); + ViewportState->ChildrenDrawOffset.x = 0; + r32 BaseOffset = 0; + r32 ScrollPct = 1.0 - State->InitialValueR32; + r32 RowsOffset = ScrollPct * ScrollableElements; + r32 ScrollOffset = (ViewportLayout->RowHeight - (Interface->Style.Margin.y)) * RowsOffset; + ViewportState->ChildrenDrawOffset.y = BaseOffset + ScrollOffset; } internal void ui_EndList(ui_interface* Interface) { - // Pop the Viewport Layout - ui_PopLayout(Interface, MakeString("Contents")); - // Pop the actual list layout - ui_EndRow(Interface); + // Pop the Viewport Layout + ui_PopLayout(Interface, MakeString("Contents")); + // Pop the actual list layout + ui_EndRow(Interface); } internal void ui_BeginMousePopup(ui_interface* Interface, rect2 Bounds, ui_layout_direction FillDir, gs_string Text) { - rect2 FollowMouseBounds = Rect2Translate(Bounds, Interface->Mouse.Pos); - ui_widget* Layout = ui_PushOverlayLayout(Interface, FollowMouseBounds, FillDir, MakeString("MousePopup")); - ui_WidgetSetFlag(Layout, UIWidgetFlag_DrawBackground); + rect2 FollowMouseBounds = Rect2Translate(Bounds, Interface->Mouse.Pos); + ui_widget* Layout = ui_PushOverlayLayout(Interface, FollowMouseBounds, FillDir, MakeString("MousePopup")); + ui_WidgetSetFlag(Layout, UIWidgetFlag_DrawBackground); } internal void ui_EndMousePopup(ui_interface* Interface) { - ui_PopLayout(Interface, MakeString("MousePopup")); + ui_PopLayout(Interface, MakeString("MousePopup")); } // internal void ui_BeginLabelRow(ui_interface* Interface, gs_string Label, u32 Count = 2) { - ui_BeginRow(Interface, Count); - ui_Label(Interface, Label); + ui_BeginRow(Interface, Count); + ui_Label(Interface, Label); } internal bool ui_LabeledToggle(ui_interface* Interface, gs_string Label, bool Value) { - ui_BeginLabelRow(Interface, Label); - bool Result = ui_Toggle(Interface, Label, Value); - ui_EndRow(Interface); - return Result; + ui_BeginLabelRow(Interface, Label); + bool Result = ui_Toggle(Interface, Label, Value); + ui_EndRow(Interface); + return Result; } internal r32 ui_LabeledRangeSlider(ui_interface* Interface, gs_string Label, r32 Value, r32 ValueMin, r32 ValueMax) { - ui_BeginLabelRow(Interface, Label); - r32 Result = ui_RangeSlider(Interface, Label, Value, ValueMin, ValueMax); - ui_EndRow(Interface); - return Result; + ui_BeginLabelRow(Interface, Label); + r32 Result = ui_RangeSlider(Interface, Label, Value, ValueMin, ValueMax); + ui_EndRow(Interface); + return Result; } internal void ui_LabeledTextEntry(ui_interface* Interface, gs_string Label, gs_string* Value) { - ui_BeginLabelRow(Interface, Label); - ui_TextEntry(Interface, Label, Value); - ui_EndRow(Interface); + ui_BeginLabelRow(Interface, Label); + ui_TextEntry(Interface, Label, Value); + ui_EndRow(Interface); } internal u64 ui_LabeledTextEntryU64(ui_interface* Interface, gs_string Label, u32 Value) { - ui_BeginLabelRow(Interface, Label); - u64 Result = ui_TextEntryU64(Interface, Label, Value); - ui_EndRow(Interface); - return Result; + ui_BeginLabelRow(Interface, Label); + u64 Result = ui_TextEntryU64(Interface, Label, Value); + ui_EndRow(Interface); + return Result; } internal bool ui_BeginLabeledDropdown(ui_interface* Interface, gs_string Label, gs_string DropdownValue) { - ui_BeginLabelRow(Interface, Label); - return ui_BeginDropdown(Interface, DropdownValue); + ui_BeginLabelRow(Interface, Label); + return ui_BeginDropdown(Interface, DropdownValue); } internal void ui_EndLabeledDropdown(ui_interface* Interface) { - ui_EndDropdown(Interface); - ui_EndRow(Interface); + ui_EndDropdown(Interface); + ui_EndRow(Interface); } internal ui_interface ui_InterfaceCreate(context Context, interface_config Style, gs_memory_arena* Permanent) { - ui_interface Result = {0}; - Result.Style = Style; - - gs_file FontFile = ReadEntireFile(Context.ThreadContext.FileHandler, ConstString("data/Anonymous Pro.ttf")); - Result.Style.Font = PushStruct(Permanent, bitmap_font); - *Result.Style.Font = TextFont_Create(FontFile, 512, Style.FontSize, Context, Permanent); - - Result.Style.RowHeight = ui_GetTextLineHeight(Result) + (2 * Result.Style.Margin.y); - - Result.WidgetsCountMax = 4096; - Result.Widgets = PushArray(Permanent, ui_widget, Result.WidgetsCountMax); - Result.PerFrameMemory = PushStruct(Permanent, gs_memory_arena); - *Result.PerFrameMemory = CreateMemoryArena(Context.ThreadContext.Allocator, "Interface Per Frame Memory Arena", KB(32)); - InterfaceAssert(Result.PerFrameMemory); - - Result.Permanent = Permanent; - - return Result; + ui_interface Result = {0}; + Result.Style = Style; + + gs_file FontFile = ReadEntireFile(Context.ThreadContext.FileHandler, ConstString("data/Anonymous Pro.ttf")); + Result.Style.Font = PushStruct(Permanent, bitmap_font); + *Result.Style.Font = TextFont_Create(FontFile, 512, Style.FontSize, Context, Permanent); + + Result.Style.RowHeight = ui_GetTextLineHeight(Result) + (2 * Result.Style.Margin.y); + + Result.WidgetsCountMax = 4096; + Result.Widgets = PushArray(Permanent, ui_widget, Result.WidgetsCountMax); + Result.PerFrameMemory = PushStruct(Permanent, gs_memory_arena); + *Result.PerFrameMemory = MemoryArenaCreate(KB(32), Bytes(8), Context.ThreadContext.Allocator, 0, 0, "Interface Per Frame Memory Arena"); + InterfaceAssert(Result.PerFrameMemory); + + Result.Permanent = Permanent; + + return Result; } #define INTERFACE_H diff --git a/src/app/editor/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h index 050bd0a..64b03d5 100644 --- a/src/app/editor/panels/foldhaus_panel_file_view.h +++ b/src/app/editor/panels/foldhaus_panel_file_view.h @@ -7,42 +7,42 @@ enum file_view_mode { - FileViewMode_Load, - FileViewMode_Save, + FileViewMode_Load, + FileViewMode_Save, }; struct file_view_state { - file_view_mode Mode; - - gs_string WorkingDirectory; - gs_string DisplayDirectory; - - gs_memory_arena FileNamesArena; - gs_file_info_array FileNames; - - gs_file_info SelectedFile; + file_view_mode Mode; + + gs_string WorkingDirectory; + gs_string DisplayDirectory; + + gs_memory_arena FileNamesArena; + gs_file_info_array FileNames; + + gs_file_info SelectedFile; }; internal void FileView_SetMode(panel* Panel, file_view_mode Mode) { - file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state); - FileViewState->Mode = Mode; + file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state); + FileViewState->Mode = Mode; } internal void FileView_Exit_(panel* FileViewPanel, app_state* State, context Context) { - // TODO(pjs): Free State->FileNamesArena - - Assert(FileViewPanel->IsModalOverrideFor != 0); - panel* ReturnTo = FileViewPanel->IsModalOverrideFor; - if (ReturnTo->ModalOverrideCB) - { - ReturnTo->ModalOverrideCB(FileViewPanel, State, Context); - } - Panel_PopModalOverride(ReturnTo, &State->PanelSystem); + // TODO(pjs): Free State->FileNamesArena + + Assert(FileViewPanel->IsModalOverrideFor != 0); + panel* ReturnTo = FileViewPanel->IsModalOverrideFor; + if (ReturnTo->ModalOverrideCB) + { + ReturnTo->ModalOverrideCB(FileViewPanel, State, Context); + } + Panel_PopModalOverride(ReturnTo, &State->PanelSystem); } global input_command* FileView_Commands = 0; @@ -51,35 +51,35 @@ s32 FileView_CommandsCount = 0; internal void FileView_UpdateWorkingDirectory(gs_const_string WorkingDirectory, file_view_state* State, context Context) { - // NOTE(pjs): make sure we're only passing valid directory paths to the - // function - char LastChar = WorkingDirectory.Str[WorkingDirectory.Length - 1]; - Assert(LastChar == '\\' || LastChar == '/'); - ClearArena(&State->FileNamesArena); + // NOTE(pjs): make sure we're only passing valid directory paths to the + // function + char LastChar = WorkingDirectory.Str[WorkingDirectory.Length - 1]; + Assert(LastChar == '\\' || LastChar == '/'); + MemoryArenaClear(&State->FileNamesArena); + + + gs_string SanitizedDir = PushString(Context.ThreadContext.Transient, WorkingDirectory.Length + 2); + SanitizePath(WorkingDirectory, &SanitizedDir, Context.ThreadContext.Transient); + if (SanitizedDir.Str[SanitizedDir.Length - 1] != '\\') + { + AppendPrintF(&SanitizedDir, "\\"); + } + + gs_const_string SanitizedDisplayDir = SanitizedDir.ConstString; + + gs_file_info NewWorkingDir = GetFileInfo(Context.ThreadContext.FileHandler, SanitizedDir.ConstString); + if (NewWorkingDir.IsDirectory) + { + AppendPrintF(&SanitizedDir, "*"); + NullTerminate(&SanitizedDir); + State->FileNames = EnumerateDirectory(Context.ThreadContext.FileHandler, &State->FileNamesArena, SanitizedDir.ConstString, EnumerateDirectory_IncludeDirectories); - gs_string SanitizedDir = PushString(Context.ThreadContext.Transient, WorkingDirectory.Length + 2); - SanitizePath(WorkingDirectory, &SanitizedDir, Context.ThreadContext.Transient); - if (SanitizedDir.Str[SanitizedDir.Length - 1] != '\\') - { - AppendPrintF(&SanitizedDir, "\\"); - } - - gs_const_string SanitizedDisplayDir = SanitizedDir.ConstString; - - gs_file_info NewWorkingDir = GetFileInfo(Context.ThreadContext.FileHandler, SanitizedDir.ConstString); - if (NewWorkingDir.IsDirectory) - { - AppendPrintF(&SanitizedDir, "*"); - NullTerminate(&SanitizedDir); - - State->FileNames = EnumerateDirectory(Context.ThreadContext.FileHandler, &State->FileNamesArena, SanitizedDir.ConstString, EnumerateDirectory_IncludeDirectories); - - // NOTE(pjs): we might be printing from State->WorkingDirectory to State->WorkingDirectory - // in some cases. Shouldn't be a problem but it is unnecessary - PrintF(&State->WorkingDirectory, "%S", SanitizedDir.ConstString); - PrintF(&State->DisplayDirectory, "%S", SanitizedDisplayDir); - } + // NOTE(pjs): we might be printing from State->WorkingDirectory to State->WorkingDirectory + // in some cases. Shouldn't be a problem but it is unnecessary + PrintF(&State->WorkingDirectory, "%S", SanitizedDir.ConstString); + PrintF(&State->DisplayDirectory, "%S", SanitizedDisplayDir); + } } GSMetaTag(panel_init); @@ -87,16 +87,16 @@ GSMetaTag(panel_type_file_view); internal void FileView_Init(panel* Panel, app_state* State, context Context) { - // TODO: :FreePanelMemory - file_view_state* FileViewState = PushStruct(&State->Permanent, file_view_state); - Panel->StateMemory = StructToData(FileViewState, file_view_state); - FileViewState->FileNamesArena = CreateMemoryArena(Context.ThreadContext.Allocator, "File View - File Names Arena"); - - // TODO(pjs): this shouldn't be stored in permanent - FileViewState->DisplayDirectory = PushString(&State->Permanent, 1024); - FileViewState->WorkingDirectory = PushString(&State->Permanent, 1024); - - FileView_UpdateWorkingDirectory(ConstString(".\\"), FileViewState, Context); + // TODO: :FreePanelMemory + file_view_state* FileViewState = PushStruct(&State->Permanent, file_view_state); + Panel->StateMemory = StructToData(FileViewState, file_view_state); + FileViewState->FileNamesArena = MemoryArenaCreate(MB(4), Bytes(8), Context.ThreadContext.Allocator, 0, 0, "File View - File Names Arena"); + + // TODO(pjs): this shouldn't be stored in permanent + FileViewState->DisplayDirectory = PushString(&State->Permanent, 1024); + FileViewState->WorkingDirectory = PushString(&State->Permanent, 1024); + + FileView_UpdateWorkingDirectory(ConstString(".\\"), FileViewState, Context); } GSMetaTag(panel_cleanup); @@ -104,7 +104,7 @@ GSMetaTag(panel_type_file_view); internal void FileView_Cleanup(panel* Panel, app_state* State) { - + } GSMetaTag(panel_render); @@ -112,87 +112,87 @@ GSMetaTag(panel_type_file_view); internal void FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state); - - ui_PushLayout(&State->Interface, PanelBounds, LayoutDirection_TopDown, MakeString("FileView Layout")); + file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state); + + ui_PushLayout(&State->Interface, PanelBounds, LayoutDirection_TopDown, MakeString("FileView Layout")); + { + ui_BeginRow(&State->Interface, 3); { - ui_BeginRow(&State->Interface, 3); + if (FileViewState->Mode == FileViewMode_Save) + { + if (ui_Button(&State->Interface, MakeString("Save"))) { - if (FileViewState->Mode == FileViewMode_Save) - { - if (ui_Button(&State->Interface, MakeString("Save"))) - { - if (!FileViewState->SelectedFile.Path.Str) - { - FileViewState->SelectedFile.Path = FileViewState->DisplayDirectory.ConstString; - } - - FileView_Exit_(Panel, State, Context); - } - } - - if (ui_Button(&State->Interface, MakeString("Exit"))) - { - FileView_Exit_(Panel, State, Context); - } + if (!FileViewState->SelectedFile.Path.Str) + { + FileViewState->SelectedFile.Path = FileViewState->DisplayDirectory.ConstString; + } + + FileView_Exit_(Panel, State, Context); } - ui_EndRow(&State->Interface); - - // Header - if (ui_TextEntry(&State->Interface, MakeString("pwd"), &FileViewState->DisplayDirectory)) - { - // if last character is a slash, update pwd, and clear the filter string - // otherwise update the filter string - gs_string Pwd = FileViewState->DisplayDirectory; - char LastChar = Pwd.Str[Pwd.Length - 1]; - if (LastChar == '\\' || LastChar == '/') - { - FileView_UpdateWorkingDirectory(Pwd.ConstString, FileViewState, Context); - } - else - { - - } - } - - // File Display - ui_BeginList(&State->Interface, MakeString("Files"), 10, FileViewState->FileNames.Count); - for (u32 i = 0; i < FileViewState->FileNames.Count; i++) - { - gs_file_info File = FileViewState->FileNames.Values[i]; - - u32 LastSlashIndex = FindLast(File.Path, File.Path.Length - 2, '\\'); - gs_const_string FileName = Substring(File.Path, LastSlashIndex + 1, File.Path.Length); - gs_string PathString = PushString(State->Transient, FileName.Length); - PrintF(&PathString, "%S", FileName); - - if (ui_LayoutListButton(&State->Interface, PathString, i)) - { - if (File.IsDirectory) - { - FileView_UpdateWorkingDirectory(File.Path, FileViewState, Context); - } - else - { - FileViewState->SelectedFile = File; - switch (FileViewState->Mode) - { - case FileViewMode_Load: - { - FileView_Exit_(Panel, State, Context); - } break; - - case FileViewMode_Save: - { - - } break; - } - } - } - } - ui_EndList(&State->Interface); + } + + if (ui_Button(&State->Interface, MakeString("Exit"))) + { + FileView_Exit_(Panel, State, Context); + } } - ui_PopLayout(&State->Interface, MakeString("FileView Layout")); + ui_EndRow(&State->Interface); + + // Header + if (ui_TextEntry(&State->Interface, MakeString("pwd"), &FileViewState->DisplayDirectory)) + { + // if last character is a slash, update pwd, and clear the filter string + // otherwise update the filter string + gs_string Pwd = FileViewState->DisplayDirectory; + char LastChar = Pwd.Str[Pwd.Length - 1]; + if (LastChar == '\\' || LastChar == '/') + { + FileView_UpdateWorkingDirectory(Pwd.ConstString, FileViewState, Context); + } + else + { + + } + } + + // File Display + ui_BeginList(&State->Interface, MakeString("Files"), 10, FileViewState->FileNames.Count); + for (u32 i = 0; i < FileViewState->FileNames.Count; i++) + { + gs_file_info File = FileViewState->FileNames.Values[i]; + + u32 LastSlashIndex = FindLast(File.Path, File.Path.Length - 2, '\\'); + gs_const_string FileName = Substring(File.Path, LastSlashIndex + 1, File.Path.Length); + gs_string PathString = PushString(State->Transient, FileName.Length); + PrintF(&PathString, "%S", FileName); + + if (ui_LayoutListButton(&State->Interface, PathString, i)) + { + if (File.IsDirectory) + { + FileView_UpdateWorkingDirectory(File.Path, FileViewState, Context); + } + else + { + FileViewState->SelectedFile = File; + switch (FileViewState->Mode) + { + case FileViewMode_Load: + { + FileView_Exit_(Panel, State, Context); + } break; + + case FileViewMode_Save: + { + + } break; + } + } + } + } + ui_EndList(&State->Interface); + } + ui_PopLayout(&State->Interface, MakeString("FileView Layout")); } diff --git a/src/app/editor/panels/foldhaus_panel_profiler.h b/src/app/editor/panels/foldhaus_panel_profiler.h index b8684ee..c0ecd79 100644 --- a/src/app/editor/panels/foldhaus_panel_profiler.h +++ b/src/app/editor/panels/foldhaus_panel_profiler.h @@ -13,7 +13,7 @@ GSMetaTag(panel_type_profiler); internal void ProfilerView_Init(panel* Panel, app_state* State, context Context) { - + } GSMetaTag(panel_cleanup); @@ -21,213 +21,217 @@ GSMetaTag(panel_type_profiler); internal void ProfilerView_Cleanup(panel* Panel, app_state* State) { - + } internal void RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_widget* Layout, debug_frame* VisibleFrame, gs_memory_arena* Transient) { - rect2 Bounds = ui_LayoutRemaining(*Layout); - r32 Width = Rect2Width(Bounds); - r32 DepthHeight = 32; + rect2 Bounds = ui_LayoutRemaining(*Layout); + r32 Width = Rect2Width(Bounds); + r32 DepthHeight = 32; + + s64 FrameStartCycles = VisibleFrame->FrameStartCycles; + r32 FrameTotalCycles = (r32)(VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles); + + r32 NextThreadTop = Bounds.Max.y; + + for (s32 t = 0; t < VisibleFrame->ThreadCount; t++) + { + debug_scope_record_list ThreadCalls = VisibleFrame->ThreadCalls[t]; - s64 FrameStartCycles = VisibleFrame->FrameStartCycles; - r32 FrameTotalCycles = (r32)(VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles); + gs_string String = PushString(Transient, 256); - r32 NextThreadTop = Bounds.Max.y; + r32 ThreadScopeMin = Bounds.Max.y; - for (s32 t = 0; t < VisibleFrame->ThreadCount; t++) + //PrintF(&String, "Thread %d", ThreadCalls.ThreadId); + //ui_Label(Interface, String, rect2{ThreadScopeMin); + + r32 Hue = (r32)(t) / (r32)(VisibleFrame->ThreadCount); + Hue += (.5f * (t % 2)); + v4 ThreadHSV = v4{ 360.0f * Hue, .5f, 1.0f, 1.0f }; + v4 ThreadRGB = HSVToRGB(ThreadHSV); + + for (s32 i = 0; i < ThreadCalls.Count; i++) { - debug_scope_record_list ThreadCalls = VisibleFrame->ThreadCalls[t]; - - gs_string String = PushString(Transient, 256); - - r32 ThreadScopeMin = Bounds.Max.y; - - //PrintF(&String, "Thread %d", ThreadCalls.ThreadId); - //ui_Label(Interface, String, rect2{ThreadScopeMin); - - r32 Hue = (r32)(t) / (r32)(VisibleFrame->ThreadCount); - Hue += (.5f * (t % 2)); - v4 ThreadHSV = v4{ 360.0f * Hue, .5f, 1.0f, 1.0f }; - v4 ThreadRGB = HSVToRGB(ThreadHSV); - - for (s32 i = 0; i < ThreadCalls.Count; i++) + scope_record* Record = ThreadCalls.Calls + i; + scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash); + s64 OffsetStart = Record->StartCycles - FrameStartCycles; + s64 OffsetEnd = Record->EndCycles - FrameStartCycles; + r32 PercentStart = (r32)(OffsetStart) / FrameTotalCycles; + r32 PercentEnd = (r32)(OffsetEnd) / FrameTotalCycles; + r32 PercentWidth = PercentEnd - PercentStart; + + rect2 ScopeBounds = { + v2{0, 0}, + v2{PercentWidth * Width, DepthHeight - 4}, + }; + v2 Offset = { + Bounds.Min.x + (PercentStart * Width), + NextThreadTop - ((Record->CallDepth + 1) * DepthHeight) + }; + ScopeBounds = Rect2Translate(ScopeBounds, Offset); + ThreadScopeMin = Min(ScopeBounds.Min.y, ThreadScopeMin); + + if (Rect2Width(ScopeBounds) >= 1) + { + v4 Color = ThreadRGB; + if (PointIsInRect(ScopeBounds, Interface->Mouse.Pos)) { - scope_record* Record = ThreadCalls.Calls + i; - scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash); - s64 OffsetStart = Record->StartCycles - FrameStartCycles; - s64 OffsetEnd = Record->EndCycles - FrameStartCycles; - r32 PercentStart = (r32)(OffsetStart) / FrameTotalCycles; - r32 PercentEnd = (r32)(OffsetEnd) / FrameTotalCycles; - r32 PercentWidth = PercentEnd - PercentStart; - - rect2 ScopeBounds = { - v2{0, 0}, - v2{PercentWidth * Width, DepthHeight - 4}, - }; - v2 Offset = { - Bounds.Min.x + (PercentStart * Width), - NextThreadTop - ((Record->CallDepth + 1) * DepthHeight) - }; - ScopeBounds = Rect2Translate(ScopeBounds, Offset); - ThreadScopeMin = Min(ScopeBounds.Min.y, ThreadScopeMin); - - if (Rect2Width(ScopeBounds) >= 1) - { - v4 Color = ThreadRGB; - if (PointIsInRect(ScopeBounds, Interface->Mouse.Pos)) - { - Color = GreenV4; - - ui_BeginMousePopup(Interface, rect2{ 25, 25, 300, 57 }, LayoutDirection_TopDown, MakeString("Hover")); - { - s64 Cycles = (Record->EndCycles - Record->StartCycles); - r32 PercentFrame = (r32)(Cycles) / FrameTotalCycles; - PrintF(&String, "%S : %.2f%% frame | %dcy", - Name->Name, - PercentFrame, - Cycles); - ui_Label(Interface, String); - } - ui_EndMousePopup(Interface); - } - - ui_FillRect(Interface, ScopeBounds, Color); - ui_OutlineRect(Interface, ScopeBounds, 1, BlackV4); - } + Color = GreenV4; + + ui_BeginMousePopup(Interface, rect2{ 25, 25, 300, 57 }, LayoutDirection_TopDown, MakeString("Hover")); + { + s64 Cycles = (Record->EndCycles - Record->StartCycles); + r32 PercentFrame = (r32)(Cycles) / FrameTotalCycles; + PrintF(&String, "%S : %.2f%% frame | %dcy", + Name->Name, + PercentFrame, + Cycles); + ui_Label(Interface, String); + } + ui_EndMousePopup(Interface); } - NextThreadTop = ThreadScopeMin; + ui_FillRect(Interface, ScopeBounds, Color); + ui_OutlineRect(Interface, ScopeBounds, 1, BlackV4); + } } + + NextThreadTop = ThreadScopeMin; + } } internal void RenderProfiler_ListVisualization(ui_interface* Interface, ui_widget* Layout, debug_frame* VisibleFrame, gs_memory_arena* Memory) { - char Backbuffer[256]; - gs_string String = MakeString(Backbuffer, 0, 256); - - ui_column_spec ColumnWidths[] = { - { UIColumnSize_Fixed, 256 }, - { UIColumnSize_Fixed, 128 }, - { UIColumnSize_Fixed, 128 }, - { UIColumnSize_Fixed, 128 }, - { UIColumnSize_Fixed, 128 }}; - ui_BeginRow(Interface, 5, &ColumnWidths[0]); + char Backbuffer[256]; + gs_string String = MakeString(Backbuffer, 0, 256); + + ui_column_spec ColumnWidths[] = { + { UIColumnSize_Fixed, 256 }, + { UIColumnSize_Fixed, 128 }, + { UIColumnSize_Fixed, 128 }, + { UIColumnSize_Fixed, 128 }, + { UIColumnSize_Fixed, 128 }}; + ui_BeginRow(Interface, 5, &ColumnWidths[0]); + { + ui_Label(Interface, MakeString("Procedure")); + ui_Label(Interface, MakeString("% Frame")); + ui_Label(Interface, MakeString("Seconds")); + ui_Label(Interface, MakeString("Cycles")); + ui_Label(Interface, MakeString("Calls")); + } + ui_EndRow(Interface); + + s32 CountedScopes = 0; + for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++) + { + scope_name NameEntry = VisibleFrame->ScopeNamesHash[n]; + if (NameEntry.Hash != 0) { - ui_Label(Interface, MakeString("Procedure")); - ui_Label(Interface, MakeString("% Frame")); - ui_Label(Interface, MakeString("Seconds")); - ui_Label(Interface, MakeString("Cycles")); - ui_Label(Interface, MakeString("Calls")); + CountedScopes += 1; } - ui_EndRow(Interface); - - s32 CountedScopes = 0; - for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++) + } + + ui_BeginList(Interface, MakeString("Scope List"), 10, CountedScopes); + ui_BeginRow(Interface, 5, &ColumnWidths[0]); + for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++) + { + scope_name NameEntry = VisibleFrame->ScopeNamesHash[n]; + if (NameEntry.Hash != 0) { - scope_name NameEntry = VisibleFrame->ScopeNamesHash[n]; - if (NameEntry.Hash != 0) - { - CountedScopes += 1; - } + collated_scope_record* CollatedRecord = VisibleFrame->CollatedScopes + n; + + PrintF(&String, "%S", NameEntry.Name); + ui_Label(Interface, String); + + PrintF(&String, "%f%%", CollatedRecord->PercentFrameTime); + ui_Label(Interface, String); + + PrintF(&String, "%fs", CollatedRecord->TotalSeconds); + ui_Label(Interface, String); + + PrintF(&String, "%dcy", CollatedRecord->TotalCycles); + ui_Label(Interface, String); + + PrintF(&String, "%d", CollatedRecord->CallCount); + ui_Label(Interface, String); } - - ui_BeginList(Interface, MakeString("Scope List"), 10, CountedScopes); - ui_BeginRow(Interface, 5, &ColumnWidths[0]); - for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++) - { - scope_name NameEntry = VisibleFrame->ScopeNamesHash[n]; - if (NameEntry.Hash != 0) - { - collated_scope_record* CollatedRecord = VisibleFrame->CollatedScopes + n; - - PrintF(&String, "%S", NameEntry.Name); - ui_Label(Interface, String); - - PrintF(&String, "%f%%", CollatedRecord->PercentFrameTime); - ui_Label(Interface, String); - - PrintF(&String, "%fs", CollatedRecord->TotalSeconds); - ui_Label(Interface, String); - - PrintF(&String, "%dcy", CollatedRecord->TotalCycles); - ui_Label(Interface, String); - - PrintF(&String, "%d", CollatedRecord->CallCount); - ui_Label(Interface, String); - } - } - ui_EndRow(Interface); - ui_EndList(Interface); + } + ui_EndRow(Interface); + ui_EndList(Interface); } struct mem_amt { - u64 OrigSize; - r64 Size; - char* Units; + u64 OrigSize; + r64 Size; + char* Units; }; internal mem_amt GetMemAmt (u64 BytesCount) { - mem_amt Result = {}; - Result.OrigSize = BytesCount; - Result.Size = (r64)BytesCount; - Result.Units = "bytes"; - - u32 i = 0; - char* UnitList[] = { "kb", "mb", "gb", "tb" }; - while (Result.Size > 1024) { - Result.Size /= 1024.0; - Result.Units = UnitList[i++]; - } - - return Result; + mem_amt Result = {}; + Result.OrigSize = BytesCount; + Result.Size = (r64)BytesCount; + Result.Units = "bytes"; + + u32 i = 0; + char* UnitList[] = { "kb", "mb", "gb", "tb" }; + while (Result.Size > 1024) { + Result.Size /= 1024.0; + Result.Units = UnitList[i++]; + } + + return Result; } internal void RenderProfiler_MemoryView(ui_interface* Interface, ui_widget* Layout, app_state* State, context Context, gs_memory_arena* Memory) { - gs_allocator_debug Debug = *Context.ThreadContext.Allocator.Debug; - gs_string TempString = PushString(State->Transient, 256); - - mem_amt MemFootprint = GetMemAmt(Debug.TotalAllocSize); - u64 AllocCount = Debug.AllocationsCount; - - - PrintF(&TempString, "Total Memory Size: %.2f %s | Allocations: %lld", MemFootprint.Size, MemFootprint.Units, AllocCount); + gs_debug_allocations_list* DA = Context.ThreadContext.Allocator.DEBUGAllocList; + + gs_string TempString = PushString(State->Transient, 256); + + mem_amt MemFootprint = GetMemAmt(DA->AllocationsSizeTotal); + u64 AllocCount = DA->AllocationsCount; + + PrintF(&TempString, "Total Memory Size: %.2f %s | Allocations: %lld", MemFootprint.Size, MemFootprint.Units, AllocCount); + ui_Label(Interface, TempString); + + ui_column_spec ColumnWidths[] = { + { UIColumnSize_Fill, 0 }, + { UIColumnSize_Fixed,256 }, + }; + ui_BeginRow(Interface, 2, &ColumnWidths[0]); + { + ui_Label(Interface, MakeString("Location")); + ui_Label(Interface, MakeString("Alloc Size")); + } + ui_EndRow(Interface); + + ui_BeginList(Interface, MakeString("Alloc List"), 10, DA->AllocationsCount); + ui_BeginRow(Interface, 2, &ColumnWidths[0]); + + for (gs_debug_memory_allocation* A = DA->Root; + A && A->Next != 0; + A = A->Next) + { + gs_const_string Str = ConstString(A->Loc.File); + u64 LastSlash = FindLastFromSet(Str, "\\/"); + gs_const_string JustFileName = Substring(Str, LastSlash + 1, Str.Length); + PrintF(&TempString, "%s:%s(%d)", JustFileName.Str, A->Loc.Function, A->Loc.Line); ui_Label(Interface, TempString); - ui_column_spec ColumnWidths[] = { - { UIColumnSize_Fill, 0 }, - { UIColumnSize_Fixed,256 }, - }; - ui_BeginRow(Interface, 2, &ColumnWidths[0]); - { - ui_Label(Interface, MakeString("Location")); - ui_Label(Interface, MakeString("Alloc Size")); - } - ui_EndRow(Interface); + mem_amt Amt = GetMemAmt(A->Size); - ui_BeginList(Interface, MakeString("Alloc List"), 10, Debug.AllocationsCount); - ui_BeginRow(Interface, 2, &ColumnWidths[0]); - for (s32 n = 0; n < Debug.AllocationsCount; n++) - { - gs_debug_allocation A = Debug.Allocations[n]; - - PrintF(&TempString, "%S", A.Location); - ui_Label(Interface, TempString); - - mem_amt Amt = GetMemAmt(A.Size); - - PrintF(&TempString, "%.2f %s", Amt.Size, Amt.Units); - ui_Label(Interface, TempString); - } - ui_EndRow(Interface); - ui_EndList(Interface); + PrintF(&TempString, "%.2f %s", Amt.Size, Amt.Units); + ui_Label(Interface, TempString); + } + ui_EndRow(Interface); + ui_EndList(Interface); } GSMetaTag(panel_render); @@ -235,120 +239,120 @@ GSMetaTag(panel_type_profiler); internal void ProfilerView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - gs_memory_arena* Memory = State->Transient; - gs_string String = PushString(Memory, 256); + gs_memory_arena* Memory = State->Transient; + gs_string String = PushString(Memory, 256); + + v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 }; + + r32 FrameListHeight = 64; + rect2 FrameListBounds, ProcListBounds; + RectHSplitAtDistanceFromTop(PanelBounds, FrameListHeight, &FrameListBounds, &ProcListBounds); + rect2 FrameListInner = RectInset(FrameListBounds, 4); + + s32 FramesToDisplay = DEBUG_FRAME_COUNT; + if (FramesToDisplay != 0) + { + r32 SingleFrameStep = Rect2Width(FrameListInner) / FramesToDisplay; + r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2); - v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 }; - - r32 FrameListHeight = 64; - rect2 FrameListBounds, ProcListBounds; - RectHSplitAtDistanceFromTop(PanelBounds, FrameListHeight, &FrameListBounds, &ProcListBounds); - rect2 FrameListInner = RectInset(FrameListBounds, 4); - - s32 FramesToDisplay = DEBUG_FRAME_COUNT; - if (FramesToDisplay != 0) + ui_OutlineRect(&State->Interface, FrameListBounds, 2, WhiteV4); + if (MouseButtonHeldDown(Context.Mouse.LeftButtonState)) { - r32 SingleFrameStep = Rect2Width(FrameListInner) / FramesToDisplay; - r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2); - - ui_OutlineRect(&State->Interface, FrameListBounds, 2, WhiteV4); - if (MouseButtonHeldDown(Context.Mouse.LeftButtonState)) + if (PointIsInRect(FrameListBounds, Context.Mouse.Pos)) + { + v2 LocalMouse = Rect2GetRectLocalPoint(FrameListBounds, Context.Mouse.Pos); + s32 ClosestFrameIndex = (LocalMouse.x / SingleFrameStep); + if (ClosestFrameIndex >= 0 && ClosestFrameIndex < FramesToDisplay) { - if (PointIsInRect(FrameListBounds, Context.Mouse.Pos)) - { - v2 LocalMouse = Rect2GetRectLocalPoint(FrameListBounds, Context.Mouse.Pos); - s32 ClosestFrameIndex = (LocalMouse.x / SingleFrameStep); - if (ClosestFrameIndex >= 0 && ClosestFrameIndex < FramesToDisplay) - { - GlobalDebugServices->RecordFrames = false; - GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex; - } - } - } - - rect2 FrameBounds = MakeRect2MinDim(FrameListInner.Min, v2{SingleFrameWidth, Rect2Height(FrameListInner)}); - for (s32 F = 0; F < DEBUG_FRAME_COUNT; F++) - { - rect2 PositionedFrameBounds = Rect2TranslateX(FrameBounds, F * SingleFrameStep); - s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F); - if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; } - v4 Color = FrameColors[Clamp(0, FramesAgo, 3)]; - ui_FillRect(&State->Interface, PositionedFrameBounds, Color); + GlobalDebugServices->RecordFrames = false; + GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex; } + } } - ui_widget* Layout = ui_PushLayout(&State->Interface, ProcListBounds, LayoutDirection_TopDown, MakeString("Profiler Layout")); - - debug_frame* VisibleFrame = GetLastDebugFrame(GlobalDebugServices); - if (VisibleFrame) + rect2 FrameBounds = MakeRect2MinDim(FrameListInner.Min, v2{SingleFrameWidth, Rect2Height(FrameListInner)}); + for (s32 F = 0; F < DEBUG_FRAME_COUNT; F++) { - ui_BeginRow(&State->Interface, 4); - { - s64 FrameStartCycles = VisibleFrame->FrameStartCycles; - s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles; - u32 CurrentDebugFrame = GlobalDebugServices->CurrentDebugFrame - 1; - PrintF(&String, "Frame %d", CurrentDebugFrame); - ui_Label(&State->Interface, String); - - PrintF(&String, "Total Cycles: %lld", FrameTotalCycles); - ui_Label(&State->Interface, String); - - // NOTE(NAME): Skipping a space for aesthetic reasons, not functional, and could - // be removed, or used for something else - ui_ReserveBounds(&State->Interface, Layout, true); - - if (ui_Button(&State->Interface, MakeString("Resume Recording"))) - { - GlobalDebugServices->RecordFrames = true; - } - } - ui_EndRow(&State->Interface); + rect2 PositionedFrameBounds = Rect2TranslateX(FrameBounds, F * SingleFrameStep); + s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F); + if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; } + v4 Color = FrameColors[Clamp(0, FramesAgo, 3)]; + ui_FillRect(&State->Interface, PositionedFrameBounds, Color); } - - ui_BeginRow(&State->Interface, 8); + } + + ui_widget* Layout = ui_PushLayout(&State->Interface, ProcListBounds, LayoutDirection_TopDown, MakeString("Profiler Layout")); + + debug_frame* VisibleFrame = GetLastDebugFrame(GlobalDebugServices); + if (VisibleFrame) + { + ui_BeginRow(&State->Interface, 4); { - if (ui_Button(&State->Interface, MakeString("Profiler"))) - { - GlobalDebugServices->Interface.FrameView = DebugUI_Profiler; - } - if (ui_Button(&State->Interface, MakeString("List View"))) - { - GlobalDebugServices->Interface.FrameView = DebugUI_ScopeList; - } - if (ui_Button(&State->Interface, MakeString("Memory"))) - { - GlobalDebugServices->Interface.FrameView = DebugUI_MemoryView; - } + s64 FrameStartCycles = VisibleFrame->FrameStartCycles; + s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles; + u32 CurrentDebugFrame = GlobalDebugServices->CurrentDebugFrame - 1; + PrintF(&String, "Frame %d", CurrentDebugFrame); + ui_Label(&State->Interface, String); + + PrintF(&String, "Total Cycles: %lld", FrameTotalCycles); + ui_Label(&State->Interface, String); + + // NOTE(NAME): Skipping a space for aesthetic reasons, not functional, and could + // be removed, or used for something else + ui_ReserveBounds(&State->Interface, Layout, true); + + if (ui_Button(&State->Interface, MakeString("Resume Recording"))) + { + GlobalDebugServices->RecordFrames = true; + } } ui_EndRow(&State->Interface); - - switch (GlobalDebugServices->Interface.FrameView) + } + + ui_BeginRow(&State->Interface, 8); + { + if (ui_Button(&State->Interface, MakeString("Profiler"))) { - case DebugUI_Profiler: - { - if (VisibleFrame) - { - RenderProfiler_ScopeVisualization(&State->Interface, Layout, VisibleFrame, Memory); - } - }break; - - case DebugUI_ScopeList: - { - if (VisibleFrame) - { - RenderProfiler_ListVisualization(&State->Interface, Layout, VisibleFrame, Memory); - } - }break; - - case DebugUI_MemoryView: - { - RenderProfiler_MemoryView(&State->Interface, Layout, State, Context, Memory); - }break; - - InvalidDefaultCase; + GlobalDebugServices->Interface.FrameView = DebugUI_Profiler; } + if (ui_Button(&State->Interface, MakeString("List View"))) + { + GlobalDebugServices->Interface.FrameView = DebugUI_ScopeList; + } + if (ui_Button(&State->Interface, MakeString("Memory"))) + { + GlobalDebugServices->Interface.FrameView = DebugUI_MemoryView; + } + } + ui_EndRow(&State->Interface); + + switch (GlobalDebugServices->Interface.FrameView) + { + case DebugUI_Profiler: + { + if (VisibleFrame) + { + RenderProfiler_ScopeVisualization(&State->Interface, Layout, VisibleFrame, Memory); + } + }break; - ui_PopLayout(&State->Interface, MakeString("Profiler Layout")); + case DebugUI_ScopeList: + { + if (VisibleFrame) + { + RenderProfiler_ListVisualization(&State->Interface, Layout, VisibleFrame, Memory); + } + }break; + + case DebugUI_MemoryView: + { + RenderProfiler_MemoryView(&State->Interface, Layout, State, Context, Memory); + }break; + + InvalidDefaultCase; + } + + ui_PopLayout(&State->Interface, MakeString("Profiler Layout")); } diff --git a/src/app/editor/panels/foldhaus_panel_sculpture_view.h b/src/app/editor/panels/foldhaus_panel_sculpture_view.h index ad51493..474d5ca 100644 --- a/src/app/editor/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/editor/panels/foldhaus_panel_sculpture_view.h @@ -13,49 +13,49 @@ struct sculpture_view_panel_state { - camera Camera; + camera Camera; }; // 3D Mouse View OPERATION_STATE_DEF(mouse_rotate_view_operation_state) { - v4 CameraStartPos; - camera* Camera; + v4 CameraStartPos; + camera* Camera; }; OPERATION_RENDER_PROC(Update3DViewMouseRotate) { - mouse_rotate_view_operation_state* OpState = (mouse_rotate_view_operation_state*)Operation.OpStateMemory; - - v2 TotalDeltaPos = Mouse.Pos - Mouse.DownPos; - - m44 XRotation = M44RotationX(-TotalDeltaPos.y * PIXEL_TO_WORLD_SCALE); - m44 YRotation = M44RotationY(TotalDeltaPos.x * PIXEL_TO_WORLD_SCALE); - m44 Combined = XRotation * YRotation; - - OpState->Camera->Position = (Combined * OpState->CameraStartPos).xyz; + mouse_rotate_view_operation_state* OpState = (mouse_rotate_view_operation_state*)Operation.OpStateMemory; + + v2 TotalDeltaPos = Mouse.Pos - Mouse.DownPos; + + m44 XRotation = M44RotationX(-TotalDeltaPos.y * PIXEL_TO_WORLD_SCALE); + m44 YRotation = M44RotationY(TotalDeltaPos.x * PIXEL_TO_WORLD_SCALE); + m44 Combined = XRotation * YRotation; + + OpState->Camera->Position = (Combined * OpState->CameraStartPos).xyz; } FOLDHAUS_INPUT_COMMAND_PROC(End3DViewMouseRotate) { - DeactivateCurrentOperationMode(&State->Modes); + DeactivateCurrentOperationMode(&State->Modes); } input_command MouseRotateViewCommands [] = { - { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, End3DViewMouseRotate}, + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, End3DViewMouseRotate}, }; FOLDHAUS_INPUT_COMMAND_PROC(Begin3DViewMouseRotate) { - sculpture_view_panel_state* PanelState = Panel_GetStateStruct(Panel, sculpture_view_panel_state); - - operation_mode* RotateViewMode = ActivateOperationModeWithCommands(&State->Modes, MouseRotateViewCommands, Update3DViewMouseRotate); - mouse_rotate_view_operation_state* OpState = CreateOperationState(RotateViewMode, - &State->Modes, - mouse_rotate_view_operation_state); - OpState->CameraStartPos = ToV4Point(PanelState->Camera.Position); - OpState->Camera = &PanelState->Camera; + sculpture_view_panel_state* PanelState = Panel_GetStateStruct(Panel, sculpture_view_panel_state); + + operation_mode* RotateViewMode = ActivateOperationModeWithCommands(&State->Modes, MouseRotateViewCommands, Update3DViewMouseRotate); + mouse_rotate_view_operation_state* OpState = CreateOperationState(RotateViewMode, + &State->Modes, + mouse_rotate_view_operation_state); + OpState->CameraStartPos = ToV4Point(PanelState->Camera.Position); + OpState->Camera = &PanelState->Camera; } // ---------------- @@ -63,7 +63,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(Begin3DViewMouseRotate) GSMetaTag(panel_commands); GSMetaTag(panel_type_sculpture_view); global input_command SculptureView_Commands[] = { - { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, Begin3DViewMouseRotate }, + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, Begin3DViewMouseRotate }, }; global s32 SculptureView_CommandsCount = 1; @@ -72,16 +72,16 @@ GSMetaTag(panel_type_sculpture_view); internal void SculptureView_Init(panel* Panel, app_state* State, context Context) { - sculpture_view_panel_state* PanelState = PushStruct(&State->Permanent, sculpture_view_panel_state); - - PanelState->Camera.FieldOfView = 45.0f; - PanelState->Camera.AspectRatio = RectAspectRatio(State->WindowBounds); - PanelState->Camera.Near = .1f; - PanelState->Camera.Far = 800.0f; - PanelState->Camera.Position = v3{0, 0, 400}; - PanelState->Camera.LookAt = v3{0, 0, 0}; - - Panel->StateMemory = StructToData(PanelState, sculpture_view_panel_state); + sculpture_view_panel_state* PanelState = PushStruct(&State->Permanent, sculpture_view_panel_state); + + PanelState->Camera.FieldOfView = 45.0f; + PanelState->Camera.AspectRatio = RectAspectRatio(State->WindowBounds); + PanelState->Camera.Near = .1f; + PanelState->Camera.Far = 800.0f; + PanelState->Camera.Position = v3{0, 0, 400}; + PanelState->Camera.LookAt = v3{0, 0, 0}; + + Panel->StateMemory = StructToData(PanelState, sculpture_view_panel_state); } GSMetaTag(panel_cleanup); @@ -89,92 +89,92 @@ GSMetaTag(panel_type_sculpture_view); internal void SculptureView_Cleanup(panel* Panel, app_state* State) { - + } struct draw_leds_job_data { - v4 CameraPosition; - led_buffer LedBuffer; - s32 StartIndex; - s32 OnePastLastIndex; - render_quad_batch_constructor* Batch; - quad_batch_constructor_reserved_range BatchReservedRange; - r32 LEDHalfWidth; + v4 CameraPosition; + led_buffer LedBuffer; + s32 StartIndex; + s32 OnePastLastIndex; + render_quad_batch_constructor* Batch; + quad_batch_constructor_reserved_range BatchReservedRange; + r32 LEDHalfWidth; }; internal void DrawLedsInBuffer(led_buffer LedBuffer, s32 StartIndex, s32 OnePastLastIndex, render_quad_batch_constructor* Batch, quad_batch_constructor_reserved_range ReservedRange, r32 LedHalfWidth) { - s32 TrisUsed = 0; + s32 TrisUsed = 0; + + v4 P0_In = v4{-LedHalfWidth, -LedHalfWidth, 0, 1}; + v4 P1_In = v4{LedHalfWidth, -LedHalfWidth, 0, 1}; + v4 P2_In = v4{LedHalfWidth, LedHalfWidth, 0, 1}; + v4 P3_In = v4{-LedHalfWidth, LedHalfWidth, 0, 1}; + + v2 UV0 = v2{0, 0}; + v2 UV1 = v2{1, 0}; + v2 UV2 = v2{1, 1}; + v2 UV3 = v2{0, 1}; + + Assert(OnePastLastIndex <= (s32)LedBuffer.LedCount); + for (s32 LedIndex = StartIndex; LedIndex < OnePastLastIndex; LedIndex++) + { + pixel PixelColor = LedBuffer.Colors[LedIndex]; + v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f}; - v4 P0_In = v4{-LedHalfWidth, -LedHalfWidth, 0, 1}; - v4 P1_In = v4{LedHalfWidth, -LedHalfWidth, 0, 1}; - v4 P2_In = v4{LedHalfWidth, LedHalfWidth, 0, 1}; - v4 P3_In = v4{-LedHalfWidth, LedHalfWidth, 0, 1}; + v4 Position = LedBuffer.Positions[LedIndex]; + v4 PositionOffset = ToV4Vec(Position.xyz); + v4 P0 = P0_In + PositionOffset; + v4 P1 = P1_In + PositionOffset; + v4 P2 = P2_In + PositionOffset; + v4 P3 = P3_In + PositionOffset; - v2 UV0 = v2{0, 0}; - v2 UV1 = v2{1, 0}; - v2 UV2 = v2{1, 1}; - v2 UV3 = v2{0, 1}; - - Assert(OnePastLastIndex <= (s32)LedBuffer.LedCount); - for (s32 LedIndex = StartIndex; LedIndex < OnePastLastIndex; LedIndex++) - { - pixel PixelColor = LedBuffer.Colors[LedIndex]; - v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f}; - - v4 Position = LedBuffer.Positions[LedIndex]; - v4 PositionOffset = ToV4Vec(Position.xyz); - v4 P0 = P0_In + PositionOffset; - v4 P1 = P1_In + PositionOffset; - v4 P2 = P2_In + PositionOffset; - v4 P3 = P3_In + PositionOffset; - - SetTri3DInBatch(Batch, ReservedRange.Start + TrisUsed++, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); - SetTri3DInBatch(Batch, ReservedRange.Start + TrisUsed++, P0, P2, P3, UV0, UV2, UV3, Color, Color, Color); - } + SetTri3DInBatch(Batch, ReservedRange.Start + TrisUsed++, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); + SetTri3DInBatch(Batch, ReservedRange.Start + TrisUsed++, P0, P2, P3, UV0, UV2, UV3, Color, Color, Color); + } } internal void DrawLEDsInBufferRangeJob (gs_thread_context Context, gs_data JobData) { - DEBUG_TRACK_FUNCTION; - draw_leds_job_data* Data = (draw_leds_job_data*)JobData.Memory; - DrawLedsInBuffer(Data->LedBuffer, Data->StartIndex, Data->OnePastLastIndex, Data->Batch, Data->BatchReservedRange, Data->LEDHalfWidth); + DEBUG_TRACK_FUNCTION; + draw_leds_job_data* Data = (draw_leds_job_data*)JobData.Memory; + DrawLedsInBuffer(Data->LedBuffer, Data->StartIndex, Data->OnePastLastIndex, Data->Batch, Data->BatchReservedRange, Data->LEDHalfWidth); } internal void DrawQuad(render_command_buffer* RenderBuffer, v4 C, r32 Rad, v4 Color) { - v4 P0 = C + v4{-Rad,-Rad,0,0}; - v4 P1 = C + v4{ Rad,-Rad,0,0}; - v4 P2 = C + v4{ Rad,Rad,0,0}; - v4 P3 = C + v4{ -Rad,Rad,0,0}; - PushRenderQuad3D(RenderBuffer, P0, P1, P2, P3, Color); + v4 P0 = C + v4{-Rad,-Rad,0,0}; + v4 P1 = C + v4{ Rad,-Rad,0,0}; + v4 P2 = C + v4{ Rad,Rad,0,0}; + v4 P3 = C + v4{ -Rad,Rad,0,0}; + PushRenderQuad3D(RenderBuffer, P0, P1, P2, P3, Color); } internal v2 SculptureView_WorldToScreenPosition(v4 WorldPosition, camera Camera, rect2 PanelBounds) { - v2 Result = {0}; - - r32 PanelW = Rect2Width(PanelBounds); - r32 PanelH = Rect2Height(PanelBounds); - - m44 Matrix = GetCameraPerspectiveProjectionMatrix(Camera) * GetCameraModelViewMatrix(Camera); - v4 WorldPos = Matrix * WorldPosition; - - // this is the Perspective Divide - v2 ProjectedPos = WorldPos.xy / WorldPos.w; - - // Projection gets us in a range [-1, 1], and we want [0, width] - ProjectedPos.x = ((ProjectedPos.x / 2) * PanelW) + (PanelW / 2); - ProjectedPos.y = ((ProjectedPos.y / 2) * PanelH) + (PanelH / 2); - - Result = ProjectedPos + PanelBounds.Min; - return Result; + v2 Result = {0}; + + r32 PanelW = Rect2Width(PanelBounds); + r32 PanelH = Rect2Height(PanelBounds); + + m44 Matrix = GetCameraPerspectiveProjectionMatrix(Camera) * GetCameraModelViewMatrix(Camera); + v4 WorldPos = Matrix * WorldPosition; + + // this is the Perspective Divide + v2 ProjectedPos = WorldPos.xy / WorldPos.w; + + // Projection gets us in a range [-1, 1], and we want [0, width] + ProjectedPos.x = ((ProjectedPos.x / 2) * PanelW) + (PanelW / 2); + ProjectedPos.y = ((ProjectedPos.y / 2) * PanelH) + (PanelH / 2); + + Result = ProjectedPos + PanelBounds.Min; + return Result; } GSMetaTag(panel_render); @@ -182,62 +182,62 @@ GSMetaTag(panel_type_sculpture_view); internal void SculptureView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - DEBUG_TRACK_SCOPE(RenderSculpture); - sculpture_view_panel_state* PanelState = Panel_GetStateStruct(Panel, sculpture_view_panel_state); - PanelState->Camera.AspectRatio = RectAspectRatio(PanelBounds); - - PushRenderPerspective(RenderBuffer, PanelBounds, PanelState->Camera); - - u32 MaxLEDsPerJob = 2048; - render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal); - - u32 FocusPixel = 100; - - for (u32 BufferIndex = 0; BufferIndex < State->LedSystem.BuffersCount; BufferIndex++) + DEBUG_TRACK_SCOPE(RenderSculpture); + sculpture_view_panel_state* PanelState = Panel_GetStateStruct(Panel, sculpture_view_panel_state); + PanelState->Camera.AspectRatio = RectAspectRatio(PanelBounds); + + PushRenderPerspective(RenderBuffer, PanelBounds, PanelState->Camera); + + u32 MaxLEDsPerJob = 2048; + render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal); + + u32 FocusPixel = 100; + + for (u32 BufferIndex = 0; BufferIndex < State->LedSystem.BuffersCount; BufferIndex++) + { + led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, BufferIndex); + u32 JobsNeeded = U32DivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); + u32 NextLEDIndex = 0; + for (u32 Job = 0; Job < JobsNeeded; Job++) { - led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, BufferIndex); - u32 JobsNeeded = U32DivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); - u32 NextLEDIndex = 0; - for (u32 Job = 0; Job < JobsNeeded; Job++) - { - gs_data Data = PushSizeToData(State->Transient, sizeof(draw_leds_job_data)); - draw_leds_job_data* JobData = (draw_leds_job_data*)Data.Memory; - JobData->LedBuffer = *LedBuffer; - JobData->StartIndex = NextLEDIndex; - JobData->OnePastLastIndex = Min(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); - s32 JobLedCount = JobData->OnePastLastIndex - JobData->StartIndex; - JobData->Batch = &RenderLEDsBatch; - JobData->BatchReservedRange = ReserveRangeInQuadConstructor(JobData->Batch, JobLedCount * 2); - JobData->LEDHalfWidth = .5f; - JobData->CameraPosition = ToV4Point(PanelState->Camera.Position); + gs_data Data = PushSize(State->Transient, sizeof(draw_leds_job_data)); + draw_leds_job_data* JobData = (draw_leds_job_data*)Data.Memory; + JobData->LedBuffer = *LedBuffer; + JobData->StartIndex = NextLEDIndex; + JobData->OnePastLastIndex = Min(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); + s32 JobLedCount = JobData->OnePastLastIndex - JobData->StartIndex; + JobData->Batch = &RenderLEDsBatch; + JobData->BatchReservedRange = ReserveRangeInQuadConstructor(JobData->Batch, JobLedCount * 2); + JobData->LEDHalfWidth = .5f; + JobData->CameraPosition = ToV4Point(PanelState->Camera.Position); #if 1 - Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, (thread_proc*)DrawLEDsInBufferRangeJob, Data, ConstString("Sculpture Draw LEDS")); + Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, (thread_proc*)DrawLEDsInBufferRangeJob, Data, ConstString("Sculpture Draw LEDS")); #else - DrawLedsInBuffer(JobData->LedBuffer, JobData->StartIndex, JobData->OnePastLastIndex, JobData->Batch, JobData->BatchReservedRange, JobData->LEDHalfWidth); + DrawLedsInBuffer(JobData->LedBuffer, JobData->StartIndex, JobData->OnePastLastIndex, JobData->Batch, JobData->BatchReservedRange, JobData->LEDHalfWidth); #endif - NextLEDIndex = JobData->OnePastLastIndex; - } + NextLEDIndex = JobData->OnePastLastIndex; } + } + + // TODO(Peter): I don't like the fact that setting an orthographic view inside a panel render function + // needs to relyon the window bounds rather than the panel bounds. Ideally the panel only needs to know where + // itself is, and nothing else. + PushRenderOrthographic(RenderBuffer, State->WindowBounds); + if (State->Assemblies.Count > 0) + { + assembly Assembly = State->Assemblies.Values[0]; + led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex); - // TODO(Peter): I don't like the fact that setting an orthographic view inside a panel render function - // needs to relyon the window bounds rather than the panel bounds. Ideally the panel only needs to know where - // itself is, and nothing else. - PushRenderOrthographic(RenderBuffer, State->WindowBounds); - if (State->Assemblies.Count > 0) - { - assembly Assembly = State->Assemblies.Values[0]; - led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex); - - v4 LedPosition = LedBuffer->Positions[FocusPixel]; - v2 LedOnScreenPosition = SculptureView_WorldToScreenPosition(LedPosition, PanelState->Camera, PanelBounds); - - gs_string Tempgs_string = PushString(State->Transient, 256); - PrintF(&Tempgs_string, "Hot Id: %u, ZIndex: %u | Active Id: %u", State->Interface.HotWidget.Id, - State->Interface.HotWidget.ZIndex,State->Interface.ActiveWidget.Id); - DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4, -1, GreenV4); - - } - Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext); + v4 LedPosition = LedBuffer->Positions[FocusPixel]; + v2 LedOnScreenPosition = SculptureView_WorldToScreenPosition(LedPosition, PanelState->Camera, PanelBounds); + + gs_string Tempgs_string = PushString(State->Transient, 256); + PrintF(&Tempgs_string, "Hot Id: %u, ZIndex: %u | Active Id: %u", State->Interface.HotWidget.Id, + State->Interface.HotWidget.ZIndex,State->Interface.ActiveWidget.Id); + DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4, -1, GreenV4); + + } + Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext); } #define FOLDHAUS_PANEL_SCULPTURE_VIEW_H diff --git a/src/app/engine/animation/foldhaus_animation_renderer.cpp b/src/app/engine/animation/foldhaus_animation_renderer.cpp index eb2c130..6f7d243 100644 --- a/src/app/engine/animation/foldhaus_animation_renderer.cpp +++ b/src/app/engine/animation/foldhaus_animation_renderer.cpp @@ -8,122 +8,122 @@ internal pixel LedBlend_Overwrite(pixel PixelA, pixel PixelB, u8* UserData) { - r32 MagB = (r32)(PixelB.R + PixelB.G + PixelB.B) / (255 * 3); - - pixel Result = {}; - Result.R = (u8)LerpR32(MagB, PixelA.R, PixelB.R); - Result.G = (u8)LerpR32(MagB, PixelA.G, PixelB.G); - Result.B = (u8)LerpR32(MagB, PixelA.B, PixelB.B); - + r32 MagB = (r32)(PixelB.R + PixelB.G + PixelB.B) / (255 * 3); + + pixel Result = {}; + Result.R = (u8)LerpR32(MagB, PixelA.R, PixelB.R); + Result.G = (u8)LerpR32(MagB, PixelA.G, PixelB.G); + Result.B = (u8)LerpR32(MagB, PixelA.B, PixelB.B); + #if 0 - pixel Result = PixelB; - if (PixelB.R == 0 && - PixelB.G == 0 && - PixelB.B == 0) - { - Result = PixelA; - } + pixel Result = PixelB; + if (PixelB.R == 0 && + PixelB.G == 0 && + PixelB.B == 0) + { + Result = PixelA; + } #endif - return Result; + return Result; } internal pixel LedBlend_Lerp(pixel PixelA, pixel PixelB, u8* UserData) { - r32 BOpacity = *(r32*)UserData; - - pixel Result = {}; - - r32 AOpacity = 1.0f - BOpacity; - Result.R = (u8)((PixelA.R * AOpacity) + (PixelB.R * BOpacity)); - Result.G = (u8)((PixelA.G * AOpacity) + (PixelB.G * BOpacity)); - Result.B = (u8)((PixelA.B * AOpacity) + (PixelB.B * BOpacity)); - return Result; + r32 BOpacity = *(r32*)UserData; + + pixel Result = {}; + + r32 AOpacity = 1.0f - BOpacity; + Result.R = (u8)((PixelA.R * AOpacity) + (PixelB.R * BOpacity)); + Result.G = (u8)((PixelA.G * AOpacity) + (PixelB.G * BOpacity)); + Result.B = (u8)((PixelA.B * AOpacity) + (PixelB.B * BOpacity)); + return Result; } internal pixel LedBlend_Add(pixel PixelA, pixel PixelB, u8* UserData) { - pixel Result = {}; - - u32 R = (u32)PixelA.R + (u32)PixelB.R; - u32 G = (u32)PixelA.G + (u32)PixelB.G; - u32 B = (u32)PixelA.B + (u32)PixelB.B; - - Result.R = (u8)Min(R, (u32)255); - Result.G = (u8)Min(G, (u32)255); - Result.B = (u8)Min(B, (u32)255); - - return Result; + pixel Result = {}; + + u32 R = (u32)PixelA.R + (u32)PixelB.R; + u32 G = (u32)PixelA.G + (u32)PixelB.G; + u32 B = (u32)PixelA.B + (u32)PixelB.B; + + Result.R = (u8)Min(R, (u32)255); + Result.G = (u8)Min(G, (u32)255); + Result.B = (u8)Min(B, (u32)255); + + return Result; } internal pixel LedBlend_Multiply(pixel PixelA, pixel PixelB, u8* UserData) { - pixel Result = {}; - - r32 DR = (r32)PixelA.R / 255.f; - r32 DG = (r32)PixelA.G / 255.f; - r32 DB = (r32)PixelA.B / 255.f; - - r32 SR = (r32)PixelB.R / 255.f; - r32 SG = (r32)PixelB.G / 255.f; - r32 SB = (r32)PixelB.B / 255.f; - - Result.R = (u8)((DR * SR) * 255.f); - Result.G = (u8)((DG * SG) * 255.f); - Result.B = (u8)((DB * SB) * 255.f); - - return Result; + pixel Result = {}; + + r32 DR = (r32)PixelA.R / 255.f; + r32 DG = (r32)PixelA.G / 255.f; + r32 DB = (r32)PixelA.B / 255.f; + + r32 SR = (r32)PixelB.R / 255.f; + r32 SG = (r32)PixelB.G / 255.f; + r32 SB = (r32)PixelB.B / 255.f; + + Result.R = (u8)((DR * SR) * 255.f); + Result.G = (u8)((DG * SG) * 255.f); + Result.B = (u8)((DB * SB) * 255.f); + + return Result; } internal pixel LedBlend_Overlay(pixel PixelA, pixel PixelB, u8* UserData) { - pixel Result = {}; - return Result; + pixel Result = {}; + return Result; } internal led_blend_proc* LedBlend_GetProc(blend_mode BlendMode) { - led_blend_proc* Result = 0; - switch (BlendMode) - { - case BlendMode_Overwrite: { Result = LedBlend_Overwrite; }break; - case BlendMode_Add: { Result = LedBlend_Add; }break; - case BlendMode_Multiply: { Result = LedBlend_Multiply; }break; - InvalidDefaultCase; - } - return Result; + led_blend_proc* Result = 0; + switch (BlendMode) + { + case BlendMode_Overwrite: { Result = LedBlend_Overwrite; }break; + case BlendMode_Add: { Result = LedBlend_Add; }break; + case BlendMode_Multiply: { Result = LedBlend_Multiply; }break; + InvalidDefaultCase; + } + return Result; } struct pattern_args { - assembly Assembly; - gs_memory_arena* Transient; - u8* UserData; + assembly Assembly; + gs_memory_arena* Transient; + u8* UserData; }; struct render_anim_to_led_buffer_job_data { - animation_pattern Pattern; - led_buffer Buffer; - led_buffer_range BufferRange; - pattern_args PatternArgs; - r32 SecondsIntoBlock; + animation_pattern Pattern; + led_buffer Buffer; + led_buffer_range BufferRange; + pattern_args PatternArgs; + r32 SecondsIntoBlock; }; internal void AnimationSystem_RenderAnimationToLedBufferJob(gs_thread_context Context, gs_data Data) { - render_anim_to_led_buffer_job_data JobData = *(render_anim_to_led_buffer_job_data*)Data.Memory; - JobData.Pattern.Proc(&JobData.Buffer, - JobData.BufferRange, - JobData.PatternArgs.Assembly, - JobData.SecondsIntoBlock, - JobData.PatternArgs.Transient, - JobData.PatternArgs.UserData); + render_anim_to_led_buffer_job_data JobData = *(render_anim_to_led_buffer_job_data*)Data.Memory; + JobData.Pattern.Proc(&JobData.Buffer, + JobData.BufferRange, + JobData.PatternArgs.Assembly, + JobData.SecondsIntoBlock, + JobData.PatternArgs.Transient, + JobData.PatternArgs.UserData); } #define MULTITHREAD_PATTERN_RENDERING 1 @@ -132,61 +132,61 @@ internal void AnimationSystem_BeginRenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, animation_pattern_array Patterns, pattern_args PatternArgs, context Context) { - DEBUG_TRACK_FUNCTION; + DEBUG_TRACK_FUNCTION; + + u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min; + r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame; + + animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle); + Assert(Pattern.Proc); + + if (System->Multithreaded && Pattern.Multithreaded) + { + u32 JobsCount = 4; + u32 LedsPerJob = Buffer->LedCount / JobsCount; - u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min; - r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame; - - animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle); - Assert(Pattern.Proc); - - if (System->Multithreaded && Pattern.Multithreaded) + for (u32 i = 0; i < JobsCount; i++) { - u32 JobsCount = 4; - u32 LedsPerJob = Buffer->LedCount / JobsCount; - - for (u32 i = 0; i < JobsCount; i++) - { - gs_data Data = PushSizeToData(Context.ThreadContext.Transient, sizeof(render_anim_to_led_buffer_job_data)); - render_anim_to_led_buffer_job_data* JobData = (render_anim_to_led_buffer_job_data*)Data.Memory; - JobData->Pattern = Pattern; - JobData->Buffer = *Buffer; - JobData->BufferRange.First = LedsPerJob * i; - JobData->BufferRange.OnePastLast = LedsPerJob * (i + 1); - JobData->PatternArgs = PatternArgs; - JobData->SecondsIntoBlock = SecondsIntoBlock; - - Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, - (thread_proc*)AnimationSystem_RenderAnimationToLedBufferJob, - Data, - ConstString("Render Pattern To Buffer")); - } - } - else - { - led_buffer_range Range = {}; - Range.First = 0; - Range.OnePastLast = Buffer->LedCount; - - Pattern.Proc(Buffer, Range, PatternArgs.Assembly, SecondsIntoBlock, PatternArgs.Transient, PatternArgs.UserData); + gs_data Data = PushSize(Context.ThreadContext.Transient, sizeof(render_anim_to_led_buffer_job_data)); + render_anim_to_led_buffer_job_data* JobData = (render_anim_to_led_buffer_job_data*)Data.Memory; + JobData->Pattern = Pattern; + JobData->Buffer = *Buffer; + JobData->BufferRange.First = LedsPerJob * i; + JobData->BufferRange.OnePastLast = LedsPerJob * (i + 1); + JobData->PatternArgs = PatternArgs; + JobData->SecondsIntoBlock = SecondsIntoBlock; + + Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, + (thread_proc*)AnimationSystem_RenderAnimationToLedBufferJob, + Data, + ConstString("Render Pattern To Buffer")); } + } + else + { + led_buffer_range Range = {}; + Range.First = 0; + Range.OnePastLast = Buffer->LedCount; + + Pattern.Proc(Buffer, Range, PatternArgs.Assembly, SecondsIntoBlock, PatternArgs.Transient, PatternArgs.UserData); + } } internal void AnimationSystem_EndRenderBlockToLedBuffer (animation_system* System, context Context) { - if (System->Multithreaded) - { - Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext); - } + if (System->Multithreaded) + { + Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext); + } } // NOTE(pjs): This mirrors animation_layer_frame to account // for overlapping struct layer_led_buffer { - led_buffer HotBuffer; - led_buffer NextHotBuffer; + led_buffer HotBuffer; + led_buffer NextHotBuffer; }; internal led_buffer @@ -199,80 +199,80 @@ RenderAnimationToLedBuffer (animation_system* System, gs_memory_arena* Transient, context Context) { - DEBUG_TRACK_FUNCTION; + DEBUG_TRACK_FUNCTION; + + led_buffer AccBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient); + + // Create the LayerLEDBuffers + for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++) + { + layer_led_buffer TempBuffer = {}; - led_buffer AccBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient); - - // Create the LayerLEDBuffers - for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++) + if (CurrFrame.Layers[Layer].HasHot) { - layer_led_buffer TempBuffer = {}; - - if (CurrFrame.Layers[Layer].HasHot) - { - TempBuffer.HotBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient); - - if (CurrFrame.Layers[Layer].HasNextHot) - { - TempBuffer.NextHotBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient); - } - } - - LayerBuffers[Layer] = TempBuffer; + TempBuffer.HotBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient); + + if (CurrFrame.Layers[Layer].HasNextHot) + { + TempBuffer.NextHotBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient); + } } - // Render Each layer's block to the appropriate temp buffer - for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++) + LayerBuffers[Layer] = TempBuffer; + } + + // Render Each layer's block to the appropriate temp buffer + for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++) + { + animation_layer_frame LayerFrame = CurrFrame.Layers[Layer]; + if (LayerFrame.HasHot) { - animation_layer_frame LayerFrame = CurrFrame.Layers[Layer]; - if (LayerFrame.HasHot) - { - led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer; - animation_block Block = LayerFrame.Hot; - AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context); - } - - if (LayerFrame.HasNextHot) - { - led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer; - animation_block Block = LayerFrame.NextHot; - AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context); - } - - AnimationSystem_EndRenderBlockToLedBuffer(System, Context); + led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer; + animation_block Block = LayerFrame.Hot; + AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context); } - // Blend together any layers that have a hot and next hot buffer - for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++) + if (LayerFrame.HasNextHot) { - animation_layer_frame LayerFrame = CurrFrame.Layers[Layer]; - layer_led_buffer LayerBuffer = LayerBuffers[Layer]; - if (LayerFrame.HasNextHot) - { - LedBuffer_Blend(LayerBuffer.HotBuffer, - LayerBuffer.NextHotBuffer, - &LayerBuffer.HotBuffer, - LedBlend_Lerp, - (u8*)&LayerFrame.NextHotOpacity); - } + led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer; + animation_block Block = LayerFrame.NextHot; + AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context); } - // Consolidate Temp Buffers back into AssemblyLedBuffer - // We do this in reverse order so that they go from top to bottom - for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++) + AnimationSystem_EndRenderBlockToLedBuffer(System, Context); + } + + // Blend together any layers that have a hot and next hot buffer + for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++) + { + animation_layer_frame LayerFrame = CurrFrame.Layers[Layer]; + layer_led_buffer LayerBuffer = LayerBuffers[Layer]; + if (LayerFrame.HasNextHot) { - if (CurrFrame.Layers[Layer].HasHot) - { - led_blend_proc* Blend = LedBlend_GetProc(CurrFrame.Layers[Layer].BlendMode); - LedBuffer_Blend(AccBuffer, - LayerBuffers[Layer].HotBuffer, - &AccBuffer, - Blend, - 0); - } + LedBuffer_Blend(LayerBuffer.HotBuffer, + LayerBuffer.NextHotBuffer, + &LayerBuffer.HotBuffer, + LedBlend_Lerp, + (u8*)&LayerFrame.NextHotOpacity); } - - return AccBuffer; + } + + // Consolidate Temp Buffers back into AssemblyLedBuffer + // We do this in reverse order so that they go from top to bottom + for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++) + { + if (CurrFrame.Layers[Layer].HasHot) + { + led_blend_proc* Blend = LedBlend_GetProc(CurrFrame.Layers[Layer].BlendMode); + LedBuffer_Blend(AccBuffer, + LayerBuffers[Layer].HotBuffer, + &AccBuffer, + Blend, + 0); + } + } + + return AccBuffer; } internal void @@ -283,92 +283,92 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse context Context, u8* UserData) { - DEBUG_TRACK_FUNCTION; - - r32 FrameTime = AnimationSystem_GetCurrentTime(*System); - + DEBUG_TRACK_FUNCTION; + + r32 FrameTime = AnimationSystem_GetCurrentTime(*System); + #if 1 - animation_array Animations = System->Animations; - animation_fade_group FadeGroup = System->ActiveFadeGroup; + animation_array Animations = System->Animations; + animation_fade_group FadeGroup = System->ActiveFadeGroup; + + animation* FromAnim = AnimationArray_Get(Animations, FadeGroup.From); + animation_frame FromFrame = AnimationSystem_CalculateAnimationFrame(System, FromAnim, Transient); + layer_led_buffer* FromLayerBuffers = PushArray(Transient, layer_led_buffer, FromFrame.LayersCount); + + animation* ToAnim = AnimationArray_Get(Animations, FadeGroup.To); + animation_frame ToFrame = {0}; + layer_led_buffer* ToLayerBuffers = 0; + if (ToAnim) + { + ToFrame = AnimationSystem_CalculateAnimationFrame(System, ToAnim, Transient); + ToLayerBuffers = PushArray(Transient, layer_led_buffer, ToFrame.LayersCount); + } + + for (u32 AssemblyIndex = 0; AssemblyIndex < Assemblies.Count; AssemblyIndex++) + { + assembly Assembly = Assemblies.Values[AssemblyIndex]; + led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); - animation* FromAnim = AnimationArray_Get(Animations, FadeGroup.From); - animation_frame FromFrame = AnimationSystem_CalculateAnimationFrame(System, FromAnim, Transient); - layer_led_buffer* FromLayerBuffers = PushArray(Transient, layer_led_buffer, FromFrame.LayersCount); + pattern_args PatternArgs = {}; + PatternArgs.Assembly = Assembly; + PatternArgs.Transient = Transient; + PatternArgs.UserData = UserData; - animation* ToAnim = AnimationArray_Get(Animations, FadeGroup.To); - animation_frame ToFrame = {0}; - layer_led_buffer* ToLayerBuffers = 0; - if (ToAnim) - { - ToFrame = AnimationSystem_CalculateAnimationFrame(System, ToAnim, Transient); - ToLayerBuffers = PushArray(Transient, layer_led_buffer, ToFrame.LayersCount); - } - - for (u32 AssemblyIndex = 0; AssemblyIndex < Assemblies.Count; AssemblyIndex++) - { - assembly Assembly = Assemblies.Values[AssemblyIndex]; - led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); - - pattern_args PatternArgs = {}; - PatternArgs.Assembly = Assembly; - PatternArgs.Transient = Transient; - PatternArgs.UserData = UserData; - - led_buffer FromBuffer = RenderAnimationToLedBuffer(System, - PatternArgs, - FromFrame, - FromLayerBuffers, - AssemblyLedBuffer, - Patterns, - Transient, - Context); - led_buffer ConsolidatedBuffer = FromBuffer; - - if (ToAnim) { - led_buffer ToBuffer = RenderAnimationToLedBuffer(System, - PatternArgs, - ToFrame, - ToLayerBuffers, - AssemblyLedBuffer, - Patterns, - Transient, - Context); - - r32 BlendPercent = FadeGroup.FadeElapsed / FadeGroup.FadeDuration; - LedBuffer_Blend(FromBuffer, ToBuffer, &ConsolidatedBuffer, LedBlend_Lerp, (u8*)&BlendPercent); - } - - LedBuffer_Copy(ConsolidatedBuffer, AssemblyLedBuffer); + led_buffer FromBuffer = RenderAnimationToLedBuffer(System, + PatternArgs, + FromFrame, + FromLayerBuffers, + AssemblyLedBuffer, + Patterns, + Transient, + Context); + led_buffer ConsolidatedBuffer = FromBuffer; + + if (ToAnim) { + led_buffer ToBuffer = RenderAnimationToLedBuffer(System, + PatternArgs, + ToFrame, + ToLayerBuffers, + AssemblyLedBuffer, + Patterns, + Transient, + Context); + + r32 BlendPercent = FadeGroup.FadeElapsed / FadeGroup.FadeDuration; + LedBuffer_Blend(FromBuffer, ToBuffer, &ConsolidatedBuffer, LedBlend_Lerp, (u8*)&BlendPercent); } + LedBuffer_Copy(ConsolidatedBuffer, AssemblyLedBuffer); + } + #else + + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System); + animation_frame CurrFrame = AnimationSystem_CalculateAnimationFrame(System, ActiveAnim, Transient); + + for (u32 AssemblyIndex = 0; AssemblyIndex < Assemblies.Count; AssemblyIndex++) + { + assembly Assembly = Assemblies.Values[AssemblyIndex]; + led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); - animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System); - animation_frame CurrFrame = AnimationSystem_CalculateAnimationFrame(System, ActiveAnim, Transient); - - for (u32 AssemblyIndex = 0; AssemblyIndex < Assemblies.Count; AssemblyIndex++) - { - assembly Assembly = Assemblies.Values[AssemblyIndex]; - led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); - - pattern_args PatternArgs = {}; - PatternArgs.Assembly = Assembly; - PatternArgs.Transient = Transient; - PatternArgs.UserData = UserData; - - led_buffer AccBuffer = RenderAnimationToLedBuffer(System, - PatternArgs, - CurrFrame, - LayerBuffers, - AssemblyLedBuffer, - Patterns, - Transient); - LedBuffer_Copy(AccBuffer, AssemblyLedBuffer); - } + pattern_args PatternArgs = {}; + PatternArgs.Assembly = Assembly; + PatternArgs.Transient = Transient; + PatternArgs.UserData = UserData; + led_buffer AccBuffer = RenderAnimationToLedBuffer(System, + PatternArgs, + CurrFrame, + LayerBuffers, + AssemblyLedBuffer, + Patterns, + Transient); + LedBuffer_Copy(AccBuffer, AssemblyLedBuffer); + } + #endif - - System->LastUpdatedFrame = System->CurrentFrame; + + System->LastUpdatedFrame = System->CurrentFrame; } #define FOLDHAUS_ANIMATION_RENDERER_CPP diff --git a/src/app/engine/assembly/foldhaus_assembly.cpp b/src/app/engine/assembly/foldhaus_assembly.cpp index 6e69f4b..0e383f0 100644 --- a/src/app/engine/assembly/foldhaus_assembly.cpp +++ b/src/app/engine/assembly/foldhaus_assembly.cpp @@ -14,35 +14,35 @@ internal assembly_array AssemblyArray_Create(u32 CountMax, gs_memory_arena* Storage) { - assembly_array Result = {0}; - Result.CountMax = CountMax; - Result.Values = PushArray(Storage, assembly, Result.CountMax); - return Result; + assembly_array Result = {0}; + Result.CountMax = CountMax; + Result.Values = PushArray(Storage, assembly, Result.CountMax); + return Result; } internal u32 AssemblyArray_Push(assembly_array* Array, assembly Assembly) { - Assert(Array->Count < Array->CountMax); - u32 Index = Array->Count++; - Array->Values[Index] = Assembly; - Array->Values[Index].AssemblyIndex = Index; - return Index; + Assert(Array->Count < Array->CountMax); + u32 Index = Array->Count++; + Array->Values[Index] = Assembly; + Array->Values[Index].AssemblyIndex = Index; + return Index; } internal assembly* AssemblyArray_Take(assembly_array* Array) { - u32 Index = AssemblyArray_Push(Array, {}); - assembly* Result = Array->Values + Index; - return Result; + u32 Index = AssemblyArray_Push(Array, {}); + assembly* Result = Array->Values + Index; + return Result; } internal void AssemblyArray_RemoveAt(assembly_array* Array, u32 Index) { - u32 LastAssemblyIndex = --Array->Count; - Array->Values[Index] = Array->Values[LastAssemblyIndex]; + u32 LastAssemblyIndex = --Array->Count; + Array->Values[Index] = Array->Values[LastAssemblyIndex]; } typedef bool assembly_array_filter_proc(assembly A); @@ -52,18 +52,18 @@ bool AssemblyFilter_OutputsViaUART(assembly A) { return A.OutputMode == NetworkP internal assembly_array AssemblyArray_Filter(assembly_array Array, assembly_array_filter_proc* Filter, gs_memory_arena* Storage) { - assembly_array Result = AssemblyArray_Create(Array.Count, Storage); - - for (u32 i = 0; i < Array.Count; i++) + assembly_array Result = AssemblyArray_Create(Array.Count, Storage); + + for (u32 i = 0; i < Array.Count; i++) + { + assembly At = Array.Values[i]; + if (Filter(At)) { - assembly At = Array.Values[i]; - if (Filter(At)) - { - AssemblyArray_Push(&Result, At); - } + AssemblyArray_Push(&Result, At); } - - return Result; + } + + return Result; } /////////////////////////// @@ -75,177 +75,177 @@ AssemblyArray_Filter(assembly_array Array, assembly_array_filter_proc* Filter, g internal led_system LedSystem_Create(gs_allocator PlatformMemory, u32 BuffersMax) { - led_system Result = {}; - Result.PlatformMemory = PlatformMemory; - // TODO(Peter): Since we have access to PlatformMemory, just realloc Buffers when we fill it up - Result.BuffersCountMax = BuffersMax; - Result.Buffers = AllocatorAllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax); - return Result; + led_system Result = {}; + Result.PlatformMemory = PlatformMemory; + // TODO(Peter): Since we have access to PlatformMemory, just realloc Buffers when we fill it up + Result.BuffersCountMax = BuffersMax; + Result.Buffers = AllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax, "led system"); + return Result; } internal u32 LedSystemTakeFreeBuffer(led_system* System, u32 LedCount) { - s32 Result = -1; - - if (System->BuffersCount < System->BuffersCountMax) + s32 Result = -1; + + if (System->BuffersCount < System->BuffersCountMax) + { + Result = System->BuffersCount++; + } + else + { + // NOTE(Peter): Look for a buffer that's flagged as empty + for (u32 i = 0; i < System->BuffersCount; i++) { - Result = System->BuffersCount++; + if (System->Buffers[i].LedCount == 0 + && System->Buffers[i].Colors == 0 + && System->Buffers[i].Positions == 0) + { + Result = i; + break; + } } - else - { - // NOTE(Peter): Look for a buffer that's flagged as empty - for (u32 i = 0; i < System->BuffersCount; i++) - { - if (System->Buffers[i].LedCount == 0 - && System->Buffers[i].Colors == 0 - && System->Buffers[i].Positions == 0) - { - Result = i; - break; - } - } - Assert(Result >= 0); // NOTE(Peter): We ran out of room for led buffers - } - - led_buffer* Buffer = &System->Buffers[Result]; - Buffer->LedCount = LedCount; - Buffer->Colors = AllocatorAllocArray(System->PlatformMemory, pixel, Buffer->LedCount); - Buffer->Positions = AllocatorAllocArray(System->PlatformMemory, v4, Buffer->LedCount); - - System->LedsCountTotal += LedCount; - - return (u32)Result; + Assert(Result >= 0); // NOTE(Peter): We ran out of room for led buffers + } + + led_buffer* Buffer = &System->Buffers[Result]; + Buffer->A = MemoryArenaCreate(KB(16),Bytes(8),System->PlatformMemory,0,0,"Led Buffer Arena"); + Buffer->LedCount = LedCount; + Buffer->Colors = PushArray(&Buffer->A, pixel, Buffer->LedCount); + Buffer->Positions = PushArray(&Buffer->A, v4, Buffer->LedCount); + + System->LedsCountTotal += LedCount; + + return (u32)Result; } internal void LedSystemFreeBuffer(led_system* System, u32 BufferIndex) { - Assert(BufferIndex < System->BuffersCountMax); - led_buffer* Buffer = &System->Buffers[BufferIndex]; - AllocatorFreeArray(System->PlatformMemory, Buffer->Colors, pixel, Buffer->LedCount); - AllocatorFreeArray(System->PlatformMemory, Buffer->Positions, v4, Buffer->LedCount); - System->LedsCountTotal -= Buffer->LedCount; - *Buffer = {}; + Assert(BufferIndex < System->BuffersCountMax); + led_buffer* Buffer = &System->Buffers[BufferIndex]; + MemoryArenaFree(&Buffer->A); + System->LedsCountTotal -= Buffer->LedCount; + *Buffer = {}; } internal void LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) { - Assert(Led < Buffer->LedCount); - Buffer->Positions[Led] = Position; + Assert(Led < Buffer->LedCount); + Buffer->Positions[Led] = Position; } internal u32 Assembly_ConstructStrip(assembly* Assembly, led_buffer* LedBuffer, v2_strip* StripAt, strip_gen_data GenData, v4 RootPosition, u32 LedStartIndex, u32 LedLUTStartIndex) { - u32 LedsAdded = 0; - - switch (GenData.Method) + u32 LedsAdded = 0; + + switch (GenData.Method) + { + case StripGeneration_InterpolatePoints: { - case StripGeneration_InterpolatePoints: - { - strip_gen_interpolate_points InterpPoints = GenData.InterpolatePoints; - v4 WS_StripStart = RootPosition + ToV4Point(InterpPoints.StartPosition * Assembly->Scale); - v4 WS_StripEnd = RootPosition + ToV4Point(InterpPoints.EndPosition * Assembly->Scale); - - v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)InterpPoints.LedCount; - for (u32 Step = 0; Step < InterpPoints.LedCount; Step++) - { - s32 LedIndex = LedStartIndex + LedsAdded++; - v4 LedPosition = WS_StripStart + (SingleStep * Step); - LedBufferSetLed(LedBuffer, LedIndex, LedPosition); - StripAt->LedLUT[Step + LedLUTStartIndex] = LedIndex; - } - }break; - - case StripGeneration_Sequence: - { - strip_gen_sequence Sequence = GenData.Sequence; - for (u32 i = 0; i < Sequence.ElementsCount; i++) - { - strip_gen_data SegmentGenData = Sequence.Elements[i]; - LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, SegmentGenData, RootPosition, LedStartIndex + LedsAdded, LedsAdded); - } - }break; - - InvalidDefaultCase; - } + strip_gen_interpolate_points InterpPoints = GenData.InterpolatePoints; + v4 WS_StripStart = RootPosition + ToV4Point(InterpPoints.StartPosition * Assembly->Scale); + v4 WS_StripEnd = RootPosition + ToV4Point(InterpPoints.EndPosition * Assembly->Scale); + + v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)InterpPoints.LedCount; + for (u32 Step = 0; Step < InterpPoints.LedCount; Step++) + { + s32 LedIndex = LedStartIndex + LedsAdded++; + v4 LedPosition = WS_StripStart + (SingleStep * Step); + LedBufferSetLed(LedBuffer, LedIndex, LedPosition); + StripAt->LedLUT[Step + LedLUTStartIndex] = LedIndex; + } + }break; - return LedsAdded; + case StripGeneration_Sequence: + { + strip_gen_sequence Sequence = GenData.Sequence; + for (u32 i = 0; i < Sequence.ElementsCount; i++) + { + strip_gen_data SegmentGenData = Sequence.Elements[i]; + LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, SegmentGenData, RootPosition, LedStartIndex + LedsAdded, LedsAdded); + } + }break; + + InvalidDefaultCase; + } + + return LedsAdded; } internal void ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem) { - Assembly->LedBufferIndex = LedSystemTakeFreeBuffer(LedSystem, Assembly->LedCountTotal); - led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex); + Assembly->LedBufferIndex = LedSystemTakeFreeBuffer(LedSystem, Assembly->LedCountTotal); + led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex); + + v4 RootPosition = ToV4Vec(Assembly->Center); + + // Add Leds + u32 LedsAdded = 0; + for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++) + { + v2_strip* StripAt = &Assembly->Strips[StripIdx]; + StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount); - v4 RootPosition = ToV4Vec(Assembly->Center); - - // Add Leds - u32 LedsAdded = 0; - for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++) - { - v2_strip* StripAt = &Assembly->Strips[StripIdx]; - StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount); - - strip_gen_data GenData = StripAt->GenerationData; - LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, GenData, RootPosition, LedsAdded, 0); - } + strip_gen_data GenData = StripAt->GenerationData; + LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, GenData, RootPosition, LedsAdded, 0); + } } internal assembly* LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, gs_memory_arena* Scratch, context Context, gs_const_string Path, log_buffer* GlobalLog) { - assembly* NewAssembly = 0; + assembly* NewAssembly = 0; + + gs_file AssemblyFile = ReadEntireFile(Context.ThreadContext.FileHandler, Path); + if (FileNoError(AssemblyFile)) + { + gs_string AssemblyFileText = MakeString((char*)AssemblyFile.Memory); - gs_file AssemblyFile = ReadEntireFile(Context.ThreadContext.FileHandler, Path); - if (FileNoError(AssemblyFile)) + s32 IndexOfLastSlash = FindLast(Path, '\\'); + gs_const_string FileName = Substring(Path, IndexOfLastSlash + 1, Path.Length); + + NewAssembly = AssemblyArray_Take(Assemblies); + NewAssembly->Arena = MemoryArenaCreate(MB(4), Bytes(8), Context.ThreadContext.Allocator, 0, 0, "Assembly Arena"); + + parser AssemblyParser = ParseAssemblyFile(NewAssembly, FileName, AssemblyFileText, Scratch); + if (AssemblyParser.Success) { - gs_string AssemblyFileText = MakeString((char*)AssemblyFile.Memory); - - s32 IndexOfLastSlash = FindLast(Path, '\\'); - gs_const_string FileName = Substring(Path, IndexOfLastSlash + 1, Path.Length); - - NewAssembly = AssemblyArray_Take(Assemblies); - NewAssembly->Arena = CreateMemoryArena(Context.ThreadContext.Allocator, "Assembly Arena"); - - parser AssemblyParser = ParseAssemblyFile(NewAssembly, FileName, AssemblyFileText, Scratch); - if (AssemblyParser.Success) - { - ConstructAssemblyFromDefinition(NewAssembly, LedSystem); - } - else - { - FreeMemoryArena(&NewAssembly->Arena); - Assemblies->Count -= 1; - } - - for (parser_error* ErrorAt = AssemblyParser.ErrorsRoot; - ErrorAt != 0; - ErrorAt = ErrorAt->Next) - { - Log_Error(GlobalLogBuffer, ErrorAt->Message.Str); - } - + ConstructAssemblyFromDefinition(NewAssembly, LedSystem); } else { - Log_Error(GlobalLog, "Unable to load assembly file"); + MemoryArenaFree(&NewAssembly->Arena); + Assemblies->Count -= 1; } - return NewAssembly; + for (parser_error* ErrorAt = AssemblyParser.ErrorsRoot; + ErrorAt != 0; + ErrorAt = ErrorAt->Next) + { + Log_Error(GlobalLogBuffer, ErrorAt->Message.Str); + } + + } + else + { + Log_Error(GlobalLog, "Unable to load assembly file"); + } + + return NewAssembly; } internal void UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context) { - Assert(AssemblyIndex < State->Assemblies.Count); - assembly* Assembly = &State->Assemblies.Values[AssemblyIndex]; - LedSystemFreeBuffer(&State->LedSystem, Assembly->LedBufferIndex); - FreeMemoryArena(&Assembly->Arena); - AssemblyArray_RemoveAt(&State->Assemblies, AssemblyIndex); + Assert(AssemblyIndex < State->Assemblies.Count); + assembly* Assembly = &State->Assemblies.Values[AssemblyIndex]; + LedSystemFreeBuffer(&State->LedSystem, Assembly->LedBufferIndex); + MemoryArenaFree(&Assembly->Arena); + AssemblyArray_RemoveAt(&State->Assemblies, AssemblyIndex); } // Querying Assemblies @@ -253,30 +253,30 @@ UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context) internal led_strip_list AssemblyStripsGetWithTagValue(assembly Assembly, gs_const_string TagName, gs_const_string TagValue, gs_memory_arena* Storage) { - led_strip_list Result = {0}; - // TODO(pjs): @Optimization - // We can probably come back here and do this allocation procedurally, or in buckets, or with - // a linked list. But for now, I just want to get this up and running - Result.CountMax = Assembly.StripCount; - Result.StripIndices = PushArray(Storage, u32, Result.CountMax); - - u64 NameHash = HashDJB2ToU32(StringExpand(TagName)); - u64 ValueHash = 0; - if (TagValue.Length > 0) + led_strip_list Result = {0}; + // TODO(pjs): @Optimization + // We can probably come back here and do this allocation procedurally, or in buckets, or with + // a linked list. But for now, I just want to get this up and running + Result.CountMax = Assembly.StripCount; + Result.StripIndices = PushArray(Storage, u32, Result.CountMax); + + u64 NameHash = HashDJB2ToU32(StringExpand(TagName)); + u64 ValueHash = 0; + if (TagValue.Length > 0) + { + ValueHash = HashDJB2ToU32(StringExpand(TagValue)); + } + + for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++) + { + v2_strip StripAt = Assembly.Strips[StripIndex]; + if (AssemblyStrip_HasTagValue(StripAt, NameHash, ValueHash)) { - ValueHash = HashDJB2ToU32(StringExpand(TagValue)); + Result.StripIndices[Result.Count++] = StripIndex; } - - for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++) - { - v2_strip StripAt = Assembly.Strips[StripIndex]; - if (AssemblyStrip_HasTagValue(StripAt, NameHash, ValueHash)) - { - Result.StripIndices[Result.Count++] = StripIndex; - } - } - - return Result; + } + + return Result; } #define FOLDHAUS_ASSEMBLY_CPP diff --git a/src/app/engine/assembly/foldhaus_assembly.h b/src/app/engine/assembly/foldhaus_assembly.h index 7f6ca8b..b1b9db9 100644 --- a/src/app/engine/assembly/foldhaus_assembly.h +++ b/src/app/engine/assembly/foldhaus_assembly.h @@ -7,165 +7,172 @@ enum network_protocol { - NetworkProtocol_SACN, - NetworkProtocol_ArtNet, - NetworkProtocol_UART, - - NetworkProtocol_Count, + NetworkProtocol_SACN, + NetworkProtocol_ArtNet, + NetworkProtocol_UART, + + NetworkProtocol_Count, }; union pixel { - struct - { - u8 R; - u8 G; - u8 B; - }; - u8 Channels[3]; + struct + { + u8 R; + u8 G; + u8 B; + }; + u8 Channels[3]; }; struct led_buffer { - u32 LedCount; - pixel* Colors; - v4* Positions; + // NOTE(PS): This is just a tracking structure, + // that enables allocations for a particular buffer + // to occur all in contiguous memory + // and should not be pushed to after the initial + // allocation + gs_memory_arena A; + + u32 LedCount; + pixel* Colors; + v4* Positions; }; struct led_buffer_range { - u32 First; - u32 OnePastLast; + u32 First; + u32 OnePastLast; }; struct led_system { - gs_allocator PlatformMemory; - - u32 BuffersCountMax; - u32 BuffersCount; - led_buffer* Buffers; - - u32 LedsCountTotal; + gs_allocator PlatformMemory; + + u32 BuffersCountMax; + u32 BuffersCount; + led_buffer* Buffers; + + u32 LedsCountTotal; }; struct v2_tag { - u64 NameHash; - u64 ValueHash; + u64 NameHash; + u64 ValueHash; }; struct strip_sacn_addr { - s32 StartUniverse; - s32 StartChannel; + s32 StartUniverse; + s32 StartChannel; }; struct strip_uart_addr { - u8 Channel; - - gs_string ComPort; - // This may not be used based on the value of the parent - // assembly's NetworkPortMode field + u8 Channel; + + gs_string ComPort; + // This may not be used based on the value of the parent + // assembly's NetworkPortMode field }; enum strip_gen_method { - StripGeneration_InterpolatePoints, - StripGeneration_Sequence, - - StripGeneration_Count, + StripGeneration_InterpolatePoints, + StripGeneration_Sequence, + + StripGeneration_Count, }; typedef struct strip_gen_data strip_gen_data; struct strip_gen_interpolate_points { - v3 StartPosition; - v3 EndPosition; - u32 LedCount; + v3 StartPosition; + v3 EndPosition; + u32 LedCount; }; struct strip_gen_sequence { - strip_gen_data* Elements; - u32 ElementsCount; + strip_gen_data* Elements; + u32 ElementsCount; }; struct strip_gen_data { - strip_gen_method Method; - - strip_gen_interpolate_points InterpolatePoints; - strip_gen_sequence Sequence; + strip_gen_method Method; + + strip_gen_interpolate_points InterpolatePoints; + strip_gen_sequence Sequence; }; struct v2_strip { - s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore - - strip_sacn_addr SACNAddr; - strip_uart_addr UARTAddr; - - strip_gen_data GenerationData; - - u32 LedCount; - u32* LedLUT; - - u32 TagsCount; - v2_tag* Tags; + s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore + + strip_sacn_addr SACNAddr; + strip_uart_addr UARTAddr; + + strip_gen_data GenerationData; + + u32 LedCount; + u32* LedLUT; + + u32 TagsCount; + v2_tag* Tags; }; struct led_strip_list { - u32 Count; - u32 CountMax; - u32* StripIndices; + u32 Count; + u32 CountMax; + u32* StripIndices; }; enum network_port_mode { - // This enum defines the scope which contains what network - // port each address should be sent over. - - NetworkPortMode_GlobalPort, - // GlobalPort means that the port is defined in the assembly structure - - NetworkPortMode_PortPerStrip, - // PortPerStrip means that the address stored in the strip structure - // should be used, and each strip might have a different port - - NetworkPortMode_Count, + // This enum defines the scope which contains what network + // port each address should be sent over. + + NetworkPortMode_GlobalPort, + // GlobalPort means that the port is defined in the assembly structure + + NetworkPortMode_PortPerStrip, + // PortPerStrip means that the address stored in the strip structure + // should be used, and each strip might have a different port + + NetworkPortMode_Count, }; struct assembly { - gs_memory_arena Arena; - - u32 AssemblyIndex; - gs_string Name; - gs_string FilePath; - - r32 Scale; - v3 Center; - v3 MinLedPos, MaxLedPos; - s32 LedCountTotal; - u32 LedBufferIndex; - - u32 StripCount; - v2_strip* Strips; - - network_protocol OutputMode; - network_port_mode NetPortMode; - gs_string UARTComPort; + gs_memory_arena Arena; + + u32 AssemblyIndex; + gs_string Name; + gs_string FilePath; + + r32 Scale; + v3 Center; + v3 MinLedPos, MaxLedPos; + s32 LedCountTotal; + u32 LedBufferIndex; + + u32 StripCount; + v2_strip* Strips; + + network_protocol OutputMode; + network_port_mode NetPortMode; + gs_string UARTComPort; }; struct assembly_array { - u32 CountMax; - u32 Count; - assembly* Values; + u32 CountMax; + u32 Count; + assembly* Values; }; typedef pixel led_blend_proc(pixel A, pixel B, u8* UserData); @@ -173,118 +180,118 @@ typedef pixel led_blend_proc(pixel A, pixel B, u8* UserData); internal led_buffer* LedSystemGetBuffer(led_system* System, u32 Index) { - led_buffer* Result = &System->Buffers[Index]; - return Result; + led_buffer* Result = &System->Buffers[Index]; + return Result; } internal void LedBuffer_ClearToBlack(led_buffer* Buffer) { - for (u32 i = 0; i < Buffer->LedCount; i++) - { - Buffer->Colors[i].R = 0; - Buffer->Colors[i].G = 0; - Buffer->Colors[i].B = 0; - } + for (u32 i = 0; i < Buffer->LedCount; i++) + { + Buffer->Colors[i].R = 0; + Buffer->Colors[i].G = 0; + Buffer->Colors[i].B = 0; + } } internal void LedBuffer_Copy(led_buffer From, led_buffer* To) { - DEBUG_TRACK_FUNCTION; - - Assert(From.LedCount == To->LedCount); - u32 LedCount = To->LedCount; - for (u32 i = 0; i < LedCount; i++) - { - To->Colors[i] = From.Colors[i]; - } + DEBUG_TRACK_FUNCTION; + + Assert(From.LedCount == To->LedCount); + u32 LedCount = To->LedCount; + for (u32 i = 0; i < LedCount; i++) + { + To->Colors[i] = From.Colors[i]; + } } internal void LedBuffer_Blend(led_buffer A, led_buffer B, led_buffer* Dest, led_blend_proc* BlendProc, u8* UserData) { - DEBUG_TRACK_FUNCTION; - - Assert(A.LedCount == B.LedCount); - Assert(Dest->LedCount == A.LedCount); - Assert(BlendProc); - - u32 LedCount = Dest->LedCount; - for (u32 i = 0; i < LedCount; i++) - { - pixel PA = A.Colors[i]; - pixel PB = B.Colors[i]; - Dest->Colors[i] = BlendProc(PA, PB, UserData); - } + DEBUG_TRACK_FUNCTION; + + Assert(A.LedCount == B.LedCount); + Assert(Dest->LedCount == A.LedCount); + Assert(BlendProc); + + u32 LedCount = Dest->LedCount; + for (u32 i = 0; i < LedCount; i++) + { + pixel PA = A.Colors[i]; + pixel PB = B.Colors[i]; + Dest->Colors[i] = BlendProc(PA, PB, UserData); + } } internal led_buffer LedBuffer_CreateCopyCleared (led_buffer Buffer, gs_memory_arena* Arena) { - DEBUG_TRACK_FUNCTION; - - led_buffer Result = {}; - Result.LedCount = Buffer.LedCount; - Result.Positions = Buffer.Positions; - Result.Colors = PushArray(Arena, pixel, Buffer.LedCount); - LedBuffer_ClearToBlack(&Result); - return Result; + DEBUG_TRACK_FUNCTION; + + led_buffer Result = {}; + Result.LedCount = Buffer.LedCount; + Result.Positions = Buffer.Positions; + Result.Colors = PushArray(Arena, pixel, Buffer.LedCount); + LedBuffer_ClearToBlack(&Result); + return Result; } internal u32 StripGenData_CountLeds(strip_gen_data Data) { - u32 Result = 0; - - switch (Data.Method) + u32 Result = 0; + + switch (Data.Method) + { + case StripGeneration_InterpolatePoints: { - case StripGeneration_InterpolatePoints: - { - Result += Data.InterpolatePoints.LedCount; - }break; - - case StripGeneration_Sequence: - { - for (u32 i = 0; i < Data.Sequence.ElementsCount; i++) - { - Result += StripGenData_CountLeds(Data.Sequence.Elements[i]); - } - }break; - - InvalidDefaultCase; - } + Result += Data.InterpolatePoints.LedCount; + }break; - return Result; + case StripGeneration_Sequence: + { + for (u32 i = 0; i < Data.Sequence.ElementsCount; i++) + { + Result += StripGenData_CountLeds(Data.Sequence.Elements[i]); + } + }break; + + InvalidDefaultCase; + } + + return Result; } internal bool AssemblyStrip_HasTagValue(v2_strip Strip, u64 NameHash, u64 ValueHash) { - bool Result = false; - for (u32 i = 0; i < Strip.TagsCount; i++) + bool Result = false; + for (u32 i = 0; i < Strip.TagsCount; i++) + { + v2_tag TagAt = Strip.Tags[i]; + if (TagAt.NameHash == NameHash) { - v2_tag TagAt = Strip.Tags[i]; - if (TagAt.NameHash == NameHash) - { - // NOTE(pjs): We can pass an empty string to the Value parameter, - // and it will match all values of Tag - if (ValueHash == 0 || ValueHash == TagAt.ValueHash) - { - Result = true; - break; - } - } + // NOTE(pjs): We can pass an empty string to the Value parameter, + // and it will match all values of Tag + if (ValueHash == 0 || ValueHash == TagAt.ValueHash) + { + Result = true; + break; + } } - return Result; + } + return Result; } internal bool AssemblyStrip_HasTagValueSLOW(v2_strip Strip, char* Name, char* Value) { - u64 NameHash = HashDJB2ToU32(Name); - u64 ValueHash = HashDJB2ToU32(Value); - return AssemblyStrip_HasTagValue(Strip, NameHash, ValueHash); + u64 NameHash = HashDJB2ToU32(Name); + u64 ValueHash = HashDJB2ToU32(Value); + return AssemblyStrip_HasTagValue(Strip, NameHash, ValueHash); } #define FOLDHAUS_ASSEMBLY_H diff --git a/src/app/engine/foldhaus_addressed_data.h b/src/app/engine/foldhaus_addressed_data.h index 8339b6e..e2db91e 100644 --- a/src/app/engine/foldhaus_addressed_data.h +++ b/src/app/engine/foldhaus_addressed_data.h @@ -11,97 +11,97 @@ enum data_buffer_address_type { - AddressType_NetworkIP, - AddressType_ComPort, - AddressType_Invalid, + AddressType_NetworkIP, + AddressType_ComPort, + AddressType_Invalid, }; struct addressed_data_buffer { - union + union + { + struct { - struct - { - u8* Memory; - u32 MemorySize; - }; - gs_data Data; + u8* Memory; + u32 MemorySize; }; - - data_buffer_address_type AddressType; - - // IP Address - platform_socket_handle SendSocket; - u32 V4SendAddress; - u32 SendPort; - - // COM - gs_const_string ComPort; - - addressed_data_buffer* Next; + gs_data Data; + }; + + data_buffer_address_type AddressType; + + // IP Address + platform_socket_handle SendSocket; + u32 V4SendAddress; + u32 SendPort; + + // COM + gs_const_string ComPort; + + addressed_data_buffer* Next; }; struct addressed_data_buffer_list { - gs_memory_arena* Arena; - addressed_data_buffer* Root; - addressed_data_buffer* Head; + gs_memory_arena* Arena; + addressed_data_buffer* Root; + addressed_data_buffer* Head; }; internal void AddressedDataBufferList_Clear(addressed_data_buffer_list* List) { - List->Root = 0; - List->Head = 0; - ClearArena(List->Arena); + List->Root = 0; + List->Head = 0; + MemoryArenaClear(List->Arena); } internal addressed_data_buffer* AddressedDataBufferList_PushEmpty(addressed_data_buffer_list* List) { - addressed_data_buffer* Result = PushStruct(List->Arena, addressed_data_buffer); - *Result = {0}; - Result->Next = 0; - Result->MemorySize = 0; - Result->Memory = 0; - - SLLPushOrInit(List->Root, List->Head, Result); - - return Result; + addressed_data_buffer* Result = PushStruct(List->Arena, addressed_data_buffer); + *Result = {0}; + Result->Next = 0; + Result->MemorySize = 0; + Result->Memory = 0; + + SLLPushOrInit(List->Root, List->Head, Result); + + return Result; } internal addressed_data_buffer* AddressedDataBufferList_Push(addressed_data_buffer_list* List, u32 BufferSize) { - addressed_data_buffer* Result = AddressedDataBufferList_PushEmpty(List); - Result->MemorySize = BufferSize; - Result->Memory = PushArray(List->Arena, u8, Result->MemorySize); - return Result; + addressed_data_buffer* Result = AddressedDataBufferList_PushEmpty(List); + Result->MemorySize = BufferSize; + Result->Memory = PushArray(List->Arena, u8, Result->MemorySize); + return Result; } internal void AddressedDataBuffer_SetNetworkAddress(addressed_data_buffer* Buffer, platform_socket_handle SendSocket, u32 V4SendAddress, u32 SendPort) { - Buffer->AddressType = AddressType_NetworkIP; - Buffer->SendSocket = SendSocket; - Buffer->V4SendAddress = V4SendAddress; - Buffer->SendPort = SendPort; + Buffer->AddressType = AddressType_NetworkIP; + Buffer->SendSocket = SendSocket; + Buffer->V4SendAddress = V4SendAddress; + Buffer->SendPort = SendPort; } internal void AddressedDataBuffer_SetCOMPort(addressed_data_buffer* Buffer, gs_const_string ComPort) { - Buffer->AddressType = AddressType_ComPort; - Buffer->ComPort = ComPort; + Buffer->AddressType = AddressType_ComPort; + Buffer->ComPort = ComPort; } internal addressed_data_buffer_list AddressedDataBufferList_Create(gs_thread_context TC) { - addressed_data_buffer_list Result = {}; - Result.Arena = AllocatorAllocStruct(TC.Allocator, gs_memory_arena); - *Result.Arena = CreateMemoryArena(TC.Allocator, "Addressed Data Buffer List Arena"); - return Result; + addressed_data_buffer_list Result = {}; + Result.Arena = AllocStruct(TC.Allocator, gs_memory_arena, "Addressed Data"); + *Result.Arena = MemoryArenaCreate(KB(256), Bytes(8), TC.Allocator, 0, 0, "Addressed Data Buffer List Arena"); + return Result; } #define FOLDHAUS_ADDRESSED_DATA_H diff --git a/src/app/engine/foldhaus_log.h b/src/app/engine/foldhaus_log.h index 8472701..3d538b2 100644 --- a/src/app/engine/foldhaus_log.h +++ b/src/app/engine/foldhaus_log.h @@ -5,79 +5,84 @@ enum log_entry_type { - LogEntry_Message, - LogEntry_Error, + LogEntry_Message, + LogEntry_Error, }; struct log_entry { - log_entry_type Type; - gs_string String; + log_entry_type Type; + gs_string String; }; struct log_buffer { - gs_allocator Allocator; - - u64 EntriesCount; - u64 NextEntry; - log_entry* Entries; + gs_memory_arena* Arena; + + u64 EntriesCount; + u64 NextEntry; + log_entry* Entries; }; struct log_buffer_iter { - log_buffer* Buffer; - u64 Start; - u64 IndexAt; - log_entry* At; + log_buffer* Buffer; + u64 Start; + u64 IndexAt; + log_entry* At; }; internal log_buffer -Log_Init(gs_allocator Allocator, u64 Count) +Log_Init(gs_memory_arena* A, u64 Count) { - log_buffer Result = {}; - Result.Allocator = Allocator; - Result.EntriesCount = Count; - Result.Entries = AllocatorAllocArray(Allocator, log_entry, Result.EntriesCount); - - for (u32 i = 0; i < Result.EntriesCount; i++) - { - Result.Entries[i].String = AllocatorAllocString(Allocator, 512); - } - - return Result; + log_buffer Result = {}; + Result.Arena = A; + Result.EntriesCount = Count; + Result.Entries = PushArray(A, log_entry, Result.EntriesCount); + + u64 LogStringLength = 512; + u64 LogStringBufferSize = LogStringLength * Result.EntriesCount; + char* LogStringBuffer = PushArray(A, char, LogStringBufferSize); + char* LogStringBufferAt = LogStringBuffer; + for (u32 i = 0; i < Result.EntriesCount; i++) + { + Result.Entries[i].String = MakeString(LogStringBufferAt, 0, LogStringLength); + LogStringBufferAt += LogStringLength; + } + + return Result; } internal u64 Log_GetNextIndex(log_buffer Log, u64 At) { - u64 Result = At + 1; - if (Result >= Log.EntriesCount) - { - Result = 0; - } - return Result; + u64 Result = At + 1; + if (Result >= Log.EntriesCount) + { + Result = 0; + } + return Result; } internal log_entry* Log_TakeNextEntry(log_buffer* Log) { - log_entry* Result = Log->Entries + Log->NextEntry; - Log->NextEntry = Log_GetNextIndex(*Log, Log->NextEntry); - return Result; + log_entry* Result = Log->Entries + Log->NextEntry; + Log->NextEntry = Log_GetNextIndex(*Log, Log->NextEntry); + return Result; } internal void Log_PrintFVarArgs(log_buffer* Log, log_entry_type Type, char* Format, va_list Args) { - log_entry* NextEntry = Log_TakeNextEntry(Log); - NextEntry->String.Length = 0; - NextEntry->Type = Type; - PrintFArgsList(&NextEntry->String, Format, Args); - NullTerminate(&NextEntry->String); - + log_entry* NextEntry = Log_TakeNextEntry(Log); + NextEntry->String.Length = 0; + NextEntry->Type = Type; + PrintFArgsList(&NextEntry->String, Format, Args); + NullTerminate(&NextEntry->String); + #if DEBUG - OutputDebugStringA(NextEntry->String.Str); + OutputDebugStringA(NextEntry->String.Str); #endif } @@ -86,36 +91,36 @@ Log_PrintFVarArgs(log_buffer* Log, log_entry_type Type, char* Format, va_list Ar internal void Log_PrintF(log_buffer* Log, log_entry_type Type, char* Format, ...) { - va_list Args; - va_start(Args, Format); - Log_PrintFVarArgs(Log, Type, Format, Args); - va_end(Args); + va_list Args; + va_start(Args, Format); + Log_PrintFVarArgs(Log, Type, Format, Args); + va_end(Args); } internal log_buffer_iter Log_GetIter(log_buffer* Buffer) { - log_buffer_iter Result = {}; - Result.Buffer = Buffer; - Result.Start = Buffer->NextEntry; - Result.IndexAt = Result.Start; - Result.At = Result.Buffer->Entries + Result.IndexAt; - return Result; + log_buffer_iter Result = {}; + Result.Buffer = Buffer; + Result.Start = Buffer->NextEntry; + Result.IndexAt = Result.Start; + Result.At = Result.Buffer->Entries + Result.IndexAt; + return Result; } internal bool LogIter_CanAdvance(log_buffer_iter Iter) { - u64 Next = Log_GetNextIndex(*Iter.Buffer, Iter.IndexAt); - bool Result = Next != Iter.Start; - return Result; + u64 Next = Log_GetNextIndex(*Iter.Buffer, Iter.IndexAt); + bool Result = Next != Iter.Start; + return Result; } internal void LogIter_Advance(log_buffer_iter* Iter) { - Iter->IndexAt = Log_GetNextIndex(*Iter->Buffer, Iter->IndexAt); - Iter->At = Iter->Buffer->Entries + Iter->IndexAt; + Iter->IndexAt = Log_GetNextIndex(*Iter->Buffer, Iter->IndexAt); + Iter->At = Iter->Buffer->Entries + Iter->IndexAt; } #endif //FOLDHAUS_LOG_H diff --git a/src/app/engine/uart/foldhaus_uart.cpp b/src/app/engine/uart/foldhaus_uart.cpp index f18360f..b6ea3fb 100644 --- a/src/app/engine/uart/foldhaus_uart.cpp +++ b/src/app/engine/uart/foldhaus_uart.cpp @@ -9,163 +9,163 @@ internal void UART_SetChannelBuffer_Create(gs_memory_cursor* WriteCursor, uart_channel ChannelSettings, v2_strip Strip, led_buffer LedBuffer) { - // NOTE(pjs): This is just here because the information is duplicated and I want to be sure - // to catch the error where they are different - Assert(ChannelSettings.PixelsCount == Strip.LedCount); + // NOTE(pjs): This is just here because the information is duplicated and I want to be sure + // to catch the error where they are different + Assert(ChannelSettings.PixelsCount == Strip.LedCount); + + uart_header* Header = MemoryCursorPushStruct(WriteCursor, uart_header); + UART_FillHeader(Header, Strip.UARTAddr.Channel, UART_SET_CHANNEL_WS2812); + + uart_channel* Channel = MemoryCursorPushStruct(WriteCursor, uart_channel); + *Channel = ChannelSettings; + + for (u32 i = 0; i < Channel->PixelsCount; i++) + { + u32 LedIndex = Strip.LedLUT[i]; + pixel Color = LedBuffer.Colors[LedIndex]; - uart_header* Header = PushStructOnCursor(WriteCursor, uart_header); - UART_FillHeader(Header, Strip.UARTAddr.Channel, UART_SET_CHANNEL_WS2812); + u8* OutputPixel = MemoryCursorPushArray(WriteCursor, u8, 3); - uart_channel* Channel = PushStructOnCursor(WriteCursor, uart_channel); - *Channel = ChannelSettings; - - for (u32 i = 0; i < Channel->PixelsCount; i++) - { - u32 LedIndex = Strip.LedLUT[i]; - pixel Color = LedBuffer.Colors[LedIndex]; - - u8* OutputPixel = PushArrayOnCursor(WriteCursor, u8, 3); - - // TODO(pjs): Use the Output mask + // TODO(pjs): Use the Output mask #if 1 - OutputPixel[0] = Color.R; - OutputPixel[1] = Color.G; - OutputPixel[2] = Color.B; + OutputPixel[0] = Color.R; + OutputPixel[1] = Color.G; + OutputPixel[2] = Color.B; #else - OutputPixel[0] = 255; - OutputPixel[1] = 255; - OutputPixel[2] = 255; + OutputPixel[0] = 255; + OutputPixel[1] = 255; + OutputPixel[2] = 255; #endif - if (Channel->ElementsCount == 4) - { - // TODO(pjs): Calculate white from the RGB components? - // Generally we just need a good way to handle the white channel, - // both in the renderer and in output - - //OutputPixel[Channel->WhiteIndex] = Color.W; - } + if (Channel->ElementsCount == 4) + { + // TODO(pjs): Calculate white from the RGB components? + // Generally we just need a good way to handle the white channel, + // both in the renderer and in output + + //OutputPixel[Channel->WhiteIndex] = Color.W; } - - uart_footer* Footer = PushStructOnCursor(WriteCursor, uart_footer); - UART_FillFooter(Footer, (u8*)Header); + } + + uart_footer* Footer = MemoryCursorPushStruct(WriteCursor, uart_footer); + UART_FillFooter(Footer, (u8*)Header); } internal void UART_DrawAll_Create(gs_memory_cursor* WriteCursor) { - uart_header* Header = PushStructOnCursor(WriteCursor, uart_header); - UART_FillHeader(Header, 1, UART_DRAW_ALL); - - uart_footer* Footer = PushStructOnCursor(WriteCursor, uart_footer); - UART_FillFooter(Footer, (u8*)Header); + uart_header* Header = MemoryCursorPushStruct(WriteCursor, uart_header); + UART_FillHeader(Header, 1, UART_DRAW_ALL); + + uart_footer* Footer = MemoryCursorPushStruct(WriteCursor, uart_footer); + UART_FillFooter(Footer, (u8*)Header); } internal void UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem, gs_memory_arena* Transient) { - uart_channel ChannelSettings = {0}; - ChannelSettings.ElementsCount = 3; - ChannelSettings.ColorPackingOrder = 36; + uart_channel ChannelSettings = {0}; + ChannelSettings.ElementsCount = 3; + ChannelSettings.ColorPackingOrder = 36; + + // NOTE(pjs): This is the minimum size of every UART message. SetChannelBuffer messages will + // be bigger than this, but their size is based on the number of pixels in each channel + u32 MessageBaseSize = UART_MESSAGE_MIN_SIZE; + + for (u32 AssemblyIdx = 0; AssemblyIdx < Assemblies.Count; AssemblyIdx++) + { + assembly Assembly = Assemblies.Values[AssemblyIdx]; + led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); - // NOTE(pjs): This is the minimum size of every UART message. SetChannelBuffer messages will - // be bigger than this, but their size is based on the number of pixels in each channel - u32 MessageBaseSize = UART_MESSAGE_MIN_SIZE; - - for (u32 AssemblyIdx = 0; AssemblyIdx < Assemblies.Count; AssemblyIdx++) + struct strips_to_data_buffer { - assembly Assembly = Assemblies.Values[AssemblyIdx]; - led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); - - struct strips_to_data_buffer + gs_const_string ComPort; + + u32* StripIndices; + u32 StripIndicesCount; + u32 StripIndicesCountMax; + + u64 LedCount; + + u8** ChannelsStart; + + strips_to_data_buffer* Next; + }; + + u32 BuffersNeededCount = 0; + strips_to_data_buffer* BuffersNeededHead = 0; + strips_to_data_buffer* BuffersNeededTail = 0; + + for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) + { + v2_strip StripAt = Assembly.Strips[StripIdx]; + + // If there is a buffer for this com port already created + // we use that + strips_to_data_buffer* BufferSelected = 0; + for (strips_to_data_buffer* At = BuffersNeededHead; + At!= 0; + At = At->Next) + { + if (StringsEqual(At->ComPort, StripAt.UARTAddr.ComPort.ConstString)) { - gs_const_string ComPort; - - u32* StripIndices; - u32 StripIndicesCount; - u32 StripIndicesCountMax; - - u64 LedCount; - - u8** ChannelsStart; - - strips_to_data_buffer* Next; - }; - - u32 BuffersNeededCount = 0; - strips_to_data_buffer* BuffersNeededHead = 0; - strips_to_data_buffer* BuffersNeededTail = 0; - - for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) - { - v2_strip StripAt = Assembly.Strips[StripIdx]; - - // If there is a buffer for this com port already created - // we use that - strips_to_data_buffer* BufferSelected = 0; - for (strips_to_data_buffer* At = BuffersNeededHead; - At!= 0; - At = At->Next) - { - if (StringsEqual(At->ComPort, StripAt.UARTAddr.ComPort.ConstString)) - { - BufferSelected = At; - break; - } - } - - // if no existing buffer for this com port - // create a new one - if (!BufferSelected) - { - BufferSelected = PushStruct(Transient, strips_to_data_buffer); - *BufferSelected = {}; - BufferSelected->ComPort = StripAt.UARTAddr.ComPort.ConstString; - // we don't know at this point how many indices per - // com port so just make enough room to fit all the strips - // if necessary - BufferSelected->StripIndicesCountMax = Assembly.StripCount; - BufferSelected->StripIndices = PushArray(Transient, u32, BufferSelected->StripIndicesCountMax); - BufferSelected->LedCount = 0; - BufferSelected->Next = 0; - - SLLPushOrInit(BuffersNeededHead, BuffersNeededTail, BufferSelected); - BuffersNeededCount += 1; - } - - Assert(BufferSelected->StripIndicesCount < BufferSelected->StripIndicesCountMax); - u32 Index = BufferSelected->StripIndicesCount++; - BufferSelected->StripIndices[Index] = StripIdx; - BufferSelected->LedCount += StripAt.LedCount; + BufferSelected = At; + break; } + } + + // if no existing buffer for this com port + // create a new one + if (!BufferSelected) + { + BufferSelected = PushStruct(Transient, strips_to_data_buffer); + *BufferSelected = {}; + BufferSelected->ComPort = StripAt.UARTAddr.ComPort.ConstString; + // we don't know at this point how many indices per + // com port so just make enough room to fit all the strips + // if necessary + BufferSelected->StripIndicesCountMax = Assembly.StripCount; + BufferSelected->StripIndices = PushArray(Transient, u32, BufferSelected->StripIndicesCountMax); + BufferSelected->LedCount = 0; + BufferSelected->Next = 0; - for (strips_to_data_buffer* At = BuffersNeededHead; - At!= 0; - At = At->Next) - { - u32 TotalBufferSize = MessageBaseSize * Assembly.StripCount; // SetChannelBuffer messages - TotalBufferSize += MessageBaseSize; // DrawAll message - TotalBufferSize += ChannelSettings.ElementsCount * At->LedCount; // pixels * channels per pixel - - At->ChannelsStart = PushArray(Transient, u8*, At->StripIndicesCount); - - addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize); - gs_const_string ComPort = At->ComPort; - AddressedDataBuffer_SetCOMPort(Buffer, ComPort); - - gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); - - for (u32 i = 0; i < At->StripIndicesCount; i++) - { - u32 StripIdx = At->StripIndices[i]; - v2_strip StripAt = Assembly.Strips[StripIdx]; - - ChannelSettings.PixelsCount = StripAt.LedCount; - UART_SetChannelBuffer_Create(&WriteCursor, ChannelSettings, StripAt, *LedBuffer); - } - - UART_DrawAll_Create(&WriteCursor); - } + SLLPushOrInit(BuffersNeededHead, BuffersNeededTail, BufferSelected); + BuffersNeededCount += 1; + } + + Assert(BufferSelected->StripIndicesCount < BufferSelected->StripIndicesCountMax); + u32 Index = BufferSelected->StripIndicesCount++; + BufferSelected->StripIndices[Index] = StripIdx; + BufferSelected->LedCount += StripAt.LedCount; } + + for (strips_to_data_buffer* At = BuffersNeededHead; + At!= 0; + At = At->Next) + { + u32 TotalBufferSize = MessageBaseSize * Assembly.StripCount; // SetChannelBuffer messages + TotalBufferSize += MessageBaseSize; // DrawAll message + TotalBufferSize += ChannelSettings.ElementsCount * At->LedCount; // pixels * channels per pixel + + At->ChannelsStart = PushArray(Transient, u8*, At->StripIndicesCount); + + addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize); + gs_const_string ComPort = At->ComPort; + AddressedDataBuffer_SetCOMPort(Buffer, ComPort); + + gs_memory_cursor WriteCursor = MemoryCursorCreate(Buffer->Memory, Buffer->MemorySize); + + for (u32 i = 0; i < At->StripIndicesCount; i++) + { + u32 StripIdx = At->StripIndices[i]; + v2_strip StripAt = Assembly.Strips[StripIdx]; + + ChannelSettings.PixelsCount = StripAt.LedCount; + UART_SetChannelBuffer_Create(&WriteCursor, ChannelSettings, StripAt, *LedBuffer); + } + + UART_DrawAll_Create(&WriteCursor); + } + } } diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 9b37512..94d8073 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -10,190 +10,190 @@ RELOAD_STATIC_DATA(ReloadStaticData) { - GlobalDebugServices = DebugServices; - GlobalLogBuffer = LogBuffer; - if (AppReady) + GlobalDebugServices = DebugServices; + GlobalLogBuffer = LogBuffer; + if (AppReady) + { + app_state* State = (app_state*)Context.MemoryBase; + State->PanelSystem.PanelDefs = GlobalPanelDefs; + State->PanelSystem.PanelDefsCount = GlobalPanelDefsCount; + + gs_data UserData = State->UserSpaceDesc.UserData; + State->UserSpaceDesc = BlumenLumen_UserSpaceCreate(); + if (UserData.Memory && !State->UserSpaceDesc.UserData.Memory) { - app_state* State = (app_state*)Context.MemoryBase; - State->PanelSystem.PanelDefs = GlobalPanelDefs; - State->PanelSystem.PanelDefsCount = GlobalPanelDefsCount; - - gs_data UserData = State->UserSpaceDesc.UserData; - State->UserSpaceDesc = BlumenLumen_UserSpaceCreate(); - if (UserData.Memory && !State->UserSpaceDesc.UserData.Memory) - { - State->UserSpaceDesc.UserData = UserData; - } - US_LoadPatterns(&State->UserSpaceDesc, State, Context); + State->UserSpaceDesc.UserData = UserData; } + US_LoadPatterns(&State->UserSpaceDesc, State, Context); + } } INITIALIZE_APPLICATION(InitializeApplication) { - Context->MemorySize = sizeof(app_state); - Context->MemoryBase = AllocatorAlloc(Context->ThreadContext.Allocator, Context->MemorySize).Memory; - app_state* State = (app_state*)Context->MemoryBase; - *State = {}; + Context->MemorySize = sizeof(app_state); + Context->MemoryBase = Alloc(Context->ThreadContext.Allocator, Context->MemorySize, "Memory Base"); + app_state* State = (app_state*)Context->MemoryBase; + *State = {}; + + State->Permanent = MemoryArenaCreate(MB(4), Bytes(8), Context->ThreadContext.Allocator,0, 0, "Permanent"); + State->Transient = Context->ThreadContext.Transient; + State->Assemblies = AssemblyArray_Create(8, &State->Permanent); + + State->CommandQueue = CommandQueue_Create(&State->Permanent, 32); + + animation_system_desc AnimSysDesc = {}; + AnimSysDesc.Storage = &State->Permanent; + AnimSysDesc.AnimArrayCount = 32; + AnimSysDesc.SecondsPerFrame = 1.0f / 24.0f; + State->AnimationSystem = AnimationSystem_Init(AnimSysDesc); + + if (!Context->Headless) + { + interface_config IConfig = {0}; + IConfig.FontSize = 14; + IConfig.PanelBG = v4{ .3f, .3f, .3f, 1.f }; + IConfig.ButtonColor_Inactive = BlackV4; + IConfig.ButtonColor_Active = v4{ .1f, .1f, .1f, 1.f }; + IConfig.ButtonColor_Selected = v4{ .3f, .3f, .3f, 1.f }; + IConfig.TextColor = WhiteV4; + IConfig.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; + IConfig.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; + IConfig.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; + IConfig.ListBGSelected = v4{ .44f, .44f, .44f, 1.f }; + IConfig.Margin = v2{5, 5}; + State->Interface = ui_InterfaceCreate(*Context, IConfig, &State->Permanent); - State->Permanent = CreateMemoryArena(Context->ThreadContext.Allocator, "Permanent"); - State->Transient = Context->ThreadContext.Transient; - State->Assemblies = AssemblyArray_Create(8, &State->Permanent); + PanelSystem_Init(&State->PanelSystem, GlobalPanelDefs, GlobalPanelDefsCount, &State->Permanent); - State->CommandQueue = CommandQueue_Create(&State->Permanent, 32); + } + + State->SACN = SACN_Initialize(*Context); + + State->LedSystem = LedSystem_Create(Context->ThreadContext.Allocator, 128); + State->AssemblyDebugState = AssemblyDebug_Create(&State->Permanent); + State->AssemblyDebugState.Brightness = 255; + State->AssemblyDebugState.Override = ADS_Override_None; + + State->Modes = OperationModeSystemInit(&State->Permanent, Context->ThreadContext); + + ReloadStaticData(*Context, GlobalDebugServices, GlobalLogBuffer, true); + US_CustomInit(&State->UserSpaceDesc, State, *Context); + + if (!Context->Headless) + { + // NOTE(pjs): This just sets up the default panel layout + panel* RootPanel = PanelSystem_PushPanel(&State->PanelSystem, PanelType_SculptureView, State, *Context); + SplitPanel(RootPanel, .25f, PanelSplit_Horizontal, &State->PanelSystem, State, *Context); - animation_system_desc AnimSysDesc = {}; - AnimSysDesc.Storage = &State->Permanent; - AnimSysDesc.AnimArrayCount = 32; - AnimSysDesc.SecondsPerFrame = 1.0f / 24.0f; - State->AnimationSystem = AnimationSystem_Init(AnimSysDesc); + panel* AnimPanel = RootPanel->Bottom; + Panel_SetType(AnimPanel, &State->PanelSystem, PanelType_AnimationTimeline, State, *Context); - if (!Context->Headless) - { - interface_config IConfig = {0}; - IConfig.FontSize = 14; - IConfig.PanelBG = v4{ .3f, .3f, .3f, 1.f }; - IConfig.ButtonColor_Inactive = BlackV4; - IConfig.ButtonColor_Active = v4{ .1f, .1f, .1f, 1.f }; - IConfig.ButtonColor_Selected = v4{ .3f, .3f, .3f, 1.f }; - IConfig.TextColor = WhiteV4; - IConfig.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; - IConfig.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; - IConfig.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; - IConfig.ListBGSelected = v4{ .44f, .44f, .44f, 1.f }; - IConfig.Margin = v2{5, 5}; - State->Interface = ui_InterfaceCreate(*Context, IConfig, &State->Permanent); - - PanelSystem_Init(&State->PanelSystem, GlobalPanelDefs, GlobalPanelDefsCount, &State->Permanent); - - } + panel* TopPanel = RootPanel->Top; + SplitPanel(TopPanel, .5f, PanelSplit_Vertical, &State->PanelSystem, State, *Context); - State->SACN = SACN_Initialize(*Context); + panel* LeftPanel = TopPanel->Left; + SplitPanel(LeftPanel, .5f, PanelSplit_Vertical, &State->PanelSystem, State, *Context); - State->LedSystem = LedSystem_Create(Context->ThreadContext.Allocator, 128); - State->AssemblyDebugState = AssemblyDebug_Create(&State->Permanent); - State->AssemblyDebugState.Brightness = 255; - State->AssemblyDebugState.Override = ADS_Override_None; + panel* Profiler = LeftPanel->Right; + Panel_SetType(Profiler, &State->PanelSystem, PanelType_MessageLog, State, *Context); - State->Modes = OperationModeSystemInit(&State->Permanent, Context->ThreadContext); + panel* Hierarchy = LeftPanel->Left; + Panel_SetType(Hierarchy, &State->PanelSystem, PanelType_AssemblyDebug, State, *Context); - ReloadStaticData(*Context, GlobalDebugServices, GlobalLogBuffer, true); - US_CustomInit(&State->UserSpaceDesc, State, *Context); - - if (!Context->Headless) - { - // NOTE(pjs): This just sets up the default panel layout - panel* RootPanel = PanelSystem_PushPanel(&State->PanelSystem, PanelType_SculptureView, State, *Context); - SplitPanel(RootPanel, .25f, PanelSplit_Horizontal, &State->PanelSystem, State, *Context); - - panel* AnimPanel = RootPanel->Bottom; - Panel_SetType(AnimPanel, &State->PanelSystem, PanelType_AnimationTimeline, State, *Context); - - panel* TopPanel = RootPanel->Top; - SplitPanel(TopPanel, .5f, PanelSplit_Vertical, &State->PanelSystem, State, *Context); - - panel* LeftPanel = TopPanel->Left; - SplitPanel(LeftPanel, .5f, PanelSplit_Vertical, &State->PanelSystem, State, *Context); - - panel* Profiler = LeftPanel->Right; - Panel_SetType(Profiler, &State->PanelSystem, PanelType_MessageLog, State, *Context); - - panel* Hierarchy = LeftPanel->Left; - Panel_SetType(Hierarchy, &State->PanelSystem, PanelType_AssemblyDebug, State, *Context); - - } - - State->RunEditor = !Context->Headless; + } + + State->RunEditor = !Context->Headless; } internal void BuildAssemblyData (app_state* State, context Context, addressed_data_buffer_list* OutputData) { - + #define SEND_DATA #ifdef SEND_DATA - // NOTE(pjs): Building data buffers to be sent out to the sculpture - // This array is used on the platform side to actually send the information - assembly_array SACNAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaSACN, State->Transient); - assembly_array UARTAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaUART, State->Transient); - SACN_BuildOutputData(&State->SACN, OutputData, SACNAssemblies, &State->LedSystem); - UART_BuildOutputData(OutputData, UARTAssemblies, &State->LedSystem, State->Transient); + // NOTE(pjs): Building data buffers to be sent out to the sculpture + // This array is used on the platform side to actually send the information + assembly_array SACNAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaSACN, State->Transient); + assembly_array UARTAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaUART, State->Transient); + SACN_BuildOutputData(&State->SACN, OutputData, SACNAssemblies, &State->LedSystem); + UART_BuildOutputData(OutputData, UARTAssemblies, &State->LedSystem, State->Transient); #endif } UPDATE_AND_RENDER(UpdateAndRender) { - DEBUG_TRACK_FUNCTION; - app_state* State = (app_state*)Context->MemoryBase; - - // NOTE(Peter): We do this at the beginning because all the render commands are stored in Transient, - // and need to persist beyond the end of the UpdateAndRender call. In the release version, we won't - // zero the Transient arena when we clear it so it wouldn't be a problem, but it is technically - // incorrect to clear the arena, and then access the memory later. - ClearArena(State->Transient); + DEBUG_TRACK_FUNCTION; + app_state* State = (app_state*)Context->MemoryBase; + + // NOTE(Peter): We do this at the beginning because all the render commands are stored in Transient, + // and need to persist beyond the end of the UpdateAndRender call. In the release version, we won't + // zero the Transient arena when we clear it so it wouldn't be a problem, but it is technically + // incorrect to clear the arena, and then access the memory later. + MemoryArenaClear(State->Transient); + Assert(State->UserSpaceDesc.UserData.Memory != 0); + + if (State->RunEditor) + { + Editor_Update(State, Context, InputQueue); + } + + AnimationSystem_Update(&State->AnimationSystem, Context->DeltaTime); + if (AnimationSystem_NeedsRender(State->AnimationSystem)) + { Assert(State->UserSpaceDesc.UserData.Memory != 0); - - if (State->RunEditor) + AnimationSystem_RenderToLedBuffers(&State->AnimationSystem, + State->Assemblies, + &State->LedSystem, + State->Patterns, + State->Transient, + *Context, + State->UserSpaceDesc.UserData.Memory); + } + + Assert(State->UserSpaceDesc.UserData.Memory != 0); + US_CustomUpdate(&State->UserSpaceDesc, State, Context); + Assert(State->UserSpaceDesc.UserData.Memory != 0); + + AssemblyDebug_OverrideOutput(State->AssemblyDebugState, + State->Assemblies, + State->LedSystem); + + if (State->RunEditor) + { + Editor_Render(State, Context, RenderBuffer); + } + ResetWorkQueue(Context->GeneralWorkQueue); + + Assert(State->UserSpaceDesc.UserData.Memory != 0); + BuildAssemblyData(State, *Context, OutputData); + + // NOTE(PS): We introduced this in order to test some things on the + // blumen lumen circuit boards, to see if they were getting out + // of sync + if (State->SendEmptyPackets) { + for (addressed_data_buffer* At = OutputData->Root; + At != 0; + At = At->Next) { - Editor_Update(State, Context, InputQueue); - } - - AnimationSystem_Update(&State->AnimationSystem, Context->DeltaTime); - if (AnimationSystem_NeedsRender(State->AnimationSystem)) - { - Assert(State->UserSpaceDesc.UserData.Memory != 0); - AnimationSystem_RenderToLedBuffers(&State->AnimationSystem, - State->Assemblies, - &State->LedSystem, - State->Patterns, - State->Transient, - *Context, - State->UserSpaceDesc.UserData.Memory); - } - - Assert(State->UserSpaceDesc.UserData.Memory != 0); - US_CustomUpdate(&State->UserSpaceDesc, State, Context); - Assert(State->UserSpaceDesc.UserData.Memory != 0); - - AssemblyDebug_OverrideOutput(State->AssemblyDebugState, - State->Assemblies, - State->LedSystem); - - if (State->RunEditor) - { - Editor_Render(State, Context, RenderBuffer); - } - ResetWorkQueue(Context->GeneralWorkQueue); - - Assert(State->UserSpaceDesc.UserData.Memory != 0); - BuildAssemblyData(State, *Context, OutputData); - - // NOTE(PS): We introduced this in order to test some things on the - // blumen lumen circuit boards, to see if they were getting out - // of sync - if (State->SendEmptyPackets) { - for (addressed_data_buffer* At = OutputData->Root; - At != 0; - At = At->Next) - { - ZeroMemoryBlock(At->Memory, At->MemorySize); - } + ZeroMemoryBlock(At->Memory, At->MemorySize); } + } } CLEANUP_APPLICATION(CleanupApplication) { - app_state* State = (app_state*)Context.MemoryBase; - - for (u32 i = 0; i < State->Assemblies.Count; i++) - { - assembly Assembly = State->Assemblies.Values[i]; - led_buffer LedBuffer = State->LedSystem.Buffers[Assembly.LedBufferIndex]; - AssemblyDebug_OverrideWithColor(Assembly, LedBuffer, pixel{0, 0, 0}); - } - BuildAssemblyData(State, Context, OutputData); - - US_CustomCleanup(&State->UserSpaceDesc, State, Context); - SACN_Cleanup(&State->SACN, Context); + app_state* State = (app_state*)Context.MemoryBase; + + for (u32 i = 0; i < State->Assemblies.Count; i++) + { + assembly Assembly = State->Assemblies.Values[i]; + led_buffer LedBuffer = State->LedSystem.Buffers[Assembly.LedBufferIndex]; + AssemblyDebug_OverrideWithColor(Assembly, LedBuffer, pixel{0, 0, 0}); + } + BuildAssemblyData(State, Context, OutputData); + + US_CustomCleanup(&State->UserSpaceDesc, State, Context); + SACN_Cleanup(&State->SACN, Context); } #define FOLDHAUS_APP_CPP diff --git a/src/app/foldhaus_debug.h b/src/app/foldhaus_debug.h index 00a494c..8a66201 100644 --- a/src/app/foldhaus_debug.h +++ b/src/app/foldhaus_debug.h @@ -11,71 +11,71 @@ #define SCOPE_NAME_LENGTH 256 struct scope_record { - u32 NameHash; - s64 StartCycles; - s64 EndCycles; - s32 CallDepth; + u32 NameHash; + s64 StartCycles; + s64 EndCycles; + s32 CallDepth; }; struct collated_scope_record { - u32 NameHash; - s64 TotalCycles; - s32 CallCount; - - r32 PercentFrameTime; - r32 TotalSeconds; - - r32 AverageSecondsPerCall; + u32 NameHash; + s64 TotalCycles; + s32 CallCount; + + r32 PercentFrameTime; + r32 TotalSeconds; + + r32 AverageSecondsPerCall; }; #define SCOPE_NAME_BUFFER_LENGTH 128 struct scope_name { - u32 Hash; - gs_string Name; - char Buffer[SCOPE_NAME_BUFFER_LENGTH]; + u32 Hash; + gs_string Name; + char Buffer[SCOPE_NAME_BUFFER_LENGTH]; }; struct debug_scope_record_list { - s32 ThreadId; - s32 Max; - s32 Count; - scope_record* Calls; - - s32 CurrentScopeCallDepth; + s32 ThreadId; + s32 Max; + s32 Count; + scope_record* Calls; + + s32 CurrentScopeCallDepth; }; #define DEBUG_FRAME_GROW_SIZE 8102 struct debug_frame { - s64 FrameStartCycles; - s64 FrameEndCycles; - - s32 ScopeNamesMax; - s32 ScopeNamesCount; - scope_name* ScopeNamesHash; - - s32 ThreadCount; - debug_scope_record_list* ThreadCalls; - - s32 CollatedScopesMax; - collated_scope_record* CollatedScopes; + s64 FrameStartCycles; + s64 FrameEndCycles; + + s32 ScopeNamesMax; + s32 ScopeNamesCount; + scope_name* ScopeNamesHash; + + s32 ThreadCount; + debug_scope_record_list* ThreadCalls; + + s32 CollatedScopesMax; + collated_scope_record* CollatedScopes; }; enum debug_ui_view { - DebugUI_Profiler, - DebugUI_ScopeList, - DebugUI_MemoryView, - - DebugUI_Count, + DebugUI_Profiler, + DebugUI_ScopeList, + DebugUI_MemoryView, + + DebugUI_Count, }; struct debug_interface { - s32 FrameView; + s32 FrameView; }; typedef s32 debug_get_thread_id(); @@ -86,18 +86,18 @@ typedef u8* debug_realloc(u8* Memory, s32 OldSize, s32 NewSize); #define HISTOGRAM_DEPTH 10 struct debug_histogram_entry { - char ScopeName_[SCOPE_NAME_LENGTH]; - gs_string ScopeName; - - u32 PerFrame_Cycles[HISTOGRAM_DEPTH]; - u32 PerFrame_CallCount[HISTOGRAM_DEPTH]; - s32 CurrentFrame; - - // NOTE(Peter): Cached Values, recalculated ever frame - u32 Average_Cycles; - u32 Average_CallCount; - u32 Total_Cycles; - u32 Total_CallCount; + char ScopeName_[SCOPE_NAME_LENGTH]; + gs_string ScopeName; + + u32 PerFrame_Cycles[HISTOGRAM_DEPTH]; + u32 PerFrame_CallCount[HISTOGRAM_DEPTH]; + s32 CurrentFrame; + + // NOTE(Peter): Cached Values, recalculated ever frame + u32 Average_Cycles; + u32 Average_CallCount; + u32 Total_Cycles; + u32 Total_CallCount; }; #if DEBUG @@ -108,72 +108,73 @@ struct debug_histogram_entry struct debug_services { - s64 PerformanceCountFrequency; - - b32 RecordFrames; - s32 CurrentDebugFrame; - debug_frame* Frames; - - debug_interface Interface; - - gs_thread_context Ctx; - - debug_get_thread_id* GetThreadId; - debug_timing_proc* GetWallClock; + s64 PerformanceCountFrequency; + + b32 RecordFrames; + s32 CurrentDebugFrame; + debug_frame* Frames; + + debug_interface Interface; + + gs_thread_context Ctx; + gs_memory_arena A; + + debug_get_thread_id* GetThreadId; + debug_timing_proc* GetWallClock; }; internal void InitializeDebugFrame (debug_frame* Frame, s32 NameHashMax, s32 ThreadCount, s32 ScopeCallsMax, debug_services* Services) { - Frame->ScopeNamesMax = NameHashMax; - Frame->ScopeNamesHash = AllocatorAllocArray(Services->Ctx.Allocator, scope_name, NameHashMax); - - // NOTE(Peter): We use the same size as scope names because we're only storing a single instance - // per scope. If ScopeNamesMax can't hold all the scopes, this will never get filled and - // we should assert and recompile with a resized NameHashMax - Frame->CollatedScopesMax = NameHashMax; - Frame->CollatedScopes = AllocatorAllocArray(Services->Ctx.Allocator, collated_scope_record, NameHashMax); - - for (s32 i = 0; i < Frame->ScopeNamesMax; i++) - { - scope_name* Entry = Frame->ScopeNamesHash + i; - Entry->Name = MakeString(Entry->Buffer, 0, SCOPE_NAME_BUFFER_LENGTH); - } - - Frame->ThreadCount = ThreadCount; - Frame->ThreadCalls = AllocatorAllocArray(Services->Ctx.Allocator, debug_scope_record_list, ThreadCount); - - for (s32 i = 0; i < ThreadCount; i++) - { - Frame->ThreadCalls[i].Max = ScopeCallsMax; - Frame->ThreadCalls[i].Count = 0; - Frame->ThreadCalls[i].Calls = AllocatorAllocArray(Services->Ctx.Allocator, scope_record, ScopeCallsMax); - Frame->ThreadCalls[i].CurrentScopeCallDepth = 0; - Frame->ThreadCalls[i].ThreadId = 0; - } - - for (s32 c = 0; c < Frame->CollatedScopesMax; c++) - { - Frame->CollatedScopes[c].NameHash = 0; - } + Frame->ScopeNamesMax = NameHashMax; + Frame->ScopeNamesHash = PushArray(&Services->A, scope_name, NameHashMax); + + // NOTE(Peter): We use the same size as scope names because we're only storing a single instance + // per scope. If ScopeNamesMax can't hold all the scopes, this will never get filled and + // we should assert and recompile with a resized NameHashMax + Frame->CollatedScopesMax = NameHashMax; + Frame->CollatedScopes = PushArray(&Services->A, collated_scope_record, NameHashMax); + + for (s32 i = 0; i < Frame->ScopeNamesMax; i++) + { + scope_name* Entry = Frame->ScopeNamesHash + i; + Entry->Name = MakeString(Entry->Buffer, 0, SCOPE_NAME_BUFFER_LENGTH); + } + + Frame->ThreadCount = ThreadCount; + Frame->ThreadCalls = PushArray(&Services->A, debug_scope_record_list, ThreadCount); + + for (s32 i = 0; i < ThreadCount; i++) + { + Frame->ThreadCalls[i].Max = ScopeCallsMax; + Frame->ThreadCalls[i].Count = 0; + Frame->ThreadCalls[i].Calls = PushArray(&Services->A, scope_record, ScopeCallsMax); + Frame->ThreadCalls[i].CurrentScopeCallDepth = 0; + Frame->ThreadCalls[i].ThreadId = 0; + } + + for (s32 c = 0; c < Frame->CollatedScopesMax; c++) + { + Frame->CollatedScopes[c].NameHash = 0; + } } internal void StartDebugFrame(debug_frame* Frame, debug_services* Services) { - Frame->FrameStartCycles = Services->GetWallClock(); - for (s32 i = 0; i < Frame->ThreadCount; i++) - { - Frame->ThreadCalls[i].Count = 0; - Frame->ThreadCalls[i].CurrentScopeCallDepth = 0; - } - - for (s32 c = 0; c < Frame->CollatedScopesMax; c++) - { - s32 Hash = Frame->CollatedScopes[c].NameHash; - Frame->CollatedScopes[c] = {}; - Frame->CollatedScopes[c].NameHash = Hash; - } + Frame->FrameStartCycles = Services->GetWallClock(); + for (s32 i = 0; i < Frame->ThreadCount; i++) + { + Frame->ThreadCalls[i].Count = 0; + Frame->ThreadCalls[i].CurrentScopeCallDepth = 0; + } + + for (s32 c = 0; c < Frame->CollatedScopesMax; c++) + { + s32 Hash = Frame->CollatedScopes[c].NameHash; + Frame->CollatedScopes[c] = {}; + Frame->CollatedScopes[c].NameHash = Hash; + } } internal void @@ -184,17 +185,17 @@ InitDebugServices_OffMode (debug_services* Services, gs_thread_context Ctx, s32 ThreadCount) { - *Services = {0}; - - Services->Ctx = Ctx; - Services->GetWallClock = GetWallClock; - Services->GetThreadId = GetThreadId; - - Services->RecordFrames = false; - Services->Frames = 0; - - Services->CurrentDebugFrame = 0; - Services->PerformanceCountFrequency = PerformanceCountFrequency; + *Services = {0}; + + Services->Ctx = Ctx; + Services->GetWallClock = GetWallClock; + Services->GetThreadId = GetThreadId; + + Services->RecordFrames = false; + Services->Frames = 0; + + Services->CurrentDebugFrame = 0; + Services->PerformanceCountFrequency = PerformanceCountFrequency; } @@ -206,227 +207,229 @@ InitDebugServices_DebugMode (debug_services* Services, gs_thread_context Ctx, s32 ThreadCount) { - Services->Ctx = Ctx; - Services->GetWallClock = GetWallClock; - Services->GetThreadId = GetThreadId; - - Services->RecordFrames = true; - - Services->CurrentDebugFrame = 0; - s32 NameHashMax = 4096; - s32 ScopeCallsMax = 4096; - Services->Frames = AllocatorAllocArray(Ctx.Allocator, debug_frame, DEBUG_FRAME_COUNT); - for (s32 i = 0; i < DEBUG_FRAME_COUNT; i++) - { - InitializeDebugFrame(&Services->Frames[i], NameHashMax, ThreadCount, ScopeCallsMax, Services); - } - - Services->PerformanceCountFrequency = PerformanceCountFrequency; + Services->Ctx = Ctx; + Services->GetWallClock = GetWallClock; + Services->GetThreadId = GetThreadId; + + Services->RecordFrames = true; + + Services->CurrentDebugFrame = 0; + Services->A = MemoryArenaCreate(MB(64), Bytes(8), Ctx.Allocator, 0, 0, "Debug Services Allocator"); + + s32 NameHashMax = 4096; + s32 ScopeCallsMax = 4096; + Services->Frames = PushArray(&Services->A, debug_frame, DEBUG_FRAME_COUNT); + for (s32 i = 0; i < DEBUG_FRAME_COUNT; i++) + { + InitializeDebugFrame(&Services->Frames[i], NameHashMax, ThreadCount, ScopeCallsMax, Services); + } + + Services->PerformanceCountFrequency = PerformanceCountFrequency; } internal debug_frame* GetCurrentDebugFrame (debug_services* Services) { - debug_frame* Result = Services->Frames + Services->CurrentDebugFrame; - return Result; + debug_frame* Result = Services->Frames + Services->CurrentDebugFrame; + return Result; } internal debug_frame* GetLastDebugFrame(debug_services* Services) { - if (!Services->Frames) return 0; - - s32 Index = (Services->CurrentDebugFrame - 1); - if (Index < 0) { Index += DEBUG_FRAME_COUNT; } - debug_frame* Result = Services->Frames + Index; - return Result; + if (!Services->Frames) return 0; + + s32 Index = (Services->CurrentDebugFrame - 1); + if (Index < 0) { Index += DEBUG_FRAME_COUNT; } + debug_frame* Result = Services->Frames + Index; + return Result; } internal s32 GetIndexForNameHash(debug_frame* Frame, u32 NameHash) { - s32 Result = -1; - - for (s32 Offset = 0; Offset < Frame->ScopeNamesMax; Offset++) + s32 Result = -1; + + for (s32 Offset = 0; Offset < Frame->ScopeNamesMax; Offset++) + { + u32 Index = (NameHash + Offset) % Frame->ScopeNamesMax; + if (Frame->ScopeNamesHash[Index].Hash == NameHash) { - u32 Index = (NameHash + Offset) % Frame->ScopeNamesMax; - if (Frame->ScopeNamesHash[Index].Hash == NameHash) - { - Result = Index; - break; - } + Result = Index; + break; } - - // NOTE(Peter): Its not technically wrong to return a -1 here, just means we didn't find it. - // At the time of writing however, this function is only being called in contexts where we - // know there should be an entry in the Name table, so a -1 actually indicates a problem. - Assert(Result >= 0); - return Result; + } + + // NOTE(Peter): Its not technically wrong to return a -1 here, just means we didn't find it. + // At the time of writing however, this function is only being called in contexts where we + // know there should be an entry in the Name table, so a -1 actually indicates a problem. + Assert(Result >= 0); + return Result; } internal debug_scope_record_list* GetScopeListForThreadInFrame(debug_services* Services, debug_frame* Frame) { - debug_scope_record_list* List = 0; - - s32 CurrentThreadId = Services->GetThreadId(); - for (s32 Offset = 0; Offset < Frame->ThreadCount; Offset++) + debug_scope_record_list* List = 0; + + s32 CurrentThreadId = Services->GetThreadId(); + for (s32 Offset = 0; Offset < Frame->ThreadCount; Offset++) + { + s32 Index = (CurrentThreadId + Offset) % Frame->ThreadCount; + if (Frame->ThreadCalls[Index].ThreadId == CurrentThreadId) { - s32 Index = (CurrentThreadId + Offset) % Frame->ThreadCount; - if (Frame->ThreadCalls[Index].ThreadId == CurrentThreadId) - { - List = Frame->ThreadCalls + Index; - break; - } - else if (Frame->ThreadCalls[Index].ThreadId == 0) - { - Frame->ThreadCalls[Index].ThreadId = CurrentThreadId; - List = Frame->ThreadCalls + Index; - break; - } + List = Frame->ThreadCalls + Index; + break; } - - Assert(List); - return List; + else if (Frame->ThreadCalls[Index].ThreadId == 0) + { + Frame->ThreadCalls[Index].ThreadId = CurrentThreadId; + List = Frame->ThreadCalls + Index; + break; + } + } + + Assert(List); + return List; } internal void CollateThreadScopeCalls (debug_scope_record_list* ThreadRecords, debug_frame* Frame) { - for (s32 i = 0; i < ThreadRecords->Count; i++) + for (s32 i = 0; i < ThreadRecords->Count; i++) + { + scope_record Record = ThreadRecords->Calls[i]; + s32 Index = GetIndexForNameHash (Frame, Record.NameHash); + collated_scope_record* CollatedRecord = Frame->CollatedScopes + Index; + + if (CollatedRecord->NameHash != Record.NameHash) { - scope_record Record = ThreadRecords->Calls[i]; - s32 Index = GetIndexForNameHash (Frame, Record.NameHash); - collated_scope_record* CollatedRecord = Frame->CollatedScopes + Index; - - if (CollatedRecord->NameHash != Record.NameHash) - { - CollatedRecord->NameHash = Record.NameHash; - CollatedRecord->TotalCycles = 0; - CollatedRecord->CallCount = 0; - } - - CollatedRecord->TotalCycles += Record.EndCycles - Record.StartCycles; - CollatedRecord->CallCount += 1; + CollatedRecord->NameHash = Record.NameHash; + CollatedRecord->TotalCycles = 0; + CollatedRecord->CallCount = 0; } + + CollatedRecord->TotalCycles += Record.EndCycles - Record.StartCycles; + CollatedRecord->CallCount += 1; + } } internal void EndDebugFrame (debug_services* Services) { - debug_frame* ClosingFrame = GetCurrentDebugFrame(Services); - ClosingFrame->FrameEndCycles = Services->GetWallClock(); - - s64 FrameTotalCycles = ClosingFrame->FrameEndCycles - ClosingFrame->FrameStartCycles; - - for (s32 t = 0; t < ClosingFrame->ThreadCount; t++) + debug_frame* ClosingFrame = GetCurrentDebugFrame(Services); + ClosingFrame->FrameEndCycles = Services->GetWallClock(); + + s64 FrameTotalCycles = ClosingFrame->FrameEndCycles - ClosingFrame->FrameStartCycles; + + for (s32 t = 0; t < ClosingFrame->ThreadCount; t++) + { + CollateThreadScopeCalls(ClosingFrame->ThreadCalls + t, ClosingFrame); + } + + s32 ScopeNamesCount = 0; + for (s32 n = 0; n < ClosingFrame->ScopeNamesMax; n++) + { + if (ClosingFrame->ScopeNamesHash[n].Hash != 0) { - CollateThreadScopeCalls(ClosingFrame->ThreadCalls + t, ClosingFrame); + collated_scope_record* CollatedRecord = ClosingFrame->CollatedScopes + n; + CollatedRecord->TotalSeconds = (r32)CollatedRecord->TotalCycles / (r32)Services->PerformanceCountFrequency; + CollatedRecord->PercentFrameTime = (r32)CollatedRecord->TotalCycles / (r32)FrameTotalCycles; + CollatedRecord->AverageSecondsPerCall = CollatedRecord->TotalSeconds / CollatedRecord->CallCount; + ScopeNamesCount += 1; } - - s32 ScopeNamesCount = 0; - for (s32 n = 0; n < ClosingFrame->ScopeNamesMax; n++) - { - if (ClosingFrame->ScopeNamesHash[n].Hash != 0) - { - collated_scope_record* CollatedRecord = ClosingFrame->CollatedScopes + n; - CollatedRecord->TotalSeconds = (r32)CollatedRecord->TotalCycles / (r32)Services->PerformanceCountFrequency; - CollatedRecord->PercentFrameTime = (r32)CollatedRecord->TotalCycles / (r32)FrameTotalCycles; - CollatedRecord->AverageSecondsPerCall = CollatedRecord->TotalSeconds / CollatedRecord->CallCount; - ScopeNamesCount += 1; - } - } - ClosingFrame->ScopeNamesCount = ScopeNamesCount; - - s32 FramesCount = DEBUG_FRAME_COUNT; - if (FramesCount > 0) - { - Services->CurrentDebugFrame = (Services->CurrentDebugFrame + 1) % FramesCount; - } - StartDebugFrame(&Services->Frames[Services->CurrentDebugFrame], Services); + } + ClosingFrame->ScopeNamesCount = ScopeNamesCount; + + s32 FramesCount = DEBUG_FRAME_COUNT; + if (FramesCount > 0) + { + Services->CurrentDebugFrame = (Services->CurrentDebugFrame + 1) % FramesCount; + } + StartDebugFrame(&Services->Frames[Services->CurrentDebugFrame], Services); } internal u32 HashScopeName (char* ScopeName) { - // djb2 hash - u32 Hash = 5381; - char* C = ScopeName; - while(*C) - { - Hash = ((Hash << 5) + Hash) + *C; - C++; - } - return Hash; + // djb2 hash + u32 Hash = 5381; + char* C = ScopeName; + while(*C) + { + Hash = ((Hash << 5) + Hash) + *C; + C++; + } + return Hash; } internal scope_name* GetOrAddNameHashEntry(debug_frame* Frame, u32 NameHash) { - scope_name* Result = 0; - - for (s32 Offset = 0; Offset < Frame->ScopeNamesMax; Offset++) + scope_name* Result = 0; + + for (s32 Offset = 0; Offset < Frame->ScopeNamesMax; Offset++) + { + u32 Index = (NameHash + Offset) % Frame->ScopeNamesMax; + if ((Frame->ScopeNamesHash[Index].Hash == 0) || (Frame->ScopeNamesHash[Index].Hash == NameHash)) { - u32 Index = (NameHash + Offset) % Frame->ScopeNamesMax; - if ((Frame->ScopeNamesHash[Index].Hash == 0) || (Frame->ScopeNamesHash[Index].Hash == NameHash)) - { - Result = Frame->ScopeNamesHash + Index; - break; - } + Result = Frame->ScopeNamesHash + Index; + break; } - - return Result; + } + + return Result; } internal u32 BeginTrackingScopeAndGetNameHash (debug_services* Services, char* ScopeName) { - debug_frame* CurrentFrame = GetCurrentDebugFrame(Services); - debug_scope_record_list* ThreadList = GetScopeListForThreadInFrame(Services, CurrentFrame); - - ThreadList->CurrentScopeCallDepth++; - - u32 NameHash = HashScopeName(ScopeName); - scope_name* Entry = GetOrAddNameHashEntry(CurrentFrame, NameHash); - if (Entry->Hash == 0) // If its new - { - Entry->Hash = NameHash; - // TODO(Peter): need to initialize all entry name gs_strings to point at the buffer - // This will break eventually. when it does, do this ^^^^ when on startup - PrintF(&Entry->Name, "%s", ScopeName); - } - - return NameHash; + debug_frame* CurrentFrame = GetCurrentDebugFrame(Services); + debug_scope_record_list* ThreadList = GetScopeListForThreadInFrame(Services, CurrentFrame); + + ThreadList->CurrentScopeCallDepth++; + + u32 NameHash = HashScopeName(ScopeName); + scope_name* Entry = GetOrAddNameHashEntry(CurrentFrame, NameHash); + if (Entry->Hash == 0) // If its new + { + Entry->Hash = NameHash; + // TODO(Peter): need to initialize all entry name gs_strings to point at the buffer + // This will break eventually. when it does, do this ^^^^ when on startup + PrintF(&Entry->Name, "%s", ScopeName); + } + + return NameHash; } internal void PushScopeTimeOnFrame (debug_services* Services, s32 NameHash, u64 StartCycles, u64 EndCycles) { - debug_frame* CurrentFrame = GetCurrentDebugFrame(Services); - debug_scope_record_list* ThreadList = GetScopeListForThreadInFrame(Services, CurrentFrame); - - if (ThreadList->Count >= ThreadList->Max) - { - s32 NewMax = (ThreadList->Max + DEBUG_FRAME_GROW_SIZE); - AllocatorFreeArray(Services->Ctx.Allocator, ThreadList->Calls, scope_record, ThreadList->Max); - ThreadList->Calls = AllocatorAllocArray(Services->Ctx.Allocator, scope_record, NewMax); - ThreadList->Max = NewMax; - } - - Assert(ThreadList->Count < ThreadList->Max); - - s32 EntryIndex = ThreadList->Count++; - scope_record* Record = ThreadList->Calls + EntryIndex; - Record->NameHash = NameHash; - Record->StartCycles = StartCycles; - Record->EndCycles = EndCycles; - Record->CallDepth = --ThreadList->CurrentScopeCallDepth; + debug_frame* CurrentFrame = GetCurrentDebugFrame(Services); + debug_scope_record_list* ThreadList = GetScopeListForThreadInFrame(Services, CurrentFrame); + + if (ThreadList->Count >= ThreadList->Max) + { + s32 NewMax = (ThreadList->Max + DEBUG_FRAME_GROW_SIZE); + FreeArray(Services->Ctx.Allocator, ThreadList->Calls, scope_record, ThreadList->Max); + ThreadList->Calls = AllocArray(Services->Ctx.Allocator, scope_record, NewMax, "Debug Frame"); + ThreadList->Max = NewMax; + } + + Assert(ThreadList->Count < ThreadList->Max); + + s32 EntryIndex = ThreadList->Count++; + scope_record* Record = ThreadList->Calls + EntryIndex; + Record->NameHash = NameHash; + Record->StartCycles = StartCycles; + Record->EndCycles = EndCycles; + Record->CallDepth = --ThreadList->CurrentScopeCallDepth; } internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFrequency) { - r32 Result = ((r32)(End - Start) / (r32)PerformanceCountFrequency); - return Result; + r32 Result = ((r32)(End - Start) / (r32)PerformanceCountFrequency); + return Result; } #if DEBUG @@ -438,32 +441,32 @@ internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFre #endif struct scope_tracker { - s64 ScopeStart; - u32 ScopeNameHash; - debug_services* DebugServices; - - scope_tracker(char* ScopeName, debug_services* DebugServices) + s64 ScopeStart; + u32 ScopeNameHash; + debug_services* DebugServices; + + scope_tracker(char* ScopeName, debug_services* DebugServices) + { + if (DebugServices->RecordFrames) { - if (DebugServices->RecordFrames) - { - this->ScopeNameHash = BeginTrackingScopeAndGetNameHash(DebugServices, ScopeName); - this->ScopeStart = DebugServices->GetWallClock(); - this->DebugServices = DebugServices; - } - else - { - this->DebugServices = 0; - } + this->ScopeNameHash = BeginTrackingScopeAndGetNameHash(DebugServices, ScopeName); + this->ScopeStart = DebugServices->GetWallClock(); + this->DebugServices = DebugServices; } - - ~scope_tracker() + else { - if (this->DebugServices) // NOTE(Peter): If DebugServices == 0, then we werent' recording this frame - { - s64 ScopeEnd = this->DebugServices->GetWallClock(); - PushScopeTimeOnFrame(this->DebugServices, this->ScopeNameHash, this->ScopeStart, ScopeEnd); - } + this->DebugServices = 0; } + } + + ~scope_tracker() + { + if (this->DebugServices) // NOTE(Peter): If DebugServices == 0, then we werent' recording this frame + { + s64 ScopeEnd = this->DebugServices->GetWallClock(); + PushScopeTimeOnFrame(this->DebugServices, this->ScopeNameHash, this->ScopeStart, ScopeEnd); + } + } }; diff --git a/src/app/foldhaus_renderer.cpp b/src/app/foldhaus_renderer.cpp index 548acda..51c2579 100644 --- a/src/app/foldhaus_renderer.cpp +++ b/src/app/foldhaus_renderer.cpp @@ -8,190 +8,190 @@ internal render_command_buffer AllocateRenderCommandBuffer (u8* Memory, s32 Size, gs_thread_context Ctx) { - render_command_buffer Result = {}; - Result.CommandMemory = Memory; - Result.CommandMemorySize = Size; - Result.CommandMemoryUsed = 0; - Result.Ctx = Ctx; - return Result; + render_command_buffer Result = {}; + Result.CommandMemory = Memory; + Result.CommandMemorySize = Size; + Result.CommandMemoryUsed = 0; + Result.Ctx = Ctx; + return Result; } internal render_command_buffer AllocateRenderCommandBuffer(u32 MemorySize, gs_memory_arena* Arena, gs_thread_context Ctx) { - u8* Memory = PushSize(Arena, MemorySize); - return AllocateRenderCommandBuffer(Memory, MemorySize, Ctx); + u8* Memory = PushSize(Arena, MemorySize).Memory; + return AllocateRenderCommandBuffer(Memory, MemorySize, Ctx); } internal void Render3DQuadBatch (u8* CommandData, s32 TriCount) { - DEBUG_TRACK_FUNCTION; - - v4* Vertecies = (v4*)(CommandData + BATCH_3D_VERTECIES_OFFSET(TriCount)); - v2* UVs = (v2*)(CommandData + BATCH_3D_UVS_OFFSET(TriCount)); - v4* Colors = (v4*)(CommandData + BATCH_3D_COLORS_OFFSET(TriCount)); - + DEBUG_TRACK_FUNCTION; + + v4* Vertecies = (v4*)(CommandData + BATCH_3D_VERTECIES_OFFSET(TriCount)); + v2* UVs = (v2*)(CommandData + BATCH_3D_UVS_OFFSET(TriCount)); + v4* Colors = (v4*)(CommandData + BATCH_3D_COLORS_OFFSET(TriCount)); + #if IMMEDIATE_MODE_RENDERING + + for (s32 Tri = 0; Tri < TriCount; Tri++) + { + v4 P0 = Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 0)]; + v4 P1 = Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 1)]; + v4 P2 = Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 2)]; + v2 UV0 = UVs[BATCH_3D_UV_INDEX(Tri, 0)]; + v2 UV1 = UVs[BATCH_3D_UV_INDEX(Tri, 1)]; + v2 UV2 = UVs[BATCH_3D_UV_INDEX(Tri, 2)]; + v4 C0 = Colors[BATCH_3D_COLOR_INDEX(Tri, 0)]; + v4 C1 = Colors[BATCH_3D_COLOR_INDEX(Tri, 1)]; + v4 C2 = Colors[BATCH_3D_COLOR_INDEX(Tri, 2)]; - for (s32 Tri = 0; Tri < TriCount; Tri++) - { - v4 P0 = Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 0)]; - v4 P1 = Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 1)]; - v4 P2 = Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 2)]; - v2 UV0 = UVs[BATCH_3D_UV_INDEX(Tri, 0)]; - v2 UV1 = UVs[BATCH_3D_UV_INDEX(Tri, 1)]; - v2 UV2 = UVs[BATCH_3D_UV_INDEX(Tri, 2)]; - v4 C0 = Colors[BATCH_3D_COLOR_INDEX(Tri, 0)]; - v4 C1 = Colors[BATCH_3D_COLOR_INDEX(Tri, 1)]; - v4 C2 = Colors[BATCH_3D_COLOR_INDEX(Tri, 2)]; - - OpenGLDraw3DTri(P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); - } + OpenGLDraw3DTri(P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); + } #else - OpenGLRenderTriBuffer((u8*)Vertecies, 4, (u8*)UVs, 2, (u8*)Colors, 4, TriCount * 3); + OpenGLRenderTriBuffer((u8*)Vertecies, 4, (u8*)UVs, 2, (u8*)Colors, 4, TriCount * 3); #endif } internal void Render2DQuadBatch (u8* CommandData, s32 QuadCount) { - DEBUG_TRACK_FUNCTION; - - v2* Vertecies = (v2*)(CommandData + BATCH_2D_VERTECIES_OFFSET(QuadCount)); - v2* UVs = (v2*)(CommandData + BATCH_2D_UVS_OFFSET(QuadCount)); - v4* Colors = (v4*)(CommandData + BATCH_2D_COLORS_OFFSET(QuadCount)); - + DEBUG_TRACK_FUNCTION; + + v2* Vertecies = (v2*)(CommandData + BATCH_2D_VERTECIES_OFFSET(QuadCount)); + v2* UVs = (v2*)(CommandData + BATCH_2D_UVS_OFFSET(QuadCount)); + v4* Colors = (v4*)(CommandData + BATCH_2D_COLORS_OFFSET(QuadCount)); + #if IMMEDIATE_MODE_RENDERING - for (s32 Quad = 0; Quad < QuadCount; Quad++) + for (s32 Quad = 0; Quad < QuadCount; Quad++) + { + for (s32 Tri = 0; Tri < 2; Tri++) { - for (s32 Tri = 0; Tri < 2; Tri++) - { - v2 P0 = Vertecies[BATCH_2D_VERTEX_INDEX(Quad, Tri, 0)]; - v2 P1 = Vertecies[BATCH_2D_VERTEX_INDEX(Quad, Tri, 1)]; - v2 P2 = Vertecies[BATCH_2D_VERTEX_INDEX(Quad, Tri, 2)]; - v2 UV0 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 0)]; - v2 UV1 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 1)]; - v2 UV2 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 2)]; - v4 C0 = Colors[BATCH_2D_COLOR_INDEX(Quad, Tri, 0)]; - v4 C1 = Colors[BATCH_2D_COLOR_INDEX(Quad, Tri, 1)]; - v4 C2 = Colors[BATCH_2D_COLOR_INDEX(Quad, Tri, 2)]; - - OpenGLDraw2DTri(P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); - } + v2 P0 = Vertecies[BATCH_2D_VERTEX_INDEX(Quad, Tri, 0)]; + v2 P1 = Vertecies[BATCH_2D_VERTEX_INDEX(Quad, Tri, 1)]; + v2 P2 = Vertecies[BATCH_2D_VERTEX_INDEX(Quad, Tri, 2)]; + v2 UV0 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 0)]; + v2 UV1 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 1)]; + v2 UV2 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 2)]; + v4 C0 = Colors[BATCH_2D_COLOR_INDEX(Quad, Tri, 0)]; + v4 C1 = Colors[BATCH_2D_COLOR_INDEX(Quad, Tri, 1)]; + v4 C2 = Colors[BATCH_2D_COLOR_INDEX(Quad, Tri, 2)]; + + OpenGLDraw2DTri(P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); } + } #else - OpenGLRenderTriBuffer((u8*)Vertecies, 2, (u8*)UVs, 2, (u8*)Colors, 4, QuadCount * 2 * 3); + OpenGLRenderTriBuffer((u8*)Vertecies, 2, (u8*)UVs, 2, (u8*)Colors, 4, QuadCount * 2 * 3); #endif } internal void RenderCommandBuffer (render_command_buffer CommandBuffer) { - DEBUG_TRACK_FUNCTION; - - glMatrixMode(GL_TEXTURE_2D); - glLoadIdentity(); - - glClearColor(0.1f, 0.1f, 0.1f, 1); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_TEXTURE_2D); - b32 GLTextureEnabled = false; - - u8* CurrentPosition = CommandBuffer.CommandMemory; - while(CurrentPosition < CommandBuffer.CommandMemory + CommandBuffer.CommandMemoryUsed) + DEBUG_TRACK_FUNCTION; + + glMatrixMode(GL_TEXTURE_2D); + glLoadIdentity(); + + glClearColor(0.1f, 0.1f, 0.1f, 1); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_TEXTURE_2D); + b32 GLTextureEnabled = false; + + u8* CurrentPosition = CommandBuffer.CommandMemory; + while(CurrentPosition < CommandBuffer.CommandMemory + CommandBuffer.CommandMemoryUsed) + { + render_command_header* CommandHeader = (render_command_header*)CurrentPosition; + CurrentPosition += sizeof(render_command_header); + switch (CommandHeader->Type) { - render_command_header* CommandHeader = (render_command_header*)CurrentPosition; - CurrentPosition += sizeof(render_command_header); - switch (CommandHeader->Type) + case RenderCommand_render_command_set_render_mode: + { + DEBUG_TRACK_SCOPE(SetRenderMode); + + render_command_set_render_mode* Command = (render_command_set_render_mode*)(CommandHeader + 1); + + glViewport(Command->ViewOffsetX, Command->ViewOffsetY, + Command->ViewWidth, Command->ViewHeight); + + LoadModelView(Command->ModelView.Array); + LoadProjection(Command->Projection.Array); + + if (Command->UseDepthBuffer) { - case RenderCommand_render_command_set_render_mode: - { - DEBUG_TRACK_SCOPE(SetRenderMode); - - render_command_set_render_mode* Command = (render_command_set_render_mode*)(CommandHeader + 1); - - glViewport(Command->ViewOffsetX, Command->ViewOffsetY, - Command->ViewWidth, Command->ViewHeight); - - LoadModelView(Command->ModelView.Array); - LoadProjection(Command->Projection.Array); - - if (Command->UseDepthBuffer) - { - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - } - else - { - glDisable(GL_DEPTH_TEST); - } - - CurrentPosition += sizeof(render_command_set_render_mode); - }break; - - case RenderCommand_render_command_clear_screen: - { - DEBUG_TRACK_SCOPE(RendererClearScreen); - - render_command_clear_screen* Command = (render_command_clear_screen*)(CommandHeader + 1); - - ClearRenderBuffer(); - - CurrentPosition += sizeof(render_command_clear_screen); - }break; - - case RenderCommand_render_batch_command_quad_2d: - { - render_batch_command_quad_2d* Command = (render_batch_command_quad_2d*)(CommandHeader + 1); - - if (GLTextureEnabled) { glDisable(GL_TEXTURE_2D); GLTextureEnabled = false; } - u8* CommandData = (u8*)(Command + 1); - Render2DQuadBatch(CommandData, Command->QuadCount); - - CurrentPosition += sizeof(render_batch_command_quad_2d) + Command->DataSize; - }break; - - case RenderCommand_render_batch_command_quad_3d: - { - render_batch_command_quad_3d* Command = (render_batch_command_quad_3d*)(CommandHeader + 1); - - if (GLTextureEnabled) { glDisable(GL_TEXTURE_2D); GLTextureEnabled = false; } - u8* CommandData = (u8*)(Command + 1); - Render3DQuadBatch(CommandData, Command->QuadCount * 2); - - CurrentPosition += sizeof(render_batch_command_quad_3d) + Command->DataSize; - }break; - - case RenderCommand_render_batch_command_texture_2d: - { - render_batch_command_texture_2d* Command = (render_batch_command_texture_2d*)(CommandHeader + 1); - - if (!GLTextureEnabled) { glEnable(GL_TEXTURE_2D); GLTextureEnabled = true; } - Assert(Command->Texture.Handle > 0); - glBindTexture(GL_TEXTURE_2D, Command->Texture.Handle); - u8* CommandData = (u8*)(Command + 1); - Render2DQuadBatch(CommandData, Command->QuadCount); - - CurrentPosition += sizeof(render_batch_command_texture_2d) + Command->DataSize; - }break; - - default: - { - InvalidCodePath; - }break; + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); } + else + { + glDisable(GL_DEPTH_TEST); + } + + CurrentPosition += sizeof(render_command_set_render_mode); + }break; + + case RenderCommand_render_command_clear_screen: + { + DEBUG_TRACK_SCOPE(RendererClearScreen); + + render_command_clear_screen* Command = (render_command_clear_screen*)(CommandHeader + 1); + + ClearRenderBuffer(); + + CurrentPosition += sizeof(render_command_clear_screen); + }break; + + case RenderCommand_render_batch_command_quad_2d: + { + render_batch_command_quad_2d* Command = (render_batch_command_quad_2d*)(CommandHeader + 1); + + if (GLTextureEnabled) { glDisable(GL_TEXTURE_2D); GLTextureEnabled = false; } + u8* CommandData = (u8*)(Command + 1); + Render2DQuadBatch(CommandData, Command->QuadCount); + + CurrentPosition += sizeof(render_batch_command_quad_2d) + Command->DataSize; + }break; + + case RenderCommand_render_batch_command_quad_3d: + { + render_batch_command_quad_3d* Command = (render_batch_command_quad_3d*)(CommandHeader + 1); + + if (GLTextureEnabled) { glDisable(GL_TEXTURE_2D); GLTextureEnabled = false; } + u8* CommandData = (u8*)(Command + 1); + Render3DQuadBatch(CommandData, Command->QuadCount * 2); + + CurrentPosition += sizeof(render_batch_command_quad_3d) + Command->DataSize; + }break; + + case RenderCommand_render_batch_command_texture_2d: + { + render_batch_command_texture_2d* Command = (render_batch_command_texture_2d*)(CommandHeader + 1); + + if (!GLTextureEnabled) { glEnable(GL_TEXTURE_2D); GLTextureEnabled = true; } + Assert(Command->Texture.Handle > 0); + glBindTexture(GL_TEXTURE_2D, Command->Texture.Handle); + u8* CommandData = (u8*)(Command + 1); + Render2DQuadBatch(CommandData, Command->QuadCount); + + CurrentPosition += sizeof(render_batch_command_texture_2d) + Command->DataSize; + }break; + + default: + { + InvalidCodePath; + }break; } + } } internal void ClearRenderBuffer (render_command_buffer* Buffer) { - Buffer->CommandMemoryUsed = 0; + Buffer->CommandMemoryUsed = 0; } #define FOLDHAUS_RENDERER_CPP diff --git a/src/app/foldhaus_renderer.h b/src/app/foldhaus_renderer.h index 0a264de..6e48836 100644 --- a/src/app/foldhaus_renderer.h +++ b/src/app/foldhaus_renderer.h @@ -9,104 +9,104 @@ struct camera { - r32 FieldOfView; - r32 AspectRatio; - r32 Near, Far; - v3 Position; - v3 LookAt; + r32 FieldOfView; + r32 AspectRatio; + r32 Near, Far; + v3 Position; + v3 LookAt; }; inline m44 GetCameraModelViewMatrix (camera Camera) { - m44 RotationMatrix = M44LookAt(ToV4Point(Camera.Position), ToV4Point(Camera.LookAt)); - m44 PositionMatrix = M44Translation(ToV4Point(-Camera.Position)); - m44 ModelViewMatrix = RotationMatrix * PositionMatrix; - return ModelViewMatrix; + m44 RotationMatrix = M44LookAt(ToV4Point(Camera.Position), ToV4Point(Camera.LookAt)); + m44 PositionMatrix = M44Translation(ToV4Point(-Camera.Position)); + m44 ModelViewMatrix = RotationMatrix * PositionMatrix; + return ModelViewMatrix; } inline m44 GetCameraPerspectiveProjectionMatrix(camera Camera) { - m44 Result = M44ProjectionPerspective(Camera.FieldOfView, Camera.AspectRatio, Camera.Near, Camera.Far); - return Result; + m44 Result = M44ProjectionPerspective(Camera.FieldOfView, Camera.AspectRatio, Camera.Near, Camera.Far); + return Result; } internal m44 GetCameraMatrix(camera Camera) { - m44 ModelView = GetCameraModelViewMatrix(Camera); - m44 Projection = GetCameraPerspectiveProjectionMatrix(Camera); - m44 Result = Projection * ModelView; - return Result; + m44 ModelView = GetCameraModelViewMatrix(Camera); + m44 Projection = GetCameraPerspectiveProjectionMatrix(Camera); + m44 Result = Projection * ModelView; + return Result; } internal v2 ProjectWorldPointToScreen(v4 WorldSpacePoint, camera Camera, rect2 WindowBounds) { - v2 WindowExtents = v2{Rect2Width(WindowBounds), Rect2Height(WindowBounds)}; - v4 ProjectedPosition = GetCameraMatrix(Camera) * WorldSpacePoint; - ProjectedPosition.xyz /= ProjectedPosition.w; - v2 ScreenPosition = V2MultiplyPairwise(ProjectedPosition.xy, (WindowExtents / 2)) + (WindowExtents / 2); - - return ScreenPosition; + v2 WindowExtents = v2{Rect2Width(WindowBounds), Rect2Height(WindowBounds)}; + v4 ProjectedPosition = GetCameraMatrix(Camera) * WorldSpacePoint; + ProjectedPosition.xyz /= ProjectedPosition.w; + v2 ScreenPosition = V2MultiplyPairwise(ProjectedPosition.xy, (WindowExtents / 2)) + (WindowExtents / 2); + + return ScreenPosition; } internal v4_ray ProjectScreenPointToWorldRay(v2 ScreenPoint, camera Camera, rect2 WindowBounds) { - v4_ray Result = {0}; - - r32 TanFOVOverTwo = TanR32(DegToRadR32(Camera.FieldOfView / 2.0f)); - r32 Aspect = RectAspectRatio(WindowBounds); - - r32 NormalizedX = ScreenPoint.x / Rect2Width(WindowBounds); - r32 NormalizedY = ScreenPoint.y / Rect2Height(WindowBounds); - - r32 CenteredX = (2.0f * NormalizedX) - 1.0f; - r32 CenteredY = (2.0f * NormalizedY) - 1.0f; - - r32 ScaledX = CenteredX * Aspect; - r32 ScaledY = CenteredY; - - r32 CameraX = ScaledX * TanFOVOverTwo; - r32 CameraY = ScaledY * TanFOVOverTwo; - - r32 Near = Camera.Near; - r32 Far = Camera.Far; - v3 MousePointOnNearPlane = v3{CameraX, CameraY, -1} * Near; - v3 MousePointOnFarPlane = v3{CameraX, CameraY, -1} * Far; - - v4 MouseRayDirection = ToV4Vec(V3Normalize(MousePointOnFarPlane - MousePointOnNearPlane)); - m44 CameraTransform = M44Transpose(M44LookAt(ToV4Point(Camera.Position), ToV4Point(Camera.LookAt))); - - Result.Origin = ToV4Point(Camera.Position); - Result.Direction = CameraTransform * MouseRayDirection; - - return Result; + v4_ray Result = {0}; + + r32 TanFOVOverTwo = TanR32(DegToRadR32(Camera.FieldOfView / 2.0f)); + r32 Aspect = RectAspectRatio(WindowBounds); + + r32 NormalizedX = ScreenPoint.x / Rect2Width(WindowBounds); + r32 NormalizedY = ScreenPoint.y / Rect2Height(WindowBounds); + + r32 CenteredX = (2.0f * NormalizedX) - 1.0f; + r32 CenteredY = (2.0f * NormalizedY) - 1.0f; + + r32 ScaledX = CenteredX * Aspect; + r32 ScaledY = CenteredY; + + r32 CameraX = ScaledX * TanFOVOverTwo; + r32 CameraY = ScaledY * TanFOVOverTwo; + + r32 Near = Camera.Near; + r32 Far = Camera.Far; + v3 MousePointOnNearPlane = v3{CameraX, CameraY, -1} * Near; + v3 MousePointOnFarPlane = v3{CameraX, CameraY, -1} * Far; + + v4 MouseRayDirection = ToV4Vec(V3Normalize(MousePointOnFarPlane - MousePointOnNearPlane)); + m44 CameraTransform = M44Transpose(M44LookAt(ToV4Point(Camera.Position), ToV4Point(Camera.LookAt))); + + Result.Origin = ToV4Point(Camera.Position); + Result.Direction = CameraTransform * MouseRayDirection; + + return Result; } // Render Commands // Discriminated Union enum render_command_type { - RenderCommand_Invalid, - - RenderCommand_render_command_clear_screen, - RenderCommand_render_command_set_render_mode, - - RenderCommand_render_batch_command_quad_2d, - RenderCommand_render_batch_command_quad_3d, - RenderCommand_render_batch_command_texture_2d, - - RenderCommand_render_command_texture_3d, - - RenderCommand_Count + RenderCommand_Invalid, + + RenderCommand_render_command_clear_screen, + RenderCommand_render_command_set_render_mode, + + RenderCommand_render_batch_command_quad_2d, + RenderCommand_render_batch_command_quad_3d, + RenderCommand_render_batch_command_texture_2d, + + RenderCommand_render_command_texture_3d, + + RenderCommand_Count }; struct render_command_header { - render_command_type Type; + render_command_type Type; }; // NOTE(Peter): Just to keep with the rest of the system @@ -114,22 +114,22 @@ struct render_command_clear_screen {}; struct render_quad_2d { - v2 Min, Max; + v2 Min, Max; }; struct render_quad_3d { - v4 P0, P1, P2, P3; + v4 P0, P1, P2, P3; }; struct render_texture { - u8* Memory; - s32 Handle; - s32 Width; - s32 Height; - s32 BytesPerPixel; - s32 Stride; + u8* Memory; + s32 Handle; + s32 Width; + s32 Height; + s32 BytesPerPixel; + s32 Stride; }; #define BATCH_3D_SIZE(tricount) (((sizeof(v4) + sizeof(v2) + sizeof(v4)) * 3) * tricount) @@ -150,57 +150,57 @@ struct render_texture struct render_quad_batch_constructor { - s32 Max; - s32 Count; - - v4* Vertecies; - v2* UVs; - v4* ColorsV; + s32 Max; + s32 Count; + + v4* Vertecies; + v2* UVs; + v4* ColorsV; }; struct render_batch_command_quad_2d { - s32 QuadCount; - s32 DataSize; - // NOTE(Peter): The data immediately follows the command in memory + s32 QuadCount; + s32 DataSize; + // NOTE(Peter): The data immediately follows the command in memory }; struct render_batch_command_quad_3d { - s32 QuadCount; - s32 DataSize; - // NOTE(Peter): The data immediately follows the command in memory + s32 QuadCount; + s32 DataSize; + // NOTE(Peter): The data immediately follows the command in memory }; struct render_command_texture_2d { - render_quad_2d Quad; - render_quad_2d UV; - v4 Color; - render_texture Texture; + render_quad_2d Quad; + render_quad_2d UV; + v4 Color; + render_texture Texture; }; struct render_batch_command_texture_2d { - s32 QuadCount; - s32 DataSize; - render_texture Texture; + s32 QuadCount; + s32 DataSize; + render_texture Texture; }; struct render_command_texture_3d { - render_quad_3d Quad; - v4 Color; - render_texture Texture; + render_quad_3d Quad; + v4 Color; + render_texture Texture; }; struct render_command_set_render_mode { - m44 ModelView; - m44 Projection; - r32 ViewOffsetX, ViewOffsetY; - r32 ViewWidth, ViewHeight; - b32 UseDepthBuffer; + m44 ModelView; + m44 Projection; + r32 ViewOffsetX, ViewOffsetY; + r32 ViewWidth, ViewHeight; + b32 UseDepthBuffer; }; typedef u8* renderer_realloc(u8* Base, s32 CurrentSize, s32 NewSize); @@ -209,14 +209,14 @@ typedef u8* renderer_realloc(u8* Base, s32 CurrentSize, s32 NewSize); struct render_command_buffer { - u8* CommandMemory; - s32 CommandMemoryUsed; - s32 CommandMemorySize; - - gs_thread_context Ctx; - - s32 ViewWidth; - s32 ViewHeight; + u8* CommandMemory; + s32 CommandMemoryUsed; + s32 CommandMemorySize; + + gs_thread_context Ctx; + + s32 ViewWidth; + s32 ViewHeight; }; /// @@ -226,49 +226,49 @@ struct render_command_buffer internal u32 PackColorStructU8 (u8 R, u8 G, u8 B, u8 A) { - u32 Result = (u32)(A << 24 | - R << 16 | - G << 8 | - B<< 0); - return Result; + u32 Result = (u32)(A << 24 | + R << 16 | + G << 8 | + B<< 0); + return Result; } internal u32 PackColorStructR32 (r32 In_R, r32 In_G, r32 In_B, r32 In_A) { - Assert ((In_R >= 0.0f && In_R <= 1.0f) && - (In_G >= 0.0f && In_G <= 1.0f) && - (In_B >= 0.0f && In_B <= 1.0f) && - (In_A >= 0.0f && In_A <= 1.0f)); - - u8 R = (u8)(255 * In_R); - u8 G = (u8)(255 * In_G); - u8 B = (u8)(255 * In_B); - u8 A = (u8)(255 * In_A); - - u32 Result = (u32)(A << 24 | - R << 16 | - G << 8 | - B<< 0); - return Result; + Assert ((In_R >= 0.0f && In_R <= 1.0f) && + (In_G >= 0.0f && In_G <= 1.0f) && + (In_B >= 0.0f && In_B <= 1.0f) && + (In_A >= 0.0f && In_A <= 1.0f)); + + u8 R = (u8)(255 * In_R); + u8 G = (u8)(255 * In_G); + u8 B = (u8)(255 * In_B); + u8 A = (u8)(255 * In_A); + + u32 Result = (u32)(A << 24 | + R << 16 | + G << 8 | + B<< 0); + return Result; } internal void ResizeBufferIfNecessary(render_command_buffer* Buffer, s32 DataSize) { - if (Buffer->CommandMemoryUsed + DataSize > Buffer->CommandMemorySize) - { - // NOTE(Peter): If this becomes a problem just go back to the original solution of - // NewSize = Buffer->CommandMemorySize + (2 * DataSize); - s32 SpaceAvailable = Buffer->CommandMemorySize - Buffer->CommandMemoryUsed; - s32 SpaceNeeded = DataSize - SpaceAvailable; // This is known to be positive at this point - s32 AdditionSize = Max(SpaceNeeded, COMMAND_BUFFER_MIN_GROW_SIZE); - s32 NewSize = Buffer->CommandMemorySize + AdditionSize; - - AllocatorFree(Buffer->Ctx.Allocator, Buffer->CommandMemory, Buffer->CommandMemorySize); - Buffer->CommandMemory = AllocatorAlloc(Buffer->Ctx.Allocator, NewSize).Memory; - Buffer->CommandMemorySize = NewSize; - } + if (Buffer->CommandMemoryUsed + DataSize > Buffer->CommandMemorySize) + { + // NOTE(Peter): If this becomes a problem just go back to the original solution of + // NewSize = Buffer->CommandMemorySize + (2 * DataSize); + s32 SpaceAvailable = Buffer->CommandMemorySize - Buffer->CommandMemoryUsed; + s32 SpaceNeeded = DataSize - SpaceAvailable; // This is known to be positive at this point + s32 AdditionSize = Max(SpaceNeeded, COMMAND_BUFFER_MIN_GROW_SIZE); + s32 NewSize = Buffer->CommandMemorySize + AdditionSize; + + Free(Buffer->Ctx.Allocator, Buffer->CommandMemory, Buffer->CommandMemorySize); + Buffer->CommandMemory = Alloc(Buffer->Ctx.Allocator, NewSize, "Renderer"); + Buffer->CommandMemorySize = NewSize; + } } // Batch @@ -276,68 +276,68 @@ ResizeBufferIfNecessary(render_command_buffer* Buffer, s32 DataSize) internal s32 PushQuad3DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* Constructor, u8* MemStart, s32 TriCount, s32 DataSize, b32 UseIntegerColor = false) { - Constructor->Max = TriCount; - Constructor->Count = 0; - - Constructor->Vertecies = (v4*)(MemStart + BATCH_3D_VERTECIES_OFFSET(TriCount)); - Constructor->UVs = (v2*)(MemStart + BATCH_3D_UVS_OFFSET(TriCount)); - Constructor->ColorsV = (v4*)(MemStart + BATCH_3D_COLORS_OFFSET(TriCount)); - - Buffer->CommandMemoryUsed += DataSize; - return DataSize; + Constructor->Max = TriCount; + Constructor->Count = 0; + + Constructor->Vertecies = (v4*)(MemStart + BATCH_3D_VERTECIES_OFFSET(TriCount)); + Constructor->UVs = (v2*)(MemStart + BATCH_3D_UVS_OFFSET(TriCount)); + Constructor->ColorsV = (v4*)(MemStart + BATCH_3D_COLORS_OFFSET(TriCount)); + + Buffer->CommandMemoryUsed += DataSize; + return DataSize; } internal s32 PushQuad2DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* Constructor, s32 QuadCount, s32 DataSize, u8* MemStart) { - ZeroMemoryBlock(MemStart, DataSize); - - Constructor->Max = QuadCount; - Constructor->Count = 0; - - Constructor->Vertecies = (v4*)(MemStart + BATCH_2D_VERTECIES_OFFSET(QuadCount)); - Constructor->UVs = (v2*)(MemStart + BATCH_2D_UVS_OFFSET(QuadCount)); - Constructor->ColorsV = (v4*)(MemStart + BATCH_2D_COLORS_OFFSET(QuadCount)); - - Buffer->CommandMemoryUsed += DataSize; - return DataSize; + ZeroMemoryBlock(MemStart, DataSize); + + Constructor->Max = QuadCount; + Constructor->Count = 0; + + Constructor->Vertecies = (v4*)(MemStart + BATCH_2D_VERTECIES_OFFSET(QuadCount)); + Constructor->UVs = (v2*)(MemStart + BATCH_2D_UVS_OFFSET(QuadCount)); + Constructor->ColorsV = (v4*)(MemStart + BATCH_2D_COLORS_OFFSET(QuadCount)); + + Buffer->CommandMemoryUsed += DataSize; + return DataSize; } internal s32 ThreadSafeIncrementQuadConstructorCount (render_quad_batch_constructor* Constructor) { - s32 Result = InterlockedIncrement((long*)&Constructor->Count); - // NOTE(Peter): Have to decrement the value by one. - // Interlocked Increment acts as (++Constructor->Count), not (Constructor->Count++) which - // is what we wanted; - // This was causing the first triangle to be garbage data. - Result -= 1; - return Result; + s32 Result = InterlockedIncrement((long*)&Constructor->Count); + // NOTE(Peter): Have to decrement the value by one. + // Interlocked Increment acts as (++Constructor->Count), not (Constructor->Count++) which + // is what we wanted; + // This was causing the first triangle to be garbage data. + Result -= 1; + return Result; } struct quad_batch_constructor_reserved_range { - s32 Start; - s32 OnePastLast; + s32 Start; + s32 OnePastLast; }; internal quad_batch_constructor_reserved_range ReserveRangeInQuadConstructor(render_quad_batch_constructor* Constructor, s32 TrisNeeded) { - quad_batch_constructor_reserved_range Result = {}; - Result.OnePastLast = Constructor->Count + TrisNeeded; - Constructor->Count = Result.OnePastLast; - Result.Start = Result.OnePastLast - TrisNeeded; - return Result; + quad_batch_constructor_reserved_range Result = {}; + Result.OnePastLast = Constructor->Count + TrisNeeded; + Constructor->Count = Result.OnePastLast; + Result.Start = Result.OnePastLast - TrisNeeded; + return Result; } internal quad_batch_constructor_reserved_range ThreadSafeReserveRangeInQuadConstructor(render_quad_batch_constructor* Constructor, s32 TrisNeeded) { - quad_batch_constructor_reserved_range Result = {}; - Result.OnePastLast = InterlockedAdd((long*)&Constructor->Count, TrisNeeded); - Result.Start = Result.OnePastLast - TrisNeeded; - return Result; + quad_batch_constructor_reserved_range Result = {}; + Result.OnePastLast = InterlockedAdd((long*)&Constructor->Count, TrisNeeded); + Result.Start = Result.OnePastLast - TrisNeeded; + return Result; } inline void @@ -346,22 +346,22 @@ SetTri3DInBatch (render_quad_batch_constructor* Constructor, s32 TriIndex, v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { - //Assert(P0.w != 0 && P1.w != 0 && P2.w != 0); // Passing vectors, rather than positions. Will draw wrong - - // Vertecies - Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 0)] = P0; - Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 1)] = P1; - Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 2)] = P2; - - // UVs - Constructor->UVs[BATCH_3D_UV_INDEX(TriIndex, 0)] = UV0; - Constructor->UVs[BATCH_3D_UV_INDEX(TriIndex, 1)] = UV1; - Constructor->UVs[BATCH_3D_UV_INDEX(TriIndex, 2)] = UV1; - - // Color V0 - Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 0)] = C0; - Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 1)] = C1; - Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 2)] = C2; + //Assert(P0.w != 0 && P1.w != 0 && P2.w != 0); // Passing vectors, rather than positions. Will draw wrong + + // Vertecies + Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 0)] = P0; + Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 1)] = P1; + Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 2)] = P2; + + // UVs + Constructor->UVs[BATCH_3D_UV_INDEX(TriIndex, 0)] = UV0; + Constructor->UVs[BATCH_3D_UV_INDEX(TriIndex, 1)] = UV1; + Constructor->UVs[BATCH_3D_UV_INDEX(TriIndex, 2)] = UV1; + + // Color V0 + Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 0)] = C0; + Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 1)] = C1; + Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 2)] = C2; } @@ -371,18 +371,18 @@ PushTri3DOnBatch (render_quad_batch_constructor* Constructor, v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { - DEBUG_TRACK_FUNCTION; - // TODO(Peter): I think we avoid doing cross thread filling of a batch so do we need this? - s32 Tri = ThreadSafeIncrementQuadConstructorCount(Constructor); - SetTri3DInBatch(Constructor, Tri, P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); + DEBUG_TRACK_FUNCTION; + // TODO(Peter): I think we avoid doing cross thread filling of a batch so do we need this? + s32 Tri = ThreadSafeIncrementQuadConstructorCount(Constructor); + SetTri3DInBatch(Constructor, Tri, P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); }; internal void PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 P2, v4 P3, v2 UVMin, v2 UVMax, v4 Color) { - Assert(Constructor->Count + 2 <= Constructor->Max); - PushTri3DOnBatch(Constructor, P0, P1, P2, UVMin, v2{UVMax.x, UVMin.y}, UVMax, Color, Color, Color); - PushTri3DOnBatch(Constructor, P0, P2, P3, UVMin, UVMax, v2{UVMin.x, UVMax.y}, Color, Color, Color); + Assert(Constructor->Count + 2 <= Constructor->Max); + PushTri3DOnBatch(Constructor, P0, P1, P2, UVMin, v2{UVMax.x, UVMin.y}, UVMax, Color, Color, Color); + PushTri3DOnBatch(Constructor, P0, P2, P3, UVMin, UVMax, v2{UVMin.x, UVMax.y}, Color, Color, Color); } internal void @@ -391,15 +391,15 @@ PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v2 UV0, v2 UV1, v2 UV2, v2 UV3, v4 C0, v4 C1, v4 C2, v4 C3) { - Assert(Constructor->Count <= Constructor->Max); - PushTri3DOnBatch(Constructor, P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); - PushTri3DOnBatch(Constructor, P0, P2, P3, UV0, UV2, UV3, C0, C2, C3); + Assert(Constructor->Count <= Constructor->Max); + PushTri3DOnBatch(Constructor, P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); + PushTri3DOnBatch(Constructor, P0, P2, P3, UV0, UV2, UV3, C0, C2, C3); } internal void PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 P2, v4 P3, v4 Color) { - PushQuad3DOnBatch(Constructor, P0, P1, P2, P3, v2{0, 0}, v2{1, 1}, Color); + PushQuad3DOnBatch(Constructor, P0, P1, P2, P3, v2{0, 0}, v2{1, 1}, Color); } internal void @@ -408,99 +408,99 @@ PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, v2 UV0, v2 UV1, v2 UV2, v2 UV3, v4 C0, v4 C1, v4 C2, v4 C3) { - DEBUG_TRACK_FUNCTION; - - s32 Quad = ThreadSafeIncrementQuadConstructorCount(Constructor); - v2* Vertecies = (v2*)Constructor->Vertecies; - - // Tri 1 - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 0)] = P0; - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 1)] = P1; - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 2)] = P2; - - // Tri 2 - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 0)] = P0; - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 1)] = P2; - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 2)] = P3; - - // Tri 1 UVs - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 0)] = UV0; - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 1)] = UV1; - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 2)] = UV2; - // Tri 2 UVs - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 0)] = UV0; - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 1)] = UV2; - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 2)] = UV3; - - // Tri 1 Colors - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 0)] = C0; - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 1)] = C1; - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 2)] = C2; - // Tri 2 Colors - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 0)] = C0; - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 1)] = C2; - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 2)] = C3; + DEBUG_TRACK_FUNCTION; + + s32 Quad = ThreadSafeIncrementQuadConstructorCount(Constructor); + v2* Vertecies = (v2*)Constructor->Vertecies; + + // Tri 1 + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 0)] = P0; + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 1)] = P1; + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 2)] = P2; + + // Tri 2 + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 0)] = P0; + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 1)] = P2; + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 2)] = P3; + + // Tri 1 UVs + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 0)] = UV0; + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 1)] = UV1; + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 2)] = UV2; + // Tri 2 UVs + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 0)] = UV0; + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 1)] = UV2; + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 2)] = UV3; + + // Tri 1 Colors + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 0)] = C0; + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 1)] = C1; + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 2)] = C2; + // Tri 2 Colors + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 0)] = C0; + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 1)] = C2; + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 2)] = C3; } internal void PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, v2 P2, v2 P3, v2 UVMin, v2 UVMax, v4 Color) { - DEBUG_TRACK_FUNCTION; - - s32 Quad = ThreadSafeIncrementQuadConstructorCount(Constructor); - v2* Vertecies = (v2*)Constructor->Vertecies; - - // Tri 1 - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 0)] = P0; - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 1)] = P1; - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 2)] = P2; - - // Tri 2 - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 0)] = P0; - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 1)] = P2; - Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 2)] = P3; - - // Tri 1 UVs - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 0)] = UVMin; - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 1)] = v2{UVMax.x, UVMin.y}; - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 2)] = UVMax; - // Tri 2 UVs - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 0)] = UVMin; - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 1)] = UVMax; - Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 2)] = v2{UVMin.x, UVMax.y}; - - // Tri 1 Colors - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 0)] = Color; - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 1)] = Color; - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 2)] = Color; - // Tri 2 Colors - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 0)] = Color; - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 1)] = Color; - Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 2)] = Color; + DEBUG_TRACK_FUNCTION; + + s32 Quad = ThreadSafeIncrementQuadConstructorCount(Constructor); + v2* Vertecies = (v2*)Constructor->Vertecies; + + // Tri 1 + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 0)] = P0; + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 1)] = P1; + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 0, 2)] = P2; + + // Tri 2 + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 0)] = P0; + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 1)] = P2; + Vertecies[BATCH_2D_VERTEX_INDEX(Quad, 1, 2)] = P3; + + // Tri 1 UVs + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 0)] = UVMin; + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 1)] = v2{UVMax.x, UVMin.y}; + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 0, 2)] = UVMax; + // Tri 2 UVs + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 0)] = UVMin; + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 1)] = UVMax; + Constructor->UVs[BATCH_2D_UV_INDEX(Quad, 1, 2)] = v2{UVMin.x, UVMax.y}; + + // Tri 1 Colors + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 0)] = Color; + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 1)] = Color; + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 0, 2)] = Color; + // Tri 2 Colors + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 0)] = Color; + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 1)] = Color; + Constructor->ColorsV[BATCH_2D_COLOR_INDEX(Quad, 1, 2)] = Color; } internal void PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, v2 Min, v2 Max, v4 Color) { - PushQuad2DOnBatch(Constructor, v2{Min.x, Min.y}, v2{Max.x, Min.y}, v2{Max.x, Max.y}, v2{Min.x, Max.y}, - v2{0, 0}, v2{1, 1}, Color); + PushQuad2DOnBatch(Constructor, v2{Min.x, Min.y}, v2{Max.x, Min.y}, v2{Max.x, Max.y}, v2{Min.x, Max.y}, + v2{0, 0}, v2{1, 1}, Color); } internal void PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, rect2 Rect, v4 Color) { - PushQuad2DOnBatch(Constructor, v2{Rect.Min.x, Rect.Min.y}, v2{Rect.Max.x, Rect.Min.y}, v2{Rect.Max.x, Rect.Max.y}, v2{Rect.Min.x, Rect.Max.y}, - v2{0, 0}, v2{1, 1}, Color); + PushQuad2DOnBatch(Constructor, v2{Rect.Min.x, Rect.Min.y}, v2{Rect.Max.x, Rect.Min.y}, v2{Rect.Max.x, Rect.Max.y}, v2{Rect.Min.x, Rect.Max.y}, + v2{0, 0}, v2{1, 1}, Color); } internal void PushLine2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, r32 Thickness, v4 Color) { - r32 HalfThickness = Thickness / 2.0f; - v2 Perpendicular = V2Normalize(V2PerpendicularCCW(P1 - P0)) * HalfThickness; - - PushQuad2DOnBatch(Constructor, P0 - Perpendicular, P1 - Perpendicular, P1 + Perpendicular, P0 + Perpendicular, - v2{0, 0}, v2{1, 1}, Color); + r32 HalfThickness = Thickness / 2.0f; + v2 Perpendicular = V2Normalize(V2PerpendicularCCW(P1 - P0)) * HalfThickness; + + PushQuad2DOnBatch(Constructor, P0 - Perpendicular, P1 - Perpendicular, P1 + Perpendicular, P0 + Perpendicular, + v2{0, 0}, v2{1, 1}, Color); } // Commands @@ -509,174 +509,174 @@ PushLine2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, r32 internal u8* PushRenderCommand_ (render_command_buffer* CommandBuffer, render_command_type CommandType, s32 CommandSize) { - ResizeBufferIfNecessary(CommandBuffer, CommandSize); - Assert(CommandBuffer->CommandMemoryUsed + CommandSize <= CommandBuffer->CommandMemorySize); - - render_command_header* Header = (render_command_header*)(CommandBuffer->CommandMemory + CommandBuffer->CommandMemoryUsed); - Header->Type = CommandType; - - u8* Result = (u8*)(Header + 1); - CommandBuffer->CommandMemoryUsed += CommandSize; - - return Result; + ResizeBufferIfNecessary(CommandBuffer, CommandSize); + Assert(CommandBuffer->CommandMemoryUsed + CommandSize <= CommandBuffer->CommandMemorySize); + + render_command_header* Header = (render_command_header*)(CommandBuffer->CommandMemory + CommandBuffer->CommandMemoryUsed); + Header->Type = CommandType; + + u8* Result = (u8*)(Header + 1); + CommandBuffer->CommandMemoryUsed += CommandSize; + + return Result; } internal render_command_set_render_mode* PushRenderPerspective (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, s32 ViewWidth, s32 ViewHeight, camera Camera) { - render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); - - Command->ModelView = M44Transpose(GetCameraModelViewMatrix(Camera)); - Command->Projection = M44Transpose(GetCameraPerspectiveProjectionMatrix(Camera)); - - Command->ViewOffsetX = (r32)OffsetX; - Command->ViewOffsetY = (r32)OffsetY; - Command->ViewWidth = (r32)ViewWidth; - Command->ViewHeight = (r32)ViewHeight; - - Command->UseDepthBuffer = true; - - return Command; + render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); + + Command->ModelView = M44Transpose(GetCameraModelViewMatrix(Camera)); + Command->Projection = M44Transpose(GetCameraPerspectiveProjectionMatrix(Camera)); + + Command->ViewOffsetX = (r32)OffsetX; + Command->ViewOffsetY = (r32)OffsetY; + Command->ViewWidth = (r32)ViewWidth; + Command->ViewHeight = (r32)ViewHeight; + + Command->UseDepthBuffer = true; + + return Command; } internal void PushRenderPerspective(render_command_buffer* Buffer, rect2 Viewport, camera Camera) { - PushRenderPerspective(Buffer, Viewport.Min.x, Viewport.Min.y, Rect2Width(Viewport), Rect2Height(Viewport), Camera); + PushRenderPerspective(Buffer, Viewport.Min.x, Viewport.Min.y, Rect2Width(Viewport), Rect2Height(Viewport), Camera); } internal void PushRenderOrthographic (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, s32 ViewWidth, s32 ViewHeight) { - render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); - Command->ModelView = M44Identity(); - Command->Projection = M44ProjectionOrtho((r32)ViewWidth, (r32)ViewHeight, 0, 100, ViewWidth, 0, ViewHeight, 0); - - Command->ViewOffsetX = (r32)OffsetX; - Command->ViewOffsetY = (r32)OffsetY; - Command->ViewWidth = ViewWidth; - Command->ViewHeight = ViewHeight; - - Command->UseDepthBuffer = false;; + render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); + Command->ModelView = M44Identity(); + Command->Projection = M44ProjectionOrtho((r32)ViewWidth, (r32)ViewHeight, 0, 100, ViewWidth, 0, ViewHeight, 0); + + Command->ViewOffsetX = (r32)OffsetX; + Command->ViewOffsetY = (r32)OffsetY; + Command->ViewWidth = ViewWidth; + Command->ViewHeight = ViewHeight; + + Command->UseDepthBuffer = false;; } internal void PushRenderOrthographic(render_command_buffer* Buffer, rect2 Viewport) { - PushRenderOrthographic(Buffer, Viewport.Min.x, Viewport.Min.y, Rect2Width(Viewport), Rect2Height(Viewport)); + PushRenderOrthographic(Buffer, Viewport.Min.x, Viewport.Min.y, Rect2Width(Viewport), Rect2Height(Viewport)); } internal void PushRenderClearScreen (render_command_buffer* Buffer) { - render_command_clear_screen* Command = PushRenderCommand(Buffer, render_command_clear_screen); + render_command_clear_screen* Command = PushRenderCommand(Buffer, render_command_clear_screen); } internal render_quad_batch_constructor PushRenderQuad2DBatch(render_command_buffer* Buffer, s32 QuadCount) { - s32 DataSize = BATCH_2D_SIZE(QuadCount); - ResizeBufferIfNecessary(Buffer, DataSize + sizeof(render_batch_command_quad_2d)); - Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize); - - render_quad_batch_constructor Result = {}; - - render_batch_command_quad_2d* Command = PushRenderCommand(Buffer, render_batch_command_quad_2d); - Command->QuadCount = QuadCount; - Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, DataSize, (u8*)(Command + 1)); - - return Result; + s32 DataSize = BATCH_2D_SIZE(QuadCount); + ResizeBufferIfNecessary(Buffer, DataSize + sizeof(render_batch_command_quad_2d)); + Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize); + + render_quad_batch_constructor Result = {}; + + render_batch_command_quad_2d* Command = PushRenderCommand(Buffer, render_batch_command_quad_2d); + Command->QuadCount = QuadCount; + Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, DataSize, (u8*)(Command + 1)); + + return Result; } internal void PushRenderQuad2D (render_command_buffer* Buffer, v2 Min, v2 Max, v4 Color) { - render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); - PushQuad2DOnBatch(&Batch, Min, Max, Color); + render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); + PushQuad2DOnBatch(&Batch, Min, Max, Color); } internal void PushRenderQuad2D (render_command_buffer* Buffer, rect2 Rect, v4 Color) { - render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); - PushQuad2DOnBatch(&Batch, Rect.Min, Rect.Max, Color); + render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); + PushQuad2DOnBatch(&Batch, Rect.Min, Rect.Max, Color); } internal void PushRenderQuad2DClipped (render_command_buffer* Buffer, rect2 Rect, rect2 ClippingBox, v4 Color) { - rect2 Clipped = Rect2Union(Rect, ClippingBox); - render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); - PushQuad2DOnBatch(&Batch, Clipped.Min, Clipped.Max, Color); + rect2 Clipped = Rect2Union(Rect, ClippingBox); + render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); + PushQuad2DOnBatch(&Batch, Clipped.Min, Clipped.Max, Color); } internal void PushRenderQuad2D(render_command_buffer* Buffer, v2 P0, v2 P1, v2 P2, v2 P3, v4 Color) { - render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); - PushQuad2DOnBatch(&Batch, P0, P1, P2, P3, v2{0,0}, v2{1,1}, Color); + render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); + PushQuad2DOnBatch(&Batch, P0, P1, P2, P3, v2{0,0}, v2{1,1}, Color); } internal void PushRenderLine2D (render_command_buffer* Buffer, v2 P0, v2 P1, r32 Thickness, v4 Color) { - render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); - PushLine2DOnBatch(&Batch, P0, P1, Thickness, Color); + render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); + PushLine2DOnBatch(&Batch, P0, P1, Thickness, Color); } internal render_quad_batch_constructor PushRenderQuad3DBatch(render_command_buffer* Buffer, s32 QuadCount) { - s32 TriCount = QuadCount * 2; - s32 DataSize = BATCH_3D_SIZE(TriCount); - ResizeBufferIfNecessary(Buffer, DataSize + sizeof(render_batch_command_quad_3d)); - Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize); - - render_quad_batch_constructor Result = {}; - - render_batch_command_quad_3d* Command = PushRenderCommand(Buffer, render_batch_command_quad_3d); - Command->QuadCount = QuadCount; - Command->DataSize = PushQuad3DBatch(Buffer, &Result, (u8*)(Command + 1), TriCount, DataSize); - - return Result; + s32 TriCount = QuadCount * 2; + s32 DataSize = BATCH_3D_SIZE(TriCount); + ResizeBufferIfNecessary(Buffer, DataSize + sizeof(render_batch_command_quad_3d)); + Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize); + + render_quad_batch_constructor Result = {}; + + render_batch_command_quad_3d* Command = PushRenderCommand(Buffer, render_batch_command_quad_3d); + Command->QuadCount = QuadCount; + Command->DataSize = PushQuad3DBatch(Buffer, &Result, (u8*)(Command + 1), TriCount, DataSize); + + return Result; } internal void PushRenderQuad3D (render_command_buffer* Buffer, v4 A, v4 B, v4 C, v4 D, v4 Color) { - render_quad_batch_constructor Batch = PushRenderQuad3DBatch(Buffer, 1); - PushQuad3DOnBatch(&Batch, A, B, C, D, Color); + render_quad_batch_constructor Batch = PushRenderQuad3DBatch(Buffer, 1); + PushQuad3DOnBatch(&Batch, A, B, C, D, Color); } internal void PushRenderCameraFacingQuad (render_command_buffer* Buffer, v4 Center, v2 Dimensions, v4 Color) { - // TODO(Peter): Turn this into an actual camera facing quad - v4 A = v4{Center.x - Dimensions.x, Center.y - Dimensions.y, Center.z, Center.w}; - v4 B = v4{Center.x + Dimensions.x, Center.y - Dimensions.y, Center.z, Center.w}; - v4 C = v4{Center.x + Dimensions.x, Center.y + Dimensions.y, Center.z, Center.w}; - v4 D = v4{Center.x - Dimensions.x, Center.y + Dimensions.y, Center.z, Center.w}; - - PushRenderQuad3D(Buffer, A, B, C, D, Color); + // TODO(Peter): Turn this into an actual camera facing quad + v4 A = v4{Center.x - Dimensions.x, Center.y - Dimensions.y, Center.z, Center.w}; + v4 B = v4{Center.x + Dimensions.x, Center.y - Dimensions.y, Center.z, Center.w}; + v4 C = v4{Center.x + Dimensions.x, Center.y + Dimensions.y, Center.z, Center.w}; + v4 D = v4{Center.x - Dimensions.x, Center.y + Dimensions.y, Center.z, Center.w}; + + PushRenderQuad3D(Buffer, A, B, C, D, Color); } internal render_quad_batch_constructor PushRenderTexture2DBatch(render_command_buffer* Buffer, s32 QuadCount, render_texture Texture) { - s32 DataSize = BATCH_2D_SIZE(QuadCount); - ResizeBufferIfNecessary(Buffer, DataSize); - Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize); - - render_quad_batch_constructor Result = {}; - - render_batch_command_texture_2d* Command = PushRenderCommand(Buffer, render_batch_command_texture_2d); - Command->QuadCount = QuadCount; - Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, DataSize, (u8*)(Command + 1)); - Command->Texture = Texture; - - return Result; + s32 DataSize = BATCH_2D_SIZE(QuadCount); + ResizeBufferIfNecessary(Buffer, DataSize); + Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize); + + render_quad_batch_constructor Result = {}; + + render_batch_command_texture_2d* Command = PushRenderCommand(Buffer, render_batch_command_texture_2d); + Command->QuadCount = QuadCount; + Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, DataSize, (u8*)(Command + 1)); + Command->Texture = Texture; + + return Result; } internal render_quad_batch_constructor @@ -684,14 +684,14 @@ PushRenderTexture2DBatch (render_command_buffer* Buffer, s32 QuadCount, u8* TextureMemory, s32 TextureHandle, s32 TextureWidth, s32 TextureHeight, s32 TextureBytesPerPixel, s32 TextureStride) { - render_texture Texture = render_texture{ - TextureMemory, - TextureHandle, - TextureWidth, - TextureHeight, - TextureBytesPerPixel, - TextureStride}; - return PushRenderTexture2DBatch(Buffer, QuadCount, Texture); + render_texture Texture = render_texture{ + TextureMemory, + TextureHandle, + TextureWidth, + TextureHeight, + TextureBytesPerPixel, + TextureStride}; + return PushRenderTexture2DBatch(Buffer, QuadCount, Texture); } internal void @@ -699,19 +699,19 @@ PushRenderTexture2D (render_command_buffer* Buffer, v2 Min, v2 Max, v4 Color, v2 UVMin, v2 UVMax, render_texture* Texture) { - render_quad_batch_constructor Batch = PushRenderTexture2DBatch(Buffer, 1, *Texture); - PushQuad2DOnBatch(&Batch, v2{Min.x, Min.y}, v2{Max.x, Min.y}, v2{Max.x, Max.y}, v2{Min.x, Max.y}, - UVMin, UVMax, Color); + render_quad_batch_constructor Batch = PushRenderTexture2DBatch(Buffer, 1, *Texture); + PushQuad2DOnBatch(&Batch, v2{Min.x, Min.y}, v2{Max.x, Min.y}, v2{Max.x, Max.y}, v2{Min.x, Max.y}, + UVMin, UVMax, Color); } internal void PushRenderBoundingBox2D (render_command_buffer* Buffer, v2 Min, v2 Max, r32 Thickness, v4 Color) { - render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 4); - PushQuad2DOnBatch(&Batch, Min, v2{Min.x + Thickness, Max.y}, Color); - PushQuad2DOnBatch(&Batch, v2{Min.x, Max.y - Thickness}, Max, Color); - PushQuad2DOnBatch(&Batch, v2{Max.x - Thickness, Min.y}, Max, Color); - PushQuad2DOnBatch(&Batch, Min, v2{Max.x, Min.y + Thickness}, Color); + render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 4); + PushQuad2DOnBatch(&Batch, Min, v2{Min.x + Thickness, Max.y}, Color); + PushQuad2DOnBatch(&Batch, v2{Min.x, Max.y - Thickness}, Max, Color); + PushQuad2DOnBatch(&Batch, v2{Max.x - Thickness, Min.y}, Max, Color); + PushQuad2DOnBatch(&Batch, Min, v2{Max.x, Min.y + Thickness}, Color); } diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index bb3edde..4a4752d 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -40,8 +40,8 @@ window MainWindow; PLATFORM_GET_GPU_TEXTURE_HANDLE(Win32GetGPUTextureHandle) { - s32 Handle = SubmitTexture(Memory, Width, Height); - return Handle; + s32 Handle = SubmitTexture(Memory, Width, Height); + return Handle; } HDC FontDrawingDC; @@ -50,462 +50,462 @@ HFONT CurrentFont; GET_FONT_INFO(Win32GetFontInfo) { - platform_font_info Result = {}; - - FontDrawingDC = CreateCompatibleDC(NULL); - SetBkColor(FontDrawingDC, RGB(0, 0, 0)); - SetTextColor(FontDrawingDC, RGB(255, 255, 255)); - FontBitmap = CreateCompatibleBitmap(FontDrawingDC, PixelHeight * 2, PixelHeight * 2); - HGDIOBJ SelectObjectResult = SelectObject(FontDrawingDC, FontBitmap); - - CurrentFont = CreateFont(PixelHeight, 0, 0, 0, - FontWeight, - Italic, - Underline, - Strikeout, - ANSI_CHARSET, - OUT_OUTLINE_PRECIS, - CLIP_DEFAULT_PRECIS, - PROOF_QUALITY, - FIXED_PITCH, - FontName); - SelectFont(FontDrawingDC, CurrentFont); - - TEXTMETRIC WindowsFontMetrics = {}; - if (GetTextMetrics(FontDrawingDC, &WindowsFontMetrics)) - { - Result.PixelHeight = WindowsFontMetrics.tmHeight; - Result.Ascent = WindowsFontMetrics.tmAscent; - Result.Descent = WindowsFontMetrics.tmDescent; - Result.Leading = WindowsFontMetrics.tmExternalLeading; - Result.MaxCharWidth = WindowsFontMetrics.tmMaxCharWidth; - Result.CodepointStart = WindowsFontMetrics.tmFirstChar; - Result.CodepointOnePastLast = WindowsFontMetrics.tmLastChar + 1; - } - - return Result; + platform_font_info Result = {}; + + FontDrawingDC = CreateCompatibleDC(NULL); + SetBkColor(FontDrawingDC, RGB(0, 0, 0)); + SetTextColor(FontDrawingDC, RGB(255, 255, 255)); + FontBitmap = CreateCompatibleBitmap(FontDrawingDC, PixelHeight * 2, PixelHeight * 2); + HGDIOBJ SelectObjectResult = SelectObject(FontDrawingDC, FontBitmap); + + CurrentFont = CreateFont(PixelHeight, 0, 0, 0, + FontWeight, + Italic, + Underline, + Strikeout, + ANSI_CHARSET, + OUT_OUTLINE_PRECIS, + CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, + FIXED_PITCH, + FontName); + SelectFont(FontDrawingDC, CurrentFont); + + TEXTMETRIC WindowsFontMetrics = {}; + if (GetTextMetrics(FontDrawingDC, &WindowsFontMetrics)) + { + Result.PixelHeight = WindowsFontMetrics.tmHeight; + Result.Ascent = WindowsFontMetrics.tmAscent; + Result.Descent = WindowsFontMetrics.tmDescent; + Result.Leading = WindowsFontMetrics.tmExternalLeading; + Result.MaxCharWidth = WindowsFontMetrics.tmMaxCharWidth; + Result.CodepointStart = WindowsFontMetrics.tmFirstChar; + Result.CodepointOnePastLast = WindowsFontMetrics.tmLastChar + 1; + } + + return Result; } DRAW_FONT_CODEPOINT(Win32DrawFontCodepoint) { - SIZE CodepointSize = {}; - if (GetTextExtentPoint32(FontDrawingDC, &Codepoint, 1, &CodepointSize)) + SIZE CodepointSize = {}; + if (GetTextExtentPoint32(FontDrawingDC, &Codepoint, 1, &CodepointSize)) + { + *OutWidth = CodepointSize.cx; + *OutHeight = CodepointSize.cy; + + RECT TextRect = {}; + TextRect.left = 0; + TextRect.right = *OutWidth; + TextRect.top = 0; + TextRect.bottom = *OutHeight; + + int Error = DrawText(FontDrawingDC, &Codepoint, 1, &TextRect, DT_LEFT | DT_NOCLIP | DT_TOP); + + u8* Row = DestBuffer + (YOffset * (DestBufferWidth * 4)); + COLORREF PixelColor; + for (u32 Y = 0; Y < *OutHeight; Y++) { - *OutWidth = CodepointSize.cx; - *OutHeight = CodepointSize.cy; - - RECT TextRect = {}; - TextRect.left = 0; - TextRect.right = *OutWidth; - TextRect.top = 0; - TextRect.bottom = *OutHeight; - - int Error = DrawText(FontDrawingDC, &Codepoint, 1, &TextRect, DT_LEFT | DT_NOCLIP | DT_TOP); - - u8* Row = DestBuffer + (YOffset * (DestBufferWidth * 4)); - COLORREF PixelColor; - for (u32 Y = 0; Y < *OutHeight; Y++) - { - // NOTE(Peter): XOffset * 4 b/c its 4 bytes per pixel. - u8* Channel = (u8*)Row + (XOffset * 4); - for (u32 X = 0; X < *OutWidth; X++) - { - PixelColor = GetPixel(FontDrawingDC, X + TextRect.left, TextRect.bottom - Y); - Assert(PixelColor != CLR_INVALID); - u8 RValue = GetRValue(PixelColor); - *Channel++ = RValue; - *Channel++ = RValue; - *Channel++ = RValue; - *Channel++ = RValue; - } - Row += DestBufferWidth * 4; - } - + // NOTE(Peter): XOffset * 4 b/c its 4 bytes per pixel. + u8* Channel = (u8*)Row + (XOffset * 4); + for (u32 X = 0; X < *OutWidth; X++) + { + PixelColor = GetPixel(FontDrawingDC, X + TextRect.left, TextRect.bottom - Y); + Assert(PixelColor != CLR_INVALID); + u8 RValue = GetRValue(PixelColor); + *Channel++ = RValue; + *Channel++ = RValue; + *Channel++ = RValue; + *Channel++ = RValue; + } + Row += DestBufferWidth * 4; } + + } } LRESULT CALLBACK HandleWindowEvents (HWND WindowHandle, UINT Msg, WPARAM WParam, LPARAM LParam) { - LRESULT Result = 0; - - switch (Msg) + LRESULT Result = 0; + + switch (Msg) + { + case WM_SIZE: { - case WM_SIZE: - { - Win32UpdateWindowDimension(&MainWindow); - //Win32ResizeDIBSection(&GlobalBackbuffer, MainWindow.Info.Width, MainWindow.Info.Height); - }break; - - case WM_CLOSE: - { - Result = DefWindowProc(WindowHandle, Msg, WParam, LParam); - Running = false; - }break; - - case WM_DESTROY: - { - }break; - - case WM_PAINT: - { - PAINTSTRUCT PaintStruct; - HDC DeviceContext; - b32 PaintResult; - - DeviceContext = BeginPaint(WindowHandle, &PaintStruct); - PaintResult = EndPaint(WindowHandle, &PaintStruct); - }break; - - case WM_ACTIVATE: - { - WindowIsActive = (LOWORD(WParam) == WA_ACTIVE || LOWORD(WParam) == WA_CLICKACTIVE); - }break; - - default: - { - Result = DefWindowProc(WindowHandle, Msg, WParam, LParam); - } - } + Win32UpdateWindowDimension(&MainWindow); + //Win32ResizeDIBSection(&GlobalBackbuffer, MainWindow.Info.Width, MainWindow.Info.Height); + }break; - return Result; + case WM_CLOSE: + { + Result = DefWindowProc(WindowHandle, Msg, WParam, LParam); + Running = false; + }break; + + case WM_DESTROY: + { + }break; + + case WM_PAINT: + { + PAINTSTRUCT PaintStruct; + HDC DeviceContext; + b32 PaintResult; + + DeviceContext = BeginPaint(WindowHandle, &PaintStruct); + PaintResult = EndPaint(WindowHandle, &PaintStruct); + }break; + + case WM_ACTIVATE: + { + WindowIsActive = (LOWORD(WParam) == WA_ACTIVE || LOWORD(WParam) == WA_CLICKACTIVE); + }break; + + default: + { + Result = DefWindowProc(WindowHandle, Msg, WParam, LParam); + } + } + + return Result; } internal void HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse_state* Mouse) { - switch (Message.message) + switch (Message.message) + { + case WM_MOUSEWHEEL: + { + Mouse->Scroll = GET_WHEEL_DELTA_WPARAM(Message.wParam); + }break; + + case WM_LBUTTONDOWN: + { + b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; + b32 AltDown = GetKeyState(VK_MENU) & 0x8000; + b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; + + AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true, + ShiftDown, AltDown, CtrlDown, false); + + Mouse->LeftButtonState |= KeyState_IsDown; + Mouse->DownPos = Mouse->Pos; + + // :Win32MouseEventCapture + // NOTE(Peter): We capture events when the mouse goes down so that + // if the user drags outside the window, we still get the mouse up + // event and can process it. Otherwise, we can get into cases where + // an event was started, didn't end, but the user can click again and + // try to start the event again. + // We relase event capture on mouse up. + SetCapture(Window->Handle); + }break; + + case WM_MBUTTONDOWN: + { + b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; + b32 AltDown = GetKeyState(VK_MENU) & 0x8000; + b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; + + AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true, + ShiftDown, AltDown, CtrlDown, false); + Mouse->MiddleButtonState = KeyState_IsDown & ~KeyState_WasDown; + + // :Win32MouseEventCapture + SetCapture(Window->Handle); + }break; + + case WM_RBUTTONDOWN: + { + b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; + b32 AltDown = GetKeyState(VK_MENU) & 0x8000; + b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; + + AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true, + ShiftDown, AltDown, CtrlDown, false); + Mouse->RightButtonState = KeyState_IsDown & ~KeyState_WasDown; + Mouse->DownPos = Mouse->Pos; + + // :Win32MouseEventCapture + SetCapture(Window->Handle); + }break; + + case WM_LBUTTONUP: + { + b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; + b32 AltDown = GetKeyState(VK_MENU) & 0x8000; + b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; + + AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false, + ShiftDown, AltDown, CtrlDown, false); + Mouse->LeftButtonState &= ~KeyState_IsDown; + + // :Win32MouseEventCapture + ReleaseCapture(); + }break; + + case WM_MBUTTONUP: + { + b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; + b32 AltDown = GetKeyState(VK_MENU) & 0x8000; + b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; + + AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false, + ShiftDown, AltDown, CtrlDown, false); + Mouse->MiddleButtonState = ~KeyState_IsDown & KeyState_WasDown; + + // :Win32MouseEventCapture + ReleaseCapture(); + }break; + + case WM_RBUTTONUP: + { + b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; + b32 AltDown = GetKeyState(VK_MENU) & 0x8000; + b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; + + AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false, + ShiftDown, AltDown, CtrlDown, false); + Mouse->RightButtonState = ~KeyState_IsDown & KeyState_WasDown; + + // :Win32MouseEventCapture + ReleaseCapture(); + }break; + + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_KEYDOWN: + case WM_KEYUP: { - case WM_MOUSEWHEEL: - { - Mouse->Scroll = GET_WHEEL_DELTA_WPARAM(Message.wParam); - }break; - - case WM_LBUTTONDOWN: - { - b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; - b32 AltDown = GetKeyState(VK_MENU) & 0x8000; - b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - - AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true, - ShiftDown, AltDown, CtrlDown, false); - - Mouse->LeftButtonState |= KeyState_IsDown; - Mouse->DownPos = Mouse->Pos; - - // :Win32MouseEventCapture - // NOTE(Peter): We capture events when the mouse goes down so that - // if the user drags outside the window, we still get the mouse up - // event and can process it. Otherwise, we can get into cases where - // an event was started, didn't end, but the user can click again and - // try to start the event again. - // We relase event capture on mouse up. - SetCapture(Window->Handle); - }break; - - case WM_MBUTTONDOWN: - { - b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; - b32 AltDown = GetKeyState(VK_MENU) & 0x8000; - b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - - AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true, - ShiftDown, AltDown, CtrlDown, false); - Mouse->MiddleButtonState = KeyState_IsDown & ~KeyState_WasDown; - - // :Win32MouseEventCapture - SetCapture(Window->Handle); - }break; - - case WM_RBUTTONDOWN: - { - b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; - b32 AltDown = GetKeyState(VK_MENU) & 0x8000; - b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - - AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true, - ShiftDown, AltDown, CtrlDown, false); - Mouse->RightButtonState = KeyState_IsDown & ~KeyState_WasDown; - Mouse->DownPos = Mouse->Pos; - - // :Win32MouseEventCapture - SetCapture(Window->Handle); - }break; - - case WM_LBUTTONUP: - { - b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; - b32 AltDown = GetKeyState(VK_MENU) & 0x8000; - b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - - AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false, - ShiftDown, AltDown, CtrlDown, false); - Mouse->LeftButtonState &= ~KeyState_IsDown; - - // :Win32MouseEventCapture - ReleaseCapture(); - }break; - - case WM_MBUTTONUP: - { - b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; - b32 AltDown = GetKeyState(VK_MENU) & 0x8000; - b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - - AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false, - ShiftDown, AltDown, CtrlDown, false); - Mouse->MiddleButtonState = ~KeyState_IsDown & KeyState_WasDown; - - // :Win32MouseEventCapture - ReleaseCapture(); - }break; - - case WM_RBUTTONUP: - { - b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; - b32 AltDown = GetKeyState(VK_MENU) & 0x8000; - b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - - AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false, - ShiftDown, AltDown, CtrlDown, false); - Mouse->RightButtonState = ~KeyState_IsDown & KeyState_WasDown; - - // :Win32MouseEventCapture - ReleaseCapture(); - }break; - - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - case WM_KEYDOWN: - case WM_KEYUP: - { #if 0 - int VirtualKey = (int)Message.wParam; - key_code Key = Win32GetKeyCode(VirtualKey, true, false); - s32 KeyIndex = (int)Key; - - b32 KeyWasDown = (Message.lParam & (1 << 30)) != 0; - b32 KeyIsDown = (Message.lParam & (1 << 31)) == 0; - - b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; - b32 AltDown = GetKeyState(VK_MENU) & 0x8000; - b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - - // New Input Queue - AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown, - ShiftDown, AltDown, CtrlDown, false); + int VirtualKey = (int)Message.wParam; + key_code Key = Win32GetKeyCode(VirtualKey, true, false); + s32 KeyIndex = (int)Key; + + b32 KeyWasDown = (Message.lParam & (1 << 30)) != 0; + b32 KeyIsDown = (Message.lParam & (1 << 31)) == 0; + + b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; + b32 AltDown = GetKeyState(VK_MENU) & 0x8000; + b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; + + // New Input Queue + AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown, + ShiftDown, AltDown, CtrlDown, false); #endif - TranslateMessage(&Message); - DispatchMessage(&Message); - }break; - - case WM_CHAR: - { - char VirtualKey = (char)Message.wParam; - key_code Key = CharToKeyCode(VirtualKey); - s32 KeyIndex = (int)Key; - - b32 KeyWasDown = (Message.lParam & (1 << 30)) != 0; - b32 KeyIsDown = (Message.lParam & (1 << 31)) == 0; - - b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; - b32 AltDown = GetKeyState(VK_MENU) & 0x8000; - b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - - // New Input Queue - AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown, - ShiftDown, AltDown, CtrlDown, false); - }break; - - default: - { - TranslateMessage(&Message); - DispatchMessage(&Message); - }break; - } + TranslateMessage(&Message); + DispatchMessage(&Message); + }break; + + case WM_CHAR: + { + char VirtualKey = (char)Message.wParam; + key_code Key = CharToKeyCode(VirtualKey); + s32 KeyIndex = (int)Key; + + b32 KeyWasDown = (Message.lParam & (1 << 30)) != 0; + b32 KeyIsDown = (Message.lParam & (1 << 31)) == 0; + + b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000; + b32 AltDown = GetKeyState(VK_MENU) & 0x8000; + b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; + + // New Input Queue + AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown, + ShiftDown, AltDown, CtrlDown, false); + }break; + + default: + { + TranslateMessage(&Message); + DispatchMessage(&Message); + }break; + } } internal void DebugPrint (char* Format, ...) { - char Buffer[256]; - gs_string StringBuffer = MakeString(Buffer, 256); - va_list Args; - va_start(Args, Format); - Log_PrintFVarArgs(GlobalLogBuffer, LogEntry_Message, Format, Args); - va_end(Args); + char Buffer[256]; + gs_string StringBuffer = MakeString(Buffer, 256); + va_list Args; + va_start(Args, Format); + Log_PrintFVarArgs(GlobalLogBuffer, LogEntry_Message, Format, Args); + va_end(Args); } internal void SetApplicationLinks (context* Context, win32_dll_refresh DLL, gs_work_queue* WorkQueue) { - if (DLL.IsValid) - { - Context->InitializeApplication = (initialize_application*)GetProcAddress(DLL.DLL, "InitializeApplication"); - Context->ReloadStaticData = (reload_static_data*)GetProcAddress(DLL.DLL, "ReloadStaticData"); - Context->UpdateAndRender = (update_and_render*)GetProcAddress(DLL.DLL, "UpdateAndRender"); - Context->CleanupApplication = (cleanup_application*)GetProcAddress(DLL.DLL, "CleanupApplication"); - } - else - { - Context->InitializeApplication = 0; - Context->ReloadStaticData = 0; - Context->UpdateAndRender = 0; - Context->CleanupApplication = 0; - } + if (DLL.IsValid) + { + Context->InitializeApplication = (initialize_application*)GetProcAddress(DLL.DLL, "InitializeApplication"); + Context->ReloadStaticData = (reload_static_data*)GetProcAddress(DLL.DLL, "ReloadStaticData"); + Context->UpdateAndRender = (update_and_render*)GetProcAddress(DLL.DLL, "UpdateAndRender"); + Context->CleanupApplication = (cleanup_application*)GetProcAddress(DLL.DLL, "CleanupApplication"); + } + else + { + Context->InitializeApplication = 0; + Context->ReloadStaticData = 0; + Context->UpdateAndRender = 0; + Context->CleanupApplication = 0; + } } internal void Win32_SendAddressedDataBuffer(gs_thread_context Context, addressed_data_buffer* BufferAt) { - DEBUG_TRACK_FUNCTION; - - u32 BuffersSent = 0; - u32 DataSizeSent = 0; - - switch(BufferAt->AddressType) + DEBUG_TRACK_FUNCTION; + + u32 BuffersSent = 0; + u32 DataSizeSent = 0; + + switch(BufferAt->AddressType) + { + case AddressType_NetworkIP: { - case AddressType_NetworkIP: + Win32Socket_SendTo(BufferAt->SendSocket, + BufferAt->V4SendAddress, + BufferAt->SendPort, + (const char*)BufferAt->Memory, + BufferAt->MemorySize, + 0); + }break; + + case AddressType_ComPort: + { + if (BufferAt->ComPort.Length > 0) + { + HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1, Context.Transient); + if (SerialPort != INVALID_HANDLE_VALUE) { - Win32Socket_SendTo(BufferAt->SendSocket, - BufferAt->V4SendAddress, - BufferAt->SendPort, - (const char*)BufferAt->Memory, - BufferAt->MemorySize, - 0); - }break; - - case AddressType_ComPort: - { - if (BufferAt->ComPort.Length > 0) - { - HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1, Context.Transient); - if (SerialPort != INVALID_HANDLE_VALUE) - { - if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) - { - BuffersSent += 1; - DataSizeSent += BufferAt->Data.Size; - } - else - { - Win32SerialArray_Close(BufferAt->ComPort); - } - } - } - else - { + if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) + { + BuffersSent += 1; + DataSizeSent += BufferAt->Data.Size; + } + else + { + Win32SerialArray_Close(BufferAt->ComPort); + } + } + } + else + { #if 0 - Log_Message(GlobalLogBuffer, - "Skipping data buffer because its COM Port isn't set"); + Log_Message(GlobalLogBuffer, + "Skipping data buffer because its COM Port isn't set"); #endif - } - }break; - - InvalidDefaultCase; - } + } + }break; + + InvalidDefaultCase; + } } internal void Win32_SendAddressedDataBuffer_Job(gs_thread_context Context, gs_data Arg) { - addressed_data_buffer* OutputData = (addressed_data_buffer*)Arg.Memory; - Win32_SendAddressedDataBuffer(Context, OutputData); + addressed_data_buffer* OutputData = (addressed_data_buffer*)Arg.Memory; + Win32_SendAddressedDataBuffer(Context, OutputData); } internal bool ReloadAndLinkDLL(win32_dll_refresh* DLL, context* Context, gs_work_queue* WorkQueue, bool ShouldError, bool AppReady) { - bool Success = false; - if (HotLoadDLL(DLL)) - { - SetApplicationLinks(Context, *DLL, WorkQueue); - Context->ReloadStaticData(*Context, GlobalDebugServices, GlobalLogBuffer, AppReady); - Success = true; - Log_Message(GlobalLogBuffer, "Reloaded DLL\n"); - } - else if(ShouldError) - { - Log_Error(GlobalLogBuffer, "Unable to load application DLL at startup.\nAborting\n"); - } - return Success; + bool Success = false; + if (HotLoadDLL(DLL)) + { + SetApplicationLinks(Context, *DLL, WorkQueue); + Context->ReloadStaticData(*Context, GlobalDebugServices, GlobalLogBuffer, AppReady); + Success = true; + Log_Message(GlobalLogBuffer, "Reloaded DLL\n"); + } + else if(ShouldError) + { + Log_Error(GlobalLogBuffer, "Unable to load application DLL at startup.\nAborting\n"); + } + return Success; } internal gs_const_string GetExePath(HINSTANCE HInstance, gs_thread_context ThreadContext) { - gs_const_string Result = {}; - - u32 Error = 0; - u32 PathSize = MAX_PATH; - char* Path = PushArray(ThreadContext.Transient, char, PathSize); - DWORD Length = GetModuleFileNameA(HInstance, Path, PathSize); - - if (Length) - { - Error = GetLastError(); - if (Error == ERROR_INSUFFICIENT_BUFFER) { - // PathSize wasn't long enough - // TODO(pjs): handle this case - InvalidCodePath; - } - - Result.Str = Path; - Result.Length = (u64)Length; - } - else - { - Error = GetLastError(); - InvalidCodePath; + gs_const_string Result = {}; + + u32 Error = 0; + u32 PathSize = MAX_PATH; + char* Path = PushArray(ThreadContext.Transient, char, PathSize); + DWORD Length = GetModuleFileNameA(HInstance, Path, PathSize); + + if (Length) + { + Error = GetLastError(); + if (Error == ERROR_INSUFFICIENT_BUFFER) { + // PathSize wasn't long enough + // TODO(pjs): handle this case + InvalidCodePath; } - return Result; + Result.Str = Path; + Result.Length = (u64)Length; + } + else + { + Error = GetLastError(); + InvalidCodePath; + } + + return Result; } internal bool SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext) { - bool Result = false; + bool Result = false; + + gs_const_string ExePath = GetExePath(HInstance, ThreadContext); + gs_string ScratchPath = PushString(ThreadContext.Transient, ExePath.Length + 128); + gs_string WorkingDirectory = PushString(ThreadContext.Transient, ExePath.Length + 128); + + while (WorkingDirectory.Length == 0) + { + s64 LastSlash = FindLastFromSet(ExePath, "\\/"); + if (LastSlash < 0) break; - gs_const_string ExePath = GetExePath(HInstance, ThreadContext); - gs_string ScratchPath = PushString(ThreadContext.Transient, ExePath.Length + 128); - gs_string WorkingDirectory = PushString(ThreadContext.Transient, ExePath.Length + 128); + ExePath = Substring(ExePath, 0, LastSlash); + PrintF(&ScratchPath, "%S\\data", ExePath); + NullTerminate(&ScratchPath); - while (WorkingDirectory.Length == 0) - { - s64 LastSlash = FindLastFromSet(ExePath, "\\/"); - if (LastSlash < 0) break; - - ExePath = Substring(ExePath, 0, LastSlash); - PrintF(&ScratchPath, "%S\\data", ExePath); - NullTerminate(&ScratchPath); - - gs_file_info PathInfo = GetFileInfo(ThreadContext.FileHandler, ScratchPath.ConstString); - if (PathInfo.Path.Length > 0 && - PathInfo.IsDirectory) { - PrintF(&WorkingDirectory, "%S", ExePath); - NullTerminate(&WorkingDirectory); - } + gs_file_info PathInfo = GetFileInfo(ThreadContext.FileHandler, ScratchPath.ConstString); + if (PathInfo.Path.Length > 0 && + PathInfo.IsDirectory) { + PrintF(&WorkingDirectory, "%S", ExePath); + NullTerminate(&WorkingDirectory); } - - if (WorkingDirectory.Length > 0) + } + + if (WorkingDirectory.Length > 0) + { + Log_Message(GlobalLogBuffer, + "Setting Working Directory \n%S \n", + WorkingDirectory.ConstString); + Result = SetCurrentDirectory(WorkingDirectory.Str); + if (!Result) { - Log_Message(GlobalLogBuffer, - "Setting Working Directory \n%S \n", - WorkingDirectory.ConstString); - Result = SetCurrentDirectory(WorkingDirectory.Str); - if (!Result) - { - u32 Error = GetLastError(); - InvalidCodePath; - } + u32 Error = GetLastError(); + InvalidCodePath; } - else - { - Log_Error(GlobalLogBuffer, "Error, no data folder found\n"); - } - - return Result; + } + else + { + Log_Error(GlobalLogBuffer, "Error, no data folder found\n"); + } + + return Result; } #include "../../gs_libs/gs_path.h" @@ -513,67 +513,67 @@ SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext) internal void Win32_SendOutputData(gs_thread_context ThreadContext, addressed_data_buffer_list OutputData) { - bool Multithread = true; - if (Multithread) + bool Multithread = true; + if (Multithread) + { + for (addressed_data_buffer* At = OutputData.Root; + At != 0; + At = At->Next) { - for (addressed_data_buffer* At = OutputData.Root; - At != 0; - At = At->Next) - { - gs_data ProcArg = {}; - ProcArg.Memory = (u8*)At; - ProcArg.Size = sizeof(addressed_data_buffer); - Win32PushWorkOnQueue(&Win32WorkQueue.WorkQueue, Win32_SendAddressedDataBuffer_Job, ProcArg, ConstString("Send UART Data")); - } + gs_data ProcArg = {}; + ProcArg.Memory = (u8*)At; + ProcArg.Size = sizeof(addressed_data_buffer); + Win32PushWorkOnQueue(&Win32WorkQueue.WorkQueue, Win32_SendAddressedDataBuffer_Job, ProcArg, ConstString("Send UART Data")); } - else + } + else + { + for (addressed_data_buffer* At = OutputData.Root; + At != 0; + At = At->Next) { - for (addressed_data_buffer* At = OutputData.Root; - At != 0; - At = At->Next) - { - gs_data ProcArg = {}; - ProcArg.Memory = (u8*)At; - ProcArg.Size = sizeof(addressed_data_buffer); - Win32_SendAddressedDataBuffer_Job(ThreadContext, ProcArg); - } + gs_data ProcArg = {}; + ProcArg.Memory = (u8*)At; + ProcArg.Size = sizeof(addressed_data_buffer); + Win32_SendAddressedDataBuffer_Job(ThreadContext, ProcArg); } - + } + } // Time internal system_time Win32GetSystemTime() { - system_time Result = {}; + system_time Result = {}; + + SYSTEMTIME WinLocalTime; + GetLocalTime(&WinLocalTime); + + SYSTEMTIME WinSysTime; + FILETIME WinSysFileTime; + GetSystemTime(&WinSysTime); + if (SystemTimeToFileTime((const SYSTEMTIME*)&WinSysTime, &WinSysFileTime)) + { + ULARGE_INTEGER SysTime = {}; + SysTime.LowPart = WinSysFileTime.dwLowDateTime; + SysTime.HighPart = WinSysFileTime.dwHighDateTime; - SYSTEMTIME WinLocalTime; - GetLocalTime(&WinLocalTime); - - SYSTEMTIME WinSysTime; - FILETIME WinSysFileTime; - GetSystemTime(&WinSysTime); - if (SystemTimeToFileTime((const SYSTEMTIME*)&WinSysTime, &WinSysFileTime)) - { - ULARGE_INTEGER SysTime = {}; - SysTime.LowPart = WinSysFileTime.dwLowDateTime; - SysTime.HighPart = WinSysFileTime.dwHighDateTime; - - Result.NanosSinceEpoch = SysTime.QuadPart; - Result.Year = WinLocalTime.wYear; - Result.Month = WinLocalTime.wMonth; - Result.Day = WinLocalTime.wDay; - Result.Hour = WinLocalTime.wHour; - Result.Minute = WinLocalTime.wMinute; - Result.Second = WinLocalTime.wSecond; - } - else - { - u32 Error = GetLastError(); - InvalidCodePath; - } - - return Result; + Result.NanosSinceEpoch = SysTime.QuadPart; + Result.Year = WinLocalTime.wYear; + Result.Month = WinLocalTime.wMonth; + Result.Day = WinLocalTime.wDay; + Result.Hour = WinLocalTime.wHour; + Result.Minute = WinLocalTime.wMinute; + Result.Second = WinLocalTime.wSecond; + } + else + { + u32 Error = GetLastError(); + InvalidCodePath; + } + + return Result; } int WINAPI @@ -584,203 +584,202 @@ WinMain ( INT NCmdShow ) { - gs_thread_context ThreadContext = Win32CreateThreadContext(); - GlobalLogBuffer = AllocatorAllocStruct(ThreadContext.Allocator, log_buffer); - *GlobalLogBuffer = Log_Init(ThreadContext.Allocator, 32); + gs_thread_context ThreadContext = Win32CreateThreadContext(); + + gs_memory_arena PlatformPermanent = MemoryArenaCreate(MB(4), + Bytes(8), ThreadContext.Allocator, + 0, + 0, + "Platform Memory"); + + GlobalLogBuffer = AllocStruct(ThreadContext.Allocator, log_buffer, "Global Log Buffer"); + *GlobalLogBuffer = Log_Init(&PlatformPermanent, 32); + + if (!SetWorkingDirectory(HInstance, ThreadContext)) return 1; + + context Context = {}; + Context.ThreadContext = ThreadContext; + Context.SystemTime_Current = Win32GetSystemTime(); + + gs_const_string Args = ConstString((char*)CmdLineArgs); + if (StringsEqual(Args, ConstString("-headless"))) + { + Log_Message(GlobalLogBuffer, "Running Headless\n"); + Context.Headless = true; + } + + if (!Context.Headless) + { + MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); + Win32UpdateWindowDimension(&MainWindow); - gs_allocator_debug AllocDebug = {}; - AllocDebug.AllocationsCountMax = 4096; - AllocDebug.Allocations = AllocatorAllocArray(ThreadContext.Allocator, gs_debug_allocation, AllocDebug.AllocationsCountMax); - - ThreadContext.Allocator.Debug = &AllocDebug; - - if (!SetWorkingDirectory(HInstance, ThreadContext)) return 1; - - context Context = {}; - Context.ThreadContext = ThreadContext; - Context.SystemTime_Current = Win32GetSystemTime(); - - gs_const_string Args = ConstString((char*)CmdLineArgs); - if (StringsEqual(Args, ConstString("-headless"))) - { - Log_Message(GlobalLogBuffer, "Running Headless\n"); - Context.Headless = true; - } - - if (!Context.Headless) - { - MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); - Win32UpdateWindowDimension(&MainWindow); - - win32_opengl_window_info OpenGLWindowInfo = {}; - OpenGLWindowInfo.ColorBits = 32; - OpenGLWindowInfo.AlphaBits = 8; - OpenGLWindowInfo.DepthBits = 0; - CreateOpenGLWindowContext(OpenGLWindowInfo, &MainWindow); - } - - gs_memory_arena PlatformPermanent = CreateMemoryArena(Context.ThreadContext.Allocator, "Platform Memory"); - - s64 PerformanceCountFrequency = GetPerformanceFrequency(); - s64 LastFrameEnd = GetWallClock(); - r32 TargetSecondsPerFrame = 1 / 30.0f; - r32 LastFrameSecondsElapsed = 0.0f; - - GlobalDebugServices = PushStruct(&PlatformPermanent, debug_services); + win32_opengl_window_info OpenGLWindowInfo = {}; + OpenGLWindowInfo.ColorBits = 32; + OpenGLWindowInfo.AlphaBits = 8; + OpenGLWindowInfo.DepthBits = 0; + CreateOpenGLWindowContext(OpenGLWindowInfo, &MainWindow); + } + + s64 PerformanceCountFrequency = GetPerformanceFrequency(); + s64 LastFrameEnd = GetWallClock(); + r32 TargetSecondsPerFrame = 1 / 30.0f; + r32 LastFrameSecondsElapsed = 0.0f; + + GlobalDebugServices = PushStruct(&PlatformPermanent, debug_services); #if DEBUG - InitDebugServices_DebugMode(GlobalDebugServices, - PerformanceCountFrequency, - GetWallClock, - Win32GetThreadId, - Context.ThreadContext, - PLATFORM_THREAD_COUNT + 1); -#else - InitDebugServices_OffMode(GlobalDebugServices, + InitDebugServices_DebugMode(GlobalDebugServices, PerformanceCountFrequency, GetWallClock, Win32GetThreadId, Context.ThreadContext, PLATFORM_THREAD_COUNT + 1); +#else + InitDebugServices_OffMode(GlobalDebugServices, + PerformanceCountFrequency, + GetWallClock, + Win32GetThreadId, + Context.ThreadContext, + PLATFORM_THREAD_COUNT + 1); #endif - - input_queue InputQueue = InputQueue_Create(&PlatformPermanent, 32); - - Win32WorkQueue_Init(&PlatformPermanent, PLATFORM_THREAD_COUNT); - - // Platform functions - Context.GeneralWorkQueue = &Win32WorkQueue.WorkQueue; - Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; - Context.PlatformGetSocketHandle = Win32GetSocketHandle; - Context.PlatformGetFontInfo = Win32GetFontInfo; - Context.PlatformDrawFontCodepoint = Win32DrawFontCodepoint; - - Context.ThreadManager = PushStruct(&PlatformPermanent, platform_thread_manager); - *Context.ThreadManager = CreatePlatformThreadManager(Win32CreateThread, Win32KillThread); - - Context.SocketManager = PushStruct(&PlatformPermanent, platform_socket_manager); - *Context.SocketManager = CreatePlatformSocketManager(Win32ConnectSocket, Win32CloseSocket, Win32SocketQueryStatus, Win32SocketPeek, Win32SocketReceive, Win32SocketSend); - - win32_dll_refresh DLLRefresh = InitializeDLLHotReloading(DLLName, WorkingDLLName, DLLLockFileName); - if (!ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, true, false)) { return -1; } - - Mouse_Init(); - - Win32SocketSystem_Init(&PlatformPermanent); - - Win32SerialArray_Create(ThreadContext); - - render_command_buffer RenderBuffer = {}; - if (!Context.Headless) + + input_queue InputQueue = InputQueue_Create(&PlatformPermanent, 32); + + Win32WorkQueue_Init(&PlatformPermanent, PLATFORM_THREAD_COUNT); + + // Platform functions + Context.GeneralWorkQueue = &Win32WorkQueue.WorkQueue; + Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; + Context.PlatformGetSocketHandle = Win32GetSocketHandle; + Context.PlatformGetFontInfo = Win32GetFontInfo; + Context.PlatformDrawFontCodepoint = Win32DrawFontCodepoint; + + Context.ThreadManager = PushStruct(&PlatformPermanent, platform_thread_manager); + *Context.ThreadManager = CreatePlatformThreadManager(Win32CreateThread, Win32KillThread); + + Context.SocketManager = PushStruct(&PlatformPermanent, platform_socket_manager); + *Context.SocketManager = CreatePlatformSocketManager(Win32ConnectSocket, Win32CloseSocket, Win32SocketQueryStatus, Win32SocketPeek, Win32SocketReceive, Win32SocketSend); + + win32_dll_refresh DLLRefresh = InitializeDLLHotReloading(DLLName, WorkingDLLName, DLLLockFileName); + if (!ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, true, false)) { return -1; } + + Mouse_Init(); + + Win32SocketSystem_Init(&PlatformPermanent); + + Win32SerialArray_Create(&PlatformPermanent); + + render_command_buffer RenderBuffer = {}; + if (!Context.Headless) + { + RenderBuffer = AllocateRenderCommandBuffer(MB(12), &PlatformPermanent, ThreadContext); + } + + addressed_data_buffer_list OutputData = AddressedDataBufferList_Create(ThreadContext); + + Context.InitializeApplication(&Context); + + system_time StartTime = Win32GetSystemTime(); + + Running = true; + Context.WindowIsVisible = true; + while (Running) + { + if (GlobalDebugServices->RecordFrames) { - RenderBuffer = AllocateRenderCommandBuffer(MB(12), &PlatformPermanent, ThreadContext); + EndDebugFrame(GlobalDebugServices); } - addressed_data_buffer_list OutputData = AddressedDataBufferList_Create(ThreadContext); + DEBUG_TRACK_SCOPE(MainLoop); - Context.InitializeApplication(&Context); - - system_time StartTime = Win32GetSystemTime(); - - Running = true; - Context.WindowIsVisible = true; - while (Running) { - if (GlobalDebugServices->RecordFrames) - { - EndDebugFrame(GlobalDebugServices); - } - - DEBUG_TRACK_SCOPE(MainLoop); - - { - Context.SystemTime_Last = Context.SystemTime_Current; - Context.SystemTime_Current = Win32GetSystemTime(); - + Context.SystemTime_Last = Context.SystemTime_Current; + Context.SystemTime_Current = Win32GetSystemTime(); + #define PRINT_SYSTEM_TIME 0 #if PRINT_SYSTEM_TIME - gs_string T = PushStringF(Context.ThreadContext.Transient, - 256, - "%d %d %d - %lld\n", - Context.SystemTime_Current.Hour, - Context.SystemTime_Current.Minute, - Context.SystemTime_Current.Second, - Context.SystemTime_Current.NanosSinceEpoch); - - u64 NanosElapsed = Context.SystemTime_Current.NanosSinceEpoch - StartTime.NanosSinceEpoch; - r64 SecondsElapsed = (r64)NanosElapsed * NanosToSeconds; - - Log_Message(GlobalLogBuffer, - "%lld %f Seconds \n", - NanosElapsed, - SecondsElapsed); + gs_string T = PushStringF(Context.ThreadContext.Transient, + 256, + "%d %d %d - %lld\n", + Context.SystemTime_Current.Hour, + Context.SystemTime_Current.Minute, + Context.SystemTime_Current.Second, + Context.SystemTime_Current.NanosSinceEpoch); + + u64 NanosElapsed = Context.SystemTime_Current.NanosSinceEpoch - StartTime.NanosSinceEpoch; + r64 SecondsElapsed = (r64)NanosElapsed * NanosToSeconds; + + Log_Message(GlobalLogBuffer, + "%lld %f Seconds \n", + NanosElapsed, + SecondsElapsed); #endif - } - - ResetInputQueue(&InputQueue); - - ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, false, true); - - AddressedDataBufferList_Clear(&OutputData); - - if (!Context.Headless) - { - Mouse_Update(MainWindow, &Context); - MSG Message; - while (PeekMessageA(&Message, MainWindow.Handle, 0, 0, PM_REMOVE)) - { - DEBUG_TRACK_SCOPE(PeekWindowsMessages); - HandleWindowMessage(Message, &MainWindow, &InputQueue, &Context.Mouse); - } - - Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; - RenderBuffer.ViewWidth = MainWindow.Width; - RenderBuffer.ViewHeight = MainWindow.Height; - } - - Context.DeltaTime = LastFrameSecondsElapsed; - Context.TotalTime += (r64)Context.DeltaTime; - - Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData); - - Win32_SendOutputData(ThreadContext, OutputData); - - if (!Context.Headless) - { - RenderCommandBuffer(RenderBuffer); - ClearRenderBuffer(&RenderBuffer); - - Mouse_Advance(&Context); - - HDC DeviceContext = GetDC(MainWindow.Handle); - SwapBuffers(DeviceContext); - ReleaseDC(MainWindow.Handle, DeviceContext); - } - - Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext); - - s64 FinishedWorkTime = GetWallClock(); - r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency); - - while (SecondsElapsed < TargetSecondsPerFrame) - { - DEBUG_TRACK_SCOPE(UnusedTime); - u32 SleepTime = 1000.0f * (TargetSecondsPerFrame - SecondsElapsed); - Sleep(SleepTime); - SecondsElapsed = GetSecondsElapsed(LastFrameEnd, GetWallClock(), PerformanceCountFrequency); - } - - LastFrameSecondsElapsed = SecondsElapsed; - LastFrameEnd = GetWallClock(); } - Context.CleanupApplication(Context, &OutputData); + ResetInputQueue(&InputQueue); + + ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, false, true); + + AddressedDataBufferList_Clear(&OutputData); + + if (!Context.Headless) + { + Mouse_Update(MainWindow, &Context); + MSG Message; + while (PeekMessageA(&Message, MainWindow.Handle, 0, 0, PM_REMOVE)) + { + DEBUG_TRACK_SCOPE(PeekWindowsMessages); + HandleWindowMessage(Message, &MainWindow, &InputQueue, &Context.Mouse); + } + + Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; + RenderBuffer.ViewWidth = MainWindow.Width; + RenderBuffer.ViewHeight = MainWindow.Height; + } + + Context.DeltaTime = LastFrameSecondsElapsed; + Context.TotalTime += (r64)Context.DeltaTime; + + Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData); + Win32_SendOutputData(ThreadContext, OutputData); + + if (!Context.Headless) + { + RenderCommandBuffer(RenderBuffer); + ClearRenderBuffer(&RenderBuffer); + + Mouse_Advance(&Context); + + HDC DeviceContext = GetDC(MainWindow.Handle); + SwapBuffers(DeviceContext); + ReleaseDC(MainWindow.Handle, DeviceContext); + } + Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext); - Win32WorkQueue_Cleanup(); - Win32SocketSystem_Cleanup(); + s64 FinishedWorkTime = GetWallClock(); + r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency); - return 0; + while (SecondsElapsed < TargetSecondsPerFrame) + { + DEBUG_TRACK_SCOPE(UnusedTime); + u32 SleepTime = 1000.0f * (TargetSecondsPerFrame - SecondsElapsed); + Sleep(SleepTime); + SecondsElapsed = GetSecondsElapsed(LastFrameEnd, GetWallClock(), PerformanceCountFrequency); + } + + LastFrameSecondsElapsed = SecondsElapsed; + LastFrameEnd = GetWallClock(); + } + + Context.CleanupApplication(Context, &OutputData); + Win32_SendOutputData(ThreadContext, OutputData); + Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext); + + Win32WorkQueue_Cleanup(); + Win32SocketSystem_Cleanup(); + + return 0; } #define WIN32_FOLDHAUS_CPP diff --git a/src/app/platform_win32/win32_foldhaus_dll.h b/src/app/platform_win32/win32_foldhaus_dll.h index 26071e6..396f15e 100644 --- a/src/app/platform_win32/win32_foldhaus_dll.h +++ b/src/app/platform_win32/win32_foldhaus_dll.h @@ -11,92 +11,92 @@ // DLL struct win32_dll_refresh { - FILETIME LastWriteTime; - HMODULE DLL; - - bool IsValid; - - char SourceDLLPath[MAX_PATH]; - char WorkingDLLPath[MAX_PATH]; - char LockFilePath[MAX_PATH]; + FILETIME LastWriteTime; + HMODULE DLL; + + bool IsValid; + + char SourceDLLPath[MAX_PATH]; + char WorkingDLLPath[MAX_PATH]; + char LockFilePath[MAX_PATH]; }; internal int Win32DLLgs_stringLength(char* gs_string) { - char* At = gs_string; - while (*At) { At++; }; - return At - gs_string; + char* At = gs_string; + while (*At) { At++; }; + return At - gs_string; } internal int Win32DLLConcatgs_strings(int ALength, char* A, int BLength, char* B, int DestLength, char* Dest) { - char* Dst = Dest; - char* AAt = A; - int ALengthToCopy = ALength < DestLength ? ALength : DestLength; - for (s32 a = 0; a < ALength; a++) - { - *Dst++ = *AAt++; - } - char* BAt = B; - int DestLengthRemaining = DestLength - (Dst - Dest); - int BLengthToCopy = BLength < DestLengthRemaining ? BLength : DestLength; - for (s32 b = 0; b < BLengthToCopy; b++) - { - *Dst++ = *BAt++; - } - int DestLengthOut = Dst - Dest; - int NullTermIndex = DestLengthOut < DestLength ? DestLengthOut : DestLength; - Dest[NullTermIndex] = 0; - return DestLengthOut; + char* Dst = Dest; + char* AAt = A; + int ALengthToCopy = ALength < DestLength ? ALength : DestLength; + for (s32 a = 0; a < ALength; a++) + { + *Dst++ = *AAt++; + } + char* BAt = B; + int DestLengthRemaining = DestLength - (Dst - Dest); + int BLengthToCopy = BLength < DestLengthRemaining ? BLength : DestLength; + for (s32 b = 0; b < BLengthToCopy; b++) + { + *Dst++ = *BAt++; + } + int DestLengthOut = Dst - Dest; + int NullTermIndex = DestLengthOut < DestLength ? DestLengthOut : DestLength; + Dest[NullTermIndex] = 0; + return DestLengthOut; } internal void GetApplicationPath(system_path* Result) { - Assert(Result->Path); - Result->PathLength = GetModuleFileNameA(0, Result->Path, Result->PathLength); - - u32 CharactersScanned = 0; - u32 IndexOfLastSlash = 0; - char *Scan = Result->Path; - while(*Scan) + Assert(Result->Path); + Result->PathLength = GetModuleFileNameA(0, Result->Path, Result->PathLength); + + u32 CharactersScanned = 0; + u32 IndexOfLastSlash = 0; + char *Scan = Result->Path; + while(*Scan) + { + if (*Scan == '\\') { - if (*Scan == '\\') - { - Result->IndexOfLastSlash = CharactersScanned + 1; - } - Scan++; - CharactersScanned++; + Result->IndexOfLastSlash = CharactersScanned + 1; } + Scan++; + CharactersScanned++; + } } internal b32 LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult) { - b32 Success = false; - Assert(DLLResult->DLL == 0); - - DLLResult->DLL = LoadLibraryA(DLLName); - if (DLLResult->DLL) - { - Success = true; - DLLResult->IsValid = true; - } - - return Success; + b32 Success = false; + Assert(DLLResult->DLL == 0); + + DLLResult->DLL = LoadLibraryA(DLLName); + if (DLLResult->DLL) + { + Success = true; + DLLResult->IsValid = true; + } + + return Success; } internal void UnloadApplicationDLL(win32_dll_refresh* DLL) { - if (DLL->DLL) - { - FreeLibrary(DLL->DLL); - } - DLL->DLL = 0; - DLL->IsValid = false; + if (DLL->DLL) + { + FreeLibrary(DLL->DLL); + } + DLL->DLL = 0; + DLL->IsValid = false; } internal win32_dll_refresh @@ -104,57 +104,57 @@ InitializeDLLHotReloading(char* SourceDLLName, char* WorkingDLLFileName, char* LockFileName) { - win32_dll_refresh Result = {}; - Result.IsValid = false; - - system_path ExePath = {}; - ExePath.PathLength = MAX_PATH; - ExePath.Path = (char*)VirtualAlloc(NULL, ExePath.PathLength, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - GetApplicationPath(&ExePath); - - Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32DLLgs_stringLength(SourceDLLName), SourceDLLName, - MAX_PATH, Result.SourceDLLPath); - Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32DLLgs_stringLength(WorkingDLLFileName), WorkingDLLFileName, - MAX_PATH, Result.WorkingDLLPath); - Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32DLLgs_stringLength(LockFileName), LockFileName, - MAX_PATH, Result.LockFilePath); - - Win32Free((u8*)ExePath.Path, ExePath.PathLength); - return Result; - + win32_dll_refresh Result = {}; + Result.IsValid = false; + + system_path ExePath = {}; + ExePath.PathLength = MAX_PATH; + ExePath.Path = (char*)VirtualAlloc(NULL, ExePath.PathLength, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + GetApplicationPath(&ExePath); + + Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32DLLgs_stringLength(SourceDLLName), SourceDLLName, + MAX_PATH, Result.SourceDLLPath); + Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32DLLgs_stringLength(WorkingDLLFileName), WorkingDLLFileName, + MAX_PATH, Result.WorkingDLLPath); + Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32DLLgs_stringLength(LockFileName), LockFileName, + MAX_PATH, Result.LockFilePath); + + Win32Free((u8*)ExePath.Path, ExePath.PathLength, 0); + return Result; + } internal b32 HotLoadDLL(win32_dll_refresh* DLL) { - b32 DidReload = false; - - FILETIME UpdatedLastWriteTime = {}; - WIN32_FIND_DATA FindData = {}; - HANDLE FileHandle = FindFirstFileA(DLL->SourceDLLPath, &FindData); - if (FileHandle != INVALID_HANDLE_VALUE) + b32 DidReload = false; + + FILETIME UpdatedLastWriteTime = {}; + WIN32_FIND_DATA FindData = {}; + HANDLE FileHandle = FindFirstFileA(DLL->SourceDLLPath, &FindData); + if (FileHandle != INVALID_HANDLE_VALUE) + { + UpdatedLastWriteTime = FindData.ftLastWriteTime; + FindClose(FileHandle); + } + + if (CompareFileTime(&UpdatedLastWriteTime, &DLL->LastWriteTime)) + { + WIN32_FILE_ATTRIBUTE_DATA Ignored; + if (!GetFileAttributesEx(DLL->LockFilePath, GetFileExInfoStandard, &Ignored)) { - UpdatedLastWriteTime = FindData.ftLastWriteTime; - FindClose(FileHandle); + UnloadApplicationDLL(DLL); + CopyFileA(DLL->SourceDLLPath, DLL->WorkingDLLPath, FALSE); + LoadApplicationDLL(DLL->WorkingDLLPath, DLL); + DLL->LastWriteTime = UpdatedLastWriteTime; + DidReload = true; } - - if (CompareFileTime(&UpdatedLastWriteTime, &DLL->LastWriteTime)) - { - WIN32_FILE_ATTRIBUTE_DATA Ignored; - if (!GetFileAttributesEx(DLL->LockFilePath, GetFileExInfoStandard, &Ignored)) - { - UnloadApplicationDLL(DLL); - CopyFileA(DLL->SourceDLLPath, DLL->WorkingDLLPath, FALSE); - LoadApplicationDLL(DLL->WorkingDLLPath, DLL); - DLL->LastWriteTime = UpdatedLastWriteTime; - DidReload = true; - } - } - - return DidReload; + } + + return DidReload; } diff --git a/src/app/platform_win32/win32_foldhaus_memory.h b/src/app/platform_win32/win32_foldhaus_memory.h index 100dd1a..6dbce1c 100644 --- a/src/app/platform_win32/win32_foldhaus_memory.h +++ b/src/app/platform_win32/win32_foldhaus_memory.h @@ -1,36 +1,26 @@ -// -// File: win32_foldhaus_memory.h -// Author: Peter Slattery -// Creation Date: 2020-02-04 -// -// -// NOTE: Relies on having imported foldhaus_platform.h prior to this file -// -#ifndef WIN32_FOLDHAUS_MEMORY_H +/* date = May 10th 2021 11:48 pm */ -ALLOCATOR_ALLOC(Win32Alloc) +#ifndef GS_MEMORY_WIN32_H +#define GS_MEMORY_WIN32_H + +PLATFORM_ALLOC(Win32Alloc) { - u8* Result = (u8*)VirtualAlloc(NULL, Size, - MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); - if (ResultSize != 0) - { - *ResultSize = Size; - } - return Result; + u8* Result = (u8*)VirtualAlloc(NULL, Size, + MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + if (ResultSize) *ResultSize = Size; + return Result; } -ALLOCATOR_FREE(Win32Free) +PLATFORM_FREE(Win32Free) { - b32 Result = VirtualFree(Ptr, 0, MEM_RELEASE); - if (!Result) - { - s32 Error = GetLastError(); - // TODO(Peter): I'm waiting to see an error actually occur here - // to know what it could possibly be. - InvalidCodePath; - } + VirtualFree(Base, 0, MEM_RELEASE); } -#define WIN32_FOLDHAUS_MEMORY_H -#endif // WIN32_FOLDHAUS_MEMORY_H \ No newline at end of file +internal gs_allocator +CreatePlatformAllocator() +{ + return AllocatorCreate(Win32Alloc, Win32Free, 0); +} + +#endif //GS_MEMORY_WIN32_H diff --git a/src/app/platform_win32/win32_foldhaus_serial.h b/src/app/platform_win32/win32_foldhaus_serial.h index 567811b..4b309c8 100644 --- a/src/app/platform_win32/win32_foldhaus_serial.h +++ b/src/app/platform_win32/win32_foldhaus_serial.h @@ -13,367 +13,367 @@ global s32* Win32SerialPortFilled; DCB Win32SerialPort_GetState(HANDLE ComPortHandle) { - DEBUG_TRACK_FUNCTION; - DCB ControlSettings = {0}; - ZeroStruct(&ControlSettings); - ControlSettings.DCBlength = sizeof(ControlSettings); - - bool Success = GetCommState(ComPortHandle, &ControlSettings); - Assert(Success); - - return ControlSettings; + DEBUG_TRACK_FUNCTION; + DCB ControlSettings = {0}; + ZeroStruct(&ControlSettings); + ControlSettings.DCBlength = sizeof(ControlSettings); + + bool Success = GetCommState(ComPortHandle, &ControlSettings); + Assert(Success); + + return ControlSettings; } void Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits) { - DEBUG_TRACK_FUNCTION; - DCB ControlSettings = Win32SerialPort_GetState(ComPortHandle); - - // TODO(pjs): Validate BaudRate - There's only certain rates that are valid right? - ControlSettings.BaudRate = BaudRate; - - if (Parity == NOPARITY) - { - ControlSettings.Parity = Parity; - ControlSettings.fParity = 0; - } - if (Parity == EVENPARITY || Parity == ODDPARITY) - { - ControlSettings.Parity = Parity; - ControlSettings.fParity = 1; - } - - ControlSettings.StopBits = StopBits; - ControlSettings.ByteSize = ByteSize; - - ControlSettings.fBinary = true; - - ControlSettings.fOutxCtsFlow = false; - ControlSettings.fOutxDsrFlow = false; - ControlSettings.fDtrControl = DTR_CONTROL_DISABLE; - ControlSettings.fDsrSensitivity = 0; - ControlSettings.fRtsControl = RTS_CONTROL_DISABLE; - ControlSettings.fOutX = false; - ControlSettings.fInX = false; - - ControlSettings.fErrorChar = 0; - ControlSettings.fNull = false; - ControlSettings.fAbortOnError = false; - ControlSettings.wReserved = false; - ControlSettings.XonLim = 2; - ControlSettings.XoffLim = 4; - ControlSettings.XonChar = 0x13; - ControlSettings.XoffChar = 0x19; - ControlSettings.EvtChar = 0; - - bool Success = SetCommState(ComPortHandle, &ControlSettings); + DEBUG_TRACK_FUNCTION; + DCB ControlSettings = Win32SerialPort_GetState(ComPortHandle); + + // TODO(pjs): Validate BaudRate - There's only certain rates that are valid right? + ControlSettings.BaudRate = BaudRate; + + if (Parity == NOPARITY) + { + ControlSettings.Parity = Parity; + ControlSettings.fParity = 0; + } + if (Parity == EVENPARITY || Parity == ODDPARITY) + { + ControlSettings.Parity = Parity; + ControlSettings.fParity = 1; + } + + ControlSettings.StopBits = StopBits; + ControlSettings.ByteSize = ByteSize; + + ControlSettings.fBinary = true; + + ControlSettings.fOutxCtsFlow = false; + ControlSettings.fOutxDsrFlow = false; + ControlSettings.fDtrControl = DTR_CONTROL_DISABLE; + ControlSettings.fDsrSensitivity = 0; + ControlSettings.fRtsControl = RTS_CONTROL_DISABLE; + ControlSettings.fOutX = false; + ControlSettings.fInX = false; + + ControlSettings.fErrorChar = 0; + ControlSettings.fNull = false; + ControlSettings.fAbortOnError = false; + ControlSettings.wReserved = false; + ControlSettings.XonLim = 2; + ControlSettings.XoffLim = 4; + ControlSettings.XonChar = 0x13; + ControlSettings.XoffChar = 0x19; + ControlSettings.EvtChar = 0; + + bool Success = SetCommState(ComPortHandle, &ControlSettings); } gs_const_string_array Win32SerialPorts_List(gs_memory_arena* Arena, gs_memory_arena* Transient) { - gs_const_string_array Result = {}; + gs_const_string_array Result = {}; + + DWORD SizeNeeded0 = 0; + DWORD CountReturned0 = 0; + EnumPorts(NULL, 1, 0, 0, &SizeNeeded0, &CountReturned0); + Assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER); + + DWORD SizeNeeded1 = 0; + DWORD CountReturned1 = 0; + PORT_INFO_1* PortsArray = (PORT_INFO_1*)PushSize(Transient, SizeNeeded0).Memory; + if (EnumPorts(NULL, + 1, + (u8*)PortsArray, + SizeNeeded0, + &SizeNeeded1, + &CountReturned1)) + { + Result.CountMax = (u64)CountReturned1; + Result.Strings = PushArray(Arena, gs_const_string, Result.CountMax); - DWORD SizeNeeded0 = 0; - DWORD CountReturned0 = 0; - EnumPorts(NULL, 1, 0, 0, &SizeNeeded0, &CountReturned0); - Assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER); - - DWORD SizeNeeded1 = 0; - DWORD CountReturned1 = 0; - PORT_INFO_1* PortsArray = (PORT_INFO_1*)PushSize(Transient, SizeNeeded0); - if (EnumPorts(NULL, - 1, - (u8*)PortsArray, - SizeNeeded0, - &SizeNeeded1, - &CountReturned1)) + for (; Result.Count < Result.CountMax; Result.Count++) { - Result.CountMax = (u64)CountReturned1; - Result.Strings = PushArray(Arena, gs_const_string, Result.CountMax); - - for (; Result.Count < Result.CountMax; Result.Count++) - { - u64 Index = Result.Count; - u64 StrLen = CStringLength(PortsArray[Index].pName); - gs_string Str = PushString(Arena, StrLen); - PrintF(&Str, "%.*s", StrLen, PortsArray[Index].pName); - Result.Strings[Result.Count] = Str.ConstString; - } + u64 Index = Result.Count; + u64 StrLen = CStringLength(PortsArray[Index].pName); + gs_string Str = PushString(Arena, StrLen); + PrintF(&Str, "%.*s", StrLen, PortsArray[Index].pName); + Result.Strings[Result.Count] = Str.ConstString; } - - return Result; + } + + return Result; } bool Win32SerialPort_Exists(char* PortName, gs_memory_arena* Transient) { - bool Result = false; - if (PortName != 0) + bool Result = false; + if (PortName != 0) + { + gs_const_string PortIdent = ConstString(PortName); + u32 IdentBegin = FindLast(PortIdent, '\\') + 1; + PortIdent = Substring(PortIdent, IdentBegin, PortIdent.Length); + + gs_const_string_array PortsAvailable = Win32SerialPorts_List(Transient, Transient); + + for (u64 i = 0; i < PortsAvailable.Count; i++) { - gs_const_string PortIdent = ConstString(PortName); - u32 IdentBegin = FindLast(PortIdent, '\\') + 1; - PortIdent = Substring(PortIdent, IdentBegin, PortIdent.Length); - - gs_const_string_array PortsAvailable = Win32SerialPorts_List(Transient, Transient); - - for (u64 i = 0; i < PortsAvailable.Count; i++) - { - gs_const_string AvailablePortName = PortsAvailable.Strings[i]; - if (StringsEqualUpToLength(AvailablePortName, PortIdent, PortIdent.Length)) - { - Result = true; - break; - } - } + gs_const_string AvailablePortName = PortsAvailable.Strings[i]; + if (StringsEqualUpToLength(AvailablePortName, PortIdent, PortIdent.Length)) + { + Result = true; + break; + } } - return Result; + } + return Result; } HANDLE Win32SerialPort_Open(char* PortName, gs_memory_arena* Transient) { - DEBUG_TRACK_FUNCTION; - HANDLE ComPortHandle = INVALID_HANDLE_VALUE;; + DEBUG_TRACK_FUNCTION; + HANDLE ComPortHandle = INVALID_HANDLE_VALUE;; + + if (Win32SerialPort_Exists(PortName, Transient)) + { - if (Win32SerialPort_Exists(PortName, Transient)) + ComPortHandle = CreateFile(PortName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, // Default Security Attr + OPEN_EXISTING, + 0, // Not overlapped I/O + NULL); + + bool HasError = false; + + if (ComPortHandle != INVALID_HANDLE_VALUE) { - - ComPortHandle = CreateFile(PortName, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, // Default Security Attr - OPEN_EXISTING, - 0, // Not overlapped I/O - NULL); - - bool HasError = false; - - if (ComPortHandle != INVALID_HANDLE_VALUE) - { - COMMTIMEOUTS Timeouts = { 0 }; - Timeouts.ReadIntervalTimeout = 0; // in milliseconds - Timeouts.ReadTotalTimeoutConstant = 0; // in milliseconds - Timeouts.ReadTotalTimeoutMultiplier = 0; // in milliseconds - Timeouts.WriteTotalTimeoutConstant = 0; // in milliseconds - Timeouts.WriteTotalTimeoutMultiplier = 0; // in milliseconds - - HasError = !SetCommTimeouts(ComPortHandle, &Timeouts); - } - else - { - HasError = true; - } - - if (HasError) - { - // Error - s32 Error = GetLastError(); - switch (Error) - { - case ERROR_INVALID_FUNCTION: - case ERROR_NO_SUCH_DEVICE: - case ERROR_FILE_NOT_FOUND: - { - // NOTE(PS): The outer scope should handle these cases - ComPortHandle = INVALID_HANDLE_VALUE; - }break; - - InvalidDefaultCase; - } - } + COMMTIMEOUTS Timeouts = { 0 }; + Timeouts.ReadIntervalTimeout = 0; // in milliseconds + Timeouts.ReadTotalTimeoutConstant = 0; // in milliseconds + Timeouts.ReadTotalTimeoutMultiplier = 0; // in milliseconds + Timeouts.WriteTotalTimeoutConstant = 0; // in milliseconds + Timeouts.WriteTotalTimeoutMultiplier = 0; // in milliseconds + + HasError = !SetCommTimeouts(ComPortHandle, &Timeouts); + } + else + { + HasError = true; } - return ComPortHandle; + if (HasError) + { + // Error + s32 Error = GetLastError(); + switch (Error) + { + case ERROR_INVALID_FUNCTION: + case ERROR_NO_SUCH_DEVICE: + case ERROR_FILE_NOT_FOUND: + { + // NOTE(PS): The outer scope should handle these cases + ComPortHandle = INVALID_HANDLE_VALUE; + }break; + + InvalidDefaultCase; + } + } + } + + return ComPortHandle; } void Win32SerialPort_Close(HANDLE PortHandle) { - CloseHandle(PortHandle); + CloseHandle(PortHandle); } bool Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer) { - DEBUG_TRACK_FUNCTION; - Assert(PortHandle != INVALID_HANDLE_VALUE); - bool Success = false; - - DWORD BytesWritten = 0; - if (WriteFile(PortHandle, Buffer.Memory, Buffer.Size, &BytesWritten, NULL)) + DEBUG_TRACK_FUNCTION; + Assert(PortHandle != INVALID_HANDLE_VALUE); + bool Success = false; + + DWORD BytesWritten = 0; + if (WriteFile(PortHandle, Buffer.Memory, Buffer.Size, &BytesWritten, NULL)) + { + Success = (BytesWritten == Buffer.Size); + if (!Success) { - Success = (BytesWritten == Buffer.Size); - if (!Success) - { - Log_Error(GlobalLogBuffer, "Error: Entire buffer not written.\n"); - } + Log_Error(GlobalLogBuffer, "Error: Entire buffer not written.\n"); } - else + } + else + { + Log_Error(GlobalLogBuffer, "Error: Unable to write to port\n"); + s32 Error = GetLastError(); + switch (Error) { - Log_Error(GlobalLogBuffer, "Error: Unable to write to port\n"); - s32 Error = GetLastError(); - switch (Error) - { - case ERROR_OPERATION_ABORTED: - case ERROR_GEN_FAILURE: - { - // NOTE(pjs): Probably means that the serial port became invalid - // ie. the usb stick was removed - }break; - - case ERROR_ACCESS_DENIED: - { - // ?? - }break; - - case ERROR_NO_SUCH_DEVICE: - { - }break; - - case ERROR_INVALID_HANDLE: - InvalidDefaultCase; - } + case ERROR_OPERATION_ABORTED: + case ERROR_GEN_FAILURE: + { + // NOTE(pjs): Probably means that the serial port became invalid + // ie. the usb stick was removed + }break; + + case ERROR_ACCESS_DENIED: + { + // ?? + }break; + + case ERROR_NO_SUCH_DEVICE: + { + }break; + + case ERROR_INVALID_HANDLE: + InvalidDefaultCase; } - - return Success; + } + + return Success; } bool Win32SerialPort_SetRead(HANDLE PortHandle) { - bool Status = SetCommMask(PortHandle, EV_RXCHAR); - return Status; + bool Status = SetCommMask(PortHandle, EV_RXCHAR); + return Status; } u32 Win32SerialPort_ReadMessageWhenReady(HANDLE PortHandle, gs_data Data) { - u32 ReadSize = 0; - - DWORD EventMask = 0; - bool Status = WaitCommEvent(PortHandle, &EventMask, NULL); - if (Status) + u32 ReadSize = 0; + + DWORD EventMask = 0; + bool Status = WaitCommEvent(PortHandle, &EventMask, NULL); + if (Status) + { + DWORD NoBytesRead = 0; + do { - DWORD NoBytesRead = 0; - do - { - u8 Byte = 0; - Status = ReadFile(PortHandle, &Byte, sizeof(char), &NoBytesRead, NULL); - Data.Memory[ReadSize] = Byte; - ReadSize++; - } - while (NoBytesRead > 0 && ReadSize < Data.Size); + u8 Byte = 0; + Status = ReadFile(PortHandle, &Byte, sizeof(char), &NoBytesRead, NULL); + Data.Memory[ReadSize] = Byte; + ReadSize++; } - //Read data and store in a buffer - - return ReadSize; + while (NoBytesRead > 0 && ReadSize < Data.Size); + } + //Read data and store in a buffer + + return ReadSize; } ///////////////////////// // Win32SerialArray void -Win32SerialArray_Create(gs_thread_context Context) +Win32SerialArray_Create(gs_memory_arena* A) { - DEBUG_TRACK_FUNCTION; - - Win32SerialHandlesCountMax = 32; - - Win32SerialHandles = AllocatorAllocArray(Context.Allocator, HANDLE, Win32SerialHandlesCountMax); - Win32SerialPortNames = AllocatorAllocArray(Context.Allocator, gs_string, Win32SerialHandlesCountMax); - Win32SerialPortFilled = AllocatorAllocArray(Context.Allocator, s32, Win32SerialHandlesCountMax); - - u64 PortNameSize = 256; - u64 PortNameBufferSize = PortNameSize * Win32SerialHandlesCountMax; - char* PortNameBuffer = AllocatorAllocArray(Context.Allocator, char, PortNameBufferSize); - for (u32 i = 0; i < Win32SerialHandlesCountMax; i++) - { - char* NameBase = PortNameBuffer + (PortNameSize * i); - Win32SerialPortNames[i] = MakeString(NameBase, 0, PortNameSize); - Win32SerialPortFilled[i] = 0; - } + DEBUG_TRACK_FUNCTION; + + Win32SerialHandlesCountMax = 32; + + Win32SerialHandles = PushArray(A, HANDLE, Win32SerialHandlesCountMax); + Win32SerialPortNames = PushArray(A, gs_string, Win32SerialHandlesCountMax); + Win32SerialPortFilled = PushArray(A, s32, Win32SerialHandlesCountMax); + + u64 PortNameSize = 256; + u64 PortNameBufferSize = PortNameSize * Win32SerialHandlesCountMax; + char* PortNameBuffer = PushArray(A, char, PortNameBufferSize); + for (u32 i = 0; i < Win32SerialHandlesCountMax; i++) + { + char* NameBase = PortNameBuffer + (PortNameSize * i); + Win32SerialPortNames[i] = MakeString(NameBase, 0, PortNameSize); + Win32SerialPortFilled[i] = 0; + } } void Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName) { - DEBUG_TRACK_FUNCTION; - - bool Found = false; - for (u32 i = 0; i < Win32SerialHandlesCountMax; i++) + DEBUG_TRACK_FUNCTION; + + bool Found = false; + for (u32 i = 0; i < Win32SerialHandlesCountMax; i++) + { + bool WasFilled = InterlockedCompareExchange((LONG volatile*)Win32SerialPortFilled + i, 1, 0); + if (!WasFilled) { - bool WasFilled = InterlockedCompareExchange((LONG volatile*)Win32SerialPortFilled + i, 1, 0); - if (!WasFilled) - { - Win32SerialHandles[i] = SerialHandle; - PrintF(&Win32SerialPortNames[i], "%S", PortName); - Found = true; - break; - } + Win32SerialHandles[i] = SerialHandle; + PrintF(&Win32SerialPortNames[i], "%S", PortName); + Found = true; + break; } - Assert(Found); + } + Assert(Found); } void Win32SerialArray_Pop(u32 Index) { - bool WasFilled = InterlockedCompareExchange((LONG volatile*)Win32SerialPortFilled + Index, 0, 1); - Assert(WasFilled); - Win32SerialPortFilled[Index] = false; - Win32SerialHandles[Index] = INVALID_HANDLE_VALUE; + bool WasFilled = InterlockedCompareExchange((LONG volatile*)Win32SerialPortFilled + Index, 0, 1); + Assert(WasFilled); + Win32SerialPortFilled[Index] = false; + Win32SerialHandles[Index] = INVALID_HANDLE_VALUE; } HANDLE Win32SerialArray_Get(gs_const_string PortName) { - DEBUG_TRACK_FUNCTION; - - HANDLE PortHandle = INVALID_HANDLE_VALUE; - for (u32 i = 0; i < Win32SerialHandlesCountMax; i++) + DEBUG_TRACK_FUNCTION; + + HANDLE PortHandle = INVALID_HANDLE_VALUE; + for (u32 i = 0; i < Win32SerialHandlesCountMax; i++) + { + if (Win32SerialPortFilled[i] && + StringsEqual(Win32SerialPortNames[i].ConstString, PortName)) { - if (Win32SerialPortFilled[i] && - StringsEqual(Win32SerialPortNames[i].ConstString, PortName)) - { - PortHandle = Win32SerialHandles[i]; - break; - } + PortHandle = Win32SerialHandles[i]; + break; } - return PortHandle; + } + return PortHandle; } HANDLE Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits, gs_memory_arena* Transient) { - DEBUG_TRACK_FUNCTION; - - HANDLE PortHandle = Win32SerialArray_Get(PortName); - if (PortHandle == INVALID_HANDLE_VALUE) + DEBUG_TRACK_FUNCTION; + + HANDLE PortHandle = Win32SerialArray_Get(PortName); + if (PortHandle == INVALID_HANDLE_VALUE) + { + Assert(IsNullTerminated(PortName)); + PortHandle = Win32SerialPort_Open(PortName.Str, Transient); + if (PortHandle != INVALID_HANDLE_VALUE) { - Assert(IsNullTerminated(PortName)); - PortHandle = Win32SerialPort_Open(PortName.Str, Transient); - if (PortHandle != INVALID_HANDLE_VALUE) - { - Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits); - Win32SerialArray_Push(PortHandle, PortName); - } + Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits); + Win32SerialArray_Push(PortHandle, PortName); } - return PortHandle; + } + return PortHandle; } void Win32SerialArray_Close(gs_const_string PortName) { - for (u32 i = 0; i < Win32SerialHandlesCountMax; i++) + for (u32 i = 0; i < Win32SerialHandlesCountMax; i++) + { + if (Win32SerialPortFilled[i] && StringsEqual(Win32SerialPortNames[i].ConstString, PortName)) { - if (Win32SerialPortFilled[i] && StringsEqual(Win32SerialPortNames[i].ConstString, PortName)) - { - Win32SerialPort_Close(Win32SerialHandles[i]); - Win32SerialArray_Pop(i); - break; - } + Win32SerialPort_Close(Win32SerialHandles[i]); + Win32SerialArray_Pop(i); + break; } + } } #define WIN32_SERIAL_H diff --git a/src/app/platform_win32/win32_foldhaus_socket.h b/src/app/platform_win32/win32_foldhaus_socket.h index ca36cac..ab656f5 100644 --- a/src/app/platform_win32/win32_foldhaus_socket.h +++ b/src/app/platform_win32/win32_foldhaus_socket.h @@ -7,14 +7,14 @@ struct win32_socket { - SOCKET Socket; + SOCKET Socket; }; struct win32_socket_array { - win32_socket* Values; - s32 CountMax; - s32 Count; + win32_socket* Values; + s32 CountMax; + s32 Count; }; global WSADATA WSAData; @@ -27,28 +27,28 @@ global win32_socket_array Win32Sockets; internal win32_socket_array Win32SocketArray_Create(u32 CountMax, gs_memory_arena* Storage) { - win32_socket_array Result = {}; - Result.CountMax = CountMax; - Result.Values = PushArray(Storage, win32_socket, CountMax); - return Result; + win32_socket_array Result = {}; + Result.CountMax = CountMax; + Result.Values = PushArray(Storage, win32_socket, CountMax); + return Result; } internal s32 Win32SocketArray_Take(win32_socket_array* Array) { - Assert(Array->Count < Array->CountMax); - s32 Result = Array->Count++; - win32_socket* Socket = Array->Values + Result; - *Socket = {0}; - return Result; + Assert(Array->Count < Array->CountMax); + s32 Result = Array->Count++; + win32_socket* Socket = Array->Values + Result; + *Socket = {0}; + return Result; } internal win32_socket* Win32SocketArray_Get(win32_socket_array Array, s32 Index) { - Assert(Index < Array.Count); - win32_socket* Result = Array.Values + Index; - return Result; + Assert(Index < Array.Count); + win32_socket* Result = Array.Values + Index; + return Result; } ////////////////////// @@ -58,259 +58,259 @@ Win32SocketArray_Get(win32_socket_array Array, s32 Index) internal win32_socket Win32Socket_Create(s32 AddressFamily, s32 Type, s32 Protocol) { - win32_socket Result = {0}; - Result.Socket = socket(AddressFamily, Type, Protocol); - if (Result.Socket == INVALID_SOCKET) - { - s32 Error = WSAGetLastError(); - InvalidCodePath; - } - return Result; + win32_socket Result = {0}; + Result.Socket = socket(AddressFamily, Type, Protocol); + if (Result.Socket == INVALID_SOCKET) + { + s32 Error = WSAGetLastError(); + InvalidCodePath; + } + return Result; } internal void Win32Socket_Bind(win32_socket* Socket, s32 AddressFamily, char* Address, s32 Port) { - sockaddr_in Service = {0}; - Service.sin_family = AddressFamily; - Service.sin_addr.s_addr = inet_addr(Address); - Service.sin_port = htons(Port); - - s32 Result = bind(Socket->Socket, (SOCKADDR*)&Service, sizeof(Service)); - if (Result == SOCKET_ERROR) - { - s32 Error = WSAGetLastError(); - InvalidCodePath; - } + sockaddr_in Service = {0}; + Service.sin_family = AddressFamily; + Service.sin_addr.s_addr = inet_addr(Address); + Service.sin_port = htons(Port); + + s32 Result = bind(Socket->Socket, (SOCKADDR*)&Service, sizeof(Service)); + if (Result == SOCKET_ERROR) + { + s32 Error = WSAGetLastError(); + InvalidCodePath; + } } internal win32_socket Win32Socket_ConnectToAddress(char* Address, char* DefaultPort) { - win32_socket Result = {}; - - addrinfo Hints = {0}; - Hints.ai_family = AF_UNSPEC; - Hints.ai_socktype = SOCK_STREAM; - Hints.ai_protocol = IPPROTO_TCP; - - addrinfo* PotentialConnections; - s32 Error = getaddrinfo(Address, DefaultPort, &Hints, &PotentialConnections); - if (Error == 0) - { - for (addrinfo* InfoAt = PotentialConnections; InfoAt != NULL; InfoAt = InfoAt->ai_next) - { - win32_socket Socket = Win32Socket_Create(InfoAt->ai_family, InfoAt->ai_socktype, InfoAt->ai_protocol); - if (Socket.Socket == INVALID_SOCKET) - { - Error = WSAGetLastError(); - InvalidCodePath; - } - - Error = connect(Socket.Socket, InfoAt->ai_addr, (int)InfoAt->ai_addrlen); - if (Error == SOCKET_ERROR) - { - closesocket(Socket.Socket); - continue; - } - else - { - Result = Socket; - break; - } - } - } - else + win32_socket Result = {}; + + addrinfo Hints = {0}; + Hints.ai_family = AF_UNSPEC; + Hints.ai_socktype = SOCK_STREAM; + Hints.ai_protocol = IPPROTO_TCP; + + addrinfo* PotentialConnections; + s32 Error = getaddrinfo(Address, DefaultPort, &Hints, &PotentialConnections); + if (Error == 0) + { + for (addrinfo* InfoAt = PotentialConnections; InfoAt != NULL; InfoAt = InfoAt->ai_next) { + win32_socket Socket = Win32Socket_Create(InfoAt->ai_family, InfoAt->ai_socktype, InfoAt->ai_protocol); + if (Socket.Socket == INVALID_SOCKET) + { Error = WSAGetLastError(); InvalidCodePath; + } + + Error = connect(Socket.Socket, InfoAt->ai_addr, (int)InfoAt->ai_addrlen); + if (Error == SOCKET_ERROR) + { + closesocket(Socket.Socket); + continue; + } + else + { + Result = Socket; + break; + } } - - freeaddrinfo(PotentialConnections); - - return Result; + } + else + { + Error = WSAGetLastError(); + InvalidCodePath; + } + + freeaddrinfo(PotentialConnections); + + return Result; } internal bool Win32ConnectSocket(platform_socket_manager* Manager, platform_socket* Socket) { - bool Result = false; - - addrinfo Hints = {0}; - Hints.ai_family = AF_UNSPEC; - Hints.ai_socktype = SOCK_STREAM; - Hints.ai_protocol = IPPROTO_TCP; - - addrinfo* PotentialConnections; - s32 Error = getaddrinfo(Socket->Addr, Socket->Port, &Hints, &PotentialConnections); - if (Error == 0) - { - for (addrinfo* InfoAt = PotentialConnections; InfoAt != NULL; InfoAt = InfoAt->ai_next) - { - SOCKET SocketHandle = socket(InfoAt->ai_family, InfoAt->ai_socktype, InfoAt->ai_protocol); - if (SocketHandle == INVALID_SOCKET) - { - Error = WSAGetLastError(); - InvalidCodePath; - } - - // If iMode == 0, blocking is enabled - // if iMode != 0, non-blocking mode is enabled - u_long iMode = 0; - Error = ioctlsocket(SocketHandle, FIONBIO, &iMode); - if (Error != NO_ERROR) - { - InvalidCodePath; - } - - Error = connect(SocketHandle, InfoAt->ai_addr, (int)InfoAt->ai_addrlen); - if (Error == SOCKET_ERROR) - { - u32 Status = WSAGetLastError(); - if (Status == WSAEWOULDBLOCK) - { - // Non-blocking sockets -#if 0 - TIMEVAL Timeout = { 0, 500 }; - fd_set SocketSet = {}; - FD_ZERO(&SocketSet); - FD_SET(SocketHandle, &SocketSet); - Assert(FD_ISSET(SocketHandle, &SocketSet)); - Status = select(0, &SocketSet, 0, 0, (const TIMEVAL*)&Timeout); - if (Status == SOCKET_ERROR) - { - - } - else if (Status == 0) - { - } - else - { - - } -#endif - } - else - { - closesocket(SocketHandle); - continue; - } - } - - Socket->PlatformHandle = (u8*)Win32Alloc(sizeof(SOCKET), 0); - *(SOCKET*)Socket->PlatformHandle = SocketHandle; - Result = true; - break; - } - } - else + bool Result = false; + + addrinfo Hints = {0}; + Hints.ai_family = AF_UNSPEC; + Hints.ai_socktype = SOCK_STREAM; + Hints.ai_protocol = IPPROTO_TCP; + + addrinfo* PotentialConnections; + s32 Error = getaddrinfo(Socket->Addr, Socket->Port, &Hints, &PotentialConnections); + if (Error == 0) + { + for (addrinfo* InfoAt = PotentialConnections; InfoAt != NULL; InfoAt = InfoAt->ai_next) { + SOCKET SocketHandle = socket(InfoAt->ai_family, InfoAt->ai_socktype, InfoAt->ai_protocol); + if (SocketHandle == INVALID_SOCKET) + { Error = WSAGetLastError(); InvalidCodePath; + } + + // If iMode == 0, blocking is enabled + // if iMode != 0, non-blocking mode is enabled + u_long iMode = 0; + Error = ioctlsocket(SocketHandle, FIONBIO, &iMode); + if (Error != NO_ERROR) + { + InvalidCodePath; + } + + Error = connect(SocketHandle, InfoAt->ai_addr, (int)InfoAt->ai_addrlen); + if (Error == SOCKET_ERROR) + { + u32 Status = WSAGetLastError(); + if (Status == WSAEWOULDBLOCK) + { + // Non-blocking sockets +#if 0 + TIMEVAL Timeout = { 0, 500 }; + fd_set SocketSet = {}; + FD_ZERO(&SocketSet); + FD_SET(SocketHandle, &SocketSet); + Assert(FD_ISSET(SocketHandle, &SocketSet)); + Status = select(0, &SocketSet, 0, 0, (const TIMEVAL*)&Timeout); + if (Status == SOCKET_ERROR) + { + + } + else if (Status == 0) + { + } + else + { + + } +#endif + } + else + { + closesocket(SocketHandle); + continue; + } + } + + Socket->PlatformHandle = (u8*)Win32Alloc(sizeof(SOCKET), 0, 0); + *(SOCKET*)Socket->PlatformHandle = SocketHandle; + Result = true; + break; } - - if (!Result) - { - Assert(Socket->PlatformHandle == 0); - } - - freeaddrinfo(PotentialConnections); - return Result; + } + else + { + Error = WSAGetLastError(); + InvalidCodePath; + } + + if (!Result) + { + Assert(Socket->PlatformHandle == 0); + } + + freeaddrinfo(PotentialConnections); + return Result; } internal bool Win32CloseSocket(platform_socket_manager* Manager, platform_socket* Socket) { - SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; - closesocket(*Win32Sock); - Win32Free((u8*)Socket->PlatformHandle, sizeof(SOCKET)); - *Socket = {}; - return true; + SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; + closesocket(*Win32Sock); + Win32Free((u8*)Socket->PlatformHandle, sizeof(SOCKET), 0); + *Socket = {}; + return true; } internal bool Win32SocketQueryStatus(platform_socket_manager* Manager, platform_socket* Socket) { - SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; - bool Result = (*Win32Sock != INVALID_SOCKET); - return Result; + SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; + bool Result = (*Win32Sock != INVALID_SOCKET); + return Result; } internal u32 Win32SocketPeek(platform_socket_manager* Manager, platform_socket* Socket) { - u32 Result = 0; - s32 Flags = MSG_PEEK; - SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; - char Temp[4]; - u32 TempSize = 4; - - //Log_Message(GlobalLogBuffer, "Pre Peek..."); - //s32 BytesQueued = recv(*Win32Sock, Temp, TempSize, Flags); - u_long BytesQueued = 0; - ioctlsocket(*Win32Sock, FIONREAD, &BytesQueued); - //Log_Message(GlobalLogBuffer, "Post Peek\n"); - - if (BytesQueued != SOCKET_ERROR) + u32 Result = 0; + s32 Flags = MSG_PEEK; + SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; + char Temp[4]; + u32 TempSize = 4; + + //Log_Message(GlobalLogBuffer, "Pre Peek..."); + //s32 BytesQueued = recv(*Win32Sock, Temp, TempSize, Flags); + u_long BytesQueued = 0; + ioctlsocket(*Win32Sock, FIONREAD, &BytesQueued); + //Log_Message(GlobalLogBuffer, "Post Peek\n"); + + if (BytesQueued != SOCKET_ERROR) + { + Result = (u32)BytesQueued; + } + else + { + s32 Error = WSAGetLastError(); + switch (Error) { - Result = (u32)BytesQueued; + case WSAEWOULDBLOCK: + { + // NOTE(PS): This case covers non-blocking sockets + // if we peek and there's nothing there, it returns + // this error code. MSDN says its a non-fatal error + // and the operation should be retried later + Result = 0; + } break; + + case WSAENOTCONN: + case WSAECONNRESET: + case WSAECONNABORTED: + { + CloseSocket(Manager, Socket); + }break; + + InvalidDefaultCase; } - else - { - s32 Error = WSAGetLastError(); - switch (Error) - { - case WSAEWOULDBLOCK: - { - // NOTE(PS): This case covers non-blocking sockets - // if we peek and there's nothing there, it returns - // this error code. MSDN says its a non-fatal error - // and the operation should be retried later - Result = 0; - } break; - - case WSAENOTCONN: - case WSAECONNRESET: - case WSAECONNABORTED: - { - CloseSocket(Manager, Socket); - }break; - - InvalidDefaultCase; - } - } - return (s32)Result; + } + return (s32)Result; } internal gs_data Win32SocketReceive(platform_socket_manager* Manager, platform_socket* Socket, gs_memory_arena* Storage) { - // TODO(pjs): Test this first code path when you have data running - it should - // get the actual size of the data packet being sent + // TODO(pjs): Test this first code path when you have data running - it should + // get the actual size of the data packet being sent #if 0 - gs_data Result = {}; - s32 BytesQueued = Win32Socket_PeekGetTotalSize(Socket); - if (BytesQueued > 0) - { - Result = PushSizeToData(Storage, BytesQueued); - s32 Flags = 0; - s32 BytesReceived = recv(Socket->Socket, (char*)Result.Memory, Result.Size, Flags); - Assert(BytesReceived == BytesQueued); - } - return Result; -#else - gs_data Result = PushSizeToData(Storage, 1024); + gs_data Result = {}; + s32 BytesQueued = Win32Socket_PeekGetTotalSize(Socket); + if (BytesQueued > 0) + { + Result = PushSizeToData(Storage, BytesQueued); s32 Flags = 0; - SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; - s32 BytesReceived = recv(*Win32Sock, (char*)Result.Memory, Result.Size, Flags); - if (BytesReceived == SOCKET_ERROR) - { - // TODO(pjs): Error logging - s32 Error = WSAGetLastError(); - InvalidCodePath; - } - Result.Size = BytesReceived; - return Result; + s32 BytesReceived = recv(Socket->Socket, (char*)Result.Memory, Result.Size, Flags); + Assert(BytesReceived == BytesQueued); + } + return Result; +#else + gs_data Result = PushSize(Storage, 1024); + s32 Flags = 0; + SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; + s32 BytesReceived = recv(*Win32Sock, (char*)Result.Memory, Result.Size, Flags); + if (BytesReceived == SOCKET_ERROR) + { + // TODO(pjs): Error logging + s32 Error = WSAGetLastError(); + InvalidCodePath; + } + Result.Size = BytesReceived; + return Result; #endif } @@ -318,193 +318,193 @@ Win32SocketReceive(platform_socket_manager* Manager, platform_socket* Socket, gs internal s32 Win32SocketSend(platform_socket_manager* Manager, platform_socket* Socket, u32 Address, u32 Port, gs_data Data, s32 Flags) { - SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; - - sockaddr_in SockAddress = {}; - SockAddress.sin_family = AF_INET; - SockAddress.sin_port = HostToNetU16(Port); - SockAddress.sin_addr.s_addr = HostToNetU32(Address); - - s32 LengthSent = sendto(*Win32Sock, (char*)Data.Memory, Data.Size, Flags, (sockaddr*)&SockAddress, sizeof(sockaddr_in)); - - //Log_Message(GlobalLogBuffer, "Attempting To Send Network Data: "); - if (LengthSent == SOCKET_ERROR) + SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; + + sockaddr_in SockAddress = {}; + SockAddress.sin_family = AF_INET; + SockAddress.sin_port = HostToNetU16(Port); + SockAddress.sin_addr.s_addr = HostToNetU32(Address); + + s32 LengthSent = sendto(*Win32Sock, (char*)Data.Memory, Data.Size, Flags, (sockaddr*)&SockAddress, sizeof(sockaddr_in)); + + //Log_Message(GlobalLogBuffer, "Attempting To Send Network Data: "); + if (LengthSent == SOCKET_ERROR) + { + s32 Error = WSAGetLastError(); + switch (Error) { - s32 Error = WSAGetLastError(); - switch (Error) + case WSAEWOULDBLOCK: + { + // NOTE(PS): This covers non-blocking sockets + // In this case the message should be tried again + LengthSent = 0; + //Log_Message(GlobalLogBuffer, "Not sent, buffered\n"); + }break; + + case WSAECONNABORTED: + case WSAENETUNREACH: + case WSAECONNRESET: + case WSAENOTCONN: + { + if (CloseSocket(Manager, Socket)) { - case WSAEWOULDBLOCK: - { - // NOTE(PS): This covers non-blocking sockets - // In this case the message should be tried again - LengthSent = 0; - //Log_Message(GlobalLogBuffer, "Not sent, buffered\n"); - }break; - - case WSAECONNABORTED: - case WSAENETUNREACH: - case WSAECONNRESET: - case WSAENOTCONN: - { - if (CloseSocket(Manager, Socket)) - { - Log_Error(GlobalLogBuffer, "Error: %d\n", Error); - Error = 0; - } - }break; - - InvalidDefaultCase; + Log_Error(GlobalLogBuffer, "Error: %d\n", Error); + Error = 0; } + }break; + + InvalidDefaultCase; } - else - { - Log_Message(GlobalLogBuffer, "Sent\n"); - } - - return LengthSent; + } + else + { + Log_Message(GlobalLogBuffer, "Sent\n"); + } + + return LengthSent; } internal s32 Win32Socket_SetOption(win32_socket* Socket, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength) { - int Error = setsockopt(Socket->Socket, Level, Option, OptionValue, OptionLength); - if (Error == SOCKET_ERROR) - { - Error = WSAGetLastError(); - // TODO(Peter): :ErrorLogging - } - - return Error; + int Error = setsockopt(Socket->Socket, Level, Option, OptionValue, OptionLength); + if (Error == SOCKET_ERROR) + { + Error = WSAGetLastError(); + // TODO(Peter): :ErrorLogging + } + + return Error; } internal s32 Win32Socket_SetOption(platform_socket_handle SocketHandle, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength) { - win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, (s32)SocketHandle); - return Win32Socket_SetOption(Socket, Level, Option, OptionValue, OptionLength); + win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, (s32)SocketHandle); + return Win32Socket_SetOption(Socket, Level, Option, OptionValue, OptionLength); } internal s32 Win32Socket_SendTo(platform_socket_handle SocketHandle, u32 Address, u32 Port, const char* Buffer, s32 BufferLength, s32 Flags) { - win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, (s32)SocketHandle); - - sockaddr_in SockAddress = {}; - SockAddress.sin_family = AF_INET; - SockAddress.sin_port = HostToNetU16(Port); - SockAddress.sin_addr.s_addr = HostToNetU32(Address); - - s32 LengthSent = sendto(Socket->Socket, Buffer, BufferLength, Flags, (sockaddr*)&SockAddress, sizeof(sockaddr_in)); - - Log_Message(GlobalLogBuffer, "Attempting To Send Network Data: "); - if (LengthSent == SOCKET_ERROR) + win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, (s32)SocketHandle); + + sockaddr_in SockAddress = {}; + SockAddress.sin_family = AF_INET; + SockAddress.sin_port = HostToNetU16(Port); + SockAddress.sin_addr.s_addr = HostToNetU32(Address); + + s32 LengthSent = sendto(Socket->Socket, Buffer, BufferLength, Flags, (sockaddr*)&SockAddress, sizeof(sockaddr_in)); + + Log_Message(GlobalLogBuffer, "Attempting To Send Network Data: "); + if (LengthSent == SOCKET_ERROR) + { + s32 Error = WSAGetLastError(); + switch (Error) { - s32 Error = WSAGetLastError(); - switch (Error) - { - case WSAENETUNREACH: - { - Log_Message(GlobalLogBuffer, - "Non Critical Error: WSAENETUNREACH \n"); - } break; - - default: - { - Log_Error(GlobalLogBuffer, "Error: %d \n", Error); - InvalidCodePath; - } break; - } + case WSAENETUNREACH: + { + Log_Message(GlobalLogBuffer, + "Non Critical Error: WSAENETUNREACH \n"); + } break; + + default: + { + Log_Error(GlobalLogBuffer, "Error: %d \n", Error); + InvalidCodePath; + } break; } - else - { - Log_Message(GlobalLogBuffer, "Sent\n"); - } - - return LengthSent; + } + else + { + Log_Message(GlobalLogBuffer, "Sent\n"); + } + + return LengthSent; } internal void Win32Socket_SetListening(win32_socket* Socket) { - if (listen(Socket->Socket, SOMAXCONN) == SOCKET_ERROR) - { - // TODO(pjs): Error logging - s32 Error = WSAGetLastError(); - InvalidCodePath; - } + if (listen(Socket->Socket, SOMAXCONN) == SOCKET_ERROR) + { + // TODO(pjs): Error logging + s32 Error = WSAGetLastError(); + InvalidCodePath; + } } internal s32 Win32Socket_PeekGetTotalSize(win32_socket* Socket) { - s32 Flags = MSG_PEEK; - char Temp[4]; - s32 BytesQueued = recv(Socket->Socket, Temp, 4, Flags); - if (BytesQueued == SOCKET_ERROR) - { - // TODO(pjs): Error logging - s32 Error = WSAGetLastError(); - BytesQueued = 0; - } - return BytesQueued; + s32 Flags = MSG_PEEK; + char Temp[4]; + s32 BytesQueued = recv(Socket->Socket, Temp, 4, Flags); + if (BytesQueued == SOCKET_ERROR) + { + // TODO(pjs): Error logging + s32 Error = WSAGetLastError(); + BytesQueued = 0; + } + return BytesQueued; } internal gs_data Win32Socket_Receive(win32_socket* Socket, gs_memory_arena* Storage) { #if 0 - gs_data Result = {}; - s32 BytesQueued = Win32Socket_PeekGetTotalSize(Socket); - if (BytesQueued > 0) - { - Result = PushSizeToData(Storage, BytesQueued); - s32 Flags = 0; - s32 BytesReceived = recv(Socket->Socket, (char*)Result.Memory, Result.Size, Flags); - Assert(BytesReceived == BytesQueued); - } - return Result; -#else - gs_data Result = PushSizeToData(Storage, 1024); + gs_data Result = {}; + s32 BytesQueued = Win32Socket_PeekGetTotalSize(Socket); + if (BytesQueued > 0) + { + Result = PushSizeToData(Storage, BytesQueued); s32 Flags = 0; s32 BytesReceived = recv(Socket->Socket, (char*)Result.Memory, Result.Size, Flags); - if (BytesReceived == SOCKET_ERROR) + Assert(BytesReceived == BytesQueued); + } + return Result; +#else + gs_data Result = PushSize(Storage, 1024); + s32 Flags = 0; + s32 BytesReceived = recv(Socket->Socket, (char*)Result.Memory, Result.Size, Flags); + if (BytesReceived == SOCKET_ERROR) + { + // TODO(pjs): Error logging + s32 Error = WSAGetLastError(); + switch (Error) { - // TODO(pjs): Error logging - s32 Error = WSAGetLastError(); - switch (Error) - { - case WSAECONNABORTED: - case WSANOTINITIALISED: - break; - - case WSAENOTCONN: - { - - }break; - InvalidDefaultCase; - } + case WSAECONNABORTED: + case WSANOTINITIALISED: + break; + + case WSAENOTCONN: + { + + }break; + InvalidDefaultCase; } - Result.Size = BytesReceived; - return Result; + } + Result.Size = BytesReceived; + return Result; #endif } internal void Win32Socket_Close(win32_socket* Socket) { - closesocket(Socket->Socket); - Socket->Socket = INVALID_SOCKET; + closesocket(Socket->Socket); + Socket->Socket = INVALID_SOCKET; } internal void Win32Socket_CloseArray(win32_socket_array Array) { - for (s32 i = 0; i < Array.Count; i++) - { - win32_socket* Socket = Array.Values + i; - Win32Socket_Close(Socket); - } + for (s32 i = 0; i < Array.Count; i++) + { + win32_socket* Socket = Array.Values + i; + Win32Socket_Close(Socket); + } } ////////////////////// @@ -514,30 +514,30 @@ Win32Socket_CloseArray(win32_socket_array Array) internal void Win32SocketSystem_Init(gs_memory_arena* Arena) { - WSAStartup(MAKEWORD(2, 2), &WSAData); - Win32Sockets = Win32SocketArray_Create(16, Arena); + WSAStartup(MAKEWORD(2, 2), &WSAData); + Win32Sockets = Win32SocketArray_Create(16, Arena); } internal void Win32SocketSystem_Cleanup() { - Win32Socket_CloseArray(Win32Sockets); - - s32 CleanupResult = 0; - do { - CleanupResult = WSACleanup(); - }while(CleanupResult == SOCKET_ERROR); + Win32Socket_CloseArray(Win32Sockets); + + s32 CleanupResult = 0; + do { + CleanupResult = WSACleanup(); + }while(CleanupResult == SOCKET_ERROR); } PLATFORM_GET_SOCKET_HANDLE(Win32GetSocketHandle) { - s32 Result = Win32SocketArray_Take(&Win32Sockets); - s32 Error = 0; - win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, Result); - *Socket = Win32Socket_Create(AF_INET, SOCK_DGRAM, 0); - Error = Win32Socket_SetOption(Socket, IPPROTO_IP, IP_MULTICAST_TTL, - (const char*)(&Multicast_TimeToLive), sizeof(Multicast_TimeToLive)); - return (platform_socket_handle)Result; + s32 Result = Win32SocketArray_Take(&Win32Sockets); + s32 Error = 0; + win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, Result); + *Socket = Win32Socket_Create(AF_INET, SOCK_DGRAM, 0); + Error = Win32Socket_SetOption(Socket, IPPROTO_IP, IP_MULTICAST_TTL, + (const char*)(&Multicast_TimeToLive), sizeof(Multicast_TimeToLive)); + return (platform_socket_handle)Result; } #define WIN32_FOLDHAUS_SOCKET_H diff --git a/src/app/platform_win32/win32_foldhaus_work_queue.h b/src/app/platform_win32/win32_foldhaus_work_queue.h index f35259e..7c56418 100644 --- a/src/app/platform_win32/win32_foldhaus_work_queue.h +++ b/src/app/platform_win32/win32_foldhaus_work_queue.h @@ -7,22 +7,22 @@ struct worker_thread_entry { - b32 IsValid; - u32 Index; + b32 IsValid; + u32 Index; }; struct worker_thread_info { - gs_thread_context ThreadContext; - HANDLE Handle; - gs_work_queue* Queue; + gs_thread_context ThreadContext; + HANDLE Handle; + gs_work_queue* Queue; }; struct win32_work_queue { - u32 ThreadCount; - worker_thread_info* Threads; - gs_work_queue WorkQueue; + u32 ThreadCount; + worker_thread_info* Threads; + gs_work_queue WorkQueue; }; worker_thread_info* WorkerThreads; @@ -31,219 +31,219 @@ win32_work_queue Win32WorkQueue; internal s32 Win32GetThreadId() { - s32 Result = GetCurrentThreadId(); - return Result; + s32 Result = GetCurrentThreadId(); + return Result; } internal gs_thread_context Win32CreateThreadContext(gs_memory_arena* Transient = 0) { - gs_thread_context Result = {0}; - Result.ThreadInfo.ThreadID = Win32GetThreadId(); - Result.Allocator = CreateAllocator(Win32Alloc, Win32Free); - if (Transient != 0) - { - Result.Transient = Transient; - } - else - { - Result.Transient = (gs_memory_arena*)AllocatorAlloc(Result.Allocator, sizeof(gs_memory_arena)).Memory; - *Result.Transient = CreateMemoryArena(Result.Allocator, "Tctx Transient"); - } - Result.FileHandler = CreateFileHandler(Win32GetFileInfo, - Win32ReadEntireFile, - Win32WriteEntireFile, - Win32EnumerateDirectory, - Result.Transient); - - Result.DebugOutput.Print = Win32DebugPrint; - - return Result; + gs_thread_context Result = {0}; + Result.ThreadInfo.ThreadID = Win32GetThreadId(); + Result.Allocator = CreatePlatformAllocator(); + if (Transient != 0) + { + Result.Transient = Transient; + } + else + { + Result.Transient = AllocStruct(Result.Allocator, gs_memory_arena, "Work Queue"); + *Result.Transient = MemoryArenaCreate(MB(4), Bytes(8), Result.Allocator, 0, 0, "Tctx Transient"); + } + Result.FileHandler = CreateFileHandler(Win32GetFileInfo, + Win32ReadEntireFile, + Win32WriteEntireFile, + Win32EnumerateDirectory, + Result.Transient); + + Result.DebugOutput.Print = Win32DebugPrint; + + return Result; } PUSH_WORK_ON_QUEUE(Win32PushWorkOnQueue) { #if DEBUG - // NOTE(Peter): Just prints out the names of all the pending jobs if we end up - // overflowing the buffer - if (Queue->JobsCount >= Queue->JobsMax) + // NOTE(Peter): Just prints out the names of all the pending jobs if we end up + // overflowing the buffer + if (Queue->JobsCount >= Queue->JobsMax) + { + gs_string DebugString = MakeString((char*)malloc(256), 256); + for (u32 i = 0; i < Queue->JobsCount; i++) { - gs_string DebugString = MakeString((char*)malloc(256), 256); - for (u32 i = 0; i < Queue->JobsCount; i++) - { - Log_Message(GlobalLogBuffer, "%d %s \n", i, Queue->Jobs[i].JobName); - } + Log_Message(GlobalLogBuffer, "%d %s \n", i, Queue->Jobs[i].JobName); } + } #endif - Assert(Queue->JobsCount < Queue->JobsMax); - - gs_threaded_job* Job = Queue->Jobs + Queue->JobsCount; - Job->WorkProc = WorkProc; - Job->Data = Data; + Assert(Queue->JobsCount < Queue->JobsMax); + + gs_threaded_job* Job = Queue->Jobs + Queue->JobsCount; + Job->WorkProc = WorkProc; + Job->Data = Data; #if DEBUG - Job->JobName = JobName; + Job->JobName = JobName; #endif - - // Complete Past Writes before Future Writes - _WriteBarrier(); - _mm_sfence(); - - ++Queue->JobsCount; - ReleaseSemaphore(Queue->SemaphoreHandle, 1, 0); + + // Complete Past Writes before Future Writes + _WriteBarrier(); + _mm_sfence(); + + ++Queue->JobsCount; + ReleaseSemaphore(Queue->SemaphoreHandle, 1, 0); } internal worker_thread_entry CompleteAndTakeNextJob(gs_work_queue* Queue, worker_thread_entry Completed, gs_thread_context Context) { - if (Completed.IsValid) + if (Completed.IsValid) + { + InterlockedIncrement((LONG volatile*)&Queue->JobsCompleted); + } + + worker_thread_entry Result = {}; + Result.IsValid = false; + + u32 OriginalNextJobIndex = Queue->NextJobIndex; + while (OriginalNextJobIndex < Queue->JobsCount) + { + u32 Index = InterlockedCompareExchange((LONG volatile*)&Queue->NextJobIndex, + OriginalNextJobIndex + 1, + OriginalNextJobIndex); + if (Index == OriginalNextJobIndex) { - InterlockedIncrement((LONG volatile*)&Queue->JobsCompleted); + Result.Index = Index; + Result.IsValid = true; + break; } - - worker_thread_entry Result = {}; - Result.IsValid = false; - - u32 OriginalNextJobIndex = Queue->NextJobIndex; - while (OriginalNextJobIndex < Queue->JobsCount) - { - u32 Index = InterlockedCompareExchange((LONG volatile*)&Queue->NextJobIndex, - OriginalNextJobIndex + 1, - OriginalNextJobIndex); - if (Index == OriginalNextJobIndex) - { - Result.Index = Index; - Result.IsValid = true; - break; - } - OriginalNextJobIndex = Queue->NextJobIndex; - } - - return Result; + OriginalNextJobIndex = Queue->NextJobIndex; + } + + return Result; } COMPLETE_QUEUE_WORK(Win32DoQueueWorkUntilDone) { - worker_thread_entry Entry = {}; - Entry.IsValid = false; - while (Queue->JobsCompleted < Queue->JobsCount) + worker_thread_entry Entry = {}; + Entry.IsValid = false; + while (Queue->JobsCompleted < Queue->JobsCount) + { + Entry = CompleteAndTakeNextJob(Queue, Entry, Context); + if (Entry.IsValid) { - Entry = CompleteAndTakeNextJob(Queue, Entry, Context); - if (Entry.IsValid) - { - Queue->Jobs[Entry.Index].WorkProc(Context, Queue->Jobs[Entry.Index].Data); - } + Queue->Jobs[Entry.Index].WorkProc(Context, Queue->Jobs[Entry.Index].Data); } + } } DWORD WINAPI WorkerThreadProc (LPVOID InputThreadInfo) { - worker_thread_info* ThreadInfo = (worker_thread_info*)InputThreadInfo; - ThreadInfo->ThreadContext = Win32CreateThreadContext(); - - worker_thread_entry Entry = {}; - Entry.IsValid = false; - while (true) + worker_thread_info* ThreadInfo = (worker_thread_info*)InputThreadInfo; + ThreadInfo->ThreadContext = Win32CreateThreadContext(); + + worker_thread_entry Entry = {}; + Entry.IsValid = false; + while (true) + { + MemoryArenaClear(ThreadInfo->ThreadContext.Transient); + Entry = CompleteAndTakeNextJob(ThreadInfo->Queue, Entry, ThreadInfo->ThreadContext); + if (Entry.IsValid) { - ClearArena(ThreadInfo->ThreadContext.Transient); - Entry = CompleteAndTakeNextJob(ThreadInfo->Queue, Entry, ThreadInfo->ThreadContext); - if (Entry.IsValid) - { - ThreadInfo->Queue->Jobs[Entry.Index].WorkProc(ThreadInfo->ThreadContext, - ThreadInfo->Queue->Jobs[Entry.Index].Data); - } - else - { - WaitForSingleObjectEx(ThreadInfo->Queue->SemaphoreHandle, INFINITE, 0); - } + ThreadInfo->Queue->Jobs[Entry.Index].WorkProc(ThreadInfo->ThreadContext, + ThreadInfo->Queue->Jobs[Entry.Index].Data); } - - return 0; + else + { + WaitForSingleObjectEx(ThreadInfo->Queue->SemaphoreHandle, INFINITE, 0); + } + } + + return 0; } DWORD WINAPI Win32ThreadProcWrapper(LPVOID ThreadInfo) { - platform_thread* Thread = (platform_thread*)ThreadInfo; - gs_thread_context Ctx = Win32CreateThreadContext(); - Thread->Proc(&Ctx, Thread->UserData); - - // TODO(pjs): Destroy Thread Context - // TODO(pjs): How do we notify the thread manager this thread belongs to that it is free? - // Probaby put a pointer to the thread manager in the platform_thread struct - // so we can update the tracking structure? - - return 0; + platform_thread* Thread = (platform_thread*)ThreadInfo; + gs_thread_context Ctx = Win32CreateThreadContext(); + Thread->Proc(&Ctx, Thread->UserData); + + // TODO(pjs): Destroy Thread Context + // TODO(pjs): How do we notify the thread manager this thread belongs to that it is free? + // Probaby put a pointer to the thread manager in the platform_thread struct + // so we can update the tracking structure? + + return 0; } CREATE_THREAD(Win32CreateThread) { - Thread->Proc = Proc; - Thread->UserData = UserData; - - // TODO(pjs): ugh, allocation out in the middle of nowhere - HANDLE* ThreadHandle = AllocatorAllocStruct(Ctx.Allocator, HANDLE); - *ThreadHandle = CreateThread(0, 0, Win32ThreadProcWrapper, (void*)Thread, 0, 0); - // TODO(pjs): Error checking on the created thread - - Thread->PlatformHandle = (u8*)ThreadHandle; - - return true; + Thread->Proc = Proc; + Thread->UserData = UserData; + + // TODO(pjs): ugh, allocation out in the middle of nowhere + HANDLE* ThreadHandle = AllocStruct(Ctx.Allocator, HANDLE, "Create Thread"); + *ThreadHandle = CreateThread(0, 0, Win32ThreadProcWrapper, (void*)Thread, 0, 0); + // TODO(pjs): Error checking on the created thread + + Thread->PlatformHandle = (u8*)ThreadHandle; + + return true; } KILL_THREAD(Win32KillThread) { - HANDLE* ThreadHandle = (HANDLE*)Thread->PlatformHandle; - TerminateThread(ThreadHandle, 0); - - // TODO(pjs): see allocation out in the middle of nowhere in Win32CreateThread - Win32Free((void*)Thread->PlatformHandle, sizeof(HANDLE)); - - // TODO(pjs): Error checking - return true; + HANDLE* ThreadHandle = (HANDLE*)Thread->PlatformHandle; + TerminateThread(ThreadHandle, 0); + + // TODO(pjs): see allocation out in the middle of nowhere in Win32CreateThread + Win32Free((void*)Thread->PlatformHandle, sizeof(HANDLE), 0); + + // TODO(pjs): Error checking + return true; } internal void Win32WorkQueue_Init(gs_memory_arena* Arena, u32 ThreadCount) { - if (ThreadCount > 0) - { - Win32WorkQueue.ThreadCount = ThreadCount; - Win32WorkQueue.Threads = PushArray(Arena, worker_thread_info, ThreadCount); - } - - gs_work_queue WQ = {}; - WQ.SemaphoreHandle = CreateSemaphoreEx(0, 0, ThreadCount, 0, 0, SEMAPHORE_ALL_ACCESS);; - WQ.JobsMax = 512; - WQ.Jobs = PushArray(Arena, gs_threaded_job, WQ.JobsMax); - WQ.NextJobIndex = 0; - WQ.PushWorkOnQueue = Win32PushWorkOnQueue; - WQ.CompleteQueueWork = Win32DoQueueWorkUntilDone; - - Win32WorkQueue.WorkQueue = WQ; - - // ID = 0 is reserved for this thread - for (u32 i = 0; i < ThreadCount; i++) - { - worker_thread_info* T = Win32WorkQueue.Threads + i; - T->Queue = &Win32WorkQueue.WorkQueue; - T->Handle = CreateThread(0, 0, &WorkerThreadProc, (void*)T, 0, 0); - } + if (ThreadCount > 0) + { + Win32WorkQueue.ThreadCount = ThreadCount; + Win32WorkQueue.Threads = PushArray(Arena, worker_thread_info, ThreadCount); + } + + gs_work_queue WQ = {}; + WQ.SemaphoreHandle = CreateSemaphoreEx(0, 0, ThreadCount, 0, 0, SEMAPHORE_ALL_ACCESS);; + WQ.JobsMax = 512; + WQ.Jobs = PushArray(Arena, gs_threaded_job, WQ.JobsMax); + WQ.NextJobIndex = 0; + WQ.PushWorkOnQueue = Win32PushWorkOnQueue; + WQ.CompleteQueueWork = Win32DoQueueWorkUntilDone; + + Win32WorkQueue.WorkQueue = WQ; + + // ID = 0 is reserved for this thread + for (u32 i = 0; i < ThreadCount; i++) + { + worker_thread_info* T = Win32WorkQueue.Threads + i; + T->Queue = &Win32WorkQueue.WorkQueue; + T->Handle = CreateThread(0, 0, &WorkerThreadProc, (void*)T, 0, 0); + } } internal void Win32WorkQueue_Cleanup() { - u32 Error = 0; - for (u32 Thread = 0; Thread < Win32WorkQueue.ThreadCount; Thread++) + u32 Error = 0; + for (u32 Thread = 0; Thread < Win32WorkQueue.ThreadCount; Thread++) + { + u32 Success = TerminateThread(Win32WorkQueue.Threads[Thread].Handle, 0); + if (!Success) { - u32 Success = TerminateThread(Win32WorkQueue.Threads[Thread].Handle, 0); - if (!Success) - { - Error = GetLastError(); - InvalidCodePath; - } + Error = GetLastError(); + InvalidCodePath; } + } } #define WIN32_FOLDHAUS_WORK_QUEUE_H diff --git a/src/app/ss_blumen_lumen/blumen_lumen.cpp b/src/app/ss_blumen_lumen/blumen_lumen.cpp index 349db9c..5dcc0a8 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen.cpp +++ b/src/app/ss_blumen_lumen/blumen_lumen.cpp @@ -8,72 +8,72 @@ internal animation_handle_array LoadAllAnimationsInDir(gs_const_string Path, blumen_lumen_state* BLState, app_state* State, context Context) { - animation_handle_array Result = {}; - - gs_thread_context Ctx = Context.ThreadContext; - gs_file_info_array FilesInDir = EnumerateDirectory(Ctx.FileHandler, State->Transient, Path, 0); - - Result.Count = FilesInDir.Count; - Result.Handles = PushArray(&State->Permanent, animation_handle, Result.Count); - - for (u32 i = 0; i < FilesInDir.Count; i++) - { - gs_file_info File = FilesInDir.Values[i]; - Result.Handles[i] = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, - State->Patterns, - Context, - File.Path); - } - - return Result; + animation_handle_array Result = {}; + + gs_thread_context Ctx = Context.ThreadContext; + gs_file_info_array FilesInDir = EnumerateDirectory(Ctx.FileHandler, State->Transient, Path, 0); + + Result.Count = FilesInDir.Count; + Result.Handles = PushArray(&State->Permanent, animation_handle, Result.Count); + + for (u32 i = 0; i < FilesInDir.Count; i++) + { + gs_file_info File = FilesInDir.Values[i]; + Result.Handles[i] = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, + State->Patterns, + Context, + File.Path); + } + + return Result; } internal s32 GetCCIndex (assembly Assembly, blumen_lumen_state* BLState) { - s32 Result = 0; - - u64 AssemblyNameHash = HashDJB2ToU32(StringExpand(Assembly.Name)); - for (u32 i = 0; i < BLState->AssemblyNameToClearCoreMapCount; i++) + s32 Result = 0; + + u64 AssemblyNameHash = HashDJB2ToU32(StringExpand(Assembly.Name)); + for (u32 i = 0; i < BLState->AssemblyNameToClearCoreMapCount; i++) + { + if (AssemblyNameHash == BLState->AssemblyNameToClearCore_Names[i]) { - if (AssemblyNameHash == BLState->AssemblyNameToClearCore_Names[i]) - { - Result = (s32)i; - break; - } + Result = (s32)i; + break; } - - return Result; + } + + return Result; } internal void DEBUG_AppendText(gs_string Str, gs_thread_context Ctx) { - gs_const_string DebugPath = ConstString("data/debug_motor_changes.txt"); - gs_file DebugFile = ReadEntireFile(Ctx.FileHandler, - DebugPath); - gs_string NewString = PushString(Ctx.Transient, DebugFile.Size + Str.Size + 16); - if (DebugFile.Size > 0) - { - PrintF(&NewString, "%.*s\nENTRY:\n", DebugFile.Size, (char*)DebugFile.Memory); - } - AppendPrintF(&NewString, "%S\n", Str.ConstString); - NullTerminate(&NewString); - - if (!WriteEntireFile(Ctx.FileHandler, DebugPath, StringToData(NewString))) - { - InvalidCodePath; - } + gs_const_string DebugPath = ConstString("data/debug_motor_changes.txt"); + gs_file DebugFile = ReadEntireFile(Ctx.FileHandler, + DebugPath); + gs_string NewString = PushString(Ctx.Transient, DebugFile.Size + Str.Size + 16); + if (DebugFile.Size > 0) + { + PrintF(&NewString, "%.*s\nENTRY:\n", DebugFile.Size, (char*)DebugFile.Memory); + } + AppendPrintF(&NewString, "%S\n", Str.ConstString); + NullTerminate(&NewString); + + if (!WriteEntireFile(Ctx.FileHandler, DebugPath, StringToData(NewString))) + { + InvalidCodePath; + } } internal void DEBUG_SentMotorCommand(motor_packet Packet, gs_thread_context Ctx) { - Log_Message(GlobalLogBuffer, - "Motor Command Sent\nRequested Positions: %d %d %d\n", - Packet.FlowerPositions[0], - Packet.FlowerPositions[1], - Packet.FlowerPositions[2]); + Log_Message(GlobalLogBuffer, + "Motor Command Sent\nRequested Positions: %d %d %d\n", + Packet.FlowerPositions[0], + Packet.FlowerPositions[1], + Packet.FlowerPositions[2]); } internal void @@ -81,1021 +81,1021 @@ DEBUG_ReceivedMotorPositions(blumen_lumen_state* BLState, motor_status_packet NewPos, gs_thread_context Ctx) { - motor_packet LastPos = BLState->LastKnownMotorState; - bool PosChanged = (LastPos.FlowerPositions[0] != NewPos.Pos.FlowerPositions[0] || - LastPos.FlowerPositions[1] != NewPos.Pos.FlowerPositions[1] || - LastPos.FlowerPositions[2] != NewPos.Pos.FlowerPositions[2]); - - if (PosChanged) - { - Log_Message(GlobalLogBuffer, - "Motor Status Received\nCurrent Positions: %d %d %d\n", - NewPos.Pos.FlowerPositions[0], - NewPos.Pos.FlowerPositions[1], - NewPos.Pos.FlowerPositions[2]); - } + motor_packet LastPos = BLState->LastKnownMotorState; + bool PosChanged = (LastPos.FlowerPositions[0] != NewPos.Pos.FlowerPositions[0] || + LastPos.FlowerPositions[1] != NewPos.Pos.FlowerPositions[1] || + LastPos.FlowerPositions[2] != NewPos.Pos.FlowerPositions[2]); + + if (PosChanged) + { + Log_Message(GlobalLogBuffer, + "Motor Status Received\nCurrent Positions: %d %d %d\n", + NewPos.Pos.FlowerPositions[0], + NewPos.Pos.FlowerPositions[1], + NewPos.Pos.FlowerPositions[2]); + } } internal void DEBUG_ReceivedTemperature(temp_packet Temp, gs_thread_context Ctx) { - Log_Message(GlobalLogBuffer, - "\nTemperature: %d\n", - Temp.Temperature); + Log_Message(GlobalLogBuffer, + "\nTemperature: %d\n", + Temp.Temperature); } internal void BlumenLumen_MicListenJob(gs_thread_context* Ctx, u8* UserData) { - mic_listen_job_data* Data = (mic_listen_job_data*)UserData; - - gs_data Msg = {}; - - u8 WeathermanIPAddr[4] = {}; - WeathermanIPAddr[0] = 127; - WeathermanIPAddr[1] = 0; - WeathermanIPAddr[2] = 0; - WeathermanIPAddr[3] = 1; - - u32 WeathermanIPV4 = (u32)UpackB4(WeathermanIPAddr); - u32 WeathermanPort = 20185; - - platform_socket_handle_ ListenSocket = {0}; - - while (*Data->Running) + mic_listen_job_data* Data = (mic_listen_job_data*)UserData; + + gs_data Msg = {}; + + u8 WeathermanIPAddr[4] = {}; + WeathermanIPAddr[0] = 127; + WeathermanIPAddr[1] = 0; + WeathermanIPAddr[2] = 0; + WeathermanIPAddr[3] = 1; + + u32 WeathermanIPV4 = (u32)UpackB4(WeathermanIPAddr); + u32 WeathermanPort = 20185; + + platform_socket_handle_ ListenSocket = {0}; + + while (*Data->Running) + { + if (!SocketQueryStatus(Data->SocketManager, ListenSocket)) { - if (!SocketQueryStatus(Data->SocketManager, ListenSocket)) - { - Data->IsConnected = false; - if (SocketHandleIsValid(ListenSocket)) - { - Log_Message(GlobalLogBuffer, "Disconnected from Python Server\n"); - CloseSocket(Data->SocketManager, ListenSocket); - } - ListenSocket = CreateSocket(Data->SocketManager, "127.0.0.1", "20185"); - if (ListenSocket.Index != 0) - { - Log_Message(GlobalLogBuffer, "Connected to Python Server\n"); - Data->IsConnected = true; - } - } - - if (SocketQueryStatus(Data->SocketManager, ListenSocket)) - { - if (SocketPeek(Data->SocketManager, ListenSocket)) - { - Msg = SocketRecieve(Data->SocketManager, ListenSocket, Ctx->Transient); - if (Msg.Size > 0) - { - MessageQueue_Write(Data->IncomingMsgQueue, Msg); - } - } - - while (MessageQueue_CanRead(*Data->OutgoingMsgQueue)) - { - Msg = MessageQueue_Peek(Data->OutgoingMsgQueue); - - u32 Address = WeathermanIPV4; - u32 Port = WeathermanPort; - s32 Flags = 0; - s32 LengthSent = SocketSend(Data->SocketManager, ListenSocket, Address, Port, Msg, Flags); - if (LengthSent != 0) - { - // if we actually sent the message, THEN we pull it off the - // message queue - MessageQueue_Read(Data->OutgoingMsgQueue); - } else { - break; - } - } - } + Data->IsConnected = false; + if (SocketHandleIsValid(ListenSocket)) + { + Log_Message(GlobalLogBuffer, "Disconnected from Python Server\n"); + CloseSocket(Data->SocketManager, ListenSocket); + } + ListenSocket = CreateSocket(Data->SocketManager, "127.0.0.1", "20185"); + if (ListenSocket.Index != 0) + { + Log_Message(GlobalLogBuffer, "Connected to Python Server\n"); + Data->IsConnected = true; + } } - CloseSocket(Data->SocketManager, ListenSocket); + if (SocketQueryStatus(Data->SocketManager, ListenSocket)) + { + if (SocketPeek(Data->SocketManager, ListenSocket)) + { + Msg = SocketRecieve(Data->SocketManager, ListenSocket, Ctx->Transient); + if (Msg.Size > 0) + { + MessageQueue_Write(Data->IncomingMsgQueue, Msg); + } + } + + while (MessageQueue_CanRead(*Data->OutgoingMsgQueue)) + { + Msg = MessageQueue_Peek(Data->OutgoingMsgQueue); + + u32 Address = WeathermanIPV4; + u32 Port = WeathermanPort; + s32 Flags = 0; + s32 LengthSent = SocketSend(Data->SocketManager, ListenSocket, Address, Port, Msg, Flags); + if (LengthSent != 0) + { + // if we actually sent the message, THEN we pull it off the + // message queue + MessageQueue_Read(Data->OutgoingMsgQueue); + } else { + break; + } + } + } + } + + CloseSocket(Data->SocketManager, ListenSocket); } internal void BlumenLumen_SetPatternMode(bl_pattern_mode Mode, r32 FadeDuration, animation_system* System, blumen_lumen_state* BLState) { - BLState->PatternMode = Mode; - animation_handle_array Playlist = BLState->ModeAnimations[Mode]; - System->RepeatMode = AnimationRepeat_Loop; - System->PlaylistFadeTime = FadeDuration; - AnimationSystem_FadeToPlaylist(System, Playlist); + BLState->PatternMode = Mode; + animation_handle_array Playlist = BLState->ModeAnimations[Mode]; + System->RepeatMode = AnimationRepeat_Loop; + System->PlaylistFadeTime = FadeDuration; + AnimationSystem_FadeToPlaylist(System, Playlist); } internal void BlumenLumen_LoadPatterns(app_state* State) { - animation_pattern_array* Patterns = &State->Patterns; - if (Patterns->CountMax == 0) - { - *Patterns = Patterns_Create(&State->Permanent, 32); - } - - Patterns->Count = 0; - Patterns_PushPattern(Patterns, Pattern_None, PATTERN_SINGLETHREADED); - Patterns_PushPattern(Patterns, Pattern_HueShift, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_Rainbow, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_BasicFlowers, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_Wavy, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_Patchy, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_Leafy, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_LeafyPatchy, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_WavyPatchy, PATTERN_SINGLETHREADED); - Patterns_PushPattern(Patterns, Pattern_VerticalLines, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_Rotary, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_AllOnMask, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_BulbMask, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_VoicePattern, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_VoiceAddIns, PATTERN_MULTITHREADED); - - Patterns_PushPattern(Patterns, Pattern_StemSolid, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_PrimaryHue, PATTERN_MULTITHREADED); - - Patterns_PushPattern(Patterns, Pattern_GrowFadeMask, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_RainbowLoadingBar, PATTERN_MULTITHREADED); - - Patterns_PushPattern(Patterns, Pattern_Blue, PATTERN_MULTITHREADED); + animation_pattern_array* Patterns = &State->Patterns; + if (Patterns->CountMax == 0) + { + *Patterns = Patterns_Create(&State->Permanent, 32); + } + + Patterns->Count = 0; + Patterns_PushPattern(Patterns, Pattern_None, PATTERN_SINGLETHREADED); + Patterns_PushPattern(Patterns, Pattern_HueShift, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_Rainbow, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_BasicFlowers, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_Wavy, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_Patchy, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_Leafy, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_LeafyPatchy, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_WavyPatchy, PATTERN_SINGLETHREADED); + Patterns_PushPattern(Patterns, Pattern_VerticalLines, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_Rotary, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_AllOnMask, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_BulbMask, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_VoicePattern, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_VoiceAddIns, PATTERN_MULTITHREADED); + + Patterns_PushPattern(Patterns, Pattern_StemSolid, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_PrimaryHue, PATTERN_MULTITHREADED); + + Patterns_PushPattern(Patterns, Pattern_GrowFadeMask, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_RainbowLoadingBar, PATTERN_MULTITHREADED); + + Patterns_PushPattern(Patterns, Pattern_Blue, PATTERN_MULTITHREADED); } internal void AppendPrintDate(gs_string* WriteStr, system_time Time) { - AppendPrintF(WriteStr, "%d-%d-%d : %d:%d:%d\n\n", - Time.Year, Time.Month, Time.Day, - Time.Hour, Time.Minute, Time.Second); + AppendPrintF(WriteStr, "%d-%d-%d : %d:%d:%d\n\n", + Time.Year, Time.Month, Time.Day, + Time.Hour, Time.Minute, Time.Second); } internal void BlumenLumen_AppendBootupLog(app_state* State, blumen_lumen_state* BLState, context Context) { - gs_thread_context Ctx = Context.ThreadContext; - gs_const_string BootupLogPath = ConstString("lumenarium_boot_log.log"); - - gs_file BootLog = ReadEntireFile(Ctx.FileHandler, BootupLogPath); - gs_string WriteStr = {}; - - // we don't want the log file getting huge - // if it gets above some threshold, instead of appending, - // copy what there is to an _old file, and start this one over - // - // The thinking is that without the copy operation, when we reached - // our threshold, we'd overwrite the whole log. If something went - // wrong at that point, we'd have nothing to go on. This way, there is - // always some historical data present on the system - // - if (BootLog.Size < MB(4)) + gs_thread_context Ctx = Context.ThreadContext; + gs_const_string BootupLogPath = ConstString("lumenarium_boot_log.log"); + + gs_file BootLog = ReadEntireFile(Ctx.FileHandler, BootupLogPath); + gs_string WriteStr = {}; + + // we don't want the log file getting huge + // if it gets above some threshold, instead of appending, + // copy what there is to an _old file, and start this one over + // + // The thinking is that without the copy operation, when we reached + // our threshold, we'd overwrite the whole log. If something went + // wrong at that point, we'd have nothing to go on. This way, there is + // always some historical data present on the system + // + if (BootLog.Size < MB(4)) + { + WriteStr = PushString(State->Transient, BootLog.Size + 1024); + } + else + { + if (!WriteEntireFile(Ctx.FileHandler, ConstString("lumenarium_boot_log_old.log"), + BootLog.Data)) { - WriteStr = PushString(State->Transient, BootLog.Size + 1024); + InvalidCodePath; } - else - { - if (!WriteEntireFile(Ctx.FileHandler, ConstString("lumenarium_boot_log_old.log"), - BootLog.Data)) - { - InvalidCodePath; - } - WriteStr = PushString(State->Transient, 1024); - } - - - // Copy old entries in - if (BootLog.Size > 0) - { - PrintF(&WriteStr, "%.*s", BootLog.Size, BootLog.Memory); - } - - // New Entry - AppendPrintF(&WriteStr, "Lumenarium Restarted\n"); - AppendPrintF(&WriteStr, "* Time: "); - AppendPrintDate(&WriteStr, Context.SystemTime_Current); - - gs_data Data = StringToData(WriteStr); - WriteEntireFile(Ctx.FileHandler, BootupLogPath, Data); + WriteStr = PushString(State->Transient, 1024); + } + + + // Copy old entries in + if (BootLog.Size > 0) + { + PrintF(&WriteStr, "%.*s", BootLog.Size, BootLog.Memory); + } + + // New Entry + AppendPrintF(&WriteStr, "Lumenarium Restarted\n"); + AppendPrintF(&WriteStr, "* Time: "); + AppendPrintDate(&WriteStr, Context.SystemTime_Current); + + gs_data Data = StringToData(WriteStr); + WriteEntireFile(Ctx.FileHandler, BootupLogPath, Data); } internal void BlumenLumen_UpdateLog(app_state* State, blumen_lumen_state* BLState, context Context) { - if (!BLState->ShouldUpdateLog) return; - - gs_string FileStr = PushString(State->Transient, 1024); - AppendPrintF(&FileStr, "Lumenarium Status\n"); - - AppendPrintF(&FileStr, "Last Updated At:"); - AppendPrintDate(&FileStr, Context.SystemTime_Current); - AppendPrintF(&FileStr, "\n\n"); - - animation* CurrAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); - AppendPrintF(&FileStr, "Curr Animation: %S\n", CurrAnim->Name); - - bool IsPlaying = State->AnimationSystem.TimelineShouldAdvance; - AppendPrintF(&FileStr, "\tIs Playing: %s\n", - IsPlaying ? "True" : "False"); - - char* Connected = BLState->MicListenJobData.IsConnected ? "Connected" : "Disconnected"; - AppendPrintF(&FileStr, "Connected to Python: %s\n", Connected); - - u8 MP0 = BLState->LastKnownMotorState.FlowerPositions[0]; - u8 MP1 = BLState->LastKnownMotorState.FlowerPositions[1]; - u8 MP2 = BLState->LastKnownMotorState.FlowerPositions[2]; - AppendPrintF(&FileStr, "Last Known Motor State: %d %d %d\n", MP0, MP1, MP2); - - time_range MotorRange = {}; - if (SystemTimeIsInTimeRangeList(Context.SystemTime_Current, - MotorOpenTimes, - MotorOpenTimesCount, - &MotorRange)) - { - AppendPrintF(&FileStr, "\tIn Motor-Open Time Range: ( %d:%d - %d:%d)\n", - MotorRange.StartHour, MotorRange.StartMinute, - MotorRange.EndHour, MotorRange.EndMinute); - } - else - { - AppendPrintF(&FileStr, "\tIn Motor-Open Time Range: None\n"); - } - - char* PatternMode = 0; - switch (BLState->PatternMode) - { - case BlumenPattern_Standard: { PatternMode = "Standard"; } break; - case BlumenPattern_VoiceCommand: { PatternMode = "Voice Command"; } break; - case BlumenPattern_NoControl: { PatternMode = "No Control: Someone's doing the Awaken sequence!"; } break; - } - AppendPrintF(&FileStr, "Pattern Mode: %s\n", PatternMode); - - phrase_hue LastHuePhrase = BLState->LastHuePhrase; - AppendPrintF(&FileStr, "Last Mic Phrase: %S\n", LastHuePhrase.Phrase); - - AppendPrintF(&FileStr, "Pattern Speed: %f\n", BLState->PatternSpeed); - - AppendPrintF(&FileStr, "Pattern Brightness: %f\n", BLState->BrightnessPercent); - - time_range RangeIn = {}; - if (SystemTimeIsInTimeRangeList(Context.SystemTime_Current, - LedOnTimes, - LedOnTimesCount, - &RangeIn)) - { - AppendPrintF(&FileStr, "\tIn Leds-On Time Range: ( %d:%d - %d:%d)\n", - RangeIn.StartHour, RangeIn.StartMinute, - RangeIn.EndHour, RangeIn.EndMinute); - } - else - { - AppendPrintF(&FileStr, "\tIn Leds-On Time Range: None\n"); - } - - AppendPrintF(&FileStr, "\tTemp Dimming: %s\n", - Blumen_TempShouldDimLeds(BLState) ? "On" : "Off"); - - AppendPrintF(&FileStr, "Last Temp Received: %d\n", BLState->LastTemperatureReceived); - - gs_data LogMem = StringToData(FileStr); - if (!WriteEntireFile(Context.ThreadContext.FileHandler, ConstString("lumenarium_status.log"), LogMem)) - { - InvalidCodePath; - } + if (!BLState->ShouldUpdateLog) return; + + gs_string FileStr = PushString(State->Transient, 1024); + AppendPrintF(&FileStr, "Lumenarium Status\n"); + + AppendPrintF(&FileStr, "Last Updated At:"); + AppendPrintDate(&FileStr, Context.SystemTime_Current); + AppendPrintF(&FileStr, "\n\n"); + + animation* CurrAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); + AppendPrintF(&FileStr, "Curr Animation: %S\n", CurrAnim->Name); + + bool IsPlaying = State->AnimationSystem.TimelineShouldAdvance; + AppendPrintF(&FileStr, "\tIs Playing: %s\n", + IsPlaying ? "True" : "False"); + + char* Connected = BLState->MicListenJobData.IsConnected ? "Connected" : "Disconnected"; + AppendPrintF(&FileStr, "Connected to Python: %s\n", Connected); + + u8 MP0 = BLState->LastKnownMotorState.FlowerPositions[0]; + u8 MP1 = BLState->LastKnownMotorState.FlowerPositions[1]; + u8 MP2 = BLState->LastKnownMotorState.FlowerPositions[2]; + AppendPrintF(&FileStr, "Last Known Motor State: %d %d %d\n", MP0, MP1, MP2); + + time_range MotorRange = {}; + if (SystemTimeIsInTimeRangeList(Context.SystemTime_Current, + MotorOpenTimes, + MotorOpenTimesCount, + &MotorRange)) + { + AppendPrintF(&FileStr, "\tIn Motor-Open Time Range: ( %d:%d - %d:%d)\n", + MotorRange.StartHour, MotorRange.StartMinute, + MotorRange.EndHour, MotorRange.EndMinute); + } + else + { + AppendPrintF(&FileStr, "\tIn Motor-Open Time Range: None\n"); + } + + char* PatternMode = 0; + switch (BLState->PatternMode) + { + case BlumenPattern_Standard: { PatternMode = "Standard"; } break; + case BlumenPattern_VoiceCommand: { PatternMode = "Voice Command"; } break; + case BlumenPattern_NoControl: { PatternMode = "No Control: Someone's doing the Awaken sequence!"; } break; + } + AppendPrintF(&FileStr, "Pattern Mode: %s\n", PatternMode); + + phrase_hue LastHuePhrase = BLState->LastHuePhrase; + AppendPrintF(&FileStr, "Last Mic Phrase: %S\n", LastHuePhrase.Phrase); + + AppendPrintF(&FileStr, "Pattern Speed: %f\n", BLState->PatternSpeed); + + AppendPrintF(&FileStr, "Pattern Brightness: %f\n", BLState->BrightnessPercent); + + time_range RangeIn = {}; + if (SystemTimeIsInTimeRangeList(Context.SystemTime_Current, + LedOnTimes, + LedOnTimesCount, + &RangeIn)) + { + AppendPrintF(&FileStr, "\tIn Leds-On Time Range: ( %d:%d - %d:%d)\n", + RangeIn.StartHour, RangeIn.StartMinute, + RangeIn.EndHour, RangeIn.EndMinute); + } + else + { + AppendPrintF(&FileStr, "\tIn Leds-On Time Range: None\n"); + } + + AppendPrintF(&FileStr, "\tTemp Dimming: %s\n", + Blumen_TempShouldDimLeds(BLState) ? "On" : "Off"); + + AppendPrintF(&FileStr, "Last Temp Received: %d\n", BLState->LastTemperatureReceived); + + gs_data LogMem = StringToData(FileStr); + if (!WriteEntireFile(Context.ThreadContext.FileHandler, ConstString("lumenarium_status.log"), LogMem)) + { + InvalidCodePath; + } } internal gs_data BlumenLumen_CustomInit(app_state* State, context Context) { - // This is memory for any custom data that we want to use - // as a part of a particular sculpture. - // By returning it from here, it will be sent as an argument to - // the sculpture's CustomUpdate function; - gs_data Result = {}; - - Result = PushSizeToData(&State->Permanent, sizeof(blumen_lumen_state)); - - blumen_lumen_state* BLState = (blumen_lumen_state*)Result.Memory; - BLState->Running = true; - BLState->BrightnessPercent = 1; - MessageQueue_Init(&BLState->IncomingMsgQueue, &State->Permanent); - MessageQueue_Init(&BLState->OutgoingMsgQueue, &State->Permanent); - - BLState->MicListenJobData.Running = &BLState->Running; - BLState->MicListenJobData.SocketManager = Context.SocketManager; - BLState->MicListenJobData.IncomingMsgQueue = &BLState->IncomingMsgQueue; - BLState->MicListenJobData.OutgoingMsgQueue = &BLState->OutgoingMsgQueue; - - BLState->PatternSpeed = GlobalAnimSpeed; - + // This is memory for any custom data that we want to use + // as a part of a particular sculpture. + // By returning it from here, it will be sent as an argument to + // the sculpture's CustomUpdate function; + gs_data Result = {}; + + Result = PushSize(&State->Permanent, sizeof(blumen_lumen_state)); + + blumen_lumen_state* BLState = (blumen_lumen_state*)Result.Memory; + BLState->Running = true; + BLState->BrightnessPercent = 1; + MessageQueue_Init(&BLState->IncomingMsgQueue, &State->Permanent); + MessageQueue_Init(&BLState->OutgoingMsgQueue, &State->Permanent); + + BLState->MicListenJobData.Running = &BLState->Running; + BLState->MicListenJobData.SocketManager = Context.SocketManager; + BLState->MicListenJobData.IncomingMsgQueue = &BLState->IncomingMsgQueue; + BLState->MicListenJobData.OutgoingMsgQueue = &BLState->OutgoingMsgQueue; + + BLState->PatternSpeed = GlobalAnimSpeed; + #if 1 - BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData, Context.ThreadContext); + BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData, Context.ThreadContext); #endif + + assembly* Flower0 = LoadAssembly(Flower0AssemblyPath, State, Context); + assembly* Flower1 = LoadAssembly(Flower1AssemblyPath, State, Context); + assembly* Flower2 = LoadAssembly(Flower2AssemblyPath, State, Context); + + for (u32 i = 0; i < BL_FLOWER_COUNT; i++) + { + assembly Assembly = State->Assemblies.Values[i]; + BLState->StemStrips[Assembly.AssemblyIndex] = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("stem"), &State->Permanent); + } + + BLState->AssemblyNameToClearCoreMapCount = 3; + BLState->AssemblyNameToClearCore_Names = PushArray(&State->Permanent, + u64, + BLState->AssemblyNameToClearCoreMapCount); + BLState->AssemblyNameToClearCore_Names[0] = HashDJB2ToU32(StringExpand(Flower2->Name)); + BLState->AssemblyNameToClearCore_Names[1] = HashDJB2ToU32(StringExpand(Flower1->Name)); + BLState->AssemblyNameToClearCore_Names[2] = HashDJB2ToU32(StringExpand(Flower0->Name)); + + gs_file_handler FileHandler = Context.ThreadContext.FileHandler; + gs_file ColorPhraseCSVFile = ReadEntireFile(FileHandler, PhraseMapCSVPath); + if (ColorPhraseCSVFile.Memory != 0) + { + gs_const_string ColorPhraseMapStr = DataToString(ColorPhraseCSVFile.Data); + gscsv_sheet ColorPhraseSheet = CSV_Parse(ColorPhraseMapStr, + { PhraseMapCSVSeparator }, + State->Transient); - assembly* Flower0 = LoadAssembly(Flower0AssemblyPath, State, Context); - assembly* Flower1 = LoadAssembly(Flower1AssemblyPath, State, Context); - assembly* Flower2 = LoadAssembly(Flower2AssemblyPath, State, Context); - - for (u32 i = 0; i < BL_FLOWER_COUNT; i++) - { - assembly Assembly = State->Assemblies.Values[i]; - BLState->StemStrips[Assembly.AssemblyIndex] = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("stem"), &State->Permanent); - } - - BLState->AssemblyNameToClearCoreMapCount = 3; - BLState->AssemblyNameToClearCore_Names = PushArray(&State->Permanent, - u64, - BLState->AssemblyNameToClearCoreMapCount); - BLState->AssemblyNameToClearCore_Names[0] = HashDJB2ToU32(StringExpand(Flower2->Name)); - BLState->AssemblyNameToClearCore_Names[1] = HashDJB2ToU32(StringExpand(Flower1->Name)); - BLState->AssemblyNameToClearCore_Names[2] = HashDJB2ToU32(StringExpand(Flower0->Name)); - - gs_file_handler FileHandler = Context.ThreadContext.FileHandler; - gs_file ColorPhraseCSVFile = ReadEntireFile(FileHandler, PhraseMapCSVPath); - if (ColorPhraseCSVFile.Memory != 0) - { - gs_const_string ColorPhraseMapStr = DataToString(ColorPhraseCSVFile.Data); - gscsv_sheet ColorPhraseSheet = CSV_Parse(ColorPhraseMapStr, - { PhraseMapCSVSeparator }, - State->Transient); - - BLState->PhraseHueMap = PhraseHueMap_GenFromCSV(ColorPhraseSheet, - &State->Permanent); - } - + BLState->PhraseHueMap = PhraseHueMap_GenFromCSV(ColorPhraseSheet, + &State->Permanent); + } + #if 0 - animation_handle DemoPatternsAnim = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, - State->Patterns, - Context, - ConstString("data/demo_patterns.foldanim")); - State->AnimationSystem.ActiveFadeGroup.From = DemoPatternsAnim; + animation_handle DemoPatternsAnim = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, + State->Patterns, + Context, + ConstString("data/demo_patterns.foldanim")); + State->AnimationSystem.ActiveFadeGroup.From = DemoPatternsAnim; #else - - BLState->ModeAnimations[BlumenPattern_Standard] = LoadAllAnimationsInDir(AmbientPatternFolder, BLState, State, Context); - BLState->ModeAnimations[BlumenPattern_VoiceCommand] = LoadAllAnimationsInDir(VoicePatternFolder, BLState, State, Context); - AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, State->Patterns, Context, ConstString("data/blumen_animations/anim_demo.foldanim")); - - BlumenLumen_SetPatternMode(BlumenPattern_Standard, GlobalAnimTransitionSpeed, &State->AnimationSystem, BLState); - - BLState->AwakenHandle = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, - State->Patterns, - Context, - ConstString("data/blumen_animations/awaken.foldanim")); - BLState->OffAnimHandle = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, - State->Patterns, - Context, - ConstString("data/blumen_animations/off_anim.foldanim")); - + + BLState->ModeAnimations[BlumenPattern_Standard] = LoadAllAnimationsInDir(AmbientPatternFolder, BLState, State, Context); + BLState->ModeAnimations[BlumenPattern_VoiceCommand] = LoadAllAnimationsInDir(VoicePatternFolder, BLState, State, Context); + AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, State->Patterns, Context, ConstString("data/blumen_animations/anim_demo.foldanim")); + + BlumenLumen_SetPatternMode(BlumenPattern_Standard, GlobalAnimTransitionSpeed, &State->AnimationSystem, BLState); + + BLState->AwakenHandle = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, + State->Patterns, + Context, + ConstString("data/blumen_animations/awaken.foldanim")); + BLState->OffAnimHandle = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, + State->Patterns, + Context, + ConstString("data/blumen_animations/off_anim.foldanim")); + #endif - State->AnimationSystem.TimelineShouldAdvance = true; - - BLState->StandardPatternHues.Granularity = 1; - BLState->StandardPatternHues.Speed = 1; - BLState->StandardPatternHues.AddIn = AddIn_Rotary; - BLState->StandardPatternHues.Pattern = HuePattern_Wavy; - - BLState->DebugHue.Hue0.HSV = v4{0, 1, 1, 1}; - BLState->DebugHue.Hue1.HSV = v4{0, 1, 1, 1}; - BLState->DebugHue.Hue2.HSV = v4{0, 1, 1, 1}; - - BlumenLumen_AppendBootupLog(State, BLState, Context); - return Result; + State->AnimationSystem.TimelineShouldAdvance = true; + + BLState->StandardPatternHues.Granularity = 1; + BLState->StandardPatternHues.Speed = 1; + BLState->StandardPatternHues.AddIn = AddIn_Rotary; + BLState->StandardPatternHues.Pattern = HuePattern_Wavy; + + BLState->DebugHue.Hue0.HSV = v4{0, 1, 1, 1}; + BLState->DebugHue.Hue1.HSV = v4{0, 1, 1, 1}; + BLState->DebugHue.Hue2.HSV = v4{0, 1, 1, 1}; + + BlumenLumen_AppendBootupLog(State, BLState, Context); + return Result; } internal void BlumenLumen_UpdateMotorState(blumen_lumen_state* BLState, motor_status_packet Motor, context Context) { - DEBUG_ReceivedMotorPositions(BLState, Motor, Context.ThreadContext); - - motor_packet LastPos = BLState->LastKnownMotorState; - motor_packet CurrPos = Motor.Pos; - for (u32 i = 0; i < BL_FLOWER_COUNT; i++) + DEBUG_ReceivedMotorPositions(BLState, Motor, Context.ThreadContext); + + motor_packet LastPos = BLState->LastKnownMotorState; + motor_packet CurrPos = Motor.Pos; + for (u32 i = 0; i < BL_FLOWER_COUNT; i++) + { + if (LastPos.FlowerPositions[i] != CurrPos.FlowerPositions[i]) { - if (LastPos.FlowerPositions[i] != CurrPos.FlowerPositions[i]) - { - BLState->LastTimeMotorStateChanged[i] = Context.SystemTime_Current.NanosSinceEpoch; - } + BLState->LastTimeMotorStateChanged[i] = Context.SystemTime_Current.NanosSinceEpoch; } - - BLState->LastKnownMotorState = Motor.Pos; - BLState->ShouldUpdateLog = true; + } + + BLState->LastKnownMotorState = Motor.Pos; + BLState->ShouldUpdateLog = true; } internal void BlumenLumen_ApplyNextHotHue(blumen_lumen_state* BLState, context Context, gs_string* DebugStr, app_state* State) { - // if we are in standard color mode, shift all flowers to the new color - // otherwise, only shift the next flower in the sequence to the new color - phrase_hue NewHue = BLState->NextHotHue; - Log_Message(GlobalLogBuffer, "Switching To: %S\n", NewHue.Phrase); - - - if (BLState->PatternMode == BlumenPattern_Standard || - NewHue.OverrideAll) - { - BlumenLumen_SetNextHue(BLState, 0, NewHue); - BlumenLumen_SetNextHue(BLState, 1, NewHue); - BlumenLumen_SetNextHue(BLState, 2, NewHue); - } - else - { - u32 AssemblyIdx = BLState->LastAssemblyColorSet; - BlumenLumen_SetNextHue(BLState, AssemblyIdx, NewHue); - BLState->LastAssemblyColorSet = (BLState->LastAssemblyColorSet + 1) % 3; - } - - BlumenLumen_SetPatternMode(BlumenPattern_VoiceCommand, GlobalAnimTransitionSpeed, &State->AnimationSystem, BLState); - BLState->TimeLastSetToVoiceMode = Context.SystemTime_Current; - BLState->LastHuePhrase = NewHue; - BLState->ShouldUpdateLog = true; - BLState->InPhraseReceptionMode = false; + // if we are in standard color mode, shift all flowers to the new color + // otherwise, only shift the next flower in the sequence to the new color + phrase_hue NewHue = BLState->NextHotHue; + Log_Message(GlobalLogBuffer, "Switching To: %S\n", NewHue.Phrase); + + + if (BLState->PatternMode == BlumenPattern_Standard || + NewHue.OverrideAll) + { + BlumenLumen_SetNextHue(BLState, 0, NewHue); + BlumenLumen_SetNextHue(BLState, 1, NewHue); + BlumenLumen_SetNextHue(BLState, 2, NewHue); + } + else + { + u32 AssemblyIdx = BLState->LastAssemblyColorSet; + BlumenLumen_SetNextHue(BLState, AssemblyIdx, NewHue); + BLState->LastAssemblyColorSet = (BLState->LastAssemblyColorSet + 1) % 3; + } + + BlumenLumen_SetPatternMode(BlumenPattern_VoiceCommand, GlobalAnimTransitionSpeed, &State->AnimationSystem, BLState); + BLState->TimeLastSetToVoiceMode = Context.SystemTime_Current; + BLState->LastHuePhrase = NewHue; + BLState->ShouldUpdateLog = true; + BLState->InPhraseReceptionMode = false; } internal void BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) { - blumen_lumen_state* BLState = (blumen_lumen_state*)UserData.Memory; - BLState->ShouldUpdateLog = false; + blumen_lumen_state* BLState = (blumen_lumen_state*)UserData.Memory; + BLState->ShouldUpdateLog = false; + + gs_string DebugStr = PushString(State->Transient, 256); + + while (MessageQueue_CanRead(BLState->IncomingMsgQueue)) + { + gs_data PacketData = MessageQueue_Read(&BLState->IncomingMsgQueue); + if (PacketData.Memory == 0) continue; - gs_string DebugStr = PushString(State->Transient, 256); - - while (MessageQueue_CanRead(BLState->IncomingMsgQueue)) - { - gs_data PacketData = MessageQueue_Read(&BLState->IncomingMsgQueue); - if (PacketData.Memory == 0) continue; + blumen_packet Packet = *(blumen_packet*)PacketData.Memory; + switch (Packet.Type) { + case PacketType_PatternCommand: + { + microphone_packet Mic = Packet.MicPacket; + u64 NameHash = HashDJB2ToU32(Mic.AnimationFileName); + u32 NameLen = CStringLength(Mic.AnimationFileName); - blumen_packet Packet = *(blumen_packet*)PacketData.Memory; - switch (Packet.Type) { - case PacketType_PatternCommand: - { - microphone_packet Mic = Packet.MicPacket; - u64 NameHash = HashDJB2ToU32(Mic.AnimationFileName); - u32 NameLen = CStringLength(Mic.AnimationFileName); - - phrase_hue NewHue = PhraseHueMap_Find(BLState->PhraseHueMap, NameHash); - if (NewHue.Phrase.Length > 0) - { - bool IsLonger = (BLState->NextHotHue.Phrase.Length < NewHue.Phrase.Length); - bool IsntInPhraseReceptionMode = !BLState->InPhraseReceptionMode; - if (IsLonger || IsntInPhraseReceptionMode) - { - Log_Message(GlobalLogBuffer, "Queueing: %S\n", NewHue.Phrase); - - BLState->NextHotHue = NewHue; - if (SecondsElapsed(BLState->TimePhraseReceptionBegan, - Context->SystemTime_Current) > PhrasePriorityMessageGroupingTime) - { - BLState->TimePhraseReceptionBegan = Context->SystemTime_Current; - BLState->InPhraseReceptionMode = true; - } - BLState->TimeLastPhraseReceived = Context->SystemTime_Current; - } - } - }break; - - case PacketType_MotorState: - { - motor_status_packet Motor = Packet.MotorStatusPacket; - - // NOTE(pjs): Python sends multi-byte integers in little endian - // order. Have to unpack - u8* T = (u8*)&Motor.Temperature; - Motor.Temperature = (T[0] << 8 | - T[1] << 0); - - BlumenLumen_UpdateMotorState(BLState, Motor, *Context); - }break; - - case PacketType_Temperature: - { - temp_packet Temp = Packet.TempPacket; - BLState->LastTemperatureReceived = Temp.Temperature; - DEBUG_ReceivedTemperature(Temp, Context->ThreadContext); - BLState->ShouldUpdateLog = true; - }break; - - InvalidDefaultCase; - } - } - - if (BLState->InPhraseReceptionMode) - { - r32 SecondsSincePhraseBegan = SecondsElapsed(BLState->TimePhraseReceptionBegan, Context->SystemTime_Current); - if (SecondsSincePhraseBegan > PhrasePriorityMessageGroupingTime) + phrase_hue NewHue = PhraseHueMap_Find(BLState->PhraseHueMap, NameHash); + if (NewHue.Phrase.Length > 0) { - BlumenLumen_ApplyNextHotHue(BLState, *Context, &DebugStr, State); - } - } - - BlumenLumen_AdvanceHueFade(BLState, *Context); - - // Update next frames Hues - if (!BLState->DebugOverrideHue) - { - r32 AnimTime = AnimationSystem_GetCurrentTime(State->AnimationSystem); - AnimTime = (r32)Context->TotalTime; - r32 BaseTime = AnimTime * BLState->PatternSpeed; - - r32 ColorSpeed = 1; //.001; - r32 ColorOscSpeed = .05 * ColorSpeed; - r32 ColorRelOscSpeed = 1 * ColorSpeed;; - r32 ColorOscillation = (SinR32(BaseTime * ColorOscSpeed) + 1) / 2; - r32 ColorRelationship = 30 + (((1 + SinR32(BaseTime * ColorRelOscSpeed)) / 2) * 300); - - r32 H0 = ModR32(ColorOscillation * 360, 360); - r32 H1 = ModR32(BaseTime + ColorRelationship, 360); - // TODO(PS): use our new HSV lerp - r32 H2 = LerpR32(.3f, H0, H1); - - BLState->StandardPatternHues.Hue0.HSV = v4{ H0, 1, 1, 1 }; - BLState->StandardPatternHues.Hue1.HSV = v4{ H1, 1, 1, 1 }; - BLState->StandardPatternHues.Hue2.HSV = v4{ H2, 1, 1, 1 }; - - // Transition back to standard mode after some time - if (BLState->PatternMode == BlumenPattern_VoiceCommand) - { - u64 LastChangeClock = BLState->TimeLastSetToVoiceMode.NanosSinceEpoch; - u64 NowClocks = Context->SystemTime_Current.NanosSinceEpoch; - s64 NanosSinceChange = NowClocks - LastChangeClock; - r64 SecondsSinceChange = (r64)NanosSinceChange * NanosToSeconds; + bool IsLonger = (BLState->NextHotHue.Phrase.Length < NewHue.Phrase.Length); + bool IsntInPhraseReceptionMode = !BLState->InPhraseReceptionMode; + if (IsLonger || IsntInPhraseReceptionMode) + { + Log_Message(GlobalLogBuffer, "Queueing: %S\n", NewHue.Phrase); - if (SecondsSinceChange > VoiceCommandSustainDuration) + BLState->NextHotHue = NewHue; + if (SecondsElapsed(BLState->TimePhraseReceptionBegan, + Context->SystemTime_Current) > PhrasePriorityMessageGroupingTime) { - BlumenLumen_SetPatternMode(BlumenPattern_Standard, GlobalAnimTransitionSpeed, &State->AnimationSystem, BLState); - BLState->ShouldUpdateLog = true; + BLState->TimePhraseReceptionBegan = Context->SystemTime_Current; + BLState->InPhraseReceptionMode = true; } + BLState->TimeLastPhraseReceived = Context->SystemTime_Current; + } } + }break; + + case PacketType_MotorState: + { + motor_status_packet Motor = Packet.MotorStatusPacket; + // NOTE(pjs): Python sends multi-byte integers in little endian + // order. Have to unpack + u8* T = (u8*)&Motor.Temperature; + Motor.Temperature = (T[0] << 8 | + T[1] << 0); + + BlumenLumen_UpdateMotorState(BLState, Motor, *Context); + }break; + + case PacketType_Temperature: + { + temp_packet Temp = Packet.TempPacket; + BLState->LastTemperatureReceived = Temp.Temperature; + DEBUG_ReceivedTemperature(Temp, Context->ThreadContext); + BLState->ShouldUpdateLog = true; + }break; + + InvalidDefaultCase; } - else + } + + if (BLState->InPhraseReceptionMode) + { + r32 SecondsSincePhraseBegan = SecondsElapsed(BLState->TimePhraseReceptionBegan, Context->SystemTime_Current); + if (SecondsSincePhraseBegan > PhrasePriorityMessageGroupingTime) { - BLState->StandardPatternHues = BLState->DebugHue; - AnimationSystem_FadeToPlaylist(&State->AnimationSystem, BLState->ModeAnimations[BlumenPattern_VoiceCommand]); - + BlumenLumen_ApplyNextHotHue(BLState, *Context, &DebugStr, State); + } + } + + BlumenLumen_AdvanceHueFade(BLState, *Context); + + // Update next frames Hues + if (!BLState->DebugOverrideHue) + { + r32 AnimTime = AnimationSystem_GetCurrentTime(State->AnimationSystem); + AnimTime = (r32)Context->TotalTime; + r32 BaseTime = AnimTime * BLState->PatternSpeed; + + r32 ColorSpeed = 1; //.001; + r32 ColorOscSpeed = .05 * ColorSpeed; + r32 ColorRelOscSpeed = 1 * ColorSpeed;; + r32 ColorOscillation = (SinR32(BaseTime * ColorOscSpeed) + 1) / 2; + r32 ColorRelationship = 30 + (((1 + SinR32(BaseTime * ColorRelOscSpeed)) / 2) * 300); + + r32 H0 = ModR32(ColorOscillation * 360, 360); + r32 H1 = ModR32(BaseTime + ColorRelationship, 360); + // TODO(PS): use our new HSV lerp + r32 H2 = LerpR32(.3f, H0, H1); + + BLState->StandardPatternHues.Hue0.HSV = v4{ H0, 1, 1, 1 }; + BLState->StandardPatternHues.Hue1.HSV = v4{ H1, 1, 1, 1 }; + BLState->StandardPatternHues.Hue2.HSV = v4{ H2, 1, 1, 1 }; + + // Transition back to standard mode after some time + if (BLState->PatternMode == BlumenPattern_VoiceCommand) + { + u64 LastChangeClock = BLState->TimeLastSetToVoiceMode.NanosSinceEpoch; + u64 NowClocks = Context->SystemTime_Current.NanosSinceEpoch; + s64 NanosSinceChange = NowClocks - LastChangeClock; + r64 SecondsSinceChange = (r64)NanosSinceChange * NanosToSeconds; + + if (SecondsSinceChange > VoiceCommandSustainDuration) + { + BlumenLumen_SetPatternMode(BlumenPattern_Standard, GlobalAnimTransitionSpeed, &State->AnimationSystem, BLState); + BLState->ShouldUpdateLog = true; + } } - // Open / Close the Motor - if (MessageQueue_CanWrite(BLState->OutgoingMsgQueue) && - !BLState->IgnoreTimeOfDay_MotorState) + } + else + { + BLState->StandardPatternHues = BLState->DebugHue; + AnimationSystem_FadeToPlaylist(&State->AnimationSystem, BLState->ModeAnimations[BlumenPattern_VoiceCommand]); + + } + + // Open / Close the Motor + if (MessageQueue_CanWrite(BLState->OutgoingMsgQueue) && + !BLState->IgnoreTimeOfDay_MotorState) + { + bool SendMotorCommand = false; + + u64 NanosSinceLastSend = Context->SystemTime_Current.NanosSinceEpoch - BLState->LastSendTime.NanosSinceEpoch; + r32 SecondsSinceLastSend = (r64)NanosSinceLastSend * NanosToSeconds; + bool ShouldSendCurrentState = SecondsSinceLastSend >= MotorResendStatePeriod; + + bl_motor_state_value NewMotorState = MotorState_Closed; + bool SendOpen = false; + for (u32 i = 0; i < MotorOpenTimesCount; i++) { - bool SendMotorCommand = false; - - u64 NanosSinceLastSend = Context->SystemTime_Current.NanosSinceEpoch - BLState->LastSendTime.NanosSinceEpoch; - r32 SecondsSinceLastSend = (r64)NanosSinceLastSend * NanosToSeconds; - bool ShouldSendCurrentState = SecondsSinceLastSend >= MotorResendStatePeriod; - - bl_motor_state_value NewMotorState = MotorState_Closed; - bool SendOpen = false; - for (u32 i = 0; i < MotorOpenTimesCount; i++) - { - time_range Range = MotorOpenTimes[i]; - bool CurrTimeInRange = SystemTimeIsInTimeRange(Context->SystemTime_Current, Range); - if (CurrTimeInRange) { - NewMotorState = MotorState_Open; - } - } - - if (NewMotorState != BLState->LastSendState) - { - ShouldSendCurrentState = true; - } - - if (ShouldSendCurrentState) - { - BLState->LastSendTime = Context->SystemTime_Current; - BLState->LastSendState = NewMotorState; - - blumen_packet Packet = {}; - Packet.Type = PacketType_MotorState; - Packet.MotorPacket.FlowerPositions[0] = NewMotorState; - Packet.MotorPacket.FlowerPositions[1] = NewMotorState; - Packet.MotorPacket.FlowerPositions[2] = NewMotorState; - gs_data Msg = StructToData(&Packet, blumen_packet); - MessageQueue_Write(&BLState->OutgoingMsgQueue, Msg); - - DEBUG_SentMotorCommand(Packet.MotorPacket, Context->ThreadContext); - } + time_range Range = MotorOpenTimes[i]; + bool CurrTimeInRange = SystemTimeIsInTimeRange(Context->SystemTime_Current, Range); + if (CurrTimeInRange) { + NewMotorState = MotorState_Open; + } } - // When a motor state changes to being open, wait to turn Upper Leds on - // in order to hide the fact that they are turning off - motor_packet CurrMotorPos = BLState->LastKnownMotorState; - u64 NowNanos = Context->SystemTime_Current.NanosSinceEpoch; - for (u32 i = 0; i < BL_FLOWER_COUNT; i++) + if (NewMotorState != BLState->LastSendState) { - // have to map from "assembly load order" to - // the order that the clear core is referencing the - // motors by - assembly Assembly = State->Assemblies.Values[i]; - u64 AssemblyCCIndex = GetCCIndex(Assembly, BLState); - u8 MotorPos = CurrMotorPos.FlowerPositions[AssemblyCCIndex]; - - if ((MotorPos == MotorState_Open || MotorPos == MotorState_MostlyOpen) && - !BLState->ShouldDimUpperLeds[i]) - { - u64 ChangedNanos = BLState->LastTimeMotorStateChanged[i]; - u64 NanosSinceChanged = NowNanos - ChangedNanos; - r64 SecondsSinceChanged = (r64)NanosSinceChanged * NanosToSeconds; - if (SecondsSinceChanged > TurnUpperLedsOffAfterMotorCloseCommandDelay) - { - BLState->ShouldDimUpperLeds[i] = true; - } - else - { - BLState->ShouldDimUpperLeds[i] = false; - } - } - else if (MotorPos == MotorState_Closed || - MotorPos == MotorState_HalfOpen) - { - BLState->ShouldDimUpperLeds[i] = false; - } + ShouldSendCurrentState = true; } - // NOTE(PS): If the flowers are mostly open or full open - // we mask off the top leds to prevent them from overheating - // while telescoped inside the flower - for (u32 a = 0; a < BL_FLOWER_COUNT; a++) + if (ShouldSendCurrentState) { - assembly Assembly = State->Assemblies.Values[a]; - if (!BLState->ShouldDimUpperLeds[a]) continue; - - led_buffer Buffer = State->LedSystem.Buffers[Assembly.LedBufferIndex]; - led_strip_list TopStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("inner_bloom"), State->Transient); - for (u32 s = 0; s < TopStrips.Count; s++) - { - u32 SIndex = TopStrips.StripIndices[s]; - v2_strip Strip = Assembly.Strips[SIndex]; - for (u32 l = 0; l < Strip.LedCount; l++) - { - u32 LIndex = Strip.LedLUT[l]; - Buffer.Colors[LIndex] = {0}; - } - } + BLState->LastSendTime = Context->SystemTime_Current; + BLState->LastSendState = NewMotorState; + + blumen_packet Packet = {}; + Packet.Type = PacketType_MotorState; + Packet.MotorPacket.FlowerPositions[0] = NewMotorState; + Packet.MotorPacket.FlowerPositions[1] = NewMotorState; + Packet.MotorPacket.FlowerPositions[2] = NewMotorState; + gs_data Msg = StructToData(&Packet, blumen_packet); + MessageQueue_Write(&BLState->OutgoingMsgQueue, Msg); + + DEBUG_SentMotorCommand(Packet.MotorPacket, Context->ThreadContext); + } + } + + // When a motor state changes to being open, wait to turn Upper Leds on + // in order to hide the fact that they are turning off + motor_packet CurrMotorPos = BLState->LastKnownMotorState; + u64 NowNanos = Context->SystemTime_Current.NanosSinceEpoch; + for (u32 i = 0; i < BL_FLOWER_COUNT; i++) + { + // have to map from "assembly load order" to + // the order that the clear core is referencing the + // motors by + assembly Assembly = State->Assemblies.Values[i]; + u64 AssemblyCCIndex = GetCCIndex(Assembly, BLState); + u8 MotorPos = CurrMotorPos.FlowerPositions[AssemblyCCIndex]; + + if ((MotorPos == MotorState_Open || MotorPos == MotorState_MostlyOpen) && + !BLState->ShouldDimUpperLeds[i]) + { + u64 ChangedNanos = BLState->LastTimeMotorStateChanged[i]; + u64 NanosSinceChanged = NowNanos - ChangedNanos; + r64 SecondsSinceChanged = (r64)NanosSinceChanged * NanosToSeconds; + if (SecondsSinceChanged > TurnUpperLedsOffAfterMotorCloseCommandDelay) + { + BLState->ShouldDimUpperLeds[i] = true; + } + else + { + BLState->ShouldDimUpperLeds[i] = false; + } + } + else if (MotorPos == MotorState_Closed || + MotorPos == MotorState_HalfOpen) + { + BLState->ShouldDimUpperLeds[i] = false; + } + } + + // NOTE(PS): If the flowers are mostly open or full open + // we mask off the top leds to prevent them from overheating + // while telescoped inside the flower + for (u32 a = 0; a < BL_FLOWER_COUNT; a++) + { + assembly Assembly = State->Assemblies.Values[a]; + if (!BLState->ShouldDimUpperLeds[a]) continue; + + led_buffer Buffer = State->LedSystem.Buffers[Assembly.LedBufferIndex]; + led_strip_list TopStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("inner_bloom"), State->Transient); + for (u32 s = 0; s < TopStrips.Count; s++) + { + u32 SIndex = TopStrips.StripIndices[s]; + v2_strip Strip = Assembly.Strips[SIndex]; + for (u32 l = 0; l < Strip.LedCount; l++) + { + u32 LIndex = Strip.LedLUT[l]; + Buffer.Colors[LIndex] = {0}; + } + } + } + + if (!BLState->IgnoreTimeOfDay_LedDimming) + { + bool TimelineShouldAdvance = false; + r32 OverrideBrightness = 0.0f; + + time_range RangeIn = {}; + if (SystemTimeIsInTimeRangeList(Context->SystemTime_Current, + LedOnTimes, + LedOnTimesCount, + &RangeIn)) + { + + if (Blumen_TempShouldDimLeds(BLState)) + { + OverrideBrightness = HighTemperatureBrightnessPercent; + } + else + { + OverrideBrightness = FullBrightnessPercent; + } + TimelineShouldAdvance = true; } - if (!BLState->IgnoreTimeOfDay_LedDimming) + State->AnimationSystem.TimelineShouldAdvance = TimelineShouldAdvance; + BLState->BrightnessPercent = OverrideBrightness; + } + + // Dim the leds based on temp data + if (!BLState->DEBUG_IgnoreWeatherDimmingLeds) + { + for (u32 i = 0; i < State->LedSystem.BuffersCount; i++) { - bool TimelineShouldAdvance = false; - r32 OverrideBrightness = 0.0f; - - time_range RangeIn = {}; - if (SystemTimeIsInTimeRangeList(Context->SystemTime_Current, - LedOnTimes, - LedOnTimesCount, - &RangeIn)) - { - - if (Blumen_TempShouldDimLeds(BLState)) - { - OverrideBrightness = HighTemperatureBrightnessPercent; - } - else - { - OverrideBrightness = FullBrightnessPercent; - } - TimelineShouldAdvance = true; - } - - State->AnimationSystem.TimelineShouldAdvance = TimelineShouldAdvance; - BLState->BrightnessPercent = OverrideBrightness; + led_buffer Buffer = State->LedSystem.Buffers[i]; + for (u32 j = 0; j < Buffer.LedCount; j++) + { + pixel* Color = Buffer.Colors + j; + Color->R = Color->R * BLState->BrightnessPercent; + Color->G = Color->G * BLState->BrightnessPercent; + Color->B = Color->B * BLState->BrightnessPercent; + } } - - // Dim the leds based on temp data - if (!BLState->DEBUG_IgnoreWeatherDimmingLeds) + } + + // Send Status Packet + { + system_time LastSendTime = BLState->LastStatusUpdateTime; + r64 NanosSinceLastSend = ((r64)Context->SystemTime_Current.NanosSinceEpoch - (r64)LastSendTime.NanosSinceEpoch); + r64 SecondsSinceLastSend = NanosSinceLastSend * NanosToSeconds; + if (SecondsSinceLastSend >= STATUS_PACKET_FREQ_SECONDS) { - for (u32 i = 0; i < State->LedSystem.BuffersCount; i++) - { - led_buffer Buffer = State->LedSystem.Buffers[i]; - for (u32 j = 0; j < Buffer.LedCount; j++) - { - pixel* Color = Buffer.Colors + j; - Color->R = Color->R * BLState->BrightnessPercent; - Color->G = Color->G * BLState->BrightnessPercent; - Color->B = Color->B * BLState->BrightnessPercent; - } - } + BLState->LastStatusUpdateTime = Context->SystemTime_Current; + Log_Message(GlobalLogBuffer, "Attempting to Send Lumenarium Status\n"); + + blumen_packet Packet = {}; + Packet.Type = PacketType_LumenariumStatus; + Packet.StatusPacket.NextMotorEventType = 0; + Packet.StatusPacket.NextEventTime = 0; + + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); + if (ActiveAnim) + { + CopyMemoryTo(ActiveAnim->Name.Str, Packet.StatusPacket.AnimFileName, + Min(ActiveAnim->Name.Length, 32)); + Packet.StatusPacket.AnimFileName[ActiveAnim->Name.Length] = 0; + } + + gs_data Msg = StructToData(&Packet, blumen_packet); + MessageQueue_Write(&BLState->OutgoingMsgQueue, Msg); + + // there's no new information here, but by updating the log here, + // we're updating it at some infrequent but regular period that isnt + // every single frame + BLState->ShouldUpdateLog = true; } - - // Send Status Packet - { - system_time LastSendTime = BLState->LastStatusUpdateTime; - r64 NanosSinceLastSend = ((r64)Context->SystemTime_Current.NanosSinceEpoch - (r64)LastSendTime.NanosSinceEpoch); - r64 SecondsSinceLastSend = NanosSinceLastSend * NanosToSeconds; - if (SecondsSinceLastSend >= STATUS_PACKET_FREQ_SECONDS) - { - BLState->LastStatusUpdateTime = Context->SystemTime_Current; - Log_Message(GlobalLogBuffer, "Attempting to Send Lumenarium Status\n"); - - blumen_packet Packet = {}; - Packet.Type = PacketType_LumenariumStatus; - Packet.StatusPacket.NextMotorEventType = 0; - Packet.StatusPacket.NextEventTime = 0; - - animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); - if (ActiveAnim) - { - CopyMemoryTo(ActiveAnim->Name.Str, Packet.StatusPacket.AnimFileName, - Min(ActiveAnim->Name.Length, 32)); - Packet.StatusPacket.AnimFileName[ActiveAnim->Name.Length] = 0; - } - - gs_data Msg = StructToData(&Packet, blumen_packet); - MessageQueue_Write(&BLState->OutgoingMsgQueue, Msg); - - // there's no new information here, but by updating the log here, - // we're updating it at some infrequent but regular period that isnt - // every single frame - BLState->ShouldUpdateLog = true; - } - } - - BlumenLumen_UpdateLog(State, BLState, *Context); + } + + BlumenLumen_UpdateLog(State, BLState, *Context); } US_CUSTOM_DEBUG_UI(BlumenLumen_DebugUI) { - blumen_lumen_state* BLState = (blumen_lumen_state*)UserData.Memory; - ui_interface* I = &State->Interface; - - ui_BeginRow(I, BlumenDebug_Count); - for (u32 i = 0; i < BlumenDebug_Count; i++) + blumen_lumen_state* BLState = (blumen_lumen_state*)UserData.Memory; + ui_interface* I = &State->Interface; + + ui_BeginRow(I, BlumenDebug_Count); + for (u32 i = 0; i < BlumenDebug_Count; i++) + { + if (ui_Button(I, MakeString(BlDebugUiModeStrings[i]))) { - if (ui_Button(I, MakeString(BlDebugUiModeStrings[i]))) + BLState->DebugMode = (bl_debug_ui_mode)i; + } + } + ui_EndRow(I); + + switch (BLState->DebugMode) + { + case BlumenDebug_Motors: + { + motor_packet PendingPacket = BLState->DEBUG_PendingMotorPacket; + + BLState->IgnoreTimeOfDay_MotorState = ui_ToggleText(I, MakeString("Motors Ignore Time Limit"), BLState->IgnoreTimeOfDay_MotorState); + + for (u32 MotorIndex = 0; MotorIndex < BL_FLOWER_COUNT; MotorIndex++) + { + gs_string Label = PushStringF(State->Transient, 32, "Motor %d", MotorIndex); + ui_BeginRow(I, 5); { - BLState->DebugMode = (bl_debug_ui_mode)i; + ui_Label(I, Label); + + bool IsClosed = PendingPacket.FlowerPositions[MotorIndex] == MotorState_Closed; + if (ui_ToggleText(I, MakeString("Closed (1)"), IsClosed)) + { + PendingPacket.FlowerPositions[MotorIndex] = MotorState_Closed; + } + bool IsHOpen = PendingPacket.FlowerPositions[MotorIndex] == MotorState_HalfOpen; + if (ui_ToggleText(I, MakeString("Half Open (3)"), IsHOpen)) + { + PendingPacket.FlowerPositions[MotorIndex] = MotorState_HalfOpen; + } + bool IsMOpen = PendingPacket.FlowerPositions[MotorIndex] == MotorState_MostlyOpen; + if (ui_ToggleText(I, MakeString("Mostly Open (4)"), IsMOpen)) + { + PendingPacket.FlowerPositions[MotorIndex] = MotorState_MostlyOpen; + } + bool IsOpen = PendingPacket.FlowerPositions[MotorIndex] == MotorState_Open; + if (ui_ToggleText(I, MakeString("Open (2)"), IsOpen)) + { + PendingPacket.FlowerPositions[MotorIndex] = MotorState_Open; + } } - } - ui_EndRow(I); + ui_EndRow(I); + } + BLState->DEBUG_PendingMotorPacket = PendingPacket; + + if (ui_Button(I, MakeString("Send Motor Packet"))) + { + blumen_packet Packet = {}; + Packet.Type = PacketType_MotorState; + Packet.MotorPacket = BLState->DEBUG_PendingMotorPacket; + gs_data Msg = StructToData(&Packet, blumen_packet); + MessageQueue_Write(&BLState->OutgoingMsgQueue, Msg); + DEBUG_SentMotorCommand(Packet.MotorPacket, Context.ThreadContext); + + } + + motor_packet MotorPos = BLState->LastKnownMotorState; + ui_Label(I, MakeString("Current Motor Positions")); + { + for (u32 i = 0; i < BL_FLOWER_COUNT; i++) + { + ui_BeginRow(I, 2); + gs_string MotorStr = PushStringF(State->Transient, 32, + "Motor %d", + i); + ui_Label(I, MotorStr); + + gs_string StateStr = {}; + switch (MotorPos.FlowerPositions[i]) + { + case MotorState_Closed: { + StateStr = MakeString("Closed"); + } break; + case MotorState_HalfOpen: { + StateStr = MakeString("Half Open"); + } break; + case MotorState_MostlyOpen: { + StateStr = MakeString("Mostly Open"); + } break; + case MotorState_Open: { + StateStr = MakeString("Open"); + } break; + + default: + { + StateStr = MakeString("Invalid Value"); + } break; + } + + ui_Label(I, StateStr); + ui_EndRow(I); + } + } + + ui_Label(I, MakeString("Set Internal Motor State:")); + if (ui_Button(I, MakeString("Closed"))) + { + motor_status_packet Motor = {}; + Motor.Pos.FlowerPositions[0] = MotorState_Closed; + Motor.Pos.FlowerPositions[1] = MotorState_Closed; + Motor.Pos.FlowerPositions[2] = MotorState_Closed; + Motor.Temperature = 16; + + BlumenLumen_UpdateMotorState(BLState, Motor, Context); + } + if (ui_Button(I, MakeString("Open"))) + { + motor_status_packet Motor = {}; + Motor.Pos.FlowerPositions[0] = MotorState_Open; + Motor.Pos.FlowerPositions[1] = MotorState_Open; + Motor.Pos.FlowerPositions[2] = MotorState_Open; + Motor.Temperature = 16; + + BlumenLumen_UpdateMotorState(BLState, Motor, Context); + } + } break; - switch (BLState->DebugMode) + case BlumenDebug_Leds: { - case BlumenDebug_Motors: + BLState->DEBUG_IgnoreWeatherDimmingLeds = ui_LabeledToggle(I, MakeString("Ignore Weather Dimming Leds"), BLState->DEBUG_IgnoreWeatherDimmingLeds); + + BLState->IgnoreTimeOfDay_LedDimming = ui_ToggleText(I, MakeString("Leds Ignore Time Limit"), BLState->IgnoreTimeOfDay_LedDimming); + + if (ui_BeginLabeledDropdown(I, MakeString("Phrase"), MakeString(BLState->PendingPhrase.Phrase))) + { + u32 ListCount = BLState->PhraseHueMap.Count; + ui_BeginList(I, MakeString("Phrase List"), 5, ListCount); + for (u32 i = 0; i < ListCount; i++) { - motor_packet PendingPacket = BLState->DEBUG_PendingMotorPacket; - - BLState->IgnoreTimeOfDay_MotorState = ui_ToggleText(I, MakeString("Motors Ignore Time Limit"), BLState->IgnoreTimeOfDay_MotorState); - - for (u32 MotorIndex = 0; MotorIndex < BL_FLOWER_COUNT; MotorIndex++) - { - gs_string Label = PushStringF(State->Transient, 32, "Motor %d", MotorIndex); - ui_BeginRow(I, 5); - { - ui_Label(I, Label); - - bool IsClosed = PendingPacket.FlowerPositions[MotorIndex] == MotorState_Closed; - if (ui_ToggleText(I, MakeString("Closed (1)"), IsClosed)) - { - PendingPacket.FlowerPositions[MotorIndex] = MotorState_Closed; - } - bool IsHOpen = PendingPacket.FlowerPositions[MotorIndex] == MotorState_HalfOpen; - if (ui_ToggleText(I, MakeString("Half Open (3)"), IsHOpen)) - { - PendingPacket.FlowerPositions[MotorIndex] = MotorState_HalfOpen; - } - bool IsMOpen = PendingPacket.FlowerPositions[MotorIndex] == MotorState_MostlyOpen; - if (ui_ToggleText(I, MakeString("Mostly Open (4)"), IsMOpen)) - { - PendingPacket.FlowerPositions[MotorIndex] = MotorState_MostlyOpen; - } - bool IsOpen = PendingPacket.FlowerPositions[MotorIndex] == MotorState_Open; - if (ui_ToggleText(I, MakeString("Open (2)"), IsOpen)) - { - PendingPacket.FlowerPositions[MotorIndex] = MotorState_Open; - } - } - ui_EndRow(I); - } - BLState->DEBUG_PendingMotorPacket = PendingPacket; - - if (ui_Button(I, MakeString("Send Motor Packet"))) - { - blumen_packet Packet = {}; - Packet.Type = PacketType_MotorState; - Packet.MotorPacket = BLState->DEBUG_PendingMotorPacket; - gs_data Msg = StructToData(&Packet, blumen_packet); - MessageQueue_Write(&BLState->OutgoingMsgQueue, Msg); - DEBUG_SentMotorCommand(Packet.MotorPacket, Context.ThreadContext); - - } - - motor_packet MotorPos = BLState->LastKnownMotorState; - ui_Label(I, MakeString("Current Motor Positions")); - { - for (u32 i = 0; i < BL_FLOWER_COUNT; i++) - { - ui_BeginRow(I, 2); - gs_string MotorStr = PushStringF(State->Transient, 32, - "Motor %d", - i); - ui_Label(I, MotorStr); - - gs_string StateStr = {}; - switch (MotorPos.FlowerPositions[i]) - { - case MotorState_Closed: { - StateStr = MakeString("Closed"); - } break; - case MotorState_HalfOpen: { - StateStr = MakeString("Half Open"); - } break; - case MotorState_MostlyOpen: { - StateStr = MakeString("Mostly Open"); - } break; - case MotorState_Open: { - StateStr = MakeString("Open"); - } break; - - default: - { - StateStr = MakeString("Invalid Value"); - } break; - } - - ui_Label(I, StateStr); - ui_EndRow(I); - } - } - - ui_Label(I, MakeString("Set Internal Motor State:")); - if (ui_Button(I, MakeString("Closed"))) - { - motor_status_packet Motor = {}; - Motor.Pos.FlowerPositions[0] = MotorState_Closed; - Motor.Pos.FlowerPositions[1] = MotorState_Closed; - Motor.Pos.FlowerPositions[2] = MotorState_Closed; - Motor.Temperature = 16; - - BlumenLumen_UpdateMotorState(BLState, Motor, Context); - } - if (ui_Button(I, MakeString("Open"))) - { - motor_status_packet Motor = {}; - Motor.Pos.FlowerPositions[0] = MotorState_Open; - Motor.Pos.FlowerPositions[1] = MotorState_Open; - Motor.Pos.FlowerPositions[2] = MotorState_Open; - Motor.Temperature = 16; - - BlumenLumen_UpdateMotorState(BLState, Motor, Context); - } - } break; + gs_string Str = MakeString(BLState->PhraseHueMap.Phrases[i]); + if (ui_Button(I, Str)) + { + BLState->PendingPhrase = PhraseHueMap_Get(BLState->PhraseHueMap, i); + BLState->DebugHue = BLState->PendingPhrase; + } + } + ui_EndList(I); + } + ui_EndLabeledDropdown(I); + if (ui_Button(I, MakeString("Say Phrase"))) + { + gs_string DebugStr = PushString(State->Transient, 256); + BLState->NextHotHue = BLState->PendingPhrase; + BlumenLumen_ApplyNextHotHue(BLState, Context, &DebugStr, State); + } + + ui_Label(I, MakeString("Phrase Constructor")); + BLState->DebugOverrideHue = ui_ToggleText(I, MakeString("Override Hue"), BLState->DebugOverrideHue); + if (BLState->DebugOverrideHue) + { + phrase_hue PHue = BLState->DebugHue; + PHue.Hue0.HSV.x = (r64)ui_LabeledRangeSlider(I, MakeString("Hue0"), (r32)PHue.Hue0.HSV.x, 0, 360); + PHue.Hue1.HSV.x = (r64)ui_LabeledRangeSlider(I, MakeString("Hue1"), (r32)PHue.Hue1.HSV.x, 0, 360); + PHue.Hue2.HSV.x = (r64)ui_LabeledRangeSlider(I, MakeString("Hue2"), (r32)PHue.Hue2.HSV.x, 0, 360); + PHue.Granularity = (u32)ui_LabeledRangeSlider(I, MakeString("Granularity"), (r32)PHue.Granularity, 0, 5); + PHue.Speed = ui_LabeledRangeSlider(I, MakeString("Speed"), PHue.Speed, 0, 4); - case BlumenDebug_Leds: + gs_string PatternOptions[HuePattern_Count] = {}; + PatternOptions[HuePattern_Patchy] = MakeString("patchy"); + PatternOptions[HuePattern_Wavy] = MakeString("wavy"); + + gs_string CPattern = PatternOptions[PHue.Pattern]; + if (ui_BeginLabeledDropdown(I, MakeString("Pattern"), CPattern)) { - BLState->DEBUG_IgnoreWeatherDimmingLeds = ui_LabeledToggle(I, MakeString("Ignore Weather Dimming Leds"), BLState->DEBUG_IgnoreWeatherDimmingLeds); - - BLState->IgnoreTimeOfDay_LedDimming = ui_ToggleText(I, MakeString("Leds Ignore Time Limit"), BLState->IgnoreTimeOfDay_LedDimming); - - if (ui_BeginLabeledDropdown(I, MakeString("Phrase"), MakeString(BLState->PendingPhrase.Phrase))) + for (u32 i = 0; i < HuePattern_Count; i++) + { + if (ui_Button(I, PatternOptions[i])) { - u32 ListCount = BLState->PhraseHueMap.Count; - ui_BeginList(I, MakeString("Phrase List"), 5, ListCount); - for (u32 i = 0; i < ListCount; i++) - { - gs_string Str = MakeString(BLState->PhraseHueMap.Phrases[i]); - if (ui_Button(I, Str)) - { - BLState->PendingPhrase = PhraseHueMap_Get(BLState->PhraseHueMap, i); - BLState->DebugHue = BLState->PendingPhrase; - } - } - ui_EndList(I); + PHue.Pattern = i; } - ui_EndLabeledDropdown(I); - if (ui_Button(I, MakeString("Say Phrase"))) - { - gs_string DebugStr = PushString(State->Transient, 256); - BLState->NextHotHue = BLState->PendingPhrase; - BlumenLumen_ApplyNextHotHue(BLState, Context, &DebugStr, State); - } - - ui_Label(I, MakeString("Phrase Constructor")); - BLState->DebugOverrideHue = ui_ToggleText(I, MakeString("Override Hue"), BLState->DebugOverrideHue); - if (BLState->DebugOverrideHue) - { - phrase_hue PHue = BLState->DebugHue; - PHue.Hue0.HSV.x = (r64)ui_LabeledRangeSlider(I, MakeString("Hue0"), (r32)PHue.Hue0.HSV.x, 0, 360); - PHue.Hue1.HSV.x = (r64)ui_LabeledRangeSlider(I, MakeString("Hue1"), (r32)PHue.Hue1.HSV.x, 0, 360); - PHue.Hue2.HSV.x = (r64)ui_LabeledRangeSlider(I, MakeString("Hue2"), (r32)PHue.Hue2.HSV.x, 0, 360); - PHue.Granularity = (u32)ui_LabeledRangeSlider(I, MakeString("Granularity"), (r32)PHue.Granularity, 0, 5); - PHue.Speed = ui_LabeledRangeSlider(I, MakeString("Speed"), PHue.Speed, 0, 4); - - gs_string PatternOptions[HuePattern_Count] = {}; - PatternOptions[HuePattern_Patchy] = MakeString("patchy"); - PatternOptions[HuePattern_Wavy] = MakeString("wavy"); - - gs_string CPattern = PatternOptions[PHue.Pattern]; - if (ui_BeginLabeledDropdown(I, MakeString("Pattern"), CPattern)) - { - for (u32 i = 0; i < HuePattern_Count; i++) - { - if (ui_Button(I, PatternOptions[i])) - { - PHue.Pattern = i; - } - } - } - ui_EndLabeledDropdown(I); - - - gs_string AddInOptions[AddIn_Count] = {}; - AddInOptions[AddIn_None] = MakeString("NA"); - AddInOptions[AddIn_Waves] = MakeString("waves"); - AddInOptions[AddIn_Rotary] = MakeString("rotary"); - - gs_string CAddIn = AddInOptions[PHue.AddIn]; - if (ui_BeginLabeledDropdown(I, MakeString("Add In"), CAddIn)) - { - for (u32 i = 0; i < AddIn_Count; i++) - { - if (ui_Button(I, AddInOptions[i])) - { - PHue.AddIn = i; - } - } - } - ui_EndLabeledDropdown(I); - BLState->DebugHue = PHue; - } - - - InterfaceAssert(I->PerFrameMemory); - }break; + } + } + ui_EndLabeledDropdown(I); - case BlumenDebug_Awaken: + + gs_string AddInOptions[AddIn_Count] = {}; + AddInOptions[AddIn_None] = MakeString("NA"); + AddInOptions[AddIn_Waves] = MakeString("waves"); + AddInOptions[AddIn_Rotary] = MakeString("rotary"); + + gs_string CAddIn = AddInOptions[PHue.AddIn]; + if (ui_BeginLabeledDropdown(I, MakeString("Add In"), CAddIn)) { - ui_Label(I, MakeString("Step 1:")); - ui_Label(I, MakeString("Leds off, flowers closed")); - if (ui_Button(I, MakeString("Prepare"))) + for (u32 i = 0; i < AddIn_Count; i++) + { + if (ui_Button(I, AddInOptions[i])) { - // motors closed - blumen_packet M = {}; - M.Type = PacketType_MotorState; - M.MotorPacket.FlowerPositions[0] = MotorState_Closed; - M.MotorPacket.FlowerPositions[1] = MotorState_Closed; - M.MotorPacket.FlowerPositions[2] = MotorState_Closed; - gs_data D = StructToData(&M, blumen_packet); - MessageQueue_Write(&BLState->OutgoingMsgQueue, D); - - // animation - State->AnimationSystem.RepeatMode = AnimationRepeat_Single; - AnimationFadeGroup_FadeTo(&State->AnimationSystem.ActiveFadeGroup, - BLState->OffAnimHandle, - VoiceCommandFadeDuration); - - BLState->PatternMode = BlumenPattern_NoControl; - BLState->IgnoreTimeOfDay_LedDimming = true; - BLState->IgnoreTimeOfDay_MotorState = true; + PHue.AddIn = i; } - - ui_Label(I, MakeString("Step 2:")); - if (ui_Button(I, MakeString("Begin Light Show"))) - { - AnimationFadeGroup_FadeTo(&State->AnimationSystem.ActiveFadeGroup, - BLState->AwakenHandle, - VoiceCommandFadeDuration); - } - - ui_Label(I, MakeString("Step 3:")); - if (ui_Button(I, MakeString("Open Flowers"))) - { - // motors closed - blumen_packet M = {}; - M.Type = PacketType_MotorState; - M.MotorPacket.FlowerPositions[0] = MotorState_Open; - M.MotorPacket.FlowerPositions[1] = MotorState_Open; - M.MotorPacket.FlowerPositions[2] = MotorState_Open; - gs_data D = StructToData(&M, blumen_packet); - MessageQueue_Write(&BLState->OutgoingMsgQueue, D); - } - - ui_Label(I, MakeString("Step 4:")); - ui_Label(I, MakeString("Resets Lumenarium")); - if (ui_Button(I, MakeString("Complete"))) - { - BLState->IgnoreTimeOfDay_LedDimming = false; - BLState->IgnoreTimeOfDay_MotorState = false; - BlumenLumen_SetPatternMode(BlumenPattern_Standard, GlobalAnimTransitionSpeed, &State->AnimationSystem, - BLState); - } - }break; + } + } + ui_EndLabeledDropdown(I); + BLState->DebugHue = PHue; + } + + + InterfaceAssert(I->PerFrameMemory); + }break; + + case BlumenDebug_Awaken: + { + ui_Label(I, MakeString("Step 1:")); + ui_Label(I, MakeString("Leds off, flowers closed")); + if (ui_Button(I, MakeString("Prepare"))) + { + // motors closed + blumen_packet M = {}; + M.Type = PacketType_MotorState; + M.MotorPacket.FlowerPositions[0] = MotorState_Closed; + M.MotorPacket.FlowerPositions[1] = MotorState_Closed; + M.MotorPacket.FlowerPositions[2] = MotorState_Closed; + gs_data D = StructToData(&M, blumen_packet); + MessageQueue_Write(&BLState->OutgoingMsgQueue, D); - InvalidDefaultCase; - } + // animation + State->AnimationSystem.RepeatMode = AnimationRepeat_Single; + AnimationFadeGroup_FadeTo(&State->AnimationSystem.ActiveFadeGroup, + BLState->OffAnimHandle, + VoiceCommandFadeDuration); + + BLState->PatternMode = BlumenPattern_NoControl; + BLState->IgnoreTimeOfDay_LedDimming = true; + BLState->IgnoreTimeOfDay_MotorState = true; + } + + ui_Label(I, MakeString("Step 2:")); + if (ui_Button(I, MakeString("Begin Light Show"))) + { + AnimationFadeGroup_FadeTo(&State->AnimationSystem.ActiveFadeGroup, + BLState->AwakenHandle, + VoiceCommandFadeDuration); + } + + ui_Label(I, MakeString("Step 3:")); + if (ui_Button(I, MakeString("Open Flowers"))) + { + // motors closed + blumen_packet M = {}; + M.Type = PacketType_MotorState; + M.MotorPacket.FlowerPositions[0] = MotorState_Open; + M.MotorPacket.FlowerPositions[1] = MotorState_Open; + M.MotorPacket.FlowerPositions[2] = MotorState_Open; + gs_data D = StructToData(&M, blumen_packet); + MessageQueue_Write(&BLState->OutgoingMsgQueue, D); + } + + ui_Label(I, MakeString("Step 4:")); + ui_Label(I, MakeString("Resets Lumenarium")); + if (ui_Button(I, MakeString("Complete"))) + { + BLState->IgnoreTimeOfDay_LedDimming = false; + BLState->IgnoreTimeOfDay_MotorState = false; + BlumenLumen_SetPatternMode(BlumenPattern_Standard, GlobalAnimTransitionSpeed, &State->AnimationSystem, + BLState); + } + }break; + + InvalidDefaultCase; + } } US_CUSTOM_CLEANUP(BlumenLumen_CustomCleanup) { - blumen_lumen_state* BLState = (blumen_lumen_state*)UserData.Memory; - BLState->Running = false; + blumen_lumen_state* BLState = (blumen_lumen_state*)UserData.Memory; + BLState->Running = false; } internal user_space_desc BlumenLumen_UserSpaceCreate() { - user_space_desc Result = {}; - Result.LoadPatterns = BlumenLumen_LoadPatterns; - Result.CustomInit = BlumenLumen_CustomInit; - Result.CustomUpdate = BlumenLumen_CustomUpdate; - Result.CustomDebugUI = BlumenLumen_DebugUI; - Result.CustomCleanup = BlumenLumen_CustomCleanup; - return Result; + user_space_desc Result = {}; + Result.LoadPatterns = BlumenLumen_LoadPatterns; + Result.CustomInit = BlumenLumen_CustomInit; + Result.CustomUpdate = BlumenLumen_CustomUpdate; + Result.CustomDebugUI = BlumenLumen_DebugUI; + Result.CustomCleanup = BlumenLumen_CustomCleanup; + return Result; } #define BLUMEN_LUMEN_CPP diff --git a/src/app/ss_blumen_lumen/message_queue.cpp b/src/app/ss_blumen_lumen/message_queue.cpp index a132d64..4d4211d 100644 --- a/src/app/ss_blumen_lumen/message_queue.cpp +++ b/src/app/ss_blumen_lumen/message_queue.cpp @@ -2,79 +2,82 @@ internal void MessageQueue_Init(blumen_network_msg_queue* Queue, gs_memory_arena* Arena) { - for (u32 i = 0; i < BLUMEN_MESSAGE_QUEUE_COUNT; i++) - { - Queue->Buffers[i] = PushSizeToData(Arena, DEFAULT_QUEUE_ENTRY_SIZE); - } + gs_data MessageQueueData = PushSize(Arena, DEFAULT_QUEUE_ENTRY_SIZE * BLUMEN_MESSAGE_QUEUE_COUNT); + gs_memory_cursor C = MemoryCursorCreateFromData(MessageQueueData); + + for (u32 i = 0; i < BLUMEN_MESSAGE_QUEUE_COUNT; i++) + { + Queue->Buffers[i] = MemoryCursorPushSize(&C, DEFAULT_QUEUE_ENTRY_SIZE); + } } internal bool MessageQueue_CanWrite(blumen_network_msg_queue Queue) { - bool Result = ((Queue.WriteHead >= Queue.ReadHead) || - (Queue.WriteHead < Queue.ReadHead)); - return Result; + bool Result = ((Queue.WriteHead >= Queue.ReadHead) || + (Queue.WriteHead < Queue.ReadHead)); + return Result; } internal bool MessageQueue_Write(blumen_network_msg_queue* Queue, gs_data Msg) { - Assert(Msg.Size <= DEFAULT_QUEUE_ENTRY_SIZE); - - u32 Index = Queue->WriteHead; - Assert(Index >= 0 && - Index < BLUMEN_MESSAGE_QUEUE_COUNT); - - gs_data* Dest = Queue->Buffers + Index; - CopyMemoryTo(Msg.Memory, Dest->Memory, Msg.Size); - Dest->Size = Msg.Size; - - // NOTE(pjs): We increment write head at the end of writing so that - // a reader thread doesn't pull the message off before we've finished - // filling it out - Queue->WriteHead = (Queue->WriteHead + 1) % BLUMEN_MESSAGE_QUEUE_COUNT; - return true; + Assert(Msg.Size <= DEFAULT_QUEUE_ENTRY_SIZE); + + u32 Index = Queue->WriteHead; + Assert(Index >= 0 && + Index < BLUMEN_MESSAGE_QUEUE_COUNT); + + gs_data* Dest = Queue->Buffers + Index; + CopyMemoryTo(Msg.Memory, Dest->Memory, Msg.Size); + Dest->Size = Msg.Size; + + // NOTE(pjs): We increment write head at the end of writing so that + // a reader thread doesn't pull the message off before we've finished + // filling it out + Queue->WriteHead = (Queue->WriteHead + 1) % BLUMEN_MESSAGE_QUEUE_COUNT; + return true; } internal bool MessageQueue_CanRead(blumen_network_msg_queue Queue) { - bool Result = (Queue.ReadHead != Queue.WriteHead); - return Result; + bool Result = (Queue.ReadHead != Queue.WriteHead); + return Result; } internal gs_data MessageQueue_Peek(blumen_network_msg_queue* Queue) { - gs_data Result = {}; - u32 ReadIndex = Queue->ReadHead; - if (ReadIndex >= BLUMEN_MESSAGE_QUEUE_COUNT) - { - ReadIndex = 0; - } - Result = Queue->Buffers[ReadIndex]; - return Result; + gs_data Result = {}; + u32 ReadIndex = Queue->ReadHead; + if (ReadIndex >= BLUMEN_MESSAGE_QUEUE_COUNT) + { + ReadIndex = 0; + } + Result = Queue->Buffers[ReadIndex]; + return Result; } internal gs_data MessageQueue_Read(blumen_network_msg_queue* Queue) { - gs_data Result = {}; - u32 ReadIndex = Queue->ReadHead++; - if (ReadIndex >= BLUMEN_MESSAGE_QUEUE_COUNT) - { - Queue->ReadHead = 0; - ReadIndex = 0; - } - Result = Queue->Buffers[ReadIndex]; - return Result; + gs_data Result = {}; + u32 ReadIndex = Queue->ReadHead++; + if (ReadIndex >= BLUMEN_MESSAGE_QUEUE_COUNT) + { + Queue->ReadHead = 0; + ReadIndex = 0; + } + Result = Queue->Buffers[ReadIndex]; + return Result; } internal void MessageQueue_Clear(blumen_network_msg_queue* Queue) { - while (MessageQueue_CanRead(*Queue)) - { - MessageQueue_Read(Queue); - } + while (MessageQueue_CanRead(*Queue)) + { + MessageQueue_Read(Queue); + } } diff --git a/src/gs_libs/gs_input.h b/src/gs_libs/gs_input.h index 4a696b3..f0c1c79 100644 --- a/src/gs_libs/gs_input.h +++ b/src/gs_libs/gs_input.h @@ -6,86 +6,86 @@ #ifndef GS_INPUT_H enum key_code { - KeyCode_Invalid, - - KeyCode_Esc, - - KeyCode_Space, - KeyCode_Tab, - KeyCode_CapsLock, - KeyCode_LeftShift, KeyCode_RightShift, - KeyCode_LeftCtrl, KeyCode_RightCtrl, - KeyCode_Fn, - KeyCode_Alt, - KeyCode_PageUp, KeyCode_PageDown, - KeyCode_Backspace, KeyCode_Delete, - KeyCode_Enter, - - // Function Keys - KeyCode_F0, KeyCode_F1, KeyCode_F2, KeyCode_F3, KeyCode_F4, KeyCode_F5, KeyCode_F6, KeyCode_F7, - KeyCode_F8, KeyCode_F9, KeyCode_F10, KeyCode_F11, KeyCode_F12, - - // Letters - KeyCode_a, KeyCode_b, KeyCode_c, KeyCode_d, KeyCode_e, KeyCode_f, KeyCode_g, KeyCode_h, - KeyCode_i, KeyCode_j, KeyCode_k, KeyCode_l, KeyCode_m, KeyCode_n, KeyCode_o, KeyCode_p, - KeyCode_q, KeyCode_r, KeyCode_s, KeyCode_t, KeyCode_u, KeyCode_v, KeyCode_w, KeyCode_x, - KeyCode_y, KeyCode_z, - - KeyCode_A, KeyCode_B, KeyCode_C, KeyCode_D, KeyCode_E, KeyCode_F, KeyCode_G, KeyCode_H, - KeyCode_I, KeyCode_J, KeyCode_K, KeyCode_L, KeyCode_M, KeyCode_N, KeyCode_O, KeyCode_P, - KeyCode_Q, KeyCode_R, KeyCode_S, KeyCode_T, KeyCode_U, KeyCode_V, KeyCode_W, KeyCode_X, - KeyCode_Y, KeyCode_Z, - - // Numbers - KeyCode_0, KeyCode_1, KeyCode_2, KeyCode_3, KeyCode_4, KeyCode_5, KeyCode_6, KeyCode_7, - KeyCode_8, KeyCode_9, - - KeyCode_Num0, KeyCode_Num1, KeyCode_Num2, KeyCode_Num3, KeyCode_Num4, KeyCode_Num5, - KeyCode_Num6, KeyCode_Num7, KeyCode_Num8, KeyCode_Num9, - - // Symbols - KeyCode_Bang, KeyCode_At, KeyCode_Pound, KeyCode_Dollar, KeyCode_Percent, KeyCode_Carrot, - KeyCode_Ampersand, KeyCode_Star, KeyCode_LeftParen, KeyCode_RightParen, KeyCode_Minus, KeyCode_Plus, - KeyCode_Equals, KeyCode_Underscore, KeyCode_LeftBrace, KeyCode_RightBrace, KeyCode_LeftBracket, - KeyCode_RightBracket, KeyCode_Colon, KeyCode_SemiColon, KeyCode_SingleQuote, KeyCode_DoubleQuote, - KeyCode_ForwardSlash, KeyCode_Backslash, KeyCode_Pipe, KeyCode_Comma, KeyCode_Period, - KeyCode_QuestionMark, KeyCode_LessThan, KeyCode_GreaterThan, KeyCode_Tilde, KeyCode_BackQuote, - - // Arrows - KeyCode_UpArrow, - KeyCode_DownArrow, - KeyCode_LeftArrow, - KeyCode_RightArrow, - - // Mouse - // NOTE(Peter): Including this here so we can utilize the same KeyDown, KeyUp etc. functions - KeyCode_MouseLeftButton, - KeyCode_MouseMiddleButton, - KeyCode_MouseRightButton, - - KeyCode_Count, + KeyCode_Invalid, + + KeyCode_Esc, + + KeyCode_Space, + KeyCode_Tab, + KeyCode_CapsLock, + KeyCode_LeftShift, KeyCode_RightShift, + KeyCode_LeftCtrl, KeyCode_RightCtrl, + KeyCode_Fn, + KeyCode_Alt, + KeyCode_PageUp, KeyCode_PageDown, + KeyCode_Backspace, KeyCode_Delete, + KeyCode_Enter, + + // Function Keys + KeyCode_F0, KeyCode_F1, KeyCode_F2, KeyCode_F3, KeyCode_F4, KeyCode_F5, KeyCode_F6, KeyCode_F7, + KeyCode_F8, KeyCode_F9, KeyCode_F10, KeyCode_F11, KeyCode_F12, + + // Letters + KeyCode_a, KeyCode_b, KeyCode_c, KeyCode_d, KeyCode_e, KeyCode_f, KeyCode_g, KeyCode_h, + KeyCode_i, KeyCode_j, KeyCode_k, KeyCode_l, KeyCode_m, KeyCode_n, KeyCode_o, KeyCode_p, + KeyCode_q, KeyCode_r, KeyCode_s, KeyCode_t, KeyCode_u, KeyCode_v, KeyCode_w, KeyCode_x, + KeyCode_y, KeyCode_z, + + KeyCode_A, KeyCode_B, KeyCode_C, KeyCode_D, KeyCode_E, KeyCode_F, KeyCode_G, KeyCode_H, + KeyCode_I, KeyCode_J, KeyCode_K, KeyCode_L, KeyCode_M, KeyCode_N, KeyCode_O, KeyCode_P, + KeyCode_Q, KeyCode_R, KeyCode_S, KeyCode_T, KeyCode_U, KeyCode_V, KeyCode_W, KeyCode_X, + KeyCode_Y, KeyCode_Z, + + // Numbers + KeyCode_0, KeyCode_1, KeyCode_2, KeyCode_3, KeyCode_4, KeyCode_5, KeyCode_6, KeyCode_7, + KeyCode_8, KeyCode_9, + + KeyCode_Num0, KeyCode_Num1, KeyCode_Num2, KeyCode_Num3, KeyCode_Num4, KeyCode_Num5, + KeyCode_Num6, KeyCode_Num7, KeyCode_Num8, KeyCode_Num9, + + // Symbols + KeyCode_Bang, KeyCode_At, KeyCode_Pound, KeyCode_Dollar, KeyCode_Percent, KeyCode_Carrot, + KeyCode_Ampersand, KeyCode_Star, KeyCode_LeftParen, KeyCode_RightParen, KeyCode_Minus, KeyCode_Plus, + KeyCode_Equals, KeyCode_Underscore, KeyCode_LeftBrace, KeyCode_RightBrace, KeyCode_LeftBracket, + KeyCode_RightBracket, KeyCode_Colon, KeyCode_SemiColon, KeyCode_SingleQuote, KeyCode_DoubleQuote, + KeyCode_ForwardSlash, KeyCode_Backslash, KeyCode_Pipe, KeyCode_Comma, KeyCode_Period, + KeyCode_QuestionMark, KeyCode_LessThan, KeyCode_GreaterThan, KeyCode_Tilde, KeyCode_BackQuote, + + // Arrows + KeyCode_UpArrow, + KeyCode_DownArrow, + KeyCode_LeftArrow, + KeyCode_RightArrow, + + // Mouse + // NOTE(Peter): Including this here so we can utilize the same KeyDown, KeyUp etc. functions + KeyCode_MouseLeftButton, + KeyCode_MouseMiddleButton, + KeyCode_MouseRightButton, + + KeyCode_Count, }; internal char CharacterFromKeyCode (key_code Code) { - char Result = 0; + char Result = 0; + + switch (Code) + { + case KeyCode_Space: { Result = ' '; }break; + case KeyCode_Tab: { Result = '\t'; }break; - switch (Code) - { - case KeyCode_Space: { Result = ' '; }break; - case KeyCode_Tab: { Result = '\t'; }break; - - // Letters - case KeyCode_a: { Result = 'a'; }break; - case KeyCode_b: { Result = 'b'; }break; - case KeyCode_c: { Result = 'c'; }break; - case KeyCode_d: { Result = 'd'; }break; - case KeyCode_e: { Result = 'e'; }break; + // Letters + case KeyCode_a: { Result = 'a'; }break; + case KeyCode_b: { Result = 'b'; }break; + case KeyCode_c: { Result = 'c'; }break; + case KeyCode_d: { Result = 'd'; }break; + case KeyCode_e: { Result = 'e'; }break; case KeyCode_f: { Result = 'f'; }break; case KeyCode_g: { Result = 'g'; }break; case KeyCode_h: { Result = 'h'; }break; - case KeyCode_i: { Result = 'i'; }break; + case KeyCode_i: { Result = 'i'; }break; case KeyCode_j: { Result = 'j'; }break; case KeyCode_k: { Result = 'k'; }break; case KeyCode_l: { Result = 'l'; }break; @@ -93,7 +93,7 @@ CharacterFromKeyCode (key_code Code) case KeyCode_n: { Result = 'n'; }break; case KeyCode_o: { Result = 'o'; }break; case KeyCode_p: { Result = 'p'; }break; - case KeyCode_q: { Result = 'q'; }break; + case KeyCode_q: { Result = 'q'; }break; case KeyCode_r: { Result = 'r'; }break; case KeyCode_s: { Result = 's'; }break; case KeyCode_t: { Result = 't'; }break; @@ -101,10 +101,10 @@ CharacterFromKeyCode (key_code Code) case KeyCode_v: { Result = 'v'; }break; case KeyCode_w: { Result = 'w'; }break; case KeyCode_x: { Result = 'x'; }break; - case KeyCode_y: { Result = 'y'; }break; + case KeyCode_y: { Result = 'y'; }break; case KeyCode_z: { Result = 'z'; }break; - - case KeyCode_A: { Result = 'A'; }break; + + case KeyCode_A: { Result = 'A'; }break; case KeyCode_B: { Result = 'B'; }break; case KeyCode_C: { Result = 'C'; }break; case KeyCode_D: { Result = 'D'; }break; @@ -112,7 +112,7 @@ CharacterFromKeyCode (key_code Code) case KeyCode_F: { Result = 'F'; }break; case KeyCode_G: { Result = 'G'; }break; case KeyCode_H: { Result = 'H'; }break; - case KeyCode_I: { Result = 'I'; }break; + case KeyCode_I: { Result = 'I'; }break; case KeyCode_J: { Result = 'J'; }break; case KeyCode_K: { Result = 'K'; }break; case KeyCode_L: { Result = 'L'; }break; @@ -120,7 +120,7 @@ CharacterFromKeyCode (key_code Code) case KeyCode_N: { Result = 'N'; }break; case KeyCode_O: { Result = 'O'; }break; case KeyCode_P: { Result = 'P'; }break; - case KeyCode_Q: { Result = 'Q'; }break; + case KeyCode_Q: { Result = 'Q'; }break; case KeyCode_R: { Result = 'R'; }break; case KeyCode_S: { Result = 'S'; }break; case KeyCode_T: { Result = 'T'; }break; @@ -128,11 +128,11 @@ CharacterFromKeyCode (key_code Code) case KeyCode_V: { Result = 'V'; }break; case KeyCode_W: { Result = 'W'; }break; case KeyCode_X: { Result = 'X'; }break; - case KeyCode_Y: { Result = 'Y'; }break; + case KeyCode_Y: { Result = 'Y'; }break; case KeyCode_Z: { Result = 'Z'; }break; - - // Numbers - case KeyCode_0: { Result = '0'; }break; + + // Numbers + case KeyCode_0: { Result = '0'; }break; case KeyCode_1: { Result = '1'; }break; case KeyCode_2: { Result = '2'; }break; case KeyCode_3: { Result = '3'; }break; @@ -140,88 +140,88 @@ CharacterFromKeyCode (key_code Code) case KeyCode_5: { Result = '5'; }break; case KeyCode_6: { Result = '6'; }break; case KeyCode_7: { Result = '7'; }break; - case KeyCode_8: { Result = '8'; }break; + case KeyCode_8: { Result = '8'; }break; case KeyCode_9: { Result = '9'; }break; - - case KeyCode_Num0: { Result = '0'; }break; + + case KeyCode_Num0: { Result = '0'; }break; case KeyCode_Num1: { Result = '1'; }break; case KeyCode_Num2: { Result = '2'; }break; case KeyCode_Num3: { Result = '3'; }break; case KeyCode_Num4: { Result = '4'; }break; case KeyCode_Num5: { Result = '5'; }break; - case KeyCode_Num6: { Result = '6'; }break; + case KeyCode_Num6: { Result = '6'; }break; case KeyCode_Num7: { Result = '7'; }break; case KeyCode_Num8: { Result = '8'; }break; case KeyCode_Num9: { Result = '9'; }break; - - // Symbols - case KeyCode_Bang: { Result = '!'; }break; + + // Symbols + case KeyCode_Bang: { Result = '!'; }break; case KeyCode_At: { Result = '@'; }break; case KeyCode_Pound: { Result = '#'; }break; case KeyCode_Dollar: { Result = '$'; }break; case KeyCode_Percent: { Result = '%'; }break; case KeyCode_Carrot: { Result = '^'; }break; - case KeyCode_Ampersand: { Result = '&'; }break; + case KeyCode_Ampersand: { Result = '&'; }break; case KeyCode_Star: { Result = '*'; }break; case KeyCode_LeftParen: { Result = '('; }break; case KeyCode_RightParen: { Result = ')'; }break; case KeyCode_Minus: { Result = '-'; }break; case KeyCode_Plus: { Result = '+'; }break; - case KeyCode_Equals: { Result = '='; }break; + case KeyCode_Equals: { Result = '='; }break; case KeyCode_Underscore: { Result = '_'; }break; case KeyCode_LeftBrace: { Result = '['; }break; case KeyCode_RightBrace: { Result = ']'; }break; case KeyCode_LeftBracket: { Result = '{'; }break; - case KeyCode_RightBracket: { Result = '}'; }break; + case KeyCode_RightBracket: { Result = '}'; }break; case KeyCode_Colon: { Result = ':'; }break; case KeyCode_SemiColon: { Result = ';'; }break; case KeyCode_SingleQuote: { Result = '\''; }break; case KeyCode_DoubleQuote: { Result = '"'; }break; - case KeyCode_ForwardSlash: { Result = '/'; }break; + case KeyCode_ForwardSlash: { Result = '/'; }break; case KeyCode_Backslash: { Result = '\\'; }break; case KeyCode_Pipe: { Result = '|'; }break; case KeyCode_Comma: { Result = ','; }break; case KeyCode_Period: { Result = '.'; }break; - case KeyCode_QuestionMark: { Result = '?'; }break; + case KeyCode_QuestionMark: { Result = '?'; }break; case KeyCode_LessThan: { Result = '<'; }break; case KeyCode_GreaterThan: { Result = '>'; }break; case KeyCode_Tilde: { Result = '~'; }break; case KeyCode_BackQuote: { Result = '`'; }break; - } - - Assert(Result != 0); - return Result; + } + + Assert(Result != 0); + return Result; } enum modifier_flags { - Modifier_Shift = 1 << 0, - Modifier_Ctrl = 1 << 1, - Modifier_Alt = 1 << 2, - Modifier_Sys = 1 << 3, // NOTE(Peter): this is the windows key + Modifier_Shift = 1 << 0, + Modifier_Ctrl = 1 << 1, + Modifier_Alt = 1 << 2, + Modifier_Sys = 1 << 3, // NOTE(Peter): this is the windows key }; #define INPUT_FRAME_STRING_LENGTH 32 struct input_frame { - b32 KeysDown[(int)KeyCode_Count]; - s32 StringInputUsed; - char StringInput[INPUT_FRAME_STRING_LENGTH]; - s32 MouseX, MouseY, MouseScroll; + b32 KeysDown[(int)KeyCode_Count]; + s32 StringInputUsed; + char StringInput[INPUT_FRAME_STRING_LENGTH]; + s32 MouseX, MouseY, MouseScroll; }; struct input { - input_frame Frames[2]; - input_frame* New; - input_frame* Old; - s32 MouseDownX, MouseDownY; + input_frame Frames[2]; + input_frame* New; + input_frame* Old; + s32 MouseDownX, MouseDownY; }; enum key_state_flags { - KeyState_WasDown = 1 << 0, - KeyState_IsDown = 1 << 1, + KeyState_WasDown = 1 << 0, + KeyState_IsDown = 1 << 1, }; #define KeyWasDown(event) ((event & KeyState_WasDown) > 0) @@ -234,75 +234,75 @@ enum key_state_flags struct input_entry { - key_code Key; - b32 State; - b32 Modifiers; + key_code Key; + b32 State; + b32 Modifiers; }; struct input_queue { - s32 QueueSize; - s32 QueueUsed; - input_entry* Entries; + s32 QueueSize; + s32 QueueUsed; + input_entry* Entries; }; enum cursor_type { - CursorType_Arrow, - CursorType_Pointer, - CursorType_Loading, - CursorType_HArrows, - CursorType_VArrows, - CursorType_DTopLeftArrows, - CursorType_DTopRightArrows, - CursorType_Count, + CursorType_Arrow, + CursorType_Pointer, + CursorType_Loading, + CursorType_HArrows, + CursorType_VArrows, + CursorType_DTopLeftArrows, + CursorType_DTopRightArrows, + CursorType_Count, }; struct mouse_state { - s32 Scroll; - - v2 Pos; - v2 OldPos; - v2 DeltaPos; - v2 DownPos; - - b32 LeftButtonState; - b32 MiddleButtonState; - b32 RightButtonState; - - - - cursor_type CursorType; + s32 Scroll; + + v2 Pos; + v2 OldPos; + v2 DeltaPos; + v2 DownPos; + + b32 LeftButtonState; + b32 MiddleButtonState; + b32 RightButtonState; + + + + cursor_type CursorType; }; internal input_queue InputQueue_Create (u8* Memory, s32 MemorySize) { - input_queue Result = {}; - s32 EntriesCount = MemorySize / sizeof(input_entry); - Result.QueueSize = EntriesCount; - Result.QueueUsed = 0; - Result.Entries = (input_entry*)Memory; - return Result; + input_queue Result = {}; + s32 EntriesCount = MemorySize / sizeof(input_entry); + Result.QueueSize = EntriesCount; + Result.QueueUsed = 0; + Result.Entries = (input_entry*)Memory; + return Result; } internal input_queue InputQueue_Create(gs_memory_arena* Arena, u32 CountMax) { - input_queue Result = {0}; - if (CountMax > 0) - { - s32 Size = sizeof(input_entry) * 32; - u8* Memory = PushSize(Arena, Size); - Result = InputQueue_Create(Memory, Size); - } - return Result; + input_queue Result = {0}; + if (CountMax > 0) + { + s32 Size = sizeof(input_entry) * 32; + u8* Memory = PushSize(Arena, Size).Memory; + Result = InputQueue_Create(Memory, Size); + } + return Result; } internal void ResetInputQueue (input_queue* Queue) { - Queue->QueueUsed = 0; + Queue->QueueUsed = 0; } internal void InitializeInput (input* Input); @@ -311,360 +311,360 @@ internal void SwapInputBuffers (input* Input); internal void InitializeInput (input* Input) { - *(Input) = {}; - Input->New = &Input->Frames[0]; - Input->Old = &Input->Frames[1]; + *(Input) = {}; + Input->New = &Input->Frames[0]; + Input->Old = &Input->Frames[1]; } internal void SwapInputBuffers (input* Input) { - input_frame* NowOld = Input->New; - Input->New = Input->Old; - Input->Old = NowOld; - - for (s32 Key = 0; Key < KeyCode_Count; Key++) { Input->New->KeysDown[Key] = Input->Old->KeysDown[Key]; } - Input->New->StringInputUsed = 0; + input_frame* NowOld = Input->New; + Input->New = Input->Old; + Input->Old = NowOld; + + for (s32 Key = 0; Key < KeyCode_Count; Key++) { Input->New->KeysDown[Key] = Input->Old->KeysDown[Key]; } + Input->New->StringInputUsed = 0; } internal b32 KeyDown (input Input, key_code Key) { - return Input.New->KeysDown[Key]; + return Input.New->KeysDown[Key]; } internal b32 KeyTransitionedDown (input Input, key_code Key) { - return Input.New->KeysDown[Key] && !Input.Old->KeysDown[Key]; + return Input.New->KeysDown[Key] && !Input.Old->KeysDown[Key]; } internal b32 KeyTransitionedUp (input Input, key_code Key) { - return !Input.New->KeysDown[Key] && Input.Old->KeysDown[Key]; + return !Input.New->KeysDown[Key] && Input.Old->KeysDown[Key]; } internal void AddInputEventEntry (input_queue* Queue, key_code Key, b32 WasDown, b32 IsDown, b32 ShiftDown, b32 AltDown, b32 CtrlDown, b32 SysDown) { - Assert(Queue->QueueUsed < Queue->QueueSize); - - input_entry* Entry = Queue->Entries + Queue->QueueUsed++; - Entry->Key = Key; - - Entry->State = (key_state_flags)0; - if (WasDown) { Entry->State |= KeyState_WasDown; } - if (IsDown) { Entry->State |= KeyState_IsDown; } - - Entry->Modifiers = 0; - if (ShiftDown) { Entry->Modifiers |= Modifier_Shift; } - if (CtrlDown) { Entry->Modifiers |= Modifier_Ctrl; } - if (AltDown) { Entry->Modifiers |= Modifier_Alt; } - if (SysDown) { Entry->Modifiers |= Modifier_Sys; } + Assert(Queue->QueueUsed < Queue->QueueSize); + + input_entry* Entry = Queue->Entries + Queue->QueueUsed++; + Entry->Key = Key; + + Entry->State = (key_state_flags)0; + if (WasDown) { Entry->State |= KeyState_WasDown; } + if (IsDown) { Entry->State |= KeyState_IsDown; } + + Entry->Modifiers = 0; + if (ShiftDown) { Entry->Modifiers |= Modifier_Shift; } + if (CtrlDown) { Entry->Modifiers |= Modifier_Ctrl; } + if (AltDown) { Entry->Modifiers |= Modifier_Alt; } + if (SysDown) { Entry->Modifiers |= Modifier_Sys; } } internal b32 KeyTransitionedDown (input_entry Entry) { - return (!KeyWasDown(Entry.State) && KeyIsDown(Entry.State)); + return (!KeyWasDown(Entry.State) && KeyIsDown(Entry.State)); } internal b32 KeyTransitionedUp (input_entry Entry) { - return (KeyWasDown(Entry.State) && !KeyIsDown(Entry.State)); + return (KeyWasDown(Entry.State) && !KeyIsDown(Entry.State)); } internal b32 KeyHeldDown (input_entry Entry) { - return (KeyWasDown(Entry.State) && KeyIsDown(Entry.State)); + return (KeyWasDown(Entry.State) && KeyIsDown(Entry.State)); } internal b32 MouseButtonTransitionedDown (b32 MouseButtonState) { - return (!KeyWasDown(MouseButtonState) && KeyIsDown(MouseButtonState)); + return (!KeyWasDown(MouseButtonState) && KeyIsDown(MouseButtonState)); } internal b32 MouseButtonTransitionedUp (b32 MouseButtonState) { - return (KeyWasDown(MouseButtonState) && !KeyIsDown(MouseButtonState)); + return (KeyWasDown(MouseButtonState) && !KeyIsDown(MouseButtonState)); } internal b32 MouseButtonHeldDown (b32 MouseButtonState) { - b32 WasDown = KeyWasDown(MouseButtonState); - b32 IsDown = KeyIsDown(MouseButtonState); - return (WasDown && IsDown); + b32 WasDown = KeyWasDown(MouseButtonState); + b32 IsDown = KeyIsDown(MouseButtonState); + return (WasDown && IsDown); } inline b32 GetMouseButtonStateAdvanced (b32 ButtonState) { - b32 Result = ButtonState; - if (ButtonState & KeyState_WasDown && - !((ButtonState & KeyState_IsDown) > 0)) - { - Result= 0; - } - else if (ButtonState & KeyState_IsDown) - { - Result |= KeyState_WasDown; - } - return Result; + b32 Result = ButtonState; + if (ButtonState & KeyState_WasDown && + !((ButtonState & KeyState_IsDown) > 0)) + { + Result= 0; + } + else if (ButtonState & KeyState_IsDown) + { + Result |= KeyState_WasDown; + } + return Result; } internal char KeyCodeToChar(key_code Code) { - char Result = 0; + char Result = 0; + + switch (Code) + { + case KeyCode_Space: { Result = ' '; } break; + case KeyCode_Tab: { Result = '\t'; } break; + case KeyCode_Enter: { Result = '\n'; } break; + case KeyCode_Backspace: { Result = '\b'; } break; - switch (Code) - { - case KeyCode_Space: { Result = ' '; } break; - case KeyCode_Tab: { Result = '\t'; } break; - case KeyCode_Enter: { Result = '\n'; } break; - case KeyCode_Backspace: { Result = '\b'; } break; - - case KeyCode_a: { Result = 'a'; } break; - case KeyCode_b: { Result = 'b'; } break; - case KeyCode_c: { Result = 'c'; } break; - case KeyCode_d: { Result = 'd'; } break; - case KeyCode_e: { Result = 'e'; } break; - case KeyCode_f: { Result = 'f'; } break; - case KeyCode_g: { Result = 'g'; } break; - case KeyCode_h: { Result = 'h'; } break; - case KeyCode_i: { Result = 'i'; } break; - case KeyCode_j: { Result = 'j'; } break; - case KeyCode_k: { Result = 'k'; } break; - case KeyCode_l: { Result = 'l'; } break; - case KeyCode_m: { Result = 'm'; } break; - case KeyCode_n: { Result = 'n'; } break; - case KeyCode_o: { Result = 'o'; } break; - case KeyCode_p: { Result = 'p'; } break; - case KeyCode_q: { Result = 'q'; } break; - case KeyCode_r: { Result = 'r'; } break; - case KeyCode_s: { Result = 's'; } break; - case KeyCode_t: { Result = 't'; } break; - case KeyCode_u: { Result = 'u'; } break; - case KeyCode_v: { Result = 'v'; } break; - case KeyCode_w: { Result = 'w'; } break; - case KeyCode_x: { Result = 'x'; } break; - case KeyCode_y: { Result = 'y'; } break; - case KeyCode_z: { Result = 'z'; } break; - case KeyCode_A: { Result = 'A'; } break; - case KeyCode_B: { Result = 'B'; } break; - case KeyCode_C: { Result = 'C'; } break; - case KeyCode_D: { Result = 'D'; } break; - case KeyCode_E: { Result = 'E'; } break; - case KeyCode_F: { Result = 'F'; } break; - case KeyCode_G: { Result = 'G'; } break; - case KeyCode_H: { Result = 'H'; } break; - case KeyCode_I: { Result = 'I'; } break; - case KeyCode_J: { Result = 'J'; } break; - case KeyCode_K: { Result = 'K'; } break; - case KeyCode_L: { Result = 'L'; } break; - case KeyCode_M: { Result = 'M'; } break; - case KeyCode_N: { Result = 'N'; } break; - case KeyCode_O: { Result = 'O'; } break; - case KeyCode_P: { Result = 'P'; } break; - case KeyCode_Q: { Result = 'Q'; } break; - case KeyCode_R: { Result = 'R'; } break; - case KeyCode_S: { Result = 'S'; } break; - case KeyCode_T: { Result = 'T'; } break; - case KeyCode_U: { Result = 'U'; } break; - case KeyCode_V: { Result = 'V'; } break; - case KeyCode_W: { Result = 'W'; } break; - case KeyCode_X: { Result = 'X'; } break; - case KeyCode_Y: { Result = 'Y'; } break; - case KeyCode_Z: { Result = 'Z'; } break; - - case KeyCode_Num0: - case KeyCode_0: { Result = '0'; } break; - case KeyCode_Num1: - case KeyCode_1: { Result = '1'; } break; - case KeyCode_Num2: - case KeyCode_2: { Result = '2'; } break; - case KeyCode_Num3: - case KeyCode_3: { Result = '3'; } break; - case KeyCode_Num4: - case KeyCode_4: { Result = '4'; } break; - case KeyCode_Num5: - case KeyCode_5: { Result = '5'; } break; - case KeyCode_Num6: - case KeyCode_6: { Result = '6'; } break; - case KeyCode_Num7: - case KeyCode_7: { Result = '7'; } break; - case KeyCode_Num8: - case KeyCode_8: { Result = '8'; } break; - case KeyCode_Num9: - case KeyCode_9: { Result = '9'; } break; - - case KeyCode_Bang: { Result = '!'; } break; - case KeyCode_At: { Result = '@'; } break; - case KeyCode_Pound: { Result = '#'; } break; - case KeyCode_Dollar: { Result = '$'; } break; - case KeyCode_Percent: { Result = '%'; } break; - case KeyCode_Carrot: { Result = '^'; } break; - case KeyCode_Ampersand: { Result = '&'; } break; - case KeyCode_Star: { Result = '*'; } break; - case KeyCode_LeftParen: { Result = '('; } break; - case KeyCode_RightParen: { Result = ')'; } break; - case KeyCode_Minus: { Result = '-'; } break; - case KeyCode_Plus: { Result = '+'; } break; - case KeyCode_Equals: { Result = '='; } break; - case KeyCode_Underscore: { Result = '_'; } break; - case KeyCode_LeftBrace: { Result = '{'; } break; - case KeyCode_RightBrace: { Result = '}'; } break; - case KeyCode_LeftBracket: { Result = '['; } break; - case KeyCode_RightBracket: { Result = ']'; } break; - case KeyCode_Colon: { Result = ':'; } break; - case KeyCode_SemiColon: { Result = ';'; } break; - case KeyCode_SingleQuote: { Result = '\''; } break; - case KeyCode_DoubleQuote: { Result = '"'; } break; - case KeyCode_ForwardSlash: { Result = '/'; } break; - case KeyCode_Backslash: { Result = '\\'; } break; - case KeyCode_Pipe: { Result = '|'; } break; - case KeyCode_Comma: { Result = ','; } break; - case KeyCode_Period: { Result = '.'; } break; - case KeyCode_QuestionMark: { Result = '?'; } break; - case KeyCode_LessThan: { Result = '<'; } break; - case KeyCode_GreaterThan: { Result = '>'; } break; - case KeyCode_Tilde: { Result = '~'; } break; - case KeyCode_BackQuote: { Result = '`'; } break; - - default: { Result = 0; } break; - } + case KeyCode_a: { Result = 'a'; } break; + case KeyCode_b: { Result = 'b'; } break; + case KeyCode_c: { Result = 'c'; } break; + case KeyCode_d: { Result = 'd'; } break; + case KeyCode_e: { Result = 'e'; } break; + case KeyCode_f: { Result = 'f'; } break; + case KeyCode_g: { Result = 'g'; } break; + case KeyCode_h: { Result = 'h'; } break; + case KeyCode_i: { Result = 'i'; } break; + case KeyCode_j: { Result = 'j'; } break; + case KeyCode_k: { Result = 'k'; } break; + case KeyCode_l: { Result = 'l'; } break; + case KeyCode_m: { Result = 'm'; } break; + case KeyCode_n: { Result = 'n'; } break; + case KeyCode_o: { Result = 'o'; } break; + case KeyCode_p: { Result = 'p'; } break; + case KeyCode_q: { Result = 'q'; } break; + case KeyCode_r: { Result = 'r'; } break; + case KeyCode_s: { Result = 's'; } break; + case KeyCode_t: { Result = 't'; } break; + case KeyCode_u: { Result = 'u'; } break; + case KeyCode_v: { Result = 'v'; } break; + case KeyCode_w: { Result = 'w'; } break; + case KeyCode_x: { Result = 'x'; } break; + case KeyCode_y: { Result = 'y'; } break; + case KeyCode_z: { Result = 'z'; } break; + case KeyCode_A: { Result = 'A'; } break; + case KeyCode_B: { Result = 'B'; } break; + case KeyCode_C: { Result = 'C'; } break; + case KeyCode_D: { Result = 'D'; } break; + case KeyCode_E: { Result = 'E'; } break; + case KeyCode_F: { Result = 'F'; } break; + case KeyCode_G: { Result = 'G'; } break; + case KeyCode_H: { Result = 'H'; } break; + case KeyCode_I: { Result = 'I'; } break; + case KeyCode_J: { Result = 'J'; } break; + case KeyCode_K: { Result = 'K'; } break; + case KeyCode_L: { Result = 'L'; } break; + case KeyCode_M: { Result = 'M'; } break; + case KeyCode_N: { Result = 'N'; } break; + case KeyCode_O: { Result = 'O'; } break; + case KeyCode_P: { Result = 'P'; } break; + case KeyCode_Q: { Result = 'Q'; } break; + case KeyCode_R: { Result = 'R'; } break; + case KeyCode_S: { Result = 'S'; } break; + case KeyCode_T: { Result = 'T'; } break; + case KeyCode_U: { Result = 'U'; } break; + case KeyCode_V: { Result = 'V'; } break; + case KeyCode_W: { Result = 'W'; } break; + case KeyCode_X: { Result = 'X'; } break; + case KeyCode_Y: { Result = 'Y'; } break; + case KeyCode_Z: { Result = 'Z'; } break; - return Result; + case KeyCode_Num0: + case KeyCode_0: { Result = '0'; } break; + case KeyCode_Num1: + case KeyCode_1: { Result = '1'; } break; + case KeyCode_Num2: + case KeyCode_2: { Result = '2'; } break; + case KeyCode_Num3: + case KeyCode_3: { Result = '3'; } break; + case KeyCode_Num4: + case KeyCode_4: { Result = '4'; } break; + case KeyCode_Num5: + case KeyCode_5: { Result = '5'; } break; + case KeyCode_Num6: + case KeyCode_6: { Result = '6'; } break; + case KeyCode_Num7: + case KeyCode_7: { Result = '7'; } break; + case KeyCode_Num8: + case KeyCode_8: { Result = '8'; } break; + case KeyCode_Num9: + case KeyCode_9: { Result = '9'; } break; + + case KeyCode_Bang: { Result = '!'; } break; + case KeyCode_At: { Result = '@'; } break; + case KeyCode_Pound: { Result = '#'; } break; + case KeyCode_Dollar: { Result = '$'; } break; + case KeyCode_Percent: { Result = '%'; } break; + case KeyCode_Carrot: { Result = '^'; } break; + case KeyCode_Ampersand: { Result = '&'; } break; + case KeyCode_Star: { Result = '*'; } break; + case KeyCode_LeftParen: { Result = '('; } break; + case KeyCode_RightParen: { Result = ')'; } break; + case KeyCode_Minus: { Result = '-'; } break; + case KeyCode_Plus: { Result = '+'; } break; + case KeyCode_Equals: { Result = '='; } break; + case KeyCode_Underscore: { Result = '_'; } break; + case KeyCode_LeftBrace: { Result = '{'; } break; + case KeyCode_RightBrace: { Result = '}'; } break; + case KeyCode_LeftBracket: { Result = '['; } break; + case KeyCode_RightBracket: { Result = ']'; } break; + case KeyCode_Colon: { Result = ':'; } break; + case KeyCode_SemiColon: { Result = ';'; } break; + case KeyCode_SingleQuote: { Result = '\''; } break; + case KeyCode_DoubleQuote: { Result = '"'; } break; + case KeyCode_ForwardSlash: { Result = '/'; } break; + case KeyCode_Backslash: { Result = '\\'; } break; + case KeyCode_Pipe: { Result = '|'; } break; + case KeyCode_Comma: { Result = ','; } break; + case KeyCode_Period: { Result = '.'; } break; + case KeyCode_QuestionMark: { Result = '?'; } break; + case KeyCode_LessThan: { Result = '<'; } break; + case KeyCode_GreaterThan: { Result = '>'; } break; + case KeyCode_Tilde: { Result = '~'; } break; + case KeyCode_BackQuote: { Result = '`'; } break; + + default: { Result = 0; } break; + } + + return Result; } internal bool KeyCodeHasChar(key_code Code) { - bool Result = KeyCodeToChar(Code) != 0; - return Result; + bool Result = KeyCodeToChar(Code) != 0; + return Result; } internal key_code CharToKeyCode(char C) { - key_code Result = KeyCode_Invalid; + key_code Result = KeyCode_Invalid; + + switch (C) + { + case ' ': { Result = KeyCode_Space; } break; + case '\t': { Result = KeyCode_Tab; } break; + case '\n': { Result = KeyCode_Enter; } break; + case '\b': { Result = KeyCode_Backspace; } break; - switch (C) - { - case ' ': { Result = KeyCode_Space; } break; - case '\t': { Result = KeyCode_Tab; } break; - case '\n': { Result = KeyCode_Enter; } break; - case '\b': { Result = KeyCode_Backspace; } break; - - case 'a': { Result = KeyCode_a; } break; - case 'b': { Result = KeyCode_b; } break; - case 'c': { Result = KeyCode_c; } break; - case 'd': { Result = KeyCode_d; } break; - case 'e': { Result = KeyCode_e; } break; - case 'f': { Result = KeyCode_f; } break; - case 'g': { Result = KeyCode_g; } break; - case 'h': { Result = KeyCode_h; } break; - case 'i': { Result = KeyCode_i; } break; - case 'j': { Result = KeyCode_j; } break; - case 'k': { Result = KeyCode_k; } break; - case 'l': { Result = KeyCode_l; } break; - case 'm': { Result = KeyCode_m; } break; - case 'n': { Result = KeyCode_n; } break; - case 'o': { Result = KeyCode_o; } break; - case 'p': { Result = KeyCode_p; } break; - case 'q': { Result = KeyCode_q; } break; - case 'r': { Result = KeyCode_r; } break; - case 's': { Result = KeyCode_s; } break; - case 't': { Result = KeyCode_t; } break; - case 'u': { Result = KeyCode_u; } break; - case 'v': { Result = KeyCode_v; } break; - case 'w': { Result = KeyCode_w; } break; - case 'x': { Result = KeyCode_x; } break; - case 'y': { Result = KeyCode_y; } break; - case 'z': { Result = KeyCode_z; } break; - case 'A': { Result = KeyCode_A; } break; - case 'B': { Result = KeyCode_B; } break; - case 'C': { Result = KeyCode_C; } break; - case 'D': { Result = KeyCode_D; } break; - case 'E': { Result = KeyCode_E; } break; - case 'F': { Result = KeyCode_F; } break; - case 'G': { Result = KeyCode_G; } break; - case 'H': { Result = KeyCode_H; } break; - case 'I': { Result = KeyCode_I; } break; - case 'J': { Result = KeyCode_J; } break; - case 'K': { Result = KeyCode_K; } break; - case 'L': { Result = KeyCode_L; } break; - case 'M': { Result = KeyCode_M; } break; - case 'N': { Result = KeyCode_N; } break; - case 'O': { Result = KeyCode_O; } break; - case 'P': { Result = KeyCode_P; } break; - case 'Q': { Result = KeyCode_Q; } break; - case 'R': { Result = KeyCode_R; } break; - case 'S': { Result = KeyCode_S; } break; - case 'T': { Result = KeyCode_T; } break; - case 'U': { Result = KeyCode_U; } break; - case 'V': { Result = KeyCode_V; } break; - case 'W': { Result = KeyCode_W; } break; - case 'X': { Result = KeyCode_X; } break; - case 'Y': { Result = KeyCode_Y; } break; - case 'Z': { Result = KeyCode_Z; } break; - - case '0': { Result = KeyCode_0; } break; - case '1': { Result = KeyCode_1; } break; - case '2': { Result = KeyCode_2; } break; - case '3': { Result = KeyCode_3; } break; - case '4': { Result = KeyCode_4; } break; - case '5': { Result = KeyCode_5; } break; - case '6': { Result = KeyCode_6; } break; - case '7': { Result = KeyCode_7; } break; - case '8': { Result = KeyCode_8; } break; - case '9': { Result = KeyCode_9; } break; - - case '!': { Result = KeyCode_Bang; } break; - case '@': { Result = KeyCode_At; } break; - case '#': { Result = KeyCode_Pound; } break; - case '$': { Result = KeyCode_Dollar; } break; - case '%': { Result = KeyCode_Percent; } break; - case '^': { Result = KeyCode_Carrot; } break; - case '&': { Result = KeyCode_Ampersand; } break; - case '*': { Result = KeyCode_Star; } break; - case '(': { Result = KeyCode_LeftParen; } break; - case ')': { Result = KeyCode_RightParen; } break; - case '-': { Result = KeyCode_Minus; } break; - case '+': { Result = KeyCode_Plus; } break; - case '=': { Result = KeyCode_Equals; } break; - case '_': { Result = KeyCode_Underscore; } break; - case '{': { Result = KeyCode_LeftBrace; } break; - case '}': { Result = KeyCode_RightBrace; } break; - case '[': { Result = KeyCode_LeftBracket; } break; - case ']': { Result = KeyCode_RightBracket; } break; - case ':': { Result = KeyCode_Colon; } break; - case ';': { Result = KeyCode_SemiColon; } break; - case '\'': { Result = KeyCode_SingleQuote; } break; - case '"': { Result = KeyCode_DoubleQuote; } break; - case '/': { Result = KeyCode_ForwardSlash; } break; - case '\\': { Result = KeyCode_Backslash; } break; - case '|': { Result = KeyCode_Pipe; } break; - case ',': { Result = KeyCode_Comma; } break; - case '.': { Result = KeyCode_Period; } break; - case '?': { Result = KeyCode_QuestionMark; } break; - case '<': { Result = KeyCode_LessThan; } break; - case '>': { Result = KeyCode_GreaterThan; } break; - case '~': { Result = KeyCode_Tilde; } break; - case '`': { Result = KeyCode_BackQuote; } break; - - default: { Result = KeyCode_Invalid; } break; - } + case 'a': { Result = KeyCode_a; } break; + case 'b': { Result = KeyCode_b; } break; + case 'c': { Result = KeyCode_c; } break; + case 'd': { Result = KeyCode_d; } break; + case 'e': { Result = KeyCode_e; } break; + case 'f': { Result = KeyCode_f; } break; + case 'g': { Result = KeyCode_g; } break; + case 'h': { Result = KeyCode_h; } break; + case 'i': { Result = KeyCode_i; } break; + case 'j': { Result = KeyCode_j; } break; + case 'k': { Result = KeyCode_k; } break; + case 'l': { Result = KeyCode_l; } break; + case 'm': { Result = KeyCode_m; } break; + case 'n': { Result = KeyCode_n; } break; + case 'o': { Result = KeyCode_o; } break; + case 'p': { Result = KeyCode_p; } break; + case 'q': { Result = KeyCode_q; } break; + case 'r': { Result = KeyCode_r; } break; + case 's': { Result = KeyCode_s; } break; + case 't': { Result = KeyCode_t; } break; + case 'u': { Result = KeyCode_u; } break; + case 'v': { Result = KeyCode_v; } break; + case 'w': { Result = KeyCode_w; } break; + case 'x': { Result = KeyCode_x; } break; + case 'y': { Result = KeyCode_y; } break; + case 'z': { Result = KeyCode_z; } break; + case 'A': { Result = KeyCode_A; } break; + case 'B': { Result = KeyCode_B; } break; + case 'C': { Result = KeyCode_C; } break; + case 'D': { Result = KeyCode_D; } break; + case 'E': { Result = KeyCode_E; } break; + case 'F': { Result = KeyCode_F; } break; + case 'G': { Result = KeyCode_G; } break; + case 'H': { Result = KeyCode_H; } break; + case 'I': { Result = KeyCode_I; } break; + case 'J': { Result = KeyCode_J; } break; + case 'K': { Result = KeyCode_K; } break; + case 'L': { Result = KeyCode_L; } break; + case 'M': { Result = KeyCode_M; } break; + case 'N': { Result = KeyCode_N; } break; + case 'O': { Result = KeyCode_O; } break; + case 'P': { Result = KeyCode_P; } break; + case 'Q': { Result = KeyCode_Q; } break; + case 'R': { Result = KeyCode_R; } break; + case 'S': { Result = KeyCode_S; } break; + case 'T': { Result = KeyCode_T; } break; + case 'U': { Result = KeyCode_U; } break; + case 'V': { Result = KeyCode_V; } break; + case 'W': { Result = KeyCode_W; } break; + case 'X': { Result = KeyCode_X; } break; + case 'Y': { Result = KeyCode_Y; } break; + case 'Z': { Result = KeyCode_Z; } break; - return Result; + case '0': { Result = KeyCode_0; } break; + case '1': { Result = KeyCode_1; } break; + case '2': { Result = KeyCode_2; } break; + case '3': { Result = KeyCode_3; } break; + case '4': { Result = KeyCode_4; } break; + case '5': { Result = KeyCode_5; } break; + case '6': { Result = KeyCode_6; } break; + case '7': { Result = KeyCode_7; } break; + case '8': { Result = KeyCode_8; } break; + case '9': { Result = KeyCode_9; } break; + + case '!': { Result = KeyCode_Bang; } break; + case '@': { Result = KeyCode_At; } break; + case '#': { Result = KeyCode_Pound; } break; + case '$': { Result = KeyCode_Dollar; } break; + case '%': { Result = KeyCode_Percent; } break; + case '^': { Result = KeyCode_Carrot; } break; + case '&': { Result = KeyCode_Ampersand; } break; + case '*': { Result = KeyCode_Star; } break; + case '(': { Result = KeyCode_LeftParen; } break; + case ')': { Result = KeyCode_RightParen; } break; + case '-': { Result = KeyCode_Minus; } break; + case '+': { Result = KeyCode_Plus; } break; + case '=': { Result = KeyCode_Equals; } break; + case '_': { Result = KeyCode_Underscore; } break; + case '{': { Result = KeyCode_LeftBrace; } break; + case '}': { Result = KeyCode_RightBrace; } break; + case '[': { Result = KeyCode_LeftBracket; } break; + case ']': { Result = KeyCode_RightBracket; } break; + case ':': { Result = KeyCode_Colon; } break; + case ';': { Result = KeyCode_SemiColon; } break; + case '\'': { Result = KeyCode_SingleQuote; } break; + case '"': { Result = KeyCode_DoubleQuote; } break; + case '/': { Result = KeyCode_ForwardSlash; } break; + case '\\': { Result = KeyCode_Backslash; } break; + case '|': { Result = KeyCode_Pipe; } break; + case ',': { Result = KeyCode_Comma; } break; + case '.': { Result = KeyCode_Period; } break; + case '?': { Result = KeyCode_QuestionMark; } break; + case '<': { Result = KeyCode_LessThan; } break; + case '>': { Result = KeyCode_GreaterThan; } break; + case '~': { Result = KeyCode_Tilde; } break; + case '`': { Result = KeyCode_BackQuote; } break; + + default: { Result = KeyCode_Invalid; } break; + } + + return Result; } #define GS_INPUT_H diff --git a/src/gs_libs/gs_memory.h b/src/gs_libs/gs_memory.h new file mode 100644 index 0000000..d72ac56 --- /dev/null +++ b/src/gs_libs/gs_memory.h @@ -0,0 +1,528 @@ +/* date = May 10th 2021 10:19 pm */ + +#ifndef GS_MEMORY_H +#define GS_MEMORY_H + +#if !defined(Assert) +# define Assert(c) +#endif + +#if !defined(InvalidCodePath) +# define InvalidCodePath +#endif + +#if !defined(GS_MEMORY_PROFILE_FUNC) +# define GS_MEMORY_PROFILE_FUNC +#endif + +#define MemoryClearArray(b,t,s) MemoryClear((u8*)(b), sizeof(t) * (s)) +internal void +MemoryClear(u8* Base, u64 Size) +{ + for (u64 i = 0; i < Size; i++) Base[i] = 0; +} + +#ifndef DEBUG_LOC + +typedef struct gs_debug_loc +{ + char* File; + char* Function; + u32 Line; +} gs_debug_loc; + +# define DEBUG_LOC gs_debug_loc{ (char*)__FILE__, (char*)__FUNCTION__, __LINE__ } + +#endif +// +// Debug Info +// + +typedef struct gs_debug_memory_allocation +{ + gs_debug_loc Loc; + u64 ArenaHash; + u64 Size; + + struct gs_debug_memory_allocation* Next; +} gs_debug_memory_allocation; + +typedef struct gs_debug_arena_info +{ + char* ArenaName; + u64 AllocationsCount; + u64 TotalSize; +} gs_debug_arena_info; + +typedef struct gs_debug_allocations_list +{ + gs_debug_memory_allocation* Root; + gs_debug_memory_allocation* Head; + u64 AllocationsSizeTotal; + u64 AllocationsCount; + + u64 ArenaHashesCount; + u64* ArenaHashes; + gs_debug_arena_info* ArenaInfos; +} gs_debug_allocations_list; + +// +// Allocator +// + +#define PLATFORM_ALLOC(name) void* name(u64 Size, u64* ResultSize, u8* UserData) +typedef PLATFORM_ALLOC(platform_alloc); + +#define PLATFORM_FREE(name) void name(void* Base, u64 Size, u8* UserData) +typedef PLATFORM_FREE(platform_free); + +typedef struct gs_allocator +{ + platform_alloc* PAlloc; + platform_free* PFree; + u8* UserData; + + gs_debug_allocations_list* DEBUGAllocList; +} gs_allocator; + +PLATFORM_ALLOC(AllocNoOp) +{ + GS_MEMORY_PROFILE_FUNC; + if (ResultSize) *ResultSize = 0; + return 0; +} + +PLATFORM_FREE(FreeNoOp) +{ + GS_MEMORY_PROFILE_FUNC; + return; +} + +internal u64 +GSMemoryHash(char* Str, u64 Len) +{ + u64 Hash = 5381; + for (u32 i = 0; i < Len; i++) + { + Hash = ((Hash << 5) + Hash) + Str[i]; + } + return Hash; +} + +#define Alloc(a,s,an) Alloc_((a),(s),DEBUG_LOC, (char*)(an)).Memory +#define AllocStruct(a,t,an) (t*)Alloc_((a),sizeof(t),DEBUG_LOC, (char*)(an)).Memory +#define AllocArray(a,t,c,an) (t*)Alloc_((a),sizeof(t)*(c),DEBUG_LOC, (char*)(an)).Memory +#define AllocData(a,s,an) Alloc_((a),(s),DEBUG_LOC, (char*)(an)) + +internal gs_data +Alloc_(gs_allocator A, u64 Size, gs_debug_loc Loc, char* ArenaName) +{ + GS_MEMORY_PROFILE_FUNC; + + gs_data Result = {}; + Result.Memory = (u8*)A.PAlloc(Size, &Result.Size, A.UserData); + + // Debug + { + u64 ArenaHash = GSMemoryHash(ArenaName, CStringLength(ArenaName)); + + gs_debug_memory_allocation* Allocation = (gs_debug_memory_allocation*)A.PAlloc(sizeof(gs_debug_memory_allocation*), 0, A.UserData); + Allocation->Loc = Loc; + Allocation->Size = Size; + Allocation->ArenaHash = ArenaHash; + SLLPushOrInit(A.DEBUGAllocList->Root, A.DEBUGAllocList->Head, Allocation); + + A.DEBUGAllocList->AllocationsSizeTotal += Size; + A.DEBUGAllocList->AllocationsCount += 1; + + u64 ArenaStartIndex = ArenaHash % A.DEBUGAllocList->ArenaHashesCount; + u64 ArenaIndex = ArenaStartIndex; + while (A.DEBUGAllocList->ArenaHashes[ArenaIndex] != 0 && + A.DEBUGAllocList->ArenaHashes[ArenaIndex] != ArenaHash) + { + ArenaIndex = (ArenaIndex + 1) % A.DEBUGAllocList->ArenaHashesCount; + + // NOTE(PS): this means you've created enough arena's to fill up every + // slot in the arena hash table. Go increase the size of of DEBUG_ALLOCATOR_ARENA_MAX + Assert(ArenaIndex != ArenaStartIndex); + } + + if (A.DEBUGAllocList->ArenaHashes[ArenaIndex] == 0) + { + A.DEBUGAllocList->ArenaHashes[ArenaIndex] = ArenaHash; + + gs_debug_arena_info AI = {}; + AI.ArenaName = ArenaName; + A.DEBUGAllocList->ArenaInfos[ArenaIndex] = AI; + } + + A.DEBUGAllocList->ArenaInfos[ArenaIndex].AllocationsCount += 1; + A.DEBUGAllocList->ArenaInfos[ArenaIndex].TotalSize += Size; + } + + + + return Result; +} + +#define AllocString(a,s,l) AllocString_((a), (s), DEBUG_LOC, (l)) +internal gs_string +AllocString_(gs_allocator A, u64 Size, gs_debug_loc Loc, char* LocString) +{ + gs_string Result = {}; + Result.Str = (char*)Alloc_(A, sizeof(char)*Size, Loc, LocString).Memory; + Result.Length = 0; + Result.Size = Size; + return Result; +} + +#define Free(a,b,s) Free_((a),(b),(s),DEBUG_LOC) +#define FreeStruct(a,b,t) Free_((a),(u8*)(b),sizeof(t),DEBUG_LOC) +#define FreeArray(a,b,t,c) Free_((a),(u8*)(b),sizeof(t)*(c),DEBUG_LOC) +internal void +Free_(gs_allocator A, u8* Base, u64 Size, gs_debug_loc Loc) +{ + GS_MEMORY_PROFILE_FUNC; + + A.PFree(Base, Size, A.UserData); +} + +// NOTE(PS): cast function and struct pointers to proper data types +// for convenience +#define AllocatorCreate(a,f,u) AllocatorCreate_((platform_alloc*)(a),(platform_free*)(f),(u8*)(u)) +internal gs_allocator +AllocatorCreate_(platform_alloc* PAlloc, platform_free* PFree, u8* UserData) +{ + gs_allocator Result = {}; + Result.PAlloc = PAlloc; + Result.PFree = PFree; + Result.UserData = UserData; + + if (!PAlloc) Result.PAlloc = AllocNoOp; + if (!PFree) Result.PFree = FreeNoOp; + + // @DEBUG +#define DEBUG_ALLOCATOR_ARENA_MAX 256 + Result.DEBUGAllocList = (gs_debug_allocations_list*)PAlloc(sizeof(gs_debug_allocations_list*), 0, UserData); + + Result.DEBUGAllocList->ArenaHashesCount = DEBUG_ALLOCATOR_ARENA_MAX; + Result.DEBUGAllocList->ArenaHashes = (u64*)PAlloc(sizeof(u64*) * DEBUG_ALLOCATOR_ARENA_MAX, 0, UserData); + Result.DEBUGAllocList->ArenaInfos = (gs_debug_arena_info*)PAlloc(sizeof(gs_debug_arena_info) * DEBUG_ALLOCATOR_ARENA_MAX, 0, UserData); + return Result; +} + +// +// Memory Cursor +// + +typedef struct gs_memory_cursor +{ + gs_data Data; + u64 Position; +} gs_memory_cursor; + +internal gs_memory_cursor +MemoryCursorCreate(u8* Base, u64 Size) +{ + GS_MEMORY_PROFILE_FUNC; + + gs_memory_cursor Result = {}; + Result.Data.Memory = Base; + Result.Data.Size = Size; + Result.Position = 0; + + return Result; +} +internal gs_memory_cursor +MemoryCursorCreateFromData(gs_data Data) +{ + GS_MEMORY_PROFILE_FUNC; + return MemoryCursorCreate(Data.Memory, Data.Size); +} + +internal u64 +MemoryCursorRoomLeft(gs_memory_cursor Cursor) +{ + GS_MEMORY_PROFILE_FUNC; + + u64 Result = 0; + if (Cursor.Data.Size >= Cursor.Position) + { + Result = Cursor.Data.Size - Cursor.Position; + } + return Result; +} + +internal bool +MemoryCursorHasRoom(gs_memory_cursor Cursor) +{ + GS_MEMORY_PROFILE_FUNC; + + u64 RoomLeft = MemoryCursorRoomLeft(Cursor); + bool Result = RoomLeft > 0; + return Result; +} + +internal bool +MemoryCursorCanPush(gs_memory_cursor Cursor, u64 Size) +{ + GS_MEMORY_PROFILE_FUNC; + + u64 RoomLeft = MemoryCursorRoomLeft(Cursor); + bool Result = RoomLeft >= Size; + return Result; +} + +#define MemoryCursorPushSize(c,s) MemoryCursorPushSize_((c),(s)) +#define MemoryCursorPushStruct(c,s) (s*)MemoryCursorPushSize_((c),sizeof(s)).Memory +#define MemoryCursorPushArray(c,s,l) (s*)MemoryCursorPushSize_((c),sizeof(s)*(l)).Memory +internal gs_data +MemoryCursorPushSize_(gs_memory_cursor* C, u64 Size) +{ + GS_MEMORY_PROFILE_FUNC; + + gs_data Result = {0}; + if (MemoryCursorCanPush(*C, Size)) + { + Result.Memory = C->Data.Memory + C->Position; + Result.Size = Size, + C->Position += Size; + } + return Result; +} + +internal gs_data +MemoryCursorAlign(gs_memory_cursor* C, u64 Alignment) +{ + GS_MEMORY_PROFILE_FUNC; + + u64 Position = RoundUpTo64(C->Position, Alignment); + if (Position > C->Data.Size) + { + Position = C->Data.Size; + } + u64 AlignmentDist = Position - C->Position; + gs_data Result = MemoryCursorPushSize_(C, AlignmentDist); + return Result; +} + +#define MemoryCursorWriteValue(c,t,v) *PushStructOnCursor((c),(t)) = (v) +internal void +MemoryCursorWriteBuffer(gs_memory_cursor* C, gs_data Buffer) +{ + GS_MEMORY_PROFILE_FUNC; + + gs_data Dest = MemoryCursorPushSize(C, Buffer.Size); + if (Dest.Size == Buffer.Size) + { + CopyMemoryTo(Buffer.Memory, Dest.Memory, Buffer.Size); + } +} + +internal void +MemoryCursorPopSize(gs_memory_cursor* C, u64 Size) +{ + GS_MEMORY_PROFILE_FUNC; + + u64 SizeToPop = Size; + if (SizeToPop > C->Position) + { + SizeToPop = C->Position; + } + + C->Position -= SizeToPop; +} + +internal void +MemoryCursorReset(gs_memory_cursor* C) +{ + GS_MEMORY_PROFILE_FUNC; + + C->Position = 0; +} + +// +// Memory Arena +// + +typedef struct gs_memory_cursor_sll +{ + gs_memory_cursor Cursor; + struct gs_memory_cursor_sll* Next; +} gs_memory_cursor_sll; + +typedef struct gs_memory_arena +{ + u64 ChunkSize; + u64 Alignment; + char* ArenaName; + + gs_memory_cursor_sll* CursorsRoot; + gs_memory_cursor_sll* CursorsHead; + + struct gs_memory_arena* Parent; + gs_allocator Allocator; + u8* UserData; + // TODO: some sort of GrowArena function +} gs_memory_arena; + +internal gs_memory_arena +MemoryArenaCreate(u64 ChunkSize, u64 Alignment, gs_allocator Allocator, gs_memory_arena* Parent, u8* UserData, char* Name) +{ + GS_MEMORY_PROFILE_FUNC; + + gs_memory_arena Result = {}; + Result.ChunkSize = ChunkSize; + Result.Alignment = Alignment; + Result.Allocator = Allocator; + Result.Parent = Parent; + Result.UserData = UserData; + Result.ArenaName = Name; + + return Result; +} + +internal gs_data PushSize_(gs_memory_arena* Arena, u64 Size, gs_debug_loc Loc); + +internal gs_memory_cursor* +MemoryArenaPushCursor(gs_memory_arena* Arena, u64 MinSize, gs_debug_loc Loc) +{ + GS_MEMORY_PROFILE_FUNC; + + gs_memory_cursor* Result = 0; + + u64 CursorSize = MinSize; + if (CursorSize < Arena->ChunkSize) + { + CursorSize = Arena->ChunkSize; + } + u64 AllocSize = CursorSize + sizeof(gs_memory_cursor_sll); + + gs_data CursorMemory = {0}; + if (Arena->Parent) + { + CursorMemory = PushSize_(Arena->Parent, AllocSize, Loc); + } else if (Arena->UserData) { + // TODO(PS): implement custom MemoryArenaAllocCursor functionality + InvalidCodePath; + } else { + Assert(Arena->Allocator.PAlloc); + CursorMemory = Alloc_(Arena->Allocator, AllocSize, Loc, Arena->ArenaName); + } + + gs_memory_cursor_sll* CursorEntry = (gs_memory_cursor_sll*)CursorMemory.Memory; + if (!Arena->CursorsRoot) + { + Arena->CursorsRoot = CursorEntry; + } + if (Arena->CursorsHead) + { + Arena->CursorsHead->Next = CursorEntry; + } + Arena->CursorsHead = CursorEntry; + + u8* CursorBase = (u8*)(CursorEntry + 1); + CursorEntry->Cursor = MemoryCursorCreate(CursorBase, CursorSize); + Result = &CursorEntry->Cursor; + + return Result; +} + +#define PushSize(a,s) PushSize_((a), (s), DEBUG_LOC) +#define PushStruct(a,t) (t*)PushSize_((a), sizeof(t), DEBUG_LOC).Memory +#define PushArray(a,t,c) (t*)PushSize_((a), sizeof(t) * (c), DEBUG_LOC).Memory +#define PushString(a,c) gs_string{ PushArray((a),char,(c)), 0, (c) } + +internal gs_data +PushSize_(gs_memory_arena* Arena, u64 Size, gs_debug_loc Loc) +{ + GS_MEMORY_PROFILE_FUNC; + + gs_data Result = {0}; + if (Size > 0) + { + gs_memory_cursor* Cursor = 0; + for (gs_memory_cursor_sll* C = Arena->CursorsRoot; + C != 0; + C = C->Next) + { + if (MemoryCursorCanPush(C->Cursor, Size)) + { + Cursor = &C->Cursor; + break; + } + } + + // NOTE(PS): We didn't find a cursor with enough room + // for the allocation being requested + if (!Cursor) + { + Cursor = MemoryArenaPushCursor(Arena, Size, Loc); + } + Assert(Cursor); + Assert(MemoryCursorCanPush(*Cursor, Size)); + + Result = MemoryCursorPushSize(Cursor, Size); + + gs_data Alignment = MemoryCursorAlign(Cursor, Arena->Alignment); + Result.Size += Alignment.Size; + } + return Result; +} + +internal void +MemoryArenaClear(gs_memory_arena* Arena) +{ + GS_MEMORY_PROFILE_FUNC; + + for (gs_memory_cursor_sll* C = Arena->CursorsRoot; + C != 0; + C = C->Next) + { + MemoryCursorReset(&C->Cursor); + } +} + +internal void +MemoryArenaFree(gs_memory_arena* Arena) +{ + GS_MEMORY_PROFILE_FUNC; + + // NOTE(PS): If this isn't a base arena, we can't + // really free it. + // TODO(PS): Once we have the User Specified codepaths + // in, we can probably provide a way for the user to + // let us free a custom allocator + Assert(Arena->Allocator.PFree); + + gs_allocator A = Arena->Allocator; + gs_memory_cursor_sll* At = Arena->CursorsRoot; + while (At) + { + gs_memory_cursor_sll* NextAt = At->Next; + + u64 Size = At->Cursor.Data.Size + sizeof(gs_memory_cursor_sll); + Free(A, (u8*)At, Size); + + At = NextAt; + } + + Arena->CursorsRoot = 0; + Arena->CursorsHead = 0; +} + +#ifdef GS_PLATFORM_IMPLEMENTATION + +internal gs_allocator CreatePlatformAllocator(); + +# if PLATFORM_WINDOWS +# include "./gs_memory_win32.h" +# elif PLATFORM_OSX +# include "./gs_memory_osx.h" +# elif PLATFORM_LINUX +# include "./gs_memory_linux.h" +# endif + +#endif + +#endif //GS_MEMORY_H diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp index bcf9f99..bdf12c4 100644 --- a/src/gs_libs/gs_types.cpp +++ b/src/gs_libs/gs_types.cpp @@ -9,18 +9,18 @@ internal gs_data StructToData_(u8* Memory, u64 Size) { - gs_data Result = {0}; - Result.Memory = Memory; - Result.Size = Size; - return Result; + gs_data Result = {0}; + Result.Memory = Memory; + Result.Size = Size; + return Result; } internal u32 U32DivideRoundUp (u32 A, u32 B) { - r32 Result = (r32)A / (r32)B; - Result += .99999f; - return (u32)Result; + r32 Result = (r32)A / (r32)B; + Result += .99999f; + return (u32)Result; } inline bool XOR(bool A, bool B) { return (A == !B); } @@ -31,495 +31,495 @@ inline bool XOR(b64 A, b64 B) { return (A == !B); } internal u32 RoundUpToMultiple(u32 Value, u32 MultipleOf) { - u32 Result = Value; - if (MultipleOf != 0) - { - u32 Remainder = Value % MultipleOf; - Result = Value + (MultipleOf - Remainder); - } - return Result; + u32 Result = Value; + if (MultipleOf != 0) + { + u32 Remainder = Value % MultipleOf; + Result = Value + (MultipleOf - Remainder); + } + return Result; } internal u32 RoundUpToPow2U32(u32 Value) { - u32 Result = Value - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result |= Result >> 8; - Result |= Result >> 16; - Result++; - return Result; + u32 Result = Value - 1; + Result |= Result >> 1; + Result |= Result >> 2; + Result |= Result >> 4; + Result |= Result >> 8; + Result |= Result >> 16; + Result++; + return Result; } internal u32 RoundUpToPow2U64(u64 Value) { - u64 Result = Value - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result |= Result >> 8; - Result |= Result >> 16; - Result |= Result >> 32; - Result++; - return Result; + u64 Result = Value - 1; + Result |= Result >> 1; + Result |= Result >> 2; + Result |= Result >> 4; + Result |= Result >> 8; + Result |= Result >> 16; + Result |= Result >> 32; + Result++; + return Result; } internal u64 RoundUpTo64(u64 Value, u64 Alignment) { - Value += Alignment - 1; - Value -= Value % Alignment; - return Value; + Value += Alignment - 1; + Value -= Value % Alignment; + return Value; } internal u8 PowU8(u8 X, u32 Power) { - u8 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + u8 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal u16 PowU16(u16 X, u32 Power) { - u16 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + u16 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal u32 PowU32(u32 X, u32 Power) { - u32 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + u32 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal u64 PowU64(u64 X, u32 Power) { - u64 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + u64 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal s8 PowS8(s8 X, u32 Power) { - s8 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + s8 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal s16 PowS16(s16 X, u32 Power) { - s16 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + s16 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal s32 PowS32(s32 X, u32 Power) { - s32 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + s32 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal s64 PowS64(s64 X, u32 Power) { - s64 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + s64 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal r32 PowR32(r32 X, u32 Power) { - r32 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + r32 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal r64 PowR64(r64 X, u32 Power) { - r64 Result = X; - for (u32 i = 1; i < Power; i++) { Result *= X; } - return Result; + r64 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; } internal u8 LerpU8(r32 T, u8 A, u8 B) { - return (u8)((A * (1.0f - T)) + (B * T)); + return (u8)((A * (1.0f - T)) + (B * T)); } internal u16 LerpU16(r32 T, u16 A, u16 B) { - return (u16)((A * (1.0f - T)) + (B * T)); + return (u16)((A * (1.0f - T)) + (B * T)); } internal u32 LerpU32(r32 T, u32 A, u32 B) { - return (u32)((A * (1.0f - T)) + (B * T)); + return (u32)((A * (1.0f - T)) + (B * T)); } internal u64 LerpU64(r32 T, u64 A, u64 B) { - return (u64)((A * (1.0f - T)) + (B * T)); + return (u64)((A * (1.0f - T)) + (B * T)); } internal s8 LerpS8(r32 T, s8 A, s8 B) { - return (s8)((A * (1.0f - T)) + (B * T)); + return (s8)((A * (1.0f - T)) + (B * T)); } internal s16 LerpS16(r32 T, s16 A, s16 B) { - return (s16)((A * (1.0f - T)) + (B * T)); + return (s16)((A * (1.0f - T)) + (B * T)); } internal s32 LerpS32(r32 T, s32 A, s32 B) { - return (s32)((A * (1.0f - T)) + (B * T)); + return (s32)((A * (1.0f - T)) + (B * T)); } internal s64 LerpS64(r32 T, s64 A, s64 B) { - return (s64)((A * (1.0f - T)) + (B * T)); + return (s64)((A * (1.0f - T)) + (B * T)); } internal r32 LerpR32(r32 T, r32 A, r32 B) { - return (r32)((A * (1.0f - T)) + (B * T)); + return (r32)((A * (1.0f - T)) + (B * T)); } internal r64 LerpR64(r32 T, r64 A, r64 B) { - return (r64)((A * (1.0f - T)) + (B * T)); + return (r64)((A * (1.0f - T)) + (B * T)); } internal u8 UnlerpU8(u8 Value, u8 Min, u8 Max) { - return (u8)((r64)(Value - Min) / (r64)(Max - Min)); + return (u8)((r64)(Value - Min) / (r64)(Max - Min)); } internal u16 UnlerpU16(u16 Value, u16 Min, u16 Max) { - return (u16)((r64)(Value - Min) / (r64)(Max - Min)); + return (u16)((r64)(Value - Min) / (r64)(Max - Min)); } internal u32 UnlerpU32(u32 Value, u32 Min, u32 Max) { - return (u32)((r64)(Value - Min) / (r64)(Max - Min)); + return (u32)((r64)(Value - Min) / (r64)(Max - Min)); } internal u64 UnlerpU64(u64 Value, u64 Min, u64 Max) { - return (u64)((r64)(Value - Min) / (r64)(Max - Min)); + return (u64)((r64)(Value - Min) / (r64)(Max - Min)); } internal s8 UnlerpS8(s8 Value, s8 Min, s8 Max) { - return (s8)((r64)(Value - Min) / (r64)(Max - Min)); + return (s8)((r64)(Value - Min) / (r64)(Max - Min)); } internal s16 UnlerpS16(s16 Value, s16 Min, s16 Max) { - return (s16)((r64)(Value - Min) / (r64)(Max - Min)); + return (s16)((r64)(Value - Min) / (r64)(Max - Min)); } internal s32 UnlerpS32(s32 Value, s32 Min, s32 Max) { - return (s32)((r64)(Value - Min) / (r64)(Max - Min)); + return (s32)((r64)(Value - Min) / (r64)(Max - Min)); } internal s64 UnlerpS64(s64 Value, s64 Min, s64 Max) { - return (s64)((r64)(Value - Min) / (r64)(Max - Min)); + return (s64)((r64)(Value - Min) / (r64)(Max - Min)); } internal r32 UnlerpR32(r32 Value, r32 Min, r32 Max) { - return (Value - Min) / (Max - Min); + return (Value - Min) / (Max - Min); } internal r64 UnlerpR64(r64 Value, r64 Min, r64 Max) { - return (Value - Min) / (Max - Min); + return (Value - Min) / (Max - Min); } internal u8 RemapU8(u8 Value, u8 OldMin, u8 OldMax, u8 NewMin, u8 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - u8 Result = (u8)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + u8 Result = (u8)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal u16 RemapU16(u16 Value, u16 OldMin, u16 OldMax, u16 NewMin, u16 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - u16 Result = (u16)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + u16 Result = (u16)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal u32 RemapU32(u32 Value, u32 OldMin, u32 OldMax, u32 NewMin, u32 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - u32 Result = (u32)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + u32 Result = (u32)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal u64 RemapU64(u64 Value, u64 OldMin, u64 OldMax, u64 NewMin, u64 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - u64 Result = (u64)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + u64 Result = (u64)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal s8 RemapS8(s8 Value, s8 OldMin, s8 OldMax, s8 NewMin, s8 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - s8 Result = (s8)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + s8 Result = (s8)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal s16 RemapS16(s16 Value, s16 OldMin, s16 OldMax, s16 NewMin, s16 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - s16 Result = (s16)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + s16 Result = (s16)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal s32 RemapS32(s32 Value, s32 OldMin, s32 OldMax, s32 NewMin, s32 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - s32 Result = (s32)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + s32 Result = (s32)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal s64 RemapS64(s64 Value, s64 OldMin, s64 OldMax, s64 NewMin, s64 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - s64 Result = (s64)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + s64 Result = (s64)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal r32 RemapR32(r32 Value, r32 OldMin, r32 OldMax, r32 NewMin, r32 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r32 Result = (r32)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r32 Result = (r32)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal r64 RemapR64(r64 Value, r64 OldMin, r64 OldMax, r64 NewMin, r64 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 Result = (r64)((A * (NewMax - NewMin)) + NewMin); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 Result = (r64)((A * (NewMax - NewMin)) + NewMin); + return Result; } internal u8 RemapClampedU8(u8 Value, u8 OldMin, u8 OldMax, u8 NewMin, u8 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - u8 Result = (u8)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + u8 Result = (u8)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal u16 RemapClampedU16(u16 Value, u16 OldMin, u16 OldMax, u16 NewMin, u16 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - u16 Result = (u16)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + u16 Result = (u16)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal u32 RemapClampedU32(u32 Value, u32 OldMin, u32 OldMax, u32 NewMin, u32 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - u32 Result = (u32)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + u32 Result = (u32)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal u64 RemapClampedU64(u64 Value, u64 OldMin, u64 OldMax, u64 NewMin, u64 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - u64 Result = (u64)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + u64 Result = (u64)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal s8 RemapClampedS8(s8 Value, s8 OldMin, s8 OldMax, s8 NewMin, s8 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - s8 Result = (s8)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + s8 Result = (s8)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal s16 RemapClampedS16(s16 Value, s16 OldMin, s16 OldMax, s16 NewMin, s16 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - s16 Result = (s16)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + s16 Result = (s16)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal s32 RemapClampedS32(s32 Value, s32 OldMin, s32 OldMax, s32 NewMin, s32 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - s32 Result = (s32)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + s32 Result = (s32)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal s64 RemapClampedS64(s64 Value, s64 OldMin, s64 OldMax, s64 NewMin, s64 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - s64 Result = (s64)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + s64 Result = (s64)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal r32 RemapClampedR32(r32 Value, r32 OldMin, r32 OldMax, r32 NewMin, r32 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - r32 Result = (r32)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + r32 Result = (r32)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal r64 RemapClampedR64(r64 Value, r64 OldMin, r64 OldMax, r64 NewMin, r64 NewMax) { - r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); - r64 AClamped = Clamp01(A); - r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); - r64 Result = (r64)Clamp(NewMin, UnclampedResult, NewMax); - return Result; + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + r64 Result = (r64)Clamp(NewMin, UnclampedResult, NewMax); + return Result; } internal r32 FloorR32(r32 V) { - return (r32)((s64)V); + return (r32)((s64)V); } internal r64 FloorR64(r64 V) { - return (r64)((s64)V); + return (r64)((s64)V); } internal r32 FractR32(r32 V) { - return V - FloorR32(V); + return V - FloorR32(V); } internal r64 FractR64(r64 V) { - return V - FloorR64(V); + return V - FloorR64(V); } internal r32 SqrtR32(r32 V) { - return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); + return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); } internal u32 SqrtU32(u32 V) { - return sqrt(V); + return sqrt(V); } internal r32 ModR32(r32 Value, r32 Int) { - r32 Div = Value / Int; - r32 Fract = Abs(FractR32(Div)); - return Int * Fract; + r32 Div = Value / Int; + r32 Fract = Abs(FractR32(Div)); + return Int * Fract; } internal r64 ModR64(r64 Value, r64 Int) { - r64 Div = Value / Int; - r64 Fract = Abs(FractR64(Div)); - return Int * Fract; + r64 Div = Value / Int; + r64 Fract = Abs(FractR64(Div)); + return Int * Fract; } internal r32 SinR32(r32 Rad) { - return sinf(Rad); + return sinf(Rad); } internal r64 SinR64(r64 Rad) { - return sin(Rad); + return sin(Rad); } internal r32 CosR32(r32 Rad) { - return cosf(Rad); + return cosf(Rad); } internal r64 CosR64(r64 Rad) { - return cos(Rad); + return cos(Rad); } internal r32 TanR32(r32 Rad) { - return tanf(Rad); + return tanf(Rad); } internal r64 TanR64(r64 Rad) { - return tan(Rad); + return tan(Rad); } internal r32 ASinR32(r32 Rad) { - return asinf(Rad); + return asinf(Rad); } internal r64 ASinR64(r64 Rad) { - return asin(Rad); + return asin(Rad); } internal r32 ACosR32(r32 Rad) { - return acosf(Rad); + return acosf(Rad); } internal r64 ACosR64(r64 Rad) { - return acos(Rad); + return acos(Rad); } internal r32 ATanR32(r32 Rad) { - return atanf(Rad); + return atanf(Rad); } internal r64 ATanR64(r64 Rad) { - return atan(Rad); + return atan(Rad); } /////////////////////////// @@ -529,34 +529,34 @@ ATanR64(r64 Rad) internal v2 V2MultiplyPairwise(v2 A, v2 B) { - v2 Result = v2{ - A.x * B.x, - A.y * B.y, - }; - return Result; + v2 Result = v2{ + A.x * B.x, + A.y * B.y, + }; + return Result; } internal v3 V3MultiplyPairwise(v3 A, v3 B) { - v3 Result = v3{ - A.x * B.x, - A.y * B.y, - A.z * B.z, - }; - return Result; + v3 Result = v3{ + A.x * B.x, + A.y * B.y, + A.z * B.z, + }; + return Result; } internal v4 V4MultiplyPairwise(v4 A, v4 B) { - v4 Result = v4{ - A.x * B.x, - A.y * B.y, - A.z * B.z, - A.w * B.w, - }; - return Result; + v4 Result = v4{ + A.x * B.x, + A.y * B.y, + A.z * B.z, + A.w * B.w, + }; + return Result; } @@ -608,7 +608,7 @@ internal v3 ToV3(v2 V, r32 Z = 0) { return v3{V.x, V.y, Z}; } internal v4 V2ToV4(v2 V, r32 Z = 0, r32 W = 0) { return v4{V.x, V.y, Z, W}; } internal v4 ToV4_(v3 V, r32 W) { - return v4{V.x, V.y, V.z, W}; + return v4{V.x, V.y, V.z, W}; } #define ToV4Point(v) ToV4_((v), 1.0f) // all points have a w value of 1 #define ToV4Vec(v) ToV4_((v), 0.0f) // all vectors have a w value of 0 ie. they cannot be translated @@ -632,20 +632,20 @@ internal r32 V4Distance(v4 A, v4 B) { return V4Mag(A - B); } internal v2 V2Normalize(v2 A) { - r32 Magnitude = V2Mag(A); - return A / Magnitude; + r32 Magnitude = V2Mag(A); + return A / Magnitude; } internal v3 V3Normalize(v3 A) { - r32 Magnitude = V3Mag(A); - return A / Magnitude; + r32 Magnitude = V3Mag(A); + return A / Magnitude; } internal v4 V4Normalize(v4 A) { - r32 Magnitude = V4Mag(A); - return A / Magnitude; + r32 Magnitude = V4Mag(A); + return A / Magnitude; } internal r32 V2Dot(v2 A, v2 B) { return ((A.x * B.x) + (A.y * B.y)); } @@ -658,102 +658,102 @@ internal v2 V2PerpendicularCCW(v2 A) { return v2{A.y, A.x}; } internal r32 V2Cross(v2 A, v2 B) { - return ((A.x * B.y) - (A.y * B.x)); + return ((A.x * B.y) - (A.y * B.x)); } internal v3 V3Cross(v3 A, v3 B) { - v3 Result = { - (A.y * B.z) - (A.z * B.y), - (A.z * B.x) - (A.x * B.z), - (A.x * B.y) - (A.y * B.x) - }; - return Result; + v3 Result = { + (A.y * B.z) - (A.z * B.y), + (A.z * B.x) - (A.x * B.z), + (A.x * B.y) - (A.y * B.x) + }; + return Result; } internal v4 V4Cross(v4 A, v4 B) { - v4 Result = { - (A.y * B.z) - (A.z * B.y), - (A.z * B.x) - (A.x * B.z), - (A.x * B.y) - (A.y * B.x), - 0 - }; - return Result; + v4 Result = { + (A.y * B.z) - (A.z * B.y), + (A.z * B.x) - (A.x * B.z), + (A.x * B.y) - (A.y * B.x), + 0 + }; + return Result; } internal v2 V2Lerp(r32 T, v2 A, v2 B) { - v2 Result = v2{ - LerpR32(T, A.x, B.x), - LerpR32(T, A.y, B.y), - }; - return Result; + v2 Result = v2{ + LerpR32(T, A.x, B.x), + LerpR32(T, A.y, B.y), + }; + return Result; } internal v3 V3Lerp(r32 T, v3 A, v3 B) { - v3 Result = v3{ - LerpR32(T, A.x, B.x), - LerpR32(T, A.y, B.y), - LerpR32(T, A.z, B.z), - }; - return Result; + v3 Result = v3{ + LerpR32(T, A.x, B.x), + LerpR32(T, A.y, B.y), + LerpR32(T, A.z, B.z), + }; + return Result; } internal v4 V4Lerp(r32 T, v4 A, v4 B) { - v4 Result = v4{ - LerpR32(T, A.x, B.x), - LerpR32(T, A.y, B.y), - LerpR32(T, A.z, B.z), - LerpR32(T, A.w, B.w), - }; - return Result; + v4 Result = v4{ + LerpR32(T, A.x, B.x), + LerpR32(T, A.y, B.y), + LerpR32(T, A.z, B.z), + LerpR32(T, A.w, B.w), + }; + return Result; } internal v2 V2Remap(v2 P, v2 OldMin, v2 OldMax, v2 NewMin, v2 NewMax) { - v2 Result = {0}; - Result.x = RemapR32(P.x, OldMin.x, OldMax.x, NewMin.x, NewMax.x); - Result.y = RemapR32(P.y, OldMin.y, OldMax.y, NewMin.y, NewMax.y); - return Result; + v2 Result = {0}; + Result.x = RemapR32(P.x, OldMin.x, OldMax.x, NewMin.x, NewMax.x); + Result.y = RemapR32(P.y, OldMin.y, OldMax.y, NewMin.y, NewMax.y); + return Result; } internal v3 V3Remap(v3 P, v3 OldMin, v3 OldMax, v3 NewMin, v3 NewMax) { - v3 Result = {0}; - Result.x = RemapR32(P.x, OldMin.x, OldMax.x, NewMin.x, NewMax.x); - Result.y = RemapR32(P.y, OldMin.y, OldMax.y, NewMin.y, NewMax.y); - Result.z = RemapR32(P.z, OldMin.z, OldMax.z, NewMin.z, NewMax.z); - return Result; + v3 Result = {0}; + Result.x = RemapR32(P.x, OldMin.x, OldMax.x, NewMin.x, NewMax.x); + Result.y = RemapR32(P.y, OldMin.y, OldMax.y, NewMin.y, NewMax.y); + Result.z = RemapR32(P.z, OldMin.z, OldMax.z, NewMin.z, NewMax.z); + return Result; } internal v4 V4Remap(v4 P, v4 OldMin, v4 OldMax, v4 NewMin, v4 NewMax) { - v4 Result = {0}; - Result.x = RemapR32(P.x, OldMin.x, OldMax.x, NewMin.x, NewMax.x); - Result.y = RemapR32(P.y, OldMin.y, OldMax.y, NewMin.y, NewMax.y); - Result.z = RemapR32(P.z, OldMin.z, OldMax.z, NewMin.z, NewMax.z); - Result.w = RemapR32(P.w, OldMin.w, OldMax.w, NewMin.w, NewMax.w); - return Result; + v4 Result = {0}; + Result.x = RemapR32(P.x, OldMin.x, OldMax.x, NewMin.x, NewMax.x); + Result.y = RemapR32(P.y, OldMin.y, OldMax.y, NewMin.y, NewMax.y); + Result.z = RemapR32(P.z, OldMin.z, OldMax.z, NewMin.z, NewMax.z); + Result.w = RemapR32(P.w, OldMin.w, OldMax.w, NewMin.w, NewMax.w); + return Result; } internal v4 V4RemapAsV3(v4 P, v4 OldMin, v4 OldMax, v4 NewMin, v4 NewMax) { - v4 Result = {0}; - Result.xyz = V3Remap(P.xyz, OldMin.xyz, OldMax.xyz, NewMin.xyz, NewMax.xyz); - Result.w = P.w; - return Result; + v4 Result = {0}; + Result.xyz = V3Remap(P.xyz, OldMin.xyz, OldMax.xyz, NewMin.xyz, NewMax.xyz); + Result.w = P.w; + return Result; } /////////////////////////// @@ -762,47 +762,47 @@ V4RemapAsV3(v4 P, v4 OldMin, v4 OldMax, v4 NewMin, v4 NewMax) internal rect2 MakeRect2MinDim(v2 Min, v2 Dim) { - rect2 Result = {0}; - Result.Min = Min; - Result.Max = Min + Dim; - return Result; + rect2 Result = {0}; + Result.Min = Min; + Result.Max = Min + Dim; + return Result; } internal rect2 MakeRect2CenterDim(v2 Center, v2 Dim) { - v2 HalfDim = Dim / 2; - rect2 Result = {0}; - Result.Min = Center - HalfDim; - Result.Max = Center + HalfDim; - return Result; + v2 HalfDim = Dim / 2; + rect2 Result = {0}; + Result.Min = Center - HalfDim; + Result.Max = Center + HalfDim; + return Result; } internal b32 ValueInRangeR32(r32 Min, r32 Max, r32 V) { - return ((V >= Min) && (V <= Max)); + return ((V >= Min) && (V <= Max)); } internal b32 ValueInRange1(range1 Range, r32 V) { - return ValueInRangeR32(Range.Min, Range.Max, V); + return ValueInRangeR32(Range.Min, Range.Max, V); } internal b32 ValueInRange2(range2 Range, v2 V) { - return (ValueInRangeR32(Range.Min.x, Range.Max.x, V.x) && - ValueInRangeR32(Range.Min.y, Range.Max.y, V.y)); + return (ValueInRangeR32(Range.Min.x, Range.Max.x, V.x) && + ValueInRangeR32(Range.Min.y, Range.Max.y, V.y)); } internal b32 ValueInRange3(range3 Range, v3 V) { - return (ValueInRangeR32(Range.Min.x, Range.Max.x, V.x) && - ValueInRangeR32(Range.Min.y, Range.Max.y, V.y) && - ValueInRangeR32(Range.Min.z, Range.Max.z, V.z)); + return (ValueInRangeR32(Range.Min.x, Range.Max.x, V.x) && + ValueInRangeR32(Range.Min.y, Range.Max.y, V.y) && + ValueInRangeR32(Range.Min.z, Range.Max.z, V.z)); } internal b32 ValueInRange4(range4 Range, v4 V) { - return (ValueInRangeR32(Range.Min.x, Range.Max.x, V.x) && - ValueInRangeR32(Range.Min.y, Range.Max.y, V.y) && - ValueInRangeR32(Range.Min.z, Range.Max.z, V.z) && - ValueInRangeR32(Range.Min.w, Range.Max.w, V.w)); + return (ValueInRangeR32(Range.Min.x, Range.Max.x, V.x) && + ValueInRangeR32(Range.Min.y, Range.Max.y, V.y) && + ValueInRangeR32(Range.Min.z, Range.Max.z, V.z) && + ValueInRangeR32(Range.Min.w, Range.Max.w, V.w)); } #define PointIsInRect(range, point) ValueInRange2((range), (point)) @@ -843,19 +843,19 @@ internal range4 Range4Offset(range4 Range, v4 Delta) { return range4{ Range.Min internal v2 RectTopLeft(rect2 Rect) { - return v2{ Rect.Min.x, Rect.Max.y }; + return v2{ Rect.Min.x, Rect.Max.y }; } internal v2 RectTopRight(rect2 Rect) { - return Rect.Max; + return Rect.Max; } internal v2 RectBottomLeft(rect2 Rect) { - return Rect.Min; + return Rect.Min; } internal v2 RectBottomRight(rect2 Rect) { - return v2{ Rect.Max.x, Rect.Min.y }; + return v2{ Rect.Max.x, Rect.Min.y }; } internal r32 AspectRatio(r32 Width, r32 Height) { return Width / Height; } @@ -864,143 +864,143 @@ internal r32 RectAspectRatio(rect2 Rect) { return Range2SizeX(Rect) / Range2Size internal void RectHSplit(rect2 Rect, r32 YValue, rect2* Top, rect2* Bottom) { - r32 ClampedYValue = Clamp(Rect.Min.y, YValue, Rect.Max.y); - Top->Max = Rect.Max; - Top->Min = { Rect.Min.x, ClampedYValue }; - Bottom->Max = { Rect.Max.x, ClampedYValue }; - Bottom->Min = Rect.Min; + r32 ClampedYValue = Clamp(Rect.Min.y, YValue, Rect.Max.y); + Top->Max = Rect.Max; + Top->Min = { Rect.Min.x, ClampedYValue }; + Bottom->Max = { Rect.Max.x, ClampedYValue }; + Bottom->Min = Rect.Min; } internal void RectVSplit(rect2 Rect, r32 XValue, rect2* Left, rect2* Right) { - r32 ClampedXValue = Clamp(Rect.Min.x, XValue, Rect.Max.x); - Left->Max = { ClampedXValue, Rect.Max.y}; - Left->Min = Rect.Min; - Right->Max = Rect.Max; - Right->Min = { ClampedXValue, Rect.Min.y }; + r32 ClampedXValue = Clamp(Rect.Min.x, XValue, Rect.Max.x); + Left->Max = { ClampedXValue, Rect.Max.y}; + Left->Min = Rect.Min; + Right->Max = Rect.Max; + Right->Min = { ClampedXValue, Rect.Min.y }; } internal void RectHSplitAtDistanceFromTop(rect2 Rect, r32 YDist, rect2* Top, rect2* Bottom) { - RectHSplit(Rect, Rect.Max.y - YDist, Top, Bottom); + RectHSplit(Rect, Rect.Max.y - YDist, Top, Bottom); } internal void RectHSplitAtDistanceFromBottom(rect2 Rect, r32 YDist, rect2* Top, rect2* Bottom) { - RectHSplit(Rect, Rect.Min.y + YDist, Top, Bottom); + RectHSplit(Rect, Rect.Min.y + YDist, Top, Bottom); } internal void RectVSplitAtDistanceFromRight(rect2 Rect, r32 XDist, rect2* Left, rect2* Right) { - RectVSplit(Rect, Rect.Max.x - XDist, Left, Right); + RectVSplit(Rect, Rect.Max.x - XDist, Left, Right); } internal void RectVSplitAtDistanceFromLeft(rect2 Rect, r32 XDist, rect2* Left, rect2* Right) { - RectVSplit(Rect, Rect.Min.x + XDist, Left, Right); + RectVSplit(Rect, Rect.Min.x + XDist, Left, Right); } internal void RectHSplitAtPercent(rect2 Rect, r32 YPercent, rect2* Top, rect2* Bottom) { - RectHSplit(Rect, LerpR32(YPercent, Rect.Min.y, Rect.Max.y), Top, Bottom); + RectHSplit(Rect, LerpR32(YPercent, Rect.Min.y, Rect.Max.y), Top, Bottom); } internal void RectVSplitAtPercent(rect2 Rect, r32 XPercent, rect2* Left, rect2* Right) { - RectVSplit(Rect, LerpR32(XPercent, Rect.Min.x, Rect.Max.x), Left, Right); + RectVSplit(Rect, LerpR32(XPercent, Rect.Min.x, Rect.Max.x), Left, Right); } internal rect2 RectInset(rect2 Outer, v2 Amount) { - rect2 Result = { Outer.Min + Amount, Outer.Max - Amount }; - return Result; + rect2 Result = { Outer.Min + Amount, Outer.Max - Amount }; + return Result; } internal rect2 RectInset(rect2 Outer, r32 UniformAmount) { - return RectInset(Outer, v2{UniformAmount, UniformAmount}); + return RectInset(Outer, v2{UniformAmount, UniformAmount}); } internal range1 Range1Union(range1 A, range1 B) { - range1 Result = {}; - Result.Min = Max(A.Min, B.Min); - Result.Max = Min(A.Max, B.Max); - return Result; + range1 Result = {}; + Result.Min = Max(A.Min, B.Min); + Result.Max = Min(A.Max, B.Max); + return Result; } #define Rect2Union(a,b) Range2Union((a), (b)) internal range2 Range2Union(range2 A, range2 B) { - range2 Result = {}; - Result.Min.x = Max(A.Min.x, B.Min.x); - Result.Min.y = Max(A.Min.y, B.Min.y); - Result.Max.x = Min(A.Max.x, B.Max.x); - Result.Max.y = Min(A.Max.y, B.Max.y); - - if (Rect2Width(Result) < 0) { Result.Min.x = Result.Max.x; } - if (Rect2Height(Result) < 0) { Result.Min.y = Result.Max.y; } - - return Result; + range2 Result = {}; + Result.Min.x = Max(A.Min.x, B.Min.x); + Result.Min.y = Max(A.Min.y, B.Min.y); + Result.Max.x = Min(A.Max.x, B.Max.x); + Result.Max.y = Min(A.Max.y, B.Max.y); + + if (Rect2Width(Result) < 0) { Result.Min.x = Result.Max.x; } + if (Rect2Height(Result) < 0) { Result.Min.y = Result.Max.y; } + + return Result; } internal range3 Range3Union(range3 A, range3 B) { - range3 Result = {}; - Result.Min.x = Max(A.Min.x, B.Min.x); - Result.Min.y = Max(A.Min.y, B.Min.y); - Result.Min.z = Max(A.Min.z, B.Min.z); - Result.Max.x = Min(A.Max.x, B.Max.x); - Result.Max.y = Min(A.Max.y, B.Max.y); - Result.Max.z = Min(A.Max.z, B.Max.z); - return Result; + range3 Result = {}; + Result.Min.x = Max(A.Min.x, B.Min.x); + Result.Min.y = Max(A.Min.y, B.Min.y); + Result.Min.z = Max(A.Min.z, B.Min.z); + Result.Max.x = Min(A.Max.x, B.Max.x); + Result.Max.y = Min(A.Max.y, B.Max.y); + Result.Max.z = Min(A.Max.z, B.Max.z); + return Result; } internal v2 Rect2GetRectLocalPoint(rect2 Rect, v2 Point) { - v2 Result = Point - Rect.Min; - return Result; + v2 Result = Point - Rect.Min; + return Result; } internal r32 Rect2Area(rect2 Rect) { - r32 Result = Rect2Width(Rect) * Rect2Height(Rect); - return Result; + r32 Result = Rect2Width(Rect) * Rect2Height(Rect); + return Result; } internal v2 Rect2BottomLeft(rect2 Rect) { - v2 Result = Rect.Min; - return Result; + v2 Result = Rect.Min; + return Result; } internal v2 Rect2BottomRight(rect2 Rect) { - v2 Result = v2{ Rect.Max.x, Rect.Min.y }; - return Result; + v2 Result = v2{ Rect.Max.x, Rect.Min.y }; + return Result; } internal v2 Rect2TopRight(rect2 Rect) { - v2 Result = Rect.Max; - return Result; + v2 Result = Rect.Max; + return Result; } internal v2 Rect2TopLeft(rect2 Rect) { - v2 Result = v2{ Rect.Min.x, Rect.Max.y }; - return Result; + v2 Result = v2{ Rect.Min.x, Rect.Max.y }; + return Result; } /////////////////////////// @@ -1010,55 +1010,55 @@ Rect2TopLeft(rect2 Rect) internal v4 RayGetPointAlong(v4 RayOrigin, v4 RayDirection, r32 T) { - v4 Result = RayOrigin + (RayDirection * T); - return Result; + v4 Result = RayOrigin + (RayDirection * T); + return Result; } internal r32 RayPlaneIntersectionDistance(v4 RayOrigin, v4 RayDirection, v4 PlanePoint, v4 PlaneNormal) { - r32 T = 0.0f; - float Denominator = V4Dot(PlaneNormal, RayDirection); - if (Abs(Denominator) > 0.00001f) - { - T = V4Dot(PlanePoint - RayDirection, PlaneNormal) / Denominator; - } - return T; + r32 T = 0.0f; + float Denominator = V4Dot(PlaneNormal, RayDirection); + if (Abs(Denominator) > 0.00001f) + { + T = V4Dot(PlanePoint - RayDirection, PlaneNormal) / Denominator; + } + return T; } internal v4 GetRayPlaneIntersectionPoint(v4 RayOrigin, v4 RayDirection, v4 PlanePoint, v4 PlaneNormal) { - v4 Result = {0}; - r32 T = RayPlaneIntersectionDistance(RayOrigin, RayDirection, PlanePoint, PlaneNormal); - if (T >= 0) - { - Result = RayGetPointAlong(RayOrigin, RayDirection, T); - } - return Result; + v4 Result = {0}; + r32 T = RayPlaneIntersectionDistance(RayOrigin, RayDirection, PlanePoint, PlaneNormal); + if (T >= 0) + { + Result = RayGetPointAlong(RayOrigin, RayDirection, T); + } + return Result; } internal v4 GetRayPlaneIntersectionPoint(v4_ray Ray, v4 PlanePoint, v4 PlaneNormal) { - return GetRayPlaneIntersectionPoint(Ray.Origin, Ray.Direction, PlanePoint, PlaneNormal); + return GetRayPlaneIntersectionPoint(Ray.Origin, Ray.Direction, PlanePoint, PlaneNormal); } internal bool RayIntersectsPlane(v4 RayOrigin, v4 RayDirection, v4 PlanePoint, v4 PlaneNormal, v4* OutPoint) { - bool Result = false; - r32 T = RayPlaneIntersectionDistance(RayOrigin, RayDirection, PlanePoint, PlaneNormal); - if (T >= 0) - { - Result = true; - *OutPoint = RayGetPointAlong(RayOrigin, RayDirection, T); - } - return Result; + bool Result = false; + r32 T = RayPlaneIntersectionDistance(RayOrigin, RayDirection, PlanePoint, PlaneNormal); + if (T >= 0) + { + Result = true; + *OutPoint = RayGetPointAlong(RayOrigin, RayDirection, T); + } + return Result; } internal bool RayIntersectsPlane(v4_ray Ray, v4 PlanePoint, v4 PlaneNormal, v4* OutPoint) { - return RayIntersectsPlane(Ray.Origin, Ray.Direction, PlanePoint, PlaneNormal, OutPoint); + return RayIntersectsPlane(Ray.Origin, Ray.Direction, PlanePoint, PlaneNormal, OutPoint); } /////////////////////////// @@ -1068,286 +1068,286 @@ RayIntersectsPlane(v4_ray Ray, v4 PlanePoint, v4 PlaneNormal, v4* OutPoint) internal m44 M44Identity() { - m44 M = {0}; - M.AXx = 1.0f; - M.AYy = 1.0f; - M.AZz = 1.0f; - M.Tw = 1.0f; - return M; + m44 M = {0}; + M.AXx = 1.0f; + M.AYy = 1.0f; + M.AZz = 1.0f; + M.Tw = 1.0f; + return M; } internal m44 M44Transpose(m44 M) { - m44 Result = {0}; - for (u32 Y = 0; Y < 4; Y++) + m44 Result = {0}; + for (u32 Y = 0; Y < 4; Y++) + { + for (u32 X = 0; X < 4; X++) { - for (u32 X = 0; X < 4; X++) - { - Result.Array[(X * 4) + Y] = M.Array[(Y * 4) + X]; - } + Result.Array[(X * 4) + Y] = M.Array[(Y * 4) + X]; } - return Result; + } + return Result; } // Matrix * Matrix m44 operator* (m44 L, m44 R) { - m44 M = {0}; - - // ci ic ci ic ci ic i ic - M.AXx = (L.AXx * R.AXx) + (L.AYx * R.AXy) + (L.AZx * R.AXz) + (L.Tx * R.AXw); - M.AXy = (L.AXy * R.AXx) + (L.AYy * R.AXy) + (L.AZy * R.AXz) + (L.Ty * R.AXw); - M.AXz = (L.AXz * R.AXx) + (L.AYz * R.AXy) + (L.AZz * R.AXz) + (L.Tz * R.AXw); - M.AXw = (L.AXw * R.AXx) + (L.AYw * R.AXy) + (L.AZw * R.AXz) + (L.Tw * R.AXw); - - M.AYx = (L.AXx * R.AYx) + (L.AYx * R.AYy) + (L.AZx * R.AYz) + (L.Tx * R.AYw); - M.AYy = (L.AXy * R.AYx) + (L.AYy * R.AYy) + (L.AZy * R.AYz) + (L.Ty * R.AYw); - M.AYz = (L.AXz * R.AYx) + (L.AYz * R.AYy) + (L.AZz * R.AYz) + (L.Tz * R.AYw); - M.AYz = (L.AXw * R.AYx) + (L.AYw * R.AYy) + (L.AZw * R.AYz) + (L.Tw * R.AYw); - - M.AZx = (L.AXx * R.AZx) + (L.AYx * R.AZy) + (L.AZx * R.AZz) + (L.Tx * R.AZw); - M.AZy = (L.AXy * R.AZx) + (L.AYy * R.AZy) + (L.AZy * R.AZz) + (L.Ty * R.AZw); - M.AZz = (L.AXz * R.AZx) + (L.AYz * R.AZy) + (L.AZz * R.AZz) + (L.Tz * R.AZw); - M.AZw = (L.AXw * R.AZx) + (L.AYw * R.AZy) + (L.AZw * R.AZz) + (L.Tw * R.AZw); - - M.Tx = (L.AXx * R.Tx) + (L.AYx * R.Ty) + (L.AZx * R.Tz) + (L.Tx * R.Tw); - M.Ty = (L.AXy * R.Tx) + (L.AYy * R.Ty) + (L.AZy * R.Tz) + (L.Ty * R.Tw); - M.Tz = (L.AXz * R.Tx) + (L.AYz * R.Ty) + (L.AZz * R.Tz) + (L.Tz * R.Tw); - M.Tw = (L.AXw * R.Tx) + (L.AYw * R.Ty) + (L.AZw * R.Tz) + (L.Tw * R.Tw); - - return M; + m44 M = {0}; + + // ci ic ci ic ci ic i ic + M.AXx = (L.AXx * R.AXx) + (L.AYx * R.AXy) + (L.AZx * R.AXz) + (L.Tx * R.AXw); + M.AXy = (L.AXy * R.AXx) + (L.AYy * R.AXy) + (L.AZy * R.AXz) + (L.Ty * R.AXw); + M.AXz = (L.AXz * R.AXx) + (L.AYz * R.AXy) + (L.AZz * R.AXz) + (L.Tz * R.AXw); + M.AXw = (L.AXw * R.AXx) + (L.AYw * R.AXy) + (L.AZw * R.AXz) + (L.Tw * R.AXw); + + M.AYx = (L.AXx * R.AYx) + (L.AYx * R.AYy) + (L.AZx * R.AYz) + (L.Tx * R.AYw); + M.AYy = (L.AXy * R.AYx) + (L.AYy * R.AYy) + (L.AZy * R.AYz) + (L.Ty * R.AYw); + M.AYz = (L.AXz * R.AYx) + (L.AYz * R.AYy) + (L.AZz * R.AYz) + (L.Tz * R.AYw); + M.AYz = (L.AXw * R.AYx) + (L.AYw * R.AYy) + (L.AZw * R.AYz) + (L.Tw * R.AYw); + + M.AZx = (L.AXx * R.AZx) + (L.AYx * R.AZy) + (L.AZx * R.AZz) + (L.Tx * R.AZw); + M.AZy = (L.AXy * R.AZx) + (L.AYy * R.AZy) + (L.AZy * R.AZz) + (L.Ty * R.AZw); + M.AZz = (L.AXz * R.AZx) + (L.AYz * R.AZy) + (L.AZz * R.AZz) + (L.Tz * R.AZw); + M.AZw = (L.AXw * R.AZx) + (L.AYw * R.AZy) + (L.AZw * R.AZz) + (L.Tw * R.AZw); + + M.Tx = (L.AXx * R.Tx) + (L.AYx * R.Ty) + (L.AZx * R.Tz) + (L.Tx * R.Tw); + M.Ty = (L.AXy * R.Tx) + (L.AYy * R.Ty) + (L.AZy * R.Tz) + (L.Ty * R.Tw); + M.Tz = (L.AXz * R.Tx) + (L.AYz * R.Ty) + (L.AZz * R.Tz) + (L.Tz * R.Tw); + M.Tw = (L.AXw * R.Tx) + (L.AYw * R.Ty) + (L.AZw * R.Tz) + (L.Tw * R.Tw); + + return M; } // Matrix * Vector v4 operator* (m44 M, v4 V) { - v4 Result = {0}; - Result.x = (V.x * M.AXx) + (V.y * M.AYx) + (V.z * M.AZx) + (V.w * M.Tx); - Result.y = (V.x * M.AXy) + (V.y * M.AYy) + (V.z * M.AZy) + (V.w * M.Ty); - Result.z = (V.x * M.AXz) + (V.y * M.AYz) + (V.z * M.AZz) + (V.w * M.Tz); - Result.w = (V.x * M.AXw) + (V.y * M.AYw) + (V.z * M.AZw) + (V.w * M.Tw); - return Result; + v4 Result = {0}; + Result.x = (V.x * M.AXx) + (V.y * M.AYx) + (V.z * M.AZx) + (V.w * M.Tx); + Result.y = (V.x * M.AXy) + (V.y * M.AYy) + (V.z * M.AZy) + (V.w * M.Ty); + Result.z = (V.x * M.AXz) + (V.y * M.AYz) + (V.z * M.AZz) + (V.w * M.Tz); + Result.w = (V.x * M.AXw) + (V.y * M.AYw) + (V.z * M.AZw) + (V.w * M.Tw); + return Result; } internal m44 M44Translation(v4 Offset) { - m44 Result = M44Identity(); - Result.Tx = Offset.x; - Result.Ty = Offset.y; - Result.Tz = Offset.z; - return Result; + m44 Result = M44Identity(); + Result.Tx = Offset.x; + Result.Ty = Offset.y; + Result.Tz = Offset.z; + return Result; } internal m44 M44RotationX(r32 Radians) { - r32 CosRad = CosR32(Radians); - r32 SinRad = SinR32(Radians); - m44 Result = M44Identity(); - Result.AYy = CosRad; - Result.AZy = SinRad; - Result.AYz = -SinRad; - Result.AZz = CosRad; - return Result; + r32 CosRad = CosR32(Radians); + r32 SinRad = SinR32(Radians); + m44 Result = M44Identity(); + Result.AYy = CosRad; + Result.AZy = SinRad; + Result.AYz = -SinRad; + Result.AZz = CosRad; + return Result; } internal m44 M44RotationY(r32 Radians) { - r32 CosRad = CosR32(Radians); - r32 SinRad = SinR32(Radians); - m44 Result = M44Identity(); - Result.AXx = CosRad; - Result.AZx = SinRad; - Result.AXz = -SinRad; - Result.AZz = CosRad; - return Result; + r32 CosRad = CosR32(Radians); + r32 SinRad = SinR32(Radians); + m44 Result = M44Identity(); + Result.AXx = CosRad; + Result.AZx = SinRad; + Result.AXz = -SinRad; + Result.AZz = CosRad; + return Result; } internal m44 M44RotationZ(r32 Radians) { - r32 CosRad = CosR32(Radians); - r32 SinRad = SinR32(Radians); - m44 Result = M44Identity(); - Result.AXx = CosRad; - Result.AYx = -SinRad; - Result.AXy = SinRad; - Result.AYy = CosRad; - return Result; + r32 CosRad = CosR32(Radians); + r32 SinRad = SinR32(Radians); + m44 Result = M44Identity(); + Result.AXx = CosRad; + Result.AYx = -SinRad; + Result.AXy = SinRad; + Result.AYy = CosRad; + return Result; } internal m44 M44Rotation(v3 Radians) { - r32 CosX = CosR32(Radians.x); - r32 SinX = SinR32(Radians.x); - r32 CosY = CosR32(Radians.y); - r32 SinY = SinR32(Radians.y); - r32 CosZ = CosR32(Radians.z); - r32 SinZ = SinR32(Radians.z); - - m44 Result = {0}; - Result.AXx = CosY * CosZ; - Result.AXy = -(SinX * SinY * CosZ) + (CosX * SinZ); - Result.AXz = -(CosX * SinY * CosZ) - (SinX * SinZ); - Result.AXw = 0; - - Result.AYx = -(SinZ * CosY); - Result.AYy = (SinX * SinY * SinZ) + (CosX * CosZ); - Result.AYz = (CosX * SinY * SinZ) - (SinX * CosZ); - Result.AYw = 0; - - Result.AZx = SinY; - Result.AZy = SinX * CosY; - Result.AZz = CosX * CosY; - Result.AZw = 0; - - Result.Tx = 0; - Result.Ty = 0; - Result.Tz = 0; - Result.Tw = 1; - - return Result; + r32 CosX = CosR32(Radians.x); + r32 SinX = SinR32(Radians.x); + r32 CosY = CosR32(Radians.y); + r32 SinY = SinR32(Radians.y); + r32 CosZ = CosR32(Radians.z); + r32 SinZ = SinR32(Radians.z); + + m44 Result = {0}; + Result.AXx = CosY * CosZ; + Result.AXy = -(SinX * SinY * CosZ) + (CosX * SinZ); + Result.AXz = -(CosX * SinY * CosZ) - (SinX * SinZ); + Result.AXw = 0; + + Result.AYx = -(SinZ * CosY); + Result.AYy = (SinX * SinY * SinZ) + (CosX * CosZ); + Result.AYz = (CosX * SinY * SinZ) - (SinX * CosZ); + Result.AYw = 0; + + Result.AZx = SinY; + Result.AZy = SinX * CosY; + Result.AZz = CosX * CosY; + Result.AZw = 0; + + Result.Tx = 0; + Result.Ty = 0; + Result.Tz = 0; + Result.Tw = 1; + + return Result; } internal m44 M44Scale(v3 Scale) { - m44 Result = M44Identity(); - Result.AXx = Scale.x; - Result.AYy = Scale.y; - Result.AZz = Scale.z; - return Result; + m44 Result = M44Identity(); + Result.AXx = Scale.x; + Result.AYy = Scale.y; + Result.AZz = Scale.z; + return Result; } internal m44 M44ScaleUniform(r32 Scale) { - m44 Result = M44Identity(); - Result.AXx = Scale; - Result.AYy = Scale; - Result.AZz = Scale; - return Result; + m44 Result = M44Identity(); + Result.AXx = Scale; + Result.AYy = Scale; + Result.AZz = Scale; + return Result; } internal m44 M44CoordinateFrame(v4 Forward, v4 Right, v4 Up) { - m44 Result = {0}; - Result.AXx = Right.x; - Result.AYx = Right.y; - Result.AZx = Right.z; - Result.Tx = Right.w; - - Result.AXy = Up.x; - Result.AYy = Up.y; - Result.AZy = Up.z; - Result.Ty = Up.w; - - Result.AXz = Forward.x; - Result.AYz = Forward.y; - Result.AZz = Forward.z; - Result.Tz = Forward.w; - - Result.Tw = 1.0f; - return Result; + m44 Result = {0}; + Result.AXx = Right.x; + Result.AYx = Right.y; + Result.AZx = Right.z; + Result.Tx = Right.w; + + Result.AXy = Up.x; + Result.AYy = Up.y; + Result.AZy = Up.z; + Result.Ty = Up.w; + + Result.AXz = Forward.x; + Result.AYz = Forward.y; + Result.AZz = Forward.z; + Result.Tz = Forward.w; + + Result.Tw = 1.0f; + return Result; } internal m44 M44ModelMatrix(v4 Forward, v4 Right, v4 Up, v4 Position) { - m44 RotationMatrix = M44CoordinateFrame(Forward, Right, Up); - m44 PositionMatrix = M44Translation(-Position); - m44 ModelViewMatrix = PositionMatrix * RotationMatrix; - return ModelViewMatrix; + m44 RotationMatrix = M44CoordinateFrame(Forward, Right, Up); + m44 PositionMatrix = M44Translation(-Position); + m44 ModelViewMatrix = PositionMatrix * RotationMatrix; + return ModelViewMatrix; } internal m44 M44ProjectionOrtho(r32 Width, r32 Height, r32 Near, r32 Far, r32 Right, r32 Left, r32 Top, r32 Bottom) { - m44 Result = {0}; - Result.AXx = 2.0f / Width; - Result.AYy = 2.0f / Height; - Result.AZz = 2.0f / (Near - Far); - Result.AXw = -(Right + Left) / (Right - Left); - Result.AYw = -(Top + Bottom) / (Top - Bottom); - Result.AZw = -(Far + Near) / (Far - Near); - Result.Tw = 1; - return Result; + m44 Result = {0}; + Result.AXx = 2.0f / Width; + Result.AYy = 2.0f / Height; + Result.AZz = 2.0f / (Near - Far); + Result.AXw = -(Right + Left) / (Right - Left); + Result.AYw = -(Top + Bottom) / (Top - Bottom); + Result.AZw = -(Far + Near) / (Far - Near); + Result.Tw = 1; + return Result; } internal m44 M44ProjectionOrtho(r32 Aspect, r32 Scale, r32 Near, r32 Far) { - m44 Result = {0}; - r32 Width = Scale * Aspect; - r32 Height = Scale; - r32 Right = Width / 2.0f; - r32 Left = -Right; - r32 Top = Height / 2.0f; - r32 Bottom = -Top; - Result = M44ProjectionOrtho(Width, Height, Near, Far, Right, Left, Top, Bottom); - return Result; + m44 Result = {0}; + r32 Width = Scale * Aspect; + r32 Height = Scale; + r32 Right = Width / 2.0f; + r32 Left = -Right; + r32 Top = Height / 2.0f; + r32 Bottom = -Top; + Result = M44ProjectionOrtho(Width, Height, Near, Far, Right, Left, Top, Bottom); + return Result; } internal m44 M44ProjectionInterfaceOrtho(r32 Width, r32 Height, r32 Near, r32 Far) { - m44 Result = {0}; - r32 Aspect = Width / Height; - r32 Right = Width; - r32 Left = 0; - r32 Top = Height; - r32 Bottom = 0; - Result = M44ProjectionOrtho(Width, Height, Near, Far, Right, Left, Top, Bottom); - return Result; + m44 Result = {0}; + r32 Aspect = Width / Height; + r32 Right = Width; + r32 Left = 0; + r32 Top = Height; + r32 Bottom = 0; + Result = M44ProjectionOrtho(Width, Height, Near, Far, Right, Left, Top, Bottom); + return Result; } internal m44 M44ProjectionPerspective(r32 FieldOfViewDegrees, r32 AspectRatio, r32 Near, r32 Far) { - m44 Result = M44Identity(); - - // The perspective divide step involves dividing x and y by -z - // Making Tz = -1 will make Tw of the result = -z - Result.Tw = 0; - Result.AZw = -1; - - // Remap z' from the range [near clip : far clip] to [0 : 1] - r32 ViewRange = Far - Near; - Result.AZz = -((Far + Near) / ViewRange); - Result.Tz = -(2 * Near * Far) / ViewRange; - - // Adjust for field of view - adjust the x' and y coordinates based - // on how - r32 FovBasedScale = TanR32(DegToRadR32(FieldOfViewDegrees / 2)); - r32 Top = Near * FovBasedScale; - r32 Bottom = -Top; - r32 Right = Top * AspectRatio; - r32 Left = -Right; - Result.AXx = (2 * Near) / (Right - Left); - Result.AZx = (Right + Left) / (Right - Left); - Result.AYy = (2 * Near) / (Top - Bottom); - Result.AZy = (Top + Bottom) / (Top - Bottom); - - return Result; + m44 Result = M44Identity(); + + // The perspective divide step involves dividing x and y by -z + // Making Tz = -1 will make Tw of the result = -z + Result.Tw = 0; + Result.AZw = -1; + + // Remap z' from the range [near clip : far clip] to [0 : 1] + r32 ViewRange = Far - Near; + Result.AZz = -((Far + Near) / ViewRange); + Result.Tz = -(2 * Near * Far) / ViewRange; + + // Adjust for field of view - adjust the x' and y coordinates based + // on how + r32 FovBasedScale = TanR32(DegToRadR32(FieldOfViewDegrees / 2)); + r32 Top = Near * FovBasedScale; + r32 Bottom = -Top; + r32 Right = Top * AspectRatio; + r32 Left = -Right; + Result.AXx = (2 * Near) / (Right - Left); + Result.AZx = (Right + Left) / (Right - Left); + Result.AYy = (2 * Near) / (Top - Bottom); + Result.AZy = (Top + Bottom) / (Top - Bottom); + + return Result; } internal m44 M44LookAt(v4 Position, v4 Target) { - // NOTE(Peter): the camera usually points along the -z axis, hence - // Forward = a ray that points from the target back towards your position - v4 Forward = V4Normalize(Position - Target); - v4 Right = V4Normalize(V4Cross(v4{0, 1, 0, 0}, Forward)); - v4 Up = V4Normalize(V4Cross(Forward, Right)); - m44 Result = M44CoordinateFrame(Forward, Right, Up); - return Result; + // NOTE(Peter): the camera usually points along the -z axis, hence + // Forward = a ray that points from the target back towards your position + v4 Forward = V4Normalize(Position - Target); + v4 Right = V4Normalize(V4Cross(v4{0, 1, 0, 0}, Forward)); + v4 Up = V4Normalize(V4Cross(Forward, Right)); + m44 Result = M44CoordinateFrame(Forward, Right, Up); + return Result; } /////////////////////////// @@ -1358,44 +1358,44 @@ internal gs_const_string ConstString(char* Data, u64 Length) { return gs_const_s internal gs_const_string ConstString(char* Data) { return gs_const_string{Data, CStringLength(Data)}; } internal gs_string MakeString(char* Data, u64 Length, u64 Size) { - Assert(Length <= Size); - gs_string Result = {0}; - Result.Str = Data; - Result.Length = Length; - Result.Size = Size; - return Result; + Assert(Length <= Size); + gs_string Result = {0}; + Result.Str = Data; + Result.Length = Length; + Result.Size = Size; + return Result; } internal gs_string MakeString(char* Data, u64 Length) { - return MakeString(Data, Length, Length); + return MakeString(Data, Length, Length); } internal gs_string MakeString(char* Data) { - u64 StringLength = CStringLength(Data); - return MakeString(Data, StringLength, StringLength); + u64 StringLength = CStringLength(Data); + return MakeString(Data, StringLength, StringLength); } internal gs_string MakeString(gs_const_string ConstString) { - return MakeString(ConstString.Str, ConstString.Length); + return MakeString(ConstString.Str, ConstString.Length); } internal gs_data StringToData(gs_const_string String) { - gs_data Result = gs_data{0}; - Result.Memory = (u8*)String.Str; - Result.Size = String.Length * sizeof(char); - return Result; + gs_data Result = gs_data{0}; + Result.Memory = (u8*)String.Str; + Result.Size = String.Length * sizeof(char); + return Result; } internal gs_data StringToData(gs_string String) { - return StringToData(String.ConstString); + return StringToData(String.ConstString); } internal gs_const_string DataToString(gs_data Data) { - gs_const_string Result = {}; - Result.Str = (char*)Data.Memory; - Result.Length = Data.Size; - return Result; + gs_const_string Result = {}; + Result.Str = (char*)Data.Memory; + Result.Length = Data.Size; + return Result; } internal bool IsSlash(char C) { return ((C == '/') || (C == '\\')); } @@ -1412,1002 +1412,1002 @@ internal bool IsNumericExtended(char C) { return IsNumericDecimal(C) || (C == 'x internal bool IsAlpha(char C) { return( (('a' <= C) && (C <= 'z')) || (('A' <= C) && (C <= 'Z')) || C == '_'); } internal bool IsAlphaNumeric(char C) { return((('a' <= C) && (C <= 'z')) || (('A' <= C) && (C <= 'Z')) || (('0' <= C) && (C <= '9')) || C == '_'); } internal bool IsOperator(char C) { - return ((C == '+') || (C == '-') || (C == '*') || (C == '/') || - (C == '=') || (C == '%') || (C == '<') || (C == '>')); + return ((C == '+') || (C == '-') || (C == '*') || (C == '/') || + (C == '=') || (C == '%') || (C == '<') || (C == '>')); } internal char ToUpper(char C) { - if ((C >= 'a') && (C <= 'z')) - { - C -= 'a' - 'A'; - } - return C; + if ((C >= 'a') && (C <= 'z')) + { + C -= 'a' - 'A'; + } + return C; } internal char ToLower(char C) { - if ((C >= 'A') && (C <= 'Z')) - { - C += 'a' - 'A'; - } - return C; + if ((C >= 'A') && (C <= 'Z')) + { + C += 'a' - 'A'; + } + return C; } internal bool CharsEqualCaseInsensitive(char A, char B) { return ToLower(A) == ToLower(B); } internal u64 CharArrayLength (char* CS) { - char* At = CS; - while (*At) { At++; } - return (u64)(At - CS); + char* At = CS; + while (*At) { At++; } + return (u64)(At - CS); } internal bool IsNullTerminated(gs_const_string String) { - bool Result = false; - if (String.Str) - { - Result = (String.Str[String.Length] == 0); - } - return Result; + bool Result = false; + if (String.Str) + { + Result = (String.Str[String.Length] == 0); + } + return Result; } internal bool IsNullTerminated(gs_string String) { - return IsNullTerminated(String.ConstString); + return IsNullTerminated(String.ConstString); } internal char GetChar(gs_const_string String, u64 I) { - char Result = 0; - if (I < String.Length) - { - Result = String.Str[I]; - } - return Result; + char Result = 0; + if (I < String.Length) + { + Result = String.Str[I]; + } + return Result; } internal char GetChar(gs_string String, u64 I) { - char Result = 0; - if (I < String.Length) - { - Result = String.Str[I]; - } - return Result; + char Result = 0; + if (I < String.Length) + { + Result = String.Str[I]; + } + return Result; } internal gs_const_string GetStringPrefix(gs_const_string String, u64 Size) { - gs_const_string Result = String; - Result.Length = Min(Size, String.Length); - return Result; + gs_const_string Result = String; + Result.Length = Min(Size, String.Length); + return Result; } internal gs_const_string GetStringPostfix(gs_const_string String, u64 Size) { - gs_const_string Result = String; - u64 PostfixSize = Min(Size, String.Length); - Result.Str += (Result.Length - PostfixSize); - Result.Length = PostfixSize; - return Result; + gs_const_string Result = String; + u64 PostfixSize = Min(Size, String.Length); + Result.Str += (Result.Length - PostfixSize); + Result.Length = PostfixSize; + return Result; } internal gs_const_string GetStringAfter(gs_const_string String, u64 Cut) { - gs_const_string Result = String; - u64 CutSize = Min(Cut, String.Length); - Result.Str += CutSize; - Result.Length -= CutSize; - return Result; + gs_const_string Result = String; + u64 CutSize = Min(Cut, String.Length); + Result.Str += CutSize; + Result.Length -= CutSize; + return Result; } internal gs_string GetStringAfter(gs_string String, u64 Cut) { - gs_string Result = {0}; - Result.ConstString = GetStringAfter(String.ConstString, Cut); - Result.Size = String.Size - Cut; - return Result; + gs_string Result = {0}; + Result.ConstString = GetStringAfter(String.ConstString, Cut); + Result.Size = String.Size - Cut; + return Result; } internal gs_const_string GetStringBefore(gs_const_string String, u64 Cut) { - gs_const_string Result = String; - Result.Length = Min(Cut, String.Length); - return Result; + gs_const_string Result = String; + Result.Length = Min(Cut, String.Length); + return Result; } internal gs_const_string Substring(gs_const_string String, u64 First, u64 Last) { - gs_const_string Result = {0}; - Result.Str = String.Str + Min(First, String.Length); - Result.Length = Min(Last - First, String.Length); - return Result; + gs_const_string Result = {0}; + Result.Str = String.Str + Min(First, String.Length); + Result.Length = Min(Last - First, String.Length); + return Result; } internal gs_const_string Substring(gs_string String, u64 First, u64 Last) { - return Substring(String.ConstString, First, Last); + return Substring(String.ConstString, First, Last); } internal s64 FindFirst(gs_const_string String, u64 StartIndex, char C) { - s64 Result = -1; - for(u64 i = StartIndex; i < String.Length; i++) - { - if (String.Str[i] == C) { - Result = (s64)i; - break; - } + s64 Result = -1; + for(u64 i = StartIndex; i < String.Length; i++) + { + if (String.Str[i] == C) { + Result = (s64)i; + break; } - return Result; + } + return Result; } internal s64 FindFirst(gs_const_string String, char C) { - return FindFirst(String, 0, C); + return FindFirst(String, 0, C); } internal s64 FindFirst(gs_string String, u64 StartIndex, char C) { - return FindFirst(String.ConstString, StartIndex, C); + return FindFirst(String.ConstString, StartIndex, C); } internal s64 FindFirst(gs_string String, char C) { - return FindFirst(String.ConstString, 0, C); + return FindFirst(String.ConstString, 0, C); } internal s64 FindLast(char* String, s64 StartIndex, char C) { - s64 Result = -1; - s64 i = 0; - while (String[i] != 0 && i < StartIndex) + s64 Result = -1; + s64 i = 0; + while (String[i] != 0 && i < StartIndex) + { + i++; + } + while (String[i]) + { + if (String[i] == C) { - i++; + Result = i; } - while (String[i]) - { - if (String[i] == C) - { - Result = i; - } - i++; - } - return Result; + i++; + } + return Result; } internal s64 FindLast(gs_const_string String, u64 StartIndex, char C) { - s64 Result = -1; - for(s64 i= StartIndex; i >= 0; i--) - { - if (String.Str[i] == C) { - Result = i; - break; - } + s64 Result = -1; + for(s64 i= StartIndex; i >= 0; i--) + { + if (String.Str[i] == C) { + Result = i; + break; } - return (u64)Result; + } + return (u64)Result; } internal s64 FindLast(gs_const_string String, char C) { - return FindLast(String, String.Length - 1, C); + return FindLast(String, String.Length - 1, C); } internal s64 FindLast(gs_string String, u64 StartIndex, char C) { - return FindLast(String.ConstString, StartIndex, C); + return FindLast(String.ConstString, StartIndex, C); } internal s64 FindLast(gs_string String, char C) { - return FindLast(String.ConstString, String.Length - 1, C); + return FindLast(String.ConstString, String.Length - 1, C); } internal s64 FindFirstFromSet(gs_const_string String, char* SetArray) { - gs_const_string Set = ConstString(SetArray); - s64 Result = -1; - - s64 CurrMin = String.Length; - for (u64 SetAt = 0; SetAt < Set.Length; SetAt++) + gs_const_string Set = ConstString(SetArray); + s64 Result = -1; + + s64 CurrMin = String.Length; + for (u64 SetAt = 0; SetAt < Set.Length; SetAt++) + { + s64 Index = FindFirst(String, Set.Str[SetAt]); + if (Index >= 0 && Index < CurrMin) { - s64 Index = FindFirst(String, Set.Str[SetAt]); - if (Index >= 0 && Index < CurrMin) - { - CurrMin = Index; - } + CurrMin = Index; } - - if (CurrMin < (s64)String.Length) - { - Result = CurrMin; - } - - return Result; + } + + if (CurrMin < (s64)String.Length) + { + Result = CurrMin; + } + + return Result; } internal s64 FindLastFromSet(gs_const_string String, char* SetArray) { - gs_const_string Set = ConstString(SetArray); - s64 Result = -1; - for(s64 At = String.Length - 1; At >= 0; At--) + gs_const_string Set = ConstString(SetArray); + s64 Result = -1; + for(s64 At = String.Length - 1; At >= 0; At--) + { + char CharAt = String.Str[At]; + for (u64 SetAt = 0; SetAt < Set.Length; SetAt++) { - char CharAt = String.Str[At]; - for (u64 SetAt = 0; SetAt < Set.Length; SetAt++) - { - if (CharAt == Set.Str[SetAt]) - { - Result = (u64)At; - // NOTE(Peter): The alternative to this goto is a break in the inner loop - // followed by an if check in the outer loop, that must be evaluated - // every character you check. This is more efficient - goto find_first_from_set_complete; - } - } + if (CharAt == Set.Str[SetAt]) + { + Result = (u64)At; + // NOTE(Peter): The alternative to this goto is a break in the inner loop + // followed by an if check in the outer loop, that must be evaluated + // every character you check. This is more efficient + goto find_first_from_set_complete; + } } - find_first_from_set_complete: - return Result; + } + find_first_from_set_complete: + return Result; } internal bool StringContains(gs_const_string Str, char C) { - bool Result = false; - for (u32 i = 0; i < Str.Length; i++) + bool Result = false; + for (u32 i = 0; i < Str.Length; i++) + { + if (Str.Str[i] == C) { - if (Str.Str[i] == C) - { - Result = true; - break; - } + Result = true; + break; } - return Result; + } + return Result; } internal bool StringsEqualUpToLength(gs_const_string A, gs_const_string B, u64 Length) { - bool Result = false; - if (A.Length >= Length && B.Length >= Length) + bool Result = false; + if (A.Length >= Length && B.Length >= Length) + { + Result = true; + Length = Min(Length, A.Length); + for (u64 i = 0; i < Length; i++) { - Result = true; - Length = Min(Length, A.Length); - for (u64 i = 0; i < Length; i++) - { - if (A.Str[i] != B.Str[i]) - { - Result = false; - break; - } - } + if (A.Str[i] != B.Str[i]) + { + Result = false; + break; + } } - return Result; + } + return Result; } internal bool StringsEqual(gs_const_string A, gs_const_string B) { - bool Result = false; - if (A.Length == B.Length) - { - Result = StringsEqualUpToLength(A, B, A.Length); - } - return Result; + bool Result = false; + if (A.Length == B.Length) + { + Result = StringsEqualUpToLength(A, B, A.Length); + } + return Result; } internal bool StringEqualsCharArray(gs_const_string A, char* B, u64 Length) { - gs_const_string BStr = ConstString(B, Length); - return StringsEqual(A, BStr); + gs_const_string BStr = ConstString(B, Length); + return StringsEqual(A, BStr); } internal bool StringEqualsCharArray(gs_const_string A, char* B) { - u64 Length = CStringLength(B); - return StringEqualsCharArray(A, B, Length); + u64 Length = CStringLength(B); + return StringEqualsCharArray(A, B, Length); } internal bool StringsEqualUpToLength(gs_string A, gs_string B, u64 Length) { - return StringsEqualUpToLength(A.ConstString, B.ConstString, Length); + return StringsEqualUpToLength(A.ConstString, B.ConstString, Length); } internal bool StringsEqual(gs_string A, gs_string B) { - return StringsEqual(A.ConstString, B.ConstString); + return StringsEqual(A.ConstString, B.ConstString); } internal bool StringEqualsCharArray(gs_string A, char* B, u64 Length) { - return StringEqualsCharArray(A.ConstString, B, Length); + return StringEqualsCharArray(A.ConstString, B, Length); } internal bool StringEqualsCharArray(gs_string A, char* B) { - return StringEqualsCharArray(A.ConstString, B); + return StringEqualsCharArray(A.ConstString, B); } internal u64 StringSizeLeft(gs_string String) { - u64 Result = String.Size - String.Length; - return Result; + u64 Result = String.Size - String.Length; + return Result; } internal void ReverseStringInPlace(gs_string* String) { - char* Start = String->Str; - char* End = String->Str + String->Length; - while (Start < End) - { - End--; - char Temp = End[0]; - End[0] = Start[0]; - Start[0] = Temp; - Start++; - } + char* Start = String->Str; + char* End = String->Str + String->Length; + while (Start < End) + { + End--; + char Temp = End[0]; + End[0] = Start[0]; + Start[0] = Temp; + Start++; + } } internal gs_const_string GetCharSetForBase(u64 Base) { - gs_const_string Result = {0}; - switch(Base) - { - case 8: { Result = Base8Chars; }break; - case 10: { Result = Base10Chars; }break; - case 16: { Result = Base16Chars; }break; - InvalidDefaultCase; - } - return Result; + gs_const_string Result = {0}; + switch(Base) + { + case 8: { Result = Base8Chars; }break; + case 10: { Result = Base10Chars; }break; + case 16: { Result = Base16Chars; }break; + InvalidDefaultCase; + } + return Result; } internal u64 CharToUInt(char C, gs_const_string CharSet) { - return (u64)FindFirst(CharSet, C); + return (u64)FindFirst(CharSet, C); } internal u64 CharToUInt(char C) { - return (u64)CharToUInt(C, Base10Chars); + return (u64)CharToUInt(C, Base10Chars); } internal u64 CharToUInt(char C, u64 Base) { - return CharToUInt(C, GetCharSetForBase(Base)); + return CharToUInt(C, GetCharSetForBase(Base)); } struct parse_uint_result { - b8 Success; - u64 Value; - u32 ParsedLength; + b8 Success; + u64 Value; + u32 ParsedLength; }; internal parse_uint_result ValidateAndParseUInt(gs_const_string String, u64 Base = 10) { - parse_uint_result Result = {0}; - - gs_const_string CharSet = GetCharSetForBase(Base); - - bool StringIsValid = true; - for (u32 i = 0; i < String.Length; i++) + parse_uint_result Result = {0}; + + gs_const_string CharSet = GetCharSetForBase(Base); + + bool StringIsValid = true; + for (u32 i = 0; i < String.Length; i++) + { + if (!StringContains(CharSet, String.Str[i])) { - if (!StringContains(CharSet, String.Str[i])) - { - StringIsValid = false; - break; - } + StringIsValid = false; + break; + } + } + + if (StringIsValid) + { + u64 Acc = 0; + u64 i = 0; + for (; i < String.Length; i++) + { + u64 CharIndex = FindFirst(CharSet, String.Str[i]); + if (CharIndex < CharSet.Length) + { + Acc = CharToUInt(String.Str[i], CharSet) + (Acc * Base); + } + else + { + break; + } } - if (StringIsValid) - { - u64 Acc = 0; - u64 i = 0; - for (; i < String.Length; i++) - { - u64 CharIndex = FindFirst(CharSet, String.Str[i]); - if (CharIndex < CharSet.Length) - { - Acc = CharToUInt(String.Str[i], CharSet) + (Acc * Base); - } - else - { - break; - } - } - - Result.Success = true; - Result.Value = Acc; - Result.ParsedLength = i; - } - - return Result; + Result.Success = true; + Result.Value = Acc; + Result.ParsedLength = i; + } + + return Result; } internal u64 ParseUInt(gs_const_string String, u64 Base = 10, u64* ParsedLength = 0) { - parse_uint_result ParseResult = ValidateAndParseUInt(String, Base); - Assert(ParseResult.Success); - if (ParsedLength) - { - *ParsedLength = ParseResult.ParsedLength; - } - return ParseResult.Value; + parse_uint_result ParseResult = ValidateAndParseUInt(String, Base); + Assert(ParseResult.Success); + if (ParsedLength) + { + *ParsedLength = ParseResult.ParsedLength; + } + return ParseResult.Value; } internal u64 ParseUInt(u64 Length, char* String, u64 Base = 10, u64* ParsedLength = 0) { - return ParseUInt(ConstString(String, Length), Base, ParsedLength); + return ParseUInt(ConstString(String, Length), Base, ParsedLength); } internal u64 ParseUInt(char* String, u64 Base = 10, u64* ParsedLength = 0) { - return ParseUInt(LitString(String), Base, ParsedLength); + return ParseUInt(LitString(String), Base, ParsedLength); } internal s64 ParseInt(gs_const_string String, u64 Base = 10, u64* ParsedLength = 0) { - s64 Result = 0; - u64 TempParsedLength = 0; - if (String.Str[0] == '-') - { - Result = -1 * (s64)ParseUInt(GetStringAfter(String, 1), Base, &TempParsedLength); - TempParsedLength += 1; - } - else - { - Result = (s64)ParseUInt(String, Base, &TempParsedLength); - } - if (ParsedLength != 0) - { - *ParsedLength = TempParsedLength; - } - return Result; + s64 Result = 0; + u64 TempParsedLength = 0; + if (String.Str[0] == '-') + { + Result = -1 * (s64)ParseUInt(GetStringAfter(String, 1), Base, &TempParsedLength); + TempParsedLength += 1; + } + else + { + Result = (s64)ParseUInt(String, Base, &TempParsedLength); + } + if (ParsedLength != 0) + { + *ParsedLength = TempParsedLength; + } + return Result; } internal s64 ParseInt(char* String, u64 Base = 10, u64* ParsedLength = 0) { - return ParseInt(LitString(String), Base, ParsedLength); + return ParseInt(LitString(String), Base, ParsedLength); } struct parse_float_result { - b8 Success; - r64 Value; - u64 ParsedLength; + b8 Success; + r64 Value; + u64 ParsedLength; }; internal parse_float_result ValidateAndParseFloat(gs_const_string String) { - parse_float_result Result = {0}; - Result.Success = false; - - // Validate - bool StringIsValid = true; - for (u64 i = 0; i < String.Length; i++) + parse_float_result Result = {0}; + Result.Success = false; + + // Validate + bool StringIsValid = true; + for (u64 i = 0; i < String.Length; i++) + { + if (!IsNumericDecimal(String.Str[i]) && String.Str[i] != '-') { - if (!IsNumericDecimal(String.Str[i]) && String.Str[i] != '-') - { - StringIsValid = false; - break; - } + StringIsValid = false; + break; + } + } + + if (StringIsValid) + { + s64 DecimalIndex = FindFirst(String, '.'); + u64 TempParsedLength = 0; + u64 PlacesAfterPoint = 0; + + gs_const_string IntegerString = GetStringBefore(String, DecimalIndex); + gs_const_string DecimalString = {}; + if (DecimalIndex >= 0) + { + DecimalString = GetStringAfter(String, DecimalIndex + 1); } - if (StringIsValid) + r32 Polarity = 1; + if (IntegerString.Str[0] == '-') { - s64 DecimalIndex = FindFirst(String, '.'); - u64 TempParsedLength = 0; - u64 PlacesAfterPoint = 0; - - gs_const_string IntegerString = GetStringBefore(String, DecimalIndex); - gs_const_string DecimalString = {}; - if (DecimalIndex >= 0) - { - DecimalString = GetStringAfter(String, DecimalIndex + 1); - } - - r32 Polarity = 1; - if (IntegerString.Str[0] == '-') - { - IntegerString = GetStringAfter(IntegerString, 1); - Polarity = -1; - } - - Result.Value = (r64)ParseInt(IntegerString, 10, &TempParsedLength); - - if (TempParsedLength == IntegerString.Length) - { - r64 AfterPoint = (r64)ParseUInt(DecimalString, 10, &PlacesAfterPoint); - r64 Decimal = (AfterPoint / PowR64(10, PlacesAfterPoint)); - Result.Value = Result.Value + Decimal; - Result.Value *= Polarity; - } - - Result.ParsedLength = TempParsedLength + PlacesAfterPoint; - if (DecimalIndex < (s64)String.Length) { Result.ParsedLength += 1; } - - Result.Success = true; + IntegerString = GetStringAfter(IntegerString, 1); + Polarity = -1; } - return Result; + Result.Value = (r64)ParseInt(IntegerString, 10, &TempParsedLength); + + if (TempParsedLength == IntegerString.Length) + { + r64 AfterPoint = (r64)ParseUInt(DecimalString, 10, &PlacesAfterPoint); + r64 Decimal = (AfterPoint / PowR64(10, PlacesAfterPoint)); + Result.Value = Result.Value + Decimal; + Result.Value *= Polarity; + } + + Result.ParsedLength = TempParsedLength + PlacesAfterPoint; + if (DecimalIndex < (s64)String.Length) { Result.ParsedLength += 1; } + + Result.Success = true; + } + + return Result; } internal r64 ParseFloat(gs_const_string String, u64* ParsedLength = 0) { - parse_float_result Result = ValidateAndParseFloat(String); - Assert(Result.Success); - if (ParsedLength != 0) - { - *ParsedLength = Result.ParsedLength; - } - return Result.Value; + parse_float_result Result = ValidateAndParseFloat(String); + Assert(Result.Success); + if (ParsedLength != 0) + { + *ParsedLength = Result.ParsedLength; + } + return Result.Value; } internal r64 ParseFloat(char* String, u64* ParsedLength = 0) { - return ParseFloat(LitString(String), ParsedLength); + return ParseFloat(LitString(String), ParsedLength); } internal u64 AppendString(gs_string* Base, gs_const_string Appendix) { - u64 StartIndex = Base->Length; - u64 LengthAvailable = Base->Size - Base->Length; - u64 Written = 0; - for (; Written < Min(LengthAvailable, Appendix.Length); Written++) - { - Base->Str[StartIndex + Written] = Appendix.Str[Written]; - } - Base->Length += Written; - Assert(Base->Length <= Base->Size); - return Written; + u64 StartIndex = Base->Length; + u64 LengthAvailable = Base->Size - Base->Length; + u64 Written = 0; + for (; Written < Min(LengthAvailable, Appendix.Length); Written++) + { + Base->Str[StartIndex + Written] = Appendix.Str[Written]; + } + Base->Length += Written; + Assert(Base->Length <= Base->Size); + return Written; } internal u64 AppendString(gs_string* Base, gs_string Appendix) { - return AppendString(Base, Appendix.ConstString); + return AppendString(Base, Appendix.ConstString); } internal void InsertAt(gs_string* Str, u64 Index, char C) { - if (Str->Length > Index) + if (Str->Length > Index) + { + for (u64 i = Str->Length; i > Index; i--) { - for (u64 i = Str->Length; i > Index; i--) - { - Str->Str[i] = Str->Str[i - 1]; - } - } - - if (Index < Str->Size) - { - Str->Str[Index] = C; - Str->Length += 1; - Assert(Str->Length < Str->Size); + Str->Str[i] = Str->Str[i - 1]; } + } + + if (Index < Str->Size) + { + Str->Str[Index] = C; + Str->Length += 1; + Assert(Str->Length < Str->Size); + } } internal void RemoveAt(gs_string* Str, u64 Index) { - if (Str->Length > 0 && Index < Str->Length) + if (Str->Length > 0 && Index < Str->Length) + { + for (u64 i = Index; i < Str->Length - 1; i++) { - for (u64 i = Index; i < Str->Length - 1; i++) - { - Str->Str[i] = Str->Str[i + 1]; - } - Str->Length -= 1; + Str->Str[i] = Str->Str[i + 1]; } + Str->Length -= 1; + } } internal void NullTerminate(gs_string* String) { - if (String->Length < String->Size) - { - String->Str[String->Length] = 0; - } - else - { - String->Str[String->Length - 1] = 0; - } + if (String->Length < String->Size) + { + String->Str[String->Length] = 0; + } + else + { + String->Str[String->Length - 1] = 0; + } } internal void OutChar(gs_string* String, char C) { - if (String->Length < String->Size) - { - String->Str[String->Length++] = C; - } + if (String->Length < String->Size) + { + String->Str[String->Length++] = C; + } } internal void U64ToASCII(gs_string* String, u64 Value, u64 Base, gs_const_string Digits) { - u64 ValueRemaining = Value; - u64 At = 0; - do { - u64 Index = ValueRemaining % Base; - char Digit = Digits.Str[Index]; - OutChar(String, Digit); - ValueRemaining /= Base; - }while(ValueRemaining); - char* End = String->Str + String->Length; - ReverseStringInPlace(String); + u64 ValueRemaining = Value; + u64 At = 0; + do { + u64 Index = ValueRemaining % Base; + char Digit = Digits.Str[Index]; + OutChar(String, Digit); + ValueRemaining /= Base; + }while(ValueRemaining); + char* End = String->Str + String->Length; + ReverseStringInPlace(String); } internal void U64ToASCII(gs_string* String, u64 Value, u64 Base) { - U64ToASCII(String, Value, Base, GetCharSetForBase(Base)); + U64ToASCII(String, Value, Base, GetCharSetForBase(Base)); } internal void R64ToASCII(gs_string* String, r64 Value, u64 Precision) { - if (Value < 0) + if (Value < 0) + { + OutChar(String, '-'); + Value = Abs(Value); + } + u64 IntegerPart = (u64)Value; + // NOTE(Peter): If we don't use the inner string, when U64ToASCII reverses the characters + // it'll put the negative sign at the end. + gs_string IntegerString = GetStringAfter(*String, String->Length); + U64ToASCII(&IntegerString, IntegerPart, 10); + String->Length += IntegerString.Length; + Value -= IntegerPart; + if (Value > 0) + { + OutChar(String, '.'); + for (u64 i = 0; i < Precision; i++) { - OutChar(String, '-'); - Value = Abs(Value); - } - u64 IntegerPart = (u64)Value; - // NOTE(Peter): If we don't use the inner string, when U64ToASCII reverses the characters - // it'll put the negative sign at the end. - gs_string IntegerString = GetStringAfter(*String, String->Length); - U64ToASCII(&IntegerString, IntegerPart, 10); - String->Length += IntegerString.Length; - Value -= IntegerPart; - if (Value > 0) - { - OutChar(String, '.'); - for (u64 i = 0; i < Precision; i++) - { - Value *= 10.0f; - u64 DecimalPlace = (u64)Value; - Value -= DecimalPlace; - OutChar(String, Base10Chars.Str[DecimalPlace]); - } + Value *= 10.0f; + u64 DecimalPlace = (u64)Value; + Value -= DecimalPlace; + OutChar(String, Base10Chars.Str[DecimalPlace]); } + } } internal s64 ReadVarArgsSignedInteger (s32 Width, va_list* Args) { - s64 Result = 0; - switch (Width) - { - // NOTE(Peter): For Width lower than 4 bytes, the C++ spec specifies - // that it will get promoted to an int anyways - case 1: { Result = (s64)va_arg(*Args, s32); } break; - case 2: { Result = (s64)va_arg(*Args, s32); } break; - case 4: { Result = (s64)va_arg(*Args, s32); } break; - case 8: { Result = (s64)va_arg(*Args, s64); } break; - InvalidDefaultCase; - } - return Result; + s64 Result = 0; + switch (Width) + { + // NOTE(Peter): For Width lower than 4 bytes, the C++ spec specifies + // that it will get promoted to an int anyways + case 1: { Result = (s64)va_arg(*Args, s32); } break; + case 2: { Result = (s64)va_arg(*Args, s32); } 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) - { - // NOTE(Peter): For Width lower than 4 bytes, the C++ spec specifies - // that it will get promoted to an int anyways - case 1: { Result = (u64)va_arg(*Args, u32); } break; - case 2: { Result = (u64)va_arg(*Args, u32); } break; - case 4: { Result = (u64)va_arg(*Args, u32); } break; - case 8: { Result = (u64)va_arg(*Args, u64); } break; - InvalidDefaultCase; - } - return Result; + u64 Result = 0; + switch (Width) + { + // NOTE(Peter): For Width lower than 4 bytes, the C++ spec specifies + // that it will get promoted to an int anyways + case 1: { Result = (u64)va_arg(*Args, u32); } break; + case 2: { Result = (u64)va_arg(*Args, u32); } 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; + 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 (gs_string* String, char* Format, va_list Args) { - char* FormatAt = Format; - while (*FormatAt) + char* FormatAt = Format; + while (*FormatAt) + { + if (FormatAt[0] != '%') { - if (FormatAt[0] != '%') - { - if (FormatAt[0] == '\\') - { - OutChar(String, *FormatAt++); - } - else - { - OutChar(String, *FormatAt++); - } - } - else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol - { - OutChar(String, '%'); - FormatAt += 2; - } - 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 (IsBase10(FormatAt[0])) - { - WidthSpecified = true; - u64 Parsed = 0; - AssertMessage("ParseInt assumes whole string is an integer"); - Width = (s32)ParseInt(FormatAt, 10, &Parsed); - FormatAt += Parsed; - } - 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 (IsBase10(FormatAt[0])) - { - PrecisionSpecified = true; - - gs_const_string PrecisionStr = {}; - PrecisionStr.Str = FormatAt; - for (char* C = FormatAt; *FormatAt && IsBase10(*C); C++) - { - PrecisionStr.Length++; - } - u64 Parsed = 0; - Precision = (s32)ParseInt(PrecisionStr, 10, &Parsed); - FormatAt += Parsed; - } - 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; - Length = 1; - FormatAt += 2; - } - else if (FormatAt[0] == 'h') - { - LengthSpecified = true; - Length = 2; - FormatAt++; - } - else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') - { - LengthSpecified = true; - Length = 8; - FormatAt += 2; - } - else if (FormatAt[0] == 'l') - { - LengthSpecified = true; - Length = 4; - FormatAt++; - } - else if (FormatAt[0] == 'j') - { - LengthSpecified = true; - Length = 8; - FormatAt++; - } - else if (FormatAt[0] == 'z') - { - FormatAt++; - } - else if (FormatAt[0] == 't') - { - FormatAt++; - } - else if (FormatAt[0] == 'L') - { - FormatAt++; - } - - // Format Specifiers - gs_string StringRemaining = GetStringAfter(*String, String->Length); - Assert(StringRemaining.Length == 0); - if (FormatAt[0] == 'd' || FormatAt[0] == 'i') - { - s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); - if (SignedInt < 0) - { - OutChar(&StringRemaining, '-'); - SignedInt *= -1; - } - U64ToASCII(&StringRemaining, (u64)SignedInt, 10, Base10Chars); - } - else if (FormatAt[0] == 'u') - { - u64 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&StringRemaining, UnsignedInt, 10, Base10Chars); - } - else if (FormatAt[0] == 'o') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&StringRemaining, UnsignedInt, 8, Base8Chars); - } - else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&StringRemaining, UnsignedInt, 16, Base16Chars); - } - else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') - { - r64 Float = ReadVarArgsFloat(Length, &Args); - s32 AfterPoint = 6; - if (PrecisionSpecified) - { - AfterPoint = Precision; - } - R64ToASCII(&StringRemaining, Float, AfterPoint); - } - else if (FormatAt[0] == 'c') - { - char InsertChar = va_arg(Args, s32); - OutChar(&StringRemaining, InsertChar); - } - else if (FormatAt[0] == 's') - { - char* InsertString = va_arg(Args, char*); - - s32 InsertStringLength = CStringLength(InsertString); - if (PrecisionSpecified) - { - InsertStringLength = Min(InsertStringLength, Precision); - } - InsertStringLength = Min(StringSizeLeft(StringRemaining), InsertStringLength); - - for (s32 c = 0; c < InsertStringLength; c++) - { - OutChar(&StringRemaining, InsertString[c]); - } - } - else if (FormatAt[0] == 'S') - { - gs_const_string InsertString = va_arg(Args, gs_const_string); - - for (s32 c = 0; c < InsertString.Length; c++) - { - OutChar(&StringRemaining, InsertString.Str[c]); - } - } - else if (FormatAt[0] == 'p') - { - // TODO(Peter): Pointer Address - } - else - { - // NOTE(Peter): Non-specifier character found - InvalidCodePath; - } - - String->Length += StringRemaining.Length; - FormatAt++; - } + if (FormatAt[0] == '\\') + { + OutChar(String, *FormatAt++); + } + else + { + OutChar(String, *FormatAt++); + } } - - return String->Length; + else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol + { + OutChar(String, '%'); + FormatAt += 2; + } + 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 (IsBase10(FormatAt[0])) + { + WidthSpecified = true; + u64 Parsed = 0; + AssertMessage("ParseInt assumes whole string is an integer"); + Width = (s32)ParseInt(FormatAt, 10, &Parsed); + FormatAt += Parsed; + } + 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 (IsBase10(FormatAt[0])) + { + PrecisionSpecified = true; + + gs_const_string PrecisionStr = {}; + PrecisionStr.Str = FormatAt; + for (char* C = FormatAt; *FormatAt && IsBase10(*C); C++) + { + PrecisionStr.Length++; + } + u64 Parsed = 0; + Precision = (s32)ParseInt(PrecisionStr, 10, &Parsed); + FormatAt += Parsed; + } + 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; + Length = 1; + FormatAt += 2; + } + else if (FormatAt[0] == 'h') + { + LengthSpecified = true; + Length = 2; + FormatAt++; + } + else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') + { + LengthSpecified = true; + Length = 8; + FormatAt += 2; + } + else if (FormatAt[0] == 'l') + { + LengthSpecified = true; + Length = 4; + FormatAt++; + } + else if (FormatAt[0] == 'j') + { + LengthSpecified = true; + Length = 8; + FormatAt++; + } + else if (FormatAt[0] == 'z') + { + FormatAt++; + } + else if (FormatAt[0] == 't') + { + FormatAt++; + } + else if (FormatAt[0] == 'L') + { + FormatAt++; + } + + // Format Specifiers + gs_string StringRemaining = GetStringAfter(*String, String->Length); + Assert(StringRemaining.Length == 0); + if (FormatAt[0] == 'd' || FormatAt[0] == 'i') + { + s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); + if (SignedInt < 0) + { + OutChar(&StringRemaining, '-'); + SignedInt *= -1; + } + U64ToASCII(&StringRemaining, (u64)SignedInt, 10, Base10Chars); + } + else if (FormatAt[0] == 'u') + { + u64 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 10, Base10Chars); + } + else if (FormatAt[0] == 'o') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 8, Base8Chars); + } + else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 16, Base16Chars); + } + else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') + { + r64 Float = ReadVarArgsFloat(Length, &Args); + s32 AfterPoint = 6; + if (PrecisionSpecified) + { + AfterPoint = Precision; + } + R64ToASCII(&StringRemaining, Float, AfterPoint); + } + else if (FormatAt[0] == 'c') + { + char InsertChar = va_arg(Args, s32); + OutChar(&StringRemaining, InsertChar); + } + else if (FormatAt[0] == 's') + { + char* InsertString = va_arg(Args, char*); + + s32 InsertStringLength = CStringLength(InsertString); + if (PrecisionSpecified) + { + InsertStringLength = Min(InsertStringLength, Precision); + } + InsertStringLength = Min(StringSizeLeft(StringRemaining), InsertStringLength); + + for (s32 c = 0; c < InsertStringLength; c++) + { + OutChar(&StringRemaining, InsertString[c]); + } + } + else if (FormatAt[0] == 'S') + { + gs_const_string InsertString = va_arg(Args, gs_const_string); + + for (s32 c = 0; c < InsertString.Length; c++) + { + OutChar(&StringRemaining, InsertString.Str[c]); + } + } + else if (FormatAt[0] == 'p') + { + // TODO(Peter): Pointer Address + } + else + { + // NOTE(Peter): Non-specifier character found + InvalidCodePath; + } + + String->Length += StringRemaining.Length; + FormatAt++; + } + } + + return String->Length; } internal void PrintF (gs_string* String, char* Format, ...) { - va_list Args; - va_start(Args, Format); - String->Length = 0; - PrintFArgsList(String, Format, Args); - va_end(Args); + va_list Args; + va_start(Args, Format); + String->Length = 0; + PrintFArgsList(String, Format, Args); + va_end(Args); } internal void PrintF (gs_string* String, const char* Format, ...) { - // NOTE(Peter): This variant is here for clang/gcc - C++ spec doesn't allow - // implicit conversion from a const char* (a static c string) to char*, so this - // version of the function just provides the conversion so the compiler will be quiet - // without removing the other implementation, which is more useful - va_list Args; - va_start(Args, Format); - String->Length = 0; - PrintFArgsList(String, (char*)Format, Args); - va_end(Args); + // NOTE(Peter): This variant is here for clang/gcc - C++ spec doesn't allow + // implicit conversion from a const char* (a static c string) to char*, so this + // version of the function just provides the conversion so the compiler will be quiet + // without removing the other implementation, which is more useful + va_list Args; + va_start(Args, Format); + String->Length = 0; + PrintFArgsList(String, (char*)Format, Args); + va_end(Args); } internal void AppendPrintF (gs_string* String, char* Format, ...) { - va_list Args; - va_start(Args, Format); - PrintFArgsList(String, Format, Args); - va_end(Args); + va_list Args; + va_start(Args, Format); + PrintFArgsList(String, Format, Args); + va_end(Args); } internal void AppendPrintF (gs_string* String, const char* Format, ...) { - // NOTE(Peter): This variant is here for clang/gcc - C++ spec doesn't allow - // implicit conversion from a const char* (a static c string) to char*, so this - // version of the function just provides the conversion so the compiler will be quiet - // without removing the other implementation, which is more useful - va_list Args; - va_start(Args, Format); - PrintFArgsList(String, (char*)Format, Args); - va_end(Args); + // NOTE(Peter): This variant is here for clang/gcc - C++ spec doesn't allow + // implicit conversion from a const char* (a static c string) to char*, so this + // version of the function just provides the conversion so the compiler will be quiet + // without removing the other implementation, which is more useful + va_list Args; + va_start(Args, Format); + PrintFArgsList(String, (char*)Format, Args); + va_end(Args); } /////////////////////////// @@ -2417,436 +2417,44 @@ AppendPrintF (gs_string* String, const char* Format, ...) internal gs_data CreateData(u8* Memory, u64 Size) { - gs_data Result = {Memory, Size}; - return Result; + gs_data Result = {Memory, Size}; + return Result; } internal bool DataIsNonEmpty(gs_data Data) { - return ((Data.Size > 0) && (Data.Memory != 0)); + return ((Data.Size > 0) && (Data.Memory != 0)); } -internal void* AllocatorAlloc_NoOp(u64 Size, u64* SizeResult) { - *SizeResult = 0; - return 0; -} -internal void AllocatorFree_NoOp(void* Base, u64 Size) { return; } - -internal gs_allocator -CreateAllocator_(allocator_allocate* Alloc, allocator_free* Free) -{ - if (Alloc == 0) - { - Alloc = AllocatorAlloc_NoOp; - } - if (Free == 0) - { - Free = AllocatorFree_NoOp; - } - gs_allocator Result = {0}; - Result.Alloc = Alloc; - Result.Free = Free; - return Result; -} -#define CreateAllocator(a, f) CreateAllocator_((allocator_allocate*)(a), (allocator_free*)(f)) - -internal void -AllocatorDebug_PushAlloc(gs_allocator_debug* Debug, u64 Size, char* Location) -{ - // NOTE(pjs): I don't want this debug procedure to be the reason the - // application crashes. - if (Debug->AllocationsCount < Debug->AllocationsCountMax) - { - gs_debug_allocation Allocation = {}; - - gs_const_string L = ConstString(Location); - - s64 LastSlash = FindLastFromSet(L, "\\/"); - if (LastSlash < 0) LastSlash = 0; - Allocation.Location = GetStringAfter(L, LastSlash); - Allocation.Size = Size; - - Debug->Allocations[Debug->AllocationsCount++] = Allocation; - } - Debug->TotalAllocSize += Size; -} - -internal gs_data -AllocatorAlloc_(gs_allocator Allocator, u64 Size, char* Location) -{ - u64 SizeResult = 0; - void* Memory = Allocator.Alloc(Size, &SizeResult); - if (Allocator.Debug) - { - AllocatorDebug_PushAlloc(Allocator.Debug, Size, Location); - } - return CreateData((u8*)Memory, SizeResult); -} -internal void -AllocatorFree_(gs_allocator Allocator, void* Base, u64 Size, char* Location) -{ - if (Base != 0 && Size != 0) - { - Allocator.Free(Base, Size); - if (Allocator.Debug) - { - // NOTE(pjs): There's no reason we should be going negative - // ie. Freeing more memory than we allocated - Assert(Allocator.Debug->TotalAllocSize >= Size); - Allocator.Debug->TotalAllocSize -= Size; - } - } -} - -#define AllocatorAlloc(alloc,size) AllocatorAlloc_((alloc), (size), FileNameAndLineNumberString) -#define AllocatorAllocStruct(alloc, type) (type*)(AllocatorAlloc((alloc), sizeof(type)).Memory) -#define AllocatorAllocArray(alloc, type, count) (type*)(AllocatorAlloc((alloc), sizeof(type) * (count)).Memory) -#define AllocatorAllocString(alloc, size) gs_string{ AllocatorAllocArray((alloc), char, (size)), 0, (size) } -#define AllocatorFree(alloc,base,size) AllocatorFree_((alloc), (base), (size), FileNameAndLineNumberString) -#define AllocatorFreeArray(alloc,base,type,count) AllocatorFree_((alloc), (base), sizeof(type) * count, FileNameAndLineNumberString) -internal gs_memory_cursor -CreateMemoryCursor(u8* Base, u64 Size) -{ - gs_memory_cursor Result = {0}; - Result.Data.Memory = Base; - Result.Data.Size = Size; - return Result; -}; -internal gs_memory_cursor -CreateMemoryCursor(gs_data Data) -{ - return CreateMemoryCursor(Data.Memory, Data.Size); -} -internal gs_memory_cursor -CreateMemoryCursor(gs_allocator Allocator, u64 Size) -{ - gs_data Data = AllocatorAlloc(Allocator, Size); - return CreateMemoryCursor(Data); -} -internal bool -CursorHasRoom(gs_memory_cursor Cursor, u64 Size) -{ - bool Result = ((Cursor.Position + Size) <= Cursor.Data.Size); - return Result; -} -internal gs_data -PushSizeOnCursor_(gs_memory_cursor* Cursor, u64 Size, char* Location) -{ - gs_data Result = {0}; - if (CursorHasRoom(*Cursor, Size)) - { - Result.Memory = Cursor->Data.Memory + Cursor->Position; - Result.Size = Size; - Cursor->Position += Size; - } - return Result; -} - -#define PushSizeOnCursor(cursor,size) PushSizeOnCursor_((cursor), (size), FileNameAndLineNumberString) -#define PushStructOnCursor(cursor,type) (type*)PushSizeOnCursor_((cursor), sizeof(type), FileNameAndLineNumberString).Memory -#define PushArrayOnCursor(cursor,type,count) (type*)PushSizeOnCursor_((cursor), sizeof(type) * (count), FileNameAndLineNumberString).Memory - -#define MemoryCursor_WriteValue(cursor, type, value) *PushStructOnCursor(cursor, type) = value -#define MemoryCursor_WriteBuffer(cursor, buf, len) CopyMemoryTo((u8*)(buf), PushArrayOnCursor((cursor), u8, (len)), (len)) - -internal void -PopSizeOnCursor(gs_memory_cursor* Cursor, u64 Size) -{ - if (Cursor->Position > Size) - { - Cursor->Position -= Size; - } - else - { - Cursor->Position = 0; - } -} -internal gs_data -AlignCursor(gs_memory_cursor* Cursor, u64 Alignment) -{ - u64 Position = RoundUpTo64(Cursor->Position, Alignment); - Position = Min(Position, Cursor->Data.Size); - u64 NewSize = Position - Cursor->Position; - return PushSizeOnCursor(Cursor, NewSize); -} -internal void -ClearCursor(gs_memory_cursor* Cursor) -{ - Cursor->Position = 0; -} - -internal void -FreeCursorListEntry(gs_allocator Allocator, gs_memory_cursor_list* CursorEntry) -{ - AllocatorFree(Allocator, CursorEntry, CursorEntry->Cursor.Data.Size + sizeof(gs_memory_cursor)); -} - -internal gs_memory_arena -CreateMemoryArena_(arena_type ArenaType, gs_allocator Allocator, u64 ChunkSize, u64 Alignment, gs_memory_arena* ParentArena, char* Name) -{ - // we only want a parent arena if the type is Arena_SubArena - Assert(((ArenaType == Arena_BaseArena) && (ParentArena == 0)) || - ((ArenaType == Arena_SubArena) && (ParentArena != 0))); - - gs_memory_arena Arena = {}; - Arena.ArenaName = Name; - Arena.Type = ArenaType; - Arena.Allocator = Allocator; - Arena.Parent = ParentArena; - -#if MEMORY_CURSOR_STATIC_ARRAY - Arena.CursorsCountMax = 4096; - Arena.Cursors = AllocatorAllocArray(Allocator, gs_memory_cursor_list, Arena.CursorsCountMax); -#endif - - Arena.MemoryChunkSize = ChunkSize; - Arena.MemoryAlignment = Alignment; - return Arena; -} - -internal gs_memory_arena -CreateMemoryArena(gs_allocator Allocator, char* Name, u64 ChunkSize = KB(4), u64 Alignment = Bytes(8)) -{ - return CreateMemoryArena_(Arena_BaseArena, Allocator, ChunkSize, Alignment, 0, Name); -} -internal gs_memory_arena -CreateMemorySubArena(gs_memory_arena* Parent, char* Name, u64 ChunkSize = KB(32), u64 Alignment = Bytes(8)) -{ - return CreateMemoryArena_(Arena_SubArena, Parent->Allocator, ChunkSize, Alignment, Parent, Name); -} - -internal gs_data PushSize_(gs_memory_arena* Arena, u64 Size, char* Location); - -internal void -FreeCursorList(gs_memory_cursor_list* List, gs_allocator Allocator) -{ -#if !MEMORY_CURSOR_STATIC_ARRAY - gs_memory_cursor_list* CursorAt = List; - while (CursorAt != 0) - { - gs_memory_cursor_list* Prev = CursorAt->Prev; - FreeCursorListEntry(Allocator, CursorAt); - CursorAt = Prev; - } -#endif -} - -internal gs_memory_cursor_list* -MemoryArenaNewCursor(gs_memory_arena* Arena, u64 MinSize, char* Location) -{ -#if MEMORY_CURSOR_STATIC_ARRAY - u64 AllocSize = Max(MinSize, Arena->MemoryChunkSize); -#else - // Allocate enough spcae for the minimum size needed + sizeo for the cursor list - u64 AllocSize = Max(MinSize, Arena->MemoryChunkSize) + sizeof(gs_memory_cursor_list); -#endif - - gs_data Data = {0}; - switch (Arena->Type) - { - case Arena_SubArena: - { - Data = PushSize_(Arena->Parent, AllocSize, Location); - }break; - - case Arena_BaseArena: - { - Data = AllocatorAlloc_(Arena->Allocator, AllocSize, Location); - }break; - - InvalidDefaultCase; - } - -#if MEMORY_CURSOR_STATIC_ARRAY - Assert(Arena->CursorsCount < Arena->CursorsCountMax); - gs_memory_cursor_list* Result = Arena->Cursors + Arena->CursorsCount++; - Result->Cursor = CreateMemoryCursor(Data.Memory, Data.Size); -#else - // Fit the memory cursor into the region allocated - Assert(MinSize + sizeof(gs_memory_cursor_list) <= Data.Size); - gs_memory_cursor_list* Result = (gs_memory_cursor_list*)Data.Memory; - u8* CursorMemoryStart = (u8*)(Result + 1); - u64 CursorMemorySize = Data.Size - sizeof(gs_memory_cursor_list); - Result->Cursor = CreateMemoryCursor(CursorMemoryStart, CursorMemorySize); - - Result->Prev = Arena->CursorList; - Result->Next = 0; - if (Arena->CursorList != 0) - { - if (Arena->CursorList->Next != 0) - { - Result->Next = Arena->CursorList->Next; - } - Arena->CursorList->Next = Result; - } - Arena->CursorList = Result; -#endif - return Result; -} - -internal gs_data -PushSize_(gs_memory_arena* Arena, u64 Size, char* Location) -{ - gs_data Result = {0}; - if (Size > 0) - { -#if MEMORY_CURSOR_STATIC_ARRAY - gs_memory_cursor_list* CursorEntry = 0; - for (u64 i = 0; - i < Arena->CursorsCount; - i++) - { - gs_memory_cursor_list* At = Arena->Cursors + i; - if (CursorHasRoom(At->Cursor, Size)) - { - CursorEntry = At; - break; - } - } - if (!CursorEntry) - { - CursorEntry = MemoryArenaNewCursor(Arena, Size, Location); - } - - if (!CursorEntry || !CursorHasRoom(CursorEntry->Cursor, Size)) - { - __debugbreak(); - - CursorEntry = 0; - for (u64 i = 0; - i < Arena->CursorsCount; - i++) - { - gs_memory_cursor_list* At = Arena->Cursors + i; - if (CursorHasRoom(At->Cursor, Size)) - { - CursorEntry = At; - break; - } - } - if (!CursorEntry) - { - CursorEntry = MemoryArenaNewCursor(Arena, Size, Location); - } - } - //Assert(CursorEntry); - //Assert(CursorHasRoom(CursorEntry->Cursor, Size)); -#else - - gs_memory_cursor_list* CursorEntry = Arena->CursorList; - if (CursorEntry == 0) - { - CursorEntry = MemoryArenaNewCursor(Arena, Size, Location); - } - if (!CursorHasRoom(CursorEntry->Cursor, Size)) - { - while ((CursorEntry != 0) && !CursorHasRoom(CursorEntry->Cursor, Size)) - { - CursorEntry = CursorEntry->Next; - } - if (CursorEntry == 0) - { - CursorEntry = MemoryArenaNewCursor(Arena, Size, Location); - } - } -#endif - Assert(CursorEntry != 0); - Assert(CursorHasRoom(CursorEntry->Cursor, Size)); - Result = PushSizeOnCursor_(&CursorEntry->Cursor, Size, Location); - Assert(Result.Memory != 0); - - gs_data Alignment = AlignCursor(&CursorEntry->Cursor, Arena->MemoryAlignment); - Result.Size += Alignment.Size; - } - - // TODO(Peter): @Cleanup @Efficiency - // There is a case I want to handle at some point: - // You have a Cursor that is empty, but the size you want to allocate is bigger - // than the cursor. So you create a new cursor, of the exact size you need, - // immediately fill it up, and push it onto the head of the cursor list. Now, - // the list looks like this: - // [root] [cursor] ... [empty cursor] [full cursor] [new, empty cursor] - // and you'll never use the memory in 'empty cursor' - // What I'd like to do is, when you fill up a cursor, it gets pushed back until - // the next cursor is more full - // NOTE: Thought on this tho - you don't want this behavior in a scratch arena - // where usage across frames could change drastically. This matters way more in - // a permanent storage (i think) - return Result; -} - -internal void -FreeMemoryArena(gs_memory_arena* Arena) -{ -#if MEMORY_CURSOR_STATIC_ARRAY - for (u32 i = 0; i < Arena->CursorsCount; i++) - { - gs_memory_cursor_list E = Arena->Cursors[i]; - AllocatorFree(Arena->Allocator, E.Cursor.Data.Memory, E.Cursor.Data.Size); - } - AllocatorFreeArray(Arena->Allocator, Arena->Cursors, gs_memory_cursor_list, Arena->CursorsCountMax); -#else - FreeCursorList(Arena->CursorList, Arena->Allocator); -#endif -} - -#define PushSizeToData(arena, size) PushSize_((arena), (size), FileNameAndLineNumberString) -#define PushSize(arena, size) PushSize_((arena), (size), FileNameAndLineNumberString).Memory -#define PushStruct(arena, type) (type*)(PushSize_((arena), sizeof(type), FileNameAndLineNumberString).Memory) -#define PushArray(arena, type, count) (type*)(PushSize_((arena), sizeof(type) * (count), FileNameAndLineNumberString).Memory) -#define PushString(arena, length) MakeString(PushArray((arena), char, (length)), 0, (length)); - +#define PushStringF(a,l,f,...) PushStringF_((a),(l),(f), DEBUG_LOC, __VA_ARGS__) internal gs_string -PushStringF(gs_memory_arena* Arena, u32 MaxLength, char* Format, ...) +PushStringF_(gs_memory_arena* Arena, u32 MaxLength, char* Format, gs_debug_loc Loc, ...) { - gs_string Result = PushString(Arena, MaxLength); - - va_list Args; - va_start(Args, Format); - PrintFArgsList(&Result, Format, Args); - va_end(Args); - - return Result; + gs_string Result = gs_string { + (char*)PushSize_(Arena, sizeof(char) * MaxLength, Loc).Memory, // Str + 0, // Length + MaxLength, // Size + }; + + va_list Args; + va_start(Args, Loc); + PrintFArgsList(&Result, Format, Args); + va_end(Args); + + return Result; } internal gs_string PushStringCopy(gs_memory_arena* Arena, gs_const_string String) { - gs_string Result = PushString(Arena, String.Length); - Result.Size = String.Length; - Result.Length = String.Length; - for (u32 i = 0; i < String.Length; i++) - { - Result.Str[i] = String.Str[i]; - } - return Result; -} - -internal void -ClearArena(gs_memory_arena* Arena) -{ -#if MEMORY_CURSOR_STATIC_ARRAY - for (u32 i = 0; i < Arena->CursorsCount; i++) - { - Arena->Cursors[i].Cursor.Position = 0; - } -#else - gs_memory_cursor_list* First = 0; - for (gs_memory_cursor_list* CursorEntry = Arena->CursorList; - CursorEntry != 0; - CursorEntry = CursorEntry->Prev) - { - First = CursorEntry; - CursorEntry->Cursor.Position = 0; - } - Arena->CursorList = First; -#endif -} - -internal void -FreeArena(gs_memory_arena* Arena) -{ - FreeMemoryArena(Arena); + gs_string Result = PushString(Arena, String.Length); + Result.Size = String.Length; + Result.Length = String.Length; + for (u32 i = 0; i < String.Length; i++) + { + Result.Str[i] = String.Str[i]; + } + return Result; } /////////////////////////// @@ -2856,162 +2464,29 @@ FreeArena(gs_memory_arena* Arena) inline void DebugPrint(debug_output Output, gs_const_string Message) { - Output.Print(Output, Message); + Output.Print(Output, Message); } inline void DebugPrint(debug_output Output, char* Message) { - gs_const_string String = ConstString(Message); - Output.Print(Output, String); + gs_const_string String = ConstString(Message); + Output.Print(Output, String); } internal void DebugPrintF(debug_output Output, char* Format, ...) { - gs_string Message = PushString(Output.Storage, 1024); - va_list Args; - va_start(Args, Format); - PrintFArgsList(&Message, Format, Args); - NullTerminate(&Message); - Output.Print(Output, Message.ConstString); -} - -/////////////////////////// -// -// Dynamic Array - -internal gs_dynarray -CreateDynarrayWithStorage(gs_memory_arena Storage, u32 ElementSize, u32 ElementsPerBuffer) -{ - gs_dynarray Result = {}; - Result.Arena = Storage; - Result.ElementSize = ElementSize; - Result.ElementsPerBuffer = ElementsPerBuffer; - Result.ElementCount = 0; - return Result; -} - -internal gs_dynarray -CreateDynarray_(gs_allocator Allocator, u32 ElementSize, u32 ElementsPerBuffer) -{ - gs_memory_arena Storage = CreateMemoryArena(Allocator, "Dynarray Arena", ElementSize * ElementsPerBuffer); - return CreateDynarrayWithStorage(Storage, ElementSize, ElementsPerBuffer); -}; - -internal gs_dynarray -CreateDynarray_(gs_memory_arena* Arena, u32 ElementSize, u32 ElementsPerBuffer) -{ - gs_memory_arena Storage = CreateMemorySubArena(Arena, "Dynarray Sub Arena", ElementSize * ElementsPerBuffer); - return CreateDynarrayWithStorage(Storage, ElementSize, ElementsPerBuffer); -}; - -internal u64 -CalculateBufferSize(gs_dynarray Array) -{ - u64 Result = Array.ElementsPerBuffer * Array.ElementSize; - return Result; -} - -internal void -GrowDynarray(gs_dynarray* Array) -{ - gs_dynarray_buffer* OldBufferList = Array->Buffers; - u64 NewBuffersCount = Array->BuffersCount + 1; - gs_dynarray_buffer* NewBufferList = AllocatorAllocArray(Array->Arena.Allocator, gs_dynarray_buffer, NewBuffersCount); - if (OldBufferList) - { - CopyArray(OldBufferList, NewBufferList, gs_dynarray_buffer, Array->BuffersCount); - AllocatorFree(Array->Arena.Allocator, OldBufferList, sizeof(gs_dynarray_buffer) * Array->BuffersCount); - } - u64 BufferSize = CalculateBufferSize(*Array); - NewBufferList[Array->BuffersCount].Memory = PushSize(&Array->Arena, BufferSize); - Array->Buffers = NewBufferList; - Array->BuffersCount = NewBuffersCount; -} -internal u64 -DynarraySize(gs_dynarray Array) -{ - u64 Result = Array.BuffersCount * Array.ElementsPerBuffer; - return Result; -} -internal gs_dynarray_handle -IndexToHandle(gs_dynarray* Array, u64 Index) -{ - gs_dynarray_handle Result = {0}; - Result.BufferIndex = Index / Array->ElementsPerBuffer; - Result.IndexInBuffer = Index % Array->ElementsPerBuffer; - return Result; -} -internal u64 -HandleToIndex(gs_dynarray Array, gs_dynarray_handle Handle) -{ - u64 Result = Handle.IndexInBuffer + (Handle.BufferIndex * Array.ElementsPerBuffer); - return Result; -} -internal gs_dynarray_handle -TakeFreeElement(gs_dynarray* Array) -{ - gs_dynarray_handle Result = {0}; - if (Array->ElementCount >= DynarraySize(*Array)) - { - GrowDynarray(Array); - } - Assert(Array->ElementCount < DynarraySize(*Array)); - u64 ElementIndex = Array->ElementCount++; - Result = IndexToHandle(Array, ElementIndex); - return Result; -} -internal bool -HandleIsValid(gs_dynarray Array, gs_dynarray_handle Handle) -{ - bool Result = Handle.IndexInBuffer < Array.ElementsPerBuffer; - Result &= Handle.BufferIndex < Array.BuffersCount; - return Result; -} -internal bool -IndexIsValid(gs_dynarray Array, u64 Index) -{ - bool Result = Index < DynarraySize(Array); - return Result; -} -internal gs_data -GetElementInList_(gs_dynarray* Array, gs_dynarray_handle Handle, u64 SizeRequested) -{ - Assert(SizeRequested == Array->ElementSize); - Assert(HandleIsValid(*Array, Handle)); - gs_dynarray_buffer Buffer = Array->Buffers[Handle.BufferIndex]; - - gs_data Result = {0}; - Result.Memory = Buffer.Memory + (Handle.IndexInBuffer * Array->ElementSize); - Result.Size = SizeRequested; - - return Result; -} -internal gs_data -GetElementInList_(gs_dynarray* Array, u64 Index, u64 SizeRequested) -{ - gs_dynarray_handle Handle = IndexToHandle(Array, Index); - return GetElementInList_(Array, Handle, SizeRequested); -} -internal void -FreeDynarray(gs_dynarray* Array) -{ - gs_allocator Allocator = Array->Arena.Allocator; - u64 BufferSize = CalculateBufferSize(*Array); - for (u64 i = 0; i < Array->BuffersCount; i++) - { - AllocatorFree(Allocator, Array->Buffers[i].Memory, BufferSize); - } - AllocatorFree(Allocator, Array->Buffers, sizeof(gs_dynarray_buffer) * Array->BuffersCount); + gs_string Message = PushString(Output.Storage, 1024); + va_list Args; + va_start(Args, Format); + PrintFArgsList(&Message, Format, Args); + NullTerminate(&Message); + Output.Print(Output, Message.ConstString); } #define HandlesAreEqual(ha, hb) ((ha.IndexInBuffer == hb.IndexInBuffer) && (ha.BufferIndex == hb.BufferIndex)) -#define CreateDynarray(allocator,type,elePerBuf) CreateDynarray_((allocator), sizeof(type), (elePerBuf)) -#define GetElement_(array,type,size,indexOrHandle) (type*)GetElementInList_(array, indexOrHandle, size).Memory -#define GetElement(array,type,indexOrHandle) GetElement_(array, type, sizeof(type), indexOrHandle) - /////////////////////////// // // String Builder @@ -3019,19 +2494,19 @@ FreeDynarray(gs_dynarray* Array) internal void GrowStringBuilder_(gs_string_builder* StringBuilder) { - gs_string_builder_buffer* NewBuffer = PushStruct(StringBuilder->Arena, gs_string_builder_buffer); - NewBuffer->String = PushString(StringBuilder->Arena, StringBuilder->BufferSize); - SLLPushOrInit(StringBuilder->Root, StringBuilder->Head, NewBuffer); + gs_string_builder_buffer* NewBuffer = PushStruct(StringBuilder->Arena, gs_string_builder_buffer); + NewBuffer->String = PushString(StringBuilder->Arena, StringBuilder->BufferSize); + SLLPushOrInit(StringBuilder->Root, StringBuilder->Head, NewBuffer); } internal void OutChar(gs_string_builder* Builder, char C) { - if (Builder->Head == 0 || Builder->Head->String.Length >= Builder->Head->String.Size) - { - GrowStringBuilder_(Builder); - } - OutChar(&Builder->Head->String, C); + if (Builder->Head == 0 || Builder->Head->String.Length >= Builder->Head->String.Size) + { + GrowStringBuilder_(Builder); + } + OutChar(&Builder->Head->String, C); } #if 0 @@ -3040,264 +2515,264 @@ OutChar(gs_string_builder* Builder, char C) internal void StringBuilderWriteFArgsList(gs_string_builder* Builder, char* Format, va_list Args) { - char* FormatAt = Format; - while (*FormatAt) + char* FormatAt = Format; + while (*FormatAt) + { + if (FormatAt[0] != '%') { - if (FormatAt[0] != '%') + if (FormatAt[0] == '\\') + { + FormatAt++; + Assert(IsBase8(FormatAt[0]) || // Octal Escape Sequences - \0 is in this set + FormatAt[0] == '\'' || + FormatAt[0] == '\"' || + FormatAt[0] == '\?' || + FormatAt[0] == '\\' || + FormatAt[0] == 'a' || // Audible Bell + FormatAt[0] == 'b' || // Backspace + FormatAt[0] == 'f' || // Form Feed - New Page + FormatAt[0] == 'n' || // Line Feed - New Line + FormatAt[0] == 'r' || // Carriage Return + FormatAt[0] == 't' || // Tab + FormatAt[0] == 'v'); // Vertical Tab + + // Not Handled (see cpp spec) \nnn \xnn \unnnn \Unnnnnnnn + Assert(FormatAt[0] != 'x' || FormatAt[0] != 'u' || FormatAt[0] != 'U'); + + if (IsBase8(FormatAt[0])) { - if (FormatAt[0] == '\\') - { - FormatAt++; - Assert(IsBase8(FormatAt[0]) || // Octal Escape Sequences - \0 is in this set - FormatAt[0] == '\'' || - FormatAt[0] == '\"' || - FormatAt[0] == '\?' || - FormatAt[0] == '\\' || - FormatAt[0] == 'a' || // Audible Bell - FormatAt[0] == 'b' || // Backspace - FormatAt[0] == 'f' || // Form Feed - New Page - FormatAt[0] == 'n' || // Line Feed - New Line - FormatAt[0] == 'r' || // Carriage Return - FormatAt[0] == 't' || // Tab - FormatAt[0] == 'v'); // Vertical Tab - - // Not Handled (see cpp spec) \nnn \xnn \unnnn \Unnnnnnnn - Assert(FormatAt[0] != 'x' || FormatAt[0] != 'u' || FormatAt[0] != 'U'); - - if (IsBase8(FormatAt[0])) - { - // TODO(Peter): this should keep going until it finds a non-octal character code - // but the only one we really need is \0 atm so I'm just handling that one - Assert(FormatAt[0] == '0'); - OutChar(Builder, (char)0); - FormatAt++; - } - else - { - OutChar(Builder, *FormatAt++); - } - } - else - { - OutChar(Builder, *FormatAt++); - } - } - else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol - { - OutChar(Builder, '%'); - FormatAt += 2; + // TODO(Peter): this should keep going until it finds a non-octal character code + // but the only one we really need is \0 atm so I'm just handling that one + Assert(FormatAt[0] == '0'); + OutChar(Builder, (char)0); + 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 (IsBase10(FormatAt[0])) - { - WidthSpecified = true; - u64 Parsed = 0; - AssertMessage("ParseInt assumes whole string is an integer"); - Width = (s32)ParseInt(FormatAt, 10, &Parsed); - FormatAt += Parsed; - } - 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 (IsBase10(FormatAt[0])) - { - - PrecisionSpecified = true; - u64 Parsed = 0; - AssertMessage("ParseInt assumes whole string is an integer"); - Precision = (s32)ParseInt(FormatAt, 10, &Parsed); - FormatAt += Parsed; - } - 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 Specifiers - gs_string StringRemaining = GetStringAfter(*String, String->Length); - Assert(StringRemaining.Length == 0); - if (FormatAt[0] == 'd' || FormatAt[0] == 'i') - { - s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); - if (SignedInt < 0) - { - OutChar(&StringRemaining, '-'); - SignedInt *= -1; - } - U64ToASCII(&StringRemaining, (u64)SignedInt, 10, Base10Chars); - } - else if (FormatAt[0] == 'u') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&StringRemaining, UnsignedInt, 10, Base10Chars); - } - else if (FormatAt[0] == 'o') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&StringRemaining, UnsignedInt, 8, Base8Chars); - } - else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&StringRemaining, UnsignedInt, 16, Base16Chars); - } - else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') - { - r64 Float = ReadVarArgsFloat(Length, &Args); - s32 AfterPoint = 6; - if (PrecisionSpecified) - { - AfterPoint = Precision; - } - R64ToASCII(&StringRemaining, Float, AfterPoint); - } - else if (FormatAt[0] == 'c') - { - char InsertChar = va_arg(Args, s32); - OutChar(&StringRemaining, InsertChar); - } - else if (FormatAt[0] == 's') - { - char* InsertString = va_arg(Args, char*); - - s32 InsertStringLength = CStringLength(InsertString); - if (PrecisionSpecified) - { - InsertStringLength = Min(InsertStringLength, Precision); - } - InsertStringLength = Min(StringSizeLeft(StringRemaining), InsertStringLength); - - for (s32 c = 0; c < InsertStringLength; c++) - { - OutChar(&StringRemaining, InsertString[c]); - } - } - else if (FormatAt[0] == 'S') - { - gs_const_string InsertString = va_arg(Args, gs_const_string); - - for (s32 c = 0; c < InsertString.Length; c++) - { - OutChar(&StringRemaining, InsertString.Str[c]); - } - } - else if (FormatAt[0] == 'p') - { - // TODO(Peter): Pointer Address - } - else - { - // NOTE(Peter): Non-specifier character found - InvalidCodePath; - } - - String->Length += StringRemaining.Length; - FormatAt++; + OutChar(Builder, *FormatAt++); } + } + else + { + OutChar(Builder, *FormatAt++); + } } - - return String->Length; + else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol + { + OutChar(Builder, '%'); + FormatAt += 2; + } + 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 (IsBase10(FormatAt[0])) + { + WidthSpecified = true; + u64 Parsed = 0; + AssertMessage("ParseInt assumes whole string is an integer"); + Width = (s32)ParseInt(FormatAt, 10, &Parsed); + FormatAt += Parsed; + } + 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 (IsBase10(FormatAt[0])) + { + + PrecisionSpecified = true; + u64 Parsed = 0; + AssertMessage("ParseInt assumes whole string is an integer"); + Precision = (s32)ParseInt(FormatAt, 10, &Parsed); + FormatAt += Parsed; + } + 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 Specifiers + gs_string StringRemaining = GetStringAfter(*String, String->Length); + Assert(StringRemaining.Length == 0); + if (FormatAt[0] == 'd' || FormatAt[0] == 'i') + { + s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); + if (SignedInt < 0) + { + OutChar(&StringRemaining, '-'); + SignedInt *= -1; + } + U64ToASCII(&StringRemaining, (u64)SignedInt, 10, Base10Chars); + } + else if (FormatAt[0] == 'u') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 10, Base10Chars); + } + else if (FormatAt[0] == 'o') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 8, Base8Chars); + } + else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 16, Base16Chars); + } + else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') + { + r64 Float = ReadVarArgsFloat(Length, &Args); + s32 AfterPoint = 6; + if (PrecisionSpecified) + { + AfterPoint = Precision; + } + R64ToASCII(&StringRemaining, Float, AfterPoint); + } + else if (FormatAt[0] == 'c') + { + char InsertChar = va_arg(Args, s32); + OutChar(&StringRemaining, InsertChar); + } + else if (FormatAt[0] == 's') + { + char* InsertString = va_arg(Args, char*); + + s32 InsertStringLength = CStringLength(InsertString); + if (PrecisionSpecified) + { + InsertStringLength = Min(InsertStringLength, Precision); + } + InsertStringLength = Min(StringSizeLeft(StringRemaining), InsertStringLength); + + for (s32 c = 0; c < InsertStringLength; c++) + { + OutChar(&StringRemaining, InsertString[c]); + } + } + else if (FormatAt[0] == 'S') + { + gs_const_string InsertString = va_arg(Args, gs_const_string); + + for (s32 c = 0; c < InsertString.Length; c++) + { + OutChar(&StringRemaining, InsertString.Str[c]); + } + } + else if (FormatAt[0] == 'p') + { + // TODO(Peter): Pointer Address + } + else + { + // NOTE(Peter): Non-specifier character found + InvalidCodePath; + } + + String->Length += StringRemaining.Length; + FormatAt++; + } + } + + return String->Length; } internal void StringBuilderWriteF(gs_string_builder* Builder, char* Format, ...) { - va_list Args; - va_start(Args, Format); - StringBuilderWriteFArgsList(Builder, Format, Args); - va_end(Args); + va_list Args; + va_start(Args, Format); + StringBuilderWriteFArgsList(Builder, Format, Args); + va_end(Args); } #endif // String builder @@ -3309,25 +2784,25 @@ StringBuilderWriteF(gs_string_builder* Builder, char* Format, ...) internal u64 FileHandlerGetFileInfo_NoOp(gs_file_handler FileHandler, gs_const_string Path) { - return 0; + return 0; } internal gs_file FileHandlerReadFile_NoOp(gs_const_string Path) { - return gs_file{0}; + return gs_file{0}; } internal bool FileHandlerWriteFile_NoOp(gs_const_string Path, gs_data Data) { - return false; + return false; } internal gs_const_string_array FileHandlerEnumerateDirectory_NoOp(gs_const_string Path, bool Recursive, bool IncludeDirs) { - return gs_const_string_array{0}; + return gs_const_string_array{0}; } internal gs_file_handler @@ -3337,110 +2812,110 @@ CreateFileHandler(file_handler_get_file_info* GetFileInfo, file_handler_enumerate_directory* EnumerateDirectory, gs_memory_arena* Transient) { - if (GetFileInfo == 0) - { - GetFileInfo = (file_handler_get_file_info*)FileHandlerGetFileInfo_NoOp; - } - if (ReadEntireFile == 0) - { - ReadEntireFile = (file_handler_read_entire_file*)FileHandlerReadFile_NoOp; - } - if (WriteEntireFile == 0) - { - WriteEntireFile = (file_handler_write_entire_file*)FileHandlerWriteFile_NoOp; - } - if (EnumerateDirectory == 0) - { - EnumerateDirectory = (file_handler_enumerate_directory*)FileHandlerEnumerateDirectory_NoOp; - } - gs_file_handler Result = {0}; - Result.GetFileInfo = GetFileInfo; - Result.ReadEntireFile = ReadEntireFile; - Result.WriteEntireFile = WriteEntireFile; - Result.EnumerateDirectory = EnumerateDirectory; - Result.Transient = Transient; - - return Result; + if (GetFileInfo == 0) + { + GetFileInfo = (file_handler_get_file_info*)FileHandlerGetFileInfo_NoOp; + } + if (ReadEntireFile == 0) + { + ReadEntireFile = (file_handler_read_entire_file*)FileHandlerReadFile_NoOp; + } + if (WriteEntireFile == 0) + { + WriteEntireFile = (file_handler_write_entire_file*)FileHandlerWriteFile_NoOp; + } + if (EnumerateDirectory == 0) + { + EnumerateDirectory = (file_handler_enumerate_directory*)FileHandlerEnumerateDirectory_NoOp; + } + gs_file_handler Result = {0}; + Result.GetFileInfo = GetFileInfo; + Result.ReadEntireFile = ReadEntireFile; + Result.WriteEntireFile = WriteEntireFile; + Result.EnumerateDirectory = EnumerateDirectory; + Result.Transient = Transient; + + return Result; } internal gs_const_string GetNullTerminatedPath(gs_file_handler FileHandler, gs_const_string Path) { - gs_const_string Result = {}; - if (!IsNullTerminated(Path)) - { - gs_string NullTermPath = PushString(FileHandler.Transient, Path.Length + 1); - PrintF(&NullTermPath, "%S", Path); - NullTerminate(&NullTermPath); - Result = NullTermPath.ConstString; - } - else - { - Result = Path; - } - return Result; + gs_const_string Result = {}; + if (!IsNullTerminated(Path)) + { + gs_string NullTermPath = PushString(FileHandler.Transient, Path.Length + 1); + PrintF(&NullTermPath, "%S", Path); + NullTerminate(&NullTermPath); + Result = NullTermPath.ConstString; + } + else + { + Result = Path; + } + return Result; } internal gs_file_info GetFileInfo(gs_file_handler FileHandler, gs_const_string Path) { - Assert(FileHandler.GetFileInfo != 0); - - Path = GetNullTerminatedPath(FileHandler, Path); - gs_file_info Result = FileHandler.GetFileInfo(FileHandler, Path); - return Result; + Assert(FileHandler.GetFileInfo != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + gs_file_info Result = FileHandler.GetFileInfo(FileHandler, Path); + return Result; } internal gs_file ReadEntireFile(gs_file_handler FileHandler, gs_const_string Path, gs_data Memory) { - Assert(FileHandler.ReadEntireFile != 0); - - Path = GetNullTerminatedPath(FileHandler, Path); - gs_file Result = FileHandler.ReadEntireFile(FileHandler, Path, Memory); - return Result; + Assert(FileHandler.ReadEntireFile != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + gs_file Result = FileHandler.ReadEntireFile(FileHandler, Path, Memory); + return Result; } internal gs_file ReadEntireFile(gs_file_handler FileHandler, gs_const_string Path) { - Assert(FileHandler.GetFileInfo != 0); - Assert(FileHandler.ReadEntireFile != 0); - - Path = GetNullTerminatedPath(FileHandler, Path); - gs_file Result = {0}; - gs_file_info FileInfo = FileHandler.GetFileInfo(FileHandler, Path); - if (FileInfo.FileSize > 0) - { - gs_data FileMemory = PushSizeToData(FileHandler.Transient, FileInfo.FileSize); - Result = ReadEntireFile(FileHandler, Path, FileMemory); - } - return Result; + Assert(FileHandler.GetFileInfo != 0); + Assert(FileHandler.ReadEntireFile != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + gs_file Result = {0}; + gs_file_info FileInfo = FileHandler.GetFileInfo(FileHandler, Path); + if (FileInfo.FileSize > 0) + { + gs_data FileMemory = PushSize(FileHandler.Transient, FileInfo.FileSize); + Result = ReadEntireFile(FileHandler, Path, FileMemory); + } + return Result; } internal bool WriteEntireFile(gs_file_handler FileHandler, gs_const_string Path, gs_data Memory) { - Assert(FileHandler.WriteEntireFile != 0); - - Path = GetNullTerminatedPath(FileHandler, Path); - return FileHandler.WriteEntireFile(FileHandler, Path, Memory); + Assert(FileHandler.WriteEntireFile != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + return FileHandler.WriteEntireFile(FileHandler, Path, Memory); } internal gs_file_info_array EnumerateDirectory(gs_file_handler FileHandler, gs_memory_arena* Storage, gs_const_string Path, u32 Flags) { - Assert(FileHandler.EnumerateDirectory != 0); - - Path = GetNullTerminatedPath(FileHandler, Path); - return FileHandler.EnumerateDirectory(FileHandler, Storage, Path, Flags); + Assert(FileHandler.EnumerateDirectory != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + return FileHandler.EnumerateDirectory(FileHandler, Storage, Path, Flags); } internal bool FileNoError(gs_file File) { - bool Result = (File.Size > 0); - return Result; + bool Result = (File.Size > 0); + return Result; } ////////////////////////// @@ -3450,15 +2925,15 @@ FileNoError(gs_file File) internal s64 TimeHandlerGetWallClock(gs_time_handler TimeHandler) { - s64 Result = TimeHandler.GetWallClock(); - return Result; + s64 Result = TimeHandler.GetWallClock(); + return Result; } internal s64 TimeHandlerGetSecondsElapsed(gs_time_handler TimeHandler, s64 StartCycles, s64 EndCycles) { - s64 Result = TimeHandler.GetSecondsElapsed(StartCycles, EndCycles); - return Result; + s64 Result = TimeHandler.GetSecondsElapsed(StartCycles, EndCycles); + return Result; } ////////////////////////// @@ -3467,71 +2942,71 @@ TimeHandlerGetSecondsElapsed(gs_time_handler TimeHandler, s64 StartCycles, s64 E CREATE_THREAD(CreateThreadStub) { - return {}; + return {}; } KILL_THREAD(KillThreadStub) { - return false; + return false; } internal platform_thread_manager CreatePlatformThreadManager(platform_create_thread* CreateThreadProc, platform_kill_thread* KillThreadProc) { - platform_thread_manager Result = {}; - Result.CreateThreadProc = CreateThreadProc; - Result.KillThreadProc = KillThreadProc; - - if (!CreateThreadProc) - { - Result.CreateThreadProc = CreateThreadStub; - } - if (!KillThreadProc) - { - Result.KillThreadProc = KillThreadStub; - } - - return Result; + platform_thread_manager Result = {}; + Result.CreateThreadProc = CreateThreadProc; + Result.KillThreadProc = KillThreadProc; + + if (!CreateThreadProc) + { + Result.CreateThreadProc = CreateThreadStub; + } + if (!KillThreadProc) + { + Result.KillThreadProc = KillThreadStub; + } + + return Result; } internal platform_thread_handle CreateThread(platform_thread_manager* Manager, thread_proc_* Proc, u8* Arg, gs_thread_context Ctx) { - platform_thread_handle Result = {}; - - for (u32 i = 1; i < THREADS_MAX; i++) + platform_thread_handle Result = {}; + + for (u32 i = 1; i < THREADS_MAX; i++) + { + if (!Manager->ThreadsUsed[i]) { - if (!Manager->ThreadsUsed[i]) - { - Result.Index = i; - break; - } + Result.Index = i; + break; } - Assert(Result.Index != 0); - - Manager->ThreadsUsed[Result.Index] = true; - Manager->CreateThreadProc(&Manager->Threads[Result.Index], Proc, Arg, Ctx); - - return Result; + } + Assert(Result.Index != 0); + + Manager->ThreadsUsed[Result.Index] = true; + Manager->CreateThreadProc(&Manager->Threads[Result.Index], Proc, Arg, Ctx); + + return Result; } internal bool KillThread(platform_thread_manager* Manager, platform_thread_handle Handle) { - Assert(Manager->ThreadsUsed[Handle.Index]); - - platform_thread* Thread = &Manager->Threads[Handle.Index]; - bool Result = Manager->KillThreadProc(Thread); - - if (Result) - { - Manager->ThreadsUsed[Handle.Index] = false; - Manager->Threads[Handle.Index] = {}; - } - - return Result; + Assert(Manager->ThreadsUsed[Handle.Index]); + + platform_thread* Thread = &Manager->Threads[Handle.Index]; + bool Result = Manager->KillThreadProc(Thread); + + if (Result) + { + Manager->ThreadsUsed[Handle.Index] = false; + Manager->Threads[Handle.Index] = {}; + } + + return Result; } @@ -3541,32 +3016,32 @@ KillThread(platform_thread_manager* Manager, platform_thread_handle Handle) CONNECT_SOCKET(PlatformConnectSocket_Stub) { - return false; + return false; } CLOSE_SOCKET(PlatformCloseSocket_Stub) { - return false; + return false; } SOCKET_QUERY_STATUS(PlatformSocketQueryStatus_Stub) { - return false; + return false; } SOCKET_PEEK(PlatformSocketPeek_Stub) { - return 0; + return 0; } SOCKET_RECEIVE(PlatformSocketRecieve_Stub) { - return {}; + return {}; } SOCKET_SEND(PlatformSocketSend_Stub) { - return false; + return false; } internal platform_socket_manager @@ -3577,194 +3052,194 @@ CreatePlatformSocketManager(platform_connect_socket* ConnectSocketProc, platform_socket_receive* SocketRecieveProc, platform_socket_send* SocketSendProc) { - platform_socket_manager Result = {}; - Result.ConnectSocketProc = ConnectSocketProc; - Result.CloseSocketProc = CloseSocketProc; - Result.SocketQueryStatusProc = SocketQueryStatusProc; - Result.SocketPeekProc = SocketPeekProc; - Result.SocketRecieveProc = SocketRecieveProc; - Result.SocketSendProc = SocketSendProc; - - if (!ConnectSocketProc) - { - Result.ConnectSocketProc = PlatformConnectSocket_Stub; - } - if (!CloseSocketProc) - { - Result.CloseSocketProc = PlatformCloseSocket_Stub; - } - if (!SocketQueryStatusProc) - { - Result.SocketQueryStatusProc = PlatformSocketQueryStatus_Stub; - } - if (!SocketPeekProc) - { - Result.SocketPeekProc = PlatformSocketPeek_Stub; - } - if (!SocketRecieveProc) - { - Result.SocketRecieveProc = PlatformSocketRecieve_Stub; - } - if (!SocketSendProc) - { - Result.SocketSendProc = PlatformSocketSend_Stub; - } - return Result; + platform_socket_manager Result = {}; + Result.ConnectSocketProc = ConnectSocketProc; + Result.CloseSocketProc = CloseSocketProc; + Result.SocketQueryStatusProc = SocketQueryStatusProc; + Result.SocketPeekProc = SocketPeekProc; + Result.SocketRecieveProc = SocketRecieveProc; + Result.SocketSendProc = SocketSendProc; + + if (!ConnectSocketProc) + { + Result.ConnectSocketProc = PlatformConnectSocket_Stub; + } + if (!CloseSocketProc) + { + Result.CloseSocketProc = PlatformCloseSocket_Stub; + } + if (!SocketQueryStatusProc) + { + Result.SocketQueryStatusProc = PlatformSocketQueryStatus_Stub; + } + if (!SocketPeekProc) + { + Result.SocketPeekProc = PlatformSocketPeek_Stub; + } + if (!SocketRecieveProc) + { + Result.SocketRecieveProc = PlatformSocketRecieve_Stub; + } + if (!SocketSendProc) + { + Result.SocketSendProc = PlatformSocketSend_Stub; + } + return Result; } internal bool SocketHandleIsValid(platform_socket_handle_ Handle) { - return Handle.Index != 0; + return Handle.Index != 0; } internal platform_socket* SocketManagerGetSocket(platform_socket_manager* Manager, platform_socket_handle_ Handle) { - platform_socket* Result = 0; - if (Manager->SocketsUsed[Handle.Index]) + platform_socket* Result = 0; + if (Manager->SocketsUsed[Handle.Index]) + { + platform_socket* Socket = &Manager->Sockets[Handle.Index]; + if (Socket->PlatformHandle != 0) { - platform_socket* Socket = &Manager->Sockets[Handle.Index]; - if (Socket->PlatformHandle != 0) - { - Result = Socket; - } + Result = Socket; } - return Result; + } + return Result; } internal bool ConnectSocket(platform_socket_manager* Manager, platform_socket_handle_ Handle) { - bool Result = false; - platform_socket* Socket = SocketManagerGetSocket(Manager, Handle); - if (Socket) - { - Result = Manager->ConnectSocketProc(Manager, Socket); - } - return Result; + bool Result = false; + platform_socket* Socket = SocketManagerGetSocket(Manager, Handle); + if (Socket) + { + Result = Manager->ConnectSocketProc(Manager, Socket); + } + return Result; } internal bool RemoveSocket (platform_socket_manager* Manager, platform_socket_handle_ Handle) { - bool Result = Manager->SocketsUsed[Handle.Index]; - Manager->SocketsUsed[Handle.Index] = false; - return Result; + bool Result = Manager->SocketsUsed[Handle.Index]; + Manager->SocketsUsed[Handle.Index] = false; + return Result; } internal platform_socket_handle_ CreateSocket(platform_socket_manager* Manager, char* Addr, char* Port) { - platform_socket_handle_ Result = {}; - for (u32 i = 1; i < SOCKETS_COUNT_MAX; i++) + platform_socket_handle_ Result = {}; + for (u32 i = 1; i < SOCKETS_COUNT_MAX; i++) + { + if (!Manager->SocketsUsed[i]) { - if (!Manager->SocketsUsed[i]) - { - Result.Index = i; - Manager->SocketsUsed[i] = true; - break; - } + Result.Index = i; + Manager->SocketsUsed[i] = true; + break; } - - Assert(Result.Index != 0); - platform_socket* Socket = &Manager->Sockets[Result.Index]; - Socket->Handle = Result; - CopyArray(Addr, Socket->Addr, char, CStringLength(Addr) + 1); - CopyArray(Port, Socket->Port, char, CStringLength(Port) + 1); - - bool Success = Manager->ConnectSocketProc(Manager, Socket); - if (!Success) + } + + Assert(Result.Index != 0); + platform_socket* Socket = &Manager->Sockets[Result.Index]; + Socket->Handle = Result; + CopyArray(Addr, Socket->Addr, char, CStringLength(Addr) + 1); + CopyArray(Port, Socket->Port, char, CStringLength(Port) + 1); + + bool Success = Manager->ConnectSocketProc(Manager, Socket); + if (!Success) + { + if (RemoveSocket(Manager, Result)) { - if (RemoveSocket(Manager, Result)) - { - Result = {}; - } - else - { - InvalidCodePath; - } + Result = {}; } - - return Result; + else + { + InvalidCodePath; + } + } + + return Result; } internal bool CloseSocket(platform_socket_manager* Manager, platform_socket* Socket) { - bool Result = false; - if (Socket) + bool Result = false; + if (Socket) + { + if (Manager->CloseSocketProc(Manager, Socket)) { - if (Manager->CloseSocketProc(Manager, Socket)) - { - RemoveSocket(Manager, Socket->Handle); - *Socket = {}; - Result = true; - } - else - { - InvalidCodePath; - } + RemoveSocket(Manager, Socket->Handle); + *Socket = {}; + Result = true; } - return Result; + else + { + InvalidCodePath; + } + } + return Result; } internal bool CloseSocket(platform_socket_manager* Manager, platform_socket_handle_ Handle) { - bool Result = false; - platform_socket* Socket = SocketManagerGetSocket(Manager, Handle); - return CloseSocket(Manager, Socket); + bool Result = false; + platform_socket* Socket = SocketManagerGetSocket(Manager, Handle); + return CloseSocket(Manager, Socket); } // NOTE(pjs): returns true if the socket is connected internal bool SocketQueryStatus(platform_socket_manager* Manager, platform_socket_handle_ SocketHandle) { - bool Result = false; - platform_socket* Socket = SocketManagerGetSocket(Manager, SocketHandle); - if (Socket) - { - Result = Manager->SocketQueryStatusProc(Manager, Socket); - } - return Result; + bool Result = false; + platform_socket* Socket = SocketManagerGetSocket(Manager, SocketHandle); + if (Socket) + { + Result = Manager->SocketQueryStatusProc(Manager, Socket); + } + return Result; } internal u32 SocketPeek(platform_socket_manager* Manager, platform_socket_handle_ SocketHandle) { - u32 Result = 0; - platform_socket* Socket = SocketManagerGetSocket(Manager, SocketHandle); - if (Socket) - { - Result = Manager->SocketPeekProc(Manager, Socket); - } - return Result; + u32 Result = 0; + platform_socket* Socket = SocketManagerGetSocket(Manager, SocketHandle); + if (Socket) + { + Result = Manager->SocketPeekProc(Manager, Socket); + } + return Result; } internal gs_data SocketRecieve(platform_socket_manager* Manager, platform_socket_handle_ SocketHandle, gs_memory_arena* Storage) { - gs_data Result = {}; - platform_socket* Socket = SocketManagerGetSocket(Manager, SocketHandle); - if (Socket) - { - Result = Manager->SocketRecieveProc(Manager, Socket, Storage); - } - return Result; + gs_data Result = {}; + platform_socket* Socket = SocketManagerGetSocket(Manager, SocketHandle); + if (Socket) + { + Result = Manager->SocketRecieveProc(Manager, Socket, Storage); + } + return Result; } internal bool SocketSend(platform_socket_manager* Manager, platform_socket_handle_ SocketHandle, u32 Address, u32 Port, gs_data Data, s32 Flags) { - bool Result = false; - platform_socket* Socket = SocketManagerGetSocket(Manager, SocketHandle); - if (Socket) - { - s32 SizeSent = Manager->SocketSendProc(Manager, Socket, Address, Port, Data, Flags); - Result = (SizeSent == Data.Size); - } - return Result; + bool Result = false; + platform_socket* Socket = SocketManagerGetSocket(Manager, SocketHandle); + if (Socket) + { + s32 SizeSent = Manager->SocketSendProc(Manager, Socket, Address, Port, Data, Flags); + Result = (SizeSent == Data.Size); + } + return Result; } /////////////////////////// @@ -3774,83 +3249,83 @@ SocketSend(platform_socket_manager* Manager, platform_socket_handle_ SocketHandl internal u32 HashAppendDJB2ToU32(u32 Hash, u8 Byte) { - u32 Result = Hash; - if (Result == 0) { Result = 5381; } - Result = ((Result << 5) + Result) + Byte; - return Result; + u32 Result = Hash; + if (Result == 0) { Result = 5381; } + Result = ((Result << 5) + Result) + Byte; + return Result; } internal u64 HashAppendDJB2ToU32(u64 Hash, u8 Byte) { - u64 Result = Hash; - if (Result == 0) { Result = 5381; } - Result = ((Result << 5) + Result) + Byte; - return Result; + u64 Result = Hash; + if (Result == 0) { Result = 5381; } + Result = ((Result << 5) + Result) + Byte; + return Result; } internal u32 HashDJB2ToU32(char* String) { - u32 Hash = 5381; - char* C = String; - while(*C) - { - Hash = ((Hash << 5) + Hash) + *C++; - } - return Hash; + u32 Hash = 5381; + char* C = String; + while(*C) + { + Hash = ((Hash << 5) + Hash) + *C++; + } + return Hash; } internal u32 HashDJB2ToU32(u32 Length, char* String) { - u32 Hash = 5381; - for (u32 i = 0; i < Length; i++) - { - Hash = ((Hash << 5) + Hash) + String[i]; - } - return Hash; + u32 Hash = 5381; + for (u32 i = 0; i < Length; i++) + { + Hash = ((Hash << 5) + Hash) + String[i]; + } + return Hash; } internal u32 HashDJB2ToU32(gs_const_string Str) { - return HashDJB2ToU32(StringExpand(Str)); + return HashDJB2ToU32(StringExpand(Str)); } internal u32 HashDJB2ToU32(gs_string Str) { - return HashDJB2ToU32(StringExpand(Str)); + return HashDJB2ToU32(StringExpand(Str)); } internal u64 HashDJB2ToU64(char* String) { - u64 Hash = 5381; - char* C = String; - while(*C) - { - Hash = ((Hash << 5) + Hash) + *C++; - } - return Hash; + u64 Hash = 5381; + char* C = String; + while(*C) + { + Hash = ((Hash << 5) + Hash) + *C++; + } + return Hash; } internal u64 HashDJB2ToU64(u32 Length, char* String) { - u64 Hash = 5381; - for (u32 i = 0; i < Length; i++) - { - Hash = ((Hash << 5) + Hash) + String[i]; - } - return Hash; + u64 Hash = 5381; + for (u32 i = 0; i < Length; i++) + { + Hash = ((Hash << 5) + Hash) + String[i]; + } + return Hash; } internal u64 HashDJB2ToU64(gs_const_string Str) { - return HashDJB2ToU64(StringExpand(Str)); + return HashDJB2ToU64(StringExpand(Str)); } internal u64 HashDJB2ToU64(gs_string Str) { - return HashDJB2ToU64(StringExpand(Str)); + return HashDJB2ToU64(StringExpand(Str)); } /////////////////////////// @@ -3860,36 +3335,36 @@ HashDJB2ToU64(gs_string Str) internal gs_random_series InitRandomSeries(u32 Seed) { - gs_random_series Result = {0}; - Result.Value = Seed; - return Result; + gs_random_series Result = {0}; + Result.Value = Seed; + return Result; } internal u32 NextRandom(gs_random_series* Series) { - u32 Result = Series->Value; - Result ^= Result << 13; - Result ^= Result >> 17; - Result ^= Result << 5; - Series->Value = Result; - return Result; + u32 Result = Series->Value; + Result ^= Result << 13; + Result ^= Result >> 17; + Result ^= Result << 5; + Series->Value = Result; + return Result; } internal r32 NextRandomUnilateral(gs_random_series* Series) { - r32 Result = (r32)NextRandom(Series) / (r32)UINT32_MAX; - return Result; + r32 Result = (r32)NextRandom(Series) / (r32)UINT32_MAX; + return Result; } internal r32 NextRandomBilateral(gs_random_series* Series) { - r32 Result = (r32)NextRandom(Series); - Result = Result / (r32)0xFFFFFFFF; - Result = (Result * 2.0f) - 1.0f; - return Result; + r32 Result = (r32)NextRandom(Series); + Result = Result / (r32)0xFFFFFFFF; + Result = (Result * 2.0f) - 1.0f; + return Result; } @@ -3901,62 +3376,62 @@ NextRandomBilateral(gs_random_series* Series) static void RadixSortInPlace_ (gs_radix_list* List, u32 Start, u32 End, u32 Iteration) { - u32 Shift = Iteration; - u32 ZerosBoundary = Start; - u32 OnesBoundary = End - 1; - - for (u32 d = Start; d < End; d++) + u32 Shift = Iteration; + u32 ZerosBoundary = Start; + u32 OnesBoundary = End - 1; + + for (u32 d = Start; d < End; d++) + { + u64 CurrentIndex = ZerosBoundary; + u64 Radix = List->Radixes.Values[CurrentIndex]; + u64 Place = (Radix >> Shift) & 0x1; + if (Place) { - u64 CurrentIndex = ZerosBoundary; - u64 Radix = List->Radixes.Values[CurrentIndex]; - u64 Place = (Radix >> Shift) & 0x1; - if (Place) - { - u64 EvictedIndex = OnesBoundary; - u64 EvictedRadix = List->Radixes.Values[EvictedIndex]; - u64 EvictedID = List->IDs.Values[EvictedIndex]; - - List->Radixes.Values[EvictedIndex] = Radix; - List->IDs.Values[EvictedIndex] = List->IDs.Values[CurrentIndex]; - - List->Radixes.Values[CurrentIndex] = EvictedRadix; - List->IDs.Values[CurrentIndex] = EvictedID; - - OnesBoundary -= 1; - } - else - { - ZerosBoundary += 1; - } + u64 EvictedIndex = OnesBoundary; + u64 EvictedRadix = List->Radixes.Values[EvictedIndex]; + u64 EvictedID = List->IDs.Values[EvictedIndex]; + + List->Radixes.Values[EvictedIndex] = Radix; + List->IDs.Values[EvictedIndex] = List->IDs.Values[CurrentIndex]; + + List->Radixes.Values[CurrentIndex] = EvictedRadix; + List->IDs.Values[CurrentIndex] = EvictedID; + + OnesBoundary -= 1; } - - if (Iteration > 0) + else { - RadixSortInPlace_(List, Start, ZerosBoundary, Iteration - 1); - RadixSortInPlace_(List, ZerosBoundary, End, Iteration - 1); + ZerosBoundary += 1; } + } + + if (Iteration > 0) + { + RadixSortInPlace_(List, Start, ZerosBoundary, Iteration - 1); + RadixSortInPlace_(List, ZerosBoundary, End, Iteration - 1); + } } static void RadixSortInPlace (gs_radix_list* List) { - u32 Highest = 0; - for (u32 i = 0; i < List->Radixes.Count; i++) + u32 Highest = 0; + for (u32 i = 0; i < List->Radixes.Count; i++) + { + if (List->Radixes.Values[i] > Highest) { - if (List->Radixes.Values[i] > Highest) - { - Highest = List->Radixes.Values[i]; - } + Highest = List->Radixes.Values[i]; } - - u32 Iterations = 0; - while (Highest > 1) - { - ++Iterations; - Highest = Highest >> 1; - } - - RadixSortInPlace_(List, 0, List->Radixes.Count, Iterations); + } + + u32 Iterations = 0; + while (Highest > 1) + { + ++Iterations; + Highest = Highest >> 1; + } + + RadixSortInPlace_(List, 0, List->Radixes.Count, Iterations); } @@ -3967,105 +3442,105 @@ RadixSortInPlace (gs_radix_list* List) inline bool KeyIsMouseButton(gs_key Key) { - bool Result = (Key >= gs_Key_MouseLeftButton); - Result = Result && Key <= gs_Key_MouseRightButton; - return Result; + bool Result = (Key >= gs_Key_MouseLeftButton); + Result = Result && Key <= gs_Key_MouseRightButton; + return Result; } inline u32 GetMouseButtonIndex(gs_key Button) { - Assert(KeyIsMouseButton(Button)); - u32 Result = Button - gs_Key_MouseLeftButton; - return Result; + Assert(KeyIsMouseButton(Button)); + u32 Result = Button - gs_Key_MouseLeftButton; + return Result; } inline bool MouseButtonTransitionedDown(gs_mouse_state Mouse, u32 Index) { - bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; - bool WasDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_WasDownBit)) != 0; - return IsDown && !WasDown; + bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; + bool WasDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_WasDownBit)) != 0; + return IsDown && !WasDown; } inline bool MouseButtonTransitionedDown(gs_mouse_state Mouse, gs_key Button) { - u32 Index = GetMouseButtonIndex(Button); - return MouseButtonTransitionedDown(Mouse, Index); + u32 Index = GetMouseButtonIndex(Button); + return MouseButtonTransitionedDown(Mouse, Index); } inline bool MouseButtonIsDown(gs_mouse_state Mouse, u32 Index) { - bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; - return IsDown; + bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; + return IsDown; } inline bool MouseButtonIsDown(gs_mouse_state Mouse, gs_key Button) { - u32 Index = GetMouseButtonIndex(Button); - return MouseButtonIsDown(Mouse, Index); + u32 Index = GetMouseButtonIndex(Button); + return MouseButtonIsDown(Mouse, Index); } inline bool MouseButtonTransitionedUp(gs_mouse_state Mouse, u32 Index) { - bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; - bool WasDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_WasDownBit)) != 0; - return !IsDown && WasDown; + bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; + bool WasDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_WasDownBit)) != 0; + return !IsDown && WasDown; } inline bool MouseButtonTransitionedUp(gs_mouse_state Mouse, gs_key Button) { - u32 Index = GetMouseButtonIndex(Button); - return MouseButtonTransitionedUp(Mouse, Index); + u32 Index = GetMouseButtonIndex(Button); + return MouseButtonTransitionedUp(Mouse, Index); } inline bool MouseButtonIsUp(gs_mouse_state Mouse, u32 Index) { - bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; - return !IsDown; + bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; + return !IsDown; } inline bool MouseButtonIsUp(gs_mouse_state Mouse, gs_key Button) { - u32 Index = GetMouseButtonIndex(Button); - return MouseButtonIsUp(Mouse, Index); + u32 Index = GetMouseButtonIndex(Button); + return MouseButtonIsUp(Mouse, Index); } internal void SetMouseButtonTransitionedDown(gs_mouse_state* Mouse, gs_key Button) { - u32 Index = GetMouseButtonIndex(Button); - - Mouse->ButtonStates[Index] = 0; - Mouse->ButtonStates[Index] |= MouseButton_IsDown << MouseButton_IsDownBit; - Mouse->ButtonStates[Index] |= MouseButton_WasNotDown << MouseButton_WasDownBit; + u32 Index = GetMouseButtonIndex(Button); + + Mouse->ButtonStates[Index] = 0; + Mouse->ButtonStates[Index] |= MouseButton_IsDown << MouseButton_IsDownBit; + Mouse->ButtonStates[Index] |= MouseButton_WasNotDown << MouseButton_WasDownBit; } internal void SetMouseButtonTransitionedUp(gs_mouse_state* Mouse, gs_key Button) { - u32 Index = GetMouseButtonIndex(Button); - - Mouse->ButtonStates[Index] = 0; - Mouse->ButtonStates[Index] |= MouseButton_IsNotDown << MouseButton_IsDownBit; - Mouse->ButtonStates[Index] |= MouseButton_WasDown << MouseButton_WasDownBit; + u32 Index = GetMouseButtonIndex(Button); + + Mouse->ButtonStates[Index] = 0; + Mouse->ButtonStates[Index] |= MouseButton_IsNotDown << MouseButton_IsDownBit; + Mouse->ButtonStates[Index] |= MouseButton_WasDown << MouseButton_WasDownBit; } internal void AdvanceMouseButtonState(gs_mouse_state* Mouse, gs_key Button) { - u32 Index = GetMouseButtonIndex(Button); - - if (MouseButtonIsDown(*Mouse, Index)) - { - Mouse->ButtonStates[Index] |= MouseButton_WasDown << MouseButton_WasDownBit; - } - else - { - Mouse->ButtonStates[Index] &= MouseButton_WasNotDown << MouseButton_WasDownBit; - } + u32 Index = GetMouseButtonIndex(Button); + + if (MouseButtonIsDown(*Mouse, Index)) + { + Mouse->ButtonStates[Index] |= MouseButton_WasDown << MouseButton_WasDownBit; + } + else + { + Mouse->ButtonStates[Index] &= MouseButton_WasNotDown << MouseButton_WasDownBit; + } } internal void AdvanceMouseButtonsState(gs_mouse_state* Mouse) { - AdvanceMouseButtonState(Mouse, gs_Key_MouseLeftButton); - AdvanceMouseButtonState(Mouse, gs_Key_MouseMiddleButton); - AdvanceMouseButtonState(Mouse, gs_Key_MouseRightButton); + AdvanceMouseButtonState(Mouse, gs_Key_MouseLeftButton); + AdvanceMouseButtonState(Mouse, gs_Key_MouseMiddleButton); + AdvanceMouseButtonState(Mouse, gs_Key_MouseRightButton); } /////////////////////////// @@ -4076,17 +3551,17 @@ AdvanceMouseButtonsState(gs_mouse_state* Mouse) 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; + 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; + unsigned char *s = (unsigned char *)&In; + u16 Result = (u16)(s[0] << 8 | s[1]); + return Result; } diff --git a/src/gs_libs/gs_types.h b/src/gs_libs/gs_types.h index 7356fbb..2a1051e 100644 --- a/src/gs_libs/gs_types.h +++ b/src/gs_libs/gs_types.h @@ -66,46 +66,46 @@ typedef double r64; enum gs_basic_type { - gs_BasicType_char, - gs_BasicType_b8, - gs_BasicType_b32, - gs_BasicType_b64, - gs_BasicType_u8, - gs_BasicType_u16, - gs_BasicType_u32, - gs_BasicType_u64, - gs_BasicType_s8, - gs_BasicType_s16, - gs_BasicType_s32, - gs_BasicType_s64, - gs_BasicType_r32, - gs_BasicType_r64, - - gs_BasicType_Count, + gs_BasicType_char, + gs_BasicType_b8, + gs_BasicType_b32, + gs_BasicType_b64, + gs_BasicType_u8, + gs_BasicType_u16, + gs_BasicType_u32, + gs_BasicType_u64, + gs_BasicType_s8, + gs_BasicType_s16, + gs_BasicType_s32, + gs_BasicType_s64, + gs_BasicType_r32, + gs_BasicType_r64, + + gs_BasicType_Count, }; global_const u64 gs_BasicTypeSizes[] = { - sizeof(char), - sizeof(b8), - sizeof(b32), - sizeof(b64), - sizeof(u8), - sizeof(u16), - sizeof(u32), - sizeof(u64), - sizeof(s8), - sizeof(s16), - sizeof(s32), - sizeof(s64), - sizeof(r32), - sizeof(r64), + sizeof(char), + sizeof(b8), + sizeof(b32), + sizeof(b64), + sizeof(u8), + sizeof(u16), + sizeof(u32), + sizeof(u64), + sizeof(s8), + sizeof(s16), + sizeof(s32), + sizeof(s64), + sizeof(r32), + sizeof(r64), }; internal u64 BasicTypeSize(gs_basic_type Type) { - return gs_BasicTypeSizes[(u32)Type]; + return gs_BasicTypeSizes[(u32)Type]; } global_const u8 MaxU8 = 0xFF; @@ -143,69 +143,69 @@ global_const r64 SecondsToNanos = 10000000.0; internal r32 DegToRadR32(r32 Degrees) { - return (Degrees * (PiR32 / 180.0f)); + return (Degrees * (PiR32 / 180.0f)); } internal r32 RadToDegR32(r32 Radians) { - return (Radians * (180.0f / PiR32)); + return (Radians * (180.0f / PiR32)); } struct s8_array { - s8* Values; - u32 Count; - u32 CountMax; + s8* Values; + u32 Count; + u32 CountMax; }; struct s16_array { - s16* Values; - u32 Count; - u32 CountMax; + s16* Values; + u32 Count; + u32 CountMax; }; struct s32_array { - s32* Values; - u32 Count; - u32 CountMax; + s32* Values; + u32 Count; + u32 CountMax; }; struct s64_array { - s64* Values; - u32 Count; - u32 CountMax; + s64* Values; + u32 Count; + u32 CountMax; }; struct u8_array { - u8* Values; - u32 Count; - u32 CountMax; + u8* Values; + u32 Count; + u32 CountMax; }; struct u16_array { - u16* Values; - u32 Count; - u32 CountMax; + u16* Values; + u32 Count; + u32 CountMax; }; struct u32_array { - u32* Values; - u32 Count; - u32 CountMax; + u32* Values; + u32 Count; + u32 CountMax; }; struct u64_array { - u64* Values; - u32 Count; - u32 CountMax; + u64* Values; + u32 Count; + u32 CountMax; }; @@ -279,19 +279,19 @@ Glue(gs_AssertFail_, __LINE__) = 1 / (int)(!!(c)), \ internal void ZeroMemory_(u8* Memory, u64 Size) { - for (u64 i = 0; i < Size; i++) - { - Memory[i] = 0; - } + for (u64 i = 0; i < Size; i++) + { + Memory[i] = 0; + } } internal void CopyMemory_(u8* From, u8* To, u64 Size) { - for (u64 i = 0; i < Size; i++) - { - To[i] = From[i]; - } + for (u64 i = 0; i < Size; i++) + { + To[i] = From[i]; + } } #define StaticArrayLength(arr) sizeof(arr) / sizeof((arr)[0]) @@ -309,8 +309,8 @@ CopyMemory_(u8* From, u8* To, u64 Size) #define SLLPop_(list_tail) list_tail=list_tail=list_tail->next #define SLLPop(list_tail) (SLLPop_((list_tail))) -#define SLLNext(ele_at) ele_at = ele_at->Next; -#define SLLPrev(ele_at) ele_at = ele_at->Prev; +#define SLLNext(ele_at) ele_at = ele_at->Next +#define SLLPrev(ele_at) ele_at = ele_at->Prev #define SLLInit(head,tail,first_ele) head=first_ele, tail=first_ele; @@ -322,80 +322,80 @@ else { SLLInit(first,last,new_ele); } union v2 { - struct - { - r32 x; - r32 y; - }; - r32 E[2]; + struct + { + r32 x; + r32 y; + }; + r32 E[2]; }; union v3 { - struct - { - r32 x; - r32 y; - r32 z; - }; - struct - { - r32 r; - r32 g; - r32 b; - }; - struct - { - v2 xy; - r32 _z0; - }; - struct - { - r32 _x0; - v2 yz; - }; - r32 E[3]; + struct + { + r32 x; + r32 y; + r32 z; + }; + struct + { + r32 r; + r32 g; + r32 b; + }; + struct + { + v2 xy; + r32 _z0; + }; + struct + { + r32 _x0; + v2 yz; + }; + r32 E[3]; }; union v4 { - struct - { - r32 x; - r32 y; - r32 z; - r32 w; - }; - struct - { - r32 r; - r32 g; - r32 b; - r32 a; - }; - struct - { - v2 xy; - v2 zw; - }; - struct - { - r32 _x0; - v2 yz; - r32 _w0; - }; - struct - { - v3 xyz; - r32 _w1; - }; - r32 E[4]; + struct + { + r32 x; + r32 y; + r32 z; + r32 w; + }; + struct + { + r32 r; + r32 g; + r32 b; + r32 a; + }; + struct + { + v2 xy; + v2 zw; + }; + struct + { + r32 _x0; + v2 yz; + r32 _w0; + }; + struct + { + v3 xyz; + r32 _w1; + }; + r32 E[4]; }; struct v4_ray { - v4 Origin; - v4 Direction; + v4 Origin; + v4 Direction; }; #define WhiteV4 v4{1, 1, 1, 1} @@ -413,76 +413,76 @@ struct v4_ray struct v2_array { - v2* Vectors; - u32 Count; - u32 CountMax; + v2* Vectors; + u32 Count; + u32 CountMax; }; struct v3_array { - v3* Vectors; - u32 Count; - u32 CountMax; + v3* Vectors; + u32 Count; + u32 CountMax; }; struct v4_array { - v4* Vectors; - u32 Count; - u32 CountMax; + v4* Vectors; + u32 Count; + u32 CountMax; }; struct range1 { - r32 Min; - r32 Max; + r32 Min; + r32 Max; }; struct range2 { - v2 Min; - v2 Max; + v2 Min; + v2 Max; }; typedef range2 rect2; struct range3 { - v3 Min; - v3 Max; + v3 Min; + v3 Max; }; struct range4 { - v4 Min; - v4 Max; + v4 Min; + v4 Max; }; struct range1_array { - range1* Ranges; - u32 Count; - u32 CountMax; + range1* Ranges; + u32 Count; + u32 CountMax; }; struct range2_array { - range2* Ranges; - u32 Count; - u32 CountMax; + range2* Ranges; + u32 Count; + u32 CountMax; }; struct range3_array { - range3* Ranges; - u32 Count; - u32 CountMax; + range3* Ranges; + u32 Count; + u32 CountMax; }; struct range4_array { - range4* Ranges; - u32 Count; - u32 CountMax; + range4* Ranges; + u32 Count; + u32 CountMax; }; #define Range1Expand(r) (r).Min, (r).Max @@ -496,39 +496,39 @@ struct range4_array union m33 { - float Array[9]; - struct - { - r32 AXx; r32 AYx; r32 AZx; - r32 AXy; r32 AYy; r32 AZy; - r32 AXz; r32 AYz; r32 AZz; - }; + float Array[9]; + struct + { + r32 AXx; r32 AYx; r32 AZx; + r32 AXy; r32 AYy; r32 AZy; + r32 AXz; r32 AYz; r32 AZz; + }; }; union m44 { - float Array[16]; - struct - { - r32 AXx; r32 AYx; r32 AZx; r32 Tx; - r32 AXy; r32 AYy; r32 AZy; r32 Ty; - r32 AXz; r32 AYz; r32 AZz; r32 Tz; - r32 AXw; r32 AYw; r32 AZw; r32 Tw; - }; + float Array[16]; + struct + { + r32 AXx; r32 AYx; r32 AZx; r32 Tx; + r32 AXy; r32 AYy; r32 AZy; r32 Ty; + r32 AXz; r32 AYz; r32 AZz; r32 Tz; + r32 AXw; r32 AYw; r32 AZw; r32 Tw; + }; }; struct m33_array { - m33* Matrices; - u32 Count; - u32 CountMax; + m33* Matrices; + u32 Count; + u32 CountMax; }; struct m44_array { - m44* Matrices; - u32 Count; - u32 CountMax; + m44* Matrices; + u32 Count; + u32 CountMax; }; ////////////////////////// @@ -537,70 +537,70 @@ struct m44_array struct gs_const_string { - union - { - char* Str; - u8* Data;; - }; - u64 Length; + union + { + char* Str; + u8* Data;; + }; + u64 Length; }; struct gs_string { - union + union + { + gs_const_string ConstString; + struct { - gs_const_string ConstString; - struct - { - char* Str; - u64 Length; - }; + char* Str; + u64 Length; }; - u64 Size; + }; + u64 Size; }; struct gs_const_string_array { - gs_const_string* Strings; - u64 Count; - u64 CountMax; + gs_const_string* Strings; + u64 Count; + u64 CountMax; }; struct gs_string_array { - gs_string* Strings; - u64 Count; - u64 CountMax; + gs_string* Strings; + u64 Count; + u64 CountMax; }; internal u64 CStringLength(char* Str) { - char* At = Str; - while (*At) { At++; } - u64 Result = PointerDifference(At, Str); - return Result; + char* At = Str; + while (*At) { At++; } + u64 Result = PointerDifference(At, Str); + return Result; } internal bool CStringsEqual(char* A, char* B) { - bool Result = true; - - char* AAt = A; - char* BAt = B; - while (AAt[0] && BAt[0]) + bool Result = true; + + char* AAt = A; + char* BAt = B; + while (AAt[0] && BAt[0]) + { + if (AAt[0] != BAt[0]) { - if (AAt[0] != BAt[0]) - { - Result = false; - break; - } - AAt++; - BAt++; + Result = false; + break; } - if (AAt[0] != 0 || BAt[0] != 0) { Result = false; } - return Result; + AAt++; + BAt++; + } + if (AAt[0] != 0 || BAt[0] != 0) { Result = false; } + return Result; } #define StringExpand(str) (int)(str).Length, (str).Str @@ -626,120 +626,35 @@ typedef struct gs_thread_context gs_thread_context; struct gs_data { - u8* Memory; - u64 Size; + u8* Memory; + u64 Size; }; struct gs_data_array { - gs_data* Data; - u64 Count; - u64 CountMax; + gs_data* Data; + u64 Count; + u64 CountMax; }; enum gs_access_flag { - gs_AccessFlag_Read = 1 << 0, - gs_AccessFlag_Write = 1 << 1, - gs_AccessFlag_Exec = 1 << 2, + gs_AccessFlag_Read = 1 << 0, + gs_AccessFlag_Write = 1 << 1, + gs_AccessFlag_Exec = 1 << 2, }; typedef s32 gs_scan_direction; enum { - gs_Scan_Backward = -1, - gs_Scan_Forward = 1, + gs_Scan_Backward = -1, + gs_Scan_Forward = 1, }; -#define ALLOCATOR_ALLOC(name) void* name(u64 Size, u64* ResultSize) -typedef ALLOCATOR_ALLOC(allocator_allocate); -#define ALLOCATOR_FREE(name) void name(void* Ptr, u64 Size) -typedef ALLOCATOR_FREE(allocator_free); +internal u64 RoundUpTo64(u64 Value, u64 Alignment); -struct gs_debug_allocation -{ - gs_const_string Location; - u64 Size; -}; - -struct gs_allocator_debug -{ - u64 TotalAllocSize; - - u64 AllocationsCount; - u64 AllocationsCountMax; - gs_debug_allocation* Allocations; -}; - -struct gs_allocator -{ - allocator_allocate* Alloc; - allocator_free* Free; - - gs_allocator_debug* Debug; -}; - -struct gs_memory_cursor -{ - gs_data Data; - u64 Position; -}; - -/* TODO(pjs): Setting MEMORY_CURSOR_STATIC_ARRAY will still compile, - However, it introduces a bug that I haven't fully diagnosed. -The problem seems to occur when trying to push to a cleared memory arena -Where the FirstCursor doesn't have enough room for the allocation, but -also FirstCursor->Next points to a valid cursor. The new cursor is put -in the middle however we seem to continually keep allocating new -cursors forever and losing old ones. -The problem in Lumenarium is found in the OutputData structure - -Leaving this in a simplified state for now -*/ -#define MEMORY_CURSOR_STATIC_ARRAY 1 - -struct gs_memory_cursor_list -{ - gs_memory_cursor Cursor; -#if !MEMORY_CURSOR_STATIC_ARRAY - gs_memory_cursor_list* Next; - gs_memory_cursor_list* Prev; -#endif -}; - -enum arena_type -{ - Arena_BaseArena, - Arena_SubArena, -}; - -struct gs_memory_arena -{ - arena_type Type; - gs_allocator Allocator; - gs_memory_arena* Parent; - -#if MEMORY_CURSOR_STATIC_ARRAY - gs_memory_cursor_list* Cursors; - u64 CursorsCount; - u64 CursorsCountMax; -#else - gs_memory_cursor_list* CursorList; -#endif - - u64 MemoryChunkSize; - u64 MemoryAlignment; - - char* ArenaName; -}; - -struct gs_memory_arena_array -{ - gs_memory_arena* Arenas; - u32 Count; - u32 Size; -}; +#include "gs_memory.h" /////////////////////////////// // @@ -748,16 +663,16 @@ struct gs_memory_arena_array struct gs_string_builder_buffer { - gs_string String; - gs_string_builder_buffer* Next; + gs_string String; + gs_string_builder_buffer* Next; }; struct gs_string_builder { - gs_memory_arena* Arena; - u32 BufferSize; - gs_string_builder_buffer* Root; - gs_string_builder_buffer* Head; + gs_memory_arena* Arena; + u32 BufferSize; + gs_string_builder_buffer* Root; + gs_string_builder_buffer* Head; }; /////////////////////////////// @@ -772,8 +687,8 @@ typedef DEBUG_PRINT(debug_print); struct debug_output { - gs_memory_arena* Storage; - debug_print* Print; + gs_memory_arena* Storage; + debug_print* Print; }; /////////////////////////////// @@ -788,34 +703,34 @@ struct debug_output struct gs_dynarray_buffer { - u8* Memory; + u8* Memory; }; struct gs_dynarray { - gs_memory_arena Arena; - - gs_dynarray_buffer* Buffers; - u64 BuffersCount; - u64 ElementCount; - - u64 ElementSize; - u64 ElementsPerBuffer; + gs_memory_arena Arena; + + gs_dynarray_buffer* Buffers; + u64 BuffersCount; + u64 ElementCount; + + u64 ElementSize; + u64 ElementsPerBuffer; }; struct gs_dynarray_handle { - u64 BufferIndex; - u64 IndexInBuffer; + u64 BufferIndex; + u64 IndexInBuffer; }; #define INVALID_DYNARRAY_HANDLE gs_dynarray_handle{0, 0} struct gs_dynarray_handle_list { - gs_dynarray_handle* Handles; - u32 Count; - u32 Size; + gs_dynarray_handle* Handles; + u32 Count; + u32 Size; }; /////////////////////////////// @@ -828,39 +743,39 @@ struct gs_dynarray_handle_list enum enumerate_directory_flag { - EnumerateDirectory_Recurse = 1 << 0, - EnumerateDirectory_IncludeDirectories = 1 << 1, + EnumerateDirectory_Recurse = 1 << 0, + EnumerateDirectory_IncludeDirectories = 1 << 1, }; struct gs_file_info { - gs_const_string Path; - gs_const_string AbsolutePath; - u64 FileSize; - u64 CreationTime; - u64 LastWriteTime; - b32 IsDirectory; + gs_const_string Path; + gs_const_string AbsolutePath; + u64 FileSize; + u64 CreationTime; + u64 LastWriteTime; + b32 IsDirectory; }; struct gs_file_info_array { - gs_file_info* Values; - u32 Count; - u32 MaxCount; + gs_file_info* Values; + u32 Count; + u32 MaxCount; }; struct gs_file { - union + union + { + gs_data Data; + struct { - gs_data Data; - struct - { - u8* Memory; - u64 Size; - }; + u8* Memory; + u64 Size; }; - gs_file_info FileInfo; + }; + gs_file_info FileInfo; }; typedef struct gs_file_handler gs_file_handler; @@ -879,11 +794,11 @@ typedef ENUMERATE_DIRECTORY(file_handler_enumerate_directory); struct gs_file_handler { - file_handler_get_file_info* GetFileInfo; - file_handler_read_entire_file* ReadEntireFile; - file_handler_write_entire_file* WriteEntireFile; - file_handler_enumerate_directory* EnumerateDirectory; - gs_memory_arena* Transient; + file_handler_get_file_info* GetFileInfo; + file_handler_read_entire_file* ReadEntireFile; + file_handler_write_entire_file* WriteEntireFile; + file_handler_enumerate_directory* EnumerateDirectory; + gs_memory_arena* Transient; }; @@ -899,8 +814,8 @@ typedef GET_SECONDS_ELAPSED(get_seconds_elapsed); struct gs_time_handler { - get_wall_clock* GetWallClock; - get_seconds_elapsed* GetSecondsElapsed; + get_wall_clock* GetWallClock; + get_seconds_elapsed* GetSecondsElapsed; }; /////////////////////////////// @@ -909,7 +824,7 @@ struct gs_time_handler struct gs_random_series { - u32 Value; + u32 Value; }; /////////////////////////////// @@ -918,8 +833,8 @@ struct gs_random_series struct gs_radix_list { - u64_array Radixes; - u64_array IDs; + u64_array Radixes; + u64_array IDs; }; @@ -929,115 +844,115 @@ struct gs_radix_list enum gs_event_type { - gs_EventType_Unknown, - - // Reached end of event stream - gs_EventType_NoMoreEvents, - // There was an event but it requires no action from the using program - gs_EventType_NoEvent, - - gs_EventType_KeyPressed, - gs_EventType_KeyReleased, - - gs_EventType_MouseMoved, - gs_EventType_MouseWheel, - - gs_EventType_Count, + gs_EventType_Unknown, + + // Reached end of event stream + gs_EventType_NoMoreEvents, + // There was an event but it requires no action from the using program + gs_EventType_NoEvent, + + gs_EventType_KeyPressed, + gs_EventType_KeyReleased, + + gs_EventType_MouseMoved, + gs_EventType_MouseWheel, + + gs_EventType_Count, }; enum gs_key { - gs_Key_Invalid, - - gs_Key_Esc, - - gs_Key_Space, - gs_Key_Tab, - gs_Key_CapsLock, - gs_Key_Shift, gs_Key_LeftShift, gs_Key_RightShift, - gs_Key_Control, gs_Key_LeftCtrl, gs_Key_RightCtrl, - gs_Key_Fn, - gs_Key_Alt, - gs_Key_PageUp, gs_Key_PageDown, - gs_Key_End, gs_Key_Home, gs_Key_Select, - gs_Key_Backspace, gs_Key_Delete, - gs_Key_Enter, - - // Function Keys - gs_Key_F0, gs_Key_F1, gs_Key_F2, gs_Key_F3, gs_Key_F4, gs_Key_F5, gs_Key_F6, gs_Key_F7, - gs_Key_F8, gs_Key_F9, gs_Key_F10, gs_Key_F11, gs_Key_F12, - - // Letters - gs_Key_a, gs_Key_b, gs_Key_c, gs_Key_d, gs_Key_e, gs_Key_f, gs_Key_g, gs_Key_h, - gs_Key_i, gs_Key_j, gs_Key_k, gs_Key_l, gs_Key_m, gs_Key_n, gs_Key_o, gs_Key_p, - gs_Key_q, gs_Key_r, gs_Key_s, gs_Key_t, gs_Key_u, gs_Key_v, gs_Key_w, gs_Key_x, - gs_Key_y, gs_Key_z, - - gs_Key_A, gs_Key_B, gs_Key_C, gs_Key_D, gs_Key_E, gs_Key_F, gs_Key_G, gs_Key_H, - gs_Key_I, gs_Key_J, gs_Key_K, gs_Key_L, gs_Key_M, gs_Key_N, gs_Key_O, gs_Key_P, - gs_Key_Q, gs_Key_R, gs_Key_S, gs_Key_T, gs_Key_U, gs_Key_V, gs_Key_W, gs_Key_X, - gs_Key_Y, gs_Key_Z, - - // Numbers - gs_Key_0, gs_Key_1, gs_Key_2, gs_Key_3, gs_Key_4, gs_Key_5, gs_Key_6, gs_Key_7, - gs_Key_8, gs_Key_9, - - gs_Key_Num0, gs_Key_Num1, gs_Key_Num2, gs_Key_Num3, gs_Key_Num4, gs_Key_Num5, - gs_Key_Num6, gs_Key_Num7, gs_Key_Num8, gs_Key_Num9, - - // Symbols - gs_Key_Bang, gs_Key_At, gs_Key_Pound, gs_Key_Dollar, gs_Key_Percent, gs_Key_Carrot, - gs_Key_Ampersand, gs_Key_Star, gs_Key_LeftParen, gs_Key_RightParen, gs_Key_Minus, gs_Key_Plus, - gs_Key_Equals, gs_Key_Underscore, gs_Key_OpenSquareBracket, gs_Key_CloseSquareBracket, gs_Key_OpenCurlyBracket, - gs_Key_CloseCurlyBracket, gs_Key_Colon, gs_Key_SemiColon, gs_Key_SingleQuote, gs_Key_DoubleQuote, - gs_Key_ForwardSlash, gs_Key_Backslash, gs_Key_Pipe, gs_Key_Comma, gs_Key_Period, - gs_Key_QuestionMark, gs_Key_LessThan, gs_Key_GreaterThan, gs_Key_Tilde, gs_Key_BackQuote, - - // Arrows - gs_Key_UpArrow, - gs_Key_DownArrow, - gs_Key_LeftArrow, - gs_Key_RightArrow, - - // Mouse - // NOTE(Peter): Including this here so we can utilize the same KeyDown, KeyUp etc. functions - gs_Key_MouseLeftButton, - gs_Key_MouseMiddleButton, - gs_Key_MouseRightButton, - gs_Key_MouseX1Button, - gs_Key_MouseX2Button, - - gs_Key_Count, + gs_Key_Invalid, + + gs_Key_Esc, + + gs_Key_Space, + gs_Key_Tab, + gs_Key_CapsLock, + gs_Key_Shift, gs_Key_LeftShift, gs_Key_RightShift, + gs_Key_Control, gs_Key_LeftCtrl, gs_Key_RightCtrl, + gs_Key_Fn, + gs_Key_Alt, + gs_Key_PageUp, gs_Key_PageDown, + gs_Key_End, gs_Key_Home, gs_Key_Select, + gs_Key_Backspace, gs_Key_Delete, + gs_Key_Enter, + + // Function Keys + gs_Key_F0, gs_Key_F1, gs_Key_F2, gs_Key_F3, gs_Key_F4, gs_Key_F5, gs_Key_F6, gs_Key_F7, + gs_Key_F8, gs_Key_F9, gs_Key_F10, gs_Key_F11, gs_Key_F12, + + // Letters + gs_Key_a, gs_Key_b, gs_Key_c, gs_Key_d, gs_Key_e, gs_Key_f, gs_Key_g, gs_Key_h, + gs_Key_i, gs_Key_j, gs_Key_k, gs_Key_l, gs_Key_m, gs_Key_n, gs_Key_o, gs_Key_p, + gs_Key_q, gs_Key_r, gs_Key_s, gs_Key_t, gs_Key_u, gs_Key_v, gs_Key_w, gs_Key_x, + gs_Key_y, gs_Key_z, + + gs_Key_A, gs_Key_B, gs_Key_C, gs_Key_D, gs_Key_E, gs_Key_F, gs_Key_G, gs_Key_H, + gs_Key_I, gs_Key_J, gs_Key_K, gs_Key_L, gs_Key_M, gs_Key_N, gs_Key_O, gs_Key_P, + gs_Key_Q, gs_Key_R, gs_Key_S, gs_Key_T, gs_Key_U, gs_Key_V, gs_Key_W, gs_Key_X, + gs_Key_Y, gs_Key_Z, + + // Numbers + gs_Key_0, gs_Key_1, gs_Key_2, gs_Key_3, gs_Key_4, gs_Key_5, gs_Key_6, gs_Key_7, + gs_Key_8, gs_Key_9, + + gs_Key_Num0, gs_Key_Num1, gs_Key_Num2, gs_Key_Num3, gs_Key_Num4, gs_Key_Num5, + gs_Key_Num6, gs_Key_Num7, gs_Key_Num8, gs_Key_Num9, + + // Symbols + gs_Key_Bang, gs_Key_At, gs_Key_Pound, gs_Key_Dollar, gs_Key_Percent, gs_Key_Carrot, + gs_Key_Ampersand, gs_Key_Star, gs_Key_LeftParen, gs_Key_RightParen, gs_Key_Minus, gs_Key_Plus, + gs_Key_Equals, gs_Key_Underscore, gs_Key_OpenSquareBracket, gs_Key_CloseSquareBracket, gs_Key_OpenCurlyBracket, + gs_Key_CloseCurlyBracket, gs_Key_Colon, gs_Key_SemiColon, gs_Key_SingleQuote, gs_Key_DoubleQuote, + gs_Key_ForwardSlash, gs_Key_Backslash, gs_Key_Pipe, gs_Key_Comma, gs_Key_Period, + gs_Key_QuestionMark, gs_Key_LessThan, gs_Key_GreaterThan, gs_Key_Tilde, gs_Key_BackQuote, + + // Arrows + gs_Key_UpArrow, + gs_Key_DownArrow, + gs_Key_LeftArrow, + gs_Key_RightArrow, + + // Mouse + // NOTE(Peter): Including this here so we can utilize the same KeyDown, KeyUp etc. functions + gs_Key_MouseLeftButton, + gs_Key_MouseMiddleButton, + gs_Key_MouseRightButton, + gs_Key_MouseX1Button, + gs_Key_MouseX2Button, + + gs_Key_Count, }; enum gs_modifier_key_flags { - gs_ModifierKeyFlag_Shift = 1 << 0, - gs_ModifierKeyFlag_Ctrl = 1 << 1, - gs_ModifierKeyFlag_Alt = 1 << 2, + gs_ModifierKeyFlag_Shift = 1 << 0, + gs_ModifierKeyFlag_Ctrl = 1 << 1, + gs_ModifierKeyFlag_Alt = 1 << 2, }; struct gs_input_event { - gs_event_type Type; - gs_key Key; - v2 Position; - r32 Amount; - b32 Modifiers; + gs_event_type Type; + gs_key Key; + v2 Position; + r32 Amount; + b32 Modifiers; }; struct gs_input_event_buffer { - gs_input_event* Values; - u32 Count; - u32 MaxCount; + gs_input_event* Values; + u32 Count; + u32 MaxCount; }; struct gs_mouse_state { - v2 Position; - b32 ButtonStates[3]; - v2 DownPosition; + v2 Position; + b32 ButtonStates[3]; + v2 DownPosition; }; #define MouseButton_IsDownBit 0 @@ -1053,29 +968,29 @@ struct gs_mouse_state struct gs_thread_info { - u32 ThreadID; + u32 ThreadID; }; struct gs_thread_context { - gs_thread_info ThreadInfo; - - // TODO(Peter): Pull these handlers out into just a gs_context struct so - // they can be shared across threads. - // specifically the allocator - gs_allocator Allocator; - gs_file_handler FileHandler; - debug_output DebugOutput; - gs_time_handler TimeHandler; - - gs_memory_arena* Transient; + gs_thread_info ThreadInfo; + + // TODO(Peter): Pull these handlers out into just a gs_context struct so + // they can be shared across threads. + // specifically the allocator + gs_allocator Allocator; + gs_file_handler FileHandler; + debug_output DebugOutput; + gs_time_handler TimeHandler; + + gs_memory_arena* Transient; }; // Threads typedef struct platform_thread_handle { - u32 Index; + u32 Index; } platform_thread_handle; typedef struct platform_thread_manager platform_thread_manager; @@ -1085,9 +1000,9 @@ typedef THREAD_PROC_(thread_proc_); typedef struct platform_thread { - u8* PlatformHandle; - thread_proc_* Proc; - u8* UserData; + u8* PlatformHandle; + thread_proc_* Proc; + u8* UserData; } platform_thread; #define CREATE_THREAD(name) bool name(platform_thread* Thread, thread_proc_* Proc, u8* UserData, gs_thread_context Ctx) @@ -1099,11 +1014,11 @@ typedef KILL_THREAD(platform_kill_thread); #define THREADS_MAX 32 typedef struct platform_thread_manager { - b8 ThreadsUsed[THREADS_MAX]; - platform_thread Threads[THREADS_MAX]; - - platform_create_thread* CreateThreadProc; - platform_kill_thread* KillThreadProc; + b8 ThreadsUsed[THREADS_MAX]; + platform_thread Threads[THREADS_MAX]; + + platform_create_thread* CreateThreadProc; + platform_kill_thread* KillThreadProc; } platform_thread_manager; // Work Queue @@ -1112,9 +1027,9 @@ typedef struct gs_work_queue gs_work_queue; typedef struct gs_worker_thread { - gs_thread_context Context; - gs_work_queue* Queue; - b32 ShouldExit; + gs_thread_context Context; + gs_work_queue* Queue; + b32 ShouldExit; } gs_worker_thread; #define THREAD_PROC(name) void name(gs_thread_context Context, gs_data Data) @@ -1122,9 +1037,9 @@ typedef THREAD_PROC(thread_proc); struct gs_threaded_job { - thread_proc* WorkProc; - gs_data Data; - gs_const_string JobName; + thread_proc* WorkProc; + gs_data Data; + gs_const_string JobName; }; #define PUSH_WORK_ON_QUEUE(name) void name(gs_work_queue* Queue, thread_proc* WorkProc, gs_data Data, gs_const_string JobName) @@ -1138,32 +1053,32 @@ typedef RESET_WORK_QUEUE(reset_work_queue); struct gs_work_queue { - void* SemaphoreHandle; - - u32 JobsMax; - u32 volatile JobsCount; - u32 volatile NextJobIndex; - u32 volatile JobsCompleted; - gs_threaded_job* Jobs; - - // Work Queue - push_work_on_queue* PushWorkOnQueue; - complete_queue_work* CompleteQueueWork; + void* SemaphoreHandle; + + u32 JobsMax; + u32 volatile JobsCount; + u32 volatile NextJobIndex; + u32 volatile JobsCompleted; + gs_threaded_job* Jobs; + + // Work Queue + push_work_on_queue* PushWorkOnQueue; + complete_queue_work* CompleteQueueWork; }; // Sockets typedef struct platform_socket_handle_ { - u32 Index; + u32 Index; } platform_socket_handle_; typedef struct platform_socket { - platform_socket_handle_ Handle; - char Addr[128]; - char Port[32]; - u8* PlatformHandle; + platform_socket_handle_ Handle; + char Addr[128]; + char Port[32]; + u8* PlatformHandle; } platform_socket; typedef struct platform_socket_manager platform_socket_manager; @@ -1193,15 +1108,15 @@ typedef SOCKET_SEND(platform_socket_send); #define SOCKETS_COUNT_MAX 32 typedef struct platform_socket_manager { - b8 SocketsUsed[SOCKETS_COUNT_MAX]; - platform_socket Sockets[SOCKETS_COUNT_MAX]; - - platform_connect_socket* ConnectSocketProc; - platform_close_socket* CloseSocketProc; - platform_socket_query_status* SocketQueryStatusProc; - platform_socket_peek* SocketPeekProc; - platform_socket_receive* SocketRecieveProc; - platform_socket_send* SocketSendProc; + b8 SocketsUsed[SOCKETS_COUNT_MAX]; + platform_socket Sockets[SOCKETS_COUNT_MAX]; + + platform_connect_socket* ConnectSocketProc; + platform_close_socket* CloseSocketProc; + platform_socket_query_status* SocketQueryStatusProc; + platform_socket_peek* SocketPeekProc; + platform_socket_receive* SocketRecieveProc; + platform_socket_send* SocketSendProc; } platform_socket_manager; #define GS_TYPES_H diff --git a/src/gs_libs/gs_win32.cpp b/src/gs_libs/gs_win32.cpp index 120bbd1..18074c6 100644 --- a/src/gs_libs/gs_win32.cpp +++ b/src/gs_libs/gs_win32.cpp @@ -9,39 +9,39 @@ struct win32_state { - b32 Initialized; - b32 Running; + b32 Initialized; + b32 Running; }; struct win32_opengl_window_info { - s32 ColorBits; - s32 AlphaBits; - s32 DepthBits; - HGLRC RenderContext; + s32 ColorBits; + s32 AlphaBits; + s32 DepthBits; + HGLRC RenderContext; }; struct window { - char* Name; - char* ClassName; - s32 Width; - s32 Height; - WNDPROC WindowEventHandler; - - WNDCLASS Class; - HWND Handle; - HDC DeviceContext; - - // TODO(peter): Make this a union? - win32_opengl_window_info OpenGLInfo; + char* Name; + char* ClassName; + s32 Width; + s32 Height; + WNDPROC WindowEventHandler; + + WNDCLASS Class; + HWND Handle; + HDC DeviceContext; + + // TODO(peter): Make this a union? + win32_opengl_window_info OpenGLInfo; }; struct handle_window_msg_result { - b32 NeedsUpdate; + b32 NeedsUpdate; #if DEBUG - char MessageType[128]; + char MessageType[128]; #endif }; @@ -54,8 +54,8 @@ internal s32 Win32ConcatStrings(s32 ALen, char* A, s32 BLen, char* B, s32 DestLe // Windowing & Graphics struct win32_offscreen_buffer { - texture_buffer Buffer; - BITMAPINFO Info; + texture_buffer Buffer; + BITMAPINFO Info; }; LRESULT CALLBACK Win32HandleWindowsEvents (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam); @@ -64,11 +64,6 @@ internal void Win32UpdateWindowDimension(window* Window); internal void Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height); internal void Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer, window Window); -// Memory - -internal ALLOCATOR_ALLOC(Win32Alloc); -internal ALLOCATOR_FREE(Win32Free); - /// // Utils /// @@ -76,32 +71,32 @@ internal ALLOCATOR_FREE(Win32Free); internal s32 Win32StringLength(char* String) { - char* At = String; - while (*At) { At++; }; - return At - String; + char* At = String; + while (*At) { At++; }; + return At - String; } internal s32 Win32ConcatStrings(s32 ALength, char* A, s32 BLength, char* B, s32 DestLength, char* Dest) { - char* Dst = Dest; - char* AAt = A; - int ALengthToCopy = ALength < DestLength ? ALength : DestLength; - for (s32 a = 0; a < ALength; a++) - { - *Dst++ = *AAt++; - } - char* BAt = B; - int DestLengthRemaining = DestLength - (Dst - Dest); - int BLengthToCopy = BLength < DestLengthRemaining ? BLength : DestLength; - for (s32 b = 0; b < BLengthToCopy; b++) - { - *Dst++ = *BAt++; - } - int DestLengthOut = Dst - Dest; - int NullTermIndex = DestLengthOut < DestLength ? DestLengthOut : DestLength; - Dest[NullTermIndex] = 0; - return DestLengthOut; + char* Dst = Dest; + char* AAt = A; + int ALengthToCopy = ALength < DestLength ? ALength : DestLength; + for (s32 a = 0; a < ALength; a++) + { + *Dst++ = *AAt++; + } + char* BAt = B; + int DestLengthRemaining = DestLength - (Dst - Dest); + int BLengthToCopy = BLength < DestLengthRemaining ? BLength : DestLength; + for (s32 b = 0; b < BLengthToCopy; b++) + { + *Dst++ = *BAt++; + } + int DestLengthOut = Dst - Dest; + int NullTermIndex = DestLengthOut < DestLength ? DestLengthOut : DestLength; + Dest[NullTermIndex] = 0; + return DestLengthOut; } /// @@ -112,158 +107,158 @@ internal window Win32CreateWindow (HINSTANCE HInstance, char* WindowName, s32 Width, s32 Height, WNDPROC WindowEventHandler) { - window Result = {}; - Result.Name = WindowName; - Result.ClassName = WindowName; - Result.Width = Width; - Result.Height = Height; - Result.WindowEventHandler = WindowEventHandler; - - Result.Class = {}; - Result.Class.style = CS_HREDRAW | CS_VREDRAW; - Result.Class.lpfnWndProc = WindowEventHandler; - Result.Class.hInstance = HInstance; - Result.Class.lpszClassName = WindowName; - - if (RegisterClass(&Result.Class)) - { - Result.Handle = CreateWindowEx( - 0, - Result.Class.lpszClassName, - WindowName, - WS_OVERLAPPEDWINDOW | WS_VISIBLE, - CW_USEDEFAULT, - CW_USEDEFAULT, - Width, - Height, - 0, - 0, - HInstance, - 0); - Result.DeviceContext = GetDC(Result.Handle); - } - - return Result; + window Result = {}; + Result.Name = WindowName; + Result.ClassName = WindowName; + Result.Width = Width; + Result.Height = Height; + Result.WindowEventHandler = WindowEventHandler; + + Result.Class = {}; + Result.Class.style = CS_HREDRAW | CS_VREDRAW; + Result.Class.lpfnWndProc = WindowEventHandler; + Result.Class.hInstance = HInstance; + Result.Class.lpszClassName = WindowName; + + if (RegisterClass(&Result.Class)) + { + Result.Handle = CreateWindowEx( + 0, + Result.Class.lpszClassName, + WindowName, + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, + CW_USEDEFAULT, + Width, + Height, + 0, + 0, + HInstance, + 0); + Result.DeviceContext = GetDC(Result.Handle); + } + + return Result; }; internal window PlatformCreateWindow (char* WindowName, s32 Width, s32 Height) { - HINSTANCE HInstance = GetModuleHandle(NULL); - return Win32CreateWindow(HInstance, WindowName, Width, Height, Win32HandleWindowsEvents); + HINSTANCE HInstance = GetModuleHandle(NULL); + return Win32CreateWindow(HInstance, WindowName, Width, Height, Win32HandleWindowsEvents); } internal void CreateOpenGLWindowContext (win32_opengl_window_info Info, window* Window) { - // Setup pixel format - { - PIXELFORMATDESCRIPTOR PixelFormatDesc = { 0 }; - // TODO: Program seems to work perfectly fine without all other params except dwFlags. - // Can we skip other params for the sake of brevity? - PixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); - PixelFormatDesc.nVersion = 1; - PixelFormatDesc.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; - PixelFormatDesc.iPixelType = PFD_TYPE_RGBA;// TODO(Peter): include this in win32_opengl_window_info? - PixelFormatDesc.cColorBits = Info.ColorBits; - PixelFormatDesc.cAlphaBits = Info.AlphaBits; - PixelFormatDesc.cDepthBits = Info.DepthBits; - PixelFormatDesc.dwLayerMask = PFD_MAIN_PLANE; // TODO(Peter): include this in win32_opengl_window_info? - // - - s32 PixelFormat = ChoosePixelFormat(Window->DeviceContext, &PixelFormatDesc); - if (!PixelFormat) { InvalidCodePath; } // TODO: Log: Choose pixel format failed - if (!SetPixelFormat(Window->DeviceContext, PixelFormat, &PixelFormatDesc)) { InvalidCodePath; } // TODO: Log: Set pixel format failed - } + // Setup pixel format + { + PIXELFORMATDESCRIPTOR PixelFormatDesc = { 0 }; + // TODO: Program seems to work perfectly fine without all other params except dwFlags. + // Can we skip other params for the sake of brevity? + PixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); + PixelFormatDesc.nVersion = 1; + PixelFormatDesc.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; + PixelFormatDesc.iPixelType = PFD_TYPE_RGBA;// TODO(Peter): include this in win32_opengl_window_info? + PixelFormatDesc.cColorBits = Info.ColorBits; + PixelFormatDesc.cAlphaBits = Info.AlphaBits; + PixelFormatDesc.cDepthBits = Info.DepthBits; + PixelFormatDesc.dwLayerMask = PFD_MAIN_PLANE; // TODO(Peter): include this in win32_opengl_window_info? + // - // Create rendering context - { - // TODO: Create "proper" context? - // https://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL)#Proper_Context_Creation - - Info.RenderContext = wglCreateContext(Window->DeviceContext); - wglMakeCurrent(Window->DeviceContext, Info.RenderContext); - - // TODO(Peter): do we want this? - /* - glGetIntegerv(GL_MAJOR_VERSION, ); - glGetIntegerv(GL_MINOR_VERSION, ); - (char*)glGetString(GL_VENDOR); - (char*)glGetString(GL_RENDERER); - */ - } + s32 PixelFormat = ChoosePixelFormat(Window->DeviceContext, &PixelFormatDesc); + if (!PixelFormat) { InvalidCodePath; } // TODO: Log: Choose pixel format failed + if (!SetPixelFormat(Window->DeviceContext, PixelFormat, &PixelFormatDesc)) { InvalidCodePath; } // TODO: Log: Set pixel format failed + } + + // Create rendering context + { + // TODO: Create "proper" context? + // https://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL)#Proper_Context_Creation - Window->OpenGLInfo = Info; + Info.RenderContext = wglCreateContext(Window->DeviceContext); + wglMakeCurrent(Window->DeviceContext, Info.RenderContext); + + // TODO(Peter): do we want this? + /* + glGetIntegerv(GL_MAJOR_VERSION, ); + glGetIntegerv(GL_MINOR_VERSION, ); + (char*)glGetString(GL_VENDOR); + (char*)glGetString(GL_RENDERER); + */ + } + + Window->OpenGLInfo = Info; } struct handle_window_event_result { - LRESULT Result; - b32 Handled; + LRESULT Result; + b32 Handled; }; internal void Win32UpdateInputFrameMouseButtonState (input_frame* InputFrame, key_code KeyCode, int Win32VirtualKey) { - InputFrame->KeysDown[KeyCode] = (GetKeyState(Win32VirtualKey) & (1 << 15)) != 0; + InputFrame->KeysDown[KeyCode] = (GetKeyState(Win32VirtualKey) & (1 << 15)) != 0; } internal void Win32UpdateInputFrameMouseState (input_frame* InputFrame) { - Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseLeftButton, VK_LBUTTON); - Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseMiddleButton, VK_MBUTTON); - Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseRightButton, VK_RBUTTON); - // NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are - // VK_XBUTTON1 and VK_XBUTTON2 + Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseLeftButton, VK_LBUTTON); + Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseMiddleButton, VK_MBUTTON); + Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseRightButton, VK_RBUTTON); + // NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are + // VK_XBUTTON1 and VK_XBUTTON2 } internal void Win32UpdateInputFrameMouseWheelDelta (input_frame* InputFrame, MSG Message) { - int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam); - InputFrame->MouseScroll = MouseWheel; + int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam); + InputFrame->MouseScroll = MouseWheel; } internal handle_window_event_result HandleWindowEventUnlessWouldUseDefault (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam) { - handle_window_event_result Result = {}; - Result.Handled = false; - - switch (Msg) + handle_window_event_result Result = {}; + Result.Handled = false; + + switch (Msg) + { + case WM_SIZE: { - case WM_SIZE: - { - - Result.Handled = true; - }break; - - case WM_CLOSE: - { - Result.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam); - Result.Handled = true; - }break; - - case WM_DESTROY: - { - GlobalWin32State.Running = false; - Result.Handled = true; - }break; - - case WM_PAINT: - { - PAINTSTRUCT PaintStruct; - HDC DeviceContext; - b32 PaintResult; - - DeviceContext = BeginPaint(WindowHandle, &PaintStruct); - PaintResult = EndPaint(WindowHandle, &PaintStruct); - Result.Handled = true; - }break; - } + + Result.Handled = true; + }break; - return Result; + case WM_CLOSE: + { + Result.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam); + Result.Handled = true; + }break; + + case WM_DESTROY: + { + GlobalWin32State.Running = false; + Result.Handled = true; + }break; + + case WM_PAINT: + { + PAINTSTRUCT PaintStruct; + HDC DeviceContext; + b32 PaintResult; + + DeviceContext = BeginPaint(WindowHandle, &PaintStruct); + PaintResult = EndPaint(WindowHandle, &PaintStruct); + Result.Handled = true; + }break; + } + + return Result; } LRESULT CALLBACK @@ -274,124 +269,124 @@ Win32HandleWindowsEvents ( LPARAM lParam ) { - handle_window_event_result EventResult = HandleWindowEventUnlessWouldUseDefault( - WindowHandle, - Msg, - wParam, - lParam); - - if (!EventResult.Handled) - { - EventResult.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam); - } - - return EventResult.Result; + handle_window_event_result EventResult = HandleWindowEventUnlessWouldUseDefault( + WindowHandle, + Msg, + wParam, + lParam); + + if (!EventResult.Handled) + { + EventResult.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam); + } + + return EventResult.Result; } static key_code Win32GetKeyCode (int Win32VirtualKey, bool NumpadValid, bool TranslateToChar) { - key_code Result = KeyCode_Invalid; + key_code Result = KeyCode_Invalid; + + if (Win32VirtualKey == VK_ESCAPE) { Result = KeyCode_Esc; } + + if (!TranslateToChar) + { + if (Win32VirtualKey == VK_SPACE) { Result = KeyCode_Space; } - if (Win32VirtualKey == VK_ESCAPE) { Result = KeyCode_Esc; } + } + + if (Win32VirtualKey == VK_CAPITAL) { Result = KeyCode_CapsLock; } + else if (Win32VirtualKey == VK_TAB) { Result = KeyCode_Tab; } + else if (Win32VirtualKey == VK_LSHIFT) { Result = KeyCode_LeftShift; } + else if (Win32VirtualKey == VK_RSHIFT) { Result = KeyCode_RightShift; } + else if (Win32VirtualKey == VK_LCONTROL) { Result = KeyCode_LeftCtrl; } + else if (Win32VirtualKey == VK_RCONTROL) { Result = KeyCode_RightCtrl; } + + // TODO(Peter): support the function key? + //else if (Win32VirtualKey == VK_) { Result = KeyCode_Fn; } + + else if (Win32VirtualKey == VK_MENU) { Result = KeyCode_Alt; } + else if (Win32VirtualKey == VK_PRIOR) { Result = KeyCode_PageUp; } + else if (Win32VirtualKey == VK_NEXT) { Result = KeyCode_PageDown; } + else if (Win32VirtualKey == VK_BACK) { Result = KeyCode_Backspace; } + else if (Win32VirtualKey == VK_DELETE) { Result = KeyCode_Delete; } + else if (Win32VirtualKey == VK_RETURN) { Result = KeyCode_Enter; } + + else if (Win32VirtualKey == VK_F1) { Result = KeyCode_F1; } + else if (Win32VirtualKey == VK_F2) { Result = KeyCode_F2; } + else if (Win32VirtualKey == VK_F3) { Result = KeyCode_F3; } + else if (Win32VirtualKey == VK_F4) { Result = KeyCode_F4; } + else if (Win32VirtualKey == VK_F5) { Result = KeyCode_F5; } + else if (Win32VirtualKey == VK_F6) { Result = KeyCode_F6; } + else if (Win32VirtualKey == VK_F7) { Result = KeyCode_F7; } + else if (Win32VirtualKey == VK_F8) { Result = KeyCode_F8; } + else if (Win32VirtualKey == VK_F9) { Result = KeyCode_F9; } + else if (Win32VirtualKey == VK_F10) { Result = KeyCode_F10; } + else if (Win32VirtualKey == VK_F11) { Result = KeyCode_F11; } + else if (Win32VirtualKey == VK_F12) { Result = KeyCode_F12; } + + if (!TranslateToChar) + { + if (Win32VirtualKey == 0x30) { Result = KeyCode_0; } + else if (Win32VirtualKey == 0x31) { Result = KeyCode_1; } + else if (Win32VirtualKey == 0x32) { Result = KeyCode_2; } + else if (Win32VirtualKey == 0x33) { Result = KeyCode_3; } + else if (Win32VirtualKey == 0x34) { Result = KeyCode_4; } + else if (Win32VirtualKey == 0x35) { Result = KeyCode_5; } + else if (Win32VirtualKey == 0x36) { Result = KeyCode_6; } + else if (Win32VirtualKey == 0x37) { Result = KeyCode_7; } + else if (Win32VirtualKey == 0x38) { Result = KeyCode_8; } + else if (Win32VirtualKey == 0x39) { Result = KeyCode_9; } - if (!TranslateToChar) - { - if (Win32VirtualKey == VK_SPACE) { Result = KeyCode_Space; } - - } - - if (Win32VirtualKey == VK_CAPITAL) { Result = KeyCode_CapsLock; } - else if (Win32VirtualKey == VK_TAB) { Result = KeyCode_Tab; } - else if (Win32VirtualKey == VK_LSHIFT) { Result = KeyCode_LeftShift; } - else if (Win32VirtualKey == VK_RSHIFT) { Result = KeyCode_RightShift; } - else if (Win32VirtualKey == VK_LCONTROL) { Result = KeyCode_LeftCtrl; } - else if (Win32VirtualKey == VK_RCONTROL) { Result = KeyCode_RightCtrl; } - - // TODO(Peter): support the function key? - //else if (Win32VirtualKey == VK_) { Result = KeyCode_Fn; } - - else if (Win32VirtualKey == VK_MENU) { Result = KeyCode_Alt; } - else if (Win32VirtualKey == VK_PRIOR) { Result = KeyCode_PageUp; } - else if (Win32VirtualKey == VK_NEXT) { Result = KeyCode_PageDown; } - else if (Win32VirtualKey == VK_BACK) { Result = KeyCode_Backspace; } - else if (Win32VirtualKey == VK_DELETE) { Result = KeyCode_Delete; } - else if (Win32VirtualKey == VK_RETURN) { Result = KeyCode_Enter; } - - else if (Win32VirtualKey == VK_F1) { Result = KeyCode_F1; } - else if (Win32VirtualKey == VK_F2) { Result = KeyCode_F2; } - else if (Win32VirtualKey == VK_F3) { Result = KeyCode_F3; } - else if (Win32VirtualKey == VK_F4) { Result = KeyCode_F4; } - else if (Win32VirtualKey == VK_F5) { Result = KeyCode_F5; } - else if (Win32VirtualKey == VK_F6) { Result = KeyCode_F6; } - else if (Win32VirtualKey == VK_F7) { Result = KeyCode_F7; } - else if (Win32VirtualKey == VK_F8) { Result = KeyCode_F8; } - else if (Win32VirtualKey == VK_F9) { Result = KeyCode_F9; } - else if (Win32VirtualKey == VK_F10) { Result = KeyCode_F10; } - else if (Win32VirtualKey == VK_F11) { Result = KeyCode_F11; } - else if (Win32VirtualKey == VK_F12) { Result = KeyCode_F12; } - - if (!TranslateToChar) - { - if (Win32VirtualKey == 0x30) { Result = KeyCode_0; } - else if (Win32VirtualKey == 0x31) { Result = KeyCode_1; } - else if (Win32VirtualKey == 0x32) { Result = KeyCode_2; } - else if (Win32VirtualKey == 0x33) { Result = KeyCode_3; } - else if (Win32VirtualKey == 0x34) { Result = KeyCode_4; } - else if (Win32VirtualKey == 0x35) { Result = KeyCode_5; } - else if (Win32VirtualKey == 0x36) { Result = KeyCode_6; } - else if (Win32VirtualKey == 0x37) { Result = KeyCode_7; } - else if (Win32VirtualKey == 0x38) { Result = KeyCode_8; } - else if (Win32VirtualKey == 0x39) { Result = KeyCode_9; } - - else if (Win32VirtualKey == 0x41) { Result = KeyCode_A; } - else if (Win32VirtualKey == 0x42) { Result = KeyCode_B; } - else if (Win32VirtualKey == 0x43) { Result = KeyCode_C; } - else if (Win32VirtualKey == 0x44) { Result = KeyCode_D; } - else if (Win32VirtualKey == 0x45) { Result = KeyCode_E; } - else if (Win32VirtualKey == 0x46) { Result = KeyCode_F; } - else if (Win32VirtualKey == 0x47) { Result = KeyCode_G; } - else if (Win32VirtualKey == 0x48) { Result = KeyCode_H; } - else if (Win32VirtualKey == 0x49) { Result = KeyCode_I; } - else if (Win32VirtualKey == 0x4A) { Result = KeyCode_J; } - else if (Win32VirtualKey == 0x4B) { Result = KeyCode_K; } - else if (Win32VirtualKey == 0x4C) { Result = KeyCode_L; } - else if (Win32VirtualKey == 0x4D) { Result = KeyCode_M; } - else if (Win32VirtualKey == 0x4E) { Result = KeyCode_N; } - else if (Win32VirtualKey == 0x4F) { Result = KeyCode_O; } - else if (Win32VirtualKey == 0x50) { Result = KeyCode_P; } - else if (Win32VirtualKey == 0x51) { Result = KeyCode_Q; } - else if (Win32VirtualKey == 0x52) { Result = KeyCode_R; } - else if (Win32VirtualKey == 0x53) { Result = KeyCode_S; } - else if (Win32VirtualKey == 0x54) { Result = KeyCode_T; } - else if (Win32VirtualKey == 0x55) { Result = KeyCode_U; } - else if (Win32VirtualKey == 0x56) { Result = KeyCode_V; } - else if (Win32VirtualKey == 0x57) { Result = KeyCode_W; } - else if (Win32VirtualKey == 0x58) { Result = KeyCode_X; } - else if (Win32VirtualKey == 0x59) { Result = KeyCode_Y; } - else if (Win32VirtualKey == 0x5A) { Result = KeyCode_Z; } - } - - if (NumpadValid) - { - if (Win32VirtualKey == VK_NUMPAD0) { Result = KeyCode_Num0; } - else if (Win32VirtualKey == VK_NUMPAD1) { Result = KeyCode_Num1; } - else if (Win32VirtualKey == VK_NUMPAD2) { Result = KeyCode_Num2; } - else if (Win32VirtualKey == VK_NUMPAD3) { Result = KeyCode_Num3; } - else if (Win32VirtualKey == VK_NUMPAD4) { Result = KeyCode_Num4; } - else if (Win32VirtualKey == VK_NUMPAD5) { Result = KeyCode_Num5; } - else if (Win32VirtualKey == VK_NUMPAD6) { Result = KeyCode_Num6; } - else if (Win32VirtualKey == VK_NUMPAD7) { Result = KeyCode_Num7; } - else if (Win32VirtualKey == VK_NUMPAD8) { Result = KeyCode_Num8; } - else if (Win32VirtualKey == VK_NUMPAD9) { Result = KeyCode_Num9; } - } - - if (Win32VirtualKey == VK_UP) { Result = KeyCode_UpArrow; } - else if (Win32VirtualKey == VK_DOWN) { Result = KeyCode_DownArrow; } - else if (Win32VirtualKey == VK_LEFT) { Result = KeyCode_LeftArrow; } - else if (Win32VirtualKey == VK_RIGHT) { Result = KeyCode_RightArrow; } - - return Result; + else if (Win32VirtualKey == 0x41) { Result = KeyCode_A; } + else if (Win32VirtualKey == 0x42) { Result = KeyCode_B; } + else if (Win32VirtualKey == 0x43) { Result = KeyCode_C; } + else if (Win32VirtualKey == 0x44) { Result = KeyCode_D; } + else if (Win32VirtualKey == 0x45) { Result = KeyCode_E; } + else if (Win32VirtualKey == 0x46) { Result = KeyCode_F; } + else if (Win32VirtualKey == 0x47) { Result = KeyCode_G; } + else if (Win32VirtualKey == 0x48) { Result = KeyCode_H; } + else if (Win32VirtualKey == 0x49) { Result = KeyCode_I; } + else if (Win32VirtualKey == 0x4A) { Result = KeyCode_J; } + else if (Win32VirtualKey == 0x4B) { Result = KeyCode_K; } + else if (Win32VirtualKey == 0x4C) { Result = KeyCode_L; } + else if (Win32VirtualKey == 0x4D) { Result = KeyCode_M; } + else if (Win32VirtualKey == 0x4E) { Result = KeyCode_N; } + else if (Win32VirtualKey == 0x4F) { Result = KeyCode_O; } + else if (Win32VirtualKey == 0x50) { Result = KeyCode_P; } + else if (Win32VirtualKey == 0x51) { Result = KeyCode_Q; } + else if (Win32VirtualKey == 0x52) { Result = KeyCode_R; } + else if (Win32VirtualKey == 0x53) { Result = KeyCode_S; } + else if (Win32VirtualKey == 0x54) { Result = KeyCode_T; } + else if (Win32VirtualKey == 0x55) { Result = KeyCode_U; } + else if (Win32VirtualKey == 0x56) { Result = KeyCode_V; } + else if (Win32VirtualKey == 0x57) { Result = KeyCode_W; } + else if (Win32VirtualKey == 0x58) { Result = KeyCode_X; } + else if (Win32VirtualKey == 0x59) { Result = KeyCode_Y; } + else if (Win32VirtualKey == 0x5A) { Result = KeyCode_Z; } + } + + if (NumpadValid) + { + if (Win32VirtualKey == VK_NUMPAD0) { Result = KeyCode_Num0; } + else if (Win32VirtualKey == VK_NUMPAD1) { Result = KeyCode_Num1; } + else if (Win32VirtualKey == VK_NUMPAD2) { Result = KeyCode_Num2; } + else if (Win32VirtualKey == VK_NUMPAD3) { Result = KeyCode_Num3; } + else if (Win32VirtualKey == VK_NUMPAD4) { Result = KeyCode_Num4; } + else if (Win32VirtualKey == VK_NUMPAD5) { Result = KeyCode_Num5; } + else if (Win32VirtualKey == VK_NUMPAD6) { Result = KeyCode_Num6; } + else if (Win32VirtualKey == VK_NUMPAD7) { Result = KeyCode_Num7; } + else if (Win32VirtualKey == VK_NUMPAD8) { Result = KeyCode_Num8; } + else if (Win32VirtualKey == VK_NUMPAD9) { Result = KeyCode_Num9; } + } + + if (Win32VirtualKey == VK_UP) { Result = KeyCode_UpArrow; } + else if (Win32VirtualKey == VK_DOWN) { Result = KeyCode_DownArrow; } + else if (Win32VirtualKey == VK_LEFT) { Result = KeyCode_LeftArrow; } + else if (Win32VirtualKey == VK_RIGHT) { Result = KeyCode_RightArrow; } + + return Result; } internal handle_window_msg_result @@ -399,173 +394,173 @@ HandleWindowsMessage ( HWND WindowHandle, MSG Message) { - handle_window_msg_result Result = {}; - Result.NeedsUpdate = 0; - - switch (Message.message) + handle_window_msg_result Result = {}; + Result.NeedsUpdate = 0; + + switch (Message.message) + { + case WM_HOTKEY: { - case WM_HOTKEY: - { - }break; - - case WM_MOUSEWHEEL: - { - int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam); - /* - Input.New->MouseScroll = MouseWheel; - Result.NeedsUpdate = true; - */ - }break; - - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - { - /* - Input.New->KeyStates[KeyCode_MouseLeftButton] = (GetKeyState(VK_LBUTTON) & (1 << 15)) != 0; - Input.New->KeyStates[KeyCode_MouseMiddleButton] = (GetKeyState(VK_MBUTTON) & (1 << 15)) != 0; - Input.New->KeyStates[KeyCode_MouseRightButton] = (GetKeyState(VK_RBUTTON) & (1 << 15)) != 0; - // NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are - // VK_XBUTTON1 and VK_XBUTTON2 - - if (KeyTransitionedDown(KeyCode_MouseLeftButton, Input)) - { - Input.MouseDownX = Input.New->MouseX; - Input.MouseDownY = Input.New->MouseY; - } - Result.NeedsUpdate = true;*/ - }break; - - case WM_MOUSEMOVE: - { - POINT MousePos; - GetCursorPos(&MousePos); - ScreenToClient(WindowHandle, &MousePos); - - /* - Input.New->MouseX = MousePos.x; - Input.New->MouseY = App.WindowHeight - MousePos.y; - - Result.NeedsUpdate = true; - */ - }break; - - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - case WM_KEYDOWN: - case WM_KEYUP: - { - int VirtualKey = (int)Message.wParam; - bool KeyDown = (Message.lParam & (1 << 31)) == 0; - int KeyIndex = Win32GetKeyCode(VirtualKey, true, true); - /* - if (KeyIndex >= 0) - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent "); - Input.New->KeyStates[KeyIndex] = KeyDown; - Result.NeedsUpdate = true; - } - else - { - if (Input.TranslateInputToCharValues && KeyDown) - { - // NOTE(Peter): Took this out b/c we're translating the WM_CHAR messages - // in the message pump, and if we do it here as well, character producing - // key messages get put on the message queue twice - TranslateMessage(&Message); - DispatchMessage(&Message); - } - else - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent "); - // NOTE(Peter): This is so that when you lift up a key that was generating a WM_CHAR, - // the app still has a chance to respond to it. - Result.NeedsUpdate = true; - } - } - */ - }break; - - case WM_CHAR: - { - /* - char TranslatedChar = (char)Message.wParam; - int KeyIndex = GetKeyIndexFromChar(TranslatedChar); - - if (KeyIndex >= 0) - { - // NOTE(Peter): Always setting this to true becuase windows is stupid and doesn't - // pass the press/release bit through correctly. So now the KEYDOWN/KEYUP Messages above - // only translate the message to a WM_CHAR message if its a key down. Since we clear all - // keystates to false at the beginning of an input frame, this will make transitions - // get registered correctly. - Input.New->KeyStates[KeyIndex] = true; - Result.NeedsUpdate = true; - } - else - { - printf("Translated Char Not Recognized: %c\n", TranslatedChar); - } - */ - }break; - - default: - { - TranslateMessage(&Message); - DispatchMessage(&Message); - }break; - } + }break; - return Result; + case WM_MOUSEWHEEL: + { + int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam); + /* + Input.New->MouseScroll = MouseWheel; + Result.NeedsUpdate = true; + */ + }break; + + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + { + /* + Input.New->KeyStates[KeyCode_MouseLeftButton] = (GetKeyState(VK_LBUTTON) & (1 << 15)) != 0; + Input.New->KeyStates[KeyCode_MouseMiddleButton] = (GetKeyState(VK_MBUTTON) & (1 << 15)) != 0; + Input.New->KeyStates[KeyCode_MouseRightButton] = (GetKeyState(VK_RBUTTON) & (1 << 15)) != 0; + // NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are + // VK_XBUTTON1 and VK_XBUTTON2 + + if (KeyTransitionedDown(KeyCode_MouseLeftButton, Input)) + { + Input.MouseDownX = Input.New->MouseX; + Input.MouseDownY = Input.New->MouseY; + } + Result.NeedsUpdate = true;*/ + }break; + + case WM_MOUSEMOVE: + { + POINT MousePos; + GetCursorPos(&MousePos); + ScreenToClient(WindowHandle, &MousePos); + + /* + Input.New->MouseX = MousePos.x; + Input.New->MouseY = App.WindowHeight - MousePos.y; + + Result.NeedsUpdate = true; + */ + }break; + + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_KEYDOWN: + case WM_KEYUP: + { + int VirtualKey = (int)Message.wParam; + bool KeyDown = (Message.lParam & (1 << 31)) == 0; + int KeyIndex = Win32GetKeyCode(VirtualKey, true, true); + /* + if (KeyIndex >= 0) + { + DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent "); + Input.New->KeyStates[KeyIndex] = KeyDown; + Result.NeedsUpdate = true; + } + else + { + if (Input.TranslateInputToCharValues && KeyDown) + { + // NOTE(Peter): Took this out b/c we're translating the WM_CHAR messages + // in the message pump, and if we do it here as well, character producing + // key messages get put on the message queue twice + TranslateMessage(&Message); + DispatchMessage(&Message); + } + else + { + DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent "); + // NOTE(Peter): This is so that when you lift up a key that was generating a WM_CHAR, + // the app still has a chance to respond to it. + Result.NeedsUpdate = true; + } + } + */ + }break; + + case WM_CHAR: + { + /* + char TranslatedChar = (char)Message.wParam; + int KeyIndex = GetKeyIndexFromChar(TranslatedChar); + + if (KeyIndex >= 0) + { + // NOTE(Peter): Always setting this to true becuase windows is stupid and doesn't + // pass the press/release bit through correctly. So now the KEYDOWN/KEYUP Messages above + // only translate the message to a WM_CHAR message if its a key down. Since we clear all + // keystates to false at the beginning of an input frame, this will make transitions + // get registered correctly. + Input.New->KeyStates[KeyIndex] = true; + Result.NeedsUpdate = true; + } + else + { + printf("Translated Char Not Recognized: %c\n", TranslatedChar); + } + */ + }break; + + default: + { + TranslateMessage(&Message); + DispatchMessage(&Message); + }break; + } + + return Result; } internal void Win32UpdateWindowDimension(window* Window) { - RECT ClientRect; - GetClientRect(Window->Handle, &ClientRect); - Window->Width = ClientRect.right - ClientRect.left; - Window->Height = ClientRect.bottom - ClientRect.top; + RECT ClientRect; + GetClientRect(Window->Handle, &ClientRect); + Window->Width = ClientRect.right - ClientRect.left; + Window->Height = ClientRect.bottom - ClientRect.top; } internal void Win32ResizeDIBSection(win32_offscreen_buffer *Win32Buffer, int Width, int Height) { - if(Win32Buffer->Buffer.Memory) - { - VirtualFree(Win32Buffer->Buffer.Memory, 0, MEM_RELEASE); - } - - Win32Buffer->Buffer.Width = Width; - Win32Buffer->Buffer.Height = Height; - - int BytesPerPixel = 4; - Win32Buffer->Buffer.BytesPerPixel = BytesPerPixel; - - Win32Buffer->Info.bmiHeader.biSize = sizeof(Win32Buffer->Info.bmiHeader); - Win32Buffer->Info.bmiHeader.biWidth = Win32Buffer->Buffer.Width; - Win32Buffer->Info.bmiHeader.biHeight = -Win32Buffer->Buffer.Height; // Top down, not bottom up - Win32Buffer->Info.bmiHeader.biPlanes = 1; - Win32Buffer->Info.bmiHeader.biBitCount = 32; - Win32Buffer->Info.bmiHeader.biCompression = BI_RGB; - - int BitmapMemorySize = (Win32Buffer->Buffer.Width * Win32Buffer->Buffer.Height)*BytesPerPixel; - Win32Buffer->Buffer.Memory = (u8*)VirtualAlloc(0, BitmapMemorySize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); - Win32Buffer->Buffer.Pitch = Width*BytesPerPixel; + if(Win32Buffer->Buffer.Memory) + { + VirtualFree(Win32Buffer->Buffer.Memory, 0, MEM_RELEASE); + } + + Win32Buffer->Buffer.Width = Width; + Win32Buffer->Buffer.Height = Height; + + int BytesPerPixel = 4; + Win32Buffer->Buffer.BytesPerPixel = BytesPerPixel; + + Win32Buffer->Info.bmiHeader.biSize = sizeof(Win32Buffer->Info.bmiHeader); + Win32Buffer->Info.bmiHeader.biWidth = Win32Buffer->Buffer.Width; + Win32Buffer->Info.bmiHeader.biHeight = -Win32Buffer->Buffer.Height; // Top down, not bottom up + Win32Buffer->Info.bmiHeader.biPlanes = 1; + Win32Buffer->Info.bmiHeader.biBitCount = 32; + Win32Buffer->Info.bmiHeader.biCompression = BI_RGB; + + int BitmapMemorySize = (Win32Buffer->Buffer.Width * Win32Buffer->Buffer.Height)*BytesPerPixel; + Win32Buffer->Buffer.Memory = (u8*)VirtualAlloc(0, BitmapMemorySize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + Win32Buffer->Buffer.Pitch = Width*BytesPerPixel; } internal void Win32DisplayBufferInWindow(win32_offscreen_buffer* Win32Buffer, window Window) { - StretchDIBits(Window.DeviceContext, - 0, 0, Win32Buffer->Buffer.Width, Win32Buffer->Buffer.Height, - 0, 0, Win32Buffer->Buffer.Width, Win32Buffer->Buffer.Height, - Win32Buffer->Buffer.Memory, - &Win32Buffer->Info, - DIB_RGB_COLORS, SRCCOPY); + StretchDIBits(Window.DeviceContext, + 0, 0, Win32Buffer->Buffer.Width, Win32Buffer->Buffer.Height, + 0, 0, Win32Buffer->Buffer.Width, Win32Buffer->Buffer.Height, + Win32Buffer->Buffer.Memory, + &Win32Buffer->Info, + DIB_RGB_COLORS, SRCCOPY); } ///////////////////////////////////////// @@ -581,20 +576,20 @@ OpenGLRenderTriBuffer (u8* Vertecies, s32 VertexElements, u8* Colors, s32 ColorsElements, s32 TriCount) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(VertexElements, GL_FLOAT, VertexElements * sizeof(r32), Vertecies); - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(UVElements, GL_FLOAT, UVElements * sizeof(r32), UVs); - - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(ColorsElements, GL_FLOAT, ColorsElements * sizeof(r32), Colors); - - glDrawArrays(GL_TRIANGLES, 0, TriCount); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(VertexElements, GL_FLOAT, VertexElements * sizeof(r32), Vertecies); + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(UVElements, GL_FLOAT, UVElements * sizeof(r32), UVs); + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(ColorsElements, GL_FLOAT, ColorsElements * sizeof(r32), Colors); + + glDrawArrays(GL_TRIANGLES, 0, TriCount); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); } internal void @@ -602,21 +597,21 @@ OpenGLDraw3DTri (v4 P0, v4 P1, v4 P2, v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { - glBegin(GL_TRIANGLES); - - glTexCoord2f(UV0.x, UV0.y); - glColor4f(C0.r, C0.g, C0.b, C0.a); - glVertex4f(P0.x, P0.y, P0.z, P0.w); - - glTexCoord2f(UV1.x, UV1.y); - glColor4f(C1.r, C1.g, C1.b, C1.a); - glVertex4f(P1.x, P1.y, P1.z, P1.w); - - glTexCoord2f(UV2.x, UV2.y); - glColor4f(C2.r, C2.g, C2.b, C2.a); - glVertex4f(P2.x, P2.y, P2.z, P2.w); - - glEnd(); + glBegin(GL_TRIANGLES); + + glTexCoord2f(UV0.x, UV0.y); + glColor4f(C0.r, C0.g, C0.b, C0.a); + glVertex4f(P0.x, P0.y, P0.z, P0.w); + + glTexCoord2f(UV1.x, UV1.y); + glColor4f(C1.r, C1.g, C1.b, C1.a); + glVertex4f(P1.x, P1.y, P1.z, P1.w); + + glTexCoord2f(UV2.x, UV2.y); + glColor4f(C2.r, C2.g, C2.b, C2.a); + glVertex4f(P2.x, P2.y, P2.z, P2.w); + + glEnd(); } internal void @@ -624,72 +619,72 @@ OpenGLDraw2DTri (v2 P0, v2 P1, v2 P2, v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { - glBegin(GL_TRIANGLES); - - glTexCoord2f(UV0.x, UV0.y); - glColor4f(C0.r, C0.g, C0.b, C0.a); - glVertex2f(P0.x, P0.y); - - glTexCoord2f(UV1.x, UV1.y); - glColor4f(C1.r, C1.g, C1.b, C1.a); - glVertex2f(P1.x, P1.y); - - glTexCoord2f(UV2.x, UV2.y); - glColor4f(C2.r, C2.g, C2.b, C2.a); - glVertex2f(P2.x, P2.y); - - glEnd(); + glBegin(GL_TRIANGLES); + + glTexCoord2f(UV0.x, UV0.y); + glColor4f(C0.r, C0.g, C0.b, C0.a); + glVertex2f(P0.x, P0.y); + + glTexCoord2f(UV1.x, UV1.y); + glColor4f(C1.r, C1.g, C1.b, C1.a); + glVertex2f(P1.x, P1.y); + + glTexCoord2f(UV2.x, UV2.y); + glColor4f(C2.r, C2.g, C2.b, C2.a); + glVertex2f(P2.x, P2.y); + + glEnd(); } internal void LoadModelView (r32 Matrix[16]) { - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(Matrix); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(Matrix); } internal void LoadProjection (r32 Matrix[16]) { - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(Matrix); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(Matrix); } internal void ClearRenderBuffer () { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } s32 NextTextureHandle = 1; internal s32 SubmitTexture (u8* Memory, s32 Width, s32 Height) { - s32 TextureHandle = NextTextureHandle++; - glBindTexture(GL_TEXTURE_2D, TextureHandle); - glTexImage2D(GL_TEXTURE_2D, - 0, // mip map level - GL_RGBA8, - Width, - Height, - 0, // border - GL_RGBA, - GL_UNSIGNED_BYTE, - Memory); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - return TextureHandle; + s32 TextureHandle = NextTextureHandle++; + glBindTexture(GL_TEXTURE_2D, TextureHandle); + glTexImage2D(GL_TEXTURE_2D, + 0, // mip map level + GL_RGBA8, + Width, + Height, + 0, // border + GL_RGBA, + GL_UNSIGNED_BYTE, + Memory); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + return TextureHandle; } internal void BindTexture (s32 TextureHandle) { - glBindTexture(GL_TEXTURE_2D, TextureHandle); + glBindTexture(GL_TEXTURE_2D, TextureHandle); } #define GS_WIN32_CPP diff --git a/src/sculpture_gen/gen_blumen_lumen.cpp b/src/sculpture_gen/gen_blumen_lumen.cpp index d7f4cb6..12b09d3 100644 --- a/src/sculpture_gen/gen_blumen_lumen.cpp +++ b/src/sculpture_gen/gen_blumen_lumen.cpp @@ -22,141 +22,141 @@ global log_buffer* GlobalLogBuffer; typedef struct { - v3 CenterStart; - v3 CenterEnd; - r32 Radius; - u32 SegmentsCount; - u32 SubsegmentsCount; - u32 SubsegmentLeds; - - // Only one of these two values is needed. - // If ChannelsArray != 0, then it will be used, and assumed to - // have SegmentsCount values - // Otherwise, each segment will increment from ChannelStart - u32 ChannelStart; - u32* ChannelsArray; - - char* ComPort; - char* SectionTagValue; - char* FlowerTagValue; + v3 CenterStart; + v3 CenterEnd; + r32 Radius; + u32 SegmentsCount; + u32 SubsegmentsCount; + u32 SubsegmentLeds; + + // Only one of these two values is needed. + // If ChannelsArray != 0, then it will be used, and assumed to + // have SegmentsCount values + // Otherwise, each segment will increment from ChannelStart + u32 ChannelStart; + u32* ChannelsArray; + + char* ComPort; + char* SectionTagValue; + char* FlowerTagValue; } loop_desc; internal void BuildLoop(gs_string* OutputBuffer, loop_desc Desc) { - r32 SegmentsArc = TauR32 / Desc.SegmentsCount; - r32 SubsegmentsArc = SegmentsArc / Desc.SubsegmentsCount; + r32 SegmentsArc = TauR32 / Desc.SegmentsCount; + r32 SubsegmentsArc = SegmentsArc / Desc.SubsegmentsCount; + + for (u32 i = 0; i < Desc.SegmentsCount; i++) + { + r32 ArcBase = SegmentsArc * i; - for (u32 i = 0; i < Desc.SegmentsCount; i++) + u32 Channel = 0; + if (Desc.ChannelsArray != 0) { - r32 ArcBase = SegmentsArc * i; - - u32 Channel = 0; - if (Desc.ChannelsArray != 0) - { - Channel = Desc.ChannelsArray[i]; - } - else - { - Channel = Desc.ChannelStart + i; - } - - WriteLedStripOpen(OutputBuffer, Channel, Desc.ComPort); - WriteSegmentSequenceOpen(OutputBuffer, Desc.SubsegmentsCount); - - for (u32 j = 0; j < Desc.SubsegmentsCount; j++) - { - r32 Arc = ArcBase + (SubsegmentsArc * j); - v3 Offset = v3{ SinR32(Arc), 0, CosR32(Arc) } * Desc.Radius; - v3 P0 = Desc.CenterStart + Offset; - v3 P1 = Desc.CenterEnd + Offset; - - // Swap directions on the middle strip - if (j%2 != 0) - { - v3 Temp = P0; - P0 = P1; - P1 = Temp; - } - - WriteSegmentSequenceSegment(OutputBuffer, P0, P1, Desc.SubsegmentLeds); - } - - WriteSegmentSequenceClose(OutputBuffer); - WriteSegmentTagsOpen(OutputBuffer, 2); - WriteSegmentTag(OutputBuffer, "section", Desc.SectionTagValue); - WriteSegmentTag(OutputBuffer, "flower", Desc.FlowerTagValue); - WriteSegmentTagsClose(OutputBuffer); - WriteLedStripClose(OutputBuffer); + Channel = Desc.ChannelsArray[i]; + } + else + { + Channel = Desc.ChannelStart + i; } + WriteLedStripOpen(OutputBuffer, Channel, Desc.ComPort); + WriteSegmentSequenceOpen(OutputBuffer, Desc.SubsegmentsCount); + + for (u32 j = 0; j < Desc.SubsegmentsCount; j++) + { + r32 Arc = ArcBase + (SubsegmentsArc * j); + v3 Offset = v3{ SinR32(Arc), 0, CosR32(Arc) } * Desc.Radius; + v3 P0 = Desc.CenterStart + Offset; + v3 P1 = Desc.CenterEnd + Offset; + + // Swap directions on the middle strip + if (j%2 != 0) + { + v3 Temp = P0; + P0 = P1; + P1 = Temp; + } + + WriteSegmentSequenceSegment(OutputBuffer, P0, P1, Desc.SubsegmentLeds); + } + + WriteSegmentSequenceClose(OutputBuffer); + WriteSegmentTagsOpen(OutputBuffer, 2); + WriteSegmentTag(OutputBuffer, "section", Desc.SectionTagValue); + WriteSegmentTag(OutputBuffer, "flower", Desc.FlowerTagValue); + WriteSegmentTagsClose(OutputBuffer); + WriteLedStripClose(OutputBuffer); + } + } typedef struct { - v3 Pos; - char* ComPort; - char* FlowerTagValue; - u32* StemChannels; - u32* BloomOuterChannels; - u32* BloomInnerChannels; + v3 Pos; + char* ComPort; + char* FlowerTagValue; + u32* StemChannels; + u32* BloomOuterChannels; + u32* BloomInnerChannels; } flower_desc; internal u32 BuildFlower(gs_string* OutputBuffer, flower_desc Desc) { - + #if 1 - // the bloom stem inner - loop_desc BloomStemInner = {}; - BloomStemInner.CenterStart = v3{0, 1.4f, 0}; - BloomStemInner.CenterEnd = v3{0, .9f, 0}; - BloomStemInner.Radius = .05f; - BloomStemInner.SegmentsCount = 6; - BloomStemInner.SubsegmentsCount = 3; - BloomStemInner.SubsegmentLeds = 35; - BloomStemInner.ChannelsArray = Desc.BloomInnerChannels; - BloomStemInner.ComPort = Desc.ComPort; - BloomStemInner.SectionTagValue = "inner_bloom"; - BloomStemInner.FlowerTagValue = Desc.FlowerTagValue; - BuildLoop(OutputBuffer, BloomStemInner); - - // the bloom stem outer - loop_desc BloomStemOuter = {}; - BloomStemOuter.CenterStart = v3{0, .5f, 0}; - BloomStemOuter.CenterEnd = v3{0, .9f, 0}; - BloomStemOuter.Radius = .07f; - BloomStemOuter.SegmentsCount = 9; - BloomStemOuter.SubsegmentsCount = 3; - BloomStemOuter.SubsegmentLeds = 41; - BloomStemOuter.ChannelsArray = Desc.BloomOuterChannels; - BloomStemOuter.ComPort = Desc.ComPort; - BloomStemOuter.SectionTagValue = "outer_bloom"; - BloomStemOuter.FlowerTagValue = Desc.FlowerTagValue; - BuildLoop(OutputBuffer, BloomStemOuter); + // the bloom stem inner + loop_desc BloomStemInner = {}; + BloomStemInner.CenterStart = v3{0, 1.4f, 0}; + BloomStemInner.CenterEnd = v3{0, .9f, 0}; + BloomStemInner.Radius = .05f; + BloomStemInner.SegmentsCount = 6; + BloomStemInner.SubsegmentsCount = 3; + BloomStemInner.SubsegmentLeds = 35; + BloomStemInner.ChannelsArray = Desc.BloomInnerChannels; + BloomStemInner.ComPort = Desc.ComPort; + BloomStemInner.SectionTagValue = "inner_bloom"; + BloomStemInner.FlowerTagValue = Desc.FlowerTagValue; + BuildLoop(OutputBuffer, BloomStemInner); + + // the bloom stem outer + loop_desc BloomStemOuter = {}; + BloomStemOuter.CenterStart = v3{0, .5f, 0}; + BloomStemOuter.CenterEnd = v3{0, .9f, 0}; + BloomStemOuter.Radius = .07f; + BloomStemOuter.SegmentsCount = 9; + BloomStemOuter.SubsegmentsCount = 3; + BloomStemOuter.SubsegmentLeds = 41; + BloomStemOuter.ChannelsArray = Desc.BloomOuterChannels; + BloomStemOuter.ComPort = Desc.ComPort; + BloomStemOuter.SectionTagValue = "outer_bloom"; + BloomStemOuter.FlowerTagValue = Desc.FlowerTagValue; + BuildLoop(OutputBuffer, BloomStemOuter); #endif - + #if 1 - // the flower stem - loop_desc FlowerStem = {}; - FlowerStem.CenterStart = v3{0, -1.5f, 0}; - FlowerStem.CenterEnd = v3{0, .5f, 0}; - FlowerStem.Radius = .05f; - FlowerStem.SegmentsCount = 6; - FlowerStem.SubsegmentsCount = 1; - FlowerStem.SubsegmentLeds = 300; - FlowerStem.ChannelsArray = Desc.StemChannels; - FlowerStem.ComPort = Desc.ComPort; - FlowerStem.SectionTagValue = "stem"; - FlowerStem.FlowerTagValue = Desc.FlowerTagValue; - BuildLoop(OutputBuffer, FlowerStem); + // the flower stem + loop_desc FlowerStem = {}; + FlowerStem.CenterStart = v3{0, -1.5f, 0}; + FlowerStem.CenterEnd = v3{0, .5f, 0}; + FlowerStem.Radius = .05f; + FlowerStem.SegmentsCount = 6; + FlowerStem.SubsegmentsCount = 1; + FlowerStem.SubsegmentLeds = 300; + FlowerStem.ChannelsArray = Desc.StemChannels; + FlowerStem.ComPort = Desc.ComPort; + FlowerStem.SectionTagValue = "stem"; + FlowerStem.FlowerTagValue = Desc.FlowerTagValue; + BuildLoop(OutputBuffer, FlowerStem); #endif - - u32 StripsCount = BloomStemInner.SegmentsCount; - StripsCount += BloomStemOuter.SegmentsCount; - StripsCount += FlowerStem.SegmentsCount; - - return StripsCount; + + u32 StripsCount = BloomStemInner.SegmentsCount; + StripsCount += BloomStemOuter.SegmentsCount; + StripsCount += FlowerStem.SegmentsCount; + + return StripsCount; } // Just for brevity, no real function provided @@ -164,88 +164,88 @@ BuildFlower(gs_string* OutputBuffer, flower_desc Desc) internal u8 FlowerStripToChannel(u8 Flower, u8 Channel) { - Assert(Flower < 3); - Assert(Channel < 8); - - u8 Result = 0; - Result |= (Flower & 0x03) << 3; - Result |= (Channel & 0x07); - - return Result; + Assert(Flower < 3); + Assert(Channel < 8); + + u8 Result = 0; + Result |= (Flower & 0x03) << 3; + Result |= (Channel & 0x07); + + return Result; } int main(int ArgCount, char** Args) { - gs_thread_context Ctx = Win32CreateThreadContext(); - GlobalLogBuffer = AllocatorAllocStruct(Ctx.Allocator, log_buffer); - *GlobalLogBuffer = Log_Init(Ctx.Allocator, 32); - - gs_string OutputBuffer0 = PushString(Ctx.Transient, MB(4)); - gs_string OutputBuffer1 = PushString(Ctx.Transient, MB(4)); - gs_string OutputBuffer2 = PushString(Ctx.Transient, MB(4)); - - WriteAssemblyUARTOpen(&OutputBuffer0, - "Blumen Lumen - Silver Spring - 00", - 100, - v3{-1, 0, 0}, - 21, - ""); - WriteAssemblyUARTOpen(&OutputBuffer1, - "Blumen Lumen - Silver Spring - 01", - 100, - v3{0, 0, 0}, - 21, - ""); - WriteAssemblyUARTOpen(&OutputBuffer2, - "Blumen Lumen - Silver Spring - 02", - 100, - v3{1, 0, 0}, - 21, - ""); - - u32 StripCount = 0; - - u32 StemChannels[] = { FSC(2, 1), FSC(2, 2), FSC(2, 3), FSC(2, 4), FSC(2, 5), FSC(2, 6) }; - u32 BloomOuterChannels[] = { FSC(1, 0), FSC(1, 1), FSC(1, 2), FSC(1, 3), FSC(1, 4), FSC(1, 5), FSC(1, 6), FSC(1, 7), FSC(2, 0) }; - u32 BloomInnerChannels[] = { FSC(0, 0), FSC(0, 1), FSC(0, 2), FSC(0, 3), FSC(0, 4), FSC(0, 5) }; - flower_desc F0 = {}; - F0.Pos = v3{0, 0, 0}; - F0.ComPort = "\\\\.\\COM11"; - F0.FlowerTagValue = "left"; - F0.StemChannels = StemChannels; - F0.BloomOuterChannels = BloomOuterChannels; - F0.BloomInnerChannels = BloomInnerChannels; - StripCount += BuildFlower(&OutputBuffer0, F0); - - flower_desc F1 = {}; - F1.Pos = v3{0, 0, 0}; - F1.ComPort = "\\\\.\\COM12"; - F1.FlowerTagValue = "center"; - F1.StemChannels = StemChannels; - F1.BloomInnerChannels = BloomInnerChannels; - F1.BloomOuterChannels = BloomOuterChannels; - StripCount += BuildFlower(&OutputBuffer1, F1); - - flower_desc F2 = {}; - F2.Pos = v3{0, 0, 0}; - F2.ComPort = "\\\\.\\COM6"; - F2.FlowerTagValue = "right"; - F2.StemChannels = StemChannels; - F2.BloomInnerChannels = BloomInnerChannels; - F2.BloomOuterChannels = BloomOuterChannels; - StripCount += BuildFlower(&OutputBuffer2, F2); - - WriteEntireFile(Ctx.FileHandler, ConstString("data/ss_blumen_one.fold"), StringToData(OutputBuffer0)); - WriteEntireFile(Ctx.FileHandler, ConstString("data/ss_blumen_two.fold"), StringToData(OutputBuffer1)); - WriteEntireFile(Ctx.FileHandler, ConstString("data/ss_blumen_three.fold"), StringToData(OutputBuffer2)); - - //printf("%.*s\n", (u32)OutputBuffer.Length, OutputBuffer.Str); - //printf("%d\n", StripCount); - - - - - return 0; + gs_thread_context Ctx = Win32CreateThreadContext(); + GlobalLogBuffer = PushStruct(Ctx.Transient, log_buffer); + *GlobalLogBuffer = Log_Init(Ctx.Transient, 32); + + gs_string OutputBuffer0 = PushString(Ctx.Transient, MB(4)); + gs_string OutputBuffer1 = PushString(Ctx.Transient, MB(4)); + gs_string OutputBuffer2 = PushString(Ctx.Transient, MB(4)); + + WriteAssemblyUARTOpen(&OutputBuffer0, + "Blumen Lumen - Silver Spring - 00", + 100, + v3{-1, 0, 0}, + 21, + ""); + WriteAssemblyUARTOpen(&OutputBuffer1, + "Blumen Lumen - Silver Spring - 01", + 100, + v3{0, 0, 0}, + 21, + ""); + WriteAssemblyUARTOpen(&OutputBuffer2, + "Blumen Lumen - Silver Spring - 02", + 100, + v3{1, 0, 0}, + 21, + ""); + + u32 StripCount = 0; + + u32 StemChannels[] = { FSC(2, 1), FSC(2, 2), FSC(2, 3), FSC(2, 4), FSC(2, 5), FSC(2, 6) }; + u32 BloomOuterChannels[] = { FSC(1, 0), FSC(1, 1), FSC(1, 2), FSC(1, 3), FSC(1, 4), FSC(1, 5), FSC(1, 6), FSC(1, 7), FSC(2, 0) }; + u32 BloomInnerChannels[] = { FSC(0, 0), FSC(0, 1), FSC(0, 2), FSC(0, 3), FSC(0, 4), FSC(0, 5) }; + flower_desc F0 = {}; + F0.Pos = v3{0, 0, 0}; + F0.ComPort = "\\\\.\\COM11"; + F0.FlowerTagValue = "left"; + F0.StemChannels = StemChannels; + F0.BloomOuterChannels = BloomOuterChannels; + F0.BloomInnerChannels = BloomInnerChannels; + StripCount += BuildFlower(&OutputBuffer0, F0); + + flower_desc F1 = {}; + F1.Pos = v3{0, 0, 0}; + F1.ComPort = "\\\\.\\COM12"; + F1.FlowerTagValue = "center"; + F1.StemChannels = StemChannels; + F1.BloomInnerChannels = BloomInnerChannels; + F1.BloomOuterChannels = BloomOuterChannels; + StripCount += BuildFlower(&OutputBuffer1, F1); + + flower_desc F2 = {}; + F2.Pos = v3{0, 0, 0}; + F2.ComPort = "\\\\.\\COM6"; + F2.FlowerTagValue = "right"; + F2.StemChannels = StemChannels; + F2.BloomInnerChannels = BloomInnerChannels; + F2.BloomOuterChannels = BloomOuterChannels; + StripCount += BuildFlower(&OutputBuffer2, F2); + + WriteEntireFile(Ctx.FileHandler, ConstString("data/ss_blumen_one.fold"), StringToData(OutputBuffer0)); + WriteEntireFile(Ctx.FileHandler, ConstString("data/ss_blumen_two.fold"), StringToData(OutputBuffer1)); + WriteEntireFile(Ctx.FileHandler, ConstString("data/ss_blumen_three.fold"), StringToData(OutputBuffer2)); + + //printf("%.*s\n", (u32)OutputBuffer.Length, OutputBuffer.Str); + //printf("%d\n", StripCount); + + + + + return 0; } diff --git a/src/serial_monitor/first.cpp b/src/serial_monitor/first.cpp index d2e47b0..a87e7c7 100644 --- a/src/serial_monitor/first.cpp +++ b/src/serial_monitor/first.cpp @@ -30,195 +30,195 @@ global log_buffer* GlobalLogBuffer; u8* FindNextHeader(gs_data Data, u8* StartAt) { - u8* At = StartAt; - while (!(At[0] == 'U' && - At[1] == 'P' && - At[2] == 'X' && - At[3] == 'L') && - (u32)(At - Data.Memory) < Data.Size) - { - At++; - } - return At; + u8* At = StartAt; + while (!(At[0] == 'U' && + At[1] == 'P' && + At[2] == 'X' && + At[3] == 'L') && + (u32)(At - Data.Memory) < Data.Size) + { + At++; + } + return At; } void CreateMessage(gs_data* Data, u8 Count) { - gs_memory_cursor WriteCursor = CreateMemoryCursor(*Data); + gs_memory_cursor WriteCursor = MemoryCursorCreateFromData(*Data); + + u32 Channels[] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 16, 17, 18, 19, 20, 21, 22, 23, + //40, 41, 42, 43, 44, 45, 46, 47, + }; + + u8* FirstHeaderAddr = 0; + + for (u32 j = 0; j < sizeof(Channels) / sizeof(u32); j++) + { + u32 ChannelIndex = Channels[j]; + uart_header* Header = MemoryCursorPushStruct(&WriteCursor, uart_header); + UART_FillHeader(Header, ChannelIndex, UART_SET_CHANNEL_WS2812); - u32 Channels[] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 16, 17, 18, 19, 20, 21, 22, 23, - //40, 41, 42, 43, 44, 45, 46, 47, - }; - - u8* FirstHeaderAddr = 0; - - for (u32 j = 0; j < sizeof(Channels) / sizeof(u32); j++) + if (FirstHeaderAddr == 0) { - u32 ChannelIndex = Channels[j]; - uart_header* Header = PushStructOnCursor(&WriteCursor, uart_header); - UART_FillHeader(Header, ChannelIndex, UART_SET_CHANNEL_WS2812); - - if (FirstHeaderAddr == 0) - { - FirstHeaderAddr = (u8*)Header; - } - - uart_channel* Channel = PushStructOnCursor(&WriteCursor, uart_channel); - Channel->ElementsCount = 3; - Channel->ColorPackingOrder = 36; // 10010000 - Channel->PixelsCount = 300; - - for (u32 i = 0; i < Channel->PixelsCount; i++) - { - u8* Pixel = PushArrayOnCursor(&WriteCursor, u8, 3); - Pixel[0] = Count; - Pixel[1] = 0; - Pixel[2] = 255 - Count; - } - - uart_footer* Footer = PushStructOnCursor(&WriteCursor, uart_footer); - Footer->CRC = UART_CalculateCRC((u8*)Header, (u8*)(Footer)); + FirstHeaderAddr = (u8*)Header; } - uart_header* DrawAllHeader = PushStructOnCursor(&WriteCursor, uart_header); - UART_FillHeader(DrawAllHeader, 255, UART_DRAW_ALL); - uart_footer* DrawAllFooter = - PushStructOnCursor(&WriteCursor, uart_footer); - DrawAllFooter->CRC = UART_CalculateCRC((u8*)DrawAllHeader, (u8*)(DrawAllFooter)); + uart_channel* Channel = MemoryCursorPushStruct(&WriteCursor, uart_channel); + Channel->ElementsCount = 3; + Channel->ColorPackingOrder = 36; // 10010000 + Channel->PixelsCount = 300; - Data->Size = ((u8*)DrawAllFooter - (u8*)FirstHeaderAddr) + sizeof(uart_footer); + for (u32 i = 0; i < Channel->PixelsCount; i++) + { + u8* Pixel = MemoryCursorPushArray(&WriteCursor, u8, 3); + Pixel[0] = Count; + Pixel[1] = 0; + Pixel[2] = 255 - Count; + } + + uart_footer* Footer = MemoryCursorPushStruct(&WriteCursor, uart_footer); + Footer->CRC = UART_CalculateCRC((u8*)Header, (u8*)(Footer)); + } + + uart_header* DrawAllHeader = MemoryCursorPushStruct(&WriteCursor, uart_header); + UART_FillHeader(DrawAllHeader, 255, UART_DRAW_ALL); + uart_footer* DrawAllFooter = + MemoryCursorPushStruct(&WriteCursor, uart_footer); + DrawAllFooter->CRC = UART_CalculateCRC((u8*)DrawAllHeader, (u8*)(DrawAllFooter)); + + Data->Size = ((u8*)DrawAllFooter - (u8*)FirstHeaderAddr) + sizeof(uart_footer); } int main(int ArgCount, char** Args) { - gs_thread_context Ctx = Win32CreateThreadContext(); - GlobalLogBuffer = AllocatorAllocStruct(Ctx.Allocator, log_buffer); - *GlobalLogBuffer = Log_Init(Ctx.Allocator, 32); + gs_thread_context Ctx = Win32CreateThreadContext(); + GlobalLogBuffer = PushStruct(Ctx.Transient, log_buffer); + *GlobalLogBuffer = Log_Init(Ctx.Transient, 32); + + HANDLE SerialHandle = Win32SerialPort_Open("\\\\.\\COM9", Ctx.Transient); + Win32SerialPort_SetState(SerialHandle, 2000000, 8, 0, 1); + + gs_const_string OutFileName = ConstString("./serial_dump.data"); + + + if (false) + { + Win32SerialPort_SetRead(SerialHandle); - HANDLE SerialHandle = Win32SerialPort_Open("\\\\.\\COM9", Ctx.Transient); - Win32SerialPort_SetState(SerialHandle, 2000000, 8, 0, 1); + gs_data Data = PushSize(Ctx.Transient, KB(32)); - gs_const_string OutFileName = ConstString("./serial_dump.data"); + Win32SerialPort_SetRead(SerialHandle); + u32 ReadSize = Win32SerialPort_ReadMessageWhenReady(SerialHandle, Data); - - if (false) + u8* SetChannelHeaderAddr = 0; + uart_header* SetChannelHeader = 0; + uart_header* DrawAllHeader = 0; + u8* ScanAt = Data.Memory; + do { - Win32SerialPort_SetRead(SerialHandle); - - gs_data Data = PushSizeToData(Ctx.Transient, KB(32)); - - Win32SerialPort_SetRead(SerialHandle); - u32 ReadSize = Win32SerialPort_ReadMessageWhenReady(SerialHandle, Data); - - u8* SetChannelHeaderAddr = 0; - uart_header* SetChannelHeader = 0; - uart_header* DrawAllHeader = 0; - u8* ScanAt = Data.Memory; - do + ScanAt = FindNextHeader(Data, ScanAt); + uart_header* Header = (uart_header*)ScanAt; + + if (Header->RecordType == UART_SET_CHANNEL_WS2812) + { + printf("Set Channel:\n"); + printf(" Channel: %d\n", Header->Channel); + printf(" Pixels: %d\n", ((uart_channel*)(Header + 1))->PixelsCount); + if (!SetChannelHeader) { - ScanAt = FindNextHeader(Data, ScanAt); - uart_header* Header = (uart_header*)ScanAt; - - if (Header->RecordType == UART_SET_CHANNEL_WS2812) - { - printf("Set Channel:\n"); - printf(" Channel: %d\n", Header->Channel); - printf(" Pixels: %d\n", ((uart_channel*)(Header + 1))->PixelsCount); - if (!SetChannelHeader) - { - SetChannelHeaderAddr = (u8*)Header; - SetChannelHeader = Header; - } - } - - if (Header->RecordType == UART_DRAW_ALL) - { - printf("Draw All:\n"); - printf(" Channel: %d\n", Header->Channel); - if (!DrawAllHeader) - { - DrawAllHeader= Header; - } - } - - ScanAt += sizeof(uart_header); - }while(((u32)(ScanAt - Data.Memory + sizeof(uart_header)) < Data.Size)); - - uart_channel* Channel = (uart_channel*)(SetChannelHeader + 1); - - u8* DataStart = (u8*)(Channel + 1); - - uart_footer* Footer = (uart_footer*)(DataStart + (Channel->ElementsCount * Channel->PixelsCount)); - - u32 TestCRC = UART_CalculateCRC((u8*)SetChannelHeader, (u8*)(Footer)); - - uart_footer* DrawAllFooter = (uart_footer*)(DrawAllHeader + 1); - u32 DrawwAllCRC = UART_CalculateCRC((u8*)DrawAllHeader, (u8*)(DrawAllFooter)); - - HANDLE FileHandle = CreateFileA(OutFileName.Str, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (FileHandle != INVALID_HANDLE_VALUE) - { - DWORD BytesWritten = 0; - if (!WriteFile(FileHandle, Data.Memory, Data.Size, &BytesWritten, NULL)) - { - InvalidCodePath; - } + SetChannelHeaderAddr = (u8*)Header; + SetChannelHeader = Header; } - CloseHandle(FileHandle); - Win32SerialPort_Close(SerialHandle); - - } - else if (true) - { - gs_data Data = PushSizeToData(Ctx.Transient, KB(32)); - - u8 Count = 0; - while(true) + } + + if (Header->RecordType == UART_DRAW_ALL) + { + printf("Draw All:\n"); + printf(" Channel: %d\n", Header->Channel); + if (!DrawAllHeader) { - CreateMessage(&Data, ++Count); - Win32SerialPort_Write(SerialHandle, Data); - Sleep(100); + DrawAllHeader= Header; } - } - else if (false) - { - gs_data Data = PushSizeToData(Ctx.Transient, KB(32)); - gs_file File = Win32ReadEntireFile(Ctx.FileHandler, OutFileName, Data); - - gs_data Messages = {0}; - u8* ScanAt = Data.Memory; - ScanAt = FindNextHeader(Data, ScanAt); - uart_header* FirstHeader = (uart_header*)ScanAt; - ScanAt += sizeof(uart_header); - - uart_header* LastHeader = 0; - do - { - ScanAt = FindNextHeader(Data, ScanAt); - uart_header* Header = (uart_header*)ScanAt; - if (Header->RecordType == UART_DRAW_ALL) - { - LastHeader = Header; - } - ScanAt += sizeof(uart_header); - }while((u32)(ScanAt - Data.Memory) < Data.Size); - - u8* OnePastLastByte = ((u8*)(LastHeader + 1)) + sizeof(uart_footer); - - Messages.Memory = (u8*)FirstHeader; - Messages.Size = OnePastLastByte - Messages.Memory; - - while (true) - { - Win32SerialPort_Write(SerialHandle, Messages); - Sleep(100); - } - } + } + + ScanAt += sizeof(uart_header); + }while(((u32)(ScanAt - Data.Memory + sizeof(uart_header)) < Data.Size)); - return 0; + uart_channel* Channel = (uart_channel*)(SetChannelHeader + 1); + + u8* DataStart = (u8*)(Channel + 1); + + uart_footer* Footer = (uart_footer*)(DataStart + (Channel->ElementsCount * Channel->PixelsCount)); + + u32 TestCRC = UART_CalculateCRC((u8*)SetChannelHeader, (u8*)(Footer)); + + uart_footer* DrawAllFooter = (uart_footer*)(DrawAllHeader + 1); + u32 DrawwAllCRC = UART_CalculateCRC((u8*)DrawAllHeader, (u8*)(DrawAllFooter)); + + HANDLE FileHandle = CreateFileA(OutFileName.Str, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD BytesWritten = 0; + if (!WriteFile(FileHandle, Data.Memory, Data.Size, &BytesWritten, NULL)) + { + InvalidCodePath; + } + } + CloseHandle(FileHandle); + Win32SerialPort_Close(SerialHandle); + + } + else if (true) + { + gs_data Data = PushSize(Ctx.Transient, KB(32)); + + u8 Count = 0; + while(true) + { + CreateMessage(&Data, ++Count); + Win32SerialPort_Write(SerialHandle, Data); + Sleep(100); + } + } + else if (false) + { + gs_data Data = PushSize(Ctx.Transient, KB(32)); + gs_file File = Win32ReadEntireFile(Ctx.FileHandler, OutFileName, Data); + + gs_data Messages = {0}; + u8* ScanAt = Data.Memory; + ScanAt = FindNextHeader(Data, ScanAt); + uart_header* FirstHeader = (uart_header*)ScanAt; + ScanAt += sizeof(uart_header); + + uart_header* LastHeader = 0; + do + { + ScanAt = FindNextHeader(Data, ScanAt); + uart_header* Header = (uart_header*)ScanAt; + if (Header->RecordType == UART_DRAW_ALL) + { + LastHeader = Header; + } + ScanAt += sizeof(uart_header); + }while((u32)(ScanAt - Data.Memory) < Data.Size); + + u8* OnePastLastByte = ((u8*)(LastHeader + 1)) + sizeof(uart_footer); + + Messages.Memory = (u8*)FirstHeader; + Messages.Size = OnePastLastByte - Messages.Memory; + + while (true) + { + Win32SerialPort_Write(SerialHandle, Messages); + Sleep(100); + } + } + + return 0; } diff --git a/src/tests/memory_arena_tests.cpp b/src/tests/memory_arena_tests.cpp index d52623a..82d446f 100644 --- a/src/tests/memory_arena_tests.cpp +++ b/src/tests/memory_arena_tests.cpp @@ -1,7 +1,5 @@ -#include "../app/platform_win32/win32_foldhaus_memory.h" - internal u32 -TESTNextRandom(u32* LastRandomValue) +NextRandom(u32* LastRandomValue) { u32 Result = *LastRandomValue; Result ^= Result << 13; @@ -11,64 +9,63 @@ TESTNextRandom(u32* LastRandomValue) return Result; } -internal void +void MemoryArenaTests() { Test("Allocator") { - gs_allocator Allocator = CreateAllocator(Win32Alloc, Win32Free); + gs_allocator A = CreatePlatformAllocator(); - u8* Data = AllocatorAllocArray(Allocator, u8, 4096); + u8* Data = AllocArray(A, u8, 4096, "root"); for (int i = 0; i < 4096; i++) Data[i] = (i % MaxU8); bool Success = true; - for (int i = 0; i < 4096; i++) Success &= (Data[i] == (i % MaxU8)); + for (int i = 0; i < 4096; i++) Success &= Data[i] == (i % MaxU8); TestResult(Success); - AllocatorFreeArray(Allocator, Data, u8, 4096); - // idk how to test free + FreeArray(A, Data, u8, 4096); + TestResult(true); // TODO(PS): How do we test free? } Test("Memory Cursor") { - gs_allocator A = CreateAllocator(Win32Alloc, Win32Free); + gs_allocator A = CreatePlatformAllocator(); u64 Size = 4096; - gs_data D = AllocatorAlloc(A, Size); - gs_memory_cursor C = CreateMemoryCursor(D); + gs_data D = AllocData(A, Size, "root"); + gs_memory_cursor C = MemoryCursorCreate(D.Memory, D.Size); - u64 RoomLeft = CursorRoomLeft(C); + u64 RoomLeft = MemoryCursorRoomLeft(C); TestResult(RoomLeft == Size); + TestResult(MemoryCursorHasRoom(C)); - TestResult(CursorHasRoom(C, 2048)); - TestResult(CursorHasRoom(C, Size)); - TestResult(!CursorHasRoom(C, Size + 1)); + TestResult(MemoryCursorCanPush(C, 2048)); + TestResult(MemoryCursorCanPush(C, Size)); + TestResult(!MemoryCursorCanPush(C, Size + 1)); for (u64 i = 0; i < 2048; i++) { - u8* Byte = PushSizeOnCursor(&C, 1).Memory; + u8* Byte = MemoryCursorPushSize(&C, 1).Memory; *Byte = (u8)(i % 256); } - RoomLeft = CursorRoomLeft(C); + RoomLeft = MemoryCursorRoomLeft(C); TestResult(RoomLeft == (Size - 2048)); - PopSizeOnCursor(&C, 2048); + MemoryCursorPopSize(&C, 2048); TestResult(C.Position == 0); bool Success = true; for (u64 i = 0; i < 2048; i++) { - u8* Byte = PushSizeOnCursor(&C, 1).Memory; + u8* Byte = MemoryCursorPushSize(&C, 1).Memory; Success &= *Byte == (u8)(i % 256); } TestResult(Success); - - AllocatorFree(A, D.Memory, D.Size); } Test("Memory Arena") { - gs_allocator Al = CreateAllocator(Win32Alloc, Win32Free); - gs_memory_arena A = CreateMemoryArena(Al, "test", 128, 4); + gs_allocator Al = CreatePlatformAllocator(); + gs_memory_arena A = MemoryArenaCreate(128, 4, Al, 0, 0, "Test"); // NOTE(PS): We loop through this block 3 times // 1. Make sure the arena works out of the box @@ -76,42 +73,40 @@ MemoryArenaTests() // 3. Make sure the arena works the same way after freeing for (int i = 0; i < 3; i++) { - gs_data D0 = PushSize_(&A, 32, FileNameAndLineNumberString); + gs_data D0 = PushSize_(&A, 32, DEBUG_LOC); TestResult(D0.Size == 32); // NOTE(PS): This should still result in 32 bytes // because its going to align the Cursor after // it allocates to a multiple of 4 bytes - gs_data D1 = PushSize_(&A, 30, FileNameAndLineNumberString); + gs_data D1 = PushSize_(&A, 30, DEBUG_LOC); TestResult(D1.Size == 32); // NOTE(PS): Allocating bigger than the size remaining // in the current cursor - gs_data D2 = PushSize_(&A, 128, FileNameAndLineNumberString); + gs_data D2 = PushSize_(&A, 128, DEBUG_LOC); TestResult(D2.Size == 128); - TestResult(A.CursorsCount != 1); + TestResult(A.CursorsRoot != A.CursorsHead); // NOTE(PS): Because there is still room in cursor // 0, the head of this gs_data should be one byte // past the end of D1 - gs_data D3 = PushSize_(&A, 32, FileNameAndLineNumberString); + gs_data D3 = PushSize_(&A, 32, DEBUG_LOC); TestResult(D3.Memory == D1.Memory + D1.Size); if (i == 0) { - ClearArena(&A); + MemoryArenaClear(&A); } else if (i == 1) { - FreeMemoryArena(&A); + MemoryArenaFree(&A); } } - - FreeMemoryArena(&A); } - Test("Memory Arena: Push") + Test("Memory Arena - Push") { - gs_allocator Al = CreateAllocator(Win32Alloc, Win32Free); - gs_memory_arena A = CreateMemoryArena(Al, "test", 128, 4); + gs_allocator Al = CreatePlatformAllocator(); + gs_memory_arena A = MemoryArenaCreate(128, 8, Al, 0, 0, "Test"); // NOTE(PS): This makes sure that the Arena is moving its next allocation // pointer forward the appropriate amount after each allocation. If it isnt' @@ -133,16 +128,21 @@ MemoryArenaTests() } TestResult(Success); - FreeArena(&A); } int FreeCount = 0; int ClearCount = 0; - Test("Memory Arena: Stress Test") + gs_debug_allocations_list* DEBUGAllocations = 0; + + Test("Memory Arena - Stress Test") { - gs_allocator Al = CreateAllocator(Win32Alloc, Win32Free); - gs_memory_arena A = CreateMemoryArena(Al, "test", 128, 4); + // NOTE(PS): We're going to create thousands of allocations + // on the allocator of varying sizes. We're also going to clear + // and free the arena at random times to make sure it all works. + + gs_allocator Al = CreatePlatformAllocator(); + gs_memory_arena A = MemoryArenaCreate(4096, 4, Al, 0, 0, "Test"); // NOTE(PS): This is an array of allocation sizes // As we repeat the loop we will get values out of this array @@ -157,19 +157,19 @@ MemoryArenaTests() u32 RandomSeed = 1923; for (u64 i = 0; i < (4096 * 14); i++) { - TESTNextRandom(&RandomSeed); + NextRandom(&RandomSeed); u32 SizeIndex = RandomSeed % RandomSizesCount; u64 RandomSize = RandomSizes[SizeIndex]; if (RandomSize == 0) { - ClearArena(&A); + MemoryArenaClear(&A); ClearCount++; } else if (RandomSize == 2) { - FreeArena(&A); + MemoryArenaFree(&A); FreeCount++; } else { - gs_data D = PushSize_(&A, RandomSize, FileNameAndLineNumberString); + gs_data D = PushSize_(&A, RandomSize, DEBUG_LOC); // NOTE(PS): This check has to be >= because the arena // might have adjusted to maintain alignment on this // allocation. @@ -179,6 +179,24 @@ MemoryArenaTests() TestResult(Success); + DEBUGAllocations = Al.DEBUGAllocList; } -} + printf("\tMemory Arena Cleared: %d times\n", ClearCount); + printf("\tMemory Arena Freed: %d times\n", FreeCount); + +#if 0 + printf("\n\nAllocations:\n"); + for (gs_debug_memory_allocation* ARecord = DEBUGAllocations->Root; + ARecord != 0; + ARecord = ARecord->Next) + { + printf("\t"); + printf("%lld\t%s:%d - %s\n", + ARecord->Size, + ARecord->Loc.File, + ARecord->Loc.Line, + ARecord->Loc.Function); + } +#endif +} \ No newline at end of file diff --git a/src/tests/sanity_tests.cpp b/src/tests/sanity_tests.cpp index fa8f271..440d4e6 100644 --- a/src/tests/sanity_tests.cpp +++ b/src/tests/sanity_tests.cpp @@ -14,11 +14,10 @@ #include "../gs_libs/gs_path.h" #include "../gs_libs/gs_csv.h" +#include "../app/platform_win32/win32_foldhaus_memory.h" #include "./memory_arena_tests.cpp" gs_memory_arena Scratch = {}; -void* Alloc(u64 Size, u64* ResultSize) { *ResultSize = Size; return malloc(Size); } -void Free(void* Ptr, u64 Size) { return free(Ptr); } bool StringTest (gs_const_string StrA, gs_const_string StrB) { @@ -38,9 +37,76 @@ Flower A 55 32 128 foo, bar, blah, baz, whatever Flower B 123 344 32 foo, bar, blah, baz, whatever Flower C 55 32 128 foo, bar, blah, baz, whatever)FOO"; +struct test_sll +{ + u32 Val; + test_sll* Next; +}; + int main (int ArgCount, char** Args) { - Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free), "Scratch"); + gs_allocator Al = CreatePlatformAllocator(); + Scratch = MemoryArenaCreate(KB(4), Bytes(8), Al, 0, 0, "Scratch"); + + Test("SLL 1") + { + test_sll* Root = 0; + test_sll* Head = 0; + + test_sll* First = PushStruct(&Scratch, test_sll); + First->Val = 0; + SLLInit(Root, Head, First); + TestResult((Root == First) && (Head == First)); + + for (u32 i = 1; i < 4; i++) + { + test_sll* New = PushStruct(&Scratch, test_sll); + New->Val = i; + SLLPush(Head, New); + TestResult((Root == First) && (Head == New)); + } + + bool Success = true; + u32 i = 0; + for (test_sll* At = Root; + At && At->Next != 0; + SLLNext(At)) + { + Success &= (At->Val == i); + i += 1; + } + TestResult(Success); + } + + Test("SLL Push Or Init") + { + test_sll* Root = 0; + test_sll* Head = 0; + + test_sll* First = PushStruct(&Scratch, test_sll); + First->Val = 0; + SLLPushOrInit(Root, Head, First); + TestResult((Root == First) && (Head == First)); + + for (u32 i = 1; i < 4; i++) + { + test_sll* New = PushStruct(&Scratch, test_sll); + New->Val = i; + SLLPushOrInit(Root, Head, New); + TestResult((Root == First) && (Head == New)); + } + + bool Success = true; + u32 i = 0; + for (test_sll* At = Root; + At && At->Next != 0; + SLLNext(At)) + { + Success &= (At->Val == i); + i += 1; + } + TestResult(Success); + } Test("gs_string") {