From 0b3d603e04b5c26fa962b57a70a58c8dd9f3f8a1 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 30 May 2020 14:54:37 -0700 Subject: [PATCH 01/43] Created platform_file_handler and integrated it --- src/app/foldhaus_app.cpp | 4 +- src/app/foldhaus_assembly.cpp | 2 +- src/app/foldhaus_platform.h | 60 +++++++++++++++++++++-- src/app/panels/foldhaus_panel_hierarchy.h | 2 +- src/app/win32_foldhaus.cpp | 56 ++++++++++----------- 5 files changed, 88 insertions(+), 36 deletions(-) diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 90a737a..ee84a3c 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -92,7 +92,7 @@ INITIALIZE_APPLICATION(InitializeApplication) // TODO(Peter): put in InitializeInterface? r32 FontSize = 14; { - platform_memory_result FontFile = Context.PlatformReadEntireFile("Anonymous Pro.ttf"); + platform_memory_result FontFile = ReadEntireFile(Context, "data/Anonymous Pro.ttf"); if (!FontFile.Error) { bitmap_font* Font = PushStruct(&State->Permanent, bitmap_font); @@ -176,7 +176,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Camera.LookAt = v3{0, 0, 0}; #if 1 - char Path[] = "blumen_lumen.fold"; + char Path[] = "data/blumen_lumen.fold"; LoadAssembly(State, Context, Path); #endif diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index 0e17226..c733c6b 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -70,7 +70,7 @@ s32 TempAssemblyOffsetsCount = 3; internal void LoadAssembly (app_state* State, context Context, char* Path) { - platform_memory_result AssemblyFile = Context.PlatformReadEntireFile(Path); + platform_memory_result AssemblyFile = ReadEntireFile(Context, Path); if (AssemblyFile.Error == PlatformMemory_NoError) { assembly_definition AssemblyDefinition = ParseAssemblyFile(AssemblyFile.Base, AssemblyFile.Size, &State->Transient, State->GlobalLog); diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index 2ee07cf..180e27c 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -63,6 +63,8 @@ enum platform_memory_error PlatformMemory_UnknownError, // You should implement handling this when you see it }; +// TODO(Peter): Change this to just be data +// - Base, and Size struct platform_memory_result { u8* Base; @@ -104,6 +106,13 @@ typedef PLATFORM_WRITE_ENTIRE_FILE(platform_write_entire_file); #define PLATFORM_GET_FILE_PATH(name) b32 name(char* PathBuffer, s32 BufferLength, const char* FilterStrings) typedef PLATFORM_GET_FILE_PATH(platform_get_file_path); +struct platform_file_handler +{ + platform_read_entire_file* ReadEntireFile; + platform_write_entire_file* WriteEntireFile; + platform_get_file_path* GetFilePath; +}; + #define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) s32 name(u8* Memory, s32 Width, s32 Height) typedef PLATFORM_GET_GPU_TEXTURE_HANDLE(platform_get_gpu_texture_handle); @@ -117,13 +126,13 @@ struct platform_network_address typedef s32 platform_socket_handle; typedef s32 platform_network_address_handle; -#define PLATFORM_GET_SOCKET_HANDLE(name) platform_socket_handle name(s32 Multicast_TimeToLive) +#define PLATFORM_GET_SOCKET_HANDLE(name) platform_socket_handle name(s32 Multicast_TimeToLive) typedef PLATFORM_GET_SOCKET_HANDLE(platform_get_socket_handle); #define PLATFORM_GET_SEND_ADDRESS_HANDLE(name) platform_network_address_handle name(s32 AddressFamily, u16 Port, u32 Address) typedef PLATFORM_GET_SEND_ADDRESS_HANDLE(platform_get_send_address); -#define PLATFORM_SET_SOCKET_OPTION(name) s32 name(platform_socket_handle SocketHandle, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength) +#define PLATFORM_SET_SOCKET_OPTION(name) s32 name(platform_socket_handle SocketHandle, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength) typedef PLATFORM_SET_SOCKET_OPTION(platform_set_socket_option); #define PLATFORM_SEND_TO(name) s32 name(platform_socket_handle SocketHandle, u32 Address, u32 Port, const char* Buffer, s32 BufferLength, s32 Flags) @@ -134,7 +143,7 @@ typedef PLATFORM_CLOSE_SOCKET(platform_close_socket); // File IO -// TODO(Peter): +// TODO(Peter): struct directory_listing { string Path; @@ -258,7 +267,9 @@ struct context platform_alloc* PlatformAlloc; platform_free* PlatformFree; platform_realloc* PlatformRealloc; - platform_read_entire_file* PlatformReadEntireFile; + + platform_file_handler FileHandler; + platform_write_entire_file* PlatformWriteEntireFile; platform_get_file_path* PlatformGetFilePath; platform_get_gpu_texture_handle* PlatformGetGPUTextureHandle; @@ -270,6 +281,47 @@ struct context platform_close_socket* PlatformCloseSocket; }; +// File Handler +internal platform_memory_result +ReadEntireFile(platform_file_handler FileHandler, char* Path) +{ + // TODO(Peter): Convert Path to be a string + platform_memory_result Result = FileHandler.ReadEntireFile(Path); + return Result; +} +internal platform_memory_result +ReadEntireFile(context Context, char* Path) +{ + return ReadEntireFile(Context.FileHandler, Path); +} + +internal b32 +WriteEntireFile(platform_file_handler FileHandler, char* Path, u8* Contents, u32 Size) +{ + // TODO(Peter): Convert Path to be a string + // TODO(Peter): Overload to take a data struct instead of Contents And Size + b32 Result = FileHandler.WriteEntireFile(Path, Contents, Size); + return Result; +} +internal b32 +WriteEntireFile(context Context, char* Path, u8* Contents, u32 Size) +{ + return WriteEntireFile(Context.FileHandler, Path, Contents, Size); +} + +internal b32 +GetFilePath(platform_file_handler FileHandler, char* PathBuffer, s32 BufferLength, char* FilterStrings) +{ + // TODO(Peter): Convert Path to be a string + b32 Result = FileHandler.GetFilePath(PathBuffer, BufferLength, (const char*)FilterStrings); + return Result; +} +internal b32 +GetFilePath(context Context, char* PathBuffer, s32 BufferLength, char* FilterStrings) +{ + return GetFilePath(Context.FileHandler, PathBuffer, BufferLength, FilterStrings); +} + #define FOLDHAUS_PLATFORM_H #endif // FOLDHAUS_PLATFORM_H \ No newline at end of file diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index 6f1ff6f..2452f22 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -66,7 +66,7 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende if (ui_LayoutButton(&State->Interface_, &Layout, TempString, ListItemBGColor, ListItemHover, ListItemSelected)) { char FilePath[256]; - b32 Success = Context.PlatformGetFilePath(FilePath, 256, "Foldhaus Files\0*.fold\0\0"); + b32 Success = GetFilePath(Context, FilePath, 256, "Foldhaus Files\0*.fold\0\0"); if (Success) { LoadAssembly(State, Context, FilePath); diff --git a/src/app/win32_foldhaus.cpp b/src/app/win32_foldhaus.cpp index cf2f5c1..3155e6b 100644 --- a/src/app/win32_foldhaus.cpp +++ b/src/app/win32_foldhaus.cpp @@ -132,7 +132,7 @@ WorkerThreadProc (LPVOID InputThreadInfo) Entry = CompleteAndTakeNextJob(ThreadInfo->Queue, Entry); if (Entry.IsValid) { - ThreadInfo->Queue->Jobs[Entry.Index].WorkProc(ThreadInfo->ID, + ThreadInfo->Queue->Jobs[Entry.Index].WorkProc(ThreadInfo->ID, ThreadInfo->Queue->Jobs[Entry.Index].Data); } else @@ -176,10 +176,10 @@ PLATFORM_SET_SOCKET_OPTION(Win32SetSocketOption) PLATFORM_GET_SOCKET_HANDLE(Win32GetSocketHandle) { - // NOTE(Peter): These used to be passed in as paramters, but we only use this function + // NOTE(Peter): These used to be passed in as paramters, but we only use this function // with AF_INET, SOCK_DGRAM, and Protocol = 0. These are also platform specific values // so I was having to include windows.h in the platform agnostic code to accomodate that - // function signature. + // function signature. s32 AddressFamily = AF_INET; s32 Type = SOCK_DGRAM; s32 Protocol = 0; @@ -207,7 +207,7 @@ PLATFORM_GET_SOCKET_HANDLE(Win32GetSocketHandle) SocketValues[NewSocketIndex].Socket = socket(AddressFamily, Type, Protocol); - int Error = Win32SetSocketOption(NewSocketIndex, IPPROTO_IP, IP_MULTICAST_TTL, + int Error = Win32SetSocketOption(NewSocketIndex, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)(&Multicast_TimeToLive), sizeof(Multicast_TimeToLive)); return (platform_socket_handle)NewSocketIndex; @@ -265,7 +265,7 @@ GET_FONT_INFO(Win32GetFontInfo) CurrentFont = CreateFont(PixelHeight, 0, 0, 0, FontWeight, - Italic, + Italic, Underline, Strikeout, ANSI_CHARSET, @@ -311,7 +311,7 @@ DRAW_FONT_CODEPOINT(Win32DrawFontCodepoint) COLORREF PixelColor; for (u32 Y = 0; Y < *OutHeight; Y++) { - // NOTE(Peter): XOffset * 4 b/c its 4 bytes per pixel. + // NOTE(Peter): XOffset * 4 b/c its 4 bytes per pixel. u8* Channel = (u8*)Row + (XOffset * 4); for (u32 X = 0; X < *OutWidth; X++) { @@ -392,7 +392,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse b32 AltDown = GetKeyState(VK_MENU) & 0x8000; b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true, + AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true, ShiftDown, AltDown, CtrlDown, false); Mouse->LeftButtonState = KeyState_IsDown & ~KeyState_WasDown; @@ -414,7 +414,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse b32 AltDown = GetKeyState(VK_MENU) & 0x8000; b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true, + AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true, ShiftDown, AltDown, CtrlDown, false); Mouse->MiddleButtonState = KeyState_IsDown & ~KeyState_WasDown; @@ -428,7 +428,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse b32 AltDown = GetKeyState(VK_MENU) & 0x8000; b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true, + AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true, ShiftDown, AltDown, CtrlDown, false); Mouse->RightButtonState = KeyState_IsDown & ~KeyState_WasDown; Mouse->DownPos = Mouse->Pos; @@ -443,7 +443,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse b32 AltDown = GetKeyState(VK_MENU) & 0x8000; b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false, + AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false, ShiftDown, AltDown, CtrlDown, false); Mouse->LeftButtonState = ~KeyState_IsDown & KeyState_WasDown; @@ -457,7 +457,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse b32 AltDown = GetKeyState(VK_MENU) & 0x8000; b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false, + AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false, ShiftDown, AltDown, CtrlDown, false); Mouse->MiddleButtonState = ~KeyState_IsDown & KeyState_WasDown; @@ -471,7 +471,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse b32 AltDown = GetKeyState(VK_MENU) & 0x8000; b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; - AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false, + AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false, ShiftDown, AltDown, CtrlDown, false); Mouse->RightButtonState = ~KeyState_IsDown & KeyState_WasDown; @@ -496,7 +496,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000; // New Input Queue - AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown, + AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown, ShiftDown, AltDown, CtrlDown, false); }break; @@ -553,7 +553,7 @@ Win32Realloc(u8* Buf, s32 OldSize, s32 NewSize) return NewMemory; } -internal s32 +internal s32 Win32GetThreadId() { s32 Result = GetCurrentThreadId(); @@ -561,8 +561,8 @@ Win32GetThreadId() } // NOTE(Peter): Only meant to take one of the values specified below: -// IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM, -// IDC_ICON, IDC_NO, IDC_SIZE, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, +// IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM, +// IDC_ICON, IDC_NO, IDC_SIZE, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, // IDC_SIZEWE, IDC_UPARROW, IDC_WAIT internal HCURSOR Win32LoadSystemCursor(char* CursorIdentifier) @@ -601,12 +601,12 @@ WinMain ( GlobalDebugServices = (debug_services*)malloc(sizeof(debug_services)); s32 DebugThreadCount = PLATFORM_THREAD_COUNT + 1; - InitDebugServices(GlobalDebugServices, - PerformanceCountFrequency, - DEBUGAlloc, - Win32Realloc, - GetWallClock, - Win32GetThreadId, + InitDebugServices(GlobalDebugServices, + PerformanceCountFrequency, + DEBUGAlloc, + Win32Realloc, + GetWallClock, + Win32GetThreadId, DebugThreadCount); input_queue InputQueue; @@ -666,9 +666,9 @@ WinMain ( Context.PlatformAlloc = Win32Alloc; Context.PlatformFree = Win32Free; Context.PlatformRealloc = Win32Realloc; - Context.PlatformReadEntireFile = Win32ReadEntireFile; - Context.PlatformWriteEntireFile = Win32WriteEntireFile; - Context.PlatformGetFilePath = Win32SystemDialogueOpenFile; + Context.FileHandler.ReadEntireFile = Win32ReadEntireFile; + Context.FileHandler.WriteEntireFile = Win32WriteEntireFile; + Context.FileHandler.GetFilePath = Win32SystemDialogueOpenFile; Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; Context.PlatformGetSocketHandle = Win32GetSocketHandle; Context.PlatformSetSocketOption = Win32SetSocketOption; @@ -702,9 +702,9 @@ WinMain ( Context.WindowIsVisible = true; while (Running) { - if (GlobalDebugServices->RecordFrames) - { - EndDebugFrame(GlobalDebugServices); + if (GlobalDebugServices->RecordFrames) + { + EndDebugFrame(GlobalDebugServices); } DEBUG_TRACK_SCOPE(MainLoop); From c2f3b9193d17cbcdf58fff65567ee010a56c2194 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 30 May 2020 15:09:06 -0700 Subject: [PATCH 02/43] platform_file_handler functions now take strings rather than char arrays --- src/app/foldhaus_app.cpp | 6 ++--- src/app/foldhaus_assembly.cpp | 7 +++--- src/app/foldhaus_platform.h | 25 ++++++++----------- .../foldhaus_panel_animation_timeline.h | 4 +-- src/app/panels/foldhaus_panel_hierarchy.h | 6 ++--- src/app/win32_foldhaus_fileio.h | 16 ++++++------ src/gs_libs/gs_string.h | 12 ++++++--- 7 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index ee84a3c..43b913e 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -92,7 +92,7 @@ INITIALIZE_APPLICATION(InitializeApplication) // TODO(Peter): put in InitializeInterface? r32 FontSize = 14; { - platform_memory_result FontFile = ReadEntireFile(Context, "data/Anonymous Pro.ttf"); + platform_memory_result FontFile = ReadEntireFile(Context, MakeStringLiteral("data/Anonymous Pro.ttf")); if (!FontFile.Error) { bitmap_font* Font = PushStruct(&State->Permanent, bitmap_font); @@ -176,8 +176,8 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Camera.LookAt = v3{0, 0, 0}; #if 1 - char Path[] = "data/blumen_lumen.fold"; - LoadAssembly(State, Context, Path); + string SculpturePath = MakeStringLiteral("data/blumen_lumen.fold"); + LoadAssembly(State, Context, SculpturePath); #endif State->PixelsToWorldScale = .01f; diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index c733c6b..7b870db 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -68,16 +68,15 @@ static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, s32 TempAssemblyOffsetsCount = 3; internal void -LoadAssembly (app_state* State, context Context, char* Path) +LoadAssembly (app_state* State, context Context, string Path) { platform_memory_result AssemblyFile = ReadEntireFile(Context, Path); if (AssemblyFile.Error == PlatformMemory_NoError) { assembly_definition AssemblyDefinition = ParseAssemblyFile(AssemblyFile.Base, AssemblyFile.Size, &State->Transient, State->GlobalLog); - string PathString = MakeStringLiteral(Path); - s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(PathString.Memory, PathString.Length, '\\'); - string FileName = Substring(PathString, IndexOfLastSlash + 1); + s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\'); + string FileName = Substring(Path, IndexOfLastSlash + 1); memory_arena AssemblyArena = {}; AssemblyArena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index 180e27c..725284b 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -97,13 +97,13 @@ typedef PLATFORM_FREE(platform_free); #define PLATFORM_REALLOC(name) u8* name(u8* Base, u32 OldSize, u32 NewSize) typedef PLATFORM_REALLOC(platform_realloc); -#define PLATFORM_READ_ENTIRE_FILE(name) platform_memory_result name(char* Path) +#define PLATFORM_READ_ENTIRE_FILE(name) platform_memory_result name(string Path) typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file); -#define PLATFORM_WRITE_ENTIRE_FILE(name) b32 name(char* Path, u8* Contents, s32 Size) +#define PLATFORM_WRITE_ENTIRE_FILE(name) b32 name(string Path, u8* Contents, s32 Size) typedef PLATFORM_WRITE_ENTIRE_FILE(platform_write_entire_file); -#define PLATFORM_GET_FILE_PATH(name) b32 name(char* PathBuffer, s32 BufferLength, const char* FilterStrings) +#define PLATFORM_GET_FILE_PATH(name) b32 name(string* PathBuffer, const char* FilterStrings) typedef PLATFORM_GET_FILE_PATH(platform_get_file_path); struct platform_file_handler @@ -283,43 +283,40 @@ struct context // File Handler internal platform_memory_result -ReadEntireFile(platform_file_handler FileHandler, char* Path) +ReadEntireFile(platform_file_handler FileHandler, string Path) { - // TODO(Peter): Convert Path to be a string platform_memory_result Result = FileHandler.ReadEntireFile(Path); return Result; } internal platform_memory_result -ReadEntireFile(context Context, char* Path) +ReadEntireFile(context Context, string Path) { return ReadEntireFile(Context.FileHandler, Path); } internal b32 -WriteEntireFile(platform_file_handler FileHandler, char* Path, u8* Contents, u32 Size) +WriteEntireFile(platform_file_handler FileHandler, string Path, u8* Contents, u32 Size) { - // TODO(Peter): Convert Path to be a string // TODO(Peter): Overload to take a data struct instead of Contents And Size b32 Result = FileHandler.WriteEntireFile(Path, Contents, Size); return Result; } internal b32 -WriteEntireFile(context Context, char* Path, u8* Contents, u32 Size) +WriteEntireFile(context Context, string Path, u8* Contents, u32 Size) { return WriteEntireFile(Context.FileHandler, Path, Contents, Size); } internal b32 -GetFilePath(platform_file_handler FileHandler, char* PathBuffer, s32 BufferLength, char* FilterStrings) +GetFilePath(platform_file_handler FileHandler, string* PathBuffer, char* FilterStrings) { - // TODO(Peter): Convert Path to be a string - b32 Result = FileHandler.GetFilePath(PathBuffer, BufferLength, (const char*)FilterStrings); + b32 Result = FileHandler.GetFilePath(PathBuffer, (const char*)FilterStrings); return Result; } internal b32 -GetFilePath(context Context, char* PathBuffer, s32 BufferLength, char* FilterStrings) +GetFilePath(context Context, string* PathBuffer, char* FilterStrings) { - return GetFilePath(Context.FileHandler, PathBuffer, BufferLength, FilterStrings); + return GetFilePath(Context.FileHandler, PathBuffer, FilterStrings); } diff --git a/src/app/panels/foldhaus_panel_animation_timeline.h b/src/app/panels/foldhaus_panel_animation_timeline.h index 36b23fc..b4a2dfe 100644 --- a/src/app/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/panels/foldhaus_panel_animation_timeline.h @@ -291,7 +291,7 @@ AnimationTimeline_Cleanup(panel* Panel, app_state* State) internal void DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBuffer, frame_range VisibleFrames, rect BarBounds, mouse_state Mouse, app_state* State) { - MakeStringBuffer(TempString, 256); + string TempString = PushString(&State->Transient, 256); s32 VisibleFrameCount = VisibleFrames.Max - VisibleFrames.Min; @@ -450,7 +450,7 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V internal gs_list_handle DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect PanelBounds, gs_list_handle SelectedBlockHandle, ui_interface* Interface, app_state* State) { - string TempString = MakeString(PushArray(&State->Transient, char, 256), 256); + string TempString = PushString(&State->Transient, 256); gs_list_handle Result = SelectedBlockHandle; rect LayerMenuBounds, TimelineBounds; diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index 2452f22..7f27c94 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -33,7 +33,7 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende v4 ListItemHover = State->Interface_.Style.ListBGHover; v4 ListItemSelected = State->Interface_.Style.ListBGSelected; - string TempString = MakeString(PushArray(&State->Transient, char, 256), 0, 256); + string TempString = PushString(&State->Transient, 256); u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1; u32 LinesDrawn = 0; @@ -65,8 +65,8 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende PrintF(&TempString, "+ Add Assembly"); if (ui_LayoutButton(&State->Interface_, &Layout, TempString, ListItemBGColor, ListItemHover, ListItemSelected)) { - char FilePath[256]; - b32 Success = GetFilePath(Context, FilePath, 256, "Foldhaus Files\0*.fold\0\0"); + string FilePath = PushString(&State->Transient, 256); + b32 Success = GetFilePath(Context, &FilePath, "Foldhaus Files\0*.fold\0\0"); if (Success) { LoadAssembly(State, Context, FilePath); diff --git a/src/app/win32_foldhaus_fileio.h b/src/app/win32_foldhaus_fileio.h index 7104c5e..3a9a9aa 100644 --- a/src/app/win32_foldhaus_fileio.h +++ b/src/app/win32_foldhaus_fileio.h @@ -13,13 +13,14 @@ PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile) platform_memory_result Result = {}; Result.Error = PlatformMemory_NoError; - HANDLE FileHandle = CreateFileA (Path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + Assert(IsNullTerminated(Path)); + HANDLE FileHandle = CreateFileA (Path.Memory, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (FileHandle != INVALID_HANDLE_VALUE) { DWORD FileSize = GetFileSize(FileHandle, NULL); Result.Base = (u8*)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (Result.Base) + if (Result.Base) { Result.Size = FileSize; @@ -49,9 +50,10 @@ PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile) PLATFORM_WRITE_ENTIRE_FILE(Win32WriteEntireFile) { + Assert(IsNullTerminated(Path)); b32 Result = false; HANDLE FileHandle = CreateFileA ( - Path, + Path.Memory, GENERIC_WRITE, 0, NULL, @@ -111,7 +113,7 @@ PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile) { b32 Result = false; - PathBuffer[0] = 0; + PathBuffer->Memory[0] = 0; OPENFILENAMEA OpenFileName = {}; OpenFileName.lStructSize = sizeof(OpenFileName); @@ -120,8 +122,8 @@ PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile) OpenFileName.lpstrCustomFilter = NULL; // NOTE(Peter): for preserving last filter string chosen OpenFileName.nMaxCustFilter = 0; // NOTE(Peter): ignored since we left CustomFilter null OpenFileName.nFilterIndex = 1; - OpenFileName.lpstrFile = PathBuffer; - OpenFileName.nMaxFile = BufferLength; + OpenFileName.lpstrFile = PathBuffer->Memory; + OpenFileName.nMaxFile = PathBuffer->Max; OpenFileName.lpstrFileTitle = NULL; OpenFileName.nMaxFileTitle = 0; // NOTE(Peter): Ignored since fileTitle is null OpenFileName.lpstrInitialDir = NULL; @@ -138,7 +140,7 @@ internal directory_listing EnumerateDirectory(char* Path, memory_arena* Storage) { directory_listing Result = {}; - // TODO(Peter): + // TODO(Peter): return Result; } diff --git a/src/gs_libs/gs_string.h b/src/gs_libs/gs_string.h index 1f335a4..edd80c7 100644 --- a/src/gs_libs/gs_string.h +++ b/src/gs_libs/gs_string.h @@ -14,6 +14,7 @@ struct string { char* Memory; s32 Length; + // TODO(Peter): Max -> LengthMax for clarity s32 Max; }; @@ -159,10 +160,7 @@ static float GSPowF (float N, s32 Power); #endif // Setup - -#ifdef GS_MEMORY_H -#define PushString(str, arena, size) (str)->Memory = PushArray(arena, char, size); (str)->Length = 0; (str)->Max = size; -#endif +#define PushString(arena, size) MakeString(PushArray(arena, char, size), 0, size); static void InitializeEmptyString (string* String, char* Data, s32 DataSize); static void InitializeString(string* String, char* Data, s32 Used, s32 Max); @@ -421,6 +419,12 @@ ClearString (string* String) // Char Value Types //////////////////////////////////////////////////////////////// +static bool IsNullTerminated(string Str) +{ + char LastChar = Str.Memory[Str.Length]; + bool Result = (LastChar == 0); + return Result; +} static bool IsSlash (char C) { return ((C == '\\') || (C == '/')); } static bool IsNewline (char C) { return (C == '\n') || (C == '\r'); } static bool IsWhitespace (char C) { return (C == ' ') || (C == '\t'); } From bfd9d6671cfc9cdbb655ffc7c4fe583e9e075aea Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Tue, 9 Jun 2020 20:33:51 -0700 Subject: [PATCH 03/43] Finished parsing the new assembly file format --- src/app/assembly_parser.cpp | 646 +++++++++++++++------------------ src/app/assembly_parser.h | 76 ---- src/app/foldhaus_app.cpp | 10 +- src/app/foldhaus_app.h | 19 +- src/app/foldhaus_assembly.cpp | 74 ++-- src/app/foldhaus_assembly.h | 38 +- src/app/foldhaus_interface.cpp | 4 +- src/app/foldhaus_panel.h | 16 +- 8 files changed, 381 insertions(+), 502 deletions(-) delete mode 100644 src/app/assembly_parser.h diff --git a/src/app/assembly_parser.cpp b/src/app/assembly_parser.cpp index 459f644..5b6605a 100644 --- a/src/app/assembly_parser.cpp +++ b/src/app/assembly_parser.cpp @@ -5,440 +5,386 @@ // #ifndef ASSEMBLY_PARSER_CPP -internal assembly_token -ParseToken (tokenizer* Tokenizer) +enum assembly_field { - assembly_token Result = {}; - Result.Token = Tokenizer->At; - Result.Length = 1; - EatChar(Tokenizer); + AssemblyField_AssemblyName, + AssemblyField_AssemblyScale, + AssemblyField_LedStripCount, - if (*Result.Token == ':'){ Result.Type = AssemblyToken_Colon; } - else if (*Result.Token == ';'){ Result.Type = AssemblyToken_SemiColon; } - else if (*Result.Token =='{'){ Result.Type = AssemblyToken_LeftCurlyBrace; } - else if (*Result.Token =='}'){ Result.Type = AssemblyToken_RightCurlyBrace; } - else if (*Result.Token ==','){ Result.Type = AssemblyToken_Comma; } - else if (IsNumericExtended(*Result.Token)) - { - while(*Tokenizer->At && IsNumericExtended(*Tokenizer->At)) { EatChar(Tokenizer); } - Result.Type = AssemblyToken_Number; - Result.Length = Tokenizer->At - Result.Token; - } - else if (*Result.Token =='\"') - { - while(*Tokenizer->At && *Tokenizer->At != '\"') { EatChar(Tokenizer); } - Result.Token++; // Skip the quote - Result.Type = AssemblyToken_String; - Result.Length = (Tokenizer->At - Result.Token) - 1; - } - else if (*Result.Token == '(') - { - while(*Tokenizer->At && *Tokenizer->At != ')') { EatChar(Tokenizer); } - Result.Token++; // Skip the paren - Result.Type = AssemblyToken_Vector; - Result.Length = (Tokenizer->At - Result.Token) - 1; - } - else if (CharArraysEqualUpToLength(Result.Token, LED_STRIP_IDENTIFIER, CharArrayLength(LED_STRIP_IDENTIFIER))) - { - Result.Type = AssemblyToken_LEDStrip; - Result.Length = CharArrayLength(LED_STRIP_IDENTIFIER); - Tokenizer->At += Result.Length - 1; - } - else if (CharArraysEqualUpToLength(Result.Token, END_ASSEMBLY_FILE_IDENTIFIER, CharArrayLength(END_ASSEMBLY_FILE_IDENTIFIER))) - { - Result.Type = AssemblyToken_EndOfFile; - Result.Length = CharArrayLength(END_ASSEMBLY_FILE_IDENTIFIER); - Tokenizer->At += Result.Length - 1; - } - else - { - Result.Type = AssemblyToken_Identifier; - while(*Tokenizer->At && !IsWhitespace(*Tokenizer->At)) { EatChar(Tokenizer); } - } + AssemblyField_LedStrip, + AssemblyField_ControlBoxId, + AssemblyField_StartUniverse, + AssemblyField_StartChannel, + AssemblyField_PointPlacementType, + AssemblyField_InterpolatePoints, + AssemblyField_Start, + AssemblyField_End, + AssemblyField_LedCount, + AssemblyField_TagsCount, + AssemblyField_Tag, + AssemblyField_Name, + AssemblyField_Value, - return Result; -} + AssemblyField_Count, +}; -internal v3 -ParseAssemblyVector (char* String) -{ - v3 Result = {}; +global_variable char* AssemblyFieldIdentifiers[] = { + "assembly_name", // AssemblyField_AssemblyName + "assembly_scale", // AssemblyField_AssemblyScale + "led_strip_count", // AssemblyField_LedStripCount - tokenizer Tokenizer = {}; - Tokenizer.At = String; + "led_strip", // AssemblyField_LedStrip - EatWhitespace(&Tokenizer); - Result.x = ParseFloatUnsafe(Tokenizer.At).FloatValue; - EatPastCharacter(&Tokenizer, ','); + "control_box_id", // AssemblyField_ControlBoxId + "start_universe", // AssemblyField_StartUniverse + "start_channel", // AssemblyField_StartChannel - EatWhitespace(&Tokenizer); - Result.y = ParseFloatUnsafe(Tokenizer.At).FloatValue; - EatPastCharacter(&Tokenizer, ','); + "point_placement_type", // AssemblyField_PointPlacementType + "interpolate_points", // AssemblyField_InterpolatePoints + "start", // AssemblyField_Start + "end", // AssemblyField_End - EatWhitespace(&Tokenizer); - Result.z = ParseFloatUnsafe(Tokenizer.At).FloatValue; - EatPastCharacter(&Tokenizer, ','); + "led_count", // AssemblyField_LedCount - return Result; -} + "tags_count", // AssemblyField_TagCount + "tag", // AssemblyField_Tag + "name", // AssemblyField_Name + "value", // AssemblyField_Value +}; -internal b32 -ParseAssemblyFileHeader (assembly_definition* Assembly, tokenizer* Tokenizer) +struct assembly_tokenizer { - b32 HeaderIsValid = false; + string Text; + char* At; - if (CharArraysEqualUpToLength(Tokenizer->At, LED_STRIP_COUNT_IDENTIFIER, CharArrayLength(LED_STRIP_COUNT_IDENTIFIER))) - { - Tokenizer->At += CharArrayLength(LED_STRIP_COUNT_IDENTIFIER); - EatWhitespace(Tokenizer); - assembly_token CountToken = ParseToken(Tokenizer); - if (CountToken.Type == AssemblyToken_Number) - { - Assembly->LEDStripSize = ParseSignedIntUnsafe(CountToken.Token).SignedIntValue; - HeaderIsValid = true; - } - EatWhitespace(Tokenizer); - } - return HeaderIsValid; -} + u32 LineNumber; +}; -internal led_strip_definition -ParseLEDStrip (tokenizer* Tokenizer) +internal bool +AtValidPosition(assembly_tokenizer* T) { - led_strip_definition Result = {}; - - // Control Box Index - while (*Tokenizer->At && !IsNumericExtended(*Tokenizer->At)) { EatChar(Tokenizer); } - assembly_token BoxIDToken = ParseToken(Tokenizer); - Assert(BoxIDToken.Type == AssemblyToken_Number); - Result.ControlBoxID = ParseSignedIntUnsafe(BoxIDToken.Token).SignedIntValue; - - // Start Universe - EatPastCharacter(Tokenizer, ','); - EatWhitespace(Tokenizer); - assembly_token StartUniverseToken = ParseToken(Tokenizer); - Assert(BoxIDToken.Type == AssemblyToken_Number); - Result.StartUniverse = ParseSignedIntUnsafe(StartUniverseToken.Token).SignedIntValue; - - // Start Channel - EatPastCharacter(Tokenizer, ','); - EatWhitespace(Tokenizer); - assembly_token StartChannelToken = ParseToken(Tokenizer); - Assert(BoxIDToken.Type == AssemblyToken_Number); - Result.StartChannel = ParseSignedIntUnsafe(StartChannelToken.Token).SignedIntValue; - - // Strip Type - // TODO(Peter): This is unused for now, and would be a branch point for parsing - // the rest of the info. Fix this. - EatPastCharacter(Tokenizer, ','); - EatWhitespace(Tokenizer); - if (CharArraysEqualUpToLength(Tokenizer->At, INTERPOLATE_POINTS_IDENTIFIER, CharArrayLength(INTERPOLATE_POINTS_IDENTIFIER))) - { - Result.InterpolationType = StripInterpolate_Points; - - // Start Position - EatPastCharacter(Tokenizer, ','); - EatWhitespace(Tokenizer); - assembly_token StartPositionToken = ParseToken(Tokenizer); - Assert(StartPositionToken.Type == AssemblyToken_Vector); - Result.InterpolatePositionStart = ParseAssemblyVector(StartPositionToken.Token); - - // End Position - EatPastCharacter(Tokenizer, ','); - EatWhitespace(Tokenizer); - assembly_token EndPositionToken = ParseToken(Tokenizer); - Assert(EndPositionToken.Type == AssemblyToken_Vector); - Result.InterpolatePositionEnd = ParseAssemblyVector(EndPositionToken.Token); - - // LEDs Per Strip - EatPastCharacter(Tokenizer, ','); - EatWhitespace(Tokenizer); - assembly_token LEDsPerStripToken = ParseToken(Tokenizer); - Assert(BoxIDToken.Type == AssemblyToken_Number); - Result.LEDsPerStrip = ParseSignedIntUnsafe(LEDsPerStripToken.Token).SignedIntValue; - } - - EatPastCharacter(Tokenizer, '}'); - EatWhitespace(Tokenizer); - + bool Result = ((T->At - T->Text.Memory) < T->Text.Length); return Result; } internal void -ParseAssemblyFileBody (assembly_definition* Assembly, tokenizer* Tokenizer) +AdvanceChar(assembly_tokenizer* T) { - EatWhitespace(Tokenizer); - - while(*Tokenizer->At) + if (IsNewline(T->At[0])) { - EatWhitespace(Tokenizer); - assembly_token Token = ParseToken(Tokenizer); - - if (Token.Type != AssemblyToken_EndOfFile) - { - switch (Token.Type) - { - case AssemblyToken_LEDStrip: - { - led_strip_definition* LEDStripDef = Assembly->LEDStrips + Assembly->LEDStripCount; - Assert(Assembly->LEDStripCount < Assembly->LEDStripSize); - - *LEDStripDef = ParseLEDStrip(Tokenizer); - Assembly->TotalLEDCount += LEDStripDef->LEDsPerStrip; - - Assembly->LEDStripCount++; - } break; - - // TODO(Peter): Other cases? What else would need to be in the assembly body? - - InvalidDefaultCase; - } - } - else - { - break; - } + T->LineNumber += 1; } - - // NOTE(Peter): Ensure the validity of the assembly file. We probably don't want an assert here, - // more likely we want to load a valid assembly anyways, and just raise this as an error to the user - // so they can fix it. - Assert(Assembly->LEDStripCount == Assembly->LEDStripSize); + T->At++; } -inline b32 -ParseTokenEquals (tokenizer* T, char* Validate) +internal void +EatWhitespace(assembly_tokenizer* T) { - b32 Result = true; + while(AtValidPosition(T) && IsNewlineOrWhitespace(T->At[0])) + { + AdvanceChar(T); + } +} + +internal bool +AdvanceIfTokenEquals(assembly_tokenizer* T, char* Value) +{ + bool Result = true; char* TAt = T->At; - char* VAt = Validate; - while (((TAt - T->Memory) < T->MemoryLength) && *VAt) + char* VAt = Value; + while (*VAt != 0) { - if (*VAt != *TAt) + if (*TAt != *VAt) { Result = false; break; } - TAt++; - *VAt++; + TAt += 1; + VAt += 1; } + // TODO(Peter): What if the token is a subset of Value? ie. this would return true for + // T->At = hello_world and Value = hello_ + // But the next token we read would fail + if (Result) { T->At = TAt; EatWhitespace(T); } - return Result; } -internal b32 -ParseComma(tokenizer* T) +internal bool +ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T) { - b32 Result = ParseTokenEquals(T, ","); - return Result; -} - -internal b32 -ParseOpenCurlyBrace(tokenizer* T) -{ - b32 Result = ParseTokenEquals(T, "{"); - return Result; -} - -internal b32 -ParseCloseCurlyBrace(tokenizer* T) -{ - b32 Result = ParseTokenEquals(T, "}"); - return Result; -} - -internal b32 -ParseOpenParen(tokenizer* T) -{ - b32 Result = ParseTokenEquals(T, "("); - return Result; -} - -internal b32 -ParseCloseParen(tokenizer* T) -{ - b32 Result = ParseTokenEquals(T, ")"); - return Result; -} - -internal b32 -ParseUnsignedInteger(tokenizer* T, u32* Value) -{ - parse_result Result = ParseUnsignedIntUnsafe(T->At); - *Value = Result.UnsignedIntValue; - T->At = Result.OnePastLast; - - // TODO(Peter): Parse functions in gs_string don't actually check for errors or - // whether or not they actually parsed an int. - // :GSStringParseErrors - return true; -} - -internal b32 -ParseFloat(tokenizer* T, r32* Value) -{ - parse_result ParseResult = ParseFloatUnsafe(T->At); - *Value = ParseResult.FloatValue; - T->At = ParseResult.OnePastLast; - - // TODO(Peter): - // :GSStringParseErrors - return true; -} - -internal b32 -ParseVector(tokenizer* T, v3* Value) -{ - b32 Result = true; - - if (ParseOpenParen(T)) + bool Result = false; + if (AdvanceIfTokenEquals(T, AssemblyFieldIdentifiers[Field])) { - for (u32 i = 0; i < 3; i++) + if (AdvanceIfTokenEquals(T, ":")) { - b32 ValueSuccess = ParseFloat(T, &(Value->E[i])); - if (!ValueSuccess) - { - Result = false; - break; - } - - b32 CommaSuccess = ParseComma(T); - if (!CommaSuccess) - { - break; - } + Result = true; } - - if (!ParseCloseParen(T)) + else { - Result = false; + // TODO(Peter): Error } } else { - Result = false; + // TODO(Peter): Error } - return Result; } -// TODO(Peter): :ErrorLogging -#define ParseLEDStripToken(tokenizer, parse_expr, error_msg) \ -(parse_expr) && (ParseComma(tokenizer)) - -internal b32 -ParseLEDStripCount (tokenizer* T, u32* Value) +internal bool +ReadFieldEnd(assembly_tokenizer* T) { - b32 Result = false; - - if (ParseTokenEquals(T, LED_STRIP_COUNT_IDENTIFIER)) + bool Result = AdvanceIfTokenEquals(T, ";"); + if (Result) { EatWhitespace(T); - if (ParseUnsignedInteger(T, Value)) + } + else + { + // TODO(Peter): Error + } + return Result; +} + +internal string +ReadString(assembly_tokenizer* T) +{ + string Result = {}; + if (AdvanceIfTokenEquals(T, "\"")) + { + char* StringStart = T->At; + while(AtValidPosition(T) && T->At[0] != '\"') + { + T->At++; + } + Result.Memory = StringStart; + Result.Max = T->At - StringStart; + Result.Length = Result.Max; + if (AdvanceIfTokenEquals(T, "\"")) + { + // Success + } + else + { + // TODO(Peter): Error + } + } + return Result; +} + +internal string +GetNumberString(assembly_tokenizer* T) +{ + string Result = {}; + Result.Memory = T->At; + while(AtValidPosition(T) && IsNumericExtended(T->At[0])) + { + AdvanceChar(T); + } + Result.Length = T->At - Result.Memory; + Result.Max = Result.Length; + return Result; +} + +internal r32 +ReadFloat(assembly_tokenizer* T) +{ + r32 Result = 0; + string NumberString = GetNumberString(T); + parse_result ParsedFloat = ParseFloat(StringExpand(NumberString)); + Result = ParsedFloat.FloatValue; + return Result; +} + +internal s32 +ReadInt(assembly_tokenizer* T) +{ + s32 Result = 0; + string NumberString = GetNumberString(T); + parse_result ParsedInt = ParseSignedInt(StringExpand(NumberString)); + Result = ParsedInt.SignedIntValue; + return Result; +} + +internal string +ReadStringField(assembly_field Field, assembly_tokenizer* T, memory_arena* Arena) +{ + string Result = {}; + if (ReadFieldIdentifier(Field, T)) + { + string ExistingString = ReadString(T); + if (ReadFieldEnd(T)) + { + // Success + Result = PushString(Arena, ExistingString.Length); + CopyStringTo(ExistingString, &Result); + } + else + { + // TODO(Peter): Error + } + } + return Result; +} + +internal r32 +ReadFloatField(assembly_field Field, assembly_tokenizer* T) +{ + r32 Result = 0.0f; + if (ReadFieldIdentifier(Field, T)) + { + Result = ReadFloat(T); + if (!ReadFieldEnd(T)) + { + // TODO(Peter): Error + } + } + return Result; +} + +internal s32 +ReadIntField(assembly_field Field, assembly_tokenizer* T) +{ + r32 Result = 0.0f; + if (ReadFieldIdentifier(Field, T)) + { + Result = ReadInt(T); + if (!ReadFieldEnd(T)) + { + // TODO(Peter): Error + } + } + return Result; +} + +internal v3 +ReadV3Field(assembly_field Field, assembly_tokenizer* T) +{ + v3 Result = {}; + if (ReadFieldIdentifier(Field, T)) + { + if (AdvanceIfTokenEquals(T, "(")) + { + Result.x = ReadFloat(T); + if (AdvanceIfTokenEquals(T, ",")) + { + Result.y = ReadFloat(T); + if (AdvanceIfTokenEquals(T, ",")) + { + Result.z = ReadFloat(T); + + if (AdvanceIfTokenEquals(T, ")")) + { + if (!ReadFieldEnd(T)) + { + // TODO(Peter): Error + } + } + } + } + } + } + return Result; +} + +internal bool +ReadStructOpening(assembly_field Field, assembly_tokenizer* T) +{ + bool Result = false; + if (ReadFieldIdentifier(Field, T)) + { + if (AdvanceIfTokenEquals(T, "{")) { Result = true; } } - return Result; } -internal b32 -ParseLEDStrip (led_strip_definition* Strip, tokenizer* T, memory_arena* Arena) +internal bool +ReadStructClosing(assembly_tokenizer* T) { - b32 Result = false; - - if (ParseTokenEquals(T, LED_STRIP_IDENTIFIER) && - ParseOpenCurlyBrace(T)) - { - Result = true; - - u32 ControlBoxIndex, StartUniverse, StartChannel; - ParseLEDStripToken(T, ParseUnsignedInteger(T, &Strip->ControlBoxID), "Control Box Error"); - ParseLEDStripToken(T, ParseUnsignedInteger(T, &Strip->StartUniverse), "Start Universe Error"); - ParseLEDStripToken(T, ParseUnsignedInteger(T, &Strip->StartChannel), "Start Channel Error"); - - if (ParseTokenEquals(T, INTERPOLATE_POINTS_IDENTIFIER) && - ParseComma(T)) - { - Strip->InterpolationType = StripInterpolate_Points; - - ParseLEDStripToken(T, ParseVector(T, &Strip->InterpolatePositionStart), "Position Start Error"); - ParseLEDStripToken(T, ParseVector(T, &Strip->InterpolatePositionEnd), "Position End Error"); - } - - ParseLEDStripToken(T, ParseUnsignedInteger(T, &Strip->LEDsPerStrip), "LEDs Per Strip Error"); - - EatWhitespace(T); - if (!ParseCloseCurlyBrace(T)) - { - Result = false; - } - } - + bool Result = AdvanceIfTokenEquals(T, "};"); return Result; } -internal assembly_definition -ParseAssemblyFile (u8* FileBase, s32 FileSize, memory_arena* Arena, event_log* EventLog) +internal void +ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) { - assembly_definition Assembly = {}; + Assert(Assembly->Arena.Alloc != 0); + Assembly->LedCountTotal = 0; - tokenizer Tokenizer = {}; - Tokenizer.At = (char*)FileBase; - Tokenizer.Memory = (char*)FileBase; - Tokenizer.MemoryLength = FileSize; + assembly_tokenizer Tokenizer = {}; + Tokenizer.Text = FileText; + Tokenizer.At = Tokenizer.Text.Memory; - if (ParseLEDStripCount(&Tokenizer, &Assembly.LEDStripSize)) + Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena); + Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer); + + Assembly->StripCount = ReadIntField(AssemblyField_LedStripCount, &Tokenizer); + Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount); + + for (u32 i = 0; i < Assembly->StripCount; i++) { - Assembly.LEDStrips = PushArray(Arena, led_strip_definition, Assembly.LEDStripSize); - - while (AtValidPosition(Tokenizer)) + v2_strip* StripAt = Assembly->Strips + i; + if (ReadStructOpening(AssemblyField_LedStrip, &Tokenizer)) { - EatWhitespace(&Tokenizer); + StripAt->ControlBoxID = ReadIntField(AssemblyField_ControlBoxId, &Tokenizer); + StripAt->StartUniverse = ReadIntField(AssemblyField_StartUniverse, &Tokenizer); + StripAt->StartChannel = ReadIntField(AssemblyField_StartChannel, &Tokenizer); - if (Assembly.LEDStripCount < Assembly.LEDStripSize) + // TODO(Peter): Need to store this + string PointPlacementType = ReadStringField(AssemblyField_PointPlacementType, &Tokenizer, &Assembly->Arena); + // TODO(Peter): Switch on value of PointPlacementType + if (ReadStructOpening(AssemblyField_InterpolatePoints, &Tokenizer)) { - led_strip_definition* LEDStrip = Assembly.LEDStrips + Assembly.LEDStripCount++; - - if (ParseLEDStrip(LEDStrip, &Tokenizer, Arena)) + StripAt->StartPosition = ReadV3Field(AssemblyField_Start, &Tokenizer); + StripAt->EndPosition = ReadV3Field(AssemblyField_End, &Tokenizer); + if (!ReadStructClosing(&Tokenizer)) { - Assembly.TotalLEDCount += LEDStrip->LEDsPerStrip; - } - else - { - LogError(EventLog, "Unable to parse LED strip in assembly file"); - break; + // TODO(Peter): Error + InvalidCodePath; } } - else + + StripAt->LedCount = ReadIntField(AssemblyField_LedCount, &Tokenizer); + Assembly->LedCountTotal += StripAt->LedCount; + + StripAt->TagsCount = ReadIntField(AssemblyField_TagsCount, &Tokenizer); + StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount); + for (u32 Tag = 0; Tag < StripAt->TagsCount; Tag++) { - if (ParseTokenEquals(&Tokenizer, END_ASSEMBLY_FILE_IDENTIFIER)) + v2_tag* TagAt = StripAt->Tags + Tag; + if (ReadStructOpening(AssemblyField_Tag, &Tokenizer)) { - break; - } - else - { - LogError(EventLog, "Did not find ent of file identifier in assembly file"); - break; + // TODO(Peter): Need to store the string somewhere we can look it up for display in the interface + // right now they are stored in temp memory and won't persist + string TagName = ReadStringField(AssemblyField_Name, &Tokenizer, Transient); + string TagValue = ReadStringField(AssemblyField_Value, &Tokenizer, Transient); + TagAt->NameHash = HashString(TagName); + TagAt->ValueHash = HashString(TagValue); + if (!ReadStructClosing(&Tokenizer)) + { + // TODO(Peter): Error + InvalidCodePath; + } } } + + if (!ReadStructClosing(&Tokenizer)) + { + // TODO(Peter): Error + InvalidCodePath; + } } } - else - { - // TODO(Peter): :ErrorLoggong - InvalidCodePath; - } - - return Assembly; } #define ASSEMBLY_PARSER_CPP diff --git a/src/app/assembly_parser.h b/src/app/assembly_parser.h deleted file mode 100644 index eee4c9d..0000000 --- a/src/app/assembly_parser.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// File: assembly_parser.h -// Author: Peter Slattery -// Creation Date: 2020-01-01 -// -#ifndef ASSEMBLY_PARSER_H - -#define LED_STRIP_COUNT_IDENTIFIER "led_strip_count" - -#define LED_STRIP_IDENTIFIER "led_strip" - -#define INTERPOLATE_POINTS_IDENTIFIER "INTERPOLATE_POINTS" - -#define END_ASSEMBLY_FILE_IDENTIFIER "END_OF_ASSEMBLY_FILE" - -enum assembly_token_type -{ - AssemblyToken_Colon, - AssemblyToken_SemiColon, - AssemblyToken_LeftCurlyBrace, - AssemblyToken_RightCurlyBrace, - AssemblyToken_Comma, - - AssemblyToken_Number, - AssemblyToken_String, - AssemblyToken_Vector, - - AssemblyToken_LEDStrip, - - AssemblyToken_Identifier, - - AssemblyToken_EndOfFile -}; - -struct assembly_token -{ - char* Token; - s32 Length; - assembly_token_type Type; -}; - -enum strip_interpolation_type -{ - StripInterpolate_Boxes, - StripInterpolate_Points, -}; - -struct led_strip_definition -{ - u32 ControlBoxID; - u32 StartUniverse; - u32 StartChannel; - - strip_interpolation_type InterpolationType; - // Interpolate Boxes - u32 StartBoxIndex; - u32 EndBoxIndex; - - // Interpolate Positions - v3 InterpolatePositionStart; - v3 InterpolatePositionEnd; - - // Universal Interpolation - u32 LEDsPerStrip; -}; - -struct assembly_definition -{ - u32 LEDStripSize; - u32 LEDStripCount; - u32 TotalLEDCount; - led_strip_definition* LEDStrips; -}; - -#define ASSEMBLY_PARSER_H -#endif // ASSEMBLY_PARSER_H \ No newline at end of file diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 43b913e..5684f52 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -176,7 +176,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Camera.LookAt = v3{0, 0, 0}; #if 1 - string SculpturePath = MakeStringLiteral("data/blumen_lumen.fold"); + string SculpturePath = MakeStringLiteral("data/blumen_lumen_v2.fold"); LoadAssembly(State, Context, SculpturePath); #endif @@ -208,7 +208,9 @@ INITIALIZE_APPLICATION(InitializeApplication) InitializePanelSystem(&State->PanelSystem); panel* Panel = TakeNewPanel(&State->PanelSystem); - SetPanelDefinition(Panel, PanelType_SculptureView, State); + SplitPanelVertically(Panel, .5f, &State->PanelSystem); + SetPanelDefinition(&Panel->Left->Panel, PanelType_ProfilerView, State); + SetPanelDefinition(&Panel->Right->Panel, PanelType_SculptureView, State); } internal void @@ -462,6 +464,9 @@ UPDATE_AND_RENDER(UpdateAndRender) s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; + // TODO(Peter): Come back and re add this in. It was tanking frame rate after + // updates to the assembly file format +#if 0 for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); @@ -469,6 +474,7 @@ UPDATE_AND_RENDER(UpdateAndRender) dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, HeaderSize, &State->Transient); DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); } +#endif //DEBUG_IF(GlobalDebugServices->Interface.SendSACNData) { diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 47f995f..7a29134 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -18,17 +18,13 @@ #include "sacn/sacn.h" #include "foldhaus_assembly.h" +#include "assembly_parser.cpp" -#include "assembly_parser.h" #include "foldhaus_node.h" -// TODO(Peter): TEMPORARY -//u32 NodeSpecificationsCount = 0; -//node_specification* NodeSpecifications = 0; +typedef struct app_state app_state; - -#include "assembly_parser.cpp" #include "test_patterns.h" // TODO(Peter): something we can do later is to remove all reliance on app_state and context @@ -36,8 +32,6 @@ // perform operations on, like panel_draw_requests = { bounds, panel* } etc. #include "foldhaus_panel.h" -typedef struct app_state app_state; - #include "foldhaus_command_dispatch.h" #include "foldhaus_operation_mode.h" @@ -55,11 +49,18 @@ enum network_protocol NetworkProtocol_Count, }; +struct led_buffer +{ + led* Leds; + pixel* Colors; + led_buffer* Next; +}; + struct app_state { rect WindowBounds; - memory_arena Permanent; + memory_arena Permanent; memory_arena Transient; s32 NetworkProtocolHeaderSize; diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index 7b870db..dd9223e 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -5,60 +5,40 @@ // #ifndef FOLDHAUS_ASSEMBLY_CPP -internal assembly -ConstructAssemblyFromDefinition (assembly_definition Definition, - string AssemblyName, - v4 RootPosition, - r32 Scale, - memory_arena Arena) +internal void +ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition) { - assembly Assembly = {}; - Assembly.Arena = Arena; - - Assembly.Name = MakeString(PushArray(&Assembly.Arena, char, AssemblyName.Length), AssemblyName.Length); - CopyStringTo(AssemblyName, &Assembly.Name); - - // NOTE(Peter): Setting this to zero so we can check at the end of the loop that creates leds - // and make sure we created to correct number. By the time this function returns it should be - // the case that: (Assembly.LEDCount == Definition.TotalLEDCount) - Assembly.LEDBuffer.LEDCount = 0; - Assembly.LEDBuffer.Colors = PushArray(&Assembly.Arena, pixel, Definition.TotalLEDCount); - Assembly.LEDBuffer.LEDs = PushArray(&Assembly.Arena, led, Definition.TotalLEDCount); - Assembly.LEDUniverseMapCount = Definition.LEDStripCount; - Assembly.LEDUniverseMap = PushArray(&Assembly.Arena, leds_in_universe_range, Definition.LEDStripCount); + Assembly->LEDBuffer.LEDCount = 0; + Assembly->LEDBuffer.Colors = PushArray(&Assembly->Arena, pixel, Assembly->LedCountTotal); + Assembly->LEDBuffer.LEDs = PushArray(&Assembly->Arena, led, Assembly->LedCountTotal); + Assembly->LEDUniverseMapCount = Assembly->LedCountTotal; + Assembly->LEDUniverseMap = PushArray(&Assembly->Arena, leds_in_universe_range, Assembly->LedCountTotal); // Add LEDs - for (u32 StripIdx = 0; StripIdx < Definition.LEDStripCount; StripIdx++) + for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++) { - led_strip_definition StripDef = Definition.LEDStrips[StripIdx]; + //led_strip_definition StripDef = Definition.LEDStrips[StripIdx]; + v2_strip* StripAt = &Assembly->Strips[StripIdx]; - leds_in_universe_range* LEDUniverseRange = Assembly.LEDUniverseMap + StripIdx; - LEDUniverseRange->Universe = StripDef.StartUniverse; - LEDUniverseRange->RangeStart = Assembly.LEDBuffer.LEDCount; - LEDUniverseRange->RangeOnePastLast = Assembly.LEDBuffer.LEDCount + StripDef.LEDsPerStrip; + leds_in_universe_range* LEDUniverseRange = &Assembly->LEDUniverseMap[StripIdx]; - // NOTE(Peter): this should be a switch on the type, but we only have one for - // now. The assert is to remind you to create more cases when necessary - Assert(StripDef.InterpolationType == StripInterpolate_Points); + LEDUniverseRange->Universe = StripAt->StartUniverse; + LEDUniverseRange->RangeStart = Assembly->LEDBuffer.LEDCount; + LEDUniverseRange->RangeOnePastLast = Assembly->LEDBuffer.LEDCount + StripAt->LedCount; - v4 WS_StripStart = RootPosition + V4(StripDef.InterpolatePositionStart * Scale, 1); - v4 WS_StripEnd = RootPosition + V4(StripDef.InterpolatePositionEnd * Scale, 1); - s32 LEDsInStripCount = StripDef.LEDsPerStrip; - - Assert(Assembly.LEDBuffer.LEDCount + LEDsInStripCount <= Definition.TotalLEDCount); + v4 WS_StripStart = RootPosition + V4(StripAt->StartPosition * Assembly->Scale, 1); + v4 WS_StripEnd = RootPosition + V4(StripAt->EndPosition * Assembly->Scale, 1); + s32 LEDsInStripCount = StripAt->LedCount; v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)LEDsInStripCount; for (s32 Step = 0; Step < LEDsInStripCount; Step++) { - s32 LEDIndex = Assembly.LEDBuffer.LEDCount++; - Assembly.LEDBuffer.LEDs[LEDIndex].Position = WS_StripStart + (SingleStep * Step); - Assembly.LEDBuffer.LEDs[LEDIndex].Index = LEDIndex; + s32 LEDIndex = Assembly->LEDBuffer.LEDCount; + Assembly->LEDBuffer.LEDs[LEDIndex].Position = WS_StripStart + (SingleStep * Step); + Assembly->LEDBuffer.LEDs[LEDIndex].Index = LEDIndex; + Assembly->LEDBuffer.LEDCount += 1; } } - - // NOTE(Peter): Did we create the correct number of LEDs? - Assert(Assembly.LEDBuffer.LEDCount == Definition.TotalLEDCount); - return Assembly; } // NOTE(Peter): These are here so that if we load 2+ sculptures, they don't all @@ -73,18 +53,18 @@ LoadAssembly (app_state* State, context Context, string Path) platform_memory_result AssemblyFile = ReadEntireFile(Context, Path); if (AssemblyFile.Error == PlatformMemory_NoError) { - assembly_definition AssemblyDefinition = ParseAssemblyFile(AssemblyFile.Base, AssemblyFile.Size, &State->Transient, State->GlobalLog); + string AssemblyFileText = MakeString((char*)AssemblyFile.Base); s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\'); string FileName = Substring(Path, IndexOfLastSlash + 1); - memory_arena AssemblyArena = {}; - AssemblyArena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; - AssemblyArena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + assembly NewAssembly = {}; + NewAssembly.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; + NewAssembly.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + ParseAssemblyFile(&NewAssembly, AssemblyFileText, &State->Transient); v4 Offset = TempAssemblyOffsets[State->ActiveAssemblyIndecies.Used % TempAssemblyOffsetsCount]; - r32 Scale = 100; - assembly NewAssembly = ConstructAssemblyFromDefinition(AssemblyDefinition, FileName, Offset, Scale, AssemblyArena); + ConstructAssemblyFromDefinition(&NewAssembly, FileName, Offset); gs_list_handle NewAssemblyHandle = State->AssemblyList.PushElementOnList(NewAssembly); State->ActiveAssemblyIndecies.PushElementOnList(NewAssemblyHandle); diff --git a/src/app/foldhaus_assembly.h b/src/app/foldhaus_assembly.h index 5852583..e414e7a 100644 --- a/src/app/foldhaus_assembly.h +++ b/src/app/foldhaus_assembly.h @@ -22,7 +22,7 @@ union pixel u8 Channels[3]; }; -// NOTE(Peter): This structure is so we can keep track of +// NOTE(Peter): This structure is so we can keep track of // what LEDs output to which DMX universe. You don't need // to use it anywhere else, as all the data for patterns, // colors, and groups is/will be stored elsewhere. @@ -40,6 +40,30 @@ struct assembly_led_buffer led* LEDs; }; +struct v2_tag +{ + u64 NameHash; + u64 ValueHash; +}; + +struct v2_strip +{ + s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore + s32 StartUniverse; + s32 StartChannel; + + // TODO(Peter): When we create more ways to calculate points, this needs to become + // a type enum and a union + v3 StartPosition; + v3 EndPosition; + + u32 LedCount; + u32* LedLUT; + + u32 TagsCount; + v2_tag* Tags; +}; + struct assembly { memory_arena Arena; @@ -47,13 +71,13 @@ struct assembly string Name; string FilePath; - assembly_led_buffer LEDBuffer; + r32 Scale; -#if 0 - u32 LEDCount; - pixel* Colors; - led* LEDs; -#endif + u32 StripCount; + v2_strip* Strips; + + s32 LedCountTotal; + assembly_led_buffer LEDBuffer; u32 LEDUniverseMapCount; leds_in_universe_range* LEDUniverseMap; diff --git a/src/app/foldhaus_interface.cpp b/src/app/foldhaus_interface.cpp index 86684f5..823b652 100644 --- a/src/app/foldhaus_interface.cpp +++ b/src/app/foldhaus_interface.cpp @@ -242,12 +242,12 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation) if (XDistance > YDistance) { r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / gs_Width(PanelBounds); - SplitPanelVertically(Panel, XPercent, PanelBounds, &State->PanelSystem); + SplitPanelVertically(Panel, XPercent, &State->PanelSystem); } else { r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / gs_Height(PanelBounds); - SplitPanelHorizontally(Panel, YPercent, PanelBounds, &State->PanelSystem); + SplitPanelHorizontally(Panel, YPercent, &State->PanelSystem); } Panel->Left->Panel.PanelDefinitionIndex = Panel->PanelDefinitionIndex; diff --git a/src/app/foldhaus_panel.h b/src/app/foldhaus_panel.h index 27f290a..2929c8b 100644 --- a/src/app/foldhaus_panel.h +++ b/src/app/foldhaus_panel.h @@ -4,7 +4,7 @@ // Creation Date: 2019-12-26 // // Usage: -// Include this file in ONE file in your project. +// Include this file in ONE file in your project. // Define SetPanelDefinitionExternal // #ifndef FOLDHAUS_PANEL_H @@ -67,8 +67,8 @@ struct panel_system }; // NOTE(Peter): This representation is used to let external code render and interact -// with panels. It shouldn't be stored across frame boundaries as the pointers to -// Panel's are liable to change. +// with panels. It shouldn't be stored across frame boundaries as the pointers to +// Panel's are liable to change. struct panel_with_layout { panel* Panel; @@ -154,10 +154,9 @@ FreePanelAtIndex(s32 Index, panel_system* PanelSystem) } internal void -SplitPanelVertically(panel* Parent, r32 Percent, rect ParentBounds, panel_system* PanelSystem) +SplitPanelVertically(panel* Parent, r32 Percent, panel_system* PanelSystem) { - r32 SplitX = GSLerp(ParentBounds.Min.x, ParentBounds.Max.x, Percent); - if (SplitX > ParentBounds.Min.x && SplitX < ParentBounds.Max.x) + if (Percent >= 0.0f && Percent <= 1.0f) { Parent->SplitDirection = PanelSplit_Vertical; Parent->SplitPercent = Percent; @@ -171,10 +170,9 @@ SplitPanelVertically(panel* Parent, r32 Percent, rect ParentBounds, panel_system } internal void -SplitPanelHorizontally(panel* Parent, r32 Percent, rect ParentBounds, panel_system* PanelSystem) +SplitPanelHorizontally(panel* Parent, r32 Percent, panel_system* PanelSystem) { - r32 SplitY = GSLerp(ParentBounds.Min.y, ParentBounds.Max.y, Percent); - if (SplitY > ParentBounds.Min.y && SplitY < ParentBounds.Max.y) + if (Percent >= 0.0f && Percent <= 1.0f) { Parent->SplitDirection = PanelSplit_Horizontal; Parent->SplitPercent = Percent; From 69db4b436c0f716a937d4343f45b538930f86638 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 15 Jun 2020 15:36:50 -0700 Subject: [PATCH 04/43] Pulled the leds out of assemblies and into their own subsystem. --- src/app/animation/foldhaus_animation.h | 10 +- src/app/assembly_parser.cpp | 56 +++-- src/app/foldhaus_app.cpp | 99 ++++---- src/app/foldhaus_app.h | 62 +++-- src/app/foldhaus_assembly.cpp | 163 +++++++++---- src/app/foldhaus_assembly.h | 40 ++-- src/app/foldhaus_platform.h | 14 +- src/app/panels/foldhaus_panel_hierarchy.h | 14 +- .../panels/foldhaus_panel_sculpture_view.h | 22 +- src/app/win32_foldhaus.cpp | 6 +- src/app/win32_foldhaus_fileio.h | 2 + src/gs_libs/gs_memory_arena.h | 215 +++++++++--------- 12 files changed, 390 insertions(+), 313 deletions(-) diff --git a/src/app/animation/foldhaus_animation.h b/src/app/animation/foldhaus_animation.h index c5b0434..a63e3d1 100644 --- a/src/app/animation/foldhaus_animation.h +++ b/src/app/animation/foldhaus_animation.h @@ -5,7 +5,7 @@ // #ifndef FOLDHAUS_ANIMATION -#define ANIMATION_PROC(name) void name(assembly_led_buffer* Assembly, r32 Time) +#define ANIMATION_PROC(name) void name(led_buffer* Assembly, r32 Time) typedef ANIMATION_PROC(animation_proc); struct frame_range @@ -39,7 +39,7 @@ struct anim_layer #define ANIMATION_SYSTEM_BLOCKS_MAX 128 struct animation_system { - memory_arena Storage; + memory_arena* Storage; gs_list Blocks; anim_layer* Layers; @@ -94,7 +94,7 @@ PercentToFrameInRange(r32 Percent, frame_range Range) return Result; } -internal s32 +internal s32 ClampFrameToRange(s32 Frame, frame_range Range) { s32 Result = Frame; @@ -135,7 +135,7 @@ RemoveAnimationBlock(gs_list_handle AnimationBlockHandle, animation_system* Anim internal u32 AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite) { - // TODO(Peter): If this assert fires its time to make the layer buffer system + // TODO(Peter): If this assert fires its time to make the layer buffer system // resizable. Assert(AnimationSystem->LayersCount < AnimationSystem->LayersMax); @@ -143,7 +143,7 @@ AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = Result = AnimationSystem->LayersCount++; anim_layer* NewLayer = AnimationSystem->Layers + Result; *NewLayer = {0}; - NewLayer->Name = MakeString(PushArray(&AnimationSystem->Storage, char, Name.Length), Name.Length); + NewLayer->Name = MakeString(PushArray(AnimationSystem->Storage, char, Name.Length), Name.Length); CopyStringTo(Name, &NewLayer->Name); NewLayer->BlendMode = BlendMode; return Result; diff --git a/src/app/assembly_parser.cpp b/src/app/assembly_parser.cpp index 5b6605a..4b06fc7 100644 --- a/src/app/assembly_parser.cpp +++ b/src/app/assembly_parser.cpp @@ -58,6 +58,8 @@ struct assembly_tokenizer char* At; u32 LineNumber; + + bool ParsingIsValid; }; internal bool @@ -128,12 +130,12 @@ ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T) } else { - // TODO(Peter): Error + T->ParsingIsValid = false; } } else { - // TODO(Peter): Error + T->ParsingIsValid = false; } return Result; } @@ -148,7 +150,7 @@ ReadFieldEnd(assembly_tokenizer* T) } else { - // TODO(Peter): Error + T->ParsingIsValid = false; } return Result; } @@ -228,7 +230,7 @@ ReadStringField(assembly_field Field, assembly_tokenizer* T, memory_arena* Arena } else { - // TODO(Peter): Error + T->ParsingIsValid = false; } } return Result; @@ -243,7 +245,7 @@ ReadFloatField(assembly_field Field, assembly_tokenizer* T) Result = ReadFloat(T); if (!ReadFieldEnd(T)) { - // TODO(Peter): Error + T->ParsingIsValid = false; } } return Result; @@ -258,7 +260,7 @@ ReadIntField(assembly_field Field, assembly_tokenizer* T) Result = ReadInt(T); if (!ReadFieldEnd(T)) { - // TODO(Peter): Error + T->ParsingIsValid = false; } } return Result; @@ -279,16 +281,31 @@ ReadV3Field(assembly_field Field, assembly_tokenizer* T) if (AdvanceIfTokenEquals(T, ",")) { Result.z = ReadFloat(T); - if (AdvanceIfTokenEquals(T, ")")) { if (!ReadFieldEnd(T)) { - // TODO(Peter): Error + T->ParsingIsValid = false; } } + else + { + T->ParsingIsValid = false; + } + } + else + { + T->ParsingIsValid = false; } } + else + { + T->ParsingIsValid = false; + } + } + else + { + T->ParsingIsValid = false; } } return Result; @@ -315,15 +332,15 @@ ReadStructClosing(assembly_tokenizer* T) return Result; } -internal void +internal bool ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) { - Assert(Assembly->Arena.Alloc != 0); Assembly->LedCountTotal = 0; assembly_tokenizer Tokenizer = {}; Tokenizer.Text = FileText; Tokenizer.At = Tokenizer.Text.Memory; + Tokenizer.ParsingIsValid = true; Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena); Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer); @@ -349,8 +366,7 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) StripAt->EndPosition = ReadV3Field(AssemblyField_End, &Tokenizer); if (!ReadStructClosing(&Tokenizer)) { - // TODO(Peter): Error - InvalidCodePath; + Tokenizer.ParsingIsValid = false; } } @@ -372,19 +388,27 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) TagAt->ValueHash = HashString(TagValue); if (!ReadStructClosing(&Tokenizer)) { - // TODO(Peter): Error - InvalidCodePath; + Tokenizer.ParsingIsValid = false; } } + else + { + Tokenizer.ParsingIsValid = false; + } } if (!ReadStructClosing(&Tokenizer)) { - // TODO(Peter): Error - InvalidCodePath; + Tokenizer.ParsingIsValid = false; } } + else + { + Tokenizer.ParsingIsValid = false; + } } + + return Tokenizer.ParsingIsValid; } #define ASSEMBLY_PARSER_CPP diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 5684f52..afb801e 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -70,13 +70,16 @@ RELOAD_STATIC_DATA(ReloadStaticData) INITIALIZE_APPLICATION(InitializeApplication) { app_state* State = (app_state*)Context.MemoryBase; + *State = {}; + State->Permanent = {}; - State->Permanent.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; - State->Permanent.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + State->Permanent.PlatformMemory = Context.PlatformMemory; State->Transient = {}; State->Transient.FindAddressRule = FindAddress_InLastBufferOnly; - State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; - State->Transient.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + State->Transient.PlatformMemory = Context.PlatformMemory; + + State->Assemblies.CountMax = 8; + State->Assemblies.Values = PushArray(&State->Permanent, assembly, State->Assemblies.CountMax); State->GlobalLog = PushStruct(&State->Transient, event_log); *State->GlobalLog = {0}; @@ -175,6 +178,8 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Camera.Position = v3{0, 0, -250}; State->Camera.LookAt = v3{0, 0, 0}; + State->LedSystem = LedSystemInitialize(Context.PlatformMemory, 128); + #if 1 string SculpturePath = MakeStringLiteral("data/blumen_lumen_v2.fold"); LoadAssembly(State, Context, SculpturePath); @@ -189,12 +194,12 @@ INITIALIZE_APPLICATION(InitializeApplication) // Setup Operation Modes State->Modes.ActiveModesCount = 0; State->Modes.Arena = {}; - State->Modes.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; - State->Modes.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + State->Modes.Arena.PlatformMemory = Context.PlatformMemory; State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly; { // Animation PLAYGROUND State->AnimationSystem = {}; + State->AnimationSystem.Storage = &State->Permanent; State->AnimationSystem.SecondsPerFrame = 1.f / 24.f; State->AnimationSystem.PlayableRange.Min = 0; State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem); @@ -273,21 +278,24 @@ HandleInput (app_state* State, rect WindowBounds, input_queue InputQueue, mouse_ } internal dmx_buffer_list* -CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena) +CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, memory_arena* Arena) { DEBUG_TRACK_FUNCTION; + led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); + dmx_buffer_list* Result = 0; dmx_buffer_list* Head = 0; s32 BufferSize = BufferHeaderSize + 512; - for (u32 Range = 0; Range < Assembly.LEDUniverseMapCount; Range++) + for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++) { - leds_in_universe_range LEDUniverseRange = Assembly.LEDUniverseMap[Range]; + v2_strip Strip = Assembly.Strips[StripIndex]; dmx_buffer_list* NewBuffer = PushStruct(Arena, dmx_buffer_list); - NewBuffer->Buffer.Universe = LEDUniverseRange.Universe; + NewBuffer->Buffer.Universe = Strip.StartUniverse; + NewBuffer->Buffer.Base = PushArray(Arena, u8, BufferSize); NewBuffer->Buffer.TotalSize = BufferSize; NewBuffer->Buffer.HeaderSize = BufferHeaderSize; @@ -302,13 +310,12 @@ CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena) Head = NewBuffer; u8* DestChannel = Head->Buffer.Base + BufferHeaderSize; - for (s32 LEDIdx = LEDUniverseRange.RangeStart; - LEDIdx < LEDUniverseRange.RangeOnePastLast; - LEDIdx++) + + for (u32 i = 0; i < Strip.LedCount; i++) { - led LED = Assembly.LEDBuffer.LEDs[LEDIdx]; - pixel Color = Assembly.LEDBuffer.Colors[LED.Index]; - + u32 LedIndex = Strip.LedLUT[i]; + led LED = LedBuffer->Leds[LedIndex]; + pixel Color = LedBuffer->Colors[LED.Index]; DestChannel[0] = Color.R; DestChannel[1] = Color.G; @@ -366,11 +373,11 @@ UPDATE_AND_RENDER(UpdateAndRender) CurrentBlocks[Block.Layer] = Block; } - assembly_led_buffer* LayerLEDBuffers = PushArray(&State->Transient, assembly_led_buffer, CurrentBlocksMax); - for (u32 AssemblyIndex = 0; AssemblyIndex < State->ActiveAssemblyIndecies.Used; AssemblyIndex++) + led_buffer* LayerLEDBuffers = PushArray(&State->Transient, led_buffer, CurrentBlocksMax); + for (u32 AssemblyIndex = 0; AssemblyIndex < State->Assemblies.Count; AssemblyIndex++) { - gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(AssemblyIndex); - assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle); + assembly* Assembly = &State->Assemblies.Values[AssemblyIndex]; + led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly->LedBufferIndex); arena_snapshot ResetAssemblyMemorySnapshot = TakeSnapshotOfArena(&State->Transient); @@ -380,8 +387,8 @@ UPDATE_AND_RENDER(UpdateAndRender) animation_block Block = CurrentBlocks[Layer]; // Prep Temp Buffer - LayerLEDBuffers[Layer] = Assembly->LEDBuffer; - LayerLEDBuffers[Layer].Colors = PushArray(&State->Transient, pixel, Assembly->LEDBuffer.LEDCount); + LayerLEDBuffers[Layer] = *AssemblyLedBuffer; + LayerLEDBuffers[Layer].Colors = PushArray(&State->Transient, pixel, AssemblyLedBuffer->LedCount); u32 FramesIntoBlock = CurrentFrame - Block.Range.Min; r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame; @@ -418,41 +425,41 @@ UPDATE_AND_RENDER(UpdateAndRender) { case BlendMode_Overwrite: { - for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++) + for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++) { - Assembly->LEDBuffer.Colors[LED] = LayerLEDBuffers[Layer].Colors[LED]; + AssemblyLedBuffer->Colors[LED] = LayerLEDBuffers[Layer].Colors[LED]; } }break; case BlendMode_Add: { - for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++) + for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++) { - u32 R = (u32)Assembly->LEDBuffer.Colors[LED].R + (u32)LayerLEDBuffers[Layer].Colors[LED].R; - u32 G = (u32)Assembly->LEDBuffer.Colors[LED].G + (u32)LayerLEDBuffers[Layer].Colors[LED].G; - u32 B = (u32)Assembly->LEDBuffer.Colors[LED].B + (u32)LayerLEDBuffers[Layer].Colors[LED].B; + u32 R = (u32)AssemblyLedBuffer->Colors[LED].R + (u32)LayerLEDBuffers[Layer].Colors[LED].R; + u32 G = (u32)AssemblyLedBuffer->Colors[LED].G + (u32)LayerLEDBuffers[Layer].Colors[LED].G; + u32 B = (u32)AssemblyLedBuffer->Colors[LED].B + (u32)LayerLEDBuffers[Layer].Colors[LED].B; - Assembly->LEDBuffer.Colors[LED].R = (u8)GSMin(R, (u32)255); - Assembly->LEDBuffer.Colors[LED].G = (u8)GSMin(G, (u32)255); - Assembly->LEDBuffer.Colors[LED].B = (u8)GSMin(B, (u32)255); + AssemblyLedBuffer->Colors[LED].R = (u8)GSMin(R, (u32)255); + AssemblyLedBuffer->Colors[LED].G = (u8)GSMin(G, (u32)255); + AssemblyLedBuffer->Colors[LED].B = (u8)GSMin(B, (u32)255); } }break; case BlendMode_Multiply: { - for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++) + for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++) { - r32 DR = (r32)Assembly->LEDBuffer.Colors[LED].R / 255.f; - r32 DG = (r32)Assembly->LEDBuffer.Colors[LED].G / 255.f; - r32 DB = (r32)Assembly->LEDBuffer.Colors[LED].B / 255.f; + r32 DR = (r32)AssemblyLedBuffer->Colors[LED].R / 255.f; + r32 DG = (r32)AssemblyLedBuffer->Colors[LED].G / 255.f; + r32 DB = (r32)AssemblyLedBuffer->Colors[LED].B / 255.f; r32 SR = (r32)LayerLEDBuffers[Layer].Colors[LED].R / 255.f; r32 SG = (r32)LayerLEDBuffers[Layer].Colors[LED].G / 255.f; r32 SB = (r32)LayerLEDBuffers[Layer].Colors[LED].B / 255.f; - Assembly->LEDBuffer.Colors[LED].R = (u8)((DR * SR) * 255.f); - Assembly->LEDBuffer.Colors[LED].G = (u8)((DG * SG) * 255.f); - Assembly->LEDBuffer.Colors[LED].B = (u8)((DB * SB) * 255.f); + AssemblyLedBuffer->Colors[LED].R = (u8)((DR * SR) * 255.f); + AssemblyLedBuffer->Colors[LED].G = (u8)((DG * SG) * 255.f); + AssemblyLedBuffer->Colors[LED].B = (u8)((DB * SB) * 255.f); } }break; } @@ -464,17 +471,12 @@ UPDATE_AND_RENDER(UpdateAndRender) s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; - // TODO(Peter): Come back and re add this in. It was tanking frame rate after - // updates to the assembly file format -#if 0 - for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) + for (u32 i = 0; i < State->Assemblies.Count; i++) { - gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); - assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle); - dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, HeaderSize, &State->Transient); + assembly* Assembly = &State->Assemblies.Values[i]; + dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, &State->LedSystem, HeaderSize, &State->Transient); DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); } -#endif //DEBUG_IF(GlobalDebugServices->Interface.SendSACNData) { @@ -530,10 +532,9 @@ UPDATE_AND_RENDER(UpdateAndRender) { DEBUG_TRACK_SCOPE(OverflowChecks); AssertAllocationsNoOverflow(State->Permanent); - for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) + for (u32 i = 0; i < State->Assemblies.Count; i++) { - gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); - assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle); + assembly* Assembly = &State->Assemblies.Values[i]; AssertAllocationsNoOverflow(Assembly->Arena); } } diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 7a29134..0e08eb1 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -49,13 +49,6 @@ enum network_protocol NetworkProtocol_Count, }; -struct led_buffer -{ - led* Leds; - pixel* Colors; - led_buffer* Next; -}; - struct app_state { rect WindowBounds; @@ -68,9 +61,8 @@ struct app_state streaming_acn SACN; - s32 TotalLEDsCount; - gs_list AssemblyList; - gs_list ActiveAssemblyIndecies; + led_system LedSystem; + assembly_array Assemblies; camera Camera; r32 PixelsToWorldScale; @@ -98,28 +90,28 @@ internal void OpenColorPicker(app_state* State, v4* Address); // BEGIN TEMPORARY PATTERNS internal void -TestPatternOne(assembly_led_buffer* Assembly, r32 Time) +TestPatternOne(led_buffer* Assembly, r32 Time) { - for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++) + for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) { - led LED = Assembly->LEDs[LEDIdx]; - if (LED.Position.x < 0) + led Led = Assembly->Leds[LedIndex]; + if (Led.Position.x < 0) { - Assembly->Colors[LED.Index].R = 255; - Assembly->Colors[LED.Index].B = 255; - Assembly->Colors[LED.Index].G = 255; + Assembly->Colors[Led.Index].R = 255; + Assembly->Colors[Led.Index].B = 255; + Assembly->Colors[Led.Index].G = 255; } else { - Assembly->Colors[LED.Index].R = 0; - Assembly->Colors[LED.Index].B = 0; - Assembly->Colors[LED.Index].G = 0; + Assembly->Colors[Led.Index].R = 0; + Assembly->Colors[Led.Index].B = 0; + Assembly->Colors[Led.Index].G = 0; } } } internal void -TestPatternTwo(assembly_led_buffer* Assembly, r32 Time) +TestPatternTwo(led_buffer* Assembly, r32 Time) { r32 PeriodicTime = (Time / PI) * 2; @@ -138,11 +130,11 @@ TestPatternTwo(assembly_led_buffer* Assembly, r32 Time) r32 OuterRadiusSquared = 1000000; r32 InnerRadiusSquared = 0; - for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++) + for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) { - led LED = Assembly->LEDs[LEDIdx]; + led Led = Assembly->Leds[LedIndex]; - v4 Position = LED.Position; + v4 Position = Led.Position; v4 ToFront = Position + FrontCenter; v4 ToBack = Position + BackCenter; @@ -158,22 +150,22 @@ TestPatternTwo(assembly_led_buffer* Assembly, r32 Time) { if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) { - Assembly->Colors[LED.Index] = Color; + Assembly->Colors[Led.Index] = Color; } else { - //Assembly->Colors[LED.Index] = {}; + //Assembly->Colors[Led.Index] = {}; } } else { - //Assembly->Colors[LED.Index] = {}; + //Assembly->Colors[Led.Index] = {}; } } } internal void -TestPatternThree(assembly_led_buffer* Assembly, r32 Time) +TestPatternThree(led_buffer* Assembly, r32 Time) { v4 GreenCenter = v4{0, 0, 150, 1}; r32 GreenRadius = GSAbs(GSSin(Time)) * 200; @@ -184,25 +176,25 @@ TestPatternThree(assembly_led_buffer* Assembly, r32 Time) r32 FadeDist = 35; - for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++) + for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) { - led LED = Assembly->LEDs[LEDIdx]; + led Led = Assembly->Leds[LedIndex]; u8 Red = 0; u8 Green = 0; u8 Blue = 0; - r32 GreenDist = GSAbs(Mag(LED.Position - GreenCenter) - GreenRadius); + r32 GreenDist = GSAbs(Mag(Led.Position - GreenCenter) - GreenRadius); r32 GreenBrightness = GSClamp(0.f, FadeDist - GSAbs(GreenDist), FadeDist); Green = (u8)(GreenBrightness * 255); - r32 TealDist = GSAbs(Mag(LED.Position - TealCenter) - TealRadius); + r32 TealDist = GSAbs(Mag(Led.Position - TealCenter) - TealRadius); r32 TealBrightness = GSClamp(0.f, FadeDist - GSAbs(TealDist), FadeDist); Red = (u8)(TealBrightness * 255); Blue = (u8)(TealBrightness * 255); - Assembly->Colors[LED.Index].R = Red; - Assembly->Colors[LED.Index].B = Green; - Assembly->Colors[LED.Index].G = Green; + Assembly->Colors[Led.Index].R = Red; + Assembly->Colors[Led.Index].B = Green; + Assembly->Colors[Led.Index].G = Green; } } diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index dd9223e..da5841e 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -5,38 +5,106 @@ // #ifndef FOLDHAUS_ASSEMBLY_CPP -internal void -ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition) +// Led System + +internal led_system +LedSystemInitialize(platform_memory_handler PlatformMemory, u32 BuffersMax) { - Assembly->LEDBuffer.LEDCount = 0; - Assembly->LEDBuffer.Colors = PushArray(&Assembly->Arena, pixel, Assembly->LedCountTotal); - Assembly->LEDBuffer.LEDs = PushArray(&Assembly->Arena, led, Assembly->LedCountTotal); - Assembly->LEDUniverseMapCount = Assembly->LedCountTotal; - Assembly->LEDUniverseMap = PushArray(&Assembly->Arena, leds_in_universe_range, Assembly->LedCountTotal); + 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 = PlatformAllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax); + return Result; +} + +internal u32 +LedSystemTakeFreeBuffer(led_system* System, u32 LedCount) +{ + s32 Result = -1; - // Add LEDs + 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++) + { + if (System->Buffers[i].LedCount == 0 + && System->Buffers[i].Colors == 0 + && System->Buffers[i].Leds == 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 = PlatformAllocArray(System->PlatformMemory, pixel, Buffer->LedCount); + Buffer->Leds = PlatformAllocArray(System->PlatformMemory, led, 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]; + PlatformFreeArray(System->PlatformMemory, Buffer->Colors, pixel, Buffer->LedCount); + PlatformFreeArray(System->PlatformMemory, Buffer->Leds, led, Buffer->LedCount); + System->LedsCountTotal -= Buffer->LedCount; + *Buffer = {}; +} + +internal led_buffer* +LedSystemGetBuffer(led_system* System, u32 Index) +{ + led_buffer* Result = &System->Buffers[Index]; + return Result; +} + +internal void +LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) +{ + Assert(Led < Buffer->LedCount); + Buffer->Leds[Led].Position = Position; + Buffer->Leds[Led].Index = Led; +} + +// Assembly + +internal void +ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition, led_system* LedSystem) +{ + Assembly->LedBufferIndex = LedSystemTakeFreeBuffer(LedSystem, Assembly->LedCountTotal); + led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex); + + // Add Leds + u32 LedsAdded = 0; for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++) { - //led_strip_definition StripDef = Definition.LEDStrips[StripIdx]; + //led_strip_definition StripDef = Definition.LedStrips[StripIdx]; v2_strip* StripAt = &Assembly->Strips[StripIdx]; - - leds_in_universe_range* LEDUniverseRange = &Assembly->LEDUniverseMap[StripIdx]; - - LEDUniverseRange->Universe = StripAt->StartUniverse; - LEDUniverseRange->RangeStart = Assembly->LEDBuffer.LEDCount; - LEDUniverseRange->RangeOnePastLast = Assembly->LEDBuffer.LEDCount + StripAt->LedCount; + StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount); v4 WS_StripStart = RootPosition + V4(StripAt->StartPosition * Assembly->Scale, 1); v4 WS_StripEnd = RootPosition + V4(StripAt->EndPosition * Assembly->Scale, 1); - s32 LEDsInStripCount = StripAt->LedCount; - v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)LEDsInStripCount; - for (s32 Step = 0; Step < LEDsInStripCount; Step++) + v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)StripAt->LedCount; + for (u32 Step = 0; Step < StripAt->LedCount; Step++) { - s32 LEDIndex = Assembly->LEDBuffer.LEDCount; - Assembly->LEDBuffer.LEDs[LEDIndex].Position = WS_StripStart + (SingleStep * Step); - Assembly->LEDBuffer.LEDs[LEDIndex].Index = LEDIndex; - Assembly->LEDBuffer.LEDCount += 1; + s32 LedIndex = LedsAdded++; + v4 LedPosition = WS_StripStart + (SingleStep * Step); + LedBufferSetLed(LedBuffer, LedIndex, LedPosition); + StripAt->LedLUT[Step] = LedIndex; } } } @@ -47,30 +115,33 @@ ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 Roo static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, 0, 75, 0} }; s32 TempAssemblyOffsetsCount = 3; +// TODO(Peter): Don't reference State, pull back to the Led buffer and Assembly Array internal void LoadAssembly (app_state* State, context Context, string Path) { platform_memory_result AssemblyFile = ReadEntireFile(Context, Path); - if (AssemblyFile.Error == PlatformMemory_NoError) + if (AssemblyFile.Error == PlatformMemory_NoError && AssemblyFile.Size > 0) { string AssemblyFileText = MakeString((char*)AssemblyFile.Base); + Assert(State->Assemblies.Count < State->Assemblies.CountMax); + assembly* NewAssembly = &State->Assemblies.Values[State->Assemblies.Count++]; + s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\'); string FileName = Substring(Path, IndexOfLastSlash + 1); - assembly NewAssembly = {}; - NewAssembly.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; - NewAssembly.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; - ParseAssemblyFile(&NewAssembly, AssemblyFileText, &State->Transient); - - v4 Offset = TempAssemblyOffsets[State->ActiveAssemblyIndecies.Used % TempAssemblyOffsetsCount]; - ConstructAssemblyFromDefinition(&NewAssembly, FileName, Offset); - gs_list_handle NewAssemblyHandle = State->AssemblyList.PushElementOnList(NewAssembly); - - State->ActiveAssemblyIndecies.PushElementOnList(NewAssemblyHandle); - State->TotalLEDsCount += NewAssembly.LEDBuffer.LEDCount; - - Context.PlatformFree(AssemblyFile.Base, AssemblyFile.Size); + NewAssembly->Arena.PlatformMemory = Context.PlatformMemory; + if (ParseAssemblyFile(NewAssembly, AssemblyFileText, &State->Transient)) + { + v4 Offset = TempAssemblyOffsets[State->Assemblies.Count % TempAssemblyOffsetsCount]; + ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, &State->LedSystem); + PlatformFree(Context.PlatformMemory, AssemblyFile.Base, AssemblyFile.Size); + } + else + { + FreeMemoryArena(&NewAssembly->Arena); + State->Assemblies.Count -= 1; + } } else { @@ -81,20 +152,12 @@ LoadAssembly (app_state* State, context Context, string Path) internal void UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context) { - assembly* Assembly = State->AssemblyList.GetElementAtIndex(AssemblyIndex); - State->TotalLEDsCount -= Assembly->LEDBuffer.LEDCount; - FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree); - - State->AssemblyList.FreeElementAtIndex(AssemblyIndex); - for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) - { - gs_list_handle Handle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); - if (Handle.Index == AssemblyIndex) - { - State->ActiveAssemblyIndecies.FreeElementAtIndex(i); - break; - } - } + Assert(AssemblyIndex < State->Assemblies.Count); + assembly* Assembly = &State->Assemblies.Values[AssemblyIndex]; + LedSystemFreeBuffer(&State->LedSystem, Assembly->LedBufferIndex); + FreeMemoryArena(&Assembly->Arena); + u32 LastAssemblyIndex = --State->Assemblies.Count; + State->Assemblies.Values[AssemblyIndex] = State->Assemblies.Values[LastAssemblyIndex]; } diff --git a/src/app/foldhaus_assembly.h b/src/app/foldhaus_assembly.h index e414e7a..68c4f24 100644 --- a/src/app/foldhaus_assembly.h +++ b/src/app/foldhaus_assembly.h @@ -7,6 +7,7 @@ struct led { + // TODO(Peter): Pretty sure we don't need this. led and pixel are always parallel arrays s32 Index; v4 Position; }; @@ -22,22 +23,22 @@ union pixel u8 Channels[3]; }; -// NOTE(Peter): This structure is so we can keep track of -// what LEDs output to which DMX universe. You don't need -// to use it anywhere else, as all the data for patterns, -// colors, and groups is/will be stored elsewhere. -struct leds_in_universe_range +struct led_buffer { - s32 RangeStart; - s32 RangeOnePastLast; - s32 Universe; + u32 LedCount; + pixel* Colors; + led* Leds; }; -struct assembly_led_buffer +struct led_system { - u32 LEDCount; - pixel* Colors; - led* LEDs; + platform_memory_handler PlatformMemory; + + u32 BuffersCountMax; + u32 BuffersCount; + led_buffer* Buffers; + + u32 LedsCountTotal; }; struct v2_tag @@ -49,6 +50,7 @@ struct v2_tag struct v2_strip { s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore + // TODO(Peter): Add in info for Serial, ArtNet, etc. s32 StartUniverse; s32 StartChannel; @@ -72,17 +74,19 @@ struct assembly string FilePath; r32 Scale; + s32 LedCountTotal; + u32 LedBufferIndex; u32 StripCount; v2_strip* Strips; - - s32 LedCountTotal; - assembly_led_buffer LEDBuffer; - - u32 LEDUniverseMapCount; - leds_in_universe_range* LEDUniverseMap; }; +struct assembly_array +{ + u32 CountMax; + u32 Count; + assembly* Values; +}; #define FOLDHAUS_ASSEMBLY_H #endif // FOLDHAUS_ASSEMBLY_H \ No newline at end of file diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index 725284b..93dfa64 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -88,15 +88,6 @@ struct system_path s32 IndexOfLastSlash; }; -#define PLATFORM_ALLOC(name) u8* name(s32 Size) -typedef PLATFORM_ALLOC(platform_alloc); - -#define PLATFORM_FREE(name) b32 name(u8* Base, s32 Size) -typedef PLATFORM_FREE(platform_free); - -#define PLATFORM_REALLOC(name) u8* name(u8* Base, u32 OldSize, u32 NewSize) -typedef PLATFORM_REALLOC(platform_realloc); - #define PLATFORM_READ_ENTIRE_FILE(name) platform_memory_result name(string Path) typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file); @@ -264,10 +255,7 @@ struct context // Platform Services work_queue* GeneralWorkQueue; - platform_alloc* PlatformAlloc; - platform_free* PlatformFree; - platform_realloc* PlatformRealloc; - + platform_memory_handler PlatformMemory; platform_file_handler FileHandler; platform_write_entire_file* PlatformWriteEntireFile; diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index 7f27c94..c2d1ddb 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -37,14 +37,14 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1; u32 LinesDrawn = 0; - u32 AssembliesToDraw = GSMin(LineCount, State->ActiveAssemblyIndecies.Used); - for (; LinesDrawn < AssembliesToDraw; LinesDrawn++) + u32 AssembliesToDraw = GSMin(LineCount, State->Assemblies.Count); + for (u32 AssemblyIndex = 0; AssemblyIndex < AssembliesToDraw; AssemblyIndex++) { rect Bounds = ui_ReserveElementBounds(&Layout); - v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, LinesDrawn); + v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, AssemblyIndex); ui_FillRect(&State->Interface_, Bounds, ListItemBGColor); - gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(LinesDrawn); - assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle); + + assembly Assembly = State->Assemblies.Values[AssemblyIndex]; PrintF(&TempString, "%S", Assembly.Name); ui_layout ItemLayout = ui_CreateLayout(State->Interface_, Bounds); @@ -53,10 +53,12 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende ui_LayoutDrawString(&State->Interface_, &ItemLayout, TempString, State->Interface_.Style.TextColor); if (ui_LayoutButton(&State->Interface_, &ItemLayout, MakeStringLiteral("X"), ListItemBGColor, ListItemHover, ListItemSelected)) { - UnloadAssembly(AssemblyHandle.Index, State, Context); + UnloadAssembly(AssemblyIndex, State, Context); } } ui_EndRow(&ItemLayout); + + LinesDrawn += 1; } if (LinesDrawn < LineCount) diff --git a/src/app/panels/foldhaus_panel_sculpture_view.h b/src/app/panels/foldhaus_panel_sculpture_view.h index 880b2f8..4d239f3 100644 --- a/src/app/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/panels/foldhaus_panel_sculpture_view.h @@ -54,7 +54,7 @@ global_variable s32 SculptureView_CommandsCount = 1; GSMetaTag(panel_init); GSMetaTag(panel_type_sculpture_view); -internal void +internal void SculptureView_Init(panel* Panel, app_state* State) { @@ -62,7 +62,7 @@ SculptureView_Init(panel* Panel, app_state* State) GSMetaTag(panel_cleanup); GSMetaTag(panel_type_sculpture_view); -internal void +internal void SculptureView_Cleanup(panel* Panel, app_state* State) { @@ -133,7 +133,7 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) GSMetaTag(panel_render); GSMetaTag(panel_type_sculpture_view); -internal void +internal void SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) { DEBUG_TRACK_SCOPE(RenderSculpture); @@ -154,21 +154,21 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende FaceCameraMatrix = FaceCameraMatrix; u32 MaxLEDsPerJob = 2048; - render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount); + render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal); - for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) + for (u32 i = 0; i < State->Assemblies.Count; i++) { - gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); - assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle); - u32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDBuffer.LEDCount, MaxLEDsPerJob); + assembly Assembly = State->Assemblies.Values[i]; + led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex); + u32 JobsNeeded = IntegerDivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); for (u32 Job = 0; Job < JobsNeeded; Job++) { draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data); - JobData->LEDs = Assembly.LEDBuffer.LEDs; - JobData->Colors = Assembly.LEDBuffer.Colors; + JobData->LEDs = LedBuffer->Leds; + JobData->Colors = LedBuffer->Colors; JobData->StartIndex = Job * MaxLEDsPerJob; - JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, Assembly.LEDBuffer.LEDCount); + JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); JobData->Batch = &RenderLEDsBatch; JobData->FaceCameraMatrix; JobData->ModelViewMatrix = ModelViewMatrix; diff --git a/src/app/win32_foldhaus.cpp b/src/app/win32_foldhaus.cpp index 3155e6b..88ff2d9 100644 --- a/src/app/win32_foldhaus.cpp +++ b/src/app/win32_foldhaus.cpp @@ -663,9 +663,9 @@ WinMain ( // Platform functions Context.GeneralWorkQueue = &WorkQueue; - Context.PlatformAlloc = Win32Alloc; - Context.PlatformFree = Win32Free; - Context.PlatformRealloc = Win32Realloc; + Context.PlatformMemory.Alloc = Win32Alloc; + Context.PlatformMemory.Free = Win32Free; + Context.PlatformMemory.Realloc = Win32Realloc; Context.FileHandler.ReadEntireFile = Win32ReadEntireFile; Context.FileHandler.WriteEntireFile = Win32WriteEntireFile; Context.FileHandler.GetFilePath = Win32SystemDialogueOpenFile; diff --git a/src/app/win32_foldhaus_fileio.h b/src/app/win32_foldhaus_fileio.h index 3a9a9aa..2240dbc 100644 --- a/src/app/win32_foldhaus_fileio.h +++ b/src/app/win32_foldhaus_fileio.h @@ -133,6 +133,8 @@ PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile) Result = GetOpenFileNameA (&OpenFileName); + PathBuffer->Length = CharArrayLength(PathBuffer->Memory); + return Result; } diff --git a/src/gs_libs/gs_memory_arena.h b/src/gs_libs/gs_memory_arena.h index 772d9e3..119656c 100644 --- a/src/gs_libs/gs_memory_arena.h +++ b/src/gs_libs/gs_memory_arena.h @@ -2,8 +2,8 @@ // Description: Single header file library that defines a push-only memory arena // Author: Peter Slattery // Date Created: 2019-12-22 -// -// +// +// // ----------------- // Set Up // ----------------- @@ -16,26 +16,26 @@ // Simply create a memory_arena and use PushSize, PushStruct, or PushArray // to allocate out of it. // See Example Program below. -// +// // While there are options you can set (see Options below), the library adheres // to a 'zero-is-initialization' policy, that is, a memory_arena initialized to -// zero, under all default options, will 'just work'. +// zero, under all default options, will 'just work'. // // Alignment: // By default, the Push functions use 4 byte alignment -// If you need to control the alignment of an allocation, there are variants of the +// If you need to control the alignment of an allocation, there are variants of the // Push functions that allow for this: PushSizeAligned, PushStructAligned, and PushArrayAligned -// These functions simply take a final parameter which specifies the alignment. +// These functions simply take a final parameter which specifies the alignment. // Note: Alignment must be a power of two // // ----------------- // Options // ----------------- -// -// DEBUG: +// +// DEBUG: // Define DEBUG for debug functionality. -// -// To override the default assert function define GSMem_Assert(expression) +// +// To override the default assert function define GSMem_Assert(expression) // before inluding this file. // // GS_MEMORY_NO_STD_LIBS: @@ -61,8 +61,8 @@ // this file // // GS_MEMORY_TRACK_ALLOCATIONS: -// If you want to keep records of each allocation performed in every arena, define -// GS_MEMORY_TRACK_ALLOCATIONS before including this file. +// If you want to keep records of each allocation performed in every arena, define +// GS_MEMORY_TRACK_ALLOCATIONS before including this file. // When defined, memory arenas gain fields that allow them to keep a list of every // allocation they contain. It also adds a footer on the end of each allocation that // can be checked to ensure there are no writes to allocations that overflow their bounds @@ -78,8 +78,8 @@ // Places the characters 'gs' at the end of each allocation. This would allow for an external // function to check that we haven't written past the end of an allocation -void* MallocWrapper(gs_mem_u32 Size) -{ +void* MallocWrapper(gs_mem_u32 Size) +{ int SizeWithFooter = Size + (sizeof(char) * 2); void* Result = malloc(SizeWithFooter); char* Footer = (char*)(Result + Size); @@ -88,17 +88,17 @@ void* MallocWrapper(gs_mem_u32 Size) return Result; } -void* ReallocWrapper(void* Address, gs_mem_u32 Size) -{ - return realloc(Address, Size); +void* ReallocWrapper(void* Address, gs_mem_u32 Size) +{ + return realloc(Address, Size); } -int +int main(int ArgCount, char** Args) { memory_arena Arena = {}; // Uncomment these lines for an example of how you can implement custom allocation functions - // Arena.Alloc = MallocWrapper; + // Arena.Alloc = MallocWrapper; // Arena.Realloc = ReallocWrapper; int ArrayLength = 10; @@ -139,9 +139,9 @@ main(int ArgCount, char** Args) #ifndef GS_MEMORY_NO_STD_LIBS // NOTE(Peter): We use this so that we can fall back on malloc and realloc -// in the event that a memory_arena needs to grow but doesn't have a +// in the event that a memory_arena needs to grow but doesn't have a // alloc or realloc function pointer assigned to it. -// +// // See GrowArena to see where this is used // #include @@ -177,13 +177,13 @@ enum gs_memory_expansion_rule // NOTE(Peter): // This rule is only here to allow for taking arena snapshots. The problem this solves -// is if you take a snapshot while there are 'holes' in memory_buffers behind the +// is if you take a snapshot while there are 'holes' in memory_buffers behind the // most recently added memory_buffer, take a snapshot of that arena, then push something // on that fits in one of those holes, we will fill the hole and be unable to track/free -// that addition via the snapshot construct. +// that addition via the snapshot construct. // // By requiring that allocations in a buffer only come from the most recent memory_buffer -// we can very easily rewind the buffer to the correct location. +// we can very easily rewind the buffer to the correct location. // Hence FindAddress_InLastBufferOnly enum gs_memory_find_address_rule { @@ -192,9 +192,21 @@ enum gs_memory_find_address_rule FindAddress_Count, }; -typedef void* gs_memory_alloc(gs_mem_u32 Size); -typedef void* gs_memory_realloc(void* Address, gs_mem_u32 OldSize, gs_mem_u32 NewSize); -typedef void gs_memory_free(void* Address, gs_mem_u32 Size); +#define PLATFORM_ALLOC(name) u8* name(s32 Size) +typedef PLATFORM_ALLOC(platform_alloc); + +#define PLATFORM_FREE(name) b32 name(u8* Base, s32 Size) +typedef PLATFORM_FREE(platform_free); + +#define PLATFORM_REALLOC(name) u8* name(u8* Base, u32 OldSize, u32 NewSize) +typedef PLATFORM_REALLOC(platform_realloc); + +struct platform_memory_handler +{ + platform_alloc* Alloc; + platform_free* Free; + platform_realloc* Realloc; +}; #ifndef GS_MEMORY_BUFFER_SIZE #define GS_MEMORY_BUFFER_SIZE 1024 @@ -237,8 +249,8 @@ struct memory_arena gs_memory_find_address_rule FindAddressRule; gs_memory_expansion_rule ExpansionRule; - gs_memory_alloc* Alloc; - gs_memory_realloc* Realloc; + + platform_memory_handler PlatformMemory; #ifdef GS_MEMORY_TRACK_ALLOCATIONS tracked_allocation_buffer** AllocationBuffers; @@ -266,31 +278,62 @@ struct arena_snapshot #endif }; +#define PlatformFreeArray(platform, base, type, count) PlatformFree((platform), (gs_mem_u8*)(base), sizeof(type) * (count)) +#define ArenaFree(arena, base, size) PlatformFree((arena).PlatformMemory, (gs_mem_u8*)(base), (gs_mem_u32)(size)) static void -FreeMemoryArena(memory_arena* Arena, gs_memory_free* Free = 0) +PlatformFree(platform_memory_handler Platform, gs_mem_u8* Base, gs_mem_u32 Size) { - if (Free) + Assert(Platform.Free != 0); + Platform.Free(Base, Size); +} + +#define PlatformAllocArray(platform, type, size) (type*)PlatformAlloc((platform), sizeof(type) * (size)) +#define ArenaAlloc(arena, size) PlatformAlloc((arena).PlatformMemory, (gs_mem_u32)(size)) +#define ArenaAllocStruct(arena, type) (type*)PlatformAlloc((arena).PlatformMemory, sizeof(type)) +#define ArenaAllocArray(arena, type, size) (type*)PlatformAlloc((arena).PlatformMemory, sizeof(type) * (size)) +static gs_mem_u8* +PlatformAlloc(platform_memory_handler Platform, gs_mem_u32 Size) +{ + Assert(Platform.Alloc != 0); + gs_mem_u8* Result = Platform.Alloc(Size); + return Result; +} + +#define ArenaRealloc(arena, base, oldSize, newSize) PlatformRealloc((arena).PlatformMemory, (gs_mem_u8*)(base), (gs_mem_u32)(oldSize), (gs_mem_u32)(newSize)) +#define ArenaReallocArray(arena, base, type, oldCount, newCount) (type*)PlatformRealloc((arena).PlatformMemory, (gs_mem_u8*)(base), sizeof(type) * oldCount, sizeof(type) * newCount) +static gs_mem_u8* +PlatformRealloc(platform_memory_handler Platform, gs_mem_u8* Head, gs_mem_u32 OldSize, gs_mem_u32 NewSize) +{ + gs_mem_u8* Result = 0; + if (Platform.Realloc != 0) { - for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) + Result = Platform.Realloc(Head, OldSize, NewSize); + } + else if (Platform.Alloc != 0 && Platform.Free != 0) + { + Result = PlatformAlloc(Platform, NewSize); + if (Head != 0 && OldSize != 0) { - memory_buffer* Buffer = Arena->Buffers + i; - Free(Buffer->Buffer, Buffer->Size); + GSMemCopy(Head, Result, OldSize); + PlatformFree(Platform, Head, OldSize); } - Free(Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount); } else { -#ifdef GS_MEMORY_NO_STD_LIBS - GSMem_Assert(0); -#else - for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) - { - memory_buffer* Buffer = Arena->Buffers + i; - free(Buffer->Buffer); - } - free(Arena->Buffers); -#endif + InvalidCodePath; } + return Result; +} + +static void +FreeMemoryArena(memory_arena* Arena) +{ + for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) + { + memory_buffer* Buffer = Arena->Buffers + i; + PlatformFree(Arena->PlatformMemory, Buffer->Buffer, Buffer->Size); + } + PlatformFree(Arena->PlatformMemory, (u8*)Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount); } #define IsPowerOfTwo(v) ((v != 0) && ((v & (v - 1)) == 0)) @@ -340,53 +383,7 @@ FindAlignedAddressInBufferWithRoom(memory_arena* Arena, gs_mem_u32 Size, gs_mem_ Result = AddressInCurrentBuffer; break; } - } - return Result; -} - -static gs_mem_u8* -ArenaAlloc(memory_arena* Arena, gs_mem_u32 Size) -{ - gs_mem_u8* Result = 0; - - if (Arena->Alloc) - { - Result = (gs_mem_u8*)Arena->Alloc(sizeof(gs_mem_u8) * Size); } - else - { -#ifdef GS_MEMORY_NO_STD_LIBS - // NOTE(Peter): If you specify no std libs AND don't supply a allocation function - // we should assert as this is an invalid codepath - GSMem_Assert(0); -#else - Result = (gs_mem_u8*)malloc(sizeof(gs_mem_u8) * Size); -#endif - } - - return Result; -} - -static gs_mem_u8* -ArenaRealloc(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 OldSize, gs_mem_u32 NewSize) -{ - gs_mem_u8* Result = 0; - - if (Arena->Realloc != 0) - { - Result = (gs_mem_u8*)Arena->Realloc(Head, OldSize, NewSize); - } - else - { -#ifdef GS_MEMORY_NO_STD_LIBS - // NOTE(Peter): If you specify no std libs AND don't supply a reallocation function - // we should assert as this is an invalid codepath - GSMem_Assert(0); -#else - Result = (gs_mem_u8*)realloc(Head, NewSize); -#endif - } - return Result; } @@ -394,15 +391,13 @@ static memory_buffer* GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded) { GSMem_Assert(Arena->ExpansionRule != MemoryExpansion_Disallowed); - if (Arena->ExpansionRule == MemoryExpansion_OnlyIfFunctionsProvided) - { - GSMem_Assert((Arena->Alloc != 0) && (Arena->Realloc != 0)); - } gs_mem_u32 NewBuffersCount = (Arena->BuffersCount + 1); +#if 0 gs_mem_u32 OldBuffersSize = sizeof(memory_buffer) * Arena->BuffersCount; gs_mem_u32 NewBuffersSize = sizeof(memory_buffer) * NewBuffersCount; - Arena->Buffers = (memory_buffer*)ArenaRealloc(Arena, (gs_mem_u8*)Arena->Buffers, OldBuffersSize, NewBuffersSize); +#endif + Arena->Buffers = ArenaReallocArray(*Arena, Arena->Buffers, memory_buffer, Arena->BuffersCount, NewBuffersCount); Arena->BuffersCount = NewBuffersCount; memory_buffer* NewBuffer = Arena->Buffers + (Arena->BuffersCount - 1); @@ -412,7 +407,7 @@ GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded) NewBuffer->Size = SizeNeeded; } - NewBuffer->Buffer = ArenaAlloc(Arena, sizeof(gs_mem_u8) * NewBuffer->Size); + NewBuffer->Buffer = ArenaAllocArray(*Arena, gs_mem_u8, NewBuffer->Size); NewBuffer->Used = 0; Arena->TotalSize += NewBuffer->Size; @@ -433,14 +428,20 @@ TrackAllocation(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 Size, char* Fil if (Arena->AllocationsUsed >= AllocationsMax) { gs_mem_u32 NewAllocationBuffersCount = Arena->AllocationBuffersCount + 1; - Arena->AllocationBuffers = (tracked_allocation_buffer**)ArenaRealloc(Arena, - (gs_mem_u8*)Arena->AllocationBuffers, - Arena->AllocationBuffersCount * sizeof(void*), - NewAllocationBuffersCount * sizeof(void*)); +#if 0 + gs_mem_u32 OldSize = Arena->AllocationBuffersCount * sizeof(void*); + gs_mem_u32 NewSize = NewAllocationBuffersCount * sizeof(void*); + Arena->AllocationBuffers = (tracked_allocation_buffer**)PlatformRealloc(Arena->PlatformMemory, + (gs_mem_u8*)Arena->AllocationBuffers, + OldSize, NewSize); +#else + Arena->AllocationBuffers = ArenaReallocArray(*Arena, Arena->AllocationBuffers, tracked_allocation_buffer*, Arena->AllocationBuffersCount, NewAllocationBuffersCount); +#endif + Arena->AllocationBuffersCount = NewAllocationBuffersCount; gs_mem_u32 NewBufferIndex = Arena->AllocationBuffersCount - 1; - Arena->AllocationBuffers[NewBufferIndex] = (tracked_allocation_buffer*)ArenaAlloc(Arena, sizeof(tracked_allocation_buffer)); + Arena->AllocationBuffers[NewBufferIndex] = ArenaAllocStruct(*Arena, tracked_allocation_buffer); } gs_mem_u32 AllocationIndex = Arena->AllocationsUsed++; @@ -474,8 +475,8 @@ VerifyAllocationNoOverflow (tracked_allocation Allocation) static void AssertAllocationsNoOverflow (memory_arena Arena) { - for (gs_mem_u32 AllocationIndex = 0; - AllocationIndex< Arena.AllocationsUsed; + for (gs_mem_u32 AllocationIndex = 0; + AllocationIndex< Arena.AllocationsUsed; AllocationIndex++) { gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; @@ -502,7 +503,7 @@ AssertAllocationsNoOverflow (memory_arena Arena) #define ClearAllocationsUsed(arena) #define ClearAllocationsUsedToSnapshot(arena, snapshot) -#define TrackAllocation(arena, head, size, filename, linenumber) +#define TrackAllocation(arena, head, size, filename, linenumber) #define PushSize(arena, size) PushSize_((arena), (size)) #define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length) @@ -517,7 +518,7 @@ static gs_mem_u8* PushSize_(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment = 4, char* Filename = 0, gs_mem_u32 LineNumber = 0) { // ie. Alignment = 4 = 100 (binary) - // 4 - 1 = 3 + // 4 - 1 = 3 // 100 - 1 = 011 which is a mask of the bits we don't want set in the start address GSMem_Assert(IsPowerOfTwo(Alignment)); gs_mem_u32 AlignmentMask = Alignment - 1; @@ -560,7 +561,7 @@ ClearArena(memory_arena* Arena) { memory_buffer* At = Arena->Buffers + i; At->Used = 0; - } + } Arena->TotalUsed = 0; ClearAllocationsUsed(Arena); From 9c432a38071b4cebf99e7d7ac0321701314bd644 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Fri, 19 Jun 2020 18:53:23 -0700 Subject: [PATCH 05/43] Cleaned up some extraneous variables in the assembly structure --- src/app/foldhaus_app.cpp | 5 +- src/app/foldhaus_app.h | 38 ++++++----- src/app/foldhaus_assembly.cpp | 9 ++- src/app/foldhaus_assembly.h | 10 +-- src/app/foldhaus_default_nodes.h | 27 ++++---- src/app/foldhaus_node.h | 8 +-- .../generated/gs_meta_generated_typeinfo.h | 14 ++-- .../panels/foldhaus_panel_sculpture_view.h | 16 ++--- src/app/test_patterns.h | 64 +++++++++---------- src/app/win32_foldhaus_memory.h | 6 +- 10 files changed, 86 insertions(+), 111 deletions(-) diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index afb801e..a202b38 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -314,8 +314,7 @@ CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, for (u32 i = 0; i < Strip.LedCount; i++) { u32 LedIndex = Strip.LedLUT[i]; - led LED = LedBuffer->Leds[LedIndex]; - pixel Color = LedBuffer->Colors[LED.Index]; + pixel Color = LedBuffer->Colors[LedIndex]; DestChannel[0] = Color.R; DestChannel[1] = Color.G; @@ -529,6 +528,7 @@ UPDATE_AND_RENDER(UpdateAndRender) Context->GeneralWorkQueue->ResetWorkQueue(Context->GeneralWorkQueue); // Checking for overflows +#if 0 { DEBUG_TRACK_SCOPE(OverflowChecks); AssertAllocationsNoOverflow(State->Permanent); @@ -538,6 +538,7 @@ UPDATE_AND_RENDER(UpdateAndRender) AssertAllocationsNoOverflow(Assembly->Arena); } } +#endif } CLEANUP_APPLICATION(CleanupApplication) diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 0e08eb1..6fe067c 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -94,18 +94,18 @@ TestPatternOne(led_buffer* Assembly, r32 Time) { for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) { - led Led = Assembly->Leds[LedIndex]; - if (Led.Position.x < 0) + v4 LedPosition = Assembly->Positions[LedIndex]; + if (LedPosition.x < 0) { - Assembly->Colors[Led.Index].R = 255; - Assembly->Colors[Led.Index].B = 255; - Assembly->Colors[Led.Index].G = 255; + Assembly->Colors[LedIndex].R = 255; + Assembly->Colors[LedIndex].B = 255; + Assembly->Colors[LedIndex].G = 255; } else { - Assembly->Colors[Led.Index].R = 0; - Assembly->Colors[Led.Index].B = 0; - Assembly->Colors[Led.Index].G = 0; + Assembly->Colors[LedIndex].R = 0; + Assembly->Colors[LedIndex].B = 0; + Assembly->Colors[LedIndex].G = 0; } } } @@ -132,9 +132,7 @@ TestPatternTwo(led_buffer* Assembly, r32 Time) for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) { - led Led = Assembly->Leds[LedIndex]; - - v4 Position = Led.Position; + v4 Position = Assembly->Positions[LedIndex]; v4 ToFront = Position + FrontCenter; v4 ToBack = Position + BackCenter; @@ -150,16 +148,16 @@ TestPatternTwo(led_buffer* Assembly, r32 Time) { if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) { - Assembly->Colors[Led.Index] = Color; + Assembly->Colors[LedIndex] = Color; } else { - //Assembly->Colors[Led.Index] = {}; + //Assembly->Colors[LedIndex] = {}; } } else { - //Assembly->Colors[Led.Index] = {}; + //Assembly->Colors[LedIndex] = {}; } } } @@ -178,23 +176,23 @@ TestPatternThree(led_buffer* Assembly, r32 Time) for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) { - led Led = Assembly->Leds[LedIndex]; + v4 LedPosition = Assembly->Positions[LedIndex]; u8 Red = 0; u8 Green = 0; u8 Blue = 0; - r32 GreenDist = GSAbs(Mag(Led.Position - GreenCenter) - GreenRadius); + r32 GreenDist = GSAbs(Mag(LedPosition - GreenCenter) - GreenRadius); r32 GreenBrightness = GSClamp(0.f, FadeDist - GSAbs(GreenDist), FadeDist); Green = (u8)(GreenBrightness * 255); - r32 TealDist = GSAbs(Mag(Led.Position - TealCenter) - TealRadius); + r32 TealDist = GSAbs(Mag(LedPosition - TealCenter) - TealRadius); r32 TealBrightness = GSClamp(0.f, FadeDist - GSAbs(TealDist), FadeDist); Red = (u8)(TealBrightness * 255); Blue = (u8)(TealBrightness * 255); - Assembly->Colors[Led.Index].R = Red; - Assembly->Colors[Led.Index].B = Green; - Assembly->Colors[Led.Index].G = Green; + Assembly->Colors[LedIndex].R = Red; + Assembly->Colors[LedIndex].B = Green; + Assembly->Colors[LedIndex].G = Green; } } diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index da5841e..97cdbf2 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -34,7 +34,7 @@ LedSystemTakeFreeBuffer(led_system* System, u32 LedCount) { if (System->Buffers[i].LedCount == 0 && System->Buffers[i].Colors == 0 - && System->Buffers[i].Leds == 0) + && System->Buffers[i].Positions == 0) { Result = i; break; @@ -46,7 +46,7 @@ LedSystemTakeFreeBuffer(led_system* System, u32 LedCount) led_buffer* Buffer = &System->Buffers[Result]; Buffer->LedCount = LedCount; Buffer->Colors = PlatformAllocArray(System->PlatformMemory, pixel, Buffer->LedCount); - Buffer->Leds = PlatformAllocArray(System->PlatformMemory, led, Buffer->LedCount); + Buffer->Positions = PlatformAllocArray(System->PlatformMemory, v4, Buffer->LedCount); System->LedsCountTotal += LedCount; @@ -59,7 +59,7 @@ LedSystemFreeBuffer(led_system* System, u32 BufferIndex) Assert(BufferIndex < System->BuffersCountMax); led_buffer* Buffer = &System->Buffers[BufferIndex]; PlatformFreeArray(System->PlatformMemory, Buffer->Colors, pixel, Buffer->LedCount); - PlatformFreeArray(System->PlatformMemory, Buffer->Leds, led, Buffer->LedCount); + PlatformFreeArray(System->PlatformMemory, Buffer->Positions, v4, Buffer->LedCount); System->LedsCountTotal -= Buffer->LedCount; *Buffer = {}; } @@ -75,8 +75,7 @@ internal void LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) { Assert(Led < Buffer->LedCount); - Buffer->Leds[Led].Position = Position; - Buffer->Leds[Led].Index = Led; + Buffer->Positions[Led] = Position; } // Assembly diff --git a/src/app/foldhaus_assembly.h b/src/app/foldhaus_assembly.h index 68c4f24..97c153a 100644 --- a/src/app/foldhaus_assembly.h +++ b/src/app/foldhaus_assembly.h @@ -5,13 +5,6 @@ // #ifndef FOLDHAUS_ASSEMBLY_H -struct led -{ - // TODO(Peter): Pretty sure we don't need this. led and pixel are always parallel arrays - s32 Index; - v4 Position; -}; - union pixel { struct @@ -27,7 +20,7 @@ struct led_buffer { u32 LedCount; pixel* Colors; - led* Leds; + v4* Positions; }; struct led_system @@ -50,6 +43,7 @@ struct v2_tag struct v2_strip { s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore + // TODO(Peter): Add in info for Serial, ArtNet, etc. s32 StartUniverse; s32 StartChannel; diff --git a/src/app/foldhaus_default_nodes.h b/src/app/foldhaus_default_nodes.h index fd68674..7083ce2 100644 --- a/src/app/foldhaus_default_nodes.h +++ b/src/app/foldhaus_default_nodes.h @@ -117,7 +117,7 @@ NODE_PROC(SinWave, sin_wave_data) // ///////////////////////////////// -GSMetaTag(node_struct); +GSMetaTag(node_struct); struct multiply_patterns_data { GSMetaTag(node_input); @@ -132,28 +132,25 @@ struct multiply_patterns_data NODE_PROC(MultiplyPatterns, multiply_patterns_data) { - led* LED = Data->Result.LEDs; - for (s32 l = 0; l < Data->Result.LEDCount; l++) + for (s32 LedIndex = 0; LedIndex < Data->Result.LEDCount; LedIndex++) { - Assert(LED->Index >= 0 && LED->Index < Data->Result.LEDCount); + Assert(LedIndex >= 0 && LedIndex < Data->Result.LEDCount); - s32 AR = Data->A.Colors[LED->Index].R; - s32 AG = Data->A.Colors[LED->Index].G; - s32 AB = Data->A.Colors[LED->Index].B; + s32 AR = Data->A.Colors[LedIndex].R; + s32 AG = Data->A.Colors[LedIndex].G; + s32 AB = Data->A.Colors[LedIndex].B; - s32 BR = Data->B.Colors[LED->Index].R; - s32 BG = Data->B.Colors[LED->Index].G; - s32 BB = Data->B.Colors[LED->Index].B; + s32 BR = Data->B.Colors[LedIndex].R; + s32 BG = Data->B.Colors[LedIndex].G; + s32 BB = Data->B.Colors[LedIndex].B; s32 RCombined = (AR * BR) / 255; s32 GCombined = (AG * BG) / 255; s32 BCombined = (AB * BB) / 255; - Data->Result.Colors[LED->Index].R = (u8)RCombined; - Data->Result.Colors[LED->Index].G = (u8)GCombined; - Data->Result.Colors[LED->Index].B = (u8)BCombined; - - LED++; + Data->Result.Colors[LedIndex].R = (u8)RCombined; + Data->Result.Colors[LedIndex].G = (u8)GCombined; + Data->Result.Colors[LedIndex].B = (u8)BCombined; } } diff --git a/src/app/foldhaus_node.h b/src/app/foldhaus_node.h index b51b9ca..17a6c7b 100644 --- a/src/app/foldhaus_node.h +++ b/src/app/foldhaus_node.h @@ -14,7 +14,7 @@ typedef enum node_type node_type; struct color_buffer { - led* LEDs; + v4* LedPositions; pixel* Colors; s32 LEDCount; }; @@ -66,7 +66,7 @@ struct node_specification_ struct pattern_node { // TODO(Peter): Something to think about further down the line is the fact that - // SpecificationIndex doesn't have to stay static throughout a single instance of + // SpecificationIndex doesn't have to stay static throughout a single instance of // an application, let alone across separate runs. If you recompile (hot load or not) // with a new specification, the indecies all get thrown off. Should we hash the spec // names or something? @@ -90,7 +90,7 @@ struct pattern_node_workspace gs_bucket Connections; // This is storage for all the structures which follow. - // It is cleared when new nodes are added so that the + // It is cleared when new nodes are added so that the // acceleration structures can be recalculated memory_arena Storage; s32* SparseToSortedNodeMap; @@ -109,7 +109,7 @@ struct data_name struct data_name #define NODE_PROC(proc_name, input_type) \ -void proc_name(input_type* Data, r32 DeltaTime) +void proc_name(input_type* Data, r32 DeltaTime) #define NODE_IN(type, name) type name #define NODE_OUT(type, name) type name diff --git a/src/app/generated/gs_meta_generated_typeinfo.h b/src/app/generated/gs_meta_generated_typeinfo.h index e5cc3e0..9395469 100644 --- a/src/app/generated/gs_meta_generated_typeinfo.h +++ b/src/app/generated/gs_meta_generated_typeinfo.h @@ -39,10 +39,9 @@ enum gsm_struct_type gsm_StructType_v4, gsm_StructType_float, gsm_StructType_color_buffer, - gsm_StructType_led, - gsm_StructType_s32, gsm_StructType_pixel, gsm_StructType_u8, + gsm_StructType_s32, gsm_StructType_sin_wave_data, gsm_StructType_r32, gsm_StructType_revolving_discs_data, @@ -62,10 +61,6 @@ static gsm_struct_member_type_info StructMembers_v4[] = { { "a", 1, (u64)&((v4*)0)->a, {}, 0}, { "E", 1, (u64)&((v4*)0)->E, {}, 0}, }; -static gsm_struct_member_type_info StructMembers_led[] = { -{ "Index", 5, (u64)&((led*)0)->Index, {}, 0}, -{ "Position", 8, (u64)&((led*)0)->Position, {}, 0}, -}; static gsm_struct_member_type_info StructMembers_pixel[] = { { "R", 1, (u64)&((pixel*)0)->R, {}, 0}, { "G", 1, (u64)&((pixel*)0)->G, {}, 0}, @@ -73,7 +68,7 @@ static gsm_struct_member_type_info StructMembers_pixel[] = { { "Channels", 8, (u64)&((pixel*)0)->Channels, {}, 0}, }; static gsm_struct_member_type_info StructMembers_color_buffer[] = { -{ "LEDs", 4, (u64)&((color_buffer*)0)->LEDs, {}, 0}, +{ "LedPositions", 12, (u64)&((color_buffer*)0)->LedPositions, {}, 0}, { "Colors", 6, (u64)&((color_buffer*)0)->Colors, {}, 0}, { "LEDCount", 8, (u64)&((color_buffer*)0)->LEDCount, {}, 0}, }; @@ -115,14 +110,13 @@ static gsm_struct_type_info StructTypes[] = { { gsm_StructType_v4, "v4", 2, 16, 0, 0, StructMembers_v4, 3 }, { gsm_StructType_float, "float", 5, 4, 0, 0, 0, 0 }, { gsm_StructType_color_buffer, "color_buffer", 12, 20, 0, 0, StructMembers_color_buffer, 3 }, -{ gsm_StructType_led, "led", 3, 20, 0, 0, StructMembers_led, 2 }, -{ gsm_StructType_s32, "s32", 3, 4, 0, 0, 0, 0 }, { gsm_StructType_pixel, "pixel", 5, 3, 0, 0, StructMembers_pixel, 2 }, { gsm_StructType_u8, "u8", 2, 1, 0, 0, 0, 0 }, +{ gsm_StructType_s32, "s32", 3, 4, 0, 0, 0, 0 }, { gsm_StructType_sin_wave_data, "sin_wave_data", 13, 20, 0, 0, StructMembers_sin_wave_data, 5 }, { gsm_StructType_r32, "r32", 3, 4, 0, 0, 0, 0 }, { gsm_StructType_revolving_discs_data, "revolving_discs_data", 20, 60, 0, 0, StructMembers_revolving_discs_data, 8 }, { gsm_StructType_vertical_color_fade_data, "vertical_color_fade_data", 24, 44, 0, 0, StructMembers_vertical_color_fade_data, 4 }, { gsm_StructType_multiply_patterns_data, "multiply_patterns_data", 22, 60, 0, 0, StructMembers_multiply_patterns_data, 3 }, }; -static gsm_u32 StructTypesCount = 13; +static gsm_u32 StructTypesCount = 12; diff --git a/src/app/panels/foldhaus_panel_sculpture_view.h b/src/app/panels/foldhaus_panel_sculpture_view.h index 4d239f3..7ff61ee 100644 --- a/src/app/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/panels/foldhaus_panel_sculpture_view.h @@ -71,7 +71,7 @@ SculptureView_Cleanup(panel* Panel, app_state* State) struct draw_leds_job_data { - led* LEDs; + v4* Positions; pixel* Colors; s32 StartIndex; s32 OnePastLastIndex; @@ -107,15 +107,13 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) v2 UV2 = v2{1, 1}; v2 UV3 = v2{0, 1}; - led* LED = Data->LEDs + Data->StartIndex; - for (s32 LEDIdx = 0; - LEDIdx < LEDCount; - LEDIdx++) + + for (s32 LedIndex = 0; LedIndex < LEDCount; LedIndex++) { - pixel PixelColor = Data->Colors[LED->Index]; + pixel PixelColor = Data->Colors[LedIndex]; v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f}; - v4 V4Position = LED->Position; + v4 V4Position = Data->Positions[Data->StartIndex + LedIndex]; V4Position.w = 0; v4 P0 = P0_In + V4Position; v4 P1 = P1_In + V4Position; @@ -126,8 +124,6 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, P0, P2, P3, UV0, UV2, UV3, Color, Color, Color); - - LED++; } } @@ -165,7 +161,7 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende for (u32 Job = 0; Job < JobsNeeded; Job++) { draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data); - JobData->LEDs = LedBuffer->Leds; + JobData->Positions = LedBuffer->Positions; JobData->Colors = LedBuffer->Colors; JobData->StartIndex = Job * MaxLEDsPerJob; JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); diff --git a/src/app/test_patterns.h b/src/app/test_patterns.h index 4215ae0..51da616 100644 --- a/src/app/test_patterns.h +++ b/src/app/test_patterns.h @@ -8,49 +8,47 @@ GSMetaTag(node_struct); struct solid_color_data { - GSMetaTag(node_input); + GSMetaTag(node_input); v4 Color; GSMetaTag(node_output); color_buffer Result; }; -GSMetaTag(node_proc); // :TagParamsForNodeParamStructs +GSMetaTag(node_proc); // :TagParamsForNodeParamStructs void SolidColorProc(solid_color_data* Data) { u8 R = (u8)GSClamp(0.f, (Data->Color.r * 255), 255.f); u8 G = (u8)GSClamp(0.f, (Data->Color.g * 255), 255.f); u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f); - led* LED = Data->Result.LEDs; - for (s32 l = 0; l < Data->Result.LEDCount; l++) + for (s32 LedIndex = 0; LedIndex < Data->Result.LEDCount; LedIndex++) { - Assert(LED->Index >= 0 && LED->Index < Data->Result.LEDCount); + Assert(LedIndex >= 0 && LedIndex < Data->Result.LEDCount); - Data->Result.Colors[LED->Index].R = R; - Data->Result.Colors[LED->Index].G = G; - Data->Result.Colors[LED->Index].B = B; - LED++; + Data->Result.Colors[LedIndex].R = R; + Data->Result.Colors[LedIndex].G = G; + Data->Result.Colors[LedIndex].B = B; } } GSMetaTag(node_struct); struct vertical_color_fade_data { - GSMetaTag(node_input); + GSMetaTag(node_input); v4 Color; - GSMetaTag(node_input); + GSMetaTag(node_input); r32 Min; - GSMetaTag(node_input); + GSMetaTag(node_input); r32 Max; GSMetaTag(node_output); color_buffer Result; }; -GSMetaTag(node_proc); // :TagParamsForNodeParamStructs +GSMetaTag(node_proc); // :TagParamsForNodeParamStructs void VerticalColorFadeProc(vertical_color_fade_data* Data) { r32 R = (Data->Color.r * 255); @@ -59,18 +57,18 @@ void VerticalColorFadeProc(vertical_color_fade_data* Data) r32 Range = Data->Max - Data->Min; - led* LED = Data->Result.LEDs; - for (s32 l = 0; l < Data->Result.LEDCount; l++) + + for (s32 LedIndex = 0; LedIndex < Data->Result.LEDCount; LedIndex++) { - Assert(LED->Index >= 0 && LED->Index < Data->Result.LEDCount); + Assert(LedIndex >= 0 && LedIndex < Data->Result.LEDCount); + v4 LedPosition = Data->Result.LedPositions[LedIndex]; - r32 Amount = (LED->Position.y - Data->Min) / Range; + r32 Amount = (LedPosition.y - Data->Min) / Range; Amount = GSClamp01(1.0f - Amount); - Data->Result.Colors[LED->Index].R = (u8)(R * Amount); - Data->Result.Colors[LED->Index].G = (u8)(G * Amount); - Data->Result.Colors[LED->Index].B = (u8)(B * Amount); - LED++; + Data->Result.Colors[LedIndex].R = (u8)(R * Amount); + Data->Result.Colors[LedIndex].G = (u8)(G * Amount); + Data->Result.Colors[LedIndex].B = (u8)(B * Amount); } } @@ -78,32 +76,32 @@ void VerticalColorFadeProc(vertical_color_fade_data* Data) GSMetaTag(node_struct); struct revolving_discs_data { - GSMetaTag(node_input); + GSMetaTag(node_input); r32 Rotation; - GSMetaTag(node_input); + GSMetaTag(node_input); r32 ThetaZ; - GSMetaTag(node_input); + GSMetaTag(node_input); r32 ThetaY; - GSMetaTag(node_input); + GSMetaTag(node_input); r32 DiscWidth; - GSMetaTag(node_input); + GSMetaTag(node_input); r32 InnerRadius; - GSMetaTag(node_input); + GSMetaTag(node_input); r32 OuterRadius; - GSMetaTag(node_input); + GSMetaTag(node_input); v4 Color; GSMetaTag(node_output); color_buffer Result; }; -GSMetaTag(node_proc); // :TagParamsForNodeParamStructs +GSMetaTag(node_proc); // :TagParamsForNodeParamStructs void RevolvingDiscs(revolving_discs_data* Data) { DEBUG_TRACK_FUNCTION; @@ -124,10 +122,9 @@ void RevolvingDiscs(revolving_discs_data* Data) r32 OuterRadiusSquared = Data->OuterRadius * Data->OuterRadius; r32 InnerRadiusSquared = Data->InnerRadius * Data->InnerRadius; - led* LED = Data->Result.LEDs; - for (s32 l = 0; l < Data->Result.LEDCount; l++) + for (s32 LedIndex = 0; LedIndex < Data->Result.LEDCount; LedIndex++) { - v4 Position = LED->Position; + v4 Position = Data->Result.LedPositions[LedIndex]; v4 ToFront = Position + FrontCenter; v4 ToBack = Position + BackCenter; @@ -143,10 +140,9 @@ void RevolvingDiscs(revolving_discs_data* Data) { if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) { - Data->Result.Colors[LED->Index] = Color; + Data->Result.Colors[LedIndex] = Color; } } - LED++; } } diff --git a/src/app/win32_foldhaus_memory.h b/src/app/win32_foldhaus_memory.h index e786c44..c1c8c1c 100644 --- a/src/app/win32_foldhaus_memory.h +++ b/src/app/win32_foldhaus_memory.h @@ -10,8 +10,8 @@ PLATFORM_ALLOC(Win32Alloc) { - u8* Result = (u8*)VirtualAlloc(NULL, Size, - MEM_COMMIT | MEM_RESERVE, + u8* Result = (u8*)VirtualAlloc(NULL, Size, + MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); return Result; } @@ -21,7 +21,7 @@ PLATFORM_FREE(Win32Free) b32 Result = VirtualFree(Base, 0, MEM_RELEASE); if (!Result) { - s32 Error = WSAGetLastError(); + s32 Error = GetLastError(); // TODO(Peter): I'm waiting to see an error actually occur here // to know what it could possibly be. InvalidCodePath; From 23c9dabfbb1db2cfa3c69103924da912f1d504ef Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 20 Jun 2020 17:05:58 -0700 Subject: [PATCH 06/43] A bit more cleanup around sacn and assemblies. --- src/app/foldhaus_app.cpp | 2 +- src/app/foldhaus_assembly.cpp | 21 ++++++++------------ src/app/foldhaus_interface.cpp | 1 - src/app/panels/foldhaus_panel_hierarchy.h | 2 +- src/app/sacn/sacn.h | 24 +++++++++++------------ 5 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index a202b38..f6c4828 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -182,7 +182,7 @@ INITIALIZE_APPLICATION(InitializeApplication) #if 1 string SculpturePath = MakeStringLiteral("data/blumen_lumen_v2.fold"); - LoadAssembly(State, Context, SculpturePath); + LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, SculpturePath, State->GlobalLog); #endif State->PixelsToWorldScale = .01f; diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index 97cdbf2..0ba40b2 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -5,8 +5,6 @@ // #ifndef FOLDHAUS_ASSEMBLY_CPP -// Led System - internal led_system LedSystemInitialize(platform_memory_handler PlatformMemory, u32 BuffersMax) { @@ -78,8 +76,6 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) Buffer->Positions[Led] = Position; } -// Assembly - internal void ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition, led_system* LedSystem) { @@ -114,37 +110,36 @@ ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 Roo static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, 0, 75, 0} }; s32 TempAssemblyOffsetsCount = 3; -// TODO(Peter): Don't reference State, pull back to the Led buffer and Assembly Array internal void -LoadAssembly (app_state* State, context Context, string Path) +LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, memory_arena* Scratch, context Context, string Path, event_log* GlobalLog) { platform_memory_result AssemblyFile = ReadEntireFile(Context, Path); if (AssemblyFile.Error == PlatformMemory_NoError && AssemblyFile.Size > 0) { string AssemblyFileText = MakeString((char*)AssemblyFile.Base); - Assert(State->Assemblies.Count < State->Assemblies.CountMax); - assembly* NewAssembly = &State->Assemblies.Values[State->Assemblies.Count++]; + Assert(Assemblies->Count < Assemblies->CountMax); + assembly* NewAssembly = &Assemblies->Values[Assemblies->Count++]; s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\'); string FileName = Substring(Path, IndexOfLastSlash + 1); NewAssembly->Arena.PlatformMemory = Context.PlatformMemory; - if (ParseAssemblyFile(NewAssembly, AssemblyFileText, &State->Transient)) + if (ParseAssemblyFile(NewAssembly, AssemblyFileText, Scratch)) { - v4 Offset = TempAssemblyOffsets[State->Assemblies.Count % TempAssemblyOffsetsCount]; - ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, &State->LedSystem); + v4 Offset = TempAssemblyOffsets[Assemblies->Count % TempAssemblyOffsetsCount]; + ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, LedSystem); PlatformFree(Context.PlatformMemory, AssemblyFile.Base, AssemblyFile.Size); } else { FreeMemoryArena(&NewAssembly->Arena); - State->Assemblies.Count -= 1; + Assemblies->Count -= 1; } } else { - LogError(State->GlobalLog, "Unable to load assembly file"); + LogError(GlobalLog, "Unable to load assembly file"); } } diff --git a/src/app/foldhaus_interface.cpp b/src/app/foldhaus_interface.cpp index 823b652..b69ca36 100644 --- a/src/app/foldhaus_interface.cpp +++ b/src/app/foldhaus_interface.cpp @@ -477,6 +477,5 @@ DrawAllPanels(panel_layout PanelLayout, render_command_buffer* RenderBuffer, mou } } - #define FOLDHAUS_INTERFACE_CPP #endif // FOLDHAUS_INTERFACE_CPP \ No newline at end of file diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index c2d1ddb..cdb9e9a 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -71,7 +71,7 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende b32 Success = GetFilePath(Context, &FilePath, "Foldhaus Files\0*.fold\0\0"); if (Success) { - LoadAssembly(State, Context, FilePath); + LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, FilePath, State->GlobalLog); } } diff --git a/src/app/sacn/sacn.h b/src/app/sacn/sacn.h index 4c4bc59..47adaa2 100644 --- a/src/app/sacn/sacn.h +++ b/src/app/sacn/sacn.h @@ -12,7 +12,7 @@ #define IP_ADDRESS_BYTES 16 #define STARTCODE_DMX 0 -/* +/* * a description of the address space being used */ #define PREAMBLE_SIZE_ADDR 0 @@ -52,7 +52,7 @@ /* * data definitions */ -#define ACN_IDENTIFIER "ASC-E1.17\0\0\0" +#define ACN_IDENTIFIER "ASC-E1.17\0\0\0" #define ROOT_VECTOR 4 #define FRAMING_VECTOR 2 #define DMP_VECTOR 2 @@ -159,7 +159,7 @@ VHD_PackLength_(u8* Buffer, u32 Length, b32 IncludeLength) return Cursor; } -internal cid +internal cid StringToCID_ (const char* String) { cid Result = {}; @@ -193,11 +193,11 @@ StringToCID_ (const char* String) Src++; } - return Result; + return Result; } internal void -InitStreamHeader (u8* Buffer, s32 BufferSize, +InitStreamHeader (u8* Buffer, s32 BufferSize, u16 SlotCount, u8 StartCode, u16 Universe, @@ -220,8 +220,8 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, // TODO(Peter): If you never use this anywhere else, go back and remove the parameters VHD_PackFlags_(Cursor, false, false, false); - Cursor = VHD_PackLength_(Cursor, - STREAM_HEADER_SIZE - RLP_PREAMBLE_SIZE + SlotCount, + Cursor = VHD_PackLength_(Cursor, + STREAM_HEADER_SIZE - RLP_PREAMBLE_SIZE + SlotCount, false); // root vector @@ -234,8 +234,8 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, } VHD_PackFlags_(Cursor, false, false, false); - Cursor = VHD_PackLength_(Cursor, - STREAM_HEADER_SIZE - FRAMING_FLAGS_AND_LENGTH_ADDR + SlotCount, + Cursor = VHD_PackLength_(Cursor, + STREAM_HEADER_SIZE - FRAMING_FLAGS_AND_LENGTH_ADDR + SlotCount, false); // framing vector @@ -263,7 +263,7 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, Cursor = PackB2(Cursor, Universe); VHD_PackFlags_(Cursor, false, false, false); - Cursor = VHD_PackLength_(Cursor, + Cursor = VHD_PackLength_(Cursor, STREAM_HEADER_SIZE - DMP_FLAGS_AND_LENGTH_ADDR + SlotCount, false); @@ -292,7 +292,7 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, // internal streaming_acn -InitializeSACN ( context Context) +InitializeSACN (context Context) { streaming_acn SACN = {}; @@ -313,7 +313,7 @@ internal void SACNUpdateSequence (streaming_acn* SACN) { // Never use 0 after the first one - if (++SACN->SequenceIterator == 0) + if (++SACN->SequenceIterator == 0) { ++SACN->SequenceIterator; } From a0072cd57bdd55911d59b666364009ef174d3150 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sun, 21 Jun 2020 21:26:13 -0700 Subject: [PATCH 07/43] removed foldhaus_debug_visuals.h Cleaned up assembly parsing. --- src/app/foldhaus_app.cpp | 13 ++-- src/app/foldhaus_debug_visuals.h | 126 ------------------------------- src/gs_libs/gs_string.h | 2 +- 3 files changed, 6 insertions(+), 135 deletions(-) delete mode 100644 src/app/foldhaus_debug_visuals.h diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index f6c4828..57ce966 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -181,7 +181,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->LedSystem = LedSystemInitialize(Context.PlatformMemory, 128); #if 1 - string SculpturePath = MakeStringLiteral("data/blumen_lumen_v2.fold"); + string SculpturePath = MakeStringLiteral("data/radialumia_v2.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, SculpturePath, State->GlobalLog); #endif @@ -213,9 +213,7 @@ INITIALIZE_APPLICATION(InitializeApplication) InitializePanelSystem(&State->PanelSystem); panel* Panel = TakeNewPanel(&State->PanelSystem); - SplitPanelVertically(Panel, .5f, &State->PanelSystem); - SetPanelDefinition(&Panel->Left->Panel, PanelType_ProfilerView, State); - SetPanelDefinition(&Panel->Right->Panel, PanelType_SculptureView, State); + SetPanelDefinition(Panel, PanelType_SculptureView, State); } internal void @@ -378,8 +376,6 @@ UPDATE_AND_RENDER(UpdateAndRender) assembly* Assembly = &State->Assemblies.Values[AssemblyIndex]; led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly->LedBufferIndex); - arena_snapshot ResetAssemblyMemorySnapshot = TakeSnapshotOfArena(&State->Transient); - for (u32 Layer = 0; Layer < CurrentBlocksMax; Layer++) { if (!CurrentBlocksFilled[Layer]) { continue; } @@ -463,11 +459,11 @@ UPDATE_AND_RENDER(UpdateAndRender) }break; } } - - ClearArenaToSnapshot(&State->Transient, ResetAssemblyMemorySnapshot); } } + // Skipped for performance at the moment +#if 0 s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; for (u32 i = 0; i < State->Assemblies.Count; i++) @@ -504,6 +500,7 @@ UPDATE_AND_RENDER(UpdateAndRender) InvalidDefaultCase; } } +#endif PushRenderOrthographic(RenderBuffer, 0, 0, gs_Width(State->WindowBounds), gs_Height(State->WindowBounds)); PushRenderClearScreen(RenderBuffer); diff --git a/src/app/foldhaus_debug_visuals.h b/src/app/foldhaus_debug_visuals.h deleted file mode 100644 index 3158e78..0000000 --- a/src/app/foldhaus_debug_visuals.h +++ /dev/null @@ -1,126 +0,0 @@ -// -// File: foldhaus_debug_visuals.h -// Author: Peter Slattery -// Creation Date: 2020-01-01 -// -#ifndef FOLDHAUS_DEBUG_VISUALS_H - -internal void -DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_config Interface, r32 WindowWidth, r32 WindowHeight, r32 DeltaTime, app_state* State, camera Camera, mouse_state Mouse, memory_arena* Transient) -{ - DEBUG_TRACK_SCOPE(DrawDebugInterface); - - v2 TopOfDebugView = v2{StartX, WindowHeight - (NewLineYOffset(*Interface.Font) + 5)}; - v2 TopOfScreenLinePos = TopOfDebugView; - - string DebugString = InitializeEmptyString(PushArray(Transient, char, 256), 256); - - if (GlobalDebugServices->Interface.ShowCameraMouse) - { - PushRenderQuad2D(RenderBuffer, - v2{TopOfDebugView.x, TopOfDebugView.y - 500}, - v2{TopOfDebugView.x + 700, TopOfDebugView.y}, - v4{0, 0, 0, .8f}); - } - - r32 FramesPerSecond = 1.0f / DeltaTime; - - PrintF(&DebugString, "Framerate: %.*f s %d fps | Modes: %d Memory Used: %d / %d | Commands: %d | HI SAM!!!! ", - 5, DeltaTime, - (u32)FramesPerSecond, - State->Modes.ActiveModesCount, - State->Modes.Arena.TotalUsed, - State->Modes.Arena.TotalSize, - State->CommandQueue.Used); - DrawString(RenderBuffer, DebugString, Interface.Font, TopOfScreenLinePos, WhiteV4); - - v2 ButtonDim = v2{200, (r32)NewLineYOffset(*Interface.Font) + 10}; - TopOfScreenLinePos.y -= ButtonDim.y + 10; - v2 ButtonPos = TopOfScreenLinePos; - button_result CameraBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, - MakeStringLiteral("Camera"), Interface, Mouse); - - ButtonPos.x += ButtonDim.x + 10; - button_result ScopeTimeBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, - MakeStringLiteral("Scope Time"), Interface, Mouse); - ButtonPos.x += ButtonDim.x + 10; - button_result RenderSculptureBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, - MakeStringLiteral("Visualize"), Interface, Mouse); - - ButtonPos.x += ButtonDim.x + 10; - - string SACNButtonString; - if (GlobalDebugServices->Interface.SendSACNData) - { - SACNButtonString = MakeStringLiteral("Turn SACN Off"); - } - else - { - SACNButtonString = MakeStringLiteral("Turn SACN On"); - } - - button_result SendSACNDataBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, - SACNButtonString, Interface, Mouse); - - TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font) + 10; - - if (CameraBtn.Pressed) - { - GlobalDebugServices->Interface.ShowCameraMouse = !GlobalDebugServices->Interface.ShowCameraMouse; - } - - if (ScopeTimeBtn.Pressed) - { - GlobalDebugServices->Interface.ShowTrackedScopes = !GlobalDebugServices->Interface.ShowTrackedScopes; - } - - if (RenderSculptureBtn.Pressed) - { - GlobalDebugServices->Interface.RenderSculpture = - !GlobalDebugServices->Interface.RenderSculpture; - } - - if (SendSACNDataBtn.Pressed) - { - GlobalDebugServices->Interface.SendSACNData = !GlobalDebugServices->Interface.SendSACNData; - } - - if (GlobalDebugServices->Interface.ShowCameraMouse) - { - PrintF(&DebugString, "Camera x=%.*f y=%.*f z=%.*f LookAt x=%.*f y=%.*f z=%.*f", - 3, Camera.Position.x, - 3, Camera.Position.y, - 3, Camera.Position.z, - 3, Camera.LookAt.x, - 3, Camera.LookAt.y, - 3, Camera.LookAt.z); - DrawString(RenderBuffer, DebugString, Interface.Font, TopOfScreenLinePos, v4{1.0f, 1.0f, 1.0f, 1.0f}); - TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); - - b32 LeftButtonIsDown = (Mouse.LeftButtonState & KeyState_IsDown) > 0; - b32 LeftButtonWasDown = (Mouse.LeftButtonState & KeyState_WasDown) > 0; - - s32 MousePrecision = 0; - PrintF(&DebugString, "Mouse Pos: (%.*f, %.*f) Down: (%.*f, %.*f) State: %s %s", - MousePrecision, Mouse.Pos.x, - MousePrecision, Mouse.Pos.y, - MousePrecision, Mouse.DownPos.x, - MousePrecision, Mouse.DownPos.y, - (LeftButtonIsDown ? "Is Down" : "Is Not Down"), - (LeftButtonWasDown ? "Was Down" : "Was Not Down")); - DrawString(RenderBuffer, DebugString, Interface.Font, - TopOfScreenLinePos, WhiteV4); - TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); - - PrintF(&DebugString, "Render Buffer: %d / %d (at this point)", - RenderBuffer->CommandMemoryUsed, - RenderBuffer->CommandMemorySize); - DrawString(RenderBuffer, DebugString, Interface.Font, - TopOfScreenLinePos, WhiteV4); - TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); - } -} - - -#define FOLDHAUS_DEBUG_VISUALS_H -#endif // FOLDHAUS_DEBUG_VISUALS_H \ No newline at end of file diff --git a/src/gs_libs/gs_string.h b/src/gs_libs/gs_string.h index edd80c7..9b3f4c0 100644 --- a/src/gs_libs/gs_string.h +++ b/src/gs_libs/gs_string.h @@ -448,7 +448,7 @@ static bool IsNumeric (char C) } static bool IsNumericExtended (char C) { - return (IsNumeric(C) || (C == 'x') || (C == 'f') || (C == '.')); + return (IsNumeric(C) || (C == '-') || (C == 'x') || (C == 'f') || (C == '.')); } static bool IsAlphaNumeric (char C) { From dc25b268f7faf4d732cde48eaf31a5e9b06cebd2 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sun, 21 Jun 2020 21:59:42 -0700 Subject: [PATCH 08/43] compressed some ui drawing code. --- src/app/foldhaus_app.cpp | 34 +++++++------- src/app/foldhaus_app.h | 1 - src/app/interface.h | 47 +++++++++++++++++-- .../foldhaus_panel_animation_timeline.h | 6 +-- src/app/panels/foldhaus_panel_hierarchy.h | 37 ++++++--------- src/app/panels/foldhaus_panel_node_graph.h | 10 ++-- src/gs_libs/gs_font.h | 4 +- 7 files changed, 83 insertions(+), 56 deletions(-) diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 57ce966..1c429bb 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -139,7 +139,7 @@ INITIALIZE_APPLICATION(InitializeApplication) AddCodepointToFont(Font, Codepoint, 0, 0, CodepointW, CodepointH, CodepointX, CodepointY); } - State->Interface.Font = Font; + State->Interface_.Style.Font = Font; Font->BitmapTextureHandle = Context.PlatformGetGPUTextureHandle(Font->BitmapMemory, Font->BitmapWidth, Font->BitmapHeight); @@ -150,23 +150,21 @@ INITIALIZE_APPLICATION(InitializeApplication) } } - State->Interface.FontSize = FontSize; - State->Interface.PanelBGColors[0] = v4{.3f, .3f, .3f, 1}; - State->Interface.PanelBGColors[1] = v4{.4f, .4f, .4f, 1}; - State->Interface.PanelBGColors[2] = v4{.5f, .5f, .5f, 1}; - State->Interface.PanelBGColors[3] = v4{.6f, .6f, .6f, 1}; - State->Interface.ButtonColor_Inactive = BlackV4; - State->Interface.ButtonColor_Active = v4{.1f, .1f, .1f, 1}; - State->Interface.ButtonColor_Selected = v4{.1f, .1f, .3f, 1}; - State->Interface.TextColor = WhiteV4; - State->Interface.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; - State->Interface.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; - State->Interface.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; - State->Interface.ListBGSelected = v4{.44f, .44f, .44f, 1.f }; - State->Interface.Margin = v2{5, 5}; - State->Interface.RowHeight = State->Interface.Font->PixelHeight + 2 * State->Interface.Margin.y; - - State->Interface_.Style = State->Interface; + State->Interface_.Style.FontSize = FontSize; + State->Interface_.Style.PanelBGColors[0] = v4{.3f, .3f, .3f, 1}; + State->Interface_.Style.PanelBGColors[1] = v4{.4f, .4f, .4f, 1}; + State->Interface_.Style.PanelBGColors[2] = v4{.5f, .5f, .5f, 1}; + State->Interface_.Style.PanelBGColors[3] = v4{.6f, .6f, .6f, 1}; + State->Interface_.Style.ButtonColor_Inactive = BlackV4; + State->Interface_.Style.ButtonColor_Active = v4{.1f, .1f, .1f, 1}; + State->Interface_.Style.ButtonColor_Selected = v4{.1f, .1f, .3f, 1}; + State->Interface_.Style.TextColor = WhiteV4; + State->Interface_.Style.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; + State->Interface_.Style.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; + State->Interface_.Style.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; + State->Interface_.Style.ListBGSelected = v4{.44f, .44f, .44f, 1.f }; + State->Interface_.Style.Margin = v2{5, 5}; + State->Interface_.Style.RowHeight = ui_GetTextLineHeight(State->Interface_); State->SACN = InitializeSACN(Context); State->NetworkProtocolHeaderSize = STREAM_HEADER_SIZE; diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 6fe067c..c0fbc66 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -72,7 +72,6 @@ struct app_state text_entry ActiveTextEntry; ui_interface Interface_; - interface_config Interface; animation_system AnimationSystem; gs_list_handle SelectedAnimationBlockHandle; diff --git a/src/app/interface.h b/src/app/interface.h index 653138f..33a50ac 100644 --- a/src/app/interface.h +++ b/src/app/interface.h @@ -339,10 +339,18 @@ ui_LayoutRemaining(ui_layout Layout) } return Result; } + // // Drawing Functions // +static r32 +ui_GetTextLineHeight(ui_interface Interface) +{ + r32 Result = Interface.Style.Font->PixelHeight + (2 * Interface.Style.Margin.y); + return Result; +} + static void ui_FillRect(ui_interface* Interface, rect Bounds, v4 Color) { @@ -430,6 +438,37 @@ ui_Button(ui_interface* Interface, string Text, rect Bounds) return ui_Button(Interface, Text, Bounds, BGColor, HoverColor, SelectedColor); } +struct list_item_colors +{ + 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; +} + +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; +} + +static b32 +ui_ListButton(ui_interface* Interface, string Text, rect Bounds, u32 ListItemIndex) +{ + list_item_colors Colors = ui_GetListItemColors(Interface, ListItemIndex); + return ui_Button(Interface, Text, Bounds, Colors.Hover, Colors.Selected, Colors.BGColor); +} + static b32 ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text, v4 BGColor, v4 HoverColor, v4 SelectColor) { @@ -450,11 +489,11 @@ ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text) return ui_LayoutButton(Interface, Layout, Text, BGColor, HoverColor, SelectedColor); } -inline v4 -ui_GetListItemBGColor(interface_config Style, u32 ElementIndex) +static b32 +ui_LayoutListButton(ui_interface* Interface, ui_layout* Layout, string Text, u32 ListItemIndex) { - v4 Result = Style.ListBGColors[ElementIndex % LIST_BG_COLORS_COUNT]; - return Result; + list_item_colors Colors = ui_GetListItemColors(Interface, ListItemIndex); + return ui_LayoutButton(Interface, Layout, Text, Colors.Hover, Colors.Selected, Colors.BGColor); } static b32 diff --git a/src/app/panels/foldhaus_panel_animation_timeline.h b/src/app/panels/foldhaus_panel_animation_timeline.h index b4a2dfe..ff1999f 100644 --- a/src/app/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/panels/foldhaus_panel_animation_timeline.h @@ -317,7 +317,7 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu r32 FramePercent = FrameToPercentRange(Frame, VisibleFrames); r32 FrameX = GSLerp(BarBounds.Min.x, BarBounds.Max.x, FramePercent); v2 FrameTextPos = v2{FrameX, BarBounds.Min.y + 2}; - DrawString(RenderBuffer, TempString, State->Interface.Font, FrameTextPos, WhiteV4); + DrawString(RenderBuffer, TempString, State->Interface_.Style.Font, FrameTextPos, WhiteV4); } // Time Slider @@ -335,7 +335,7 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu PushRenderQuad2D(RenderBuffer, HeadMin, HeadMax, TimeSliderColor); PrintF(&TempString, "%d", AnimationSystem->CurrentFrame); - DrawString(RenderBuffer, TempString, State->Interface.Font, HeadMin + v2{6, 4}, WhiteV4); + DrawString(RenderBuffer, TempString, State->Interface_.Style.Font, HeadMin + v2{6, 4}, WhiteV4); } } @@ -418,7 +418,7 @@ DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_b { PushRenderBoundingBox2D(RenderBuffer, gs_RectExpand(LayerBounds), 1, WhiteV4); } - DrawString(RenderBuffer, Layer->Name, State->Interface.Font, LayerTextPos, WhiteV4); + DrawString(RenderBuffer, Layer->Name, State->Interface_.Style.Font, LayerTextPos, WhiteV4); } } diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index cdb9e9a..4808cdb 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -30,42 +30,40 @@ internal void HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) { ui_layout Layout = ui_CreateLayout(State->Interface_, PanelBounds); - v4 ListItemHover = State->Interface_.Style.ListBGHover; - v4 ListItemSelected = State->Interface_.Style.ListBGSelected; - string TempString = PushString(&State->Transient, 256); - u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1; - u32 LinesDrawn = 0; u32 AssembliesToDraw = GSMin(LineCount, State->Assemblies.Count); + rect* LineBounds = PushArray(&State->Transient, rect, LineCount); + + // Fill in alternating color rows for the backgrounds + for (u32 Line = 0; Line < LineCount; Line++) + { + LineBounds[Line] = ui_ReserveElementBounds(&Layout); + v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, Line); + ui_FillRect(&State->Interface_, LineBounds[Line], ListItemBGColor); + } + for (u32 AssemblyIndex = 0; AssemblyIndex < AssembliesToDraw; AssemblyIndex++) { - rect Bounds = ui_ReserveElementBounds(&Layout); - v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, AssemblyIndex); - ui_FillRect(&State->Interface_, Bounds, ListItemBGColor); - assembly Assembly = State->Assemblies.Values[AssemblyIndex]; PrintF(&TempString, "%S", Assembly.Name); - ui_layout ItemLayout = ui_CreateLayout(State->Interface_, Bounds); + ui_layout ItemLayout = ui_CreateLayout(State->Interface_, LineBounds[AssemblyIndex]); ui_StartRow(&ItemLayout, 2); { ui_LayoutDrawString(&State->Interface_, &ItemLayout, TempString, State->Interface_.Style.TextColor); - if (ui_LayoutButton(&State->Interface_, &ItemLayout, MakeStringLiteral("X"), ListItemBGColor, ListItemHover, ListItemSelected)) + if (ui_LayoutListButton(&State->Interface_, &ItemLayout, MakeStringLiteral("X"), AssemblyIndex)) { UnloadAssembly(AssemblyIndex, State, Context); } } ui_EndRow(&ItemLayout); - - LinesDrawn += 1; } - if (LinesDrawn < LineCount) + if (AssembliesToDraw < LineCount) { - v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, LinesDrawn++); PrintF(&TempString, "+ Add Assembly"); - if (ui_LayoutButton(&State->Interface_, &Layout, TempString, ListItemBGColor, ListItemHover, ListItemSelected)) + if (ui_ListButton(&State->Interface_, TempString, LineBounds[AssembliesToDraw], AssembliesToDraw)) { string FilePath = PushString(&State->Transient, 256); b32 Success = GetFilePath(Context, &FilePath, "Foldhaus Files\0*.fold\0\0"); @@ -74,13 +72,6 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, FilePath, State->GlobalLog); } } - - for (; LinesDrawn < LineCount; LinesDrawn++) - { - rect Bounds = ui_ReserveElementBounds(&Layout); - ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, LinesDrawn); - ui_FillRect(&State->Interface_, Bounds, ListItemBGColor); - } } } diff --git a/src/app/panels/foldhaus_panel_node_graph.h b/src/app/panels/foldhaus_panel_node_graph.h index 12ae92d..332257c 100644 --- a/src/app/panels/foldhaus_panel_node_graph.h +++ b/src/app/panels/foldhaus_panel_node_graph.h @@ -436,7 +436,7 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf r32 NodeWidth = 150; r32 LayerDistance = 100; - r32 LineHeight = (State->Interface.Font->PixelHeight + (2 * State->Interface.Margin.y)); + r32 LineHeight = ui_GetTextLineHeight(State->Interface_); if (GraphState->LayoutIsDirty) { @@ -477,7 +477,7 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf { visual_node VisualNode = GraphState->Layout.VisualNodes[i]; gs_list_handle NodeHandle = State->NodeWorkspace.SortedNodeHandles[i]; - DrawNode(VisualNode.Position + GraphState->ViewOffset, VisualNode.Spec, NodeHandle, NodeWidth, LineHeight, State->Interface, RenderBuffer, Mouse, &State->Transient); + DrawNode(VisualNode.Position + GraphState->ViewOffset, VisualNode.Spec, NodeHandle, NodeWidth, LineHeight, State->Interface_.Style, RenderBuffer, Mouse, &State->Transient); } for (u32 p = 0; p < GraphState->Layout.VisualPortsCount; p++) @@ -514,17 +514,17 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf List.ListBounds = NodeSelectionWindowBounds; List.ListElementDimensions = v2{ gs_Width(NodeSelectionWindowBounds), - (r32)(State->Interface.Font->PixelHeight + 8), + ui_GetTextLineHeight(State->Interface_) }; List.ElementLabelIndent = v2{10, 4}; string TitleString = MakeStringLiteral("Available Nodes"); - DrawListElement(TitleString, &List, Mouse, RenderBuffer, State->Interface); + DrawListElement(TitleString, &List, Mouse, RenderBuffer, State->Interface_.Style); for (u32 i = 0; i < NodeType_Count; i++) { node_specification_ Spec = NodeSpecifications[i]; - rect ElementBounds = DrawListElement(Spec.Identifier, &List, Mouse, RenderBuffer, State->Interface); + rect ElementBounds = DrawListElement(Spec.Identifier, &List, Mouse, RenderBuffer, State->Interface_.Style); if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && gs_PointIsInRect(Mouse.DownPos, ElementBounds)) diff --git a/src/gs_libs/gs_font.h b/src/gs_libs/gs_font.h index 7570039..c901bf7 100644 --- a/src/gs_libs/gs_font.h +++ b/src/gs_libs/gs_font.h @@ -82,7 +82,7 @@ GetNextCodepointOffset (bitmap_font* Font, u32* X, u32* Y) } internal void -AddCodepointToFont (bitmap_font* Font, char Codepoint, +AddCodepointToFont (bitmap_font* Font, char Codepoint, s32 XOffset, s32 YOffset, s32 Width, s32 Height, s32 BitmapX, s32 BitmapY) { @@ -100,7 +100,7 @@ AddCodepointToFont (bitmap_font* Font, char Codepoint, Value->BitmapX = BitmapX; Value->BitmapY = BitmapY; Value->UVMin = v2{(r32)BitmapX / (r32)Font->BitmapWidth, (r32)BitmapY / (r32)Font->BitmapHeight}; - Value->UVMax = + Value->UVMax = Value->UVMin + v2{(r32)Width / (r32)Font->BitmapWidth, (r32)Height / (r32)Font->BitmapHeight}; } From e3d7a90a13f36d89205e53caa129b9f1897c0592 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 22 Jun 2020 17:39:58 -0700 Subject: [PATCH 09/43] app_state.Interface_ -> app_state.Interface --- src/app/foldhaus_app.cpp | 36 +++++++++---------- src/app/foldhaus_app.h | 2 +- src/app/foldhaus_interface.cpp | 4 +-- .../foldhaus_panel_animation_timeline.h | 8 ++--- src/app/panels/foldhaus_panel_hierarchy.h | 15 ++++---- src/app/panels/foldhaus_panel_node_graph.h | 10 +++--- src/app/panels/foldhaus_panel_profiler.h | 20 +++++------ 7 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 1c429bb..99b0246 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -139,7 +139,7 @@ INITIALIZE_APPLICATION(InitializeApplication) AddCodepointToFont(Font, Codepoint, 0, 0, CodepointW, CodepointH, CodepointX, CodepointY); } - State->Interface_.Style.Font = Font; + State->Interface.Style.Font = Font; Font->BitmapTextureHandle = Context.PlatformGetGPUTextureHandle(Font->BitmapMemory, Font->BitmapWidth, Font->BitmapHeight); @@ -150,21 +150,21 @@ INITIALIZE_APPLICATION(InitializeApplication) } } - State->Interface_.Style.FontSize = FontSize; - State->Interface_.Style.PanelBGColors[0] = v4{.3f, .3f, .3f, 1}; - State->Interface_.Style.PanelBGColors[1] = v4{.4f, .4f, .4f, 1}; - State->Interface_.Style.PanelBGColors[2] = v4{.5f, .5f, .5f, 1}; - State->Interface_.Style.PanelBGColors[3] = v4{.6f, .6f, .6f, 1}; - State->Interface_.Style.ButtonColor_Inactive = BlackV4; - State->Interface_.Style.ButtonColor_Active = v4{.1f, .1f, .1f, 1}; - State->Interface_.Style.ButtonColor_Selected = v4{.1f, .1f, .3f, 1}; - State->Interface_.Style.TextColor = WhiteV4; - State->Interface_.Style.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; - State->Interface_.Style.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; - State->Interface_.Style.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; - State->Interface_.Style.ListBGSelected = v4{.44f, .44f, .44f, 1.f }; - State->Interface_.Style.Margin = v2{5, 5}; - State->Interface_.Style.RowHeight = ui_GetTextLineHeight(State->Interface_); + State->Interface.Style.FontSize = FontSize; + State->Interface.Style.PanelBGColors[0] = v4{.3f, .3f, .3f, 1}; + State->Interface.Style.PanelBGColors[1] = v4{.4f, .4f, .4f, 1}; + State->Interface.Style.PanelBGColors[2] = v4{.5f, .5f, .5f, 1}; + State->Interface.Style.PanelBGColors[3] = v4{.6f, .6f, .6f, 1}; + State->Interface.Style.ButtonColor_Inactive = BlackV4; + State->Interface.Style.ButtonColor_Active = v4{.1f, .1f, .1f, 1}; + State->Interface.Style.ButtonColor_Selected = v4{.1f, .1f, .3f, 1}; + State->Interface.Style.TextColor = WhiteV4; + State->Interface.Style.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; + State->Interface.Style.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; + State->Interface.Style.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; + State->Interface.Style.ListBGSelected = v4{.44f, .44f, .44f, 1.f }; + State->Interface.Style.Margin = v2{5, 5}; + State->Interface.Style.RowHeight = ui_GetTextLineHeight(State->Interface); State->SACN = InitializeSACN(Context); State->NetworkProtocolHeaderSize = STREAM_HEADER_SIZE; @@ -504,8 +504,8 @@ UPDATE_AND_RENDER(UpdateAndRender) PushRenderClearScreen(RenderBuffer); State->WindowBounds = Context->WindowBounds; - State->Interface_.RenderBuffer = RenderBuffer; - State->Interface_.Mouse = Context->Mouse; + State->Interface.RenderBuffer = RenderBuffer; + State->Interface.Mouse = Context->Mouse; panel_layout PanelsToRender = GetPanelLayout(&State->PanelSystem, State->WindowBounds, &State->Transient); DrawAllPanels(PanelsToRender, RenderBuffer, &Context->Mouse, State, *Context); diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index c0fbc66..4241d77 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -71,7 +71,7 @@ struct app_state input_command_queue CommandQueue; text_entry ActiveTextEntry; - ui_interface Interface_; + ui_interface Interface; animation_system AnimationSystem; gs_list_handle SelectedAnimationBlockHandle; diff --git a/src/app/foldhaus_interface.cpp b/src/app/foldhaus_interface.cpp index b69ca36..b8c762e 100644 --- a/src/app/foldhaus_interface.cpp +++ b/src/app/foldhaus_interface.cpp @@ -422,7 +422,7 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBo { panel_definition Def = GlobalPanelDefs[i]; string DefName = MakeString(Def.PanelName, Def.PanelNameLength); - if (ui_Button(&State->Interface_, DefName, ButtonBounds)) + if (ui_Button(&State->Interface, DefName, ButtonBounds)) { SetPanelDefinition(Panel, i, State); Panel->PanelSelectionMenuOpen = false; @@ -432,7 +432,7 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBo } } - if (ui_Button(&State->Interface_, MakeStringLiteral("Select"), PanelSelectBtnBounds)) + if (ui_Button(&State->Interface, MakeStringLiteral("Select"), PanelSelectBtnBounds)) { Panel->PanelSelectionMenuOpen = !Panel->PanelSelectionMenuOpen; } diff --git a/src/app/panels/foldhaus_panel_animation_timeline.h b/src/app/panels/foldhaus_panel_animation_timeline.h index ff1999f..1f243fa 100644 --- a/src/app/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/panels/foldhaus_panel_animation_timeline.h @@ -317,7 +317,7 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu r32 FramePercent = FrameToPercentRange(Frame, VisibleFrames); r32 FrameX = GSLerp(BarBounds.Min.x, BarBounds.Max.x, FramePercent); v2 FrameTextPos = v2{FrameX, BarBounds.Min.y + 2}; - DrawString(RenderBuffer, TempString, State->Interface_.Style.Font, FrameTextPos, WhiteV4); + DrawString(RenderBuffer, TempString, State->Interface.Style.Font, FrameTextPos, WhiteV4); } // Time Slider @@ -335,7 +335,7 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu PushRenderQuad2D(RenderBuffer, HeadMin, HeadMax, TimeSliderColor); PrintF(&TempString, "%d", AnimationSystem->CurrentFrame); - DrawString(RenderBuffer, TempString, State->Interface_.Style.Font, HeadMin + v2{6, 4}, WhiteV4); + DrawString(RenderBuffer, TempString, State->Interface.Style.Font, HeadMin + v2{6, 4}, WhiteV4); } } @@ -418,7 +418,7 @@ DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_b { PushRenderBoundingBox2D(RenderBuffer, gs_RectExpand(LayerBounds), 1, WhiteV4); } - DrawString(RenderBuffer, Layer->Name, State->Interface_.Style.Font, LayerTextPos, WhiteV4); + DrawString(RenderBuffer, Layer->Name, State->Interface.Style.Font, LayerTextPos, WhiteV4); } } @@ -577,7 +577,7 @@ AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* R animation_timeline_state* TimelineState = (animation_timeline_state*)Panel.PanelStateMemory; gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; - ui_interface* Interface = &State->Interface_; + ui_interface* Interface = &State->Interface; animation_system* AnimationSystem = &State->AnimationSystem; rect TitleBarBounds, PanelContentsBounds; diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index 4808cdb..7b56c47 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -29,7 +29,7 @@ GSMetaTag(panel_type_hierarchy); internal void HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) { - ui_layout Layout = ui_CreateLayout(State->Interface_, PanelBounds); + ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); string TempString = PushString(&State->Transient, 256); u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1; u32 AssembliesToDraw = GSMin(LineCount, State->Assemblies.Count); @@ -39,8 +39,8 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende for (u32 Line = 0; Line < LineCount; Line++) { LineBounds[Line] = ui_ReserveElementBounds(&Layout); - v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, Line); - ui_FillRect(&State->Interface_, LineBounds[Line], ListItemBGColor); + v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface.Style, Line); + ui_FillRect(&State->Interface, LineBounds[Line], ListItemBGColor); } for (u32 AssemblyIndex = 0; AssemblyIndex < AssembliesToDraw; AssemblyIndex++) @@ -48,11 +48,11 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende assembly Assembly = State->Assemblies.Values[AssemblyIndex]; PrintF(&TempString, "%S", Assembly.Name); - ui_layout ItemLayout = ui_CreateLayout(State->Interface_, LineBounds[AssemblyIndex]); + ui_layout ItemLayout = ui_CreateLayout(State->Interface, LineBounds[AssemblyIndex]); ui_StartRow(&ItemLayout, 2); { - ui_LayoutDrawString(&State->Interface_, &ItemLayout, TempString, State->Interface_.Style.TextColor); - if (ui_LayoutListButton(&State->Interface_, &ItemLayout, MakeStringLiteral("X"), AssemblyIndex)) + ui_LayoutDrawString(&State->Interface, &ItemLayout, TempString, State->Interface.Style.TextColor); + if (ui_LayoutListButton(&State->Interface, &ItemLayout, MakeStringLiteral("X"), AssemblyIndex)) { UnloadAssembly(AssemblyIndex, State, Context); } @@ -62,8 +62,9 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende if (AssembliesToDraw < LineCount) { + // NOTE(Peter): Add assembly button PrintF(&TempString, "+ Add Assembly"); - if (ui_ListButton(&State->Interface_, TempString, LineBounds[AssembliesToDraw], AssembliesToDraw)) + if (ui_ListButton(&State->Interface, TempString, LineBounds[AssembliesToDraw], AssembliesToDraw)) { string FilePath = PushString(&State->Transient, 256); b32 Success = GetFilePath(Context, &FilePath, "Foldhaus Files\0*.fold\0\0"); diff --git a/src/app/panels/foldhaus_panel_node_graph.h b/src/app/panels/foldhaus_panel_node_graph.h index 332257c..3bc27c4 100644 --- a/src/app/panels/foldhaus_panel_node_graph.h +++ b/src/app/panels/foldhaus_panel_node_graph.h @@ -436,7 +436,7 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf r32 NodeWidth = 150; r32 LayerDistance = 100; - r32 LineHeight = ui_GetTextLineHeight(State->Interface_); + r32 LineHeight = ui_GetTextLineHeight(State->Interface); if (GraphState->LayoutIsDirty) { @@ -477,7 +477,7 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf { visual_node VisualNode = GraphState->Layout.VisualNodes[i]; gs_list_handle NodeHandle = State->NodeWorkspace.SortedNodeHandles[i]; - DrawNode(VisualNode.Position + GraphState->ViewOffset, VisualNode.Spec, NodeHandle, NodeWidth, LineHeight, State->Interface_.Style, RenderBuffer, Mouse, &State->Transient); + DrawNode(VisualNode.Position + GraphState->ViewOffset, VisualNode.Spec, NodeHandle, NodeWidth, LineHeight, State->Interface.Style, RenderBuffer, Mouse, &State->Transient); } for (u32 p = 0; p < GraphState->Layout.VisualPortsCount; p++) @@ -514,17 +514,17 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf List.ListBounds = NodeSelectionWindowBounds; List.ListElementDimensions = v2{ gs_Width(NodeSelectionWindowBounds), - ui_GetTextLineHeight(State->Interface_) + ui_GetTextLineHeight(State->Interface) }; List.ElementLabelIndent = v2{10, 4}; string TitleString = MakeStringLiteral("Available Nodes"); - DrawListElement(TitleString, &List, Mouse, RenderBuffer, State->Interface_.Style); + DrawListElement(TitleString, &List, Mouse, RenderBuffer, State->Interface.Style); for (u32 i = 0; i < NodeType_Count; i++) { node_specification_ Spec = NodeSpecifications[i]; - rect ElementBounds = DrawListElement(Spec.Identifier, &List, Mouse, RenderBuffer, State->Interface_.Style); + rect ElementBounds = DrawListElement(Spec.Identifier, &List, Mouse, RenderBuffer, State->Interface.Style); if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && gs_PointIsInRect(Mouse.DownPos, ElementBounds)) diff --git a/src/app/panels/foldhaus_panel_profiler.h b/src/app/panels/foldhaus_panel_profiler.h index d4e25aa..a6eadfd 100644 --- a/src/app/panels/foldhaus_panel_profiler.h +++ b/src/app/panels/foldhaus_panel_profiler.h @@ -148,7 +148,7 @@ ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* Render r32 SingleFrameStep = gs_Width(FrameListInner) / DEBUG_FRAME_COUNT; r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2); - ui_OutlineRect(&State->Interface_, FrameListBounds, 2, WhiteV4); + ui_OutlineRect(&State->Interface, FrameListBounds, 2, WhiteV4); if (gs_PointIsInRect(Mouse.Pos, FrameListBounds) && MouseButtonHeldDown(Mouse.LeftButtonState)) { v2 LocalMouse = gs_TransformPointIntoRectSpace(Mouse.Pos, FrameListBounds); @@ -167,28 +167,28 @@ ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* Render s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F); if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; } v4 Color = FrameColors[GSClamp(0, FramesAgo, 3)]; - ui_FillRect(&State->Interface_, PositionedFrameBounds, Color); + ui_FillRect(&State->Interface, PositionedFrameBounds, Color); } debug_frame* VisibleFrame = GetLastDebugFrame(GlobalDebugServices); - ui_layout Layout = ui_CreateLayout(State->Interface_, ProcListBounds); + ui_layout Layout = ui_CreateLayout(State->Interface, ProcListBounds); ui_StartRow(&Layout, 4); { s64 FrameStartCycles = VisibleFrame->FrameStartCycles; s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles; u32 CurrentDebugFrame = GlobalDebugServices->CurrentDebugFrame - 1; PrintF(&String, "Frame %d", CurrentDebugFrame); - ui_LayoutDrawString(&State->Interface_, &Layout, String, WhiteV4); + ui_LayoutDrawString(&State->Interface, &Layout, String, WhiteV4); PrintF(&String, "Total Cycles: %lld", FrameTotalCycles); - ui_LayoutDrawString(&State->Interface_, &Layout, String, WhiteV4); + ui_LayoutDrawString(&State->Interface, &Layout, String, WhiteV4); // NOTE(NAME): Skipping a space for aesthetic reasons, not functional, and could // be removed, or used for something else ui_ReserveElementBounds(&Layout); - if (ui_LayoutButton(&State->Interface_, &Layout, MakeString("Resume Recording"))) + if (ui_LayoutButton(&State->Interface, &Layout, MakeString("Resume Recording"))) { GlobalDebugServices->RecordFrames = true; } @@ -197,11 +197,11 @@ ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* Render ui_StartRow(&Layout, 8); { - if (ui_LayoutButton(&State->Interface_, &Layout, MakeString("Scope View"))) + if (ui_LayoutButton(&State->Interface, &Layout, MakeString("Scope View"))) { GlobalDebugServices->Interface.FrameView = FRAME_VIEW_PROFILER; } - if (ui_LayoutButton(&State->Interface_, &Layout, MakeString("List View"))) + if (ui_LayoutButton(&State->Interface, &Layout, MakeString("List View"))) { GlobalDebugServices->Interface.FrameView = FRAME_VIEW_SCOPE_LIST; } @@ -210,11 +210,11 @@ ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* Render if (GlobalDebugServices->Interface.FrameView == FRAME_VIEW_PROFILER) { - RenderProfiler_ScopeVisualization(&State->Interface_, Layout, VisibleFrame, Memory); + RenderProfiler_ScopeVisualization(&State->Interface, Layout, VisibleFrame, Memory); } else { - RenderProfiler_ListVisualization(&State->Interface_, Layout, VisibleFrame, Memory); + RenderProfiler_ListVisualization(&State->Interface, Layout, VisibleFrame, Memory); } } From 266f42c4f69d097e3aa5481f0501f4a98db53365 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 27 Jun 2020 11:23:50 -0700 Subject: [PATCH 10/43] Whatever I was doing last time + made leds always be camera facing. Probably could use some speed up later on. --- src/app/animation/foldhaus_animation.h | 2 +- src/app/foldhaus_app.cpp | 2 + src/app/foldhaus_app.h | 3 +- src/app/foldhaus_assembly.cpp | 6 +-- src/app/foldhaus_interface.cpp | 2 +- src/app/foldhaus_platform.h | 21 +++------ src/app/foldhaus_renderer.h | 43 ++++++++++--------- .../generated/gs_meta_generated_typeinfo.h | 6 ++- .../foldhaus_panel_animation_timeline.h | 2 +- src/app/panels/foldhaus_panel_dmx_view.h | 8 ++-- src/app/panels/foldhaus_panel_file_view.h | 2 +- src/app/panels/foldhaus_panel_hierarchy.h | 2 +- src/app/panels/foldhaus_panel_node_graph.h | 22 +++++----- src/app/panels/foldhaus_panel_profiler.h | 6 +-- .../panels/foldhaus_panel_sculpture_view.h | 28 +++++++----- src/app/win32_foldhaus_fileio.h | 25 +++++------ src/gs_libs/gs_vector_matrix.h | 19 ++++++-- 17 files changed, 105 insertions(+), 94 deletions(-) diff --git a/src/app/animation/foldhaus_animation.h b/src/app/animation/foldhaus_animation.h index a63e3d1..0c22ee7 100644 --- a/src/app/animation/foldhaus_animation.h +++ b/src/app/animation/foldhaus_animation.h @@ -135,7 +135,7 @@ RemoveAnimationBlock(gs_list_handle AnimationBlockHandle, animation_system* Anim internal u32 AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite) { - // TODO(Peter): If this assert fires its time to make the layer buffer system + // NOTE(Peter): If this assert fires its time to make the layer buffer system // resizable. Assert(AnimationSystem->LayersCount < AnimationSystem->LayersMax); diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 99b0246..c3b9cb1 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -500,6 +500,8 @@ UPDATE_AND_RENDER(UpdateAndRender) } #endif + + PushRenderOrthographic(RenderBuffer, 0, 0, gs_Width(State->WindowBounds), gs_Height(State->WindowBounds)); PushRenderClearScreen(RenderBuffer); diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 4241d77..6d65e46 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -221,8 +221,7 @@ typedef PANEL_INIT_PROC(panel_init_proc); #define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State) typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); -// TODO(Peter): Should be able to take the mouse out of this -#define PANEL_RENDER_PROC(name) void name(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +#define PANEL_RENDER_PROC(name) void name(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) typedef PANEL_RENDER_PROC(panel_render_proc); // NOTE(Peter): This is used by the meta system to generate panel type info diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index 0ba40b2..896d326 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -114,9 +114,9 @@ internal void LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, memory_arena* Scratch, context Context, string Path, event_log* GlobalLog) { platform_memory_result AssemblyFile = ReadEntireFile(Context, Path); - if (AssemblyFile.Error == PlatformMemory_NoError && AssemblyFile.Size > 0) + if (AssemblyFile.Error == PlatformMemory_NoError && AssemblyFile.Data.Size > 0) { - string AssemblyFileText = MakeString((char*)AssemblyFile.Base); + string AssemblyFileText = MakeString((char*)AssemblyFile.Data.Base); Assert(Assemblies->Count < Assemblies->CountMax); assembly* NewAssembly = &Assemblies->Values[Assemblies->Count++]; @@ -129,7 +129,7 @@ LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, memory_arena* S { v4 Offset = TempAssemblyOffsets[Assemblies->Count % TempAssemblyOffsetsCount]; ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, LedSystem); - PlatformFree(Context.PlatformMemory, AssemblyFile.Base, AssemblyFile.Size); + PlatformFree(Context.PlatformMemory, AssemblyFile.Data.Base, AssemblyFile.Data.Size); } else { diff --git a/src/app/foldhaus_interface.cpp b/src/app/foldhaus_interface.cpp index b8c762e..f9345cb 100644 --- a/src/app/foldhaus_interface.cpp +++ b/src/app/foldhaus_interface.cpp @@ -454,7 +454,7 @@ RenderPanel(panel* Panel, rect PanelBounds, rect WindowBounds, render_command_bu }; panel_definition Definition = GlobalPanelDefs[Panel->PanelDefinitionIndex]; - Definition.Render(*Panel, PanelViewBounds, RenderBuffer, State, Context, Mouse); + Definition.Render(*Panel, PanelViewBounds, RenderBuffer, State, Context); PushRenderOrthographic(RenderBuffer, WindowBounds.Min.x, WindowBounds.Min.y, WindowBounds.Max.x, WindowBounds.Max.y); DrawPanelFooter(Panel, RenderBuffer, FooterBounds, Mouse, State); diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index 93dfa64..f8f801c 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -63,12 +63,15 @@ enum platform_memory_error PlatformMemory_UnknownError, // You should implement handling this when you see it }; -// TODO(Peter): Change this to just be data -// - Base, and Size -struct platform_memory_result +struct data { u8* Base; - s32 Size; + u64 Size; +}; + +struct platform_memory_result +{ + data Data; platform_memory_error Error; }; @@ -132,15 +135,6 @@ typedef PLATFORM_SEND_TO(platform_send_to); #define PLATFORM_CLOSE_SOCKET(name) void name(platform_socket_handle SocketHandle) typedef PLATFORM_CLOSE_SOCKET(platform_close_socket); -// File IO - -// TODO(Peter): -struct directory_listing -{ - string Path; - directory_listing* Next; -}; - // Font struct platform_font_info { @@ -285,7 +279,6 @@ ReadEntireFile(context Context, string Path) internal b32 WriteEntireFile(platform_file_handler FileHandler, string Path, u8* Contents, u32 Size) { - // TODO(Peter): Overload to take a data struct instead of Contents And Size b32 Result = FileHandler.WriteEntireFile(Path, Contents, Size); return Result; } diff --git a/src/app/foldhaus_renderer.h b/src/app/foldhaus_renderer.h index b29130f..a0f384b 100644 --- a/src/app/foldhaus_renderer.h +++ b/src/app/foldhaus_renderer.h @@ -20,7 +20,7 @@ inline m44 GetCameraModelViewMatrix (camera Camera) { // Forward - v4 CamForward = V4(Normalize(Camera.Position - Camera.LookAt), 0); + v4 CamForward = V4(Normalize(Camera.Position - Camera.LookAt), 0); // Right v4 CamRight = Normalize(Cross(v4{0, 1, 0, 0}, CamForward)); // Up @@ -64,7 +64,7 @@ GetCameraPerspectiveProjectionMatrix(camera Camera) r32 E = ((2 * Camera.Near) / (Right - Left)); r32 F = ((2 * Camera.Near) / (Top - Bottom)); - m44 PerspectiveProjectionMatrix = + m44 PerspectiveProjectionMatrix = { E, 0, A, 0, 0, F, B, 0, @@ -254,7 +254,7 @@ ResizeBufferIfNecessary(render_command_buffer* Buffer, s32 DataSize) s32 SpaceNeeded = DataSize - SpaceAvailable; // This is known to be positive at this point s32 AdditionSize = GSMax(SpaceNeeded, COMMAND_BUFFER_MIN_GROW_SIZE); s32 NewSize = Buffer->CommandMemorySize + AdditionSize; - Buffer->CommandMemory = Buffer->Realloc(Buffer->CommandMemory, + Buffer->CommandMemory = Buffer->Realloc(Buffer->CommandMemory, Buffer->CommandMemorySize, NewSize); Buffer->CommandMemorySize = NewSize; @@ -297,10 +297,10 @@ internal s32 ThreadSafeIncrementQuadConstructorCount (render_quad_batch_constructor* Constructor) { s32 Result = InterlockedIncrement((long*)&Constructor->Count); - // NOTE(Peter): Have to decrement the value by one. + // 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. + // This was causing the first triangle to be garbage data. Result -= 1; return Result; } @@ -322,8 +322,8 @@ ThreadSafeReserveRangeInQuadConstructor(render_quad_batch_constructor* Construct inline void SetTri3DInBatch (render_quad_batch_constructor* Constructor, s32 TriIndex, - v4 P0, v4 P1, v4 P2, - v2 UV0, v2 UV1, v2 UV2, + v4 P0, v4 P1, v4 P2, + v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { // Vertecies @@ -342,10 +342,11 @@ SetTri3DInBatch (render_quad_batch_constructor* Constructor, s32 TriIndex, Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 2)] = C2; } + inline void -PushTri3DOnBatch (render_quad_batch_constructor* Constructor, - v4 P0, v4 P1, v4 P2, - v2 UV0, v2 UV1, v2 UV2, +PushTri3DOnBatch (render_quad_batch_constructor* Constructor, + v4 P0, v4 P1, v4 P2, + v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { DEBUG_TRACK_FUNCTION; @@ -362,9 +363,9 @@ PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 } internal void -PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, - v4 P0, v4 P1, v4 P2, v4 P3, - v2 UV0, v2 UV1, v2 UV2, v2 UV3, +PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, + v4 P0, v4 P1, v4 P2, v4 P3, + v2 UV0, v2 UV1, v2 UV2, v2 UV3, v4 C0, v4 C1, v4 C2, v4 C3) { Assert(Constructor->Count < Constructor->Max); @@ -379,8 +380,8 @@ PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 } internal void -PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, - v2 P0, v2 P1, v2 P2, v2 P3, +PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, + v2 P0, v2 P1, v2 P2, v2 P3, v2 UV0, v2 UV1, v2 UV2, v2 UV3, v4 C0, v4 C1, v4 C2, v4 C3) { @@ -610,7 +611,7 @@ PushRenderCameraFacingQuad (render_command_buffer* Buffer, v4 Center, v2 Dimensi } internal render_quad_batch_constructor -PushRenderTexture2DBatch(render_command_buffer* Buffer, s32 QuadCount, +PushRenderTexture2DBatch(render_command_buffer* Buffer, s32 QuadCount, render_texture Texture) { s32 DataSize = BATCH_2D_SIZE(QuadCount); @@ -628,15 +629,15 @@ PushRenderTexture2DBatch(render_command_buffer* Buffer, s32 QuadCount, } internal render_quad_batch_constructor -PushRenderTexture2DBatch (render_command_buffer* Buffer, s32 QuadCount, +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, + TextureMemory, + TextureHandle, + TextureWidth, + TextureHeight, TextureBytesPerPixel, TextureStride}; return PushRenderTexture2DBatch(Buffer, QuadCount, Texture); diff --git a/src/app/generated/gs_meta_generated_typeinfo.h b/src/app/generated/gs_meta_generated_typeinfo.h index 9395469..fd1d779 100644 --- a/src/app/generated/gs_meta_generated_typeinfo.h +++ b/src/app/generated/gs_meta_generated_typeinfo.h @@ -59,6 +59,10 @@ static gsm_struct_member_type_info StructMembers_v4[] = { { "g", 1, (u64)&((v4*)0)->g, {}, 0}, { "b", 1, (u64)&((v4*)0)->b, {}, 0}, { "a", 1, (u64)&((v4*)0)->a, {}, 0}, +{ "xy", 2, (u64)&((v4*)0)->xy, {}, 0}, +{ "yz", 2, (u64)&((v4*)0)->yz, {}, 0}, +{ "xyz", 3, (u64)&((v4*)0)->xyz, {}, 0}, +{ "z", 1, (u64)&((v4*)0)->z, {}, 0}, { "E", 1, (u64)&((v4*)0)->E, {}, 0}, }; static gsm_struct_member_type_info StructMembers_pixel[] = { @@ -107,7 +111,7 @@ static gsm_struct_member_type_info StructMembers_multiply_patterns_data[] = { static gsm_struct_type_info StructTypes[] = { { gsm_StructType_solid_color_data, "solid_color_data", 16, 36, 0, 0, StructMembers_solid_color_data, 2 }, -{ gsm_StructType_v4, "v4", 2, 16, 0, 0, StructMembers_v4, 3 }, +{ gsm_StructType_v4, "v4", 2, 16, 0, 0, StructMembers_v4, 5 }, { gsm_StructType_float, "float", 5, 4, 0, 0, 0, 0 }, { gsm_StructType_color_buffer, "color_buffer", 12, 20, 0, 0, StructMembers_color_buffer, 3 }, { gsm_StructType_pixel, "pixel", 5, 3, 0, 0, StructMembers_pixel, 2 }, diff --git a/src/app/panels/foldhaus_panel_animation_timeline.h b/src/app/panels/foldhaus_panel_animation_timeline.h index 1f243fa..0f5e9b6 100644 --- a/src/app/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/panels/foldhaus_panel_animation_timeline.h @@ -572,7 +572,7 @@ DrawAnimationClipsList(rect PanelBounds, ui_interface* Interface, u32 SelectedAn GSMetaTag(panel_render); GSMetaTag(panel_type_animation_timeline); internal void -AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { animation_timeline_state* TimelineState = (animation_timeline_state*)Panel.PanelStateMemory; gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; diff --git a/src/app/panels/foldhaus_panel_dmx_view.h b/src/app/panels/foldhaus_panel_dmx_view.h index b4b5ea4..8d5acce 100644 --- a/src/app/panels/foldhaus_panel_dmx_view.h +++ b/src/app/panels/foldhaus_panel_dmx_view.h @@ -37,7 +37,7 @@ DMXView_Cleanup(panel* Panel, app_state* State) // This won't actually function // :NoLongerFunctionalSACNCodeButThatsOk internal void -DrawSACNUniversePixels (render_command_buffer* RenderBuffer, sacn_universe* ToDraw, +DrawSACNUniversePixels (render_command_buffer* RenderBuffer, sacn_universe* ToDraw, v2 TopLeft, v2 Dimension) { Assert(ToDraw); @@ -69,12 +69,12 @@ DrawSACNUniversePixels (render_command_buffer* RenderBuffer, sacn_universe* ToDr ++PixelsDrawn; } } -#endif +#endif GSMetaTag(panel_render); GSMetaTag(panel_type_dmx_view); internal void -DMXView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +DMXView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { #if 0 // :NoLongerFunctionalSACNCodeButThatsOk @@ -121,7 +121,7 @@ DMXView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffe { v2 TitleDisplayStart = UniverseDisplayTopLeft + v2{0, 12}; PrintF(&TitleBarString, "Universe %d", Universe->Universe); - DrawString(RenderBuffer, TitleBarString, State->Interface.Font, + DrawString(RenderBuffer, TitleBarString, State->Interface.Font, TitleDisplayStart, WhiteV4); } diff --git a/src/app/panels/foldhaus_panel_file_view.h b/src/app/panels/foldhaus_panel_file_view.h index 658435b..bfcd34e 100644 --- a/src/app/panels/foldhaus_panel_file_view.h +++ b/src/app/panels/foldhaus_panel_file_view.h @@ -36,7 +36,7 @@ FileView_Cleanup(panel* Panel, app_state* State) GSMetaTag(panel_render); GSMetaTag(panel_type_file_view); internal void -FileView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +FileView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { rect HeaderBounds = {0}; HeaderBounds.Min = {PanelBounds.Min.x, PanelBounds.Max.y - 32}; diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index 7b56c47..043caa0 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -27,7 +27,7 @@ HierarchyView_Cleanup(panel* Panel, app_state* State) GSMetaTag(panel_render); GSMetaTag(panel_type_hierarchy); internal void -HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); string TempString = PushString(&State->Transient, 256); diff --git a/src/app/panels/foldhaus_panel_node_graph.h b/src/app/panels/foldhaus_panel_node_graph.h index 3bc27c4..80aa175 100644 --- a/src/app/panels/foldhaus_panel_node_graph.h +++ b/src/app/panels/foldhaus_panel_node_graph.h @@ -420,7 +420,7 @@ ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, GSMetaTag(panel_render); GSMetaTag(panel_type_node_graph); internal void -NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { node_graph_state* GraphState = (node_graph_state*)Panel.PanelStateMemory; b32 MouseHandled = false; @@ -477,7 +477,7 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf { visual_node VisualNode = GraphState->Layout.VisualNodes[i]; gs_list_handle NodeHandle = State->NodeWorkspace.SortedNodeHandles[i]; - DrawNode(VisualNode.Position + GraphState->ViewOffset, VisualNode.Spec, NodeHandle, NodeWidth, LineHeight, State->Interface.Style, RenderBuffer, Mouse, &State->Transient); + DrawNode(VisualNode.Position + GraphState->ViewOffset, VisualNode.Spec, NodeHandle, NodeWidth, LineHeight, State->Interface.Style, RenderBuffer, Context.Mouse, &State->Transient); } for (u32 p = 0; p < GraphState->Layout.VisualPortsCount; p++) @@ -487,12 +487,12 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf VisualPort.PortBounds.Max += GraphState->ViewOffset; v4 PortColor = WhiteV4; - if (PointIsInRange(Mouse.Pos, VisualPort.PortBounds.Min, VisualPort.PortBounds.Max)) + if (PointIsInRange(Context.Mouse.Pos, VisualPort.PortBounds.Min, VisualPort.PortBounds.Max)) { PortColor = PinkV4; - if (MouseButtonTransitionedDown(Mouse.LeftButtonState)) + if (MouseButtonTransitionedDown(Context.Mouse.LeftButtonState)) { - BeginConnectNodesOperation(VisualPort, p, Mouse, State); + BeginConnectNodesOperation(VisualPort, p, Context.Mouse, State); MouseHandled = true; } } @@ -519,15 +519,15 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf List.ElementLabelIndent = v2{10, 4}; string TitleString = MakeStringLiteral("Available Nodes"); - DrawListElement(TitleString, &List, Mouse, RenderBuffer, State->Interface.Style); + DrawListElement(TitleString, &List, Context.Mouse, RenderBuffer, State->Interface.Style); for (u32 i = 0; i < NodeType_Count; i++) { node_specification_ Spec = NodeSpecifications[i]; - rect ElementBounds = DrawListElement(Spec.Identifier, &List, Mouse, RenderBuffer, State->Interface.Style); + rect ElementBounds = DrawListElement(Spec.Identifier, &List, Context.Mouse, RenderBuffer, State->Interface.Style); - if (MouseButtonTransitionedDown(Mouse.LeftButtonState) - && gs_PointIsInRect(Mouse.DownPos, ElementBounds)) + if (MouseButtonTransitionedDown(Context.Mouse.LeftButtonState) + && gs_PointIsInRect(Context.Mouse.DownPos, ElementBounds)) { PushNodeOnWorkspace(i, &State->NodeWorkspace, &State->Transient); GraphState->LayoutIsDirty = true; @@ -535,9 +535,9 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf } } - if (!MouseHandled && MouseButtonTransitionedDown(Mouse.LeftButtonState)) + if (!MouseHandled && MouseButtonTransitionedDown(Context.Mouse.LeftButtonState)) { - BeginPanNodeGraph(State, {}, Mouse); + BeginPanNodeGraph(State, {}, Context.Mouse); } } diff --git a/src/app/panels/foldhaus_panel_profiler.h b/src/app/panels/foldhaus_panel_profiler.h index a6eadfd..75c010a 100644 --- a/src/app/panels/foldhaus_panel_profiler.h +++ b/src/app/panels/foldhaus_panel_profiler.h @@ -133,7 +133,7 @@ RenderProfiler_ListVisualization(ui_interface* Interface, ui_layout Layout, debu GSMetaTag(panel_render); GSMetaTag(panel_type_profiler); internal void -ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { memory_arena* Memory = &State->Transient; string String = InitializeEmptyString(PushArray(Memory, char, 256), 256); @@ -149,9 +149,9 @@ ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* Render r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2); ui_OutlineRect(&State->Interface, FrameListBounds, 2, WhiteV4); - if (gs_PointIsInRect(Mouse.Pos, FrameListBounds) && MouseButtonHeldDown(Mouse.LeftButtonState)) + if (gs_PointIsInRect(Context.Mouse.Pos, FrameListBounds) && MouseButtonHeldDown(Context.Mouse.LeftButtonState)) { - v2 LocalMouse = gs_TransformPointIntoRectSpace(Mouse.Pos, FrameListBounds); + v2 LocalMouse = gs_TransformPointIntoRectSpace(Context.Mouse.Pos, FrameListBounds); s32 ClosestFrameIndex = (LocalMouse.x / SingleFrameStep); if (ClosestFrameIndex >= 0 && ClosestFrameIndex < DEBUG_FRAME_COUNT) { diff --git a/src/app/panels/foldhaus_panel_sculpture_view.h b/src/app/panels/foldhaus_panel_sculpture_view.h index 7ff61ee..c605a0f 100644 --- a/src/app/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/panels/foldhaus_panel_sculpture_view.h @@ -71,6 +71,7 @@ SculptureView_Cleanup(panel* Panel, app_state* State) struct draw_leds_job_data { + v4 CameraPosition; v4* Positions; pixel* Colors; s32 StartIndex; @@ -107,18 +108,19 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) v2 UV2 = v2{1, 1}; v2 UV3 = v2{0, 1}; - for (s32 LedIndex = 0; LedIndex < LEDCount; LedIndex++) { pixel PixelColor = Data->Colors[LedIndex]; v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f}; - v4 V4Position = Data->Positions[Data->StartIndex + LedIndex]; - V4Position.w = 0; - v4 P0 = P0_In + V4Position; - v4 P1 = P1_In + V4Position; - v4 P2 = P2_In + V4Position; - v4 P3 = P3_In + V4Position; + v4 Position = Data->Positions[Data->StartIndex + LedIndex]; + m44 FaceCameraMatrix = GetLookAtMatrix(Position, Data->CameraPosition); + v4 PositionOffset = V4(Position.xyz, 0); // Ensure PositionOffset is a vector, not a point + + v4 P0 = (FaceCameraMatrix * P0_In) + PositionOffset; + v4 P1 = (FaceCameraMatrix * P1_In) + PositionOffset; + v4 P2 = (FaceCameraMatrix * P2_In) + PositionOffset; + v4 P3 = (FaceCameraMatrix * P3_In) + PositionOffset; SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); @@ -130,7 +132,7 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) GSMetaTag(panel_render); GSMetaTag(panel_type_sculpture_view); internal void -SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { DEBUG_TRACK_SCOPE(RenderSculpture); @@ -145,9 +147,7 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende PushRenderPerspective(RenderBuffer, PanelBounds.Min.x, PanelBounds.Min.y, PanelWidth, PanelHeight, State->Camera); - // TODO(Peter): Pretty sure this isn't working right now m44 FaceCameraMatrix = GetLookAtMatrix(v4{0, 0, 0, 1}, V4(State->Camera.Position, 1)); - FaceCameraMatrix = FaceCameraMatrix; u32 MaxLEDsPerJob = 2048; render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal); @@ -166,13 +166,19 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende JobData->StartIndex = Job * MaxLEDsPerJob; JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); JobData->Batch = &RenderLEDsBatch; - JobData->FaceCameraMatrix; + //JobData->FaceCameraMatrix = FaceCameraMatrix; JobData->ModelViewMatrix = ModelViewMatrix; JobData->LEDHalfWidth = LEDHalfWidth; + JobData->CameraPosition = V4(State->Camera.Position, 1); + Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, DrawLEDsInBufferRangeJob, JobData, "Sculpture Draw LEDS"); } } + + + + Context.GeneralWorkQueue->DoQueueWorkUntilDone(Context.GeneralWorkQueue, 0); } diff --git a/src/app/win32_foldhaus_fileio.h b/src/app/win32_foldhaus_fileio.h index 2240dbc..46a109a 100644 --- a/src/app/win32_foldhaus_fileio.h +++ b/src/app/win32_foldhaus_fileio.h @@ -19,30 +19,33 @@ PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile) if (FileHandle != INVALID_HANDLE_VALUE) { DWORD FileSize = GetFileSize(FileHandle, NULL); - Result.Base = (u8*)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (Result.Base) + Result.Data.Base = (u8*)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (Result.Data.Base) { - Result.Size = FileSize; + Result.Data.Size = FileSize; s32 BytesRead = 0; - if (ReadFile(FileHandle, (LPVOID)Result.Base, FileSize, (LPDWORD)(&BytesRead), NULL)) + if (ReadFile(FileHandle, (LPVOID)Result.Data.Base, FileSize, (LPDWORD)(&BytesRead), NULL)) { } else { u32 Error = GetLastError(); - // TODO(Peter): :ErrorLogging - Result.Size = 0; + VirtualFree(Result.Data.Base, 0, MEM_RELEASE); + Result.Data.Size = 0; Result.Error = PlatformMemory_UnknownError; } } + else + { + Result.Error = PlatformMemory_UnknownError; + } CloseHandle(FileHandle); } else { Result.Error = PlatformMemory_FileNotFound; - // TODO(Peter): :ErrorLogging } return Result; @@ -138,13 +141,5 @@ PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile) return Result; } -internal directory_listing -EnumerateDirectory(char* Path, memory_arena* Storage) -{ - directory_listing Result = {}; - // TODO(Peter): - return Result; -} - #define WIN32_FOLDHAUS_FILEIO_H #endif // WIN32_FOLDHAUS_FILEIO_H \ No newline at end of file diff --git a/src/gs_libs/gs_vector_matrix.h b/src/gs_libs/gs_vector_matrix.h index 3d1cfbd..1f187bc 100644 --- a/src/gs_libs/gs_vector_matrix.h +++ b/src/gs_libs/gs_vector_matrix.h @@ -75,6 +75,18 @@ union v4 float a; }; + struct + { + v2 xy; + v2 yz; + }; + + struct + { + v3 xyz; + float z; + }; + float E[4]; }; @@ -1271,11 +1283,10 @@ GetLookAtMatrix (v4 Position, v4 Target) v4 Up = Normalize(Cross(Forward, Right)); m44 RotationMatrix = M44( - Right.x, Up.x, Forward.x, 0, - Right.y, Up.y, Forward.y, 0, - Right.z, Up.z, Forward.z, 0, + Right.x, Right.y, Right.z, 0, + Up.x, Up.y, Up.z, 0, + Forward.x, Forward.y, Forward.z, 0, 0, 0, 0, 1); - return RotationMatrix; } From 295a5aaaa0a167b653a7e4ffed5b104694476628 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 27 Jun 2020 14:10:25 -0700 Subject: [PATCH 11/43] Fixed problem where leds were being drawn with the wrong color --- src/app/foldhaus_app.h | 16 ++---- src/app/foldhaus_assembly.cpp | 2 +- src/app/foldhaus_renderer.h | 5 ++ .../panels/foldhaus_panel_sculpture_view.h | 51 ++++++++++++++----- 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 6d65e46..a33d179 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -94,18 +94,10 @@ TestPatternOne(led_buffer* Assembly, r32 Time) for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) { v4 LedPosition = Assembly->Positions[LedIndex]; - if (LedPosition.x < 0) - { - Assembly->Colors[LedIndex].R = 255; - Assembly->Colors[LedIndex].B = 255; - Assembly->Colors[LedIndex].G = 255; - } - else - { - Assembly->Colors[LedIndex].R = 0; - Assembly->Colors[LedIndex].B = 0; - Assembly->Colors[LedIndex].G = 0; - } + float PercentX = GSRemap(LedPosition.x, -150.0f, 150.0f, 0.0f, 1.0f); + float PercentY = GSRemap(LedPosition.y, -150.0f, 150.0f, 0.0f, 1.0f); + Assembly->Colors[LedIndex].R = (u8)(PercentX * 255); + Assembly->Colors[LedIndex].G = (u8)(PercentY * 255); } } diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index 896d326..ea74af2 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -127,7 +127,7 @@ LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, memory_arena* S NewAssembly->Arena.PlatformMemory = Context.PlatformMemory; if (ParseAssemblyFile(NewAssembly, AssemblyFileText, Scratch)) { - v4 Offset = TempAssemblyOffsets[Assemblies->Count % TempAssemblyOffsetsCount]; + v4 Offset = v4{0,0,0,0}; //TempAssemblyOffsets[Assemblies->Count % TempAssemblyOffsetsCount]; ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, LedSystem); PlatformFree(Context.PlatformMemory, AssemblyFile.Data.Base, AssemblyFile.Data.Size); } diff --git a/src/app/foldhaus_renderer.h b/src/app/foldhaus_renderer.h index a0f384b..facfb22 100644 --- a/src/app/foldhaus_renderer.h +++ b/src/app/foldhaus_renderer.h @@ -19,6 +19,7 @@ struct camera inline m44 GetCameraModelViewMatrix (camera Camera) { +#if 0 // Forward v4 CamForward = V4(Normalize(Camera.Position - Camera.LookAt), 0); // Right @@ -42,6 +43,10 @@ GetCameraModelViewMatrix (camera Camera) 0, 0, 1, 0, -X, -Y, -Z, 1 ); +#else + m44 RotationMatrix = GetLookAtMatrix(V4(Camera.Position, 1), V4(Camera.LookAt, 1)); + m44 PositionMatrix = GetPositionM44(V4(Camera.Position, 1)); +#endif m44 ModelViewMatrix = PositionMatrix * RotationMatrix; diff --git a/src/app/panels/foldhaus_panel_sculpture_view.h b/src/app/panels/foldhaus_panel_sculpture_view.h index c605a0f..304fff6 100644 --- a/src/app/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/panels/foldhaus_panel_sculpture_view.h @@ -72,14 +72,10 @@ SculptureView_Cleanup(panel* Panel, app_state* State) struct draw_leds_job_data { v4 CameraPosition; - v4* Positions; - pixel* Colors; + led_buffer LedBuffer; s32 StartIndex; s32 OnePastLastIndex; - render_quad_batch_constructor* Batch; - - m44 FaceCameraMatrix; m44 ModelViewMatrix; r32 LEDHalfWidth; }; @@ -93,6 +89,9 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) s32 LEDCount = Data->OnePastLastIndex - Data->StartIndex; + // TODO(Peter): Why are we doing this here? Shouldn't we be able to tell what the range + // needs to be at the time of creation? That way its all on one thread and we're not + // worried about locking up. quad_batch_constructor_reserved_range BatchReservedRange = ThreadSafeReserveRangeInQuadConstructor(Data->Batch, LEDCount * 2); s32 TrisUsed = 0; @@ -108,12 +107,12 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) v2 UV2 = v2{1, 1}; v2 UV3 = v2{0, 1}; - for (s32 LedIndex = 0; LedIndex < LEDCount; LedIndex++) + for (s32 LedIndex = Data->StartIndex; LedIndex < Data->OnePastLastIndex; LedIndex++) { - pixel PixelColor = Data->Colors[LedIndex]; + pixel PixelColor = Data->LedBuffer.Colors[LedIndex]; v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f}; - v4 Position = Data->Positions[Data->StartIndex + LedIndex]; + v4 Position = Data->LedBuffer.Positions[LedIndex]; m44 FaceCameraMatrix = GetLookAtMatrix(Position, Data->CameraPosition); v4 PositionOffset = V4(Position.xyz, 0); // Ensure PositionOffset is a vector, not a point @@ -152,21 +151,24 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende u32 MaxLEDsPerJob = 2048; render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal); + u32 FocusPixel = 256; + for (u32 i = 0; i < State->Assemblies.Count; i++) { assembly Assembly = State->Assemblies.Values[i]; led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex); u32 JobsNeeded = IntegerDivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); + // TODO(Peter): TEMPORARY - identify this pixel + LedBuffer->Colors[FocusPixel] = pixel{ 255, 0, 255 }; + for (u32 Job = 0; Job < JobsNeeded; Job++) { draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data); - JobData->Positions = LedBuffer->Positions; - JobData->Colors = LedBuffer->Colors; + JobData->LedBuffer = *LedBuffer; JobData->StartIndex = Job * MaxLEDsPerJob; JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); JobData->Batch = &RenderLEDsBatch; - //JobData->FaceCameraMatrix = FaceCameraMatrix; JobData->ModelViewMatrix = ModelViewMatrix; JobData->LEDHalfWidth = LEDHalfWidth; @@ -176,8 +178,33 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende } } + // 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.Min.x, State->WindowBounds.Min.y, + State->WindowBounds.Max.x, State->WindowBounds.Max.y); - + if (State->Assemblies.Count > 0) + { + assembly Assembly = State->Assemblies.Values[0]; + led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex); + + //__debugbreak(); + v4 LedPosition = LedBuffer->Positions[FocusPixel]; + m44 Matrix = GetCameraPerspectiveProjectionMatrix(State->Camera) * GetCameraModelViewMatrix(State->Camera); + v4 LedProjectedPosition = Matrix * LedPosition; + v2 LedOnScreenPosition = LedProjectedPosition.xy; + + string TempString = PushString(&State->Transient, 256); + PrintF(&TempString, "%f %f", LedOnScreenPosition.x, LedOnScreenPosition.y); + DrawString(RenderBuffer, TempString, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4); + + v2 BoxHalfDim = v2{ 25, 25 }; + v2 BoxMin = LedOnScreenPosition - BoxHalfDim; + v2 BoxMax = LedOnScreenPosition + BoxHalfDim; + PushRenderBoundingBox2D(RenderBuffer, BoxMin, BoxMax, 2.0f, TealV4); + } Context.GeneralWorkQueue->DoQueueWorkUntilDone(Context.GeneralWorkQueue, 0); } From 50c2ef929054e2ec27b4b3cf96b96e1a90967bab Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 18 Jul 2020 12:00:14 -0700 Subject: [PATCH 12/43] Cleaning up, converting over to using new gs files. --- build/build_app_msvc_win32_debug.bat | 2 +- src/app/animation/foldhaus_animation.h | 10 +- src/app/assembly_parser.cpp | 140 +- .../{ => deprecated}/foldhaus_default_nodes.h | 8 +- .../foldhaus_panel_node_graph.h | 42 +- .../foldhaus_search_lister.cpp | 12 +- .../{ => deprecated}/foldhaus_search_lister.h | 6 +- .../{ => deprecated}/foldhaus_text_entry.cpp | 46 +- .../{ => deprecated}/foldhaus_text_entry.h | 6 +- .../node/foldhaus_node_interface.cpp | 90 +- src/app/foldhaus_app.cpp | 88 +- src/app/foldhaus_app.h | 69 +- src/app/foldhaus_assembly.cpp | 36 +- src/app/foldhaus_assembly.h | 8 +- src/app/foldhaus_command_dispatch.h | 12 +- src/app/foldhaus_debug.h | 24 +- src/app/foldhaus_interface.cpp | 119 +- src/app/foldhaus_log.h | 8 +- src/app/foldhaus_node.cpp | 34 +- src/app/foldhaus_node.h | 4 +- src/app/foldhaus_operation_mode.h | 73 +- src/app/foldhaus_panel.h | 68 +- src/app/foldhaus_platform.h | 142 +- src/app/foldhaus_renderer.cpp | 8 +- src/app/foldhaus_renderer.h | 168 +- ...oldhaus_util_radialumia_file_converter.cpp | 120 +- src/app/generated/foldhaus_panels_generated.h | 31 +- .../generated/gs_meta_generated_typeinfo.h | 168 +- src/app/gs_osx_window.mm | 2 +- src/app/handmade_math.h | 3239 ++++++++++++++++ src/app/interface.h | 141 +- .../foldhaus_panel_animation_timeline.h | 147 +- src/app/panels/foldhaus_panel_dmx_view.h | 8 +- src/app/panels/foldhaus_panel_file_view.h | 14 +- src/app/panels/foldhaus_panel_hierarchy.h | 31 +- src/app/panels/foldhaus_panel_profiler.h | 69 +- .../panels/foldhaus_panel_sculpture_view.h | 115 +- src/app/sacn/sacn.h | 10 +- src/app/test_patterns.h | 28 +- src/app/win32_foldhaus.cpp | 623 ++- src/app/win32_foldhaus_dll.h | 20 +- src/app/win32_foldhaus_fileio.h | 133 - src/app/win32_foldhaus_memory.h | 22 +- src/gs_libs/gs_language.h | 39 +- src/gs_libs/gs_memory_arena.h | 4 +- src/gs_libs/gs_string.h | 2123 +---------- src/gs_libs/gs_string_builder.h | 6 +- src/gs_libs/gs_types.cpp | 3383 +++++++++++++++++ src/gs_libs/gs_types.h | 1053 +++++ src/gs_libs/gs_vector_matrix.h | 35 +- src/gs_libs/gs_win32.cpp | 169 +- src/meta/foldhaus_meta.cpp | 6 +- src/meta/gs_meta_error.h | 25 +- src/meta/gs_meta_lexer.h | 84 +- src/meta/gs_meta_type_table.h | 30 +- 55 files changed, 9546 insertions(+), 3555 deletions(-) rename src/app/{ => deprecated}/foldhaus_default_nodes.h (90%) rename src/app/{panels => deprecated}/foldhaus_panel_node_graph.h (92%) rename src/app/{ => deprecated}/foldhaus_search_lister.cpp (68%) rename src/app/{ => deprecated}/foldhaus_search_lister.h (81%) rename src/app/{ => deprecated}/foldhaus_text_entry.cpp (88%) rename src/app/{ => deprecated}/foldhaus_text_entry.h (81%) rename src/app/{ => deprecated}/node/foldhaus_node_interface.cpp (90%) create mode 100644 src/app/handmade_math.h create mode 100644 src/gs_libs/gs_types.cpp create mode 100644 src/gs_libs/gs_types.h diff --git a/build/build_app_msvc_win32_debug.bat b/build/build_app_msvc_win32_debug.bat index e38e31d..6151e16 100644 --- a/build/build_app_msvc_win32_debug.bat +++ b/build/build_app_msvc_win32_debug.bat @@ -16,7 +16,7 @@ pushd %BuildPath% del *.pdb > NUL 2> NUL REM Run the Preprocessor -%MetaProgramPath%\foldhaus_meta.exe %SourceCodePath%\foldhaus_app.cpp +REM %MetaProgramPath%\foldhaus_meta.exe %SourceCodePath%\foldhaus_app.cpp echo WAITING FOR PDB TO WRITE > lock.tmp diff --git a/src/app/animation/foldhaus_animation.h b/src/app/animation/foldhaus_animation.h index 0c22ee7..613a940 100644 --- a/src/app/animation/foldhaus_animation.h +++ b/src/app/animation/foldhaus_animation.h @@ -31,7 +31,7 @@ enum blend_mode struct anim_layer { - string Name; + gs_string Name; blend_mode BlendMode; }; @@ -39,7 +39,7 @@ struct anim_layer #define ANIMATION_SYSTEM_BLOCKS_MAX 128 struct animation_system { - memory_arena* Storage; + gs_memory_arena* Storage; gs_list Blocks; anim_layer* Layers; @@ -75,7 +75,7 @@ FrameIsInRange(s32 Frame, frame_range Range) internal u32 GetFrameCount(frame_range Range) { - u32 Result = (u32)GSMax(0, Range.Max - Range.Min); + u32 Result = (u32)Max(0, Range.Max - Range.Min); return Result; } @@ -133,7 +133,7 @@ RemoveAnimationBlock(gs_list_handle AnimationBlockHandle, animation_system* Anim // Layers internal u32 -AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite) +AddLayer (gs_string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite) { // NOTE(Peter): If this assert fires its time to make the layer buffer system // resizable. @@ -144,7 +144,7 @@ AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = anim_layer* NewLayer = AnimationSystem->Layers + Result; *NewLayer = {0}; NewLayer->Name = MakeString(PushArray(AnimationSystem->Storage, char, Name.Length), Name.Length); - CopyStringTo(Name, &NewLayer->Name); + PrintF(&NewLayer->Name, "%S", Name); NewLayer->BlendMode = BlendMode; return Result; } diff --git a/src/app/assembly_parser.cpp b/src/app/assembly_parser.cpp index 4b06fc7..8e229e0 100644 --- a/src/app/assembly_parser.cpp +++ b/src/app/assembly_parser.cpp @@ -28,7 +28,7 @@ enum assembly_field AssemblyField_Count, }; -global_variable char* AssemblyFieldIdentifiers[] = { +global char* AssemblyFieldIdentifiers[] = { "assembly_name", // AssemblyField_AssemblyName "assembly_scale", // AssemblyField_AssemblyScale "led_strip_count", // AssemblyField_LedStripCount @@ -52,20 +52,32 @@ global_variable char* AssemblyFieldIdentifiers[] = { "value", // AssemblyField_Value }; +struct assembly_error_list +{ + gs_string String; + assembly_error_list* Next; +}; + struct assembly_tokenizer { - string Text; + gs_string Text; char* At; + gs_const_string FileName; u32 LineNumber; bool ParsingIsValid; + + gs_memory_arena* ErrorArena; + assembly_error_list* ErrorsRoot; + assembly_error_list* ErrorsTail; }; internal bool AtValidPosition(assembly_tokenizer* T) { - bool Result = ((T->At - T->Text.Memory) < T->Text.Length); + u64 Offset = T->At - T->Text.Str; + bool Result = (Offset < T->Text.Length); return Result; } @@ -88,6 +100,16 @@ EatWhitespace(assembly_tokenizer* T) } } +internal void +EatToNewLine(assembly_tokenizer* T) +{ + while(AtValidPosition(T) && !IsNewline(T->At[0])) + { + AdvanceChar(T); + } + EatWhitespace(T); +} + internal bool AdvanceIfTokenEquals(assembly_tokenizer* T, char* Value) { @@ -118,6 +140,22 @@ AdvanceIfTokenEquals(assembly_tokenizer* T, char* Value) return Result; } +internal void +TokenizerPushError(assembly_tokenizer* T, char* ErrorString) +{ + // NOTE(Peter): We can make this more expressive if we need to + assembly_error_list* Error = PushStruct(T->ErrorArena, assembly_error_list); + Error->String = PushString(T->ErrorArena, 512); + PrintF(&Error->String, "%S(%d): %s", T->FileName, T->LineNumber, ErrorString); + SLLPushOrInit(T->ErrorsRoot, T->ErrorsTail, Error); + T->ParsingIsValid = false; + + // NOTE(Peter): I'm not sure this is the best idea, but at least this way, + // if there's multiple errors, you'll get a number of them, rather than + // a bunch of erroneous errors happening on the same line + EatToNewLine(T); +} + internal bool ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T) { @@ -130,12 +168,12 @@ ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T) } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Field identifier is missing a colon"); } } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Field Identifier Invalid"); } return Result; } @@ -150,15 +188,15 @@ ReadFieldEnd(assembly_tokenizer* T) } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Missing a semicolon"); } return Result; } -internal string +internal gs_string ReadString(assembly_tokenizer* T) { - string Result = {}; + gs_string Result = {}; if (AdvanceIfTokenEquals(T, "\"")) { char* StringStart = T->At; @@ -166,32 +204,36 @@ ReadString(assembly_tokenizer* T) { T->At++; } - Result.Memory = StringStart; - Result.Max = T->At - StringStart; - Result.Length = Result.Max; + Result.Str = StringStart; + Result.Size = T->At - StringStart; + Result.Length = Result.Size; if (AdvanceIfTokenEquals(T, "\"")) { // Success } else { - // TODO(Peter): Error + TokenizerPushError(T, "String not closed with a \""); } } + else + { + TokenizerPushError(T, "Expecting a string, but none was found"); + } return Result; } -internal string +internal gs_string GetNumberString(assembly_tokenizer* T) { - string Result = {}; - Result.Memory = T->At; + gs_string Result = {}; + Result.Str = T->At; while(AtValidPosition(T) && IsNumericExtended(T->At[0])) { AdvanceChar(T); } - Result.Length = T->At - Result.Memory; - Result.Max = Result.Length; + Result.Length = T->At - Result.Str; + Result.Size = Result.Length; return Result; } @@ -199,9 +241,8 @@ internal r32 ReadFloat(assembly_tokenizer* T) { r32 Result = 0; - string NumberString = GetNumberString(T); - parse_result ParsedFloat = ParseFloat(StringExpand(NumberString)); - Result = ParsedFloat.FloatValue; + gs_string NumberString = GetNumberString(T); + Result = (r32)ParseFloat(NumberString.ConstString); return Result; } @@ -209,28 +250,23 @@ internal s32 ReadInt(assembly_tokenizer* T) { s32 Result = 0; - string NumberString = GetNumberString(T); - parse_result ParsedInt = ParseSignedInt(StringExpand(NumberString)); - Result = ParsedInt.SignedIntValue; + gs_string NumberString = GetNumberString(T); + Result = (r32)ParseInt(NumberString.ConstString); return Result; } -internal string -ReadStringField(assembly_field Field, assembly_tokenizer* T, memory_arena* Arena) +internal gs_string +ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Arena) { - string Result = {}; + gs_string Result = {}; if (ReadFieldIdentifier(Field, T)) { - string ExistingString = ReadString(T); + gs_string ExistingString = ReadString(T); if (ReadFieldEnd(T)) { // Success Result = PushString(Arena, ExistingString.Length); - CopyStringTo(ExistingString, &Result); - } - else - { - T->ParsingIsValid = false; + PrintF(&Result, "%S", ExistingString); } } return Result; @@ -290,22 +326,22 @@ ReadV3Field(assembly_field Field, assembly_tokenizer* T) } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Vector 3 doesn't end with a ')'"); } } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Vector 3: unable to read a field"); } } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Vector 3: unable to read a field"); } } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Vector 3: unable to read a field"); } } return Result; @@ -333,14 +369,18 @@ ReadStructClosing(assembly_tokenizer* T) } internal bool -ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) +ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileText, gs_memory_arena* Transient) { Assembly->LedCountTotal = 0; + r32 Value = ParseFloat(ConstString("-2.355")); + assembly_tokenizer Tokenizer = {}; Tokenizer.Text = FileText; - Tokenizer.At = Tokenizer.Text.Memory; + Tokenizer.At = Tokenizer.Text.Str; Tokenizer.ParsingIsValid = true; + Tokenizer.ErrorArena = Transient; + Tokenizer.FileName = FileName; Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena); Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer); @@ -358,7 +398,7 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) StripAt->StartChannel = ReadIntField(AssemblyField_StartChannel, &Tokenizer); // TODO(Peter): Need to store this - string PointPlacementType = ReadStringField(AssemblyField_PointPlacementType, &Tokenizer, &Assembly->Arena); + gs_string PointPlacementType = ReadStringField(AssemblyField_PointPlacementType, &Tokenizer, &Assembly->Arena); // TODO(Peter): Switch on value of PointPlacementType if (ReadStructOpening(AssemblyField_InterpolatePoints, &Tokenizer)) { @@ -367,6 +407,10 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) if (!ReadStructClosing(&Tokenizer)) { Tokenizer.ParsingIsValid = false; + // TODO(Peter): @ErrorHandling + // Have this function prepend the filename and line number. + // Create an error display popup window, or an error log window that takes over a panel automatically + // TokenizerPushError(&Tokenizer, "Unable to read } } @@ -380,31 +424,31 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) v2_tag* TagAt = StripAt->Tags + Tag; if (ReadStructOpening(AssemblyField_Tag, &Tokenizer)) { - // TODO(Peter): Need to store the string somewhere we can look it up for display in the interface + // TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface // right now they are stored in temp memory and won't persist - string TagName = ReadStringField(AssemblyField_Name, &Tokenizer, Transient); - string TagValue = ReadStringField(AssemblyField_Value, &Tokenizer, Transient); - TagAt->NameHash = HashString(TagName); - TagAt->ValueHash = HashString(TagValue); + gs_string TagName = ReadStringField(AssemblyField_Name, &Tokenizer, Transient); + gs_string TagValue = ReadStringField(AssemblyField_Value, &Tokenizer, Transient); + TagAt->NameHash = HashDJB2ToU32(StringExpand(TagName)); + TagAt->ValueHash = HashDJB2ToU32(StringExpand(TagValue)); if (!ReadStructClosing(&Tokenizer)) { - Tokenizer.ParsingIsValid = false; + TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); } } else { - Tokenizer.ParsingIsValid = false; + TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); } } if (!ReadStructClosing(&Tokenizer)) { - Tokenizer.ParsingIsValid = false; + TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); } } else { - Tokenizer.ParsingIsValid = false; + TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); } } diff --git a/src/app/foldhaus_default_nodes.h b/src/app/deprecated/foldhaus_default_nodes.h similarity index 90% rename from src/app/foldhaus_default_nodes.h rename to src/app/deprecated/foldhaus_default_nodes.h index 7083ce2..3fddaa0 100644 --- a/src/app/foldhaus_default_nodes.h +++ b/src/app/deprecated/foldhaus_default_nodes.h @@ -100,10 +100,10 @@ NODE_PROC(SinWave, sin_wave_data) Data->Accumulator -= Data->Period; } - r32 ActualMin = GSMin(Data->Min, Data->Max); - r32 ActualMax = GSMax(Data->Min, Data->Max); - r32 SinResult = GSSin((Data->Accumulator / Data->Period) * PI * 2); - Data->Result = GSRemap(SinResult, -1.f, 1.f, ActualMin, ActualMax); + r32 ActualMin = Min(Data->Min, Data->Max); + r32 ActualMax = Max(Data->Min, Data->Max); + r32 SinResult = SinR32((Data->Accumulator / Data->Period) * PiR32 * 2); + Data->Result = RemapR32(SinResult, -1.f, 1.f, ActualMin, ActualMax); } else { diff --git a/src/app/panels/foldhaus_panel_node_graph.h b/src/app/deprecated/foldhaus_panel_node_graph.h similarity index 92% rename from src/app/panels/foldhaus_panel_node_graph.h rename to src/app/deprecated/foldhaus_panel_node_graph.h index 80aa175..6830d2f 100644 --- a/src/app/panels/foldhaus_panel_node_graph.h +++ b/src/app/deprecated/foldhaus_panel_node_graph.h @@ -15,7 +15,7 @@ struct visual_port { gs_list_handle SparseNodeHandle; u32 PortIndex; - rect PortBounds; + rect2 PortBounds; }; struct visual_connection @@ -57,7 +57,7 @@ struct node_graph_state { v2 ViewOffset; - memory_arena LayoutMemory; + gs_memory_arena LayoutMemory; node_layout Layout; b32 LayoutIsDirty; @@ -128,7 +128,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndConnectNodesOperation) for (u32 p = 0; p < GraphState->Layout.VisualPortsCount; p++) { visual_port VisualPort = GraphState->Layout.VisualPorts[p]; - rect ViewAdjustedBounds = gs_RectOffsetByVector(VisualPort.PortBounds, GraphState->ViewOffset); + rect2 ViewAdjustedBounds = gs_RectOffsetByVector(VisualPort.PortBounds, GraphState->ViewOffset); if (gs_PointIsInRect(Mouse.Pos, ViewAdjustedBounds)) { visual_port UpstreamPort = (OpState->IsInput & IsInputMember) ? VisualPort : OpState->VisualPort; @@ -196,7 +196,7 @@ NodeGraph_Cleanup(panel* Panel, app_state* State) } internal void -DrawGrid (v2 Offset, v2 GridSquareDim, rect PanelBounds, render_command_buffer* RenderBuffer) +DrawGrid (v2 Offset, v2 GridSquareDim, rect2 PanelBounds, render_command_buffer* RenderBuffer) { r32 LineValue = .16f; v4 LineColor = v4{LineValue, LineValue, LineValue, 1.f}; @@ -232,9 +232,9 @@ DrawGrid (v2 Offset, v2 GridSquareDim, rect PanelBounds, render_command_buffer* } internal void -DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, r32 LineHeight, string_alignment TextAlign, v2 TextOffset, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse) +DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, r32 LineHeight, gs_string_alignment TextAlign, v2 TextOffset, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse) { - rect PortBounds = rect{v2{0, 0}, v2{6, 6}}; + rect2 PortBounds = rect2{v2{0, 0}, v2{6, 6}}; v2 LinePosition = Position; for (u32 i = 0; i < NodeDataTypeInfo.MembersCount; i++) @@ -244,7 +244,7 @@ DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, { // TODO(Peter): Can we make this rely on the same data that we use to // render the actual connection points? - string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); + gs_string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); DrawString(RenderBuffer, MemberName, Interface.Font, LinePosition + TextOffset, WhiteV4, TextAlign); LinePosition.y -= LineHeight; } @@ -252,7 +252,7 @@ DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, } internal void -DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle NodeHandle, r32 NodeWidth, r32 LineHeight, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse, memory_arena* Scratch) +DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle NodeHandle, r32 NodeWidth, r32 LineHeight, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse, gs_memory_arena* Scratch) { gsm_struct_type_info NodeDataTypeInfo = StructTypes[NodeSpecification.DataType]; @@ -264,13 +264,13 @@ DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle Nod if (MemberIsInput(Member)) { InputMembers++; } if (MemberIsOutput(Member)) { OutputMembers++; } } - u32 LineCount = 1 + GSMax(InputMembers, OutputMembers); + u32 LineCount = 1 + Max(InputMembers, OutputMembers); v2 NodeDim = v2{ NodeWidth, (LineHeight * LineCount) + Interface.Margin.y, }; - rect NodeBounds = rect{ + rect2 NodeBounds = rect2{ v2{ Position.x, Position.y - NodeDim.y }, v2{ Position.x + NodeDim.x, Position.y }, }; @@ -282,7 +282,7 @@ DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle Nod PushRenderQuad2D(RenderBuffer, LinePosition, LinePosition + v2{NodeWidth, LineHeight}, v4{1.f, .24f, .39f, 1.f}); - string NodePrintName = MakeString(PushArray(Scratch, char, 256), 0, 256); + gs_string NodePrintName = MakeString(PushArray(Scratch, char, 256), 0, 256); PrintF(&NodePrintName, "%S [%d]", NodeSpecification.Identifier, NodeHandle.Index); DrawString(RenderBuffer, NodePrintName, Interface.Font, LinePosition + TextOffset, WhiteV4); LinePosition.y -= LineHeight; @@ -293,7 +293,7 @@ DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle Nod for (u32 i = 0; i < NodeDataTypeInfo.MembersCount; i++) { gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[i]; - string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); + gs_string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); // TODO(Peter): Can we make this rely on the same data that we use to // render the actual connection points? @@ -329,7 +329,7 @@ GetVisualPortIndexForNode(gs_list_handle SparseNodeHandle, u32 PortIndex, node_l } internal node_layout -ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, r32 LineHeight, memory_arena* Storage, app_state* State) +ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, r32 LineHeight, gs_memory_arena* Storage, app_state* State) { node_layout Result = {}; @@ -373,7 +373,7 @@ ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, { gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[p]; - rect PortBounds = {0}; + rect2 PortBounds = {0}; v2 PortDim = v2{8, 8}; PortBounds.Min = VisualNode->Position + v2{0, PortDim.y / 2}; if (MemberIsInput(Member)) @@ -420,16 +420,16 @@ ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, GSMetaTag(panel_render); GSMetaTag(panel_type_node_graph); internal void -NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +NodeGraph_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { node_graph_state* GraphState = (node_graph_state*)Panel.PanelStateMemory; b32 MouseHandled = false; - rect NodeSelectionWindowBounds = rect{ + rect2 NodeSelectionWindowBounds = rect2{ PanelBounds.Min, v2{PanelBounds.Min.x + 300, PanelBounds.Max.y}, }; - rect GraphBounds = rect{ + rect2 GraphBounds = rect2{ v2{NodeSelectionWindowBounds.Max.x, PanelBounds.Min.y}, PanelBounds.Max, }; @@ -513,18 +513,18 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf List.TextColor = WhiteV4; List.ListBounds = NodeSelectionWindowBounds; List.ListElementDimensions = v2{ - gs_Width(NodeSelectionWindowBounds), + Rect2Width(NodeSelectionWindowBounds), ui_GetTextLineHeight(State->Interface) }; List.ElementLabelIndent = v2{10, 4}; - string TitleString = MakeStringLiteral("Available Nodes"); - DrawListElement(TitleString, &List, Context.Mouse, RenderBuffer, State->Interface.Style); + gs_string Titlegs_string = MakeStringLiteral("Available Nodes"); + DrawListElement(Titlegs_string, &List, Context.Mouse, RenderBuffer, State->Interface.Style); for (u32 i = 0; i < NodeType_Count; i++) { node_specification_ Spec = NodeSpecifications[i]; - rect ElementBounds = DrawListElement(Spec.Identifier, &List, Context.Mouse, RenderBuffer, State->Interface.Style); + rect2 ElementBounds = DrawListElement(Spec.Identifier, &List, Context.Mouse, RenderBuffer, State->Interface.Style); if (MouseButtonTransitionedDown(Context.Mouse.LeftButtonState) && gs_PointIsInRect(Context.Mouse.DownPos, ElementBounds)) diff --git a/src/app/foldhaus_search_lister.cpp b/src/app/deprecated/foldhaus_search_lister.cpp similarity index 68% rename from src/app/foldhaus_search_lister.cpp rename to src/app/deprecated/foldhaus_search_lister.cpp index 78734b5..cb0725b 100644 --- a/src/app/foldhaus_search_lister.cpp +++ b/src/app/deprecated/foldhaus_search_lister.cpp @@ -6,7 +6,7 @@ #ifndef FOLDHAUS_SEARCH_LISTER_CPP internal b32 -NamePassesFilter (string Target, string Filter) +NamePassesFilter (gs_string Target, gs_string Filter) { return (Filter.Length == 0 || StringContainsStringCaseInsensitive(Target, Filter)); } @@ -21,14 +21,14 @@ FilterSearchLister (search_lister* SearchLister) for (s32 i = 0; i < SearchLister->SourceListCount; i++) { - string* NameString = SearchLister->SourceList + i; - if (NamePassesFilter(*NameString, SearchLister->Filter)) + gs_string* Namegs_string = SearchLister->SourceList + i; + if (NamePassesFilter(*Namegs_string, SearchLister->Filter)) { SearchLister->FilteredIndexLUT[SearchLister->FilteredListCount++] = i; } } - SearchLister->HotItem = GSClamp(0, SearchLister->HotItem, SearchLister->FilteredListCount - 1); + SearchLister->HotItem = Clamp(0, SearchLister->HotItem, SearchLister->FilteredListCount - 1); if (SearchLister->FilteredListCount == 0) { @@ -39,14 +39,14 @@ FilterSearchLister (search_lister* SearchLister) internal s32 GetNextFilteredItem (search_lister SearchLister) { - s32 Result = GSMin(SearchLister.HotItem + 1, SearchLister.FilteredListCount - 1); + s32 Result = Min(SearchLister.HotItem + 1, SearchLister.FilteredListCount - 1); return Result; } internal s32 GetPrevFilteredItem (search_lister SearchLister) { - s32 Result = GSMax(SearchLister.HotItem - 1, 0); + s32 Result = Max(SearchLister.HotItem - 1, 0); return Result; } diff --git a/src/app/foldhaus_search_lister.h b/src/app/deprecated/foldhaus_search_lister.h similarity index 81% rename from src/app/foldhaus_search_lister.h rename to src/app/deprecated/foldhaus_search_lister.h index 8cc4d15..e2d502e 100644 --- a/src/app/foldhaus_search_lister.h +++ b/src/app/deprecated/foldhaus_search_lister.h @@ -8,11 +8,11 @@ struct search_lister { // TODO(Peter): Giving up trying to just use the source list for now. At the moment - // we are copying the strings you want to filter from and storing them here. Come back + // we are copying the gs_strings you want to filter from and storing them here. Come back // once its working and make the memory efficient version (ie store the existing memory // location, the element stride and the offset to the char*) s32 SourceListCount; - string* SourceList; + gs_string* SourceList; // NOTE(Peter): stores the source indecies of each filtered item // For example: @@ -23,7 +23,7 @@ struct search_lister s32* FilteredIndexLUT; s32 HotItem; - string Filter; + gs_string Filter; }; diff --git a/src/app/foldhaus_text_entry.cpp b/src/app/deprecated/foldhaus_text_entry.cpp similarity index 88% rename from src/app/foldhaus_text_entry.cpp rename to src/app/deprecated/foldhaus_text_entry.cpp index 1d59e10..7deb830 100644 --- a/src/app/foldhaus_text_entry.cpp +++ b/src/app/deprecated/foldhaus_text_entry.cpp @@ -17,15 +17,14 @@ PipeSearchStringToDestination (text_entry* Input) { switch (Input->Destination.Type) { - case TextTranslateTo_String: + case TextTranslateTo_gs_string: { - CopyStringTo(Input->Buffer, Input->Destination.StringDest); + PrintF(Input->Destination.StringDest, "%S", Input->Buffer); }break; case TextTranslateTo_R32: { - parse_result FloatParseResult = ParseFloat(StringExpand(Input->Buffer)); - *Input->Destination.FloatDest = FloatParseResult.FloatValue; + *Input->Destination.FloatDest = (r32)ParseFloat(Input->Buffer.ConstString); }break; InvalidDefaultCase; @@ -37,19 +36,22 @@ RemoveCharacterAtCursor (text_entry* TextEntry) { if (TextEntry->CursorPosition > 0) { - RemoveCharAt(&TextEntry->Buffer, - TextEntry->CursorPosition - 1); + for (u32 i = TextEntry->CursorPosition - 1; i < TextEntry->Buffer.Length; i++) + { + Assert(i + 1 < TextEntry->Buffer.Size); + TextEntry->Buffer.Str[i] = TextEntry->Buffer.Str[i + 1]; + } TextEntry->CursorPosition--; } } -internal void -SetTextInputDestinationToString (text_entry* TextInput, string* DestinationString) +internal void +SetTextInputDestinationToString (text_entry* TextInput, gs_string* DestinationString) { ResetTextInput(TextInput); - TextInput->Destination.Type = TextTranslateTo_String; + TextInput->Destination.Type = TextTranslateTo_gs_string; TextInput->Destination.StringDest = DestinationString; - CopyStringTo(*DestinationString, &TextInput->Buffer); + PrintF(&TextInput->Buffer, "%S", *DestinationString); } internal void @@ -69,14 +71,13 @@ SetTextInputDestinationToFloat (text_entry* TextInput, r32* DestinationFloat) internal void MoveCursorRight (text_entry* TextEntry) { - TextEntry->CursorPosition = GSMin(TextEntry->Buffer.Length, - TextEntry->CursorPosition + 1); + TextEntry->CursorPosition = Min(TextEntry->Buffer.Length, TextEntry->CursorPosition + 1); } internal void MoveCursorLeft (text_entry* TextEntry) { - TextEntry->CursorPosition = GSMax(0, TextEntry->CursorPosition - 1); + TextEntry->CursorPosition = Max(0, TextEntry->CursorPosition - 1); } FOLDHAUS_INPUT_COMMAND_PROC(TextEntryInsertChar) @@ -88,12 +89,21 @@ FOLDHAUS_INPUT_COMMAND_PROC(TextEntryInsertChar) Char += ('a' - 'A'); } - InsertChar(&State->ActiveTextEntry.Buffer, Char, State->ActiveTextEntry.CursorPosition); + // Shift string forward + Assert(State->ActiveTextEntry.Buffer.Length < State->ActiveTextEntry.Buffer.Size); + for (u32 i = State->ActiveTextEntry.Buffer.Length; + i > (u32)State->ActiveTextEntry.CursorPosition; + i--) + { + State->ActiveTextEntry.Buffer.Str[i] = State->ActiveTextEntry.Buffer.Str[i - 1]; + } + // Insert new Character + State->ActiveTextEntry.Buffer.Str[State->ActiveTextEntry.CursorPosition] = Char; State->ActiveTextEntry.CursorPosition++; PipeSearchStringToDestination(&State->ActiveTextEntry); } -FOLDHAUS_INPUT_COMMAND_PROC(RemoveCharacterFromEntryString) +FOLDHAUS_INPUT_COMMAND_PROC(RemoveCharacterFromEntrygs_string) { RemoveCharacterAtCursor(&State->ActiveTextEntry); } @@ -109,11 +119,11 @@ FOLDHAUS_INPUT_COMMAND_PROC(TextEntryMoveCursorLeft) } internal void -InitializeTextInputCommands (input_command_registry* Commands, memory_arena* PermanentStorage) +InitializeTextInputCommands (input_command_registry* Commands, gs_memory_arena* PermanentStorage) { if (Commands->Size > 0) { - RegisterKeyPressCommand(Commands, KeyCode_Backspace, Command_Began | Command_Held, KeyCode_Invalid, RemoveCharacterFromEntryString); + RegisterKeyPressCommand(Commands, KeyCode_Backspace, Command_Began | Command_Held, KeyCode_Invalid, RemoveCharacterFromEntrygs_string); RegisterKeyPressCommand(Commands, KeyCode_LeftArrow, Command_Began | Command_Held, KeyCode_Invalid, TextEntryMoveCursorLeft); RegisterKeyPressCommand(Commands, KeyCode_RightArrow, Command_Began | Command_Held, KeyCode_Invalid, TextEntryMoveCursorRight); @@ -126,7 +136,7 @@ InitializeTextInputCommands (input_command_registry* Commands, memory_arena* Per } #define DEFAULT_TEXT_ENTRY_INPUT_COMMANDS_ARRAY_ENTRY \ -{ KeyCode_Backspace, KeyCode_Invalid, Command_Began | Command_Held, RemoveCharacterFromEntryString }, \ +{ KeyCode_Backspace, KeyCode_Invalid, Command_Began | Command_Held, RemoveCharacterFromEntrygs_string }, \ { KeyCode_LeftArrow, KeyCode_Invalid, Command_Began | Command_Held, TextEntryMoveCursorLeft }, \ { KeyCode_RightArrow, KeyCode_Invalid, Command_Began | Command_Held, TextEntryMoveCursorRight }, \ { KeyCode_a, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \ diff --git a/src/app/foldhaus_text_entry.h b/src/app/deprecated/foldhaus_text_entry.h similarity index 81% rename from src/app/foldhaus_text_entry.h rename to src/app/deprecated/foldhaus_text_entry.h index dd8ba00..e25608f 100644 --- a/src/app/foldhaus_text_entry.h +++ b/src/app/deprecated/foldhaus_text_entry.h @@ -7,7 +7,7 @@ enum text_translation_type { - TextTranslateTo_String, + TextTranslateTo_gs_string, TextTranslateTo_R32, TextTranslateTo_S32, TextTranslateTo_U32, @@ -17,7 +17,7 @@ struct text_entry_destination { text_translation_type Type; union { - string* StringDest; + gs_string* StringDest; r32* FloatDest; s32* SignedIntDest; u32* UnsignedIntDest; @@ -26,7 +26,7 @@ struct text_entry_destination struct text_entry { - string Buffer; + gs_string Buffer; s32 CursorPosition; text_entry_destination Destination; diff --git a/src/app/node/foldhaus_node_interface.cpp b/src/app/deprecated/node/foldhaus_node_interface.cpp similarity index 90% rename from src/app/node/foldhaus_node_interface.cpp rename to src/app/deprecated/node/foldhaus_node_interface.cpp index 0b4c3e4..f4e3b39 100644 --- a/src/app/node/foldhaus_node_interface.cpp +++ b/src/app/deprecated/node/foldhaus_node_interface.cpp @@ -18,7 +18,7 @@ struct node_lister_operation_state }; internal void -RenderNodeLister(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderNodeLister(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { node_lister_operation_state* OpState = (node_lister_operation_state*)Operation.OpStateMemory; @@ -30,7 +30,7 @@ RenderNodeLister(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf FilterSearchLister(&OpState->SearchLister); // Display Search Lister - search_lister_result NodeListerResult = EvaluateSearchLister (&State->Interface_, TopLeft, Dimension, + search_lister_result NodeListerResult = EvaluateSearchLister (&State->Interface_, TopLeft, Dimension, MakeStringLiteral("Nodes List"), OpState->SearchLister.SourceList, OpState->SearchLister.FilteredIndexLUT, @@ -85,12 +85,12 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) AddNodeOperation->Render = RenderNodeLister; - node_lister_operation_state* OpState = CreateOperationState(AddNodeOperation, - &State->Modes, + node_lister_operation_state* OpState = CreateOperationState(AddNodeOperation, + &State->Modes, node_lister_operation_state); { OpState->SearchLister.SourceListCount = NodeSpecificationsCount; - OpState->SearchLister.SourceList = PushArray(&State->Modes.Arena, string, OpState->SearchLister.SourceListCount); + OpState->SearchLister.SourceList = PushArray(&State->Modes.Arena, gs_string, OpState->SearchLister.SourceListCount); { for (s32 i = 0; i < OpState->SearchLister.SourceListCount; i++) { @@ -107,7 +107,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) } OpState->ListPosition = Mouse.Pos; - SetTextInputDestinationToString(&State->ActiveTextEntry, &OpState->SearchLister.Filter); + SetTextInputDestinationTogs_string(&State->ActiveTextEntry, &OpState->SearchLister.Filter); } //////////////////////////////////////// @@ -133,12 +133,12 @@ FOLDHAUS_INPUT_COMMAND_PROC(CloseColorPickerCommand) } internal void -RenderColorPicker(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderColorPicker(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { color_picker_operation_state* OpState = (color_picker_operation_state*)Operation.OpStateMemory; - b32 ShouldClose = EvaluateColorPicker(RenderBuffer, OpState->ValueAddr, + b32 ShouldClose = EvaluateColorPicker(RenderBuffer, OpState->ValueAddr, v2{200, 200}, State->Interface, Mouse); if (ShouldClose) @@ -157,8 +157,8 @@ OpenColorPicker(app_state* State, node_connection* Connection) operation_mode* ColorPickerMode = ActivateOperationModeWithCommands(&State->Modes, ColorPickerCommands); ColorPickerMode->Render = RenderColorPicker; - color_picker_operation_state* OpState = CreateOperationState(ColorPickerMode, - &State->Modes, + color_picker_operation_state* OpState = CreateOperationState(ColorPickerMode, + &State->Modes, color_picker_operation_state); OpState->ValueAddr = Connection->V4ValuePtr; } @@ -184,7 +184,7 @@ input_command NodeFieldTextEditCommands [] = { internal void BeginNodeFieldTextEdit(app_state* State, node_connection* Connection) { - operation_mode* NodeFieldTextEditMode = ActivateOperationModeWithCommands(&State->Modes, + operation_mode* NodeFieldTextEditMode = ActivateOperationModeWithCommands(&State->Modes, NodeFieldTextEditCommands); SetTextInputDestinationToFloat(&State->ActiveTextEntry, Connection->R32ValuePtr); @@ -202,10 +202,10 @@ struct drag_node_port_operation_state }; internal void -RenderDraggingNodePort(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderDraggingNodePort(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { drag_node_port_operation_state* OpState = (drag_node_port_operation_state*)Operation.OpStateMemory; - UpdateDraggingNodePort(Mouse.Pos, OpState->Interaction, State->NodeList, + UpdateDraggingNodePort(Mouse.Pos, OpState->Interaction, State->NodeList, State->NodeRenderSettings, RenderBuffer); } @@ -225,12 +225,12 @@ internal void BeginDraggingNodePort(app_state* State, node_interaction Interaction) { operation_mode* DragNodePortMode = ActivateOperationModeWithCommands( - &State->Modes, + &State->Modes, DragNodePortInputCommands); DragNodePortMode->Render = RenderDraggingNodePort; - drag_node_port_operation_state* OpState = CreateOperationState(DragNodePortMode, - &State->Modes, + drag_node_port_operation_state* OpState = CreateOperationState(DragNodePortMode, + &State->Modes, drag_node_port_operation_state); OpState->Interaction = Interaction; } @@ -242,16 +242,16 @@ BeginDraggingNodePort(app_state* State, node_interaction Interaction) /////////////////////////////////////// internal void -RenderDragNodeField(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderDragNodeField(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { - // TODO(Peter): + // TODO(Peter): //UpdateDraggingNodeValue(Mouse.Pos, Mouse.OldPos, OpState->Interaction, State->NodeList, State->NodeRenderSettings, State); } internal void BeginInteractWithNodeField(app_state* State, node_interaction Interaction) { - // TODO(Peter): + // TODO(Peter): } //////////////////////////////////////// @@ -266,10 +266,10 @@ struct drag_node_operation_state }; internal void -RenderDraggingNode(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderDraggingNode(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { drag_node_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_node_operation_state); - UpdateDraggingNode(Mouse.Pos, OpState->Interaction, State->NodeList, + UpdateDraggingNode(Mouse.Pos, OpState->Interaction, State->NodeList, State->NodeRenderSettings); } @@ -286,12 +286,12 @@ internal void BeginDraggingNode(app_state* State, node_interaction Interaction) { operation_mode* DragNodeMode = ActivateOperationModeWithCommands( - &State->Modes, + &State->Modes, DragNodeInputCommands); DragNodeMode->Render = RenderDraggingNode; - drag_node_operation_state* OpState = CreateOperationState(DragNodeMode, - &State->Modes, + drag_node_operation_state* OpState = CreateOperationState(DragNodeMode, + &State->Modes, drag_node_operation_state); OpState->Interaction = Interaction; } @@ -314,8 +314,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseDragInteraction) node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.DownPos, State->NodeRenderSettings); if (Node) { - node_interaction NewInteraction = GetNodeInteractionType(Node, - Mouse.Pos, + node_interaction NewInteraction = GetNodeInteractionType(Node, + Mouse.Pos, State->NodeRenderSettings); if (IsDraggingNodePort(NewInteraction)) { @@ -324,7 +324,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseDragInteraction) else if(IsDraggingNodeValue(NewInteraction)) { // TODO(Peter): This probably wants to live in a mouse held action - // the first frame we realize we're held over a field, just transition to + // the first frame we realize we're held over a field, just transition to // drag node field //BeginInteractWithNodeField(State, NewInteraction, State->NodeRenderSettings); } @@ -347,8 +347,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseSelectInteraction) node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.Pos, State->NodeRenderSettings); if (Node) { - node_interaction NewInteraction = GetNodeInteractionType(Node, - Mouse.Pos, + node_interaction NewInteraction = GetNodeInteractionType(Node, + Mouse.Pos, State->NodeRenderSettings); if(IsDraggingNodeValue(NewInteraction)) { @@ -368,7 +368,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseSelectInteraction) } internal void -RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderNodeView(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { node_view_operation_state* OpState = (node_view_operation_state*)Operation.OpStateMemory; @@ -383,7 +383,7 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer { node_header* Node = NodeIter.At; - rect NodeBounds = CalculateNodeBounds(Node, State->NodeRenderSettings); + rect2 NodeBounds = CalculateNodeBounds(Node, State->NodeRenderSettings); b32 DrawFields = PointIsInRect(Mouse.Pos, NodeBounds); if (Node == SelectedNode) @@ -394,8 +394,8 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer PushRenderQuad2D(RenderBuffer, NodeBounds.Min, NodeBounds.Max, v4{.5f, .5f, .5f, 1.f}); // TODO(Peter): This is just for debug purposes. We can remove and go back to just having - // Node->Name in DrawString - string NodeName = GetNodeName(*Node); + // Node->Name in Drawgs_string + gs_string NodeName = GetNodeName(*Node); PrintF(&NodeHeaderBuffer, "%.*s: %d", NodeName.Length, NodeName.Memory, Node->Handle); DrawString(RenderBuffer, NodeHeaderBuffer, State->NodeRenderSettings.Font, v2{NodeBounds.Min.x + 5, NodeBounds.Max.y - (State->NodeRenderSettings.Font->PixelHeight + NODE_HEADER_HEIGHT + 5)}, @@ -408,12 +408,12 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer // Inputs if (ConnectionIsInput(Node, Connection)) { - rect PortBounds = CalculateNodeInputPortBounds(Node, Connection, State->NodeRenderSettings); + rect2 PortBounds = CalculateNodeInputPortBounds(Node, Connection, State->NodeRenderSettings); DrawPort(RenderBuffer, PortBounds, PortColor); // // TODO(Peter): I don't like excluding OutputNode, feels too much like a special case - // but I don't want to get in to the meta programming right now. + // but I don't want to get in to the meta programming right now. // We should just generate a spec and struct member types for NodeType_OutputNode // // :ExcludingOutputNodeSpecialCase @@ -422,21 +422,21 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer { node_specification Spec = NodeSpecifications[Node->Type]; node_struct_member Member = Spec.MemberList[Connection]; - DrawString(RenderBuffer, MakeString(Member.Name), + DrawString(RenderBuffer, MakeString(Member.Name), State->NodeRenderSettings.Font, v2{PortBounds.Min.x - 8, PortBounds.Min.y}, WhiteV4, Align_Right); } - rect ValueBounds = CalculateNodeInputValueBounds(Node, Connection, State->NodeRenderSettings); + rect2 ValueBounds = CalculateNodeInputValueBounds(Node, Connection, State->NodeRenderSettings); DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font); // NOTE(Peter): its way easier to draw the connection on the input port b/c its a 1:1 relationship, // whereas output ports might have many connections, they really only know about the most recent one - // Not sure if this is a problem. We mostly do everything backwards here, starting at the + // Not sure if this is a problem. We mostly do everything backwards here, starting at the // most downstream node and working back up to find dependencies. if (ConnectionHasUpstreamConnection(Node, Connection)) { - rect ConnectedPortBounds = GetBoundsOfPortConnectedToInput(Node, Connection, State->NodeList, State->NodeRenderSettings); + rect2 ConnectedPortBounds = GetBoundsOfPortConnectedToInput(Node, Connection, State->NodeList, State->NodeRenderSettings); v2 InputCenter = CalculateRectCenter(PortBounds); v2 OutputCenter = CalculateRectCenter(ConnectedPortBounds); PushRenderLine2D(RenderBuffer, OutputCenter, InputCenter, 1, WhiteV4); @@ -446,25 +446,25 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer // Outputs if (ConnectionIsOutput(Node, Connection)) { - rect PortBounds = CalculateNodeOutputPortBounds(Node, Connection, State->NodeRenderSettings); + rect2 PortBounds = CalculateNodeOutputPortBounds(Node, Connection, State->NodeRenderSettings); DrawPort(RenderBuffer, PortBounds, PortColor); if (DrawFields) { node_specification Spec = NodeSpecifications[Node->Type]; node_struct_member Member = Spec.MemberList[Connection]; - DrawString(RenderBuffer, MakeString(Member.Name), + DrawString(RenderBuffer, MakeString(Member.Name), State->NodeRenderSettings.Font, v2{PortBounds.Max.x + 8, PortBounds.Min.y}, WhiteV4); } - rect ValueBounds = CalculateNodeOutputValueBounds(Node, Connection, State->NodeRenderSettings); + rect2 ValueBounds = CalculateNodeOutputValueBounds(Node, Connection, State->NodeRenderSettings); DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font); } for (s32 Button = 0; Button < 3; Button++) { - rect ButtonRect = CalculateNodeDragHandleBounds(NodeBounds, Button, State->NodeRenderSettings); + rect2 ButtonRect = CalculateNodeDragHandleBounds(NodeBounds, Button, State->NodeRenderSettings); PushRenderQuad2D(RenderBuffer, ButtonRect.Min, ButtonRect.Max, DragButtonColors[Button]); } } @@ -501,8 +501,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeView) operation_mode* NodeViewMode = ActivateOperationModeWithCommands(&State->Modes, NodeViewCommands); NodeViewMode->Render = RenderNodeView; - node_view_operation_state* OpState = CreateOperationState(NodeViewMode, - &State->Modes, + node_view_operation_state* OpState = CreateOperationState(NodeViewMode, + &State->Modes, node_view_operation_state); OpState->SelectedNodeHandle = 0; diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index c3b9cb1..5d05907 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -8,27 +8,6 @@ #include "foldhaus_platform.h" #include "foldhaus_app.h" -internal v4 -MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, rect WindowBounds) -{ - DEBUG_TRACK_SCOPE(MouseToWorldRay); - r32 X = ((2.0f * MouseX) / gs_Width(WindowBounds)) - 1; - r32 Y = ((2.0f * MouseY) / gs_Height(WindowBounds)) - 1; - - v4 ScreenPos = v4{X, Y, -1, 1}; - - m44 InverseProjection = {}; - Inverse(GetCameraPerspectiveProjectionMatrix(*Camera), &InverseProjection); - - m44 InverseModelView = {}; - Inverse(GetCameraModelViewMatrix(*Camera), &InverseModelView); - InverseModelView = Transpose(InverseModelView); - - v4 ClipSpacePos = InverseProjection * ScreenPos; - v4 WorldPosition = InverseModelView * ClipSpacePos; - return WorldPosition; -} - struct send_sacn_job_data { @@ -72,11 +51,8 @@ INITIALIZE_APPLICATION(InitializeApplication) app_state* State = (app_state*)Context.MemoryBase; *State = {}; - State->Permanent = {}; - State->Permanent.PlatformMemory = Context.PlatformMemory; - State->Transient = {}; - State->Transient.FindAddressRule = FindAddress_InLastBufferOnly; - State->Transient.PlatformMemory = Context.PlatformMemory; + State->Permanent = CreateMemoryArena(Context.ThreadContext.Allocator); + State->Transient = CreateMemoryArena(Context.ThreadContext.Allocator); State->Assemblies.CountMax = 8; State->Assemblies.Values = PushArray(&State->Permanent, assembly, State->Assemblies.CountMax); @@ -90,13 +66,11 @@ INITIALIZE_APPLICATION(InitializeApplication) CommandQueueSize); State->CommandQueue = InitializeCommandQueue(CommandQueueMemory, CommandQueueSize); - State->ActiveTextEntry.Buffer = MakeString(PushArray(&State->Permanent, char, 256), 0, 256); - // TODO(Peter): put in InitializeInterface? r32 FontSize = 14; { - platform_memory_result FontFile = ReadEntireFile(Context, MakeStringLiteral("data/Anonymous Pro.ttf")); - if (!FontFile.Error) + gs_file FontFile = ReadEntireFile(Context.ThreadContext.FileHandler, ConstString("data/Anonymous Pro.ttf")); + if (FileNoError(FontFile)) { bitmap_font* Font = PushStruct(&State->Permanent, bitmap_font); @@ -105,7 +79,7 @@ INITIALIZE_APPLICATION(InitializeApplication) Font->BitmapBytesPerPixel = 4; Font->BitmapMemory = PushArray(&State->Permanent, u8, Font->BitmapWidth * Font->BitmapHeight * Font->BitmapBytesPerPixel); Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel; - GSMemSet(Font->BitmapMemory, 0, Font->BitmapStride * Font->BitmapHeight); + ZeroMemoryBlock(Font->BitmapMemory, Font->BitmapStride * Font->BitmapHeight); platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", FontSize, FontWeight_Normal, false, false, false); Font->PixelHeight = FontInfo.PixelHeight; @@ -169,17 +143,18 @@ INITIALIZE_APPLICATION(InitializeApplication) State->SACN = InitializeSACN(Context); State->NetworkProtocolHeaderSize = STREAM_HEADER_SIZE; - State->Camera.FieldOfView = DegreesToRadians(45.0f); - State->Camera.AspectRatio = gs_AspectRatio(State->WindowBounds); - State->Camera.Near = 1.0f; - State->Camera.Far = 100.0f; - State->Camera.Position = v3{0, 0, -250}; - State->Camera.LookAt = v3{0, 0, 0}; + State->Camera.FieldOfView = 45.0f; + State->Camera.AspectRatio = RectAspectRatio(State->WindowBounds); + State->Camera.Near = .1f; + State->Camera.Far = 800.0f; + State->Camera.Position = v3{0, 0, 400}; + State->Camera.LookAt = v3{0, 0, 0 + }; - State->LedSystem = LedSystemInitialize(Context.PlatformMemory, 128); + State->LedSystem = LedSystemInitialize(Context.ThreadContext.Allocator, 128); #if 1 - string SculpturePath = MakeStringLiteral("data/radialumia_v2.fold"); + gs_const_string SculpturePath = ConstString("data/radialumia_v2.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, SculpturePath, State->GlobalLog); #endif @@ -189,11 +164,7 @@ INITIALIZE_APPLICATION(InitializeApplication) ReloadStaticData(Context, GlobalDebugServices); - // Setup Operation Modes - State->Modes.ActiveModesCount = 0; - State->Modes.Arena = {}; - State->Modes.Arena.PlatformMemory = Context.PlatformMemory; - State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly; + State->Modes = OperationModeSystemInit(&State->Permanent, Context.ThreadContext); { // Animation PLAYGROUND State->AnimationSystem = {}; @@ -203,9 +174,9 @@ INITIALIZE_APPLICATION(InitializeApplication) State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem); State->AnimationSystem.LayersMax = 32; State->AnimationSystem.Layers = PushArray(&State->Permanent, anim_layer, State->AnimationSystem.LayersMax); - AddLayer(MakeStringLiteral("Base Layer"), &State->AnimationSystem, BlendMode_Overwrite); - AddLayer(MakeStringLiteral("Color Layer"), &State->AnimationSystem, BlendMode_Multiply); - AddLayer(MakeStringLiteral("Sparkles"), &State->AnimationSystem, BlendMode_Add); + AddLayer(MakeString("Base Layer"), &State->AnimationSystem, BlendMode_Overwrite); + AddLayer(MakeString("Color Layer"), &State->AnimationSystem, BlendMode_Multiply); + AddLayer(MakeString("Sparkles"), &State->AnimationSystem, BlendMode_Add); } // End Animation Playground @@ -215,7 +186,7 @@ INITIALIZE_APPLICATION(InitializeApplication) } internal void -HandleInput (app_state* State, rect WindowBounds, input_queue InputQueue, mouse_state Mouse) +HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse_state Mouse) { DEBUG_TRACK_FUNCTION; @@ -274,7 +245,7 @@ HandleInput (app_state* State, rect WindowBounds, input_queue InputQueue, mouse_ } internal dmx_buffer_list* -CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, memory_arena* Arena) +CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, gs_memory_arena* Arena) { DEBUG_TRACK_FUNCTION; @@ -322,6 +293,10 @@ CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, return Result; } + +#define HANDMADE_MATH_IMPLEMENTATION +#include "handmade_math.h" + UPDATE_AND_RENDER(UpdateAndRender) { DEBUG_TRACK_FUNCTION; @@ -334,6 +309,9 @@ UPDATE_AND_RENDER(UpdateAndRender) ClearArena(&State->Transient); Context->Mouse.CursorType = CursorType_Arrow; + PushRenderClearScreen(RenderBuffer); + State->Camera.AspectRatio = RectAspectRatio(Context->WindowBounds); + HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse); if (State->AnimationSystem.TimelineShouldAdvance) { @@ -355,7 +333,7 @@ UPDATE_AND_RENDER(UpdateAndRender) u32 CurrentBlocksMax = State->AnimationSystem.LayersCount; b8* CurrentBlocksFilled = PushArray(&State->Transient, b8, CurrentBlocksMax); - GSZeroArray(CurrentBlocksFilled, b8, CurrentBlocksMax); + ZeroArray(CurrentBlocksFilled, b8, CurrentBlocksMax); animation_block* CurrentBlocks = PushArray(&State->Transient, animation_block, CurrentBlocksMax); for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) @@ -432,9 +410,9 @@ UPDATE_AND_RENDER(UpdateAndRender) u32 G = (u32)AssemblyLedBuffer->Colors[LED].G + (u32)LayerLEDBuffers[Layer].Colors[LED].G; u32 B = (u32)AssemblyLedBuffer->Colors[LED].B + (u32)LayerLEDBuffers[Layer].Colors[LED].B; - AssemblyLedBuffer->Colors[LED].R = (u8)GSMin(R, (u32)255); - AssemblyLedBuffer->Colors[LED].G = (u8)GSMin(G, (u32)255); - AssemblyLedBuffer->Colors[LED].B = (u8)GSMin(B, (u32)255); + AssemblyLedBuffer->Colors[LED].R = (u8)Min(R, (u32)255); + AssemblyLedBuffer->Colors[LED].G = (u8)Min(G, (u32)255); + AssemblyLedBuffer->Colors[LED].B = (u8)Min(B, (u32)255); } }break; @@ -502,7 +480,7 @@ UPDATE_AND_RENDER(UpdateAndRender) - PushRenderOrthographic(RenderBuffer, 0, 0, gs_Width(State->WindowBounds), gs_Height(State->WindowBounds)); + PushRenderOrthographic(RenderBuffer, State->WindowBounds); PushRenderClearScreen(RenderBuffer); State->WindowBounds = Context->WindowBounds; @@ -521,7 +499,7 @@ UPDATE_AND_RENDER(UpdateAndRender) } } - Context->GeneralWorkQueue->DoQueueWorkUntilDone(Context->GeneralWorkQueue, 0); + Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext); Context->GeneralWorkQueue->ResetWorkQueue(Context->GeneralWorkQueue); // Checking for overflows diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index a33d179..cadf625 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -20,13 +20,8 @@ #include "foldhaus_assembly.h" #include "assembly_parser.cpp" - -#include "foldhaus_node.h" - typedef struct app_state app_state; -#include "test_patterns.h" - // TODO(Peter): something we can do later is to remove all reliance on app_state and context // from foldhaus_pane.h. It should just emit lists of things that the app can iterate over and // perform operations on, like panel_draw_requests = { bounds, panel* } etc. @@ -37,10 +32,6 @@ typedef struct app_state app_state; #include "animation/foldhaus_animation.h" -#include "foldhaus_text_entry.h" - -#include "foldhaus_search_lister.h" - enum network_protocol { NetworkProtocol_SACN, @@ -51,10 +42,11 @@ enum network_protocol struct app_state { - rect WindowBounds; + r32 CameraTheta; // TODO(Peter): @TEMPORARY + rect2 WindowBounds; - memory_arena Permanent; - memory_arena Transient; + gs_memory_arena Permanent; + gs_memory_arena Transient; s32 NetworkProtocolHeaderSize; network_protocol NetworkProtocol; @@ -69,7 +61,6 @@ struct app_state operation_mode_system Modes; input_command_queue CommandQueue; - text_entry ActiveTextEntry; ui_interface Interface; @@ -80,7 +71,7 @@ struct app_state panel_system PanelSystem; panel* HotPanel; - pattern_node_workspace NodeWorkspace; + //pattern_node_workspace NodeWorkspace; event_log* GlobalLog; }; @@ -94,8 +85,8 @@ TestPatternOne(led_buffer* Assembly, r32 Time) for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) { v4 LedPosition = Assembly->Positions[LedIndex]; - float PercentX = GSRemap(LedPosition.x, -150.0f, 150.0f, 0.0f, 1.0f); - float PercentY = GSRemap(LedPosition.y, -150.0f, 150.0f, 0.0f, 1.0f); + float PercentX = RemapClampedR32(LedPosition.x, -150.0f, 150.0f, 0.0f, 1.0f); + float PercentY = RemapClampedR32(LedPosition.y, -150.0f, 150.0f, 0.0f, 1.0f); Assembly->Colors[LedIndex].R = (u8)(PercentX * 255); Assembly->Colors[LedIndex].G = (u8)(PercentY * 255); } @@ -104,16 +95,16 @@ TestPatternOne(led_buffer* Assembly, r32 Time) internal void TestPatternTwo(led_buffer* Assembly, r32 Time) { - r32 PeriodicTime = (Time / PI) * 2; + r32 PeriodicTime = (Time / PiR32) * 2; - r32 ZeroOneSin = (GSSin(PeriodicTime) * .5f) + .5f; - r32 ZeroOneCos = (GSCos(PeriodicTime) * .5f) + .5f; + r32 ZeroOneSin = (SinR32(PeriodicTime) * .5f) + .5f; + r32 ZeroOneCos = (CosR32(PeriodicTime) * .5f) + .5f; pixel Color = { (u8)(ZeroOneSin * 255), 0, (u8)(ZeroOneCos * 255) }; v4 Center = v4{0, 0, 0, 1}; r32 ThetaZ = Time / 2; - v4 Normal = v4{GSCos(ThetaZ), 0, GSSin(ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 - v4 Right = Cross(Normal, v4{0, 1, 0, 0}); + v4 Normal = v4{CosR32(ThetaZ), 0, SinR32(ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 + v4 Right = V4Cross(Normal, v4{0, 1, 0, 0}); v4 FrontCenter = Center + (Normal * 25); v4 BackCenter = Center - (Normal * 25); @@ -128,13 +119,13 @@ TestPatternTwo(led_buffer* Assembly, r32 Time) v4 ToFront = Position + FrontCenter; v4 ToBack = Position + BackCenter; - r32 ToFrontDotNormal = Dot(ToFront, Normal); - r32 ToBackDotNormal = Dot(ToBack, Normal); + r32 ToFrontDotNormal = V4Dot(ToFront, Normal); + r32 ToBackDotNormal = V4Dot(ToBack, Normal); - ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000); - ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000); + ToFrontDotNormal = Clamp01(ToFrontDotNormal * 1000); + ToBackDotNormal = Clamp01(ToBackDotNormal * 1000); - r32 SqDistToCenter = MagSqr(Position); + r32 SqDistToCenter = V4MagSquared(Position); if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared) { if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) @@ -157,10 +148,10 @@ internal void TestPatternThree(led_buffer* Assembly, r32 Time) { v4 GreenCenter = v4{0, 0, 150, 1}; - r32 GreenRadius = GSAbs(GSSin(Time)) * 200; + r32 GreenRadius = Abs(SinR32(Time)) * 200; v4 TealCenter = v4{0, 0, 150, 1}; - r32 TealRadius = GSAbs(GSSin(Time + 1.5)) * 200; + r32 TealRadius = Abs(SinR32(Time + 1.5)) * 200; r32 FadeDist = 35; @@ -172,12 +163,12 @@ TestPatternThree(led_buffer* Assembly, r32 Time) u8 Green = 0; u8 Blue = 0; - r32 GreenDist = GSAbs(Mag(LedPosition - GreenCenter) - GreenRadius); - r32 GreenBrightness = GSClamp(0.f, FadeDist - GSAbs(GreenDist), FadeDist); + r32 GreenDist = Abs(V4Mag(LedPosition - GreenCenter) - GreenRadius); + r32 GreenBrightness = Clamp(0.f, FadeDist - Abs(GreenDist), FadeDist); Green = (u8)(GreenBrightness * 255); - r32 TealDist = GSAbs(Mag(LedPosition - TealCenter) - TealRadius); - r32 TealBrightness = GSClamp(0.f, FadeDist - GSAbs(TealDist), FadeDist); + r32 TealDist = Abs(V4Mag(LedPosition - TealCenter) - TealRadius); + r32 TealBrightness = Clamp(0.f, FadeDist - Abs(TealDist), FadeDist); Red = (u8)(TealBrightness * 255); Blue = (u8)(TealBrightness * 255); @@ -191,17 +182,6 @@ TestPatternThree(led_buffer* Assembly, r32 Time) #include "foldhaus_assembly.cpp" -#include "foldhaus_text_entry.cpp" -#include "foldhaus_search_lister.cpp" - -#include "foldhaus_default_nodes.h" - -#include "./generated/gs_meta_generated_typeinfo.h" -#include "generated/foldhaus_nodes_generated.h" - - -#include "foldhaus_node.cpp" - FOLDHAUS_INPUT_COMMAND_PROC(EndCurrentOperationMode) { DeactivateCurrentOperationMode(&State->Modes); @@ -213,7 +193,7 @@ typedef PANEL_INIT_PROC(panel_init_proc); #define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State) typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); -#define PANEL_RENDER_PROC(name) void name(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +#define PANEL_RENDER_PROC(name) void name(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) typedef PANEL_RENDER_PROC(panel_render_proc); // NOTE(Peter): This is used by the meta system to generate panel type info @@ -233,7 +213,6 @@ struct panel_definition #include "panels/foldhaus_panel_dmx_view.h" #include "panels/foldhaus_panel_animation_timeline.h" #include "panels/foldhaus_panel_hierarchy.h" -#include "panels/foldhaus_panel_node_graph.h" #include "panels/foldhaus_panel_file_view.h" #include "generated/foldhaus_panels_generated.h" diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index ea74af2..0d7ae9a 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -6,13 +6,13 @@ #ifndef FOLDHAUS_ASSEMBLY_CPP internal led_system -LedSystemInitialize(platform_memory_handler PlatformMemory, u32 BuffersMax) +LedSystemInitialize(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 = PlatformAllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax); + Result.Buffers = AllocatorAllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax); return Result; } @@ -43,8 +43,8 @@ LedSystemTakeFreeBuffer(led_system* System, u32 LedCount) led_buffer* Buffer = &System->Buffers[Result]; Buffer->LedCount = LedCount; - Buffer->Colors = PlatformAllocArray(System->PlatformMemory, pixel, Buffer->LedCount); - Buffer->Positions = PlatformAllocArray(System->PlatformMemory, v4, Buffer->LedCount); + Buffer->Colors = AllocatorAllocArray(System->PlatformMemory, pixel, Buffer->LedCount); + Buffer->Positions = AllocatorAllocArray(System->PlatformMemory, v4, Buffer->LedCount); System->LedsCountTotal += LedCount; @@ -56,8 +56,8 @@ LedSystemFreeBuffer(led_system* System, u32 BufferIndex) { Assert(BufferIndex < System->BuffersCountMax); led_buffer* Buffer = &System->Buffers[BufferIndex]; - PlatformFreeArray(System->PlatformMemory, Buffer->Colors, pixel, Buffer->LedCount); - PlatformFreeArray(System->PlatformMemory, Buffer->Positions, v4, Buffer->LedCount); + AllocatorFreeArray(System->PlatformMemory, Buffer->Colors, pixel, Buffer->LedCount); + AllocatorFreeArray(System->PlatformMemory, Buffer->Positions, v4, Buffer->LedCount); System->LedsCountTotal -= Buffer->LedCount; *Buffer = {}; } @@ -77,7 +77,7 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) } internal void -ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition, led_system* LedSystem) +ConstructAssemblyFromDefinition (assembly* Assembly, gs_const_string AssemblyName, v4 RootPosition, led_system* LedSystem) { Assembly->LedBufferIndex = LedSystemTakeFreeBuffer(LedSystem, Assembly->LedCountTotal); led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex); @@ -90,8 +90,8 @@ ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 Roo v2_strip* StripAt = &Assembly->Strips[StripIdx]; StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount); - v4 WS_StripStart = RootPosition + V4(StripAt->StartPosition * Assembly->Scale, 1); - v4 WS_StripEnd = RootPosition + V4(StripAt->EndPosition * Assembly->Scale, 1); + v4 WS_StripStart = RootPosition + ToV4Point(StripAt->StartPosition * Assembly->Scale); + v4 WS_StripEnd = RootPosition + ToV4Point(StripAt->EndPosition * Assembly->Scale); v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)StripAt->LedCount; for (u32 Step = 0; Step < StripAt->LedCount; Step++) @@ -111,25 +111,25 @@ static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, s32 TempAssemblyOffsetsCount = 3; internal void -LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, memory_arena* Scratch, context Context, string Path, event_log* GlobalLog) +LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, gs_memory_arena* Scratch, context Context, gs_const_string Path, event_log* GlobalLog) { - platform_memory_result AssemblyFile = ReadEntireFile(Context, Path); - if (AssemblyFile.Error == PlatformMemory_NoError && AssemblyFile.Data.Size > 0) + gs_file AssemblyFile = ReadEntireFile(Context.ThreadContext.FileHandler, Path); + if (FileNoError(AssemblyFile)) { - string AssemblyFileText = MakeString((char*)AssemblyFile.Data.Base); + gs_string AssemblyFileText = MakeString((char*)AssemblyFile.Memory); Assert(Assemblies->Count < Assemblies->CountMax); assembly* NewAssembly = &Assemblies->Values[Assemblies->Count++]; - s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\'); - string FileName = Substring(Path, IndexOfLastSlash + 1); + s32 IndexOfLastSlash = FindLast(Path, '\\'); + gs_const_string FileName = Substring(Path, IndexOfLastSlash + 1, Path.Length); - NewAssembly->Arena.PlatformMemory = Context.PlatformMemory; - if (ParseAssemblyFile(NewAssembly, AssemblyFileText, Scratch)) + NewAssembly->Arena = CreateMemoryArena(Context.ThreadContext.Allocator); + if (ParseAssemblyFile(NewAssembly, FileName, AssemblyFileText, Scratch)) { v4 Offset = v4{0,0,0,0}; //TempAssemblyOffsets[Assemblies->Count % TempAssemblyOffsetsCount]; ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, LedSystem); - PlatformFree(Context.PlatformMemory, AssemblyFile.Data.Base, AssemblyFile.Data.Size); + AllocatorFree(Context.ThreadContext.Allocator, AssemblyFile.Memory, AssemblyFile.Size); } else { diff --git a/src/app/foldhaus_assembly.h b/src/app/foldhaus_assembly.h index 97c153a..7b47451 100644 --- a/src/app/foldhaus_assembly.h +++ b/src/app/foldhaus_assembly.h @@ -25,7 +25,7 @@ struct led_buffer struct led_system { - platform_memory_handler PlatformMemory; + gs_allocator PlatformMemory; u32 BuffersCountMax; u32 BuffersCount; @@ -62,10 +62,10 @@ struct v2_strip struct assembly { - memory_arena Arena; + gs_memory_arena Arena; - string Name; - string FilePath; + gs_string Name; + gs_string FilePath; r32 Scale; s32 LedCountTotal; diff --git a/src/app/foldhaus_command_dispatch.h b/src/app/foldhaus_command_dispatch.h index 2a7fc1e..3b2d8aa 100644 --- a/src/app/foldhaus_command_dispatch.h +++ b/src/app/foldhaus_command_dispatch.h @@ -8,7 +8,7 @@ #define FOLDHAUS_INPUT_COMMAND_PROC(name) void name(app_state* State, input_entry Event, mouse_state Mouse) typedef FOLDHAUS_INPUT_COMMAND_PROC(input_command_proc); -// NOTE(Peter): Helper function so I don't have to remember the parameters to this define +// NOTE(Peter): Helper function so I don't have to remember the parameters to this define #define ExecFoldhausCommand(cmd) cmd(State, Event, Mouse) enum input_command_flags @@ -55,7 +55,7 @@ struct input_command_queue internal void InitializeInputCommandRegistry (input_command_registry* CommandRegistry, s32 Size, - memory_arena* Storage) + gs_memory_arena* Storage) { CommandRegistry->Commands = PushArray(Storage, input_command, Size); CommandRegistry->Size = Size; @@ -115,8 +115,8 @@ internal void RemoveCommandFromQueue(input_command_queue* Queue, s32 Index) { s32 CommandIndex = Index; - if (CommandIndex < Queue->Used) - { + if (CommandIndex < Queue->Used) + { Queue->Used -= 1; for (; CommandIndex < Queue->Used; CommandIndex++) @@ -132,9 +132,9 @@ RemoveCommandFromQueue(input_command_queue* Queue, input_command Command, input_ s32 CommandIndex = GetCommandIndexInQueue(Queue, Command, Event); // NOTE(Peter): If we made it through the queue without finding an event, there wasn't one - // to remove. This happens when we've changed command registries as a result of an input command, + // to remove. This happens when we've changed command registries as a result of an input command, // and the command exists in the new registry. - // For example: + // For example: // clicking a mouse button triggers a command to switch registries // the new registry tracks mouse drag (persist until release) // when the mouse is released, the event fires, but there is no mouse down event to remove diff --git a/src/app/foldhaus_debug.h b/src/app/foldhaus_debug.h index c987469..c45ad69 100644 --- a/src/app/foldhaus_debug.h +++ b/src/app/foldhaus_debug.h @@ -30,7 +30,7 @@ struct collated_scope_record struct scope_name { u32 Hash; - string Name; + gs_string Name; char Buffer[SCOPE_NAME_BUFFER_LENGTH]; }; @@ -82,7 +82,7 @@ typedef u8* debug_realloc(u8* Memory, s32 OldSize, s32 NewSize); struct debug_histogram_entry { char ScopeName_[SCOPE_NAME_LENGTH]; - string ScopeName; + gs_string ScopeName; u32 PerFrame_Cycles[HISTOGRAM_DEPTH]; u32 PerFrame_CallCount[HISTOGRAM_DEPTH]; @@ -168,12 +168,12 @@ StartDebugFrame(debug_frame* Frame, debug_services* Services) } internal void -InitDebugServices (debug_services* Services, - s64 PerformanceCountFrequency, - debug_alloc* Alloc, - debug_realloc* Realloc, - debug_timing_proc* GetWallClock, - debug_get_thread_id* GetThreadId, +InitDebugServices (debug_services* Services, + s64 PerformanceCountFrequency, + debug_alloc* Alloc, + debug_realloc* Realloc, + debug_timing_proc* GetWallClock, + debug_get_thread_id* GetThreadId, s32 ThreadCount) { Services->Alloc = Alloc; @@ -233,7 +233,7 @@ GetIndexForNameHash(debug_frame* Frame, u32 NameHash) } // 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 + // 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; @@ -359,9 +359,9 @@ BeginTrackingScopeAndGetNameHash (debug_services* Services, char* ScopeName) if (Entry->Hash == 0) // If its new { Entry->Hash = NameHash; - // TODO(Peter): need to initialize all entry name strings to point at the buffer + // 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 - CopyCharArrayToString(ScopeName, &Entry->Name); + PrintF(&Entry->Name, "%s", ScopeName); } return NameHash; @@ -402,7 +402,7 @@ internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFre #define DEBUG_TRACK_FUNCTION scope_tracker ScopeTracker ((char*)__func__, GlobalDebugServices) #define DEBUG_TRACK_SCOPE(name) scope_tracker ScopeTracker_##name (#name, GlobalDebugServices) #else -#define DEBUG_TRACK_FUNCTION +#define DEBUG_TRACK_FUNCTION #define DEBUG_TRACK_SCOPE(name) #endif struct scope_tracker diff --git a/src/app/foldhaus_interface.cpp b/src/app/foldhaus_interface.cpp index f9345cb..e5e4e43 100644 --- a/src/app/foldhaus_interface.cpp +++ b/src/app/foldhaus_interface.cpp @@ -41,7 +41,7 @@ OPERATION_STATE_DEF(drag_panel_border_operation_state) // NOTE(Peter): InitialPanelBounds is the bounds of the panel we are modifying, // it stores the value calculated when the operation mode is kicked off. - rect InitialPanelBounds; + rect2 InitialPanelBounds; panel_split_direction PanelEdgeDirection; panel_edit_mode PanelEditMode; }; @@ -49,7 +49,7 @@ OPERATION_STATE_DEF(drag_panel_border_operation_state) OPERATION_RENDER_PROC(UpdateAndRenderDragPanelBorder) { drag_panel_border_operation_state* OpState = (drag_panel_border_operation_state*)Operation.OpStateMemory; - rect PanelBounds = OpState->InitialPanelBounds; + rect2 PanelBounds = OpState->InitialPanelBounds; if (OpState->PanelEditMode == PanelEdit_Modify) { @@ -72,10 +72,10 @@ OPERATION_RENDER_PROC(UpdateAndRenderDragPanelBorder) } else if (OpState->PanelEditMode == PanelEdit_Destroy) { - rect PanelToDeleteBounds = {}; + rect2 PanelToDeleteBounds = {}; if (OpState->PanelEdgeDirection == PanelSplit_Horizontal) { - r32 SplitY = GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, OpState->Panel->SplitPercent); + r32 SplitY = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y); if (Mouse.Pos.y > SplitY) { PanelToDeleteBounds = GetTopPanelBounds(OpState->Panel, PanelBounds); @@ -87,7 +87,7 @@ OPERATION_RENDER_PROC(UpdateAndRenderDragPanelBorder) } else if (OpState->PanelEdgeDirection == PanelSplit_Vertical) { - r32 SplitX = GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, OpState->Panel->SplitPercent); + r32 SplitX = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x); if (Mouse.Pos.x > SplitX) { PanelToDeleteBounds = GetRightPanelBounds(OpState->Panel, PanelBounds); @@ -106,7 +106,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) { drag_panel_border_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_panel_border_operation_state); panel* Panel = OpState->Panel; - rect PanelBounds = OpState->InitialPanelBounds; + rect2 PanelBounds = OpState->InitialPanelBounds; if (OpState->PanelEditMode == PanelEdit_Modify) { @@ -123,7 +123,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) } else { - Panel->SplitPercent = (NewSplitY - PanelBounds.Min.y) / gs_Height(PanelBounds); + Panel->SplitPercent = (NewSplitY - PanelBounds.Min.y) / Rect2Height(PanelBounds); } } else if (Panel->SplitDirection == PanelSplit_Vertical) @@ -139,7 +139,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) } else { - Panel->SplitPercent = (NewSplitX - PanelBounds.Min.x) / gs_Width(PanelBounds); + Panel->SplitPercent = (NewSplitX - PanelBounds.Min.x) / Rect2Width(PanelBounds); } } } @@ -147,7 +147,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) { if (OpState->PanelEdgeDirection == PanelSplit_Horizontal) { - r32 SplitY = GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, OpState->Panel->SplitPercent); + r32 SplitY = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y); if (Mouse.Pos.y > SplitY) { ConsolidatePanelsKeepOne(Panel, Panel->Bottom, &State->PanelSystem); @@ -159,7 +159,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) } else if (OpState->PanelEdgeDirection == PanelSplit_Vertical) { - r32 SplitX = GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, OpState->Panel->SplitPercent); + r32 SplitX = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x); if (Mouse.Pos.x > SplitX) { ConsolidatePanelsKeepOne(Panel, Panel->Left, &State->PanelSystem); @@ -180,7 +180,7 @@ input_command DragPanelBorderCommands[] = { }; internal void -BeginDragPanelBorder(panel* Panel, panel_edit_mode PanelEditMode, rect PanelBounds, panel_split_direction PanelEdgeDirection, mouse_state Mouse, app_state* State) +BeginDragPanelBorder(panel* Panel, panel_edit_mode PanelEditMode, rect2 PanelBounds, panel_split_direction PanelEdgeDirection, mouse_state Mouse, app_state* State) { operation_mode* DragPanelBorder = ActivateOperationModeWithCommands(&State->Modes, DragPanelBorderCommands, UpdateAndRenderDragPanelBorder); drag_panel_border_operation_state* OpState = CreateOperationState(DragPanelBorder, &State->Modes, drag_panel_border_operation_state); @@ -202,17 +202,17 @@ OPERATION_STATE_DEF(split_panel_operation_state) // NOTE(Peter): InitialPanelBounds is the bounds of the panel we are modifying, // it stores the value calculated when the operation mode is kicked off. - rect InitialPanelBounds; + rect2 InitialPanelBounds; }; OPERATION_RENDER_PROC(UpdateAndRenderSplitPanel) { split_panel_operation_state* OpState = (split_panel_operation_state*)Operation.OpStateMemory; - rect PanelBounds = OpState->InitialPanelBounds; + rect2 PanelBounds = OpState->InitialPanelBounds; v4 EdgePreviewColor = v4{.3f, .3f, .3f, 1.f}; - r32 MouseDeltaX = GSAbs(Mouse.Pos.x - Mouse.DownPos.x); - r32 MouseDeltaY = GSAbs(Mouse.Pos.y - Mouse.DownPos.y); + r32 MouseDeltaX = Abs(Mouse.Pos.x - Mouse.DownPos.x); + r32 MouseDeltaY = Abs(Mouse.Pos.y - Mouse.DownPos.y); v2 EdgePreviewMin = {}; v2 EdgePreviewMax = {}; @@ -234,19 +234,19 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation) { split_panel_operation_state* OpState = GetCurrentOperationState(State->Modes, split_panel_operation_state); panel* Panel = OpState->Panel; - rect PanelBounds = OpState->InitialPanelBounds; + rect2 PanelBounds = OpState->InitialPanelBounds; - r32 XDistance = GSAbs(Mouse.Pos.x - Mouse.DownPos.x); - r32 YDistance = GSAbs(Mouse.Pos.y - Mouse.DownPos.y); + r32 XDistance = Abs(Mouse.Pos.x - Mouse.DownPos.x); + r32 YDistance = Abs(Mouse.Pos.y - Mouse.DownPos.y); if (XDistance > YDistance) { - r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / gs_Width(PanelBounds); + r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / Rect2Width(PanelBounds); SplitPanelVertically(Panel, XPercent, &State->PanelSystem); } else { - r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / gs_Height(PanelBounds); + r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / Rect2Height(PanelBounds); SplitPanelHorizontally(Panel, YPercent, &State->PanelSystem); } @@ -264,7 +264,7 @@ input_command SplitPanelCommands[] = { }; internal void -BeginSplitPanelOperation(panel* Panel, rect PanelBounds, mouse_state Mouse, app_state* State) +BeginSplitPanelOperation(panel* Panel, rect2 PanelBounds, mouse_state Mouse, app_state* State) { operation_mode* SplitPanel = ActivateOperationModeWithCommands(&State->Modes, SplitPanelCommands, UpdateAndRenderSplitPanel); split_panel_operation_state* OpState = CreateOperationState(SplitPanel, &State->Modes, split_panel_operation_state); @@ -278,20 +278,22 @@ BeginSplitPanelOperation(panel* Panel, rect PanelBounds, mouse_state Mouse, app_ #define PANEL_EDGE_CLICK_MAX_DISTANCE 6 internal b32 -HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEditMode, rect PanelBounds, mouse_state Mouse, app_state* State) +HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEditMode, rect2 PanelBounds, mouse_state Mouse, app_state* State) { b32 HandledMouseInput = false; + rect2 PanelSplitButtonBounds = rect2{ PanelBounds.Min, PanelBounds.Min + v2{25, 25} }; + if (Panel->SplitDirection == PanelSplit_NoSplit - && PointIsInRange(Mouse.DownPos, PanelBounds.Min, PanelBounds.Min + v2{25, 25})) + && PointIsInRect(PanelSplitButtonBounds, Mouse.DownPos)) { BeginSplitPanelOperation(Panel, PanelBounds, Mouse, State); HandledMouseInput = true; } else if (Panel->SplitDirection == PanelSplit_Horizontal) { - r32 SplitY = GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, Panel->SplitPercent); - r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.y - SplitY); + r32 SplitY = LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y); + r32 ClickDistanceFromSplit = Abs(Mouse.DownPos.y - SplitY); if (ClickDistanceFromSplit < PANEL_EDGE_CLICK_MAX_DISTANCE) { BeginDragPanelBorder(Panel, PanelEditMode, PanelBounds, PanelSplit_Horizontal, Mouse, State); @@ -299,13 +301,13 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit } else { - rect TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); - rect BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); - if (gs_PointIsInRect(Mouse.DownPos, BottomPanelBounds)) + rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); + rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); + if (PointIsInRect(BottomPanelBounds, Mouse.DownPos)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Bottom->Panel, PanelEditMode, BottomPanelBounds, Mouse, State); } - if (gs_PointIsInRect(Mouse.DownPos, TopPanelBounds)) + if (PointIsInRect(TopPanelBounds, Mouse.DownPos)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Top->Panel, PanelEditMode, TopPanelBounds, Mouse, State); } @@ -313,8 +315,8 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit } else if (Panel->SplitDirection == PanelSplit_Vertical) { - r32 SplitX = GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, Panel->SplitPercent); - r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.x - SplitX); + r32 SplitX = LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x); + r32 ClickDistanceFromSplit = Abs(Mouse.DownPos.x - SplitX); if (ClickDistanceFromSplit < PANEL_EDGE_CLICK_MAX_DISTANCE) { BeginDragPanelBorder(Panel, PanelEditMode, PanelBounds, PanelSplit_Vertical, Mouse, State); @@ -322,13 +324,13 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit } else { - rect LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); - rect RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); - if (gs_PointIsInRect(Mouse.DownPos, LeftPanelBounds)) + rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); + rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); + if (PointIsInRect(LeftPanelBounds, Mouse.DownPos)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Left->Panel, PanelEditMode, LeftPanelBounds, Mouse, State); } - if (gs_PointIsInRect(Mouse.DownPos, RightPanelBounds)) + if (PointIsInRect(RightPanelBounds, Mouse.DownPos)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Right->Panel, PanelEditMode, RightPanelBounds, Mouse, State); } @@ -339,7 +341,7 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit } internal b32 -HandleMousePanelInteraction(panel_system* PanelSystem, rect WindowBounds, mouse_state Mouse, app_state* State) +HandleMousePanelInteraction(panel_system* PanelSystem, rect2 WindowBounds, mouse_state Mouse, app_state* State) { b32 HandledMouseInput = false; @@ -359,10 +361,10 @@ HandleMousePanelInteraction(panel_system* PanelSystem, rect WindowBounds, mouse_ internal void DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, mouse_state* Mouse, render_command_buffer* RenderBuffer) { - r32 MouseLeftEdgeDistance = GSAbs(Mouse->Pos.x - PanelMin.x); - r32 MouseRightEdgeDistance = GSAbs(Mouse->Pos.x - PanelMax.x); - r32 MouseTopEdgeDistance = GSAbs(Mouse->Pos.y - PanelMax.y); - r32 MouseBottomEdgeDistance = GSAbs(Mouse->Pos.y - PanelMin.y); + r32 MouseLeftEdgeDistance = Abs(Mouse->Pos.x - PanelMin.x); + r32 MouseRightEdgeDistance = Abs(Mouse->Pos.x - PanelMax.x); + r32 MouseTopEdgeDistance = Abs(Mouse->Pos.y - PanelMax.y); + r32 MouseBottomEdgeDistance = Abs(Mouse->Pos.y - PanelMin.y); PushRenderBoundingBox2D(RenderBuffer, PanelMin, PanelMax, 1, Color); v4 HighlightColor = v4{.3f, .3f, .3f, 1.f}; @@ -398,41 +400,46 @@ DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, mouse_state* Mo } internal void -DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBounds, mouse_state Mouse, app_state* State) +DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterBounds, mouse_state Mouse, app_state* State) { PushRenderQuad2D(RenderBuffer, FooterBounds.Min, v2{FooterBounds.Max.x, FooterBounds.Min.y + 25}, v4{.5f, .5f, .5f, 1.f}); PushRenderQuad2D(RenderBuffer, FooterBounds.Min, FooterBounds.Min + v2{25, 25}, WhiteV4); - rect PanelSelectBtnBounds = gs_MakeRectMinWidth(FooterBounds.Min + v2{30, 1}, v2{100, 23}); + rect2 PanelSelectBtnBounds = MakeRect2MinDim(FooterBounds.Min + v2{30, 1}, v2{100, 23}); if (Panel->PanelSelectionMenuOpen) { - rect ButtonBounds = gs_MakeRectMinWidth(v2{ PanelSelectBtnBounds.Min.x, FooterBounds.Max.y }, v2{ 100, 25 }); + rect2 ButtonBounds = MakeRect2MinDim(v2{ PanelSelectBtnBounds.Min.x, FooterBounds.Max.y }, v2{ 100, 25 }); + + rect2 MenuBounds = rect2 + { + ButtonBounds.Min, + v2{ + ButtonBounds.Min.x + Rect2Width(ButtonBounds), ButtonBounds.Min.y + (Rect2Height(ButtonBounds) * GlobalPanelDefsCount) + }, + }; - v2 MenuMin = ButtonBounds.Min; - v2 MenuMax = v2{ButtonBounds.Min.x + gs_Width(ButtonBounds), ButtonBounds.Min.y + (gs_Height(ButtonBounds) * GlobalPanelDefsCount)}; if (MouseButtonTransitionedDown(Mouse.LeftButtonState) - && !PointIsInRange(Mouse.DownPos, MenuMin, MenuMax)) + && !PointIsInRect(MenuBounds, Mouse.DownPos)) { Panel->PanelSelectionMenuOpen = false; } - for (s32 i = 0; i < GlobalPanelDefsCount; i++) { panel_definition Def = GlobalPanelDefs[i]; - string DefName = MakeString(Def.PanelName, Def.PanelNameLength); + gs_string DefName = MakeString(Def.PanelName, Def.PanelNameLength); if (ui_Button(&State->Interface, DefName, ButtonBounds)) { SetPanelDefinition(Panel, i, State); Panel->PanelSelectionMenuOpen = false; } - ButtonBounds = gs_TranslateRectY(ButtonBounds, gs_Height(ButtonBounds)); + ButtonBounds = Rect2TranslateY(ButtonBounds, Rect2Height(ButtonBounds)); } } - if (ui_Button(&State->Interface, MakeStringLiteral("Select"), PanelSelectBtnBounds)) + if (ui_Button(&State->Interface, MakeString("Select"), PanelSelectBtnBounds)) { Panel->PanelSelectionMenuOpen = !Panel->PanelSelectionMenuOpen; } @@ -440,15 +447,15 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBo } internal void -RenderPanel(panel* Panel, rect PanelBounds, rect WindowBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +RenderPanel(panel* Panel, rect2 PanelBounds, rect2 WindowBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) { Assert(Panel->PanelDefinitionIndex >= 0); - rect FooterBounds = rect{ + rect2 FooterBounds = rect2{ PanelBounds.Min, v2{PanelBounds.Max.x, PanelBounds.Min.y + 25}, }; - rect PanelViewBounds = rect{ + rect2 PanelViewBounds = rect2{ v2{PanelBounds.Min.x, FooterBounds.Max.y}, PanelBounds.Max, }; @@ -456,7 +463,7 @@ RenderPanel(panel* Panel, rect PanelBounds, rect WindowBounds, render_command_bu panel_definition Definition = GlobalPanelDefs[Panel->PanelDefinitionIndex]; Definition.Render(*Panel, PanelViewBounds, RenderBuffer, State, Context); - PushRenderOrthographic(RenderBuffer, WindowBounds.Min.x, WindowBounds.Min.y, WindowBounds.Max.x, WindowBounds.Max.y); + PushRenderOrthographic(RenderBuffer, WindowBounds); DrawPanelFooter(Panel, RenderBuffer, FooterBounds, Mouse, State); } @@ -467,12 +474,12 @@ DrawAllPanels(panel_layout PanelLayout, render_command_buffer* RenderBuffer, mou { panel_with_layout PanelWithLayout = PanelLayout.Panels[i]; panel* Panel = PanelWithLayout.Panel; - rect PanelBounds = PanelWithLayout.Bounds; + rect2 PanelBounds = PanelWithLayout.Bounds; RenderPanel(Panel, PanelBounds, State->WindowBounds, RenderBuffer, State, Context, *Mouse); v4 BorderColor = v4{0, 0, 0, 1}; - PushRenderOrthographic(RenderBuffer, State->WindowBounds.Min.x, State->WindowBounds.Min.y, State->WindowBounds.Max.x, State->WindowBounds.Max.y); + PushRenderOrthographic(RenderBuffer, State->WindowBounds); DrawPanelBorder(*Panel, PanelBounds.Min, PanelBounds.Max, BorderColor, Mouse, RenderBuffer); } } diff --git a/src/app/foldhaus_log.h b/src/app/foldhaus_log.h index 12ed933..0cffd1a 100644 --- a/src/app/foldhaus_log.h +++ b/src/app/foldhaus_log.h @@ -13,7 +13,7 @@ enum log_entry_type struct log_entry { - string Message; + gs_string Message; log_entry_type Type; }; @@ -25,11 +25,11 @@ struct event_log u32 NextEntry; }; -#define LogMessage(_Log, _Message) PushLogEntry(_Log, MakeStringLiteral(_Message), LogEntry_Message) -#define LogError(_Log, _Message) PushLogEntry(_Log, MakeStringLiteral(_Message), LogEntry_Error) +#define LogMessage(_Log, _Message) PushLogEntry(_Log, MakeString(_Message), LogEntry_Message) +#define LogError(_Log, _Message) PushLogEntry(_Log, MakeString(_Message), LogEntry_Error) internal void -PushLogEntry(event_log* Log, string Message, log_entry_type Type) +PushLogEntry(event_log* Log, gs_string Message, log_entry_type Type) { u32 NewLogIndex = Log->NextEntry++; if (Log->NextEntry >= LOG_ENTRIES_MAX) diff --git a/src/app/foldhaus_node.cpp b/src/app/foldhaus_node.cpp index 29e93a9..092d55f 100644 --- a/src/app/foldhaus_node.cpp +++ b/src/app/foldhaus_node.cpp @@ -45,7 +45,7 @@ SortNodeNeighbors(u32 ContiguousNodeIndex, gs_list_handle NodeHandle, adjacency_ u32 ContiguousNeighborNodeIndex = SparseToContiguousNodeMap[Neighbor->NodeHandle.Index]; if (!NodesVisited[ContiguousNeighborNodeIndex]) { - SortedNodesCount = SortNodeNeighbors(ContiguousNeighborNodeIndex, Neighbor->NodeHandle, NeighborsLists, NodesVisited, SortedNodeHandles, SortedNodesCount, SparseToContiguousNodeMap); + SortedNodesCount = SortNodeNeighbors(ContiguousNeighborNodeIndex, Neighbor->NodeHandle, NeighborsLists, NodesVisited, SortedNodeHandles, SortedNodesCount, SparseToContiguousNodeMap); } Neighbor = Neighbor->Next; } @@ -55,7 +55,7 @@ SortNodeNeighbors(u32 ContiguousNodeIndex, gs_list_handle NodeHandle, adjacency_ } internal s32* -CreateSparseToContiguousMap (pattern_node_workspace Workspace, memory_arena* Scratch) +CreateSparseToContiguousMap (pattern_node_workspace Workspace, gs_memory_arena* Scratch) { s32* Result = PushArray(Scratch, s32, Workspace.Nodes.OnePastLastUsed); s32 ContiguousIndex = 0; @@ -71,7 +71,7 @@ CreateSparseToContiguousMap (pattern_node_workspace Workspace, memory_arena* Scr } internal void -UpdateSortedNodes(pattern_node_workspace* Workspace, memory_arena* Scratch) +UpdateSortedNodes(pattern_node_workspace* Workspace, gs_memory_arena* Scratch) { ClearNodeWorkspaceStorage(Workspace); @@ -81,7 +81,7 @@ UpdateSortedNodes(pattern_node_workspace* Workspace, memory_arena* Scratch) s32* SparseToContiguousNodeMap = CreateSparseToContiguousMap(*Workspace, &Workspace->Storage); // NOTE(Peter): We need to sort this later on so I'm just storing list lengths in this format - // to begin with. + // to begin with. // NeighborsListLengths[n].Radix = the number of neighbors for the node // NeighborsListLengths[n].ID = the sparse array index of the node gs_radix_entry* NeighborsListLengths = PushArray(Scratch, gs_radix_entry, NodeCount); @@ -119,24 +119,24 @@ UpdateSortedNodes(pattern_node_workspace* Workspace, memory_arena* Scratch) RadixSortInPlace(NeighborsListLengths, Workspace->Nodes.Used); char* OutputCharArray = PushArray(Scratch, char, 1024); - string OutputString = MakeString(OutputCharArray, 0, 1024); + gs_string Outputgs_string = MakeString(OutputCharArray, 0, 1024); - PrintF(&OutputString, "Neighbors Lists: \n"); + PrintF(&Outputgs_string, "Neighbors Lists: \n"); for (u32 d = 0; d < Workspace->Nodes.Used; d++) { - PrintF(&OutputString, " %d: Node [ %d ] : neighbors { ", d, NeighborsListLengths[d].ID); + PrintF(&Outputgs_string, " %d: Node [ %d ] : neighbors { ", d, NeighborsListLengths[d].ID); adjacency_list* Neighbors = NeighborsLists[d]; while (Neighbors) { - PrintF(&OutputString, "%d, ", Neighbors->NodeHandle.Index); + PrintF(&Outputgs_string, "%d, ", Neighbors->NodeHandle.Index); Neighbors = Neighbors->Next; } - PrintF(&OutputString, " }\n"); + PrintF(&Outputgs_string, " }\n"); } - NullTerminate(&OutputString); + NullTerminate(&Outputgs_string); - // This is a contiguous array. + // This is a contiguous array. b8* NodesVisited = PushArray(Scratch, b8, NodeCount); GSZeroArray(NodesVisited, b8, NodeCount); @@ -163,7 +163,7 @@ UpdateSortedNodes(pattern_node_workspace* Workspace, memory_arena* Scratch) } internal void -PushNodeOnWorkspace(s32 NodeSpecificationIndex, pattern_node_workspace* Workspace, memory_arena* Scratch) +PushNodeOnWorkspace(s32 NodeSpecificationIndex, pattern_node_workspace* Workspace, gs_memory_arena* Scratch) { pattern_node* NewNode = Workspace->Nodes.TakeElement(); NewNode->SpecificationIndex = NodeSpecificationIndex; @@ -172,13 +172,13 @@ PushNodeOnWorkspace(s32 NodeSpecificationIndex, pattern_node_workspace* Workspac } internal void -PushNodeConnectionOnWorkspace(gs_list_handle UpstreamNodeHandle, u32 UpstreamPortIndex, gs_list_handle DownstreamNodeHandle, u32 DownstreamPortIndex, pattern_node_workspace* Workspace, memory_arena* Scratch) +PushNodeConnectionOnWorkspace(gs_list_handle UpstreamNodeHandle, u32 UpstreamPortIndex, gs_list_handle DownstreamNodeHandle, u32 DownstreamPortIndex, pattern_node_workspace* Workspace, gs_memory_arena* Scratch) { pattern_node_connection Connection = {}; - Connection.UpstreamNodeHandle = UpstreamNodeHandle; - Connection.DownstreamNodeHandle = DownstreamNodeHandle; - Connection.UpstreamPortIndex = UpstreamPortIndex; - Connection.DownstreamPortIndex = DownstreamPortIndex; + Connection.UpstreamNodeHandle = UpstreamNodeHandle; + Connection.DownstreamNodeHandle = DownstreamNodeHandle; + Connection.UpstreamPortIndex = UpstreamPortIndex; + Connection.DownstreamPortIndex = DownstreamPortIndex; Workspace->Connections.PushElementOnBucket(Connection); UpdateSortedNodes(Workspace, Scratch); diff --git a/src/app/foldhaus_node.h b/src/app/foldhaus_node.h index 17a6c7b..b286b28 100644 --- a/src/app/foldhaus_node.h +++ b/src/app/foldhaus_node.h @@ -59,7 +59,7 @@ struct node_specification struct node_specification_ { node_type Type; - string Identifier; + gs_string Identifier; gsm_struct_type DataType; }; @@ -92,7 +92,7 @@ struct pattern_node_workspace // This is storage for all the structures which follow. // It is cleared when new nodes are added so that the // acceleration structures can be recalculated - memory_arena Storage; + gs_memory_arena Storage; s32* SparseToSortedNodeMap; gs_list_handle* SortedNodeHandles; }; diff --git a/src/app/foldhaus_operation_mode.h b/src/app/foldhaus_operation_mode.h index 49d71bd..80c1641 100644 --- a/src/app/foldhaus_operation_mode.h +++ b/src/app/foldhaus_operation_mode.h @@ -16,6 +16,7 @@ struct operation_mode { input_command_registry Commands; operation_render_proc* Render; + gs_memory_cursor Memory; u8* OpStateMemory; }; @@ -24,28 +25,66 @@ struct operation_mode_system { s32 ActiveModesCount; operation_mode ActiveModes[OPERATION_MODES_MAX]; - arena_snapshot ModeMemorySnapshots[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 - memory_arena Arena; + 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 = 16; // TODO(Peter): Static number of modes that can be active simultaneously + Result.ModeMemoryPagesFreeList.Data = PushArray(Storage, gs_data, Result.ModeMemoryPagesFreeList.CountMax); + for (u32 Page = 0; Page < Result.ModeMemoryPagesFreeList.CountMax; Page++) + { + // TODO(Peter): 4k pages = page size on windows + Result.ModeMemoryPagesFreeList.Data[Page] = PushSizeToData(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; +} + +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; +} + internal operation_mode* ActivateOperationMode (operation_mode_system* System, operation_render_proc* RenderProc) { - operation_mode* Result = 0; - Assert(System->ActiveModesCount < OPERATION_MODES_MAX); + operation_mode* Result = 0; s32 ModeIndex = System->ActiveModesCount++; - System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(&System->Arena); - - operation_mode NewMode = {}; - System->ActiveModes[ModeIndex] = NewMode; + //System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(&System->Arena); Result = &System->ActiveModes[ModeIndex]; + Result->Memory = CreateMemoryCursor(OperationModeTakeMemoryPage(System)); Result->Render = RenderProc; + return Result; } @@ -57,13 +96,18 @@ ActivateOperationModeWithCommands_(operation_mode_system* System, input_command* { 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); } - +#else + NewMode->Commands.Commands = Commands; + NewMode->Commands.Size = CommandsCount; + NewMode->Commands.Used = CommandsCount; +#endif return NewMode; } @@ -72,7 +116,8 @@ DeactivateCurrentOperationMode (operation_mode_system* System) { Assert(System->ActiveModesCount > 0); s32 ModeIndex = --System->ActiveModesCount; - ClearArenaToSnapshot(&System->Arena, System->ModeMemorySnapshots[ModeIndex]); + OperationModeFreeMemoryPage(System, System->ActiveModes[ModeIndex].Memory.Data); + //ClearArenaToSnapshot(&System->Arena, System->ModeMemorySnapshots[ModeIndex]); } #define CreateOperationState(mode, modeSystem, stateType) \ @@ -85,8 +130,12 @@ DeactivateCurrentOperationMode (operation_mode_system* System) internal u8* CreateOperationState_ (operation_mode* Mode, operation_mode_system* System, s32 StateSize) { - Mode->OpStateMemory = PushSize(&System->Arena, StateSize); - return Mode->OpStateMemory; + // 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; } diff --git a/src/app/foldhaus_panel.h b/src/app/foldhaus_panel.h index 2929c8b..53415f1 100644 --- a/src/app/foldhaus_panel.h +++ b/src/app/foldhaus_panel.h @@ -72,7 +72,7 @@ struct panel_system struct panel_with_layout { panel* Panel; - rect Bounds; + rect2 Bounds; }; struct panel_layout @@ -205,56 +205,56 @@ ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_sys // ///////////////////////////////// -internal rect -GetTopPanelBounds(panel* Panel, rect PanelBounds) +internal rect2 +GetTopPanelBounds(panel* Panel, rect2 PanelBounds) { - rect Result = {}; + rect2 Result = {}; Result.Min = v2{ PanelBounds.Min.x, - GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, Panel->SplitPercent) + LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y) }; Result.Max = PanelBounds.Max; return Result; } -internal rect -GetBottomPanelBounds(panel* Panel, rect PanelBounds) +internal rect2 +GetBottomPanelBounds(panel* Panel, rect2 PanelBounds) { - rect Result = {}; + rect2 Result = {}; Result.Min = PanelBounds.Min; Result.Max = v2{ PanelBounds.Max.x, - GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, Panel->SplitPercent) + LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y) }; return Result; } -internal rect -GetRightPanelBounds(panel* Panel, rect PanelBounds) +internal rect2 +GetRightPanelBounds(panel* Panel, rect2 PanelBounds) { - rect Result = {}; + rect2 Result = {}; Result.Min = v2{ - GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, Panel->SplitPercent), + LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x), PanelBounds.Min.y }; Result.Max = PanelBounds.Max; return Result; } -internal rect -GetLeftPanelBounds(panel* Panel, rect PanelBounds) +internal rect2 +GetLeftPanelBounds(panel* Panel, rect2 PanelBounds) { - rect Result = {}; + rect2 Result = {}; Result.Min = PanelBounds.Min; Result.Max = v2{ - GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, Panel->SplitPercent), + LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x), PanelBounds.Max.y }; return Result; } internal void -LayoutPanel(panel* Panel, rect PanelBounds, panel_layout* Layout) +LayoutPanel(panel* Panel, rect2 PanelBounds, panel_layout* Layout) { if (Panel->SplitDirection == PanelSplit_NoSplit) { @@ -264,22 +264,22 @@ LayoutPanel(panel* Panel, rect PanelBounds, panel_layout* Layout) } else if (Panel->SplitDirection == PanelSplit_Horizontal) { - rect TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); - rect BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); + rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); + rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); LayoutPanel(&Panel->Top->Panel, TopPanelBounds, Layout); LayoutPanel(&Panel->Bottom->Panel, BottomPanelBounds, Layout); } else if (Panel->SplitDirection == PanelSplit_Vertical) { - rect LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); - rect RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); + rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); + rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); LayoutPanel(&Panel->Left->Panel, LeftPanelBounds, Layout); LayoutPanel(&Panel->Right->Panel, RightPanelBounds, Layout); } } internal panel_layout -GetPanelLayout(panel_system* System, rect WindowBounds, memory_arena* Storage) +GetPanelLayout(panel_system* System, rect2 WindowBounds, gs_memory_arena* Storage) { panel_layout Result = {}; Result.PanelsMax = System->PanelsUsed; @@ -293,11 +293,11 @@ GetPanelLayout(panel_system* System, rect WindowBounds, memory_arena* Storage) struct panel_and_bounds { panel* Panel; - rect Bounds; + rect2 Bounds; }; internal panel_and_bounds -GetPanelContainingPoint(v2 Point, panel* Panel, rect PanelBounds) +GetPanelContainingPoint(v2 Point, panel* Panel, rect2 PanelBounds) { panel_and_bounds Result = {0}; @@ -308,28 +308,28 @@ GetPanelContainingPoint(v2 Point, panel* Panel, rect PanelBounds) } else if (Panel->SplitDirection == PanelSplit_Horizontal) { - rect TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); - rect BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); + rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); + rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); - if (PointIsInRange(Point, TopPanelBounds.Min, TopPanelBounds.Max)) + if (PointIsInRect(TopPanelBounds, Point)) { Result = GetPanelContainingPoint(Point, &Panel->Top->Panel, TopPanelBounds); } - else if (PointIsInRange(Point, BottomPanelBounds.Min, BottomPanelBounds.Max)) + else if (PointIsInRect(BottomPanelBounds, Point)) { Result = GetPanelContainingPoint(Point, &Panel->Bottom->Panel, BottomPanelBounds); } } else if (Panel->SplitDirection == PanelSplit_Vertical) { - rect LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); - rect RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); + rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); + rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); - if (PointIsInRange(Point, LeftPanelBounds.Min, LeftPanelBounds.Max)) + if (PointIsInRect(LeftPanelBounds, Point)) { Result = GetPanelContainingPoint(Point, &Panel->Left->Panel, LeftPanelBounds); } - else if (PointIsInRange(Point, RightPanelBounds.Min, RightPanelBounds.Max)) + else if (PointIsInRect(RightPanelBounds, Point)) { Result = GetPanelContainingPoint(Point, &Panel->Right->Panel, RightPanelBounds); } @@ -339,7 +339,7 @@ GetPanelContainingPoint(v2 Point, panel* Panel, rect PanelBounds) } internal panel_and_bounds -GetPanelContainingPoint(v2 Point, panel_system* PanelSystem, rect WindowBounds) +GetPanelContainingPoint(v2 Point, panel_system* PanelSystem, rect2 WindowBounds) { panel_and_bounds Result = {0}; if (PanelSystem->PanelsUsed > 0) diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index f8f801c..4f066d4 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -7,22 +7,30 @@ #include -#define GS_LANGUAGE_NO_PROFILER_DEFINES -#include "..\gs_libs\gs_language.h" +#include // TODO Remove -#include "..\gs_libs\gs_radix_sort.h" +#include "..\gs_libs\gs_types.h" +#include "..\gs_libs\gs_types.cpp" + +//#define GS_LANGUAGE_NO_PROFILER_DEFINES +//#include "..\gs_libs\gs_language.h" + + +//#include "..\gs_libs\gs_radix_sort.h" #include "..\gs_libs\gs_list.h" #include "..\gs_libs\gs_bucket.h" -#define GS_MEMORY_TRACK_ALLOCATIONS -#include "..\gs_libs\gs_memory_arena.h" +//#define GS_MEMORY_TRACK_ALLOCATIONS +//#include "..\gs_libs\gs_memory_arena.h" #include "..\gs_libs\gs_string.h" -#include "foldhaus_debug.h" -global_variable debug_services* GlobalDebugServices; -#include "..\gs_libs\gs_vector_matrix.h" + +#include "foldhaus_debug.h" +global debug_services* GlobalDebugServices; + +//#include "..\gs_libs\gs_vector_matrix.h" #include "..\gs_libs\gs_input.h" #include "foldhaus_renderer.h" @@ -75,15 +83,6 @@ struct platform_memory_result platform_memory_error Error; }; -struct texture_buffer -{ - u8* Memory; - s32 Width; - s32 Height; - s32 Pitch; - s32 BytesPerPixel; -}; - struct system_path { char* Path; @@ -91,20 +90,13 @@ struct system_path s32 IndexOfLastSlash; }; -#define PLATFORM_READ_ENTIRE_FILE(name) platform_memory_result name(string Path) -typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file); - -#define PLATFORM_WRITE_ENTIRE_FILE(name) b32 name(string Path, u8* Contents, s32 Size) -typedef PLATFORM_WRITE_ENTIRE_FILE(platform_write_entire_file); - -#define PLATFORM_GET_FILE_PATH(name) b32 name(string* PathBuffer, const char* FilterStrings) -typedef PLATFORM_GET_FILE_PATH(platform_get_file_path); - -struct platform_file_handler +struct texture_buffer { - platform_read_entire_file* ReadEntireFile; - platform_write_entire_file* WriteEntireFile; - platform_get_file_path* GetFilePath; + u8* Memory; + s32 Width; + s32 Height; + s32 Pitch; + s32 BytesPerPixel; }; #define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) s32 name(u8* Memory, s32 Width, s32 Height) @@ -169,50 +161,11 @@ typedef DRAW_FONT_CODEPOINT(platform_draw_font_codepoint); #define PLATFORM_THREAD_COUNT 4 -#define THREADED_WORK_PROC(name) void name(s32 ThreadID, void* Data) -typedef THREADED_WORK_PROC(threaded_work_proc); - -typedef struct work_queue work_queue; - -#define PUSH_WORK_ON_QUEUE(name) void name(work_queue* Queue, threaded_work_proc* WorkProc, void* Data, char* JobName) -typedef PUSH_WORK_ON_QUEUE(push_work_on_queue); - -#define DO_QUEUE_WORK_UNTIL_DONE(name) void name(work_queue* Queue, s32 ThreadID) -typedef DO_QUEUE_WORK_UNTIL_DONE(do_queue_work_until_done); - -#define RESET_WORK_QUEUE(name) void name(work_queue* Queue) -typedef RESET_WORK_QUEUE(reset_work_queue); - -struct worker_thread_job -{ - void* Data; - threaded_work_proc* WorkProc; -#ifdef DEBUG - char* JobName; -#endif -}; - -struct work_queue -{ - void* SemaphoreHandle; - - u32 JobsMax; - u32 volatile JobsCount; - u32 volatile NextJobIndex; - u32 volatile JobsCompleted; - worker_thread_job* Jobs; - - // Work Queue - push_work_on_queue* PushWorkOnQueue; - do_queue_work_until_done* DoQueueWorkUntilDone; - reset_work_queue* ResetWorkQueue; -}; - RESET_WORK_QUEUE(ResetWorkQueue) { for (u32 i = 0; i < Queue->JobsMax; i++) { - Queue->Jobs[i].Data = 0; + Queue->Jobs[i].Data = {0}; Queue->Jobs[i].WorkProc = 0; } @@ -232,11 +185,13 @@ GetSecondsElapsed (s64 Start, s64 End, s64 PerformanceCountFrequency) struct context { + gs_thread_context ThreadContext; + u8* MemoryBase; u32 MemorySize; b32 WindowIsVisible; - rect WindowBounds; + rect2 WindowBounds; r32 DeltaTime; mouse_state Mouse; @@ -247,59 +202,18 @@ struct context cleanup_application* CleanupApplication; // Platform Services - work_queue* GeneralWorkQueue; + gs_work_queue* GeneralWorkQueue; - platform_memory_handler PlatformMemory; - platform_file_handler FileHandler; - - platform_write_entire_file* PlatformWriteEntireFile; - platform_get_file_path* PlatformGetFilePath; platform_get_gpu_texture_handle* PlatformGetGPUTextureHandle; platform_get_font_info* PlatformGetFontInfo; platform_draw_font_codepoint* PlatformDrawFontCodepoint; + platform_get_socket_handle* PlatformGetSocketHandle; platform_set_socket_option* PlatformSetSocketOption; platform_send_to* PlatformSendTo; platform_close_socket* PlatformCloseSocket; }; -// File Handler -internal platform_memory_result -ReadEntireFile(platform_file_handler FileHandler, string Path) -{ - platform_memory_result Result = FileHandler.ReadEntireFile(Path); - return Result; -} -internal platform_memory_result -ReadEntireFile(context Context, string Path) -{ - return ReadEntireFile(Context.FileHandler, Path); -} - -internal b32 -WriteEntireFile(platform_file_handler FileHandler, string Path, u8* Contents, u32 Size) -{ - b32 Result = FileHandler.WriteEntireFile(Path, Contents, Size); - return Result; -} -internal b32 -WriteEntireFile(context Context, string Path, u8* Contents, u32 Size) -{ - return WriteEntireFile(Context.FileHandler, Path, Contents, Size); -} - -internal b32 -GetFilePath(platform_file_handler FileHandler, string* PathBuffer, char* FilterStrings) -{ - b32 Result = FileHandler.GetFilePath(PathBuffer, (const char*)FilterStrings); - return Result; -} -internal b32 -GetFilePath(context Context, string* PathBuffer, char* FilterStrings) -{ - return GetFilePath(Context.FileHandler, PathBuffer, FilterStrings); -} - #define FOLDHAUS_PLATFORM_H #endif // FOLDHAUS_PLATFORM_H \ No newline at end of file diff --git a/src/app/foldhaus_renderer.cpp b/src/app/foldhaus_renderer.cpp index 7988e3e..ece4ee7 100644 --- a/src/app/foldhaus_renderer.cpp +++ b/src/app/foldhaus_renderer.cpp @@ -64,7 +64,7 @@ Render2DQuadBatch (u8* CommandData, s32 QuadCount) 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 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)]; @@ -107,11 +107,11 @@ RenderCommandBuffer (render_command_buffer CommandBuffer) render_command_set_render_mode* Command = (render_command_set_render_mode*)(CommandHeader + 1); - glViewport(Command->ViewOffsetX, Command->ViewOffsetY, + glViewport(Command->ViewOffsetX, Command->ViewOffsetY, Command->ViewWidth, Command->ViewHeight); - LoadModelView(Command->ModelView.E); - LoadProjection(Command->Projection.E); + LoadModelView(Command->ModelView.Array); + LoadProjection(Command->Projection.Array); if (Command->UseDepthBuffer) { diff --git a/src/app/foldhaus_renderer.h b/src/app/foldhaus_renderer.h index facfb22..d563cf8 100644 --- a/src/app/foldhaus_renderer.h +++ b/src/app/foldhaus_renderer.h @@ -19,65 +19,71 @@ struct camera inline m44 GetCameraModelViewMatrix (camera Camera) { -#if 0 - // Forward - v4 CamForward = V4(Normalize(Camera.Position - Camera.LookAt), 0); - // Right - v4 CamRight = Normalize(Cross(v4{0, 1, 0, 0}, CamForward)); - // Up - v4 CamUp = Normalize(Cross(CamForward, CamRight)); - - r32 X = Camera.Position.x; - r32 Y = Camera.Position.y; - r32 Z = Camera.Position.z; - - m44 RotationMatrix = M44( - CamRight.x, CamUp.x, CamForward.x, 0, - CamRight.y, CamUp.y, CamForward.y, 0, - CamRight.z, CamUp.z, CamForward.z, 0, - 0, 0, 0, 1); - - m44 PositionMatrix = M44( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - -X, -Y, -Z, 1 - ); -#else - m44 RotationMatrix = GetLookAtMatrix(V4(Camera.Position, 1), V4(Camera.LookAt, 1)); - m44 PositionMatrix = GetPositionM44(V4(Camera.Position, 1)); -#endif - - m44 ModelViewMatrix = PositionMatrix * RotationMatrix; - + 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) { - r32 Top = Camera.Near * GSTan((Camera.FieldOfView / 2.0f)); - r32 Bottom = -Top; - r32 Right = Top * Camera.AspectRatio; - r32 Left = -Right; + 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; +} + +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); - r32 A = ((Right + Left) / (Right - Left)); - r32 B = ((Top + Bottom) / (Top - Bottom)); - r32 C = -((Camera.Far + Camera.Near) / (Camera.Far - Camera.Near)); - r32 D = -((2 * Camera.Far * Camera.Near) / (Camera.Far - Camera.Near)); + return ScreenPosition; +} + +internal v4_ray +ProjectScreenPointToWorldRay(v2 ScreenPoint, camera Camera, rect2 WindowBounds) +{ + v4_ray Result = {0}; - r32 E = ((2 * Camera.Near) / (Right - Left)); - r32 F = ((2 * Camera.Near) / (Top - Bottom)); + r32 TanFOVOverTwo = TanR32(DegToRadR32(Camera.FieldOfView / 2.0f)); + r32 Aspect = RectAspectRatio(WindowBounds); - m44 PerspectiveProjectionMatrix = - { - E, 0, A, 0, - 0, F, B, 0, - 0, 0, C, D, - 0, 0, -1, 0 - }; + r32 NormalizedX = ScreenPoint.x / Rect2Width(WindowBounds); + r32 NormalizedY = ScreenPoint.y / Rect2Height(WindowBounds); - return PerspectiveProjectionMatrix; + 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 @@ -200,7 +206,7 @@ struct render_command_set_render_mode typedef u8* renderer_realloc(u8* Base, s32 CurrentSize, s32 NewSize); -#define COMMAND_BUFFER_MIN_GROW_SIZE Megabytes(2) +#define COMMAND_BUFFER_MIN_GROW_SIZE MB(2) struct render_command_buffer { @@ -257,7 +263,7 @@ ResizeBufferIfNecessary(render_command_buffer* Buffer, s32 DataSize) // 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 = GSMax(SpaceNeeded, COMMAND_BUFFER_MIN_GROW_SIZE); + s32 AdditionSize = Max(SpaceNeeded, COMMAND_BUFFER_MIN_GROW_SIZE); s32 NewSize = Buffer->CommandMemorySize + AdditionSize; Buffer->CommandMemory = Buffer->Realloc(Buffer->CommandMemory, Buffer->CommandMemorySize, @@ -285,7 +291,7 @@ PushQuad3DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* C internal s32 PushQuad2DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* Constructor, s32 QuadCount, s32 DataSize, u8* MemStart) { - GSZeroMemory(MemStart, DataSize); + ZeroMemoryBlock(MemStart, DataSize); Constructor->Max = QuadCount; Constructor->Count = 0; @@ -316,6 +322,15 @@ struct quad_batch_constructor_reserved_range 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; + Result.Start = Result.OnePastLast - TrisNeeded; + return Result; +} + internal quad_batch_constructor_reserved_range ThreadSafeReserveRangeInQuadConstructor(render_quad_batch_constructor* Constructor, s32 TrisNeeded) { @@ -331,6 +346,8 @@ 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; @@ -355,6 +372,7 @@ PushTri3DOnBatch (render_quad_batch_constructor* Constructor, 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); }; @@ -362,7 +380,7 @@ PushTri3DOnBatch (render_quad_batch_constructor* Constructor, 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); + 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); } @@ -373,7 +391,7 @@ 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); + 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); } @@ -472,7 +490,7 @@ internal void PushLine2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, r32 Thickness, v4 Color) { r32 HalfThickness = Thickness / 2.0f; - v2 Perpendicular = Normalize(PerpendicularCCW(P1 - P0)) * HalfThickness; + v2 Perpendicular = V2Normalize(V2PerpendicularCCW(P1 - P0)) * HalfThickness; PushQuad2DOnBatch(Constructor, P0 - Perpendicular, P1 - Perpendicular, P1 + Perpendicular, P0 + Perpendicular, v2{0, 0}, v2{1, 1}, Color); @@ -501,8 +519,8 @@ PushRenderPerspective (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, { render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); - Command->ModelView = GetCameraModelViewMatrix(Camera); - Command->Projection = GetCameraPerspectiveProjectionMatrix(Camera); + Command->ModelView = M44Transpose(GetCameraModelViewMatrix(Camera)); + Command->Projection = M44Transpose(GetCameraPerspectiveProjectionMatrix(Camera)); Command->ViewOffsetX = (r32)OffsetX; Command->ViewOffsetY = (r32)OffsetY; @@ -514,25 +532,18 @@ PushRenderPerspective (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, 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); +} + 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 = m44{ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - - r32 a = 2.0f / ViewWidth; - r32 b = 2.0f / ViewHeight; - Command->Projection = m44{ - a, 0, 0, 0, - 0, b, 0, 0, - 0, 0, 1, 0, - -1, -1, 0, 1 - }; + Command->ModelView = M44Identity(); + Command->Projection = M44ProjectionOrtho((r32)ViewWidth, (r32)ViewHeight, 0, 100, ViewWidth, 0, ViewHeight, 0); Command->ViewOffsetX = (r32)OffsetX; Command->ViewOffsetY = (r32)OffsetY; @@ -542,6 +553,12 @@ PushRenderOrthographic (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, Command->UseDepthBuffer = false;; } +internal void +PushRenderOrthographic(render_command_buffer* Buffer, rect2 Viewport) +{ + PushRenderOrthographic(Buffer, Viewport.Min.x, Viewport.Min.y, Rect2Width(Viewport), Rect2Height(Viewport)); +} + internal void PushRenderClearScreen (render_command_buffer* Buffer) { @@ -571,6 +588,13 @@ PushRenderQuad2D (render_command_buffer* Buffer, v2 Min, v2 Max, v4 Color) PushQuad2DOnBatch(&Batch, Min, 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); +} + internal void PushRenderLine2D (render_command_buffer* Buffer, v2 P0, v2 P1, r32 Thickness, v4 Color) { diff --git a/src/app/foldhaus_util_radialumia_file_converter.cpp b/src/app/foldhaus_util_radialumia_file_converter.cpp index 32945dd..d03074f 100644 --- a/src/app/foldhaus_util_radialumia_file_converter.cpp +++ b/src/app/foldhaus_util_radialumia_file_converter.cpp @@ -10,42 +10,42 @@ #include #include -#include +#include #include "gs/gs_language.h" #include "gs/gs_string.h" #include "../meta/gs_meta_lexer.h" #include "gs/gs_vector.h" -#define STRING_BUFFER_SIZE 512 -struct string_buffer +#define gs_string_BUFFER_SIZE 512 +struct gs_string_buffer { char* Memory; s32 Size; - string_buffer* Next; + gs_string_buffer* Next; }; -struct string_writer +struct gs_string_writer { char* Cursor; - s32 UsedInString; - string_buffer* Buffer; + s32 UsedIngs_string; + gs_string_buffer* Buffer; }; -internal string_buffer* -GrowStringBuffer (string_buffer* Buffer) +internal gs_string_buffer* +Growgs_stringBuffer (gs_string_buffer* Buffer) { - string_buffer* Result; + gs_string_buffer* Result; if (Buffer->Next) { - Result = GrowStringBuffer(Buffer->Next); + Result = Growgs_stringBuffer(Buffer->Next); } else { - Result = (string_buffer*)malloc(sizeof(string_buffer)); - Result->Memory = (char*)malloc(sizeof(char) * STRING_BUFFER_SIZE); - memset(Result->Memory, 0, STRING_BUFFER_SIZE); - Result->Size = STRING_BUFFER_SIZE; + Result = (gs_string_buffer*)malloc(sizeof(gs_string_buffer)); + Result->Memory = (char*)malloc(sizeof(char) * gs_string_BUFFER_SIZE); + memset(Result->Memory, 0, gs_string_BUFFER_SIZE); + Result->Size = gs_string_BUFFER_SIZE; Result->Next = 0; Buffer->Next = Result; @@ -54,28 +54,28 @@ GrowStringBuffer (string_buffer* Buffer) } internal void -WriteString(string_writer* Writer, char* String, s32 Length) +Writegs_string(gs_string_writer* Writer, char* gs_string, s32 Length) { - char* Src = String; + char* Src = gs_string; char* Dst = Writer->Cursor; s32 LengthWritten = 0; - while (*Src && Writer->UsedInString < Writer->Buffer->Size &&LengthWritten < Length) + while (*Src && Writer->UsedIngs_string < Writer->Buffer->Size &&LengthWritten < Length) { LengthWritten++; *Dst++ = *Src++; - Writer->UsedInString++; + Writer->UsedIngs_string++; } Writer->Cursor = Dst; - if (*Src && Writer->UsedInString == Writer->Buffer->Size) + if (*Src && Writer->UsedIngs_string == Writer->Buffer->Size) { *(Dst - 1) = 0; // Null terminate the buffer - Writer->Buffer = GrowStringBuffer(Writer->Buffer); + Writer->Buffer = Growgs_stringBuffer(Writer->Buffer); Writer->Cursor = Writer->Buffer->Memory; - Writer->UsedInString = 0; - WriteString(Writer, (Src - 1), (Length - LengthWritten) + 1); + Writer->UsedIngs_string = 0; + Writegs_string(Writer, (Src - 1), (Length - LengthWritten) + 1); } } @@ -141,15 +141,15 @@ int main(int ArgCount, char* Args[]) control_box_pairs* StartPair = NextControlBoxPair; s32 PairsCount = 0; - if (StringsEqual(Tokenizer.At, "EOF")) + if (gs_stringsEqual(Tokenizer.At, "EOF")) { break; } EatToCharacterInclusive(&Tokenizer, '{'); EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "neighbors: [")); - Tokenizer.At += StringLength("neighbors: ["); + Assert(gs_stringsEqual(Tokenizer.At, "neighbors: [")); + Tokenizer.At += gs_stringLength("neighbors: ["); // Parse Neighbors while(*Tokenizer.At && *Tokenizer.At != ']') @@ -177,8 +177,8 @@ int main(int ArgCount, char* Args[]) EatWhitespace(&Tokenizer); //Parse IP - Assert(StringsEqual(Tokenizer.At, "ip: ")); - Tokenizer.At += StringLength("ip: "); + Assert(gs_stringsEqual(Tokenizer.At, "ip: ")); + Tokenizer.At += gs_stringLength("ip: "); NextControlBox->Address = (char*)malloc(sizeof(char) * 13); memcpy(NextControlBox->Address, Tokenizer.At, 13); Tokenizer.At += 13; @@ -186,27 +186,27 @@ int main(int ArgCount, char* Args[]) // Parse X EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "x: ")); - Tokenizer.At += StringLength("x: "); + Assert(gs_stringsEqual(Tokenizer.At, "x: ")); + Tokenizer.At += gs_stringLength("x: "); NextControlBox->X = ParseFloat(Tokenizer.At); EatToCharacterInclusive(&Tokenizer, ';'); // Parse Y EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "y: ")); - Tokenizer.At += StringLength("y: "); + Assert(gs_stringsEqual(Tokenizer.At, "y: ")); + Tokenizer.At += gs_stringLength("y: "); NextControlBox->Y = ParseFloat(Tokenizer.At); EatToCharacterInclusive(&Tokenizer, ';'); // Parse Z EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "z: ")); - Tokenizer.At += StringLength("z: "); + Assert(gs_stringsEqual(Tokenizer.At, "z: ")); + Tokenizer.At += gs_stringLength("z: "); NextControlBox->Z = ParseFloat(Tokenizer.At); EatToCharacterInclusive(&Tokenizer, ';'); // Parse ID EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "id: ")); - Tokenizer.At += StringLength("id: "); + Assert(gs_stringsEqual(Tokenizer.At, "id: ")); + Tokenizer.At += gs_stringLength("id: "); NextControlBox->ID = ParseSignedInt(Tokenizer.At); EatToCharacterInclusive(&Tokenizer, ';'); @@ -278,36 +278,36 @@ int main(int ArgCount, char* Args[]) } - string_buffer OutputFileBuffer = {}; - OutputFileBuffer.Memory = (char*)malloc(sizeof(char) * STRING_BUFFER_SIZE); - OutputFileBuffer.Size = STRING_BUFFER_SIZE; + gs_string_buffer OutputFileBuffer = {}; + OutputFileBuffer.Memory = (char*)malloc(sizeof(char) * gs_string_BUFFER_SIZE); + OutputFileBuffer.Size = gs_string_BUFFER_SIZE; OutputFileBuffer.Next = 0; - string_writer RefWriter = {}; + gs_string_writer RefWriter = {}; RefWriter.Cursor = OutputFileBuffer.Memory; - RefWriter.UsedInString = 0; + RefWriter.UsedIngs_string = 0; RefWriter.Buffer = &OutputFileBuffer; - string_writer* Writer = &RefWriter; + gs_string_writer* Writer = &RefWriter; - char StringBuffer[512]; + char gs_stringBuffer[512]; s32 Len = 0; - Len = sprintf_s(StringBuffer, 512, "control_box_count %d\n", ControlBoxesUsed); - WriteString(Writer, StringBuffer, Len); - Len = sprintf_s(StringBuffer, 512, "led_strip_count %d\n\n", ControlBoxPairsUsed); - WriteString(Writer, StringBuffer, Len); + Len = sprintf_s(gs_stringBuffer, 512, "control_box_count %d\n", ControlBoxesUsed); + Writegs_string(Writer, gs_stringBuffer, Len); + Len = sprintf_s(gs_stringBuffer, 512, "led_strip_count %d\n\n", ControlBoxPairsUsed); + Writegs_string(Writer, gs_stringBuffer, Len); for (s32 c = 0; c < ControlBoxesUsed; c++) { control_box* Box = ControlBoxes + c; - Len = sprintf_s(StringBuffer, 512, + Len = sprintf_s(gs_stringBuffer, 512, "control_box { %d, \"%s\", (%f, %f, %f) }\n", Box->ID, Box->Address, Box->X, Box->Y, Box->Z); - WriteString(Writer, StringBuffer, Len); + Writegs_string(Writer, gs_stringBuffer, Len); } - WriteString(Writer, "\n", 1); + Writegs_string(Writer, "\n", 1); #define UNIVERSES_PER_BOX 25 s32 UniversesPerBox[64]; @@ -316,7 +316,7 @@ int main(int ArgCount, char* Args[]) UniversesPerBox[u] = UNIVERSES_PER_BOX * u; } - char LEDStripFormatString[] = "led_strip { %d, %d, %d, INTERPOLATE_POINTS, (%f, %f, %f), (%f, %f, %f), 144 } \n"; + char LEDStripFormatgs_string[] = "led_strip { %d, %d, %d, INTERPOLATE_POINTS, (%f, %f, %f), (%f, %f, %f), 144 } \n"; for (s32 s = 0; s < ControlBoxPairsUsed; s++) { control_box_pairs* Pair = ControlBoxPairs + s; @@ -332,15 +332,15 @@ int main(int ArgCount, char* Args[]) r32 EndY = ControlBoxes[Pair->End].Y; r32 EndZ = ControlBoxes[Pair->End].Z; - Len = sprintf_s(StringBuffer, 512, - LEDStripFormatString, + Len = sprintf_s(gs_stringBuffer, 512, + LEDStripFormatgs_string, Pair->Start, Universe, 0, StartX, StartY, StartZ, EndX, EndY, EndZ); - WriteString(Writer, StringBuffer, Len); + Writegs_string(Writer, gs_stringBuffer, Len); } - WriteString(Writer, "\n", 1); + Writegs_string(Writer, "\n", 1); for (s32 sp = 0; sp < ExtraStripsUsed; sp++) { @@ -349,20 +349,20 @@ int main(int ArgCount, char* Args[]) s32 Universe = UniversesPerBox[Strip->BoxID]; UniversesPerBox[Strip->BoxID]++; - Len = sprintf_s(StringBuffer, 512, - LEDStripFormatString, + Len = sprintf_s(gs_stringBuffer, 512, + LEDStripFormatgs_string, Strip->BoxID, Universe, 0, Strip->Start.x, Strip->Start.y, Strip->Start.z, Strip->End.x, Strip->End.y, Strip->End.z); - WriteString(Writer, StringBuffer, Len); + Writegs_string(Writer, gs_stringBuffer, Len); } - WriteString(Writer, "END_OF_ASSEMBLY_FILE", StringLength("END_OF_ASSEMBLY_FILE")); + Writegs_string(Writer, "END_OF_ASSEMBLY_FILE", gs_stringLength("END_OF_ASSEMBLY_FILE")); *Writer->Cursor = 0; FILE* OutputFile = fopen("F:/data/radialumia.fold", "w"); - string_buffer* BufferCursor = &OutputFileBuffer; + gs_string_buffer* BufferCursor = &OutputFileBuffer; while(BufferCursor) { fprintf(OutputFile, BufferCursor->Memory); diff --git a/src/app/generated/foldhaus_panels_generated.h b/src/app/generated/foldhaus_panels_generated.h index 48610ca..67ca2a3 100644 --- a/src/app/generated/foldhaus_panels_generated.h +++ b/src/app/generated/foldhaus_panels_generated.h @@ -1,19 +1,18 @@ enum panel_type { -PanelType_FileView, -PanelType_SculptureView, -PanelType_AnimationTimeline, -PanelType_DMXView, -PanelType_HierarchyView, -PanelType_NodeGraph, -PanelType_ProfilerView, + PanelType_FileView, + PanelType_SculptureView, + PanelType_AnimationTimeline, + PanelType_DMXView, + PanelType_HierarchyView, + PanelType_NodeGraph, + PanelType_ProfilerView, }; -global_variable s32 GlobalPanelDefsCount = 7; -global_variable panel_definition GlobalPanelDefs[] = { -{ "File View", 9, FileView_Init, FileView_Cleanup, FileView_Render, FileView_Commands, FileView_CommandsCount }, -{ "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands, SculptureView_CommandsCount }, -{ "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, AnimationTimeline_Commands, AnimationTimeline_CommandsCount }, -{ "Dmx View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, DMXView_Commands, DMXView_CommandsCount }, -{ "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, HierarchyView_Commands, HierarchyView_CommandsCount }, -{ "Node Graph", 10, NodeGraph_Init, NodeGraph_Cleanup, NodeGraph_Render, NodeGraph_Commands, NodeGraph_CommandsCount }, -{ "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, ProfilerView_Commands, ProfilerView_CommandsCount }, +global s32 GlobalPanelDefsCount = 6; +global panel_definition GlobalPanelDefs[] = { + { "File View", 9, FileView_Init, FileView_Cleanup, FileView_Render, FileView_Commands, FileView_CommandsCount }, + { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands, SculptureView_CommandsCount }, + { "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, AnimationTimeline_Commands, AnimationTimeline_CommandsCount }, + { "Dmx View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, DMXView_Commands, DMXView_CommandsCount }, + { "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, HierarchyView_Commands, HierarchyView_CommandsCount }, + { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, ProfilerView_Commands, ProfilerView_CommandsCount }, }; diff --git a/src/app/generated/gs_meta_generated_typeinfo.h b/src/app/generated/gs_meta_generated_typeinfo.h index fd1d779..9477f54 100644 --- a/src/app/generated/gs_meta_generated_typeinfo.h +++ b/src/app/generated/gs_meta_generated_typeinfo.h @@ -1,40 +1,41 @@ enum gsm_meta_tag_type { -MetaTag_panel_type_file_view, -MetaTag_panel_type_node_graph, -MetaTag_node_output, -MetaTag_node_struct, -MetaTag_panel_cleanup, -MetaTag_node_input, -MetaTag_panel_init, -MetaTag_panel_type_animation_timeline, -MetaTag_panel_commands, -MetaTag_panel_type_sculpture_view, -MetaTag_node_proc, -MetaTag_panel_type_hierarchy, -MetaTag_panel_type_profiler, -MetaTag_panel_render, -MetaTag_panel_type_dmx_view, + MetaTag_panel_type_file_view, + MetaTag_panel_type_node_graph, + MetaTag_node_output, + MetaTag_node_struct, + MetaTag_panel_cleanup, + MetaTag_node_input, + MetaTag_panel_init, + MetaTag_panel_type_animation_timeline, + MetaTag_panel_commands, + MetaTag_panel_type_sculpture_view, + MetaTag_node_proc, + MetaTag_panel_type_hierarchy, + MetaTag_panel_type_profiler, + MetaTag_panel_render, + MetaTag_panel_type_dmx_view, }; -gsm_meta_tag MetaTagStrings[] = { -{ "panel_type_file_view", 20 }, -{ "panel_type_node_graph", 21 }, -{ "node_output", 11 }, -{ "node_struct", 11 }, -{ "panel_cleanup", 13 }, -{ "node_input", 10 }, -{ "panel_init", 10 }, -{ "panel_type_animation_timeline", 29 }, -{ "panel_commands", 14 }, -{ "panel_type_sculpture_view", 25 }, -{ "node_proc", 9 }, -{ "panel_type_hierarchy", 20 }, -{ "panel_type_profiler", 19 }, -{ "panel_render", 12 }, -{ "panel_type_dmx_view", 19 }, +gsm_meta_tag MetaTaggs_strings[] = { + { "panel_type_file_view", 20 }, + { "panel_type_node_graph", 21 }, + { "node_output", 11 }, + { "node_struct", 11 }, + { "panel_cleanup", 13 }, + { "node_input", 10 }, + { "panel_init", 10 }, + { "panel_type_animation_timeline", 29 }, + { "panel_commands", 14 }, + { "panel_type_sculpture_view", 25 }, + { "node_proc", 9 }, + { "panel_type_hierarchy", 20 }, + { "panel_type_profiler", 19 }, + { "panel_render", 12 }, + { "panel_type_dmx_view", 19 }, }; enum gsm_struct_type { + gsm_StructType_r32, gsm_StructType_solid_color_data, gsm_StructType_v4, gsm_StructType_float, @@ -42,85 +43,68 @@ enum gsm_struct_type gsm_StructType_pixel, gsm_StructType_u8, gsm_StructType_s32, - gsm_StructType_sin_wave_data, - gsm_StructType_r32, gsm_StructType_revolving_discs_data, gsm_StructType_vertical_color_fade_data, - gsm_StructType_multiply_patterns_data, gsm_StructType_Count, }; static gsm_struct_member_type_info StructMembers_v4[] = { -{ "x", 1, (u64)&((v4*)0)->x, {}, 0}, -{ "y", 1, (u64)&((v4*)0)->y, {}, 0}, -{ "z", 1, (u64)&((v4*)0)->z, {}, 0}, -{ "w", 1, (u64)&((v4*)0)->w, {}, 0}, -{ "r", 1, (u64)&((v4*)0)->r, {}, 0}, -{ "g", 1, (u64)&((v4*)0)->g, {}, 0}, -{ "b", 1, (u64)&((v4*)0)->b, {}, 0}, -{ "a", 1, (u64)&((v4*)0)->a, {}, 0}, -{ "xy", 2, (u64)&((v4*)0)->xy, {}, 0}, -{ "yz", 2, (u64)&((v4*)0)->yz, {}, 0}, -{ "xyz", 3, (u64)&((v4*)0)->xyz, {}, 0}, -{ "z", 1, (u64)&((v4*)0)->z, {}, 0}, -{ "E", 1, (u64)&((v4*)0)->E, {}, 0}, + { "x", 1, (u64)&((v4*)0)->x, {}, 0}, + { "y", 1, (u64)&((v4*)0)->y, {}, 0}, + { "z", 1, (u64)&((v4*)0)->z, {}, 0}, + { "w", 1, (u64)&((v4*)0)->w, {}, 0}, + { "r", 1, (u64)&((v4*)0)->r, {}, 0}, + { "g", 1, (u64)&((v4*)0)->g, {}, 0}, + { "b", 1, (u64)&((v4*)0)->b, {}, 0}, + { "a", 1, (u64)&((v4*)0)->a, {}, 0}, + { "xy", 2, (u64)&((v4*)0)->xy, {}, 0}, + { "yz", 2, (u64)&((v4*)0)->yz, {}, 0}, + { "xyz", 3, (u64)&((v4*)0)->xyz, {}, 0}, + { "z", 1, (u64)&((v4*)0)->z, {}, 0}, + { "E", 1, (u64)&((v4*)0)->E, {}, 0}, }; static gsm_struct_member_type_info StructMembers_pixel[] = { -{ "R", 1, (u64)&((pixel*)0)->R, {}, 0}, -{ "G", 1, (u64)&((pixel*)0)->G, {}, 0}, -{ "B", 1, (u64)&((pixel*)0)->B, {}, 0}, -{ "Channels", 8, (u64)&((pixel*)0)->Channels, {}, 0}, + { "R", 1, (u64)&((pixel*)0)->R, {}, 0}, + { "G", 1, (u64)&((pixel*)0)->G, {}, 0}, + { "B", 1, (u64)&((pixel*)0)->B, {}, 0}, + { "Channels", 8, (u64)&((pixel*)0)->Channels, {}, 0}, }; static gsm_struct_member_type_info StructMembers_color_buffer[] = { -{ "LedPositions", 12, (u64)&((color_buffer*)0)->LedPositions, {}, 0}, -{ "Colors", 6, (u64)&((color_buffer*)0)->Colors, {}, 0}, -{ "LEDCount", 8, (u64)&((color_buffer*)0)->LEDCount, {}, 0}, + { "LedPositions", 12, (u64)&((color_buffer*)0)->LedPositions, {}, 0}, + { "Colors", 6, (u64)&((color_buffer*)0)->Colors, {}, 0}, + { "LEDCount", 8, (u64)&((color_buffer*)0)->LEDCount, {}, 0}, }; static gsm_struct_member_type_info StructMembers_solid_color_data[] = { -{ "Color", 5, (u64)&((solid_color_data*)0)->Color, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((solid_color_data*)0)->Result, {MetaTag_node_output, }, 1}, -}; -static gsm_struct_member_type_info StructMembers_sin_wave_data[] = { -{ "Period", 6, (u64)&((sin_wave_data*)0)->Period, {MetaTag_node_input, }, 1}, -{ "Min", 3, (u64)&((sin_wave_data*)0)->Min, {MetaTag_node_input, }, 1}, -{ "Max", 3, (u64)&((sin_wave_data*)0)->Max, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((sin_wave_data*)0)->Result, {MetaTag_node_input, }, 1}, -{ "Accumulator", 11, (u64)&((sin_wave_data*)0)->Accumulator, {}, 0}, + { "Color", 5, (u64)&((solid_color_data*)0)->Color, {MetaTag_node_input, }, 1}, + { "Result", 6, (u64)&((solid_color_data*)0)->Result, {MetaTag_node_output, }, 1}, }; static gsm_struct_member_type_info StructMembers_revolving_discs_data[] = { -{ "Rotation", 8, (u64)&((revolving_discs_data*)0)->Rotation, {MetaTag_node_input, }, 1}, -{ "ThetaZ", 6, (u64)&((revolving_discs_data*)0)->ThetaZ, {MetaTag_node_input, }, 1}, -{ "ThetaY", 6, (u64)&((revolving_discs_data*)0)->ThetaY, {MetaTag_node_input, }, 1}, -{ "DiscWidth", 9, (u64)&((revolving_discs_data*)0)->DiscWidth, {MetaTag_node_input, }, 1}, -{ "InnerRadius", 11, (u64)&((revolving_discs_data*)0)->InnerRadius, {MetaTag_node_input, }, 1}, -{ "OuterRadius", 11, (u64)&((revolving_discs_data*)0)->OuterRadius, {MetaTag_node_input, }, 1}, -{ "Color", 5, (u64)&((revolving_discs_data*)0)->Color, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((revolving_discs_data*)0)->Result, {MetaTag_node_output, }, 1}, + { "Rotation", 8, (u64)&((revolving_discs_data*)0)->Rotation, {MetaTag_node_input, }, 1}, + { "ThetaZ", 6, (u64)&((revolving_discs_data*)0)->ThetaZ, {MetaTag_node_input, }, 1}, + { "ThetaY", 6, (u64)&((revolving_discs_data*)0)->ThetaY, {MetaTag_node_input, }, 1}, + { "DiscWidth", 9, (u64)&((revolving_discs_data*)0)->DiscWidth, {MetaTag_node_input, }, 1}, + { "InnerRadius", 11, (u64)&((revolving_discs_data*)0)->InnerRadius, {MetaTag_node_input, }, 1}, + { "OuterRadius", 11, (u64)&((revolving_discs_data*)0)->OuterRadius, {MetaTag_node_input, }, 1}, + { "Color", 5, (u64)&((revolving_discs_data*)0)->Color, {MetaTag_node_input, }, 1}, + { "Result", 6, (u64)&((revolving_discs_data*)0)->Result, {MetaTag_node_output, }, 1}, }; static gsm_struct_member_type_info StructMembers_vertical_color_fade_data[] = { -{ "Color", 5, (u64)&((vertical_color_fade_data*)0)->Color, {MetaTag_node_input, }, 1}, -{ "Min", 3, (u64)&((vertical_color_fade_data*)0)->Min, {MetaTag_node_input, }, 1}, -{ "Max", 3, (u64)&((vertical_color_fade_data*)0)->Max, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((vertical_color_fade_data*)0)->Result, {MetaTag_node_output, }, 1}, -}; -static gsm_struct_member_type_info StructMembers_multiply_patterns_data[] = { -{ "A", 1, (u64)&((multiply_patterns_data*)0)->A, {MetaTag_node_input, }, 1}, -{ "B", 1, (u64)&((multiply_patterns_data*)0)->B, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((multiply_patterns_data*)0)->Result, {MetaTag_node_output, }, 1}, + { "Color", 5, (u64)&((vertical_color_fade_data*)0)->Color, {MetaTag_node_input, }, 1}, + { "Min", 3, (u64)&((vertical_color_fade_data*)0)->Min, {MetaTag_node_input, }, 1}, + { "Max", 3, (u64)&((vertical_color_fade_data*)0)->Max, {MetaTag_node_input, }, 1}, + { "Result", 6, (u64)&((vertical_color_fade_data*)0)->Result, {MetaTag_node_output, }, 1}, }; static gsm_struct_type_info StructTypes[] = { -{ gsm_StructType_solid_color_data, "solid_color_data", 16, 36, 0, 0, StructMembers_solid_color_data, 2 }, -{ gsm_StructType_v4, "v4", 2, 16, 0, 0, StructMembers_v4, 5 }, -{ gsm_StructType_float, "float", 5, 4, 0, 0, 0, 0 }, -{ gsm_StructType_color_buffer, "color_buffer", 12, 20, 0, 0, StructMembers_color_buffer, 3 }, -{ gsm_StructType_pixel, "pixel", 5, 3, 0, 0, StructMembers_pixel, 2 }, -{ gsm_StructType_u8, "u8", 2, 1, 0, 0, 0, 0 }, -{ gsm_StructType_s32, "s32", 3, 4, 0, 0, 0, 0 }, -{ gsm_StructType_sin_wave_data, "sin_wave_data", 13, 20, 0, 0, StructMembers_sin_wave_data, 5 }, -{ gsm_StructType_r32, "r32", 3, 4, 0, 0, 0, 0 }, -{ gsm_StructType_revolving_discs_data, "revolving_discs_data", 20, 60, 0, 0, StructMembers_revolving_discs_data, 8 }, -{ gsm_StructType_vertical_color_fade_data, "vertical_color_fade_data", 24, 44, 0, 0, StructMembers_vertical_color_fade_data, 4 }, -{ gsm_StructType_multiply_patterns_data, "multiply_patterns_data", 22, 60, 0, 0, StructMembers_multiply_patterns_data, 3 }, + { gsm_StructType_r32, "r32", 3, 4, 0, 0, 0, 0 }, + { gsm_StructType_solid_color_data, "solid_color_data", 16, 32, 0, 0, StructMembers_solid_color_data, 2 }, + { gsm_StructType_v4, "v4", 2, 16, 0, 0, StructMembers_v4, 5 }, + { gsm_StructType_float, "float", 5, 4, 0, 0, 0, 0 }, + { gsm_StructType_color_buffer, "color_buffer", 12, 16, 0, 0, StructMembers_color_buffer, 3 }, + { gsm_StructType_pixel, "pixel", 5, 0, 0, 0, StructMembers_pixel, 2 }, + { gsm_StructType_u8, "u8", 2, 0, 0, 0, 0, 0 }, + { gsm_StructType_s32, "s32", 3, 0, 0, 0, 0, 0 }, + { gsm_StructType_revolving_discs_data, "revolving_discs_data", 20, 56, 0, 0, StructMembers_revolving_discs_data, 8 }, + { gsm_StructType_vertical_color_fade_data, "vertical_color_fade_data", 24, 40, 0, 0, StructMembers_vertical_color_fade_data, 4 }, }; static gsm_u32 StructTypesCount = 12; diff --git a/src/app/gs_osx_window.mm b/src/app/gs_osx_window.mm index 3b0d29c..eefafd3 100644 --- a/src/app/gs_osx_window.mm +++ b/src/app/gs_osx_window.mm @@ -67,7 +67,7 @@ gsosx_CreateWindow(NSApplication* App, int Width, int Height, id Title) [App setMainMenu: MenuBar]; NSMenu* AppMenu = [NSMenu alloc]; - id QuitTitle = [@"Quit " stringByAppendingString: Title]; + id QuitTitle = [@"Quit " gs_stringByAppendinggs_string: Title]; id QuitMenuItem = [[NSMenuItem alloc] initWithTitle: QuitTitle action: @selector(terminate:) keyEquivalent: @"q"]; [AppMenu addItem: QuitMenuItem]; [AppMenuItem setSubmenu: AppMenu]; diff --git a/src/app/handmade_math.h b/src/app/handmade_math.h new file mode 100644 index 0000000..049dfdb --- /dev/null +++ b/src/app/handmade_math.h @@ -0,0 +1,3239 @@ +/* + HandmadeMath.h v1.11.0 + + This is a single header file with a bunch of useful functions for game and + graphics math operations. + + ============================================================================= + + You MUST + + #define HANDMADE_MATH_IMPLEMENTATION + + in EXACTLY one C or C++ file that includes this header, BEFORE the + include, like this: + + #define HANDMADE_MATH_IMPLEMENTATION + #include "HandmadeMath.h" + + All other files should just #include "HandmadeMath.h" without the #define. + + ============================================================================= + + To disable SSE intrinsics, you MUST + + #define HANDMADE_MATH_NO_SSE + + in EXACTLY one C or C++ file that includes this header, BEFORE the + include, like this: + + #define HANDMADE_MATH_IMPLEMENTATION + #define HANDMADE_MATH_NO_SSE + #include "HandmadeMath.h" + + ============================================================================= + + If you would prefer not to use the HMM_ prefix on function names, you can + + #define HMM_PREFIX + + To use a custom prefix instead, you can + + #define HMM_PREFIX(name) YOUR_PREFIX_##name + + ============================================================================= + + To use HandmadeMath without the CRT, you MUST + + #define HMM_SINF MySinF + #define HMM_COSF MyCosF + #define HMM_TANF MyTanF + #define HMM_SQRTF MySqrtF + #define HMM_EXPF MyExpF + #define HMM_LOGF MyLogF + #define HMM_ACOSF MyACosF + #define HMM_ATANF MyATanF + #define HMM_ATAN2F MYATan2F + + Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F, + ExpF, and LogF in EXACTLY one C or C++ file that includes this header, + BEFORE the include, like this: + + #define HMM_SINF MySinF + #define HMM_COSF MyCosF + #define HMM_TANF MyTanF + #define HMM_SQRTF MySqrtF + #define HMM_EXPF MyExpF + #define HMM_LOGF MyLogF + #define HMM_ACOSF MyACosF + #define HMM_ATANF MyATanF + #define HMM_ATAN2F MyATan2F + #define HANDMADE_MATH_IMPLEMENTATION + #include "HandmadeMath.h" + + If you do not define all of these, HandmadeMath.h will use the + versions of these functions that are provided by the CRT. + + ============================================================================= + + LICENSE + + This software is in the public domain. Where that dedication is not + recognized, you are granted a perpetual, irrevocable license to copy, + distribute, and modify this file as you see fit. + + CREDITS + + Written by Zakary Strange (strangezak@gmail.com && @strangezak) + + Functionality: + Matt Mascarenhas (@miblo_) + Aleph + FieryDrake (@fierydrake) + Gingerbill (@TheGingerBill) + Ben Visness (@bvisness) + Trinton Bullard (@Peliex_Dev) + @AntonDan + + Fixes: + Jeroen van Rijn (@J_vanRijn) + Kiljacken (@Kiljacken) + Insofaras (@insofaras) + Daniel Gibson (@DanielGibson) +*/ + +// Dummy macros for when test framework is not present. +#ifndef COVERAGE +#define COVERAGE(a, b) +#endif + +#ifndef ASSERT_COVERED +#define ASSERT_COVERED(a) +#endif + +/* let's figure out if SSE is really available (unless disabled anyway) + (it isn't on non-x86/x86_64 platforms or even x86 without explicit SSE support) + => only use "#ifdef HANDMADE_MATH__USE_SSE" to check for SSE support below this block! */ +#ifndef HANDMADE_MATH_NO_SSE + +# ifdef _MSC_VER +/* MSVC supports SSE in amd64 mode or _M_IX86_FP >= 1 (2 means SSE2) */ +# if defined(_M_AMD64) || ( defined(_M_IX86_FP) && _M_IX86_FP >= 1 ) +# define HANDMADE_MATH__USE_SSE 1 +# endif +# else /* not MSVC, probably GCC, clang, icc or something that doesn't support SSE anyway */ +# ifdef __SSE__ /* they #define __SSE__ if it's supported */ +# define HANDMADE_MATH__USE_SSE 1 +# endif /* __SSE__ */ +# endif /* not _MSC_VER */ + +#endif /* #ifndef HANDMADE_MATH_NO_SSE */ + +#ifdef HANDMADE_MATH__USE_SSE +#include +#endif + +#ifndef HANDMADE_MATH_H +#define HANDMADE_MATH_H + +#ifdef _MSC_VER +#pragma warning(disable:4201) +#endif + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 8) +#pragma GCC diagnostic ignored "-Wmissing-braces" +#endif +#ifdef __clang__ +#pragma GCC diagnostic ignored "-Wgnu-anonymous-struct" +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define HMM_DEPRECATED(msg) __attribute__((deprecated(msg))) +#elif defined(_MSC_VER) +#define HMM_DEPRECATED(msg) __declspec(deprecated(msg)) +#else +#define HMM_DEPRECATED(msg) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define HMM_INLINE static inline +#define HMM_EXTERN extern + +#if !defined(HMM_SINF) || !defined(HMM_COSF) || !defined(HMM_TANF) || \ + !defined(HMM_SQRTF) || !defined(HMM_EXPF) || !defined(HMM_LOGF) || \ + !defined(HMM_ACOSF) || !defined(HMM_ATANF)|| !defined(HMM_ATAN2F) +#include +#endif + +#ifndef HMM_SINF +#define HMM_SINF sinf +#endif + +#ifndef HMM_COSF +#define HMM_COSF cosf +#endif + +#ifndef HMM_TANF +#define HMM_TANF tanf +#endif + +#ifndef HMM_SQRTF +#define HMM_SQRTF sqrtf +#endif + +#ifndef HMM_EXPF +#define HMM_EXPF expf +#endif + +#ifndef HMM_LOGF +#define HMM_LOGF logf +#endif + +#ifndef HMM_ACOSF +#define HMM_ACOSF acosf +#endif + +#ifndef HMM_ATANF +#define HMM_ATANF atanf +#endif + +#ifndef HMM_ATAN2F +#define HMM_ATAN2F atan2f +#endif + +#define HMM_PI32 3.14159265359f +#define HMM_PI 3.14159265358979323846 + +#define HMM_MIN(a, b) (a) > (b) ? (b) : (a) +#define HMM_MAX(a, b) (a) < (b) ? (b) : (a) +#define HMM_ABS(a) ((a) > 0 ? (a) : -(a)) +#define HMM_MOD(a, m) ((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)) +#define HMM_SQUARE(x) ((x) * (x)) + +#ifndef HMM_PREFIX +#define HMM_PREFIX(name) HMM_##name +#endif + + typedef union hmm_vec2 + { + struct + { + float X, Y; + }; + + struct + { + float U, V; + }; + + struct + { + float Left, Right; + }; + + struct + { + float Width, Height; + }; + + float Elements[2]; + +#ifdef __cplusplus + inline float &operator[](const int &Index) + { + return Elements[Index]; + } +#endif + } hmm_vec2; + + typedef union hmm_vec3 + { + struct + { + float X, Y, Z; + }; + + struct + { + float U, V, W; + }; + + struct + { + float R, G, B; + }; + + struct + { + hmm_vec2 XY; + float Ignored0_; + }; + + struct + { + float Ignored1_; + hmm_vec2 YZ; + }; + + struct + { + hmm_vec2 UV; + float Ignored2_; + }; + + struct + { + float Ignored3_; + hmm_vec2 VW; + }; + + float Elements[3]; + +#ifdef __cplusplus + inline float &operator[](const int &Index) + { + return Elements[Index]; + } +#endif + } hmm_vec3; + + typedef union hmm_vec4 + { + struct + { + union + { + hmm_vec3 XYZ; + struct + { + float X, Y, Z; + }; + }; + + float W; + }; + struct + { + union + { + hmm_vec3 RGB; + struct + { + float R, G, B; + }; + }; + + float A; + }; + + struct + { + hmm_vec2 XY; + float Ignored0_; + float Ignored1_; + }; + + struct + { + float Ignored2_; + hmm_vec2 YZ; + float Ignored3_; + }; + + struct + { + float Ignored4_; + float Ignored5_; + hmm_vec2 ZW; + }; + + float Elements[4]; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 InternalElementsSSE; +#endif + +#ifdef __cplusplus + inline float &operator[](const int &Index) + { + return Elements[Index]; + } +#endif + } hmm_vec4; + + typedef union hmm_mat4 + { + float Elements[4][4]; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Columns[4]; + + HMM_DEPRECATED("Our matrices are column-major, so this was named incorrectly. Use Columns instead.") + __m128 Rows[4]; +#endif + +#ifdef __cplusplus + inline hmm_vec4 operator[](const int &Index) + { + float* col = Elements[Index]; + + hmm_vec4 result; + result.Elements[0] = col[0]; + result.Elements[1] = col[1]; + result.Elements[2] = col[2]; + result.Elements[3] = col[3]; + + return result; + } +#endif + } hmm_mat4; + + typedef union hmm_quaternion + { + struct + { + union + { + hmm_vec3 XYZ; + struct + { + float X, Y, Z; + }; + }; + + float W; + }; + + float Elements[4]; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 InternalElementsSSE; +#endif + } hmm_quaternion; + + typedef signed int hmm_bool; + + typedef hmm_vec2 hmm_v2; + typedef hmm_vec3 hmm_v3; + typedef hmm_vec4 hmm_v4; + typedef hmm_mat4 hmm_m4; + + + /* + * Floating-point math functions + */ + + COVERAGE(HMM_SinF, 1) + HMM_INLINE float HMM_PREFIX(SinF)(float Radians) + { + ASSERT_COVERED(HMM_SinF); + + float Result = HMM_SINF(Radians); + + return (Result); + } + + COVERAGE(HMM_CosF, 1) + HMM_INLINE float HMM_PREFIX(CosF)(float Radians) + { + ASSERT_COVERED(HMM_CosF); + + float Result = HMM_COSF(Radians); + + return (Result); + } + + COVERAGE(HMM_TanF, 1) + HMM_INLINE float HMM_PREFIX(TanF)(float Radians) + { + ASSERT_COVERED(HMM_TanF); + + float Result = HMM_TANF(Radians); + + return (Result); + } + + COVERAGE(HMM_ACosF, 1) + HMM_INLINE float HMM_PREFIX(ACosF)(float Radians) + { + ASSERT_COVERED(HMM_ACosF); + + float Result = HMM_ACOSF(Radians); + + return (Result); + } + + COVERAGE(HMM_ATanF, 1) + HMM_INLINE float HMM_PREFIX(ATanF)(float Radians) + { + ASSERT_COVERED(HMM_ATanF); + + float Result = HMM_ATANF(Radians); + + return (Result); + } + + COVERAGE(HMM_ATan2F, 1) + HMM_INLINE float HMM_PREFIX(ATan2F)(float Left, float Right) + { + ASSERT_COVERED(HMM_ATan2F); + + float Result = HMM_ATAN2F(Left, Right); + + return (Result); + } + + COVERAGE(HMM_ExpF, 1) + HMM_INLINE float HMM_PREFIX(ExpF)(float Float) + { + ASSERT_COVERED(HMM_ExpF); + + float Result = HMM_EXPF(Float); + + return (Result); + } + + COVERAGE(HMM_LogF, 1) + HMM_INLINE float HMM_PREFIX(LogF)(float Float) + { + ASSERT_COVERED(HMM_LogF); + + float Result = HMM_LOGF(Float); + + return (Result); + } + + COVERAGE(HMM_SquareRootF, 1) + HMM_INLINE float HMM_PREFIX(SquareRootF)(float Float) + { + ASSERT_COVERED(HMM_SquareRootF); + + float Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 In = _mm_set_ss(Float); + __m128 Out = _mm_sqrt_ss(In); + Result = _mm_cvtss_f32(Out); +#else + Result = HMM_SQRTF(Float); +#endif + + return(Result); + } + + COVERAGE(HMM_RSquareRootF, 1) + HMM_INLINE float HMM_PREFIX(RSquareRootF)(float Float) + { + ASSERT_COVERED(HMM_RSquareRootF); + + float Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 In = _mm_set_ss(Float); + __m128 Out = _mm_rsqrt_ss(In); + Result = _mm_cvtss_f32(Out); +#else + Result = 1.0f/HMM_PREFIX(SquareRootF)(Float); +#endif + + return(Result); + } + + HMM_EXTERN float HMM_PREFIX(Power)(float Base, int Exponent); + + COVERAGE(HMM_PowerF, 1) + HMM_INLINE float HMM_PREFIX(PowerF)(float Base, float Exponent) + { + ASSERT_COVERED(HMM_PowerF); + + float Result = HMM_EXPF(Exponent * HMM_LOGF(Base)); + + return (Result); + } + + + /* + * Utility functions + */ + + COVERAGE(HMM_ToRadians, 1) + HMM_INLINE float HMM_PREFIX(ToRadians)(float Degrees) + { + ASSERT_COVERED(HMM_ToRadians); + + float Result = Degrees * (HMM_PI32 / 180.0f); + + return (Result); + } + + COVERAGE(HMM_Lerp, 1) + HMM_INLINE float HMM_PREFIX(Lerp)(float A, float Time, float B) + { + ASSERT_COVERED(HMM_Lerp); + + float Result = (1.0f - Time) * A + Time * B; + + return (Result); + } + + COVERAGE(HMM_Clamp, 1) + HMM_INLINE float HMM_PREFIX(Clamp)(float Min, float Value, float Max) + { + ASSERT_COVERED(HMM_Clamp); + + float Result = Value; + + if(Result < Min) + { + Result = Min; + } + else if(Result > Max) + { + Result = Max; + } + + return (Result); + } + + + /* + * Vector initialization + */ + + COVERAGE(HMM_Vec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(Vec2)(float X, float Y) + { + ASSERT_COVERED(HMM_Vec2); + + hmm_vec2 Result; + + Result.X = X; + Result.Y = Y; + + return (Result); + } + + COVERAGE(HMM_Vec2i, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(Vec2i)(int X, int Y) + { + ASSERT_COVERED(HMM_Vec2i); + + hmm_vec2 Result; + + Result.X = (float)X; + Result.Y = (float)Y; + + return (Result); + } + + COVERAGE(HMM_Vec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(Vec3)(float X, float Y, float Z) + { + ASSERT_COVERED(HMM_Vec3); + + hmm_vec3 Result; + + Result.X = X; + Result.Y = Y; + Result.Z = Z; + + return (Result); + } + + COVERAGE(HMM_Vec3i, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(Vec3i)(int X, int Y, int Z) + { + ASSERT_COVERED(HMM_Vec3i); + + hmm_vec3 Result; + + Result.X = (float)X; + Result.Y = (float)Y; + Result.Z = (float)Z; + + return (Result); + } + + COVERAGE(HMM_Vec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4)(float X, float Y, float Z, float W) + { + ASSERT_COVERED(HMM_Vec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_setr_ps(X, Y, Z, W); +#else + Result.X = X; + Result.Y = Y; + Result.Z = Z; + Result.W = W; +#endif + + return (Result); + } + + COVERAGE(HMM_Vec4i, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4i)(int X, int Y, int Z, int W) + { + ASSERT_COVERED(HMM_Vec4i); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_setr_ps((float)X, (float)Y, (float)Z, (float)W); +#else + Result.X = (float)X; + Result.Y = (float)Y; + Result.Z = (float)Z; + Result.W = (float)W; +#endif + + return (Result); + } + + COVERAGE(HMM_Vec4v, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4v)(hmm_vec3 Vector, float W) + { + ASSERT_COVERED(HMM_Vec4v); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_setr_ps(Vector.X, Vector.Y, Vector.Z, W); +#else + Result.XYZ = Vector; + Result.W = W; +#endif + + return (Result); + } + + + /* + * Binary vector operations + */ + + COVERAGE(HMM_AddVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(AddVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_AddVec2); + + hmm_vec2 Result; + + Result.X = Left.X + Right.X; + Result.Y = Left.Y + Right.Y; + + return (Result); + } + + COVERAGE(HMM_AddVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(AddVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_AddVec3); + + hmm_vec3 Result; + + Result.X = Left.X + Right.X; + Result.Y = Left.Y + Right.Y; + Result.Z = Left.Z + Right.Z; + + return (Result); + } + + COVERAGE(HMM_AddVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(AddVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_AddVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + Result.X = Left.X + Right.X; + Result.Y = Left.Y + Right.Y; + Result.Z = Left.Z + Right.Z; + Result.W = Left.W + Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_SubtractVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(SubtractVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_SubtractVec2); + + hmm_vec2 Result; + + Result.X = Left.X - Right.X; + Result.Y = Left.Y - Right.Y; + + return (Result); + } + + COVERAGE(HMM_SubtractVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(SubtractVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_SubtractVec3); + + hmm_vec3 Result; + + Result.X = Left.X - Right.X; + Result.Y = Left.Y - Right.Y; + Result.Z = Left.Z - Right.Z; + + return (Result); + } + + COVERAGE(HMM_SubtractVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(SubtractVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_SubtractVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + Result.X = Left.X - Right.X; + Result.Y = Left.Y - Right.Y; + Result.Z = Left.Z - Right.Z; + Result.W = Left.W - Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_MultiplyVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(MultiplyVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_MultiplyVec2); + + hmm_vec2 Result; + + Result.X = Left.X * Right.X; + Result.Y = Left.Y * Right.Y; + + return (Result); + } + + COVERAGE(HMM_MultiplyVec2f, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(MultiplyVec2f)(hmm_vec2 Left, float Right) + { + ASSERT_COVERED(HMM_MultiplyVec2f); + + hmm_vec2 Result; + + Result.X = Left.X * Right; + Result.Y = Left.Y * Right; + + return (Result); + } + + COVERAGE(HMM_MultiplyVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(MultiplyVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_MultiplyVec3); + + hmm_vec3 Result; + + Result.X = Left.X * Right.X; + Result.Y = Left.Y * Right.Y; + Result.Z = Left.Z * Right.Z; + + return (Result); + } + + COVERAGE(HMM_MultiplyVec3f, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(MultiplyVec3f)(hmm_vec3 Left, float Right) + { + ASSERT_COVERED(HMM_MultiplyVec3f); + + hmm_vec3 Result; + + Result.X = Left.X * Right; + Result.Y = Left.Y * Right; + Result.Z = Left.Z * Right; + + return (Result); + } + + COVERAGE(HMM_MultiplyVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_MultiplyVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + Result.X = Left.X * Right.X; + Result.Y = Left.Y * Right.Y; + Result.Z = Left.Z * Right.Z; + Result.W = Left.W * Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_MultiplyVec4f, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyVec4f)(hmm_vec4 Left, float Right) + { + ASSERT_COVERED(HMM_MultiplyVec4f); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Scalar = _mm_set1_ps(Right); + Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); +#else + Result.X = Left.X * Right; + Result.Y = Left.Y * Right; + Result.Z = Left.Z * Right; + Result.W = Left.W * Right; +#endif + + return (Result); + } + + COVERAGE(HMM_DivideVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(DivideVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_DivideVec2); + + hmm_vec2 Result; + + Result.X = Left.X / Right.X; + Result.Y = Left.Y / Right.Y; + + return (Result); + } + + COVERAGE(HMM_DivideVec2f, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(DivideVec2f)(hmm_vec2 Left, float Right) + { + ASSERT_COVERED(HMM_DivideVec2f); + + hmm_vec2 Result; + + Result.X = Left.X / Right; + Result.Y = Left.Y / Right; + + return (Result); + } + + COVERAGE(HMM_DivideVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(DivideVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_DivideVec3); + + hmm_vec3 Result; + + Result.X = Left.X / Right.X; + Result.Y = Left.Y / Right.Y; + Result.Z = Left.Z / Right.Z; + + return (Result); + } + + COVERAGE(HMM_DivideVec3f, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(DivideVec3f)(hmm_vec3 Left, float Right) + { + ASSERT_COVERED(HMM_DivideVec3f); + + hmm_vec3 Result; + + Result.X = Left.X / Right; + Result.Y = Left.Y / Right; + Result.Z = Left.Z / Right; + + return (Result); + } + + COVERAGE(HMM_DivideVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(DivideVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_DivideVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + Result.X = Left.X / Right.X; + Result.Y = Left.Y / Right.Y; + Result.Z = Left.Z / Right.Z; + Result.W = Left.W / Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_DivideVec4f, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(DivideVec4f)(hmm_vec4 Left, float Right) + { + ASSERT_COVERED(HMM_DivideVec4f); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Scalar = _mm_set1_ps(Right); + Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); +#else + Result.X = Left.X / Right; + Result.Y = Left.Y / Right; + Result.Z = Left.Z / Right; + Result.W = Left.W / Right; +#endif + + return (Result); + } + + COVERAGE(HMM_EqualsVec2, 1) + HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_EqualsVec2); + + hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y); + + return (Result); + } + + COVERAGE(HMM_EqualsVec3, 1) + HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_EqualsVec3); + + hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z); + + return (Result); + } + + COVERAGE(HMM_EqualsVec4, 1) + HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_EqualsVec4); + + hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z && Left.W == Right.W); + + return (Result); + } + + COVERAGE(HMM_DotVec2, 1) + HMM_INLINE float HMM_PREFIX(DotVec2)(hmm_vec2 VecOne, hmm_vec2 VecTwo) + { + ASSERT_COVERED(HMM_DotVec2); + + float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y); + + return (Result); + } + + COVERAGE(HMM_DotVec3, 1) + HMM_INLINE float HMM_PREFIX(DotVec3)(hmm_vec3 VecOne, hmm_vec3 VecTwo) + { + ASSERT_COVERED(HMM_DotVec3); + + float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z); + + return (Result); + } + + COVERAGE(HMM_DotVec4, 1) + HMM_INLINE float HMM_PREFIX(DotVec4)(hmm_vec4 VecOne, hmm_vec4 VecTwo) + { + ASSERT_COVERED(HMM_DotVec4); + + float Result; + + // NOTE(zak): IN the future if we wanna check what version SSE is support + // we can use _mm_dp_ps (4.3) but for now we will use the old way. + // Or a r = _mm_mul_ps(v1, v2), r = _mm_hadd_ps(r, r), r = _mm_hadd_ps(r, r) for SSE3 +#ifdef HANDMADE_MATH__USE_SSE + __m128 SSEResultOne = _mm_mul_ps(VecOne.InternalElementsSSE, VecTwo.InternalElementsSSE); + __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); + SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); + SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); + SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); + _mm_store_ss(&Result, SSEResultOne); +#else + Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z) + (VecOne.W * VecTwo.W); +#endif + + return (Result); + } + + COVERAGE(HMM_Cross, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(Cross)(hmm_vec3 VecOne, hmm_vec3 VecTwo) + { + ASSERT_COVERED(HMM_Cross); + + hmm_vec3 Result; + + Result.X = (VecOne.Y * VecTwo.Z) - (VecOne.Z * VecTwo.Y); + Result.Y = (VecOne.Z * VecTwo.X) - (VecOne.X * VecTwo.Z); + Result.Z = (VecOne.X * VecTwo.Y) - (VecOne.Y * VecTwo.X); + + return (Result); + } + + + /* + * Unary vector operations + */ + + COVERAGE(HMM_LengthSquaredVec2, 1) + HMM_INLINE float HMM_PREFIX(LengthSquaredVec2)(hmm_vec2 A) + { + ASSERT_COVERED(HMM_LengthSquaredVec2); + + float Result = HMM_PREFIX(DotVec2)(A, A); + + return (Result); + } + + COVERAGE(HMM_LengthSquaredVec3, 1) + HMM_INLINE float HMM_PREFIX(LengthSquaredVec3)(hmm_vec3 A) + { + ASSERT_COVERED(HMM_LengthSquaredVec3); + + float Result = HMM_PREFIX(DotVec3)(A, A); + + return (Result); + } + + COVERAGE(HMM_LengthSquaredVec4, 1) + HMM_INLINE float HMM_PREFIX(LengthSquaredVec4)(hmm_vec4 A) + { + ASSERT_COVERED(HMM_LengthSquaredVec4); + + float Result = HMM_PREFIX(DotVec4)(A, A); + + return (Result); + } + + COVERAGE(HMM_LengthVec2, 1) + HMM_INLINE float HMM_PREFIX(LengthVec2)(hmm_vec2 A) + { + ASSERT_COVERED(HMM_LengthVec2); + + float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec2)(A)); + + return (Result); + } + + COVERAGE(HMM_LengthVec3, 1) + HMM_INLINE float HMM_PREFIX(LengthVec3)(hmm_vec3 A) + { + ASSERT_COVERED(HMM_LengthVec3); + + float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec3)(A)); + + return (Result); + } + + COVERAGE(HMM_LengthVec4, 1) + HMM_INLINE float HMM_PREFIX(LengthVec4)(hmm_vec4 A) + { + ASSERT_COVERED(HMM_LengthVec4); + + float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec4)(A)); + + return(Result); + } + + COVERAGE(HMM_NormalizeVec2, 2) + HMM_INLINE hmm_vec2 HMM_PREFIX(NormalizeVec2)(hmm_vec2 A) + { + ASSERT_COVERED(HMM_NormalizeVec2); + + hmm_vec2 Result = {0}; + + float VectorLength = HMM_PREFIX(LengthVec2)(A); + + /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ + if (VectorLength != 0.0f) + { + ASSERT_COVERED(HMM_NormalizeVec2); + + Result.X = A.X * (1.0f / VectorLength); + Result.Y = A.Y * (1.0f / VectorLength); + } + + return (Result); + } + + COVERAGE(HMM_NormalizeVec3, 2) + HMM_INLINE hmm_vec3 HMM_PREFIX(NormalizeVec3)(hmm_vec3 A) + { + ASSERT_COVERED(HMM_NormalizeVec3); + + hmm_vec3 Result = {0}; + + float VectorLength = HMM_PREFIX(LengthVec3)(A); + + /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ + if (VectorLength != 0.0f) + { + ASSERT_COVERED(HMM_NormalizeVec3); + + Result.X = A.X * (1.0f / VectorLength); + Result.Y = A.Y * (1.0f / VectorLength); + Result.Z = A.Z * (1.0f / VectorLength); + } + + return (Result); + } + + COVERAGE(HMM_NormalizeVec4, 2) + HMM_INLINE hmm_vec4 HMM_PREFIX(NormalizeVec4)(hmm_vec4 A) + { + ASSERT_COVERED(HMM_NormalizeVec4); + + hmm_vec4 Result = {0}; + + float VectorLength = HMM_PREFIX(LengthVec4)(A); + + /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ + if (VectorLength != 0.0f) + { + ASSERT_COVERED(HMM_NormalizeVec4); + + float Multiplier = 1.0f / VectorLength; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 SSEMultiplier = _mm_set1_ps(Multiplier); + Result.InternalElementsSSE = _mm_mul_ps(A.InternalElementsSSE, SSEMultiplier); +#else + Result.X = A.X * Multiplier; + Result.Y = A.Y * Multiplier; + Result.Z = A.Z * Multiplier; + Result.W = A.W * Multiplier; +#endif + } + + return (Result); + } + + COVERAGE(HMM_FastNormalizeVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(FastNormalizeVec2)(hmm_vec2 A) + { + ASSERT_COVERED(HMM_FastNormalizeVec2); + + return HMM_PREFIX(MultiplyVec2f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec2)(A, A))); + } + + COVERAGE(HMM_FastNormalizeVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(FastNormalizeVec3)(hmm_vec3 A) + { + ASSERT_COVERED(HMM_FastNormalizeVec3); + + return HMM_PREFIX(MultiplyVec3f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec3)(A, A))); + } + + COVERAGE(HMM_FastNormalizeVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(FastNormalizeVec4)(hmm_vec4 A) + { + ASSERT_COVERED(HMM_FastNormalizeVec4); + + return HMM_PREFIX(MultiplyVec4f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec4)(A, A))); + } + + + /* + * SSE stuff + */ + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_LinearCombineSSE, 1) + HMM_INLINE __m128 HMM_PREFIX(LinearCombineSSE)(__m128 Left, hmm_mat4 Right) + { + ASSERT_COVERED(HMM_LinearCombineSSE); + + __m128 Result; + Result = _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x00), Right.Columns[0]); + Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x55), Right.Columns[1])); + Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xaa), Right.Columns[2])); + Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xff), Right.Columns[3])); + + return (Result); + } +#endif + + + /* + * Matrix functions + */ + + COVERAGE(HMM_Mat4, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Mat4)(void) + { + ASSERT_COVERED(HMM_Mat4); + + hmm_mat4 Result = {0}; + + return (Result); + } + + COVERAGE(HMM_Mat4d, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Mat4d)(float Diagonal) + { + ASSERT_COVERED(HMM_Mat4d); + + hmm_mat4 Result = HMM_PREFIX(Mat4)(); + + Result.Elements[0][0] = Diagonal; + Result.Elements[1][1] = Diagonal; + Result.Elements[2][2] = Diagonal; + Result.Elements[3][3] = Diagonal; + + return (Result); + } + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_Transpose, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix) + { + ASSERT_COVERED(HMM_Transpose); + + hmm_mat4 Result = Matrix; + + _MM_TRANSPOSE4_PS(Result.Columns[0], Result.Columns[1], Result.Columns[2], Result.Columns[3]); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix); +#endif + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_AddMat4, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right) + { + ASSERT_COVERED(HMM_AddMat4); + + hmm_mat4 Result; + + Result.Columns[0] = _mm_add_ps(Left.Columns[0], Right.Columns[0]); + Result.Columns[1] = _mm_add_ps(Left.Columns[1], Right.Columns[1]); + Result.Columns[2] = _mm_add_ps(Left.Columns[2], Right.Columns[2]); + Result.Columns[3] = _mm_add_ps(Left.Columns[3], Right.Columns[3]); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right); +#endif + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_SubtractMat4, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right) + { + ASSERT_COVERED(HMM_SubtractMat4); + + hmm_mat4 Result; + + Result.Columns[0] = _mm_sub_ps(Left.Columns[0], Right.Columns[0]); + Result.Columns[1] = _mm_sub_ps(Left.Columns[1], Right.Columns[1]); + Result.Columns[2] = _mm_sub_ps(Left.Columns[2], Right.Columns[2]); + Result.Columns[3] = _mm_sub_ps(Left.Columns[3], Right.Columns[3]); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right); +#endif + + HMM_EXTERN hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right); + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_MultiplyMat4f, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar) + { + ASSERT_COVERED(HMM_MultiplyMat4f); + + hmm_mat4 Result; + + __m128 SSEScalar = _mm_set1_ps(Scalar); + Result.Columns[0] = _mm_mul_ps(Matrix.Columns[0], SSEScalar); + Result.Columns[1] = _mm_mul_ps(Matrix.Columns[1], SSEScalar); + Result.Columns[2] = _mm_mul_ps(Matrix.Columns[2], SSEScalar); + Result.Columns[3] = _mm_mul_ps(Matrix.Columns[3], SSEScalar); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar); +#endif + + HMM_EXTERN hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector); + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_DivideMat4f, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar) + { + ASSERT_COVERED(HMM_DivideMat4f); + + hmm_mat4 Result; + + __m128 SSEScalar = _mm_set1_ps(Scalar); + Result.Columns[0] = _mm_div_ps(Matrix.Columns[0], SSEScalar); + Result.Columns[1] = _mm_div_ps(Matrix.Columns[1], SSEScalar); + Result.Columns[2] = _mm_div_ps(Matrix.Columns[2], SSEScalar); + Result.Columns[3] = _mm_div_ps(Matrix.Columns[3], SSEScalar); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar); +#endif + + + /* + * Common graphics transformations + */ + + COVERAGE(HMM_Orthographic, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Orthographic)(float Left, float Right, float Bottom, float Top, float Near, float Far) + { + ASSERT_COVERED(HMM_Orthographic); + + hmm_mat4 Result = HMM_PREFIX(Mat4)(); + + Result.Elements[0][0] = 2.0f / (Right - Left); + Result.Elements[1][1] = 2.0f / (Top - Bottom); + Result.Elements[2][2] = 2.0f / (Near - Far); + Result.Elements[3][3] = 1.0f; + + Result.Elements[3][0] = (Left + Right) / (Left - Right); + Result.Elements[3][1] = (Bottom + Top) / (Bottom - Top); + Result.Elements[3][2] = (Far + Near) / (Near - Far); + + return (Result); + } + + COVERAGE(HMM_Perspective, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Perspective)(float FOV, float AspectRatio, float Near, float Far) + { + ASSERT_COVERED(HMM_Perspective); + + hmm_mat4 Result = HMM_PREFIX(Mat4)(); + + // See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml + + float Cotangent = 1.0f / HMM_PREFIX(TanF)(FOV * (HMM_PI32 / 360.0f)); + + Result.Elements[0][0] = Cotangent / AspectRatio; + Result.Elements[1][1] = Cotangent; + Result.Elements[2][3] = -1.0f; + Result.Elements[2][2] = (Near + Far) / (Near - Far); + Result.Elements[3][2] = (2.0f * Near * Far) / (Near - Far); + Result.Elements[3][3] = 0.0f; + + return (Result); + } + + COVERAGE(HMM_Translate, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Translate)(hmm_vec3 Translation) + { + ASSERT_COVERED(HMM_Translate); + + hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); + + Result.Elements[3][0] = Translation.X; + Result.Elements[3][1] = Translation.Y; + Result.Elements[3][2] = Translation.Z; + + return (Result); + } + + HMM_EXTERN hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis); + + COVERAGE(HMM_Scale, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Scale)(hmm_vec3 Scale) + { + ASSERT_COVERED(HMM_Scale); + + hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); + + Result.Elements[0][0] = Scale.X; + Result.Elements[1][1] = Scale.Y; + Result.Elements[2][2] = Scale.Z; + + return (Result); + } + + HMM_EXTERN hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up); + + + /* + * Quaternion operations + */ + + COVERAGE(HMM_Quaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(Quaternion)(float X, float Y, float Z, float W) + { + ASSERT_COVERED(HMM_Quaternion); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_setr_ps(X, Y, Z, W); +#else + Result.X = X; + Result.Y = Y; + Result.Z = Z; + Result.W = W; +#endif + + return (Result); + } + + COVERAGE(HMM_QuaternionV4, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(QuaternionV4)(hmm_vec4 Vector) + { + ASSERT_COVERED(HMM_QuaternionV4); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = Vector.InternalElementsSSE; +#else + Result.X = Vector.X; + Result.Y = Vector.Y; + Result.Z = Vector.Z; + Result.W = Vector.W; +#endif + + return (Result); + } + + COVERAGE(HMM_AddQuaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(AddQuaternion)(hmm_quaternion Left, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_AddQuaternion); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + + Result.X = Left.X + Right.X; + Result.Y = Left.Y + Right.Y; + Result.Z = Left.Z + Right.Z; + Result.W = Left.W + Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_SubtractQuaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(SubtractQuaternion)(hmm_quaternion Left, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_SubtractQuaternion); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + + Result.X = Left.X - Right.X; + Result.Y = Left.Y - Right.Y; + Result.Z = Left.Z - Right.Z; + Result.W = Left.W - Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_MultiplyQuaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(MultiplyQuaternion)(hmm_quaternion Left, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_MultiplyQuaternion); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(0, 0, 0, 0)), _mm_setr_ps(0.f, -0.f, 0.f, -0.f)); + __m128 SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(0, 1, 2, 3)); + __m128 SSEResultThree = _mm_mul_ps(SSEResultTwo, SSEResultOne); + + SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(1, 1, 1, 1)) , _mm_setr_ps(0.f, 0.f, -0.f, -0.f)); + SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(1, 0, 3, 2)); + SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); + + SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(2, 2, 2, 2)), _mm_setr_ps(-0.f, 0.f, 0.f, -0.f)); + SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(2, 3, 0, 1)); + SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); + + SSEResultOne = _mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(3, 3, 3, 3)); + SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(3, 2, 1, 0)); + Result.InternalElementsSSE = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); +#else + Result.X = (Left.X * Right.W) + (Left.Y * Right.Z) - (Left.Z * Right.Y) + (Left.W * Right.X); + Result.Y = (-Left.X * Right.Z) + (Left.Y * Right.W) + (Left.Z * Right.X) + (Left.W * Right.Y); + Result.Z = (Left.X * Right.Y) - (Left.Y * Right.X) + (Left.Z * Right.W) + (Left.W * Right.Z); + Result.W = (-Left.X * Right.X) - (Left.Y * Right.Y) - (Left.Z * Right.Z) + (Left.W * Right.W); +#endif + + return (Result); + } + + COVERAGE(HMM_MultiplyQuaternionF, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(MultiplyQuaternionF)(hmm_quaternion Left, float Multiplicative) + { + ASSERT_COVERED(HMM_MultiplyQuaternionF); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Scalar = _mm_set1_ps(Multiplicative); + Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); +#else + Result.X = Left.X * Multiplicative; + Result.Y = Left.Y * Multiplicative; + Result.Z = Left.Z * Multiplicative; + Result.W = Left.W * Multiplicative; +#endif + + return (Result); + } + + COVERAGE(HMM_DivideQuaternionF, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(DivideQuaternionF)(hmm_quaternion Left, float Dividend) + { + ASSERT_COVERED(HMM_DivideQuaternionF); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Scalar = _mm_set1_ps(Dividend); + Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); +#else + Result.X = Left.X / Dividend; + Result.Y = Left.Y / Dividend; + Result.Z = Left.Z / Dividend; + Result.W = Left.W / Dividend; +#endif + + return (Result); + } + + HMM_EXTERN hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left); + + COVERAGE(HMM_DotQuaternion, 1) + HMM_INLINE float HMM_PREFIX(DotQuaternion)(hmm_quaternion Left, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_DotQuaternion); + + float Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 SSEResultOne = _mm_mul_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); + __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); + SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); + SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); + SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); + _mm_store_ss(&Result, SSEResultOne); +#else + Result = (Left.X * Right.X) + (Left.Y * Right.Y) + (Left.Z * Right.Z) + (Left.W * Right.W); +#endif + + return (Result); + } + + COVERAGE(HMM_NormalizeQuaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(NormalizeQuaternion)(hmm_quaternion Left) + { + ASSERT_COVERED(HMM_NormalizeQuaternion); + + hmm_quaternion Result; + + float Length = HMM_PREFIX(SquareRootF)(HMM_PREFIX(DotQuaternion)(Left, Left)); + Result = HMM_PREFIX(DivideQuaternionF)(Left, Length); + + return (Result); + } + + COVERAGE(HMM_NLerp, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(NLerp)(hmm_quaternion Left, float Time, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_NLerp); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 ScalarLeft = _mm_set1_ps(1.0f - Time); + __m128 ScalarRight = _mm_set1_ps(Time); + __m128 SSEResultOne = _mm_mul_ps(Left.InternalElementsSSE, ScalarLeft); + __m128 SSEResultTwo = _mm_mul_ps(Right.InternalElementsSSE, ScalarRight); + Result.InternalElementsSSE = _mm_add_ps(SSEResultOne, SSEResultTwo); +#else + Result.X = HMM_PREFIX(Lerp)(Left.X, Time, Right.X); + Result.Y = HMM_PREFIX(Lerp)(Left.Y, Time, Right.Y); + Result.Z = HMM_PREFIX(Lerp)(Left.Z, Time, Right.Z); + Result.W = HMM_PREFIX(Lerp)(Left.W, Time, Right.W); +#endif + Result = HMM_PREFIX(NormalizeQuaternion)(Result); + + return (Result); + } + + HMM_EXTERN hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right); + HMM_EXTERN hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left); + HMM_EXTERN hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 Left); + HMM_EXTERN hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +COVERAGE(HMM_LengthVec2CPP, 1) +HMM_INLINE float HMM_PREFIX(Length)(hmm_vec2 A) +{ + ASSERT_COVERED(HMM_LengthVec2CPP); + + float Result = HMM_PREFIX(LengthVec2)(A); + + return (Result); +} + +COVERAGE(HMM_LengthVec3CPP, 1) +HMM_INLINE float HMM_PREFIX(Length)(hmm_vec3 A) +{ + ASSERT_COVERED(HMM_LengthVec3CPP); + + float Result = HMM_PREFIX(LengthVec3)(A); + + return (Result); +} + +COVERAGE(HMM_LengthVec4CPP, 1) +HMM_INLINE float HMM_PREFIX(Length)(hmm_vec4 A) +{ + ASSERT_COVERED(HMM_LengthVec4CPP); + + float Result = HMM_PREFIX(LengthVec4)(A); + + return (Result); +} + +COVERAGE(HMM_LengthSquaredVec2CPP, 1) +HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec2 A) +{ + ASSERT_COVERED(HMM_LengthSquaredVec2CPP); + + float Result = HMM_PREFIX(LengthSquaredVec2)(A); + + return (Result); +} + +COVERAGE(HMM_LengthSquaredVec3CPP, 1) +HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec3 A) +{ + ASSERT_COVERED(HMM_LengthSquaredVec3CPP); + + float Result = HMM_PREFIX(LengthSquaredVec3)(A); + + return (Result); +} + +COVERAGE(HMM_LengthSquaredVec4CPP, 1) +HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec4 A) +{ + ASSERT_COVERED(HMM_LengthSquaredVec4CPP); + + float Result = HMM_PREFIX(LengthSquaredVec4)(A); + + return (Result); +} + +COVERAGE(HMM_NormalizeVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Normalize)(hmm_vec2 A) +{ + ASSERT_COVERED(HMM_NormalizeVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(NormalizeVec2)(A); + + return (Result); +} + +COVERAGE(HMM_NormalizeVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Normalize)(hmm_vec3 A) +{ + ASSERT_COVERED(HMM_NormalizeVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(NormalizeVec3)(A); + + return (Result); +} + +COVERAGE(HMM_NormalizeVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Normalize)(hmm_vec4 A) +{ + ASSERT_COVERED(HMM_NormalizeVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(NormalizeVec4)(A); + + return (Result); +} + +COVERAGE(HMM_FastNormalizeVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(FastNormalize)(hmm_vec2 A) +{ + ASSERT_COVERED(HMM_FastNormalizeVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(FastNormalizeVec2)(A); + + return (Result); +} + +COVERAGE(HMM_FastNormalizeVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(FastNormalize)(hmm_vec3 A) +{ + ASSERT_COVERED(HMM_FastNormalizeVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(FastNormalizeVec3)(A); + + return (Result); +} + +COVERAGE(HMM_FastNormalizeVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(FastNormalize)(hmm_vec4 A) +{ + ASSERT_COVERED(HMM_FastNormalizeVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(FastNormalizeVec4)(A); + + return (Result); +} + +COVERAGE(HMM_NormalizeQuaternionCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Normalize)(hmm_quaternion A) +{ + ASSERT_COVERED(HMM_NormalizeQuaternionCPP); + + hmm_quaternion Result = HMM_PREFIX(NormalizeQuaternion)(A); + + return (Result); +} + +COVERAGE(HMM_DotVec2CPP, 1) +HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec2 VecOne, hmm_vec2 VecTwo) +{ + ASSERT_COVERED(HMM_DotVec2CPP); + + float Result = HMM_PREFIX(DotVec2)(VecOne, VecTwo); + + return (Result); +} + +COVERAGE(HMM_DotVec3CPP, 1) +HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec3 VecOne, hmm_vec3 VecTwo) +{ + ASSERT_COVERED(HMM_DotVec3CPP); + + float Result = HMM_PREFIX(DotVec3)(VecOne, VecTwo); + + return (Result); +} + +COVERAGE(HMM_DotVec4CPP, 1) +HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec4 VecOne, hmm_vec4 VecTwo) +{ + ASSERT_COVERED(HMM_DotVec4CPP); + + float Result = HMM_PREFIX(DotVec4)(VecOne, VecTwo); + + return (Result); +} + +COVERAGE(HMM_DotQuaternionCPP, 1) +HMM_INLINE float HMM_PREFIX(Dot)(hmm_quaternion QuatOne, hmm_quaternion QuatTwo) +{ + ASSERT_COVERED(HMM_DotQuaternionCPP); + + float Result = HMM_PREFIX(DotQuaternion)(QuatOne, QuatTwo); + + return (Result); +} + +COVERAGE(HMM_AddVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Add)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_AddVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(AddVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Add)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_AddVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(AddVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Add)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_AddVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(AddVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddMat4CPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Add)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_AddMat4CPP); + + hmm_mat4 Result = HMM_PREFIX(AddMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddQuaternionCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Add)(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_AddQuaternionCPP); + + hmm_quaternion Result = HMM_PREFIX(AddQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Subtract)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_SubtractVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(SubtractVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Subtract)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_SubtractVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(SubtractVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Subtract)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_SubtractVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(SubtractVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractMat4CPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Subtract)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_SubtractMat4CPP); + + hmm_mat4 Result = HMM_PREFIX(SubtractMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractQuaternionCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Subtract)(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_SubtractQuaternionCPP); + + hmm_quaternion Result = HMM_PREFIX(SubtractQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Multiply)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2fCPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Multiply)(hmm_vec2 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2fCPP); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Multiply)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3fCPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Multiply)(hmm_vec3 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3fCPP); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4fCPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_vec4 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4fCPP); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4CPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Multiply)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4CPP); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4fCPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Multiply)(hmm_mat4 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4fCPP); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4ByVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_mat4 Matrix, hmm_vec4 Vector) +{ + ASSERT_COVERED(HMM_MultiplyMat4ByVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(MultiplyMat4ByVec4)(Matrix, Vector); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Multiply)(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionCPP); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionFCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Multiply)(hmm_quaternion Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionFCPP); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Divide)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_DivideVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(DivideVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec2fCPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Divide)(hmm_vec2 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec2fCPP); + + hmm_vec2 Result = HMM_PREFIX(DivideVec2f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Divide)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_DivideVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(DivideVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec3fCPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Divide)(hmm_vec3 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec3fCPP); + + hmm_vec3 Result = HMM_PREFIX(DivideVec3f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Divide)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_DivideVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(DivideVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec4fCPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Divide)(hmm_vec4 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec4fCPP); + + hmm_vec4 Result = HMM_PREFIX(DivideVec4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideMat4fCPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Divide)(hmm_mat4 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideMat4fCPP); + + hmm_mat4 Result = HMM_PREFIX(DivideMat4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideQuaternionFCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Divide)(hmm_quaternion Left, float Right) +{ + ASSERT_COVERED(HMM_DivideQuaternionFCPP); + + hmm_quaternion Result = HMM_PREFIX(DivideQuaternionF)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_EqualsVec2CPP, 1) +HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_EqualsVec2CPP); + + hmm_bool Result = HMM_PREFIX(EqualsVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_EqualsVec3CPP, 1) +HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_EqualsVec3CPP); + + hmm_bool Result = HMM_PREFIX(EqualsVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_EqualsVec4CPP, 1) +HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_EqualsVec4CPP); + + hmm_bool Result = HMM_PREFIX(EqualsVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec2Op, 1) +HMM_INLINE hmm_vec2 operator+(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_AddVec2Op); + + hmm_vec2 Result = HMM_PREFIX(AddVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec3Op, 1) +HMM_INLINE hmm_vec3 operator+(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_AddVec3Op); + + hmm_vec3 Result = HMM_PREFIX(AddVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec4Op, 1) +HMM_INLINE hmm_vec4 operator+(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_AddVec4Op); + + hmm_vec4 Result = HMM_PREFIX(AddVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddMat4Op, 1) +HMM_INLINE hmm_mat4 operator+(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_AddMat4Op); + + hmm_mat4 Result = HMM_PREFIX(AddMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddQuaternionOp, 1) +HMM_INLINE hmm_quaternion operator+(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_AddQuaternionOp); + + hmm_quaternion Result = HMM_PREFIX(AddQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec2Op, 1) +HMM_INLINE hmm_vec2 operator-(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_SubtractVec2Op); + + hmm_vec2 Result = HMM_PREFIX(SubtractVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec3Op, 1) +HMM_INLINE hmm_vec3 operator-(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_SubtractVec3Op); + + hmm_vec3 Result = HMM_PREFIX(SubtractVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec4Op, 1) +HMM_INLINE hmm_vec4 operator-(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_SubtractVec4Op); + + hmm_vec4 Result = HMM_PREFIX(SubtractVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractMat4Op, 1) +HMM_INLINE hmm_mat4 operator-(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_SubtractMat4Op); + + hmm_mat4 Result = HMM_PREFIX(SubtractMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractQuaternionOp, 1) +HMM_INLINE hmm_quaternion operator-(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_SubtractQuaternionOp); + + hmm_quaternion Result = HMM_PREFIX(SubtractQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2Op, 1) +HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2Op); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3Op, 1) +HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3Op); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4Op, 1) +HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4Op); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4Op, 1) +HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4Op); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionOp, 1) +HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionOp); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2fOp, 1) +HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2fOp); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3fOp, 1) +HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3fOp); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4fOp, 1) +HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4fOp); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4fOp, 1) +HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4fOp); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionFOp, 1) +HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionFOp); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2fOpLeft, 1) +HMM_INLINE hmm_vec2 operator*(float Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2fOpLeft); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3fOpLeft, 1) +HMM_INLINE hmm_vec3 operator*(float Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3fOpLeft); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4fOpLeft, 1) +HMM_INLINE hmm_vec4 operator*(float Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4fOpLeft); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4fOpLeft, 1) +HMM_INLINE hmm_mat4 operator*(float Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4fOpLeft); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionFOpLeft, 1) +HMM_INLINE hmm_quaternion operator*(float Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionFOpLeft); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4ByVec4Op, 1) +HMM_INLINE hmm_vec4 operator*(hmm_mat4 Matrix, hmm_vec4 Vector) +{ + ASSERT_COVERED(HMM_MultiplyMat4ByVec4Op); + + hmm_vec4 Result = HMM_PREFIX(MultiplyMat4ByVec4)(Matrix, Vector); + + return (Result); +} + +COVERAGE(HMM_DivideVec2Op, 1) +HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_DivideVec2Op); + + hmm_vec2 Result = HMM_PREFIX(DivideVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec3Op, 1) +HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_DivideVec3Op); + + hmm_vec3 Result = HMM_PREFIX(DivideVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec4Op, 1) +HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_DivideVec4Op); + + hmm_vec4 Result = HMM_PREFIX(DivideVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec2fOp, 1) +HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec2fOp); + + hmm_vec2 Result = HMM_PREFIX(DivideVec2f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec3fOp, 1) +HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec3fOp); + + hmm_vec3 Result = HMM_PREFIX(DivideVec3f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec4fOp, 1) +HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec4fOp); + + hmm_vec4 Result = HMM_PREFIX(DivideVec4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideMat4fOp, 1) +HMM_INLINE hmm_mat4 operator/(hmm_mat4 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideMat4fOp); + + hmm_mat4 Result = HMM_PREFIX(DivideMat4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideQuaternionFOp, 1) +HMM_INLINE hmm_quaternion operator/(hmm_quaternion Left, float Right) +{ + ASSERT_COVERED(HMM_DivideQuaternionFOp); + + hmm_quaternion Result = HMM_PREFIX(DivideQuaternionF)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec2Assign, 1) +HMM_INLINE hmm_vec2 &operator+=(hmm_vec2 &Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_AddVec2Assign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_AddVec3Assign, 1) +HMM_INLINE hmm_vec3 &operator+=(hmm_vec3 &Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_AddVec3Assign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_AddVec4Assign, 1) +HMM_INLINE hmm_vec4 &operator+=(hmm_vec4 &Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_AddVec4Assign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_AddMat4Assign, 1) +HMM_INLINE hmm_mat4 &operator+=(hmm_mat4 &Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_AddMat4Assign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_AddQuaternionAssign, 1) +HMM_INLINE hmm_quaternion &operator+=(hmm_quaternion &Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_AddQuaternionAssign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_SubtractVec2Assign, 1) +HMM_INLINE hmm_vec2 &operator-=(hmm_vec2 &Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_SubtractVec2Assign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_SubtractVec3Assign, 1) +HMM_INLINE hmm_vec3 &operator-=(hmm_vec3 &Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_SubtractVec3Assign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_SubtractVec4Assign, 1) +HMM_INLINE hmm_vec4 &operator-=(hmm_vec4 &Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_SubtractVec4Assign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_SubtractMat4Assign, 1) +HMM_INLINE hmm_mat4 &operator-=(hmm_mat4 &Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_SubtractMat4Assign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_SubtractQuaternionAssign, 1) +HMM_INLINE hmm_quaternion &operator-=(hmm_quaternion &Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_SubtractQuaternionAssign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_MultiplyVec2Assign, 1) +HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2Assign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec3Assign, 1) +HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3Assign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec4Assign, 1) +HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4Assign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec2fAssign, 1) +HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2fAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec3fAssign, 1) +HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3fAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec4fAssign, 1) +HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4fAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyMat4fAssign, 1) +HMM_INLINE hmm_mat4 &operator*=(hmm_mat4 &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4fAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyQuaternionFAssign, 1) +HMM_INLINE hmm_quaternion &operator*=(hmm_quaternion &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionFAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_DivideVec2Assign, 1) +HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_DivideVec2Assign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec3Assign, 1) +HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_DivideVec3Assign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec4Assign, 1) +HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_DivideVec4Assign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec2fAssign, 1) +HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec2fAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec3fAssign, 1) +HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec3fAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec4fAssign, 1) +HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec4fAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideMat4fAssign, 1) +HMM_INLINE hmm_mat4 &operator/=(hmm_mat4 &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideMat4fAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideQuaternionFAssign, 1) +HMM_INLINE hmm_quaternion &operator/=(hmm_quaternion &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideQuaternionFAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_EqualsVec2Op, 1) +HMM_INLINE hmm_bool operator==(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_EqualsVec2Op); + + return HMM_PREFIX(EqualsVec2)(Left, Right); +} + +COVERAGE(HMM_EqualsVec3Op, 1) +HMM_INLINE hmm_bool operator==(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_EqualsVec3Op); + + return HMM_PREFIX(EqualsVec3)(Left, Right); +} + +COVERAGE(HMM_EqualsVec4Op, 1) +HMM_INLINE hmm_bool operator==(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_EqualsVec4Op); + + return HMM_PREFIX(EqualsVec4)(Left, Right); +} + +COVERAGE(HMM_EqualsVec2OpNot, 1) +HMM_INLINE hmm_bool operator!=(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_EqualsVec2OpNot); + + return !HMM_PREFIX(EqualsVec2)(Left, Right); +} + +COVERAGE(HMM_EqualsVec3OpNot, 1) +HMM_INLINE hmm_bool operator!=(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_EqualsVec3OpNot); + + return !HMM_PREFIX(EqualsVec3)(Left, Right); +} + +COVERAGE(HMM_EqualsVec4OpNot, 1) +HMM_INLINE hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_EqualsVec4OpNot); + + return !HMM_PREFIX(EqualsVec4)(Left, Right); +} + +#endif /* __cplusplus */ + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif /* HANDMADE_MATH_H */ + +#ifdef HANDMADE_MATH_IMPLEMENTATION + +COVERAGE(HMM_Power, 2) +float HMM_PREFIX(Power)(float Base, int Exponent) +{ + ASSERT_COVERED(HMM_Power); + + float Result = 1.0f; + float Mul = Exponent < 0 ? 1.f / Base : Base; + int X = Exponent < 0 ? -Exponent : Exponent; + while (X) + { + if (X & 1) + { + ASSERT_COVERED(HMM_Power); + + Result *= Mul; + } + + Mul *= Mul; + X >>= 1; + } + + return (Result); +} + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_Transpose, 1) +hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix) +{ + ASSERT_COVERED(HMM_Transpose); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Rows][Columns] = Matrix.Elements[Columns][Rows]; + } + } + + return (Result); +} +#endif + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_AddMat4, 1) +hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_AddMat4); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] + Right.Elements[Columns][Rows]; + } + } + + return (Result); +} +#endif + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_SubtractMat4, 1) +hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_SubtractMat4); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] - Right.Elements[Columns][Rows]; + } + } + + return (Result); +} +#endif + +COVERAGE(HMM_MultiplyMat4, 1) +hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4); + + hmm_mat4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.Columns[0] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[0], Left); + Result.Columns[1] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[1], Left); + Result.Columns[2] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[2], Left); + Result.Columns[3] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[3], Left); +#else + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + float Sum = 0; + int CurrentMatrice; + for(CurrentMatrice = 0; CurrentMatrice < 4; ++CurrentMatrice) + { + Sum += Left.Elements[CurrentMatrice][Rows] * Right.Elements[Columns][CurrentMatrice]; + } + + Result.Elements[Columns][Rows] = Sum; + } + } +#endif + + return (Result); +} + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_MultiplyMat4f, 1) +hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar) +{ + ASSERT_COVERED(HMM_MultiplyMat4f); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] * Scalar; + } + } + + return (Result); +} +#endif + +COVERAGE(HMM_MultiplyMat4ByVec4, 1) +hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector) +{ + ASSERT_COVERED(HMM_MultiplyMat4ByVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = HMM_PREFIX(LinearCombineSSE)(Vector.InternalElementsSSE, Matrix); +#else + int Columns, Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + float Sum = 0; + for(Columns = 0; Columns < 4; ++Columns) + { + Sum += Matrix.Elements[Columns][Rows] * Vector.Elements[Columns]; + } + + Result.Elements[Rows] = Sum; + } +#endif + + return (Result); +} + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_DivideMat4f, 1); +hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar) +{ + ASSERT_COVERED(HMM_DivideMat4f); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] / Scalar; + } + } + + return (Result); +} +#endif + +COVERAGE(HMM_Rotate, 1) +hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis) +{ + ASSERT_COVERED(HMM_Rotate); + + hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); + + Axis = HMM_PREFIX(NormalizeVec3)(Axis); + + float SinTheta = HMM_PREFIX(SinF)(HMM_PREFIX(ToRadians)(Angle)); + float CosTheta = HMM_PREFIX(CosF)(HMM_PREFIX(ToRadians)(Angle)); + float CosValue = 1.0f - CosTheta; + + Result.Elements[0][0] = (Axis.X * Axis.X * CosValue) + CosTheta; + Result.Elements[0][1] = (Axis.X * Axis.Y * CosValue) + (Axis.Z * SinTheta); + Result.Elements[0][2] = (Axis.X * Axis.Z * CosValue) - (Axis.Y * SinTheta); + + Result.Elements[1][0] = (Axis.Y * Axis.X * CosValue) - (Axis.Z * SinTheta); + Result.Elements[1][1] = (Axis.Y * Axis.Y * CosValue) + CosTheta; + Result.Elements[1][2] = (Axis.Y * Axis.Z * CosValue) + (Axis.X * SinTheta); + + Result.Elements[2][0] = (Axis.Z * Axis.X * CosValue) + (Axis.Y * SinTheta); + Result.Elements[2][1] = (Axis.Z * Axis.Y * CosValue) - (Axis.X * SinTheta); + Result.Elements[2][2] = (Axis.Z * Axis.Z * CosValue) + CosTheta; + + return (Result); +} + +COVERAGE(HMM_LookAt, 1) +hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up) +{ + ASSERT_COVERED(HMM_LookAt); + + hmm_mat4 Result; + + hmm_vec3 F = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(SubtractVec3)(Center, Eye)); + hmm_vec3 S = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(Cross)(F, Up)); + hmm_vec3 U = HMM_PREFIX(Cross)(S, F); + + Result.Elements[0][0] = S.X; + Result.Elements[0][1] = U.X; + Result.Elements[0][2] = -F.X; + Result.Elements[0][3] = 0.0f; + + Result.Elements[1][0] = S.Y; + Result.Elements[1][1] = U.Y; + Result.Elements[1][2] = -F.Y; + Result.Elements[1][3] = 0.0f; + + Result.Elements[2][0] = S.Z; + Result.Elements[2][1] = U.Z; + Result.Elements[2][2] = -F.Z; + Result.Elements[2][3] = 0.0f; + + Result.Elements[3][0] = -HMM_PREFIX(DotVec3)(S, Eye); + Result.Elements[3][1] = -HMM_PREFIX(DotVec3)(U, Eye); + Result.Elements[3][2] = HMM_PREFIX(DotVec3)(F, Eye); + Result.Elements[3][3] = 1.0f; + + return (Result); +} + +COVERAGE(HMM_InverseQuaternion, 1) +hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left) +{ + ASSERT_COVERED(HMM_InverseQuaternion); + + hmm_quaternion Conjugate; + hmm_quaternion Result; + float Norm = 0; + float NormSquared = 0; + + Conjugate.X = -Left.X; + Conjugate.Y = -Left.Y; + Conjugate.Z = -Left.Z; + Conjugate.W = Left.W; + + Norm = HMM_PREFIX(SquareRootF)(HMM_PREFIX(DotQuaternion)(Left, Left)); + NormSquared = Norm * Norm; + + Result = HMM_PREFIX(DivideQuaternionF)(Conjugate, NormSquared); + + return (Result); +} + +COVERAGE(HMM_Slerp, 1) +hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_Slerp); + + hmm_quaternion Result; + hmm_quaternion QuaternionLeft; + hmm_quaternion QuaternionRight; + + float Cos_Theta = HMM_PREFIX(DotQuaternion)(Left, Right); + float Angle = HMM_PREFIX(ACosF)(Cos_Theta); + + float S1 = HMM_PREFIX(SinF)((1.0f - Time) * Angle); + float S2 = HMM_PREFIX(SinF)(Time * Angle); + float Is = 1.0f / HMM_PREFIX(SinF)(Angle); + + QuaternionLeft = HMM_PREFIX(MultiplyQuaternionF)(Left, S1); + QuaternionRight = HMM_PREFIX(MultiplyQuaternionF)(Right, S2); + + Result = HMM_PREFIX(AddQuaternion)(QuaternionLeft, QuaternionRight); + Result = HMM_PREFIX(MultiplyQuaternionF)(Result, Is); + + return (Result); +} + +COVERAGE(HMM_QuaternionToMat4, 1) +hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left) +{ + ASSERT_COVERED(HMM_QuaternionToMat4); + + hmm_mat4 Result; + + hmm_quaternion NormalizedQuaternion = HMM_PREFIX(NormalizeQuaternion)(Left); + + float XX, YY, ZZ, + XY, XZ, YZ, + WX, WY, WZ; + + XX = NormalizedQuaternion.X * NormalizedQuaternion.X; + YY = NormalizedQuaternion.Y * NormalizedQuaternion.Y; + ZZ = NormalizedQuaternion.Z * NormalizedQuaternion.Z; + XY = NormalizedQuaternion.X * NormalizedQuaternion.Y; + XZ = NormalizedQuaternion.X * NormalizedQuaternion.Z; + YZ = NormalizedQuaternion.Y * NormalizedQuaternion.Z; + WX = NormalizedQuaternion.W * NormalizedQuaternion.X; + WY = NormalizedQuaternion.W * NormalizedQuaternion.Y; + WZ = NormalizedQuaternion.W * NormalizedQuaternion.Z; + + Result.Elements[0][0] = 1.0f - 2.0f * (YY + ZZ); + Result.Elements[0][1] = 2.0f * (XY + WZ); + Result.Elements[0][2] = 2.0f * (XZ - WY); + Result.Elements[0][3] = 0.0f; + + Result.Elements[1][0] = 2.0f * (XY - WZ); + Result.Elements[1][1] = 1.0f - 2.0f * (XX + ZZ); + Result.Elements[1][2] = 2.0f * (YZ + WX); + Result.Elements[1][3] = 0.0f; + + Result.Elements[2][0] = 2.0f * (XZ + WY); + Result.Elements[2][1] = 2.0f * (YZ - WX); + Result.Elements[2][2] = 1.0f - 2.0f * (XX + YY); + Result.Elements[2][3] = 0.0f; + + Result.Elements[3][0] = 0.0f; + Result.Elements[3][1] = 0.0f; + Result.Elements[3][2] = 0.0f; + Result.Elements[3][3] = 1.0f; + + return (Result); +} + +// This method taken from Mike Day at Insomniac Games. +// https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf +// +// Note that as mentioned at the top of the paper, the paper assumes the matrix +// would be *post*-multiplied to a vector to rotate it, meaning the matrix is +// the transpose of what we're dealing with. But, because our matrices are +// stored in column-major order, the indices *appear* to match the paper. +// +// For example, m12 in the paper is row 1, column 2. We need to transpose it to +// row 2, column 1. But, because the column comes first when referencing +// elements, it looks like M.Elements[1][2]. +// +// Don't be confused! Or if you must be confused, at least trust this +// comment. :) +COVERAGE(HMM_Mat4ToQuaternion, 4) +hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M) +{ + float T; + hmm_quaternion Q; + + if (M.Elements[2][2] < 0.0f) { + if (M.Elements[0][0] > M.Elements[1][1]) { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + + T = 1 + M.Elements[0][0] - M.Elements[1][1] - M.Elements[2][2]; + Q = HMM_PREFIX(Quaternion)( + T, + M.Elements[0][1] + M.Elements[1][0], + M.Elements[2][0] + M.Elements[0][2], + M.Elements[1][2] - M.Elements[2][1] + ); + } else { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + + T = 1 - M.Elements[0][0] + M.Elements[1][1] - M.Elements[2][2]; + Q = HMM_PREFIX(Quaternion)( + M.Elements[0][1] + M.Elements[1][0], + T, + M.Elements[1][2] + M.Elements[2][1], + M.Elements[2][0] - M.Elements[0][2] + ); + } + } else { + if (M.Elements[0][0] < -M.Elements[1][1]) { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + + T = 1 - M.Elements[0][0] - M.Elements[1][1] + M.Elements[2][2]; + Q = HMM_PREFIX(Quaternion)( + M.Elements[2][0] + M.Elements[0][2], + M.Elements[1][2] + M.Elements[2][1], + T, + M.Elements[0][1] - M.Elements[1][0] + ); + } else { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + + T = 1 + M.Elements[0][0] + M.Elements[1][1] + M.Elements[2][2]; + Q = HMM_PREFIX(Quaternion)( + M.Elements[1][2] - M.Elements[2][1], + M.Elements[2][0] - M.Elements[0][2], + M.Elements[0][1] - M.Elements[1][0], + T + ); + } + } + + Q = HMM_PREFIX(MultiplyQuaternionF)(Q, 0.5f / HMM_PREFIX(SquareRootF)(T)); + + return Q; +} + +COVERAGE(HMM_QuaternionFromAxisAngle, 1) +hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation) +{ + ASSERT_COVERED(HMM_QuaternionFromAxisAngle); + + hmm_quaternion Result; + + hmm_vec3 AxisNormalized = HMM_PREFIX(NormalizeVec3)(Axis); + float SineOfRotation = HMM_PREFIX(SinF)(AngleOfRotation / 2.0f); + + Result.XYZ = HMM_PREFIX(MultiplyVec3f)(AxisNormalized, SineOfRotation); + Result.W = HMM_PREFIX(CosF)(AngleOfRotation / 2.0f); + + return (Result); +} + +#endif /* HANDMADE_MATH_IMPLEMENTATION */ \ No newline at end of file diff --git a/src/app/interface.h b/src/app/interface.h index 33a50ac..d382f4c 100644 --- a/src/app/interface.h +++ b/src/app/interface.h @@ -5,7 +5,7 @@ // #ifndef INTERFACE_H -enum string_alignment +enum gs_string_alignment { Align_Left, Align_Center, @@ -60,10 +60,10 @@ DrawCharacterRightAligned (render_quad_batch_constructor* BatchConstructor, char } internal v2 -DrawStringLeftAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* String, v2 InitialRegisterPosition, bitmap_font* Font, v4 Color) +DrawStringLeftAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* gs_string, v2 InitialRegisterPosition, bitmap_font* Font, v4 Color) { v2 RegisterPosition = InitialRegisterPosition; - char* C = String; + char* C = gs_string; for (s32 i = 0; i < Length; i++) { v2 PositionAfterCharacter = DrawCharacterLeftAligned(BatchConstructor, *C, *Font, RegisterPosition, Color); @@ -74,10 +74,10 @@ DrawStringLeftAligned (render_quad_batch_constructor* BatchConstructor, s32 Leng } internal v2 -DrawStringRightAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* String, v2 InitialRegisterPosition, bitmap_font* Font, v4 Color) +DrawStringRightAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* gs_string, v2 InitialRegisterPosition, bitmap_font* Font, v4 Color) { v2 RegisterPosition = InitialRegisterPosition; - char* C = String + Length - 1; + char* C = gs_string + Length - 1; for (s32 i = Length - 1; i >= 0; i--) { v2 PositionAfterCharacter = DrawCharacterRightAligned(BatchConstructor, *C, *Font, RegisterPosition, Color); @@ -88,7 +88,7 @@ DrawStringRightAligned (render_quad_batch_constructor* BatchConstructor, s32 Len } internal v2 -DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Font, v2 Position, v4 Color, string_alignment Alignment = Align_Left) +DrawString(render_command_buffer* RenderBuffer, gs_string String, bitmap_font* Font, v2 Position, v4 Color, gs_string_alignment Alignment = Align_Left) { DEBUG_TRACK_FUNCTION; v2 LowerRight = Position; @@ -129,7 +129,7 @@ DrawCursor (render_quad_batch_constructor* BatchConstructor, v2 Position, v4 Col } internal v2 -DrawStringWithCursor (render_command_buffer* RenderBuffer, string String, s32 CursorPosition, bitmap_font* Font, v2 Position, v4 Color, v4 CursorColor, string_alignment Alignment = Align_Left) +Drawgs_stringWithCursor (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; @@ -153,21 +153,21 @@ DrawStringWithCursor (render_command_buffer* RenderBuffer, string String, s32 Cu { RegisterPosition = DrawStringLeftAligned(&BatchConstructor, String.Length - CursorPosition, - String.Memory + CursorPosition, + String.Str + CursorPosition, RegisterPosition, Font, Color); } } else if (Alignment == Align_Right) { RegisterPosition = DrawStringRightAligned(&BatchConstructor, - CursorPosition, String.Memory, + CursorPosition, String.Str, RegisterPosition, Font, Color); DrawCursor(&CursorBatch, RegisterPosition, GreenV4, *Font); if (String.Length - CursorPosition > 0) { RegisterPosition = DrawStringRightAligned(&BatchConstructor, String.Length - CursorPosition, - String.Memory + CursorPosition, + String.Str + CursorPosition, RegisterPosition, Font, Color); } } @@ -201,7 +201,7 @@ struct interface_config struct ui_layout { - rect Bounds; + rect2 Bounds; v2 Margin; r32 RowHeight; r32 RowYAt; @@ -220,7 +220,7 @@ struct ui_interface }; static ui_layout -ui_CreateLayout(ui_interface Interface, rect Bounds) +ui_CreateLayout(ui_interface Interface, rect2 Bounds) { ui_layout Result = {0}; Result.Bounds = Bounds; @@ -263,7 +263,7 @@ ui_EndRow(ui_layout* Layout) } static b32 -ui_TryReserveElementBounds(ui_layout* Layout, rect* Bounds) +ui_TryReserveElementBounds(ui_layout* Layout, rect2* Bounds) { b32 Result = true; if (!Layout->DrawHorizontal) @@ -289,7 +289,7 @@ ui_TryReserveElementBounds(ui_layout* Layout, rect* Bounds) } else { - r32 ElementWidth = gs_Width(Layout->Bounds) / Layout->ColumnsMax; + r32 ElementWidth = Rect2Width(Layout->Bounds) / Layout->ColumnsMax; Bounds->Min = { Layout->Bounds.Min.x + (ElementWidth * Layout->ColumnsCount) + Layout->Margin.x, Layout->RowYAt @@ -309,18 +309,18 @@ ui_TryReserveElementBounds(ui_layout* Layout, rect* Bounds) return Result; } -static rect -ui_ReserveTextLineBounds(ui_interface Interface, string Text, ui_layout* Layout) +static rect2 +ui_ReserveTextLineBounds(ui_interface Interface, gs_string Text, ui_layout* Layout) { - rect Bounds = {0}; + rect2 Bounds = {0}; return Bounds; } -static rect +static rect2 ui_ReserveElementBounds(ui_layout* Layout) { - rect Bounds = {0}; + rect2 Bounds = {0}; if (!ui_TryReserveElementBounds(Layout, &Bounds)) { InvalidCodePath; @@ -328,10 +328,10 @@ ui_ReserveElementBounds(ui_layout* Layout) return Bounds; } -static rect +static rect2 ui_LayoutRemaining(ui_layout Layout) { - rect Result = Layout.Bounds; + rect2 Result = Layout.Bounds; Result.Max.y = Layout.RowYAt; if (Layout.DrawHorizontal) { @@ -352,19 +352,19 @@ ui_GetTextLineHeight(ui_interface Interface) } static void -ui_FillRect(ui_interface* Interface, rect Bounds, v4 Color) +ui_FillRect(ui_interface* Interface, rect2 Bounds, v4 Color) { - PushRenderQuad2D(Interface->RenderBuffer, gs_RectExpand(Bounds), Color); + PushRenderQuad2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, Color); } static void -ui_OutlineRect(ui_interface* Interface, rect Bounds, r32 Thickness, v4 Color) +ui_OutlineRect(ui_interface* Interface, rect2 Bounds, r32 Thickness, v4 Color) { PushRenderBoundingBox2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, Thickness, Color); } internal void -ui_DrawString(ui_interface* Interface, string String, rect Bounds, v4 Color, string_alignment Alignment = Align_Left) +ui_DrawString(ui_interface* Interface, gs_string String, rect2 Bounds, v4 Color, gs_string_alignment Alignment = Align_Left) { DEBUG_TRACK_FUNCTION; render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(Interface->RenderBuffer, @@ -392,9 +392,9 @@ ui_DrawString(ui_interface* Interface, string String, rect Bounds, v4 Color, str } static void -ui_LayoutDrawString(ui_interface* Interface, ui_layout* Layout, string String, v4 Color, string_alignment Alignment = Align_Left) +ui_LayoutDrawString(ui_interface* Interface, ui_layout* Layout, gs_string String, v4 Color, gs_string_alignment Alignment = Align_Left) { - rect Bounds = {0}; + rect2 Bounds = {0}; if (!ui_TryReserveElementBounds(Layout, &Bounds)) { // TODO(NAME): Not invalid, just haven't implemented yet. @@ -405,18 +405,18 @@ ui_LayoutDrawString(ui_interface* Interface, ui_layout* Layout, string String, v } static void -ui_TextBox(ui_interface* Interface, rect Bounds, string Text, v4 BGColor, v4 TextColor) +ui_TextBox(ui_interface* Interface, rect2 Bounds, gs_string Text, v4 BGColor, v4 TextColor) { ui_FillRect(Interface, Bounds, BGColor); ui_DrawString(Interface, Text, Bounds, TextColor); } static b32 -ui_Button(ui_interface* Interface, string Text, rect Bounds, v4 InactiveColor, v4 HoverColor, v4 ClickedColor) +ui_Button(ui_interface* Interface, gs_string Text, rect2 Bounds, v4 InactiveColor, v4 HoverColor, v4 ClickedColor) { b32 Pressed = false; v4 ButtonBG = InactiveColor; - if (gs_PointIsInRect(Interface->Mouse.Pos, Bounds)) + if (PointIsInRect(Bounds, Interface->Mouse.Pos)) { ButtonBG = HoverColor; if (MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState)) @@ -430,7 +430,7 @@ ui_Button(ui_interface* Interface, string Text, rect Bounds, v4 InactiveColor, v } static b32 -ui_Button(ui_interface* Interface, string Text, rect Bounds) +ui_Button(ui_interface* Interface, gs_string Text, rect2 Bounds) { v4 BGColor = Interface->Style.ButtonColor_Inactive; v4 HoverColor = Interface->Style.ButtonColor_Active; @@ -463,16 +463,16 @@ ui_GetListItemColors(ui_interface* Interface, u32 ListItemIndex) } static b32 -ui_ListButton(ui_interface* Interface, string Text, rect Bounds, u32 ListItemIndex) +ui_ListButton(ui_interface* Interface, gs_string Text, rect2 Bounds, u32 ListItemIndex) { list_item_colors Colors = ui_GetListItemColors(Interface, ListItemIndex); return ui_Button(Interface, Text, Bounds, Colors.Hover, Colors.Selected, Colors.BGColor); } static b32 -ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text, v4 BGColor, v4 HoverColor, v4 SelectColor) +ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, gs_string Text, v4 BGColor, v4 HoverColor, v4 SelectColor) { - rect ButtonBounds = {0}; + rect2 ButtonBounds = {0}; if (!ui_TryReserveElementBounds(Layout, &ButtonBounds)) { ButtonBounds = ui_ReserveTextLineBounds(*Interface, Text, Layout); @@ -481,7 +481,7 @@ ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text, v4 BGCo } static b32 -ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text) +ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, gs_string Text) { v4 BGColor = Interface->Style.ButtonColor_Inactive; v4 HoverColor = Interface->Style.ButtonColor_Active; @@ -490,16 +490,16 @@ ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text) } static b32 -ui_LayoutListButton(ui_interface* Interface, ui_layout* Layout, string Text, u32 ListItemIndex) +ui_LayoutListButton(ui_interface* Interface, ui_layout* Layout, gs_string Text, u32 ListItemIndex) { list_item_colors Colors = ui_GetListItemColors(Interface, ListItemIndex); return ui_LayoutButton(Interface, Layout, Text, Colors.Hover, Colors.Selected, Colors.BGColor); } static b32 -ui_LayoutListEntry(ui_interface* Interface, ui_layout* Layout, string Text, u32 Index) +ui_LayoutListEntry(ui_interface* Interface, ui_layout* Layout, gs_string Text, u32 Index) { - rect Bounds = {0}; + rect2 Bounds = {0}; if (!ui_TryReserveElementBounds(Layout, &Bounds)) { // TODO(Peter): this isn't really invalid, but I don't have a concrete use case @@ -527,7 +527,7 @@ enum selection_state struct interface_list { - rect ListBounds; + rect2 ListBounds; v2 ListElementDimensions; v2 ElementLabelIndent; @@ -540,10 +540,10 @@ struct interface_list s32 ListElementsCount; }; -internal rect +internal rect2 DrawListElementBackground(interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer) { - rect LineBounds = {}; + rect2 LineBounds = {}; LineBounds.Min = v2{ List->ListBounds.Min.x, List->ListBounds.Max.y - (List->ListElementDimensions.y * (List->ListElementsCount + 1)) @@ -551,7 +551,7 @@ DrawListElementBackground(interface_list* List, mouse_state Mouse, render_comman LineBounds.Max = LineBounds.Min + List->ListElementDimensions; v4 Color = List->LineBGColors[List->ListElementsCount % List->LineBGColorsCount]; - if (PointIsInRange(Mouse.Pos, LineBounds.Min, LineBounds.Max)) + if (PointIsInRect(LineBounds, Mouse.Pos)) { Color = List->LineBGHoverColor; } @@ -560,10 +560,10 @@ DrawListElementBackground(interface_list* List, mouse_state Mouse, render_comman return LineBounds; } -internal rect -DrawListElement(string Label, interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer, interface_config Interface) +internal rect2 +DrawListElement(gs_string Label, interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer, interface_config Interface) { - rect Bounds = DrawListElementBackground(List, Mouse, RenderBuffer); + rect2 Bounds = DrawListElementBackground(List, Mouse, RenderBuffer); v2 LabelPosition = Bounds.Min + List->ElementLabelIndent; DrawString(RenderBuffer, Label, Interface.Font, LabelPosition, List->TextColor); @@ -578,27 +578,34 @@ EvaluateColorChannelSlider (render_command_buffer* RenderBuffer, v4 ChannelMask, { r32 Result = Current; + // TODO(Peter): Can this come from outside the function? Would rather pass rect around than min/max + rect2 Rect = rect2{ Min, Max }; + render_quad_batch_constructor Batch = PushRenderQuad2DBatch(RenderBuffer, 2); v4 LeftColor = ChannelMask * 0; LeftColor.a = 1.f; v4 RightColor = ChannelMask; PushQuad2DOnBatch(&Batch, - Min, v2{Max.x, Min.y}, Max, v2{Min.x, Max.y}, + RectBottomLeft(Rect), RectBottomRight(Rect), + RectTopRight(Rect), RectTopLeft(Rect), v2{0, 0}, v2{1, 0}, v2{1, 1}, v2{0, 1}, LeftColor, RightColor, RightColor, LeftColor); if (MouseButtonTransitionedDown(Mouse.LeftButtonState)) { - if (PointIsInRange(Mouse.DownPos, Min, Max)) + if (PointIsInRect(Rect, Mouse.DownPos)) { Result = ((r32)Mouse.Pos.x - Min.x) / (Max.x - Min.x); - Result = GSClamp01(Result); + Result = Clamp01(Result); } } r32 DragBarWidth = 8; - v2 DragBarMin = v2{GSLerp(Min.x, Max.x, Result) - (DragBarWidth / 2), Min.y - 2}; + v2 DragBarMin = v2{ + LerpR32(Result, Min.x, Max.x) - (DragBarWidth / 2), + Min.y - 2 + }; v2 DragBarMax = DragBarMin + v2{DragBarWidth, (Max.y - Min.y) + 4}; PushQuad2DOnBatch(&Batch, DragBarMin, DragBarMax, v4{.3f, .3f, .3f, 1.f}); @@ -612,16 +619,18 @@ EvaluateColorPicker (render_command_buffer* RenderBuffer, v4* Value, v2 PanelMin b32 ShouldClose = false; v2 PanelMax = v2{400, 500}; - if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && !PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) + // TODO(Peter): Can this get passed from outside? rather pass rect2 than min/max pairs + rect2 PanelRect = rect2{PanelMin, PanelMax}; + if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && !PointIsInRect(PanelRect, Mouse.Pos)) { ShouldClose = true; } else { - PushRenderQuad2D(RenderBuffer, PanelMin, PanelMax, v4{.5f, .5f, .5f, 1.f}); + PushRenderQuad2D(RenderBuffer, PanelRect.Min, PanelRect.Max, v4{.5f, .5f, .5f, 1.f}); - v2 TitleMin = v2{PanelMin.x + 5, PanelMax.y - (Config.Font->PixelHeight + 5)}; - DrawString(RenderBuffer, MakeStringLiteral("Color Picker"), Config.Font, + v2 TitleMin = v2{PanelRect.Min.x + 5, PanelRect.Max.y - (Config.Font->PixelHeight + 5)}; + DrawString(RenderBuffer, MakeString("Color Picker"), Config.Font, TitleMin, WhiteV4); v2 SliderDim = v2{(PanelMax.x - PanelMin.x) - 20, 32}; @@ -650,13 +659,13 @@ struct search_lister_result b32 ShouldRemainOpen; }; -typedef string search_lister_get_list_item_at_offset(u8* ListMemory, s32 ListLength, string SearchString, s32 Offset); +typedef gs_string search_lister_get_list_item_at_offset(u8* ListMemory, s32 ListLength, gs_string Searchgs_string, s32 Offset); internal search_lister_result -EvaluateSearchLister (ui_interface* Interface, v2 TopLeft, v2 Dimension, string Title, - string* ItemList, s32* ListLUT, s32 ListLength, +EvaluateSearchLister (ui_interface* Interface, v2 TopLeft, v2 Dimension, gs_string Title, + gs_string* ItemList, s32* ListLUT, s32 ListLength, s32 HotItem, - string* SearchString, s32 SearchStringCursorPosition) + gs_string* Searchgs_string, s32 Searchgs_stringCursorPosition) { search_lister_result Result = {}; Result.ShouldRemainOpen = true; @@ -666,24 +675,24 @@ EvaluateSearchLister (ui_interface* Interface, v2 TopLeft, v2 Dimension, string InvalidCodePath; #if 0 // Title Bar - rect TitleBarBounds = rect{v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}}; + rect2 TitleBarBounds = rect2{v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}}; ui_FillRect(Interface, TitleBarBounds, v4{.3f, .3f, .3f, 1.f}); - ui_DrawString(Interface, Title, TitleBarBounds, Interface->Style.TextColor); + ui_Drawgs_string(Interface, Title, TitleBarBounds, Interface->Style.TextColor); - MakeStringBuffer(DebugString, 256); - PrintF(&DebugString, "Hot Item: %d | Filtered Items: %d", HotItem, ListLength); - rect DebugBounds = MakeRectMinWidth(v2{ TopLeft.x + 256, TopLeft.y - 25}, v2{256, Interface->Style.LineHeight}); - ui_DrawString(Interface, DebugString, DebugBounds, Interface->Style.TextColor); + MakeStringBuffer(Debuggs_string, 256); + PrintF(&Debuggs_string, "Hot Item: %d | Filtered Items: %d", HotItem, ListLength); + rect2 DebugBounds = MakeRectMinWidth(v2{ TopLeft.x + 256, TopLeft.y - 25}, v2{256, Interface->Style.LineHeight}); + ui_Drawgs_string(Interface, Debuggs_string, DebugBounds, Interface->Style.TextColor); // Search Bar PushRenderQuad2D(RenderBuffer, v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}, v4{.3f, .3f, .3f, 1.f}); - DrawStringWithCursor(RenderBuffer, *SearchString, SearchStringCursorPosition, Font, v2{TopLeft.x, TopLeft.y - 25}, WhiteV4, GreenV4); + Drawgs_stringWithCursor(RenderBuffer, *Searchgs_string, Searchgs_stringCursorPosition, Font, v2{TopLeft.x, TopLeft.y - 25}, WhiteV4, GreenV4); TopLeft.y -= 30; for (s32 i = 0; i < ListLength; i++) { s32 FilteredIndex = ListLUT[i]; - string ListItemString = ItemList[FilteredIndex]; + gs_string ListItemgs_string = ItemList[FilteredIndex]; v2 Min = v2{TopLeft.x, TopLeft.y - 30}; v2 Max = Min + Dimension - v2{0, Config.Margin.y}; @@ -694,7 +703,7 @@ EvaluateSearchLister (ui_interface* Interface, v2 TopLeft, v2 Dimension, string ButtonColor = Config.ButtonColor_Active; } - if (ui_Button(Interface, ListItemString, rect{Min, Max})) + if (ui_Button(Interface, ListItemgs_string, rect2{Min, Max})) { Result.SelectedItem = i; } diff --git a/src/app/panels/foldhaus_panel_animation_timeline.h b/src/app/panels/foldhaus_panel_animation_timeline.h index 0f5e9b6..fcbf0c1 100644 --- a/src/app/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/panels/foldhaus_panel_animation_timeline.h @@ -6,7 +6,7 @@ #ifndef FOLDHAUS_PANEL_ANIMATION_TIMELINE_H // Colors -global_variable v4 TimeSliderColor = v4{.36f, .52f, .78f, 1.f}; +global v4 TimeSliderColor = v4{.36f, .52f, .78f, 1.f}; // struct animation_timeline_state @@ -15,7 +15,7 @@ struct animation_timeline_state }; inline u32 -GetFrameFromPointInAnimationPanel(v2 Point, rect PanelBounds, frame_range VisibleRange) +GetFrameFromPointInAnimationPanel(v2 Point, rect2 PanelBounds, frame_range VisibleRange) { r32 HorizontalPercentOfBounds = (Point.x - PanelBounds.Min.x) / (PanelBounds.Max.x - PanelBounds.Min.x); u32 VisibleFramesCount = GetFrameCount(VisibleRange); @@ -24,10 +24,10 @@ GetFrameFromPointInAnimationPanel(v2 Point, rect PanelBounds, frame_range Visibl } inline s32 -GetXPositionFromFrameInAnimationPanel (u32 Frame, rect PanelBounds, frame_range VisibleRange) +GetXPositionFromFrameInAnimationPanel (u32 Frame, rect2 PanelBounds, frame_range VisibleRange) { r32 PercentOfTimeline = (r32)(Frame - VisibleRange.Min) / (r32)GetFrameCount(VisibleRange); - s32 XPositionAtFrame = (PercentOfTimeline * gs_Width(PanelBounds)) + PanelBounds.Min.x; + s32 XPositionAtFrame = (PercentOfTimeline * Rect2Width(PanelBounds)) + PanelBounds.Min.x; return XPositionAtFrame; } @@ -67,7 +67,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand) OPERATION_STATE_DEF(drag_time_marker_operation_state) { - rect TimelineBounds; + rect2 TimelineBounds; s32 StartFrame; s32 EndFrame; }; @@ -90,7 +90,7 @@ input_command DragTimeMarkerCommands [] = { }; internal void -StartDragTimeMarker(rect TimelineBounds, frame_range VisibleFrames, app_state* State) +StartDragTimeMarker(rect2 TimelineBounds, frame_range VisibleFrames, app_state* State) { operation_mode* DragTimeMarkerMode = ActivateOperationModeWithCommands(&State->Modes, DragTimeMarkerCommands, UpdateDragTimeMarker); @@ -112,7 +112,7 @@ StartDragTimeMarker(rect TimelineBounds, frame_range VisibleFrames, app_state* S OPERATION_STATE_DEF(drag_animation_clip_state) { - rect TimelineBounds; + rect2 TimelineBounds; frame_range VisibleRange; frame_range ClipRange; }; @@ -122,7 +122,7 @@ AttemptToSnapPosition(u32 SnappingFrame, u32 SnapToFrame) { u32 Result = SnappingFrame; s32 SnapDistance = 5; - if (GSAbs((s32)SnappingFrame - (s32)SnapToFrame) <= SnapDistance) + if (Abs((s32)SnappingFrame - (s32)SnapToFrame) <= SnapDistance) { Result = SnapToFrame; } @@ -134,13 +134,13 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) drag_animation_clip_state* OpState = (drag_animation_clip_state*)Operation.OpStateMemory; r32 ClipInitialStartFrameXPercent = FrameToPercentRange(OpState->ClipRange.Min, OpState->VisibleRange); - u32 ClipInitialStartFrameXPosition = GSLerp(OpState->TimelineBounds.Min.x, - OpState->TimelineBounds.Max.x, - ClipInitialStartFrameXPercent); + u32 ClipInitialStartFrameXPosition = LerpR32(ClipInitialStartFrameXPercent, + OpState->TimelineBounds.Min.x, + OpState->TimelineBounds.Max.x); r32 ClipInitialEndFrameXPercent = FrameToPercentRange(OpState->ClipRange.Max, OpState->VisibleRange); - u32 ClipInitialEndFrameXPosition = GSLerp(OpState->TimelineBounds.Min.x, - OpState->TimelineBounds.Max.x, - ClipInitialEndFrameXPercent); + u32 ClipInitialEndFrameXPosition = LerpR32(ClipInitialEndFrameXPercent, + OpState->TimelineBounds.Min.x, + OpState->TimelineBounds.Max.x); u32 FrameAtMouseDownX = GetFrameFromPointInAnimationPanel(Mouse.DownPos, OpState->TimelineBounds, OpState->VisibleRange); @@ -154,7 +154,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) return; } - if (GSAbs(Mouse.DownPos.x - ClipInitialStartFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) + if (Abs(Mouse.DownPos.x - ClipInitialStartFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) { s32 NewStartFrame = OpState->ClipRange.Min + FrameOffset; if (FrameOffset < 0) @@ -176,7 +176,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) } AnimationBlock->Range.Min = NewStartFrame; } - else if (GSAbs(Mouse.DownPos.x - ClipInitialEndFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) + else if (Abs(Mouse.DownPos.x - ClipInitialEndFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) { r32 NewEndFrame = OpState->ClipRange.Max + FrameOffset; if (FrameOffset > 0) @@ -228,8 +228,8 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) s32 PlayableStartFrame = State->AnimationSystem.PlayableRange.Min; s32 PlayableEndFrame = State->AnimationSystem.PlayableRange.Max; - AnimationBlock->Range.Min = (u32)GSClamp(PlayableStartFrame, (s32)AnimationBlock->Range.Min, PlayableEndFrame); - AnimationBlock->Range.Max = (u32)GSClamp(PlayableStartFrame, (s32)AnimationBlock->Range.Max, PlayableEndFrame); + AnimationBlock->Range.Min = (u32)Clamp(PlayableStartFrame, (s32)AnimationBlock->Range.Min, PlayableEndFrame); + AnimationBlock->Range.Max = (u32)Clamp(PlayableStartFrame, (s32)AnimationBlock->Range.Max, PlayableEndFrame); } input_command DragAnimationClipCommands [] = { @@ -237,7 +237,7 @@ input_command DragAnimationClipCommands [] = { }; internal void -SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range VisibleRange, rect TimelineBounds, app_state* State) +SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range VisibleRange, rect2 TimelineBounds, app_state* State) { SelectAnimationBlock(BlockHandle, State); @@ -289,20 +289,20 @@ AnimationTimeline_Cleanup(panel* Panel, app_state* State) } internal void -DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBuffer, frame_range VisibleFrames, rect BarBounds, mouse_state Mouse, app_state* State) +DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBuffer, frame_range VisibleFrames, rect2 BarBounds, mouse_state Mouse, app_state* State) { - string TempString = PushString(&State->Transient, 256); + gs_string TempString = PushString(&State->Transient, 256); s32 VisibleFrameCount = VisibleFrames.Max - VisibleFrames.Min; - r32 BarHeight = gs_Height(BarBounds); - r32 BarWidth = gs_Width(BarBounds); + r32 BarHeight = Rect2Height(BarBounds); + r32 BarWidth = Rect2Width(BarBounds); - PushRenderQuad2D(RenderBuffer, gs_RectExpand(BarBounds), v4{.16f, .16f, .16f, 1.f}); + PushRenderQuad2D(RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); // Mouse clicked inside frame nubmer bar -> change current frame on timeline if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && - PointIsInRange(Mouse.DownPos, gs_RectExpand(BarBounds))) + PointIsInRect(BarBounds, Mouse.DownPos)) { StartDragTimeMarker(BarBounds, VisibleFrames, State); } @@ -315,7 +315,7 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu u32 Frame = PercentToFrameInRange(Percent, VisibleFrames); PrintF(&TempString, "%d", Frame); r32 FramePercent = FrameToPercentRange(Frame, VisibleFrames); - r32 FrameX = GSLerp(BarBounds.Min.x, BarBounds.Max.x, FramePercent); + r32 FrameX = LerpR32(FramePercent, BarBounds.Min.x, BarBounds.Max.x); v2 FrameTextPos = v2{FrameX, BarBounds.Min.y + 2}; DrawString(RenderBuffer, TempString, State->Interface.Style.Font, FrameTextPos, WhiteV4); } @@ -324,29 +324,28 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu if (FrameIsInRange(AnimationSystem->CurrentFrame, VisibleFrames)) { r32 FrameAtPercentVisibleRange = FrameToPercentRange(AnimationSystem->CurrentFrame, VisibleFrames); - r32 SliderX = GSLerp(BarBounds.Min.x, BarBounds.Max.x, FrameAtPercentVisibleRange); + r32 SliderX = LerpR32(FrameAtPercentVisibleRange, BarBounds.Min.x, BarBounds.Max.x); + + PrintF(&TempString, "%d", AnimationSystem->CurrentFrame); - u32 FrameNumberCharCount = GetU32NumberOfCharactersNeeded(AnimationSystem->CurrentFrame); // space for each character + a margin on either side - r32 SliderWidth = (8 * FrameNumberCharCount) + 8; + r32 SliderWidth = (8 * TempString.Length) + 8; r32 SliderHalfWidth = SliderWidth / 2.f; v2 HeadMin = v2{SliderX - SliderHalfWidth, BarBounds.Min.y}; v2 HeadMax = v2{SliderX + SliderHalfWidth, BarBounds.Max.y}; PushRenderQuad2D(RenderBuffer, HeadMin, HeadMax, TimeSliderColor); - - PrintF(&TempString, "%d", AnimationSystem->CurrentFrame); DrawString(RenderBuffer, TempString, State->Interface.Style.Font, HeadMin + v2{6, 4}, WhiteV4); } } internal frame_range -DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_state* TimelineState, render_command_buffer* RenderBuffer, rect BarBounds, mouse_state Mouse) +DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_state* TimelineState, render_command_buffer* RenderBuffer, rect2 BarBounds, mouse_state Mouse) { frame_range Result = {0}; - r32 BarHeight = gs_Height(BarBounds); - r32 BarWidth = gs_Width(BarBounds); - PushRenderQuad2D(RenderBuffer, gs_RectExpand(BarBounds), v4{.16f, .16f, .16f, 1.f}); + r32 BarHeight = Rect2Height(BarBounds); + r32 BarWidth = Rect2Width(BarBounds); + PushRenderQuad2D(RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); r32 PlayableFrames = (r32)GetFrameCount(AnimationSystem->PlayableRange); v2 SliderBarDim = v2{25, BarHeight}; @@ -354,22 +353,24 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat // Convert Frames To Pixels r32 VisibleMinPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Min, AnimationSystem->PlayableRange); r32 VisibleMaxPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Max, AnimationSystem->PlayableRange); - v2 RangeMinSliderMin = v2{BarBounds.Min.x + (VisibleMinPercentPlayable * gs_Width(BarBounds)), BarBounds.Min.y}; - v2 RangeMaxSliderMin = v2{BarBounds.Min.x + (VisibleMaxPercentPlayable * gs_Width(BarBounds)) - 25, BarBounds.Min.y}; + v2 RangeMinSliderMin = v2{BarBounds.Min.x + (VisibleMinPercentPlayable * Rect2Width(BarBounds)), BarBounds.Min.y}; + v2 RangeMaxSliderMin = v2{BarBounds.Min.x + (VisibleMaxPercentPlayable * Rect2Width(BarBounds)) - 25, BarBounds.Min.y}; + + rect2 SliderBarRange = rect2{ RangeMinSliderMin, RangeMinSliderMin + SliderBarDim }; if (MouseButtonHeldDown(Mouse.LeftButtonState) || MouseButtonTransitionedUp(Mouse.LeftButtonState)) { v2 MouseDragOffset = Mouse.Pos - Mouse.DownPos; - if (PointIsInRange(Mouse.DownPos, RangeMinSliderMin, RangeMinSliderMin + SliderBarDim)) + if (PointIsInRect(SliderBarRange, Mouse.DownPos)) { r32 NewSliderX = RangeMinSliderMin.x + MouseDragOffset.x; - RangeMinSliderMin.x = GSClamp(BarBounds.Min.x, NewSliderX, RangeMaxSliderMin.x - SliderBarDim.x); + RangeMinSliderMin.x = Clamp(BarBounds.Min.x, NewSliderX, RangeMaxSliderMin.x - SliderBarDim.x); } - if (PointIsInRange(Mouse.DownPos, RangeMaxSliderMin, RangeMaxSliderMin + SliderBarDim)) + if (PointIsInRect(SliderBarRange, Mouse.DownPos)) { r32 NewSliderX = RangeMaxSliderMin.x + MouseDragOffset.x; - RangeMaxSliderMin.x = GSClamp(RangeMinSliderMin.x + SliderBarDim.x, NewSliderX, BarBounds.Max.x - SliderBarDim.x); + RangeMaxSliderMin.x = Clamp(RangeMinSliderMin.x + SliderBarDim.x, NewSliderX, BarBounds.Max.x - SliderBarDim.x); } } @@ -396,19 +397,19 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat #define LAYER_HEIGHT 52 internal void -DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) +DrawLayerMenu(animation_system* AnimationSystem, rect2 PanelDim, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) { - v2 LayerDim = { gs_Width(PanelDim), LAYER_HEIGHT }; + v2 LayerDim = { Rect2Width(PanelDim), LAYER_HEIGHT }; v2 LayerListMin = PanelDim.Min + v2{0, 24}; for (u32 LayerIndex = 0; LayerIndex < AnimationSystem->LayersCount; LayerIndex++) { anim_layer* Layer = AnimationSystem->Layers + LayerIndex; - rect LayerBounds = {0}; + rect2 LayerBounds = {0}; LayerBounds.Min = { LayerListMin.x, LayerListMin.y + (LayerDim.y * LayerIndex) }; LayerBounds.Max = LayerBounds.Min + LayerDim; if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && - gs_PointIsInRect(Mouse.Pos, LayerBounds)) + PointIsInRect(LayerBounds, Mouse.Pos)) { State->SelectedAnimationLayer = LayerIndex; } @@ -416,18 +417,18 @@ DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_b v2 LayerTextPos = { LayerBounds.Min.x + 6, LayerBounds.Max.y - 16}; if (State->SelectedAnimationLayer == LayerIndex) { - PushRenderBoundingBox2D(RenderBuffer, gs_RectExpand(LayerBounds), 1, WhiteV4); + PushRenderBoundingBox2D(RenderBuffer, LayerBounds.Min, LayerBounds.Max, 1, WhiteV4); } DrawString(RenderBuffer, Layer->Name, State->Interface.Style.Font, LayerTextPos, WhiteV4); } } -internal rect -DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range VisibleFrames, rect TimelineBounds, render_command_buffer* RenderBuffer) +internal rect2 +DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range VisibleFrames, rect2 TimelineBounds, render_command_buffer* RenderBuffer) { - rect BlockBounds = {}; + rect2 BlockBounds = {}; - r32 TimelineWidth = gs_Width(TimelineBounds); + r32 TimelineWidth = Rect2Width(TimelineBounds); u32 ClampedBlockStartFrame = ClampFrameToRange(AnimationBlock.Range.Min, VisibleFrames); r32 StartFramePercent = FrameToPercentRange(ClampedBlockStartFrame, VisibleFrames); @@ -448,18 +449,18 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V } internal gs_list_handle -DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect PanelBounds, gs_list_handle SelectedBlockHandle, ui_interface* Interface, app_state* State) +DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect2 PanelBounds, gs_list_handle SelectedBlockHandle, ui_interface* Interface, app_state* State) { - string TempString = PushString(&State->Transient, 256); + gs_string Tempgs_string = PushString(&State->Transient, 256); gs_list_handle Result = SelectedBlockHandle; - rect LayerMenuBounds, TimelineBounds; - gs_VSplitRectAtDistanceFromLeft(PanelBounds, 256, &LayerMenuBounds, &TimelineBounds); + rect2 LayerMenuBounds, TimelineBounds; + RectVSplitAtDistanceFromLeft(PanelBounds, 256, &LayerMenuBounds, &TimelineBounds); // In Top To Bottom Order - rect TimelineFrameBarBounds, TimelineBlockDisplayBounds, TimelineRangeBarBounds; - gs_HSplitRectAtDistanceFromTop(TimelineBounds, 32, &TimelineFrameBarBounds, &TimelineBounds); - gs_HSplitRectAtDistanceFromBottom(TimelineBounds, 24, &TimelineBlockDisplayBounds, &TimelineRangeBarBounds); + rect2 TimelineFrameBarBounds, TimelineBlockDisplayBounds, TimelineRangeBarBounds; + RectHSplitAtDistanceFromTop(TimelineBounds, 32, &TimelineFrameBarBounds, &TimelineBounds); + RectHSplitAtDistanceFromBottom(TimelineBounds, 24, &TimelineBlockDisplayBounds, &TimelineRangeBarBounds); // TODO(Peter): Clean Up DrawLayerMenu(AnimationSystem, LayerMenuBounds, Interface->RenderBuffer, State, Interface->Mouse); @@ -500,8 +501,8 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta BlockColor = PinkV4; } // TODO(Peter): Clean Up - rect BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer); - if (gs_PointIsInRect(Interface->Mouse.Pos, BlockBounds)) + rect2 BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer); + if (PointIsInRect(BlockBounds, Interface->Mouse.Pos)) { DragBlockHandle = CurrentBlockHandle; } @@ -519,8 +520,8 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta if (FrameIsInRange(AnimationSystem->CurrentFrame, AdjustedViewRange)) { r32 FrameAtPercentVisibleRange = FrameToPercentRange(AnimationSystem->CurrentFrame, AdjustedViewRange); - r32 SliderX = GSLerp(TimelineBounds.Min.x, TimelineBounds.Max.x, FrameAtPercentVisibleRange); - rect SliderBounds = { + r32 SliderX = LerpR32(FrameAtPercentVisibleRange, TimelineBounds.Min.x, TimelineBounds.Max.x); + rect2 SliderBounds = { v2{ SliderX, TimelineBounds.Min.y }, v2{ SliderX + 1, TimelineBounds.Max.y } }; @@ -531,7 +532,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta ui_OutlineRect(Interface, TimelineFrameBarBounds, 1.f, RedV4); ui_OutlineRect(Interface, TimelineBlockDisplayBounds, 1.f, RedV4); - if (MouseDownAndNotHandled && gs_PointIsInRect(Interface->Mouse.Pos, TimelineBounds)) + if (MouseDownAndNotHandled && PointIsInRect(TimelineBounds, Interface->Mouse.Pos)) { DeselectCurrentAnimationBlock(State); } @@ -554,13 +555,13 @@ animation_clip GlobalAnimationClips[] = { }; internal void -DrawAnimationClipsList(rect PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayer, animation_system* AnimationSystem) +DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayer, animation_system* AnimationSystem) { ui_layout Layout = ui_CreateLayout(*Interface, PanelBounds); for (s32 i = 0; i < GlobalAnimationClipsCount; i++) { animation_clip Clip = GlobalAnimationClips[i]; - string ClipName = MakeString(Clip.Name, Clip.NameLength); + gs_string ClipName = MakeString(Clip.Name, Clip.NameLength); if (ui_LayoutListEntry(Interface, &Layout, ClipName, i)) { AddAnimationBlockAtCurrentTime(i + 1, SelectedAnimationLayer, AnimationSystem); @@ -572,7 +573,7 @@ DrawAnimationClipsList(rect PanelBounds, ui_interface* Interface, u32 SelectedAn GSMetaTag(panel_render); GSMetaTag(panel_type_animation_timeline); internal void -AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +AnimationTimeline_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { animation_timeline_state* TimelineState = (animation_timeline_state*)Panel.PanelStateMemory; gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; @@ -580,24 +581,24 @@ AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* R ui_interface* Interface = &State->Interface; animation_system* AnimationSystem = &State->AnimationSystem; - rect TitleBarBounds, PanelContentsBounds; - gs_HSplitRectAtDistanceFromTop(PanelBounds, Interface->Style.RowHeight, &TitleBarBounds, &PanelContentsBounds); - rect AnimationListBounds, TimelineBounds; - gs_VSplitRectAtDistanceFromLeft(PanelContentsBounds, 300, &AnimationListBounds, &TimelineBounds); + rect2 TitleBarBounds, PanelContentsBounds; + RectHSplitAtDistanceFromTop(PanelBounds, Interface->Style.RowHeight, &TitleBarBounds, &PanelContentsBounds); + rect2 AnimationListBounds, TimelineBounds; + RectVSplitAtDistanceFromLeft(PanelContentsBounds, 300, &AnimationListBounds, &TimelineBounds); ui_FillRect(Interface, TitleBarBounds, Interface->Style.PanelBGColors[0]); ui_layout TitleBarLayout = ui_CreateLayout(*Interface, TitleBarBounds); ui_StartRow(&TitleBarLayout, 3); { - if (ui_LayoutButton(Interface, &TitleBarLayout, MakeStringLiteral("Pause"))) + if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Pause"))) { State->AnimationSystem.TimelineShouldAdvance = true; } - if (ui_LayoutButton(Interface, &TitleBarLayout, MakeStringLiteral("Play"))) + if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Play"))) { State->AnimationSystem.TimelineShouldAdvance = false; } - if (ui_LayoutButton(Interface, &TitleBarLayout, MakeStringLiteral("Stop"))) + if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Stop"))) { State->AnimationSystem.TimelineShouldAdvance = false; State->AnimationSystem.CurrentFrame = 0; @@ -605,7 +606,7 @@ AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* R } ui_EndRow(&TitleBarLayout); - if (gs_Height(TimelineBounds) > 0) + if (Rect2Height(TimelineBounds) > 0) { SelectedBlockHandle = DrawAnimationTimeline(AnimationSystem, TimelineState, TimelineBounds, SelectedBlockHandle, Interface, State); DrawAnimationClipsList(AnimationListBounds, Interface, State->SelectedAnimationLayer, &State->AnimationSystem); diff --git a/src/app/panels/foldhaus_panel_dmx_view.h b/src/app/panels/foldhaus_panel_dmx_view.h index 8d5acce..56d0352 100644 --- a/src/app/panels/foldhaus_panel_dmx_view.h +++ b/src/app/panels/foldhaus_panel_dmx_view.h @@ -74,7 +74,7 @@ DrawSACNUniversePixels (render_command_buffer* RenderBuffer, sacn_universe* ToDr GSMetaTag(panel_render); GSMetaTag(panel_type_dmx_view); internal void -DMXView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +DMXView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { #if 0 // :NoLongerFunctionalSACNCodeButThatsOk @@ -82,7 +82,7 @@ DMXView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffe universe_view_operation_state* OpState = (universe_view_operation_state*)Operation.OpStateMemory; - string TitleBarString = InitializeEmptyString(PushArray(State->Transient, char, 64), 64); + gs_string TitleBargs_string = InitializeEmptygs_string(PushArray(State->Transient, char, 64), 64); v2 DisplayArea_Dimension = v2{600, 600}; @@ -120,8 +120,8 @@ DMXView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffe if (OpState->Zoom > .5f) { v2 TitleDisplayStart = UniverseDisplayTopLeft + v2{0, 12}; - PrintF(&TitleBarString, "Universe %d", Universe->Universe); - DrawString(RenderBuffer, TitleBarString, State->Interface.Font, + PrintF(&TitleBargs_string, "Universe %d", Universe->Universe); + DrawString(RenderBuffer, TitleBargs_string, State->Interface.Font, TitleDisplayStart, WhiteV4); } diff --git a/src/app/panels/foldhaus_panel_file_view.h b/src/app/panels/foldhaus_panel_file_view.h index bfcd34e..2fd2953 100644 --- a/src/app/panels/foldhaus_panel_file_view.h +++ b/src/app/panels/foldhaus_panel_file_view.h @@ -7,7 +7,7 @@ struct file_view_state { - string WorkingDirectory; + gs_string WorkingDirectory; }; input_command* FileView_Commands = 0; @@ -36,18 +36,18 @@ FileView_Cleanup(panel* Panel, app_state* State) GSMetaTag(panel_render); GSMetaTag(panel_type_file_view); internal void -FileView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +FileView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - rect HeaderBounds = {0}; + rect2 HeaderBounds = {0}; HeaderBounds.Min = {PanelBounds.Min.x, PanelBounds.Max.y - 32}; HeaderBounds.Max = PanelBounds.Max; - rect ListBounds = {0}; + rect2 ListBounds = {0}; ListBounds.Min = PanelBounds.Min; - ListBounds.Max = gs_BottomRight(HeaderBounds); + ListBounds.Max = RectBottomRight(HeaderBounds); - PushRenderQuad2D(RenderBuffer, gs_RectExpand(HeaderBounds), PinkV4); - PushRenderQuad2D(RenderBuffer, gs_RectExpand(ListBounds), RedV4); + PushRenderQuad2D(RenderBuffer, HeaderBounds.Min, HeaderBounds.Max, PinkV4); + PushRenderQuad2D(RenderBuffer, ListBounds.Min, ListBounds.Max, RedV4); } diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index 043caa0..5d0cca7 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -27,13 +27,13 @@ HierarchyView_Cleanup(panel* Panel, app_state* State) GSMetaTag(panel_render); GSMetaTag(panel_type_hierarchy); internal void -HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +HierarchyView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); - string TempString = PushString(&State->Transient, 256); - u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1; - u32 AssembliesToDraw = GSMin(LineCount, State->Assemblies.Count); - rect* LineBounds = PushArray(&State->Transient, rect, LineCount); + gs_string Tempgs_string = PushString(&State->Transient, 256); + u32 LineCount = (u32)(Rect2Height(PanelBounds) / Layout.RowHeight) + 1; + u32 AssembliesToDraw = Min(LineCount, State->Assemblies.Count); + rect2* LineBounds = PushArray(&State->Transient, rect2, LineCount); // Fill in alternating color rows for the backgrounds for (u32 Line = 0; Line < LineCount; Line++) @@ -46,13 +46,13 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende for (u32 AssemblyIndex = 0; AssemblyIndex < AssembliesToDraw; AssemblyIndex++) { assembly Assembly = State->Assemblies.Values[AssemblyIndex]; - PrintF(&TempString, "%S", Assembly.Name); + PrintF(&Tempgs_string, "%S", Assembly.Name); ui_layout ItemLayout = ui_CreateLayout(State->Interface, LineBounds[AssemblyIndex]); ui_StartRow(&ItemLayout, 2); { - ui_LayoutDrawString(&State->Interface, &ItemLayout, TempString, State->Interface.Style.TextColor); - if (ui_LayoutListButton(&State->Interface, &ItemLayout, MakeStringLiteral("X"), AssemblyIndex)) + ui_LayoutDrawString(&State->Interface, &ItemLayout, Tempgs_string, State->Interface.Style.TextColor); + if (ui_LayoutListButton(&State->Interface, &ItemLayout, MakeString("X"), AssemblyIndex)) { UnloadAssembly(AssemblyIndex, State, Context); } @@ -63,15 +63,22 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende if (AssembliesToDraw < LineCount) { // NOTE(Peter): Add assembly button - PrintF(&TempString, "+ Add Assembly"); - if (ui_ListButton(&State->Interface, TempString, LineBounds[AssembliesToDraw], AssembliesToDraw)) + PrintF(&Tempgs_string, "+ Add Assembly"); + if (ui_ListButton(&State->Interface, Tempgs_string, LineBounds[AssembliesToDraw], AssembliesToDraw)) { - string FilePath = PushString(&State->Transient, 256); + gs_string FilePath = PushString(&State->Transient, 256); + + // TODO(Peter): Took out file opening temporarily while I get things back up and running. + // Ideally we can just write our own file lister using the new filehandler so that + // execution doesn't suspend while we try and open a file + InvalidCodePath; +#if 0 b32 Success = GetFilePath(Context, &FilePath, "Foldhaus Files\0*.fold\0\0"); if (Success) { - LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, FilePath, State->GlobalLog); + LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, FilePath.ConstString, State->GlobalLog); } +#endif } } } diff --git a/src/app/panels/foldhaus_panel_profiler.h b/src/app/panels/foldhaus_panel_profiler.h index 75c010a..bc18748 100644 --- a/src/app/panels/foldhaus_panel_profiler.h +++ b/src/app/panels/foldhaus_panel_profiler.h @@ -25,7 +25,7 @@ ProfilerView_Cleanup(panel* Panel, app_state* State) } internal void -RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, memory_arena* Memory) +RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, gs_memory_arena* Memory) { v4 ThreadColors[] = { v4{.73f, .33f, .83f, 1}, @@ -35,8 +35,8 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, deb v4{.74f, .40f, .25f, 1}, }; - rect Bounds = ui_LayoutRemaining(Layout); - r32 Width = gs_Width(Bounds); + rect2 Bounds = ui_LayoutRemaining(Layout); + r32 Width = Rect2Width(Bounds); r32 DepthHeight = 64; s64 FrameStartCycles = VisibleFrame->FrameStartCycles; @@ -48,7 +48,8 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, deb scope_record* HotRecord = 0; scope_name* HotRecordName = 0; - MakeStringBuffer(String, 256); + char Backbuffer[256]; + gs_string String = MakeString(Backbuffer, 0, 256); for (s32 i = 0; i < ThreadScopeCalls->Count; i++) { scope_record* Record = ThreadScopeCalls->Calls + i; @@ -59,14 +60,14 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, deb r32 PixelStart = Bounds.Min.x + (Width * PercentStart); r32 PixelEnd = Bounds.Min.x + (Width * PercentEnd); r32 MinY = Bounds.Max.y - ((Record->CallDepth + 1) * DepthHeight); - rect ScopeBounds = { + rect2 ScopeBounds = { v2{ PixelStart, MinY }, v2{ PixelEnd, MinY + (DepthHeight - 4) } }; - if (gs_Width(ScopeBounds) >= 1) + if (Rect2Width(ScopeBounds) >= 1) { v4 Color = ThreadColors[0]; - if (gs_PointIsInRect(Interface->Mouse.Pos, ScopeBounds)) + if (PointIsInRect(ScopeBounds, Interface->Mouse.Pos)) { Color = GreenV4; HotRecord = Record; @@ -81,23 +82,26 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, deb if (HotRecord != 0) { PrintF(&String, "%S : %d - %d", HotRecordName->Name, HotRecord->StartCycles, HotRecord->EndCycles); - ui_TextBox(Interface, gs_MakeRectMinWidth(Interface->Mouse.Pos, v2{256, 32}), String, BlackV4, WhiteV4); + + rect2 TextBounds = MakeRect2MinDim(Interface->Mouse.Pos, v2{256, 32}); + ui_TextBox(Interface, TextBounds, String, BlackV4, WhiteV4); } } internal void -RenderProfiler_ListVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, memory_arena* Memory) +RenderProfiler_ListVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, gs_memory_arena* Memory) { - MakeStringBuffer(String, 256); + char Backbuffer[256]; + gs_string String = MakeString(Backbuffer, 0, 256); r32 ColumnWidths[] = {256, 128, 128, 128, 128}; ui_StartRow(&Layout, 5, &ColumnWidths[0]); { - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Procedure"), Interface->Style.TextColor); - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("% Frame"), Interface->Style.TextColor); - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Seconds"), Interface->Style.TextColor); - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Cycles"), Interface->Style.TextColor); - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Calls"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("Procedure"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("% Frame"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("Seconds"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("Cycles"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("Calls"), Interface->Style.TextColor); } ui_EndRow(&Layout); @@ -133,40 +137,43 @@ RenderProfiler_ListVisualization(ui_interface* Interface, ui_layout Layout, debu GSMetaTag(panel_render); GSMetaTag(panel_type_profiler); internal void -ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +ProfilerView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - memory_arena* Memory = &State->Transient; - string String = InitializeEmptyString(PushArray(Memory, char, 256), 256); + gs_memory_arena* Memory = &State->Transient; + gs_string String = PushString(Memory, 256); v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 }; r32 FrameListHeight = 64; - rect FrameListBounds, ProcListBounds; - gs_HSplitRectAtDistanceFromTop(PanelBounds, FrameListHeight, &FrameListBounds, &ProcListBounds); - rect FrameListInner = gs_InsetRect(FrameListBounds, 4); + rect2 FrameListBounds, ProcListBounds; + RectHSplitAtDistanceFromTop(PanelBounds, FrameListHeight, &FrameListBounds, &ProcListBounds); + rect2 FrameListInner = RectInset(FrameListBounds, 4); - r32 SingleFrameStep = gs_Width(FrameListInner) / DEBUG_FRAME_COUNT; + r32 SingleFrameStep = Rect2Width(FrameListInner) / DEBUG_FRAME_COUNT; r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2); ui_OutlineRect(&State->Interface, FrameListBounds, 2, WhiteV4); - if (gs_PointIsInRect(Context.Mouse.Pos, FrameListBounds) && MouseButtonHeldDown(Context.Mouse.LeftButtonState)) + if (MouseButtonHeldDown(Context.Mouse.LeftButtonState)) { - v2 LocalMouse = gs_TransformPointIntoRectSpace(Context.Mouse.Pos, FrameListBounds); - s32 ClosestFrameIndex = (LocalMouse.x / SingleFrameStep); - if (ClosestFrameIndex >= 0 && ClosestFrameIndex < DEBUG_FRAME_COUNT) + if (PointIsInRect(FrameListBounds, Context.Mouse.Pos)) { - GlobalDebugServices->RecordFrames = false; - GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex; + v2 LocalMouse = Rect2GetRectLocalPoint(FrameListBounds, Context.Mouse.Pos); + s32 ClosestFrameIndex = (LocalMouse.x / SingleFrameStep); + if (ClosestFrameIndex >= 0 && ClosestFrameIndex < DEBUG_FRAME_COUNT) + { + GlobalDebugServices->RecordFrames = false; + GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex; + } } } - rect FrameBounds = gs_MakeRectMinWidth(FrameListInner.Min, v2{SingleFrameWidth, gs_Height(FrameListInner)}); + rect2 FrameBounds = MakeRect2MinDim(FrameListInner.Min, v2{SingleFrameWidth, Rect2Height(FrameListInner)}); for (s32 F = 0; F < DEBUG_FRAME_COUNT; F++) { - rect PositionedFrameBounds = gs_TranslateRectX(FrameBounds, F * SingleFrameStep); + rect2 PositionedFrameBounds = Rect2TranslateX(FrameBounds, F * SingleFrameStep); s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F); if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; } - v4 Color = FrameColors[GSClamp(0, FramesAgo, 3)]; + v4 Color = FrameColors[Clamp(0, FramesAgo, 3)]; ui_FillRect(&State->Interface, PositionedFrameBounds, Color); } diff --git a/src/app/panels/foldhaus_panel_sculpture_view.h b/src/app/panels/foldhaus_panel_sculpture_view.h index 304fff6..b9a31af 100644 --- a/src/app/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/panels/foldhaus_panel_sculpture_view.h @@ -18,11 +18,11 @@ OPERATION_RENDER_PROC(Update3DViewMouseRotate) v2 TotalDeltaPos = Mouse.Pos - Mouse.DownPos; - m44 XRotation = GetXRotation(-TotalDeltaPos.y * State->PixelsToWorldScale); - m44 YRotation = GetYRotation(TotalDeltaPos.x * State->PixelsToWorldScale); + m44 XRotation = M44RotationX(-TotalDeltaPos.y * State->PixelsToWorldScale); + m44 YRotation = M44RotationY(TotalDeltaPos.x * State->PixelsToWorldScale); m44 Combined = XRotation * YRotation; - State->Camera.Position = V3(Combined * OpState->CameraStartPos); + State->Camera.Position = (Combined * OpState->CameraStartPos).xyz; } FOLDHAUS_INPUT_COMMAND_PROC(End3DViewMouseRotate) @@ -40,17 +40,17 @@ FOLDHAUS_INPUT_COMMAND_PROC(Begin3DViewMouseRotate) mouse_rotate_view_operation_state* OpState = CreateOperationState(RotateViewMode, &State->Modes, mouse_rotate_view_operation_state); - OpState->CameraStartPos = V4(State->Camera.Position, 1); + OpState->CameraStartPos = ToV4Point(State->Camera.Position); } // ---------------- GSMetaTag(panel_commands); GSMetaTag(panel_type_sculpture_view); -global_variable input_command SculptureView_Commands[] = { +global input_command SculptureView_Commands[] = { { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, Begin3DViewMouseRotate }, }; -global_variable s32 SculptureView_CommandsCount = 1; +global s32 SculptureView_CommandsCount = 1; GSMetaTag(panel_init); GSMetaTag(panel_type_sculpture_view); @@ -76,23 +76,26 @@ struct draw_leds_job_data s32 StartIndex; s32 OnePastLastIndex; render_quad_batch_constructor* Batch; - m44 ModelViewMatrix; + quad_batch_constructor_reserved_range BatchReservedRange; r32 LEDHalfWidth; }; internal void -DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) +DrawLEDsInBufferRangeJob (gs_thread_context Context, gs_data JobData) { DEBUG_TRACK_FUNCTION; - draw_leds_job_data* Data = (draw_leds_job_data*)JobData; + draw_leds_job_data* Data = (draw_leds_job_data*)JobData.Memory; s32 LEDCount = Data->OnePastLastIndex - Data->StartIndex; +#if 0 // TODO(Peter): Why are we doing this here? Shouldn't we be able to tell what the range // needs to be at the time of creation? That way its all on one thread and we're not // worried about locking up. quad_batch_constructor_reserved_range BatchReservedRange = ThreadSafeReserveRangeInQuadConstructor(Data->Batch, LEDCount * 2); +#endif + s32 TrisUsed = 0; r32 HalfWidth = Data->LEDHalfWidth; @@ -113,77 +116,101 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f}; v4 Position = Data->LedBuffer.Positions[LedIndex]; - m44 FaceCameraMatrix = GetLookAtMatrix(Position, Data->CameraPosition); - v4 PositionOffset = V4(Position.xyz, 0); // Ensure PositionOffset is a vector, not a point + m44 FaceCameraMatrix = M44LookAt(Position, Data->CameraPosition); + v4 PositionOffset = ToV4Vec(Position.xyz); v4 P0 = (FaceCameraMatrix * P0_In) + PositionOffset; v4 P1 = (FaceCameraMatrix * P1_In) + PositionOffset; v4 P2 = (FaceCameraMatrix * P2_In) + PositionOffset; v4 P3 = (FaceCameraMatrix * P3_In) + PositionOffset; - SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, + SetTri3DInBatch(Data->Batch, Data->BatchReservedRange.Start + TrisUsed++, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); - SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, + SetTri3DInBatch(Data->Batch, Data->BatchReservedRange.Start + TrisUsed++, P0, P2, P3, UV0, UV2, UV3, Color, Color, Color); } } +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); +} + GSMetaTag(panel_render); GSMetaTag(panel_type_sculpture_view); internal void -SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { DEBUG_TRACK_SCOPE(RenderSculpture); - r32 PanelWidth = PanelBounds.Max.x - PanelBounds.Min.x; - r32 PanelHeight = PanelBounds.Max.y - PanelBounds.Min.y; - State->Camera.AspectRatio = PanelWidth / PanelHeight; + // TODO(Peter): @MajorFix + // NOTE(Peter): Just returning from this function to make sure that this isn't a problem as I go and try to fix + // the other panels + return; - m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera); - m44 ProjectionMatrix = GetCameraPerspectiveProjectionMatrix(State->Camera); - r32 LEDHalfWidth = .5f; + State->Camera.AspectRatio = RectAspectRatio(PanelBounds); - PushRenderPerspective(RenderBuffer, PanelBounds.Min.x, PanelBounds.Min.y, PanelWidth, PanelHeight, State->Camera); - - m44 FaceCameraMatrix = GetLookAtMatrix(v4{0, 0, 0, 1}, V4(State->Camera.Position, 1)); + PushRenderPerspective(RenderBuffer, PanelBounds, State->Camera); u32 MaxLEDsPerJob = 2048; render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal); u32 FocusPixel = 256; - for (u32 i = 0; i < State->Assemblies.Count; i++) + for (u32 BufferIndex = 0; BufferIndex < State->LedSystem.BuffersCount; BufferIndex++) { - assembly Assembly = State->Assemblies.Values[i]; - led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex); - u32 JobsNeeded = IntegerDivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); - - // TODO(Peter): TEMPORARY - identify this pixel - LedBuffer->Colors[FocusPixel] = pixel{ 255, 0, 255 }; + led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, BufferIndex); + u32 JobsNeeded = U32DivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); +#if 1 + u32 NextLEDIndex = 0; for (u32 Job = 0; Job < JobsNeeded; Job++) { - draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data); + 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 = Job * MaxLEDsPerJob; - JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); + JobData->StartIndex = NextLEDIndex; + JobData->OnePastLastIndex = Min(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); + s32 JobLedCount = JobData->OnePastLastIndex - JobData->StartIndex; JobData->Batch = &RenderLEDsBatch; - JobData->ModelViewMatrix = ModelViewMatrix; - JobData->LEDHalfWidth = LEDHalfWidth; + JobData->BatchReservedRange = ReserveRangeInQuadConstructor(JobData->Batch, JobLedCount * 2); + JobData->LEDHalfWidth = .5f; - JobData->CameraPosition = V4(State->Camera.Position, 1); + JobData->CameraPosition = ToV4Point(State->Camera.Position); - Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, DrawLEDsInBufferRangeJob, JobData, "Sculpture Draw LEDS"); + Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, (thread_proc*)DrawLEDsInBufferRangeJob, Data, ConstString("Sculpture Draw LEDS")); + + NextLEDIndex = JobData->OnePastLastIndex; } +#else + 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 = 0; + JobData->OnePastLastIndex = LedBuffer->LedCount; + s32 JobLedCount = JobData->OnePastLastIndex - JobData->StartIndex; + JobData->Batch = &RenderLEDsBatch; + JobData->BatchReservedRange = ReserveRangeInQuadConstructor(JobData->Batch, JobLedCount * 2); + JobData->LEDHalfWidth = .5f; + + JobData->CameraPosition = ToV4Point(State->Camera.Position); + + Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, (thread_proc*)DrawLEDsInBufferRangeJob, Data, ConstString("Sculpture Draw LEDS")); +#endif + + u32 f = 0; } // 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.Min.x, State->WindowBounds.Min.y, - State->WindowBounds.Max.x, State->WindowBounds.Max.y); + PushRenderOrthographic(RenderBuffer, State->WindowBounds); if (State->Assemblies.Count > 0) { @@ -196,9 +223,9 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende v4 LedProjectedPosition = Matrix * LedPosition; v2 LedOnScreenPosition = LedProjectedPosition.xy; - string TempString = PushString(&State->Transient, 256); - PrintF(&TempString, "%f %f", LedOnScreenPosition.x, LedOnScreenPosition.y); - DrawString(RenderBuffer, TempString, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4); + gs_string Tempgs_string = PushString(&State->Transient, 256); + PrintF(&Tempgs_string, "%f %f", LedOnScreenPosition.x, LedOnScreenPosition.y); + DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4); v2 BoxHalfDim = v2{ 25, 25 }; v2 BoxMin = LedOnScreenPosition - BoxHalfDim; @@ -206,7 +233,7 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende PushRenderBoundingBox2D(RenderBuffer, BoxMin, BoxMax, 2.0f, TealV4); } - Context.GeneralWorkQueue->DoQueueWorkUntilDone(Context.GeneralWorkQueue, 0); + Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext); } #define FOLDHAUS_PANEL_SCULPTURE_VIEW_H diff --git a/src/app/sacn/sacn.h b/src/app/sacn/sacn.h index 47adaa2..a871cea 100644 --- a/src/app/sacn/sacn.h +++ b/src/app/sacn/sacn.h @@ -160,11 +160,11 @@ VHD_PackLength_(u8* Buffer, u32 Length, b32 IncludeLength) } internal cid -StringToCID_ (const char* String) +gs_stringToCID_ (const char* gs_string) { cid Result = {}; - const char* Src = String; + const char* Src = gs_string; u8* Dest = &Result.Bytes[0]; b32 FirstNibble = true; @@ -215,7 +215,7 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, Cursor = PackB2(Cursor, RLP_PREAMBLE_SIZE); Cursor = PackB2(Cursor, RLP_POSTAMBLE_SIZE); - GSMemCopy(ACN_IDENTIFIER, Cursor, ACN_IDENTIFIER_SIZE); + CopyMemoryTo(ACN_IDENTIFIER, Cursor, ACN_IDENTIFIER_SIZE); Cursor += ACN_IDENTIFIER_SIZE; // TODO(Peter): If you never use this anywhere else, go back and remove the parameters @@ -243,7 +243,7 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, // framing source name // :Check - GSMemCopy(SourceName, (char*)Cursor, SOURCE_NAME_SIZE); + CopyMemoryTo(SourceName, (char*)Cursor, SOURCE_NAME_SIZE); Cursor[SOURCE_NAME_SIZE - 1] = '\0'; Cursor += SOURCE_NAME_SIZE; @@ -298,7 +298,7 @@ InitializeSACN (context Context) s32 Multicast_TimeToLive = 20; SACN.SendSocket = Context.PlatformGetSocketHandle(Multicast_TimeToLive); - SACN.CID = StringToCID_ ("{67F9D986-544E-4abb-8986-D5F79382586C}"); + SACN.CID = gs_stringToCID_ ("{67F9D986-544E-4abb-8986-D5F79382586C}"); return SACN; } diff --git a/src/app/test_patterns.h b/src/app/test_patterns.h index 51da616..6d4d0c6 100644 --- a/src/app/test_patterns.h +++ b/src/app/test_patterns.h @@ -18,9 +18,9 @@ struct solid_color_data GSMetaTag(node_proc); // :TagParamsForNodeParamStructs void SolidColorProc(solid_color_data* Data) { - u8 R = (u8)GSClamp(0.f, (Data->Color.r * 255), 255.f); - u8 G = (u8)GSClamp(0.f, (Data->Color.g * 255), 255.f); - u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f); + u8 R = (u8)Clamp(0.f, (Data->Color.r * 255), 255.f); + u8 G = (u8)Clamp(0.f, (Data->Color.g * 255), 255.f); + u8 B = (u8)Clamp(0.f, (Data->Color.b * 255), 255.f); for (s32 LedIndex = 0; LedIndex < Data->Result.LEDCount; LedIndex++) { @@ -64,7 +64,7 @@ void VerticalColorFadeProc(vertical_color_fade_data* Data) v4 LedPosition = Data->Result.LedPositions[LedIndex]; r32 Amount = (LedPosition.y - Data->Min) / Range; - Amount = GSClamp01(1.0f - Amount); + Amount = Clamp01(1.0f - Amount); Data->Result.Colors[LedIndex].R = (u8)(R * Amount); Data->Result.Colors[LedIndex].G = (u8)(G * Amount); @@ -107,14 +107,14 @@ void RevolvingDiscs(revolving_discs_data* Data) DEBUG_TRACK_FUNCTION; pixel Color = { - (u8)(GSClamp01(Data->Color.r) * 255), - (u8)(GSClamp01(Data->Color.g) * 255), - (u8)(GSClamp01(Data->Color.b) * 255), + (u8)(Clamp01(Data->Color.r) * 255), + (u8)(Clamp01(Data->Color.g) * 255), + (u8)(Clamp01(Data->Color.b) * 255), }; v4 Center = v4{0, 0, 0, 1}; - v4 Normal = v4{GSCos(Data->ThetaZ), 0, GSSin(Data->ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 - v4 Right = Cross(Normal, v4{0, 1, 0, 0}); + v4 Normal = v4{CosR32(Data->ThetaZ), 0, SinR32(Data->ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 + v4 Right = V4Cross(Normal, v4{0, 1, 0, 0}); v4 FrontCenter = Center + (Normal * Data->DiscWidth); v4 BackCenter = Center - (Normal * Data->DiscWidth); @@ -129,13 +129,13 @@ void RevolvingDiscs(revolving_discs_data* Data) v4 ToFront = Position + FrontCenter; v4 ToBack = Position + BackCenter; - r32 ToFrontDotNormal = Dot(ToFront, Normal); - r32 ToBackDotNormal = Dot(ToBack, Normal); + r32 ToFrontDotNormal = V4Dot(ToFront, Normal); + r32 ToBackDotNormal = V4Dot(ToBack, Normal); - ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000); - ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000); + ToFrontDotNormal = Clamp01(ToFrontDotNormal * 1000); + ToBackDotNormal = Clamp01(ToBackDotNormal * 1000); - r32 SqDistToCenter = MagSqr(Position); + r32 SqDistToCenter = V4MagSquared(Position); if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared) { if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) diff --git a/src/app/win32_foldhaus.cpp b/src/app/win32_foldhaus.cpp index 88ff2d9..65df438 100644 --- a/src/app/win32_foldhaus.cpp +++ b/src/app/win32_foldhaus.cpp @@ -16,14 +16,13 @@ #include "../gs_libs/gs_win32.cpp" #include "win32_foldhaus_memory.h" -#include "win32_foldhaus_fileio.h" #include "win32_foldhaus_dll.h" #include "win32_foldhaus_timing.h" #include "foldhaus_renderer.cpp" -global_variable b32 Running = false; -global_variable b32 WindowIsActive = false; +global b32 Running = false; +global b32 WindowIsActive = false; char DLLName[] = "foldhaus.dll"; char WorkingDLLName[] = "foldhaus_temp.dll"; @@ -31,6 +30,317 @@ char DLLLockFileName[] = "lock.tmp"; window MainWindow; +// Utils + +internal gs_string +Win32DumpErrorAndPrepareMessageBoxString(gs_memory_arena* Arena, char* Format, ...) +{ + s32 Error = GetLastError(); + gs_string ErrorDump = PushString(Arena, 4096); + PrintF(&ErrorDump, + R"FOO(Win32 Error: %s\n +Error Code: %d\n + )FOO", + __FUNCTION__, + Error); + + va_list Args; + va_start(Args, Format); + PrintFArgsList(&ErrorDump, Format, Args); + va_end(Args); + + gs_data ErrorDumpData = StringToData(ErrorDump); + + HANDLE FileHandle = CreateFileA("./crashdump.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD BytesWritten = 0; + if (WriteFile(FileHandle, ErrorDumpData.Memory, ErrorDumpData.Size, &BytesWritten, NULL)) + { + + } + CloseHandle(FileHandle); + } + + AppendPrintF(&ErrorDump, "Program will attempt to continue. See crashdump.txt for info"); + NullTerminate(&ErrorDump); + + return ErrorDump; +} + +DEBUG_PRINT(Win32DebugPrint) +{ + Assert(IsNullTerminated(Message)); + OutputDebugStringA(Message.Str); +} + +#define PrintLastError() PrintLastError_(__FILE__, __LINE__) +internal void +PrintLastError_(char* File, u32 Line) +{ + char DebugStringData[256]; + gs_string DebugString = MakeString(DebugStringData, 0, 256); + u32 Error = GetLastError(); + PrintF(&DebugString, "%s Line %d: Win32 Error %d\n\0", File, Line, Error); + OutputDebugStringA(DebugString.Str); +} + + +internal HINSTANCE +GetHInstance() +{ + HINSTANCE Result = GetModuleHandle(NULL); + if (Result == NULL) + { + PrintLastError(); + } + return Result; +} + +/////////////////////// +// +// Fie I/O + +internal u64 +Win32HighLowToU64(u32 LowPart, u32 HighPart) +{ + ULARGE_INTEGER Time = {}; + Time.LowPart = LowPart; + Time.HighPart = HighPart; + u64 Result = Time.QuadPart; + return Result; +} + +internal u64 +Win32FileTimeToU64(FILETIME FileTime) +{ + u64 Result = Win32HighLowToU64(FileTime.dwLowDateTime, FileTime.dwHighDateTime); + return Result; +} + +GET_FILE_INFO(Win32GetFileInfo) +{ + Assert(IsNullTerminated(Path)); + gs_file_info Result = {}; + HANDLE FileHandle = CreateFileA(Path.Str, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + Result.Path = Path; + Result.FileSize = (u64)GetFileSize(FileHandle, NULL) + 1; + FILETIME CreationTime, LastWriteTime; + if (GetFileTime(FileHandle, &CreationTime, (LPFILETIME)0, &LastWriteTime)) + { + Result.CreationTime = Win32FileTimeToU64(CreationTime); + Result.LastWriteTime = Win32FileTimeToU64(LastWriteTime); + } + else + { + PrintLastError(); + } + CloseHandle(FileHandle); + } + return Result; +} + +READ_ENTIRE_FILE(Win32ReadEntireFile) +{ + Assert(DataIsNonEmpty(Memory)); + Assert(IsNullTerminated(Path)); + + gs_file Result = {0}; + u32 Error = 0; + Result.FileInfo.Path = Path; + + HANDLE FileHandle = CreateFileA(Path.Str, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD BytesRead = 0; + if (ReadFile(FileHandle, (LPVOID)Memory.Memory, Memory.Size - 1, (LPDWORD)(&BytesRead), NULL)) + { + Memory.Memory[Memory.Size - 1] = 0; + Result.Data = Memory; + + gs_string AbsolutePath = PushString(FileHandler.Transient, 512); + AbsolutePath.Length = GetFullPathNameA(Path.Str, AbsolutePath.Size, AbsolutePath.Str, NULL); + if (AbsolutePath.Length == 0) + { + Error = GetLastError(); + InvalidCodePath; + } + Result.FileInfo.AbsolutePath = AbsolutePath.ConstString; + } + else + { + // NOTE(Peter): If we get to this error case, it means that the file exists, + // and was successfully opened, but we can't read from it. I'm choosing to + // treat this as a legitimate error at this point. + gs_string Message = Win32DumpErrorAndPrepareMessageBoxString(FileHandler.Transient, "Attempting to read file: %S", Path); + if (MessageBox(NULL, Message.Str, "Error", MB_OK) == IDOK) + { + PostQuitMessage(-1); + } + } + CloseHandle(FileHandle); + } + else + { + + } + + return Result; +} + +WRITE_ENTIRE_FILE(Win32WriteEntireFile) +{ + Assert(DataIsNonEmpty(Data)); + Assert(IsNullTerminated(Path)); + + bool Success = false; + HANDLE FileHandle = CreateFileA(Path.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)) + { + Success = (BytesWritten == Data.Size); + } + else + { + gs_string Message = Win32DumpErrorAndPrepareMessageBoxString(FileHandler.Transient, "Attempting to write to file: %S", Path); + MessageBox(NULL, Message.Str, "Error", MB_OK); + } + CloseHandle(FileHandle); + } + else + { + + } + + return Success; +} + +internal FILETIME +GetFileLastWriteTime(char* Path) +{ + FILETIME Result = {}; + + WIN32_FIND_DATA FindData = {}; + HANDLE FileHandle = FindFirstFileA(Path, &FindData); + + if (FileHandle != INVALID_HANDLE_VALUE) + { + Result = FindData.ftLastWriteTime; + FindClose(FileHandle); + } + else + { + // TODO(Peter): :ErrorLogging + } + + return Result; +} + +struct temp_file_list_entry +{ + gs_file_info Info; + temp_file_list_entry* Next; +}; + +struct temp_file_list +{ + temp_file_list_entry* First; + temp_file_list_entry* Last; +}; + +internal u32 +Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* TempList, gs_const_string Path, gs_memory_arena* Storage, b32 Flags) +{ + u32 FilesCount = 0; + + u32 IndexOfLastSlash = FindLastFromSet(Path, "\\/"); + gs_const_string SearchPath = Substring(Path, 0, IndexOfLastSlash + 1); + + WIN32_FIND_DATA FindFileData; + HANDLE SearchHandle = FindFirstFile(Path.Str, &FindFileData); + if (SearchHandle != INVALID_HANDLE_VALUE) + { + do + { + if (HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) + { + if (HasFlag(Flags, EnumerateDirectory_Recurse)) + { + gs_const_string SubDirName = ConstString(FindFileData.cFileName); + if (!StringsEqual(SubDirName, ConstString(".")) && + !StringsEqual(SubDirName, ConstString(".."))) + { + gs_string SubDirectoryPath = PushString(FileHandler.Transient, SearchPath.Length + SubDirName.Length + 3); + PrintF(&SubDirectoryPath, "%S%S/*\0", SearchPath, SubDirName); + FilesCount += Win32EnumerateDirectoryIntoTempList(FileHandler, TempList, SubDirectoryPath.ConstString, Storage, Flags); + } + } + + if (HasFlag(Flags, EnumerateDirectory_IncludeDirectories)) + { + FilesCount += 1; + } + } + else + { + temp_file_list_entry* File = PushStruct(FileHandler.Transient, temp_file_list_entry); + File->Info.FileSize = Win32HighLowToU64(FindFileData.nFileSizeLow, FindFileData.nFileSizeHigh); + File->Info.CreationTime = Win32FileTimeToU64(FindFileData.ftCreationTime); + File->Info.LastWriteTime = Win32FileTimeToU64(FindFileData.ftLastWriteTime); + File->Next = 0; + + u32 FileNameLength = CharArrayLength(FindFileData.cFileName); + + // NOTE(Peter): String Storage + // Storing the string in the final storage means we don't have to copy the string later, and all + // strings will be continguous in memory at the calling site, though they will be before the array + gs_string FileName = PushString(Storage, SearchPath.Length + FileNameLength + 1); + PrintF(&FileName, "%S%.*s", SearchPath, FileName.Size, FindFileData.cFileName); + NullTerminate(&FileName); + File->Info.Path = FileName.ConstString; + + SLLPushOrInit(TempList->First, TempList->Last, File); + FilesCount += 1; + } + }while(FindNextFile(SearchHandle, &FindFileData)); + } + else + { + PrintLastError(); + } + + return FilesCount; +} + +ENUMERATE_DIRECTORY(Win32EnumerateDirectory) +{ + Assert(IsNullTerminated(Path)); + gs_file_info_array Result = {}; + + temp_file_list TempList = {}; + Result.MaxCount = Win32EnumerateDirectoryIntoTempList(FileHandler, &TempList, Path, Storage, Flags); + + Result.Values = PushArray(Storage, gs_file_info, Result.MaxCount); + for (temp_file_list_entry* FileAt = TempList.First; + FileAt != 0; + FileAt = FileAt->Next) + { + // NOTE(Peter): We don't copy the file name here because its already in Storage. + // See String Storage note above ^^ + Result.Values[Result.Count++] = FileAt->Info; + } + + return Result; +} + +/////////////////////// +// +// Job System + struct worker_thread_entry { b32 IsValid; @@ -39,11 +349,42 @@ struct worker_thread_entry struct worker_thread_info { - s32 ID; + gs_thread_context ThreadContext; HANDLE Handle; - work_queue* Queue; + gs_work_queue* Queue; }; +internal s32 +Win32GetThreadId() +{ + 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); + } + Result.FileHandler = CreateFileHandler(Win32GetFileInfo, + Win32ReadEntireFile, + Win32WriteEntireFile, + Win32EnumerateDirectory, + Result.Transient); + + return Result; +} + PUSH_WORK_ON_QUEUE(Win32PushWorkOnQueue) { #ifdef DEBUG @@ -51,18 +392,18 @@ PUSH_WORK_ON_QUEUE(Win32PushWorkOnQueue) // overflowing the buffer if (Queue->JobsCount >= Queue->JobsMax) { - string DebugString = MakeString((char*)malloc(256), 256); + gs_string DebugString = MakeString((char*)malloc(256), 256); for (u32 i = 0; i < Queue->JobsCount; i++) { PrintF(&DebugString, "%d %s\n", i, Queue->Jobs[i].JobName); NullTerminate(&DebugString); - OutputDebugStringA(DebugString.Memory); + OutputDebugStringA(DebugString.Str); } } #endif Assert(Queue->JobsCount < Queue->JobsMax); - worker_thread_job* Job = Queue->Jobs + Queue->JobsCount; + gs_threaded_job* Job = Queue->Jobs + Queue->JobsCount; Job->WorkProc = WorkProc; Job->Data = Data; #ifdef DEBUG @@ -78,7 +419,7 @@ PUSH_WORK_ON_QUEUE(Win32PushWorkOnQueue) } internal worker_thread_entry -CompleteAndTakeNextJob(work_queue* Queue, worker_thread_entry Completed) +CompleteAndTakeNextJob(gs_work_queue* Queue, worker_thread_entry Completed, gs_thread_context Context) { if (Completed.IsValid) { @@ -106,16 +447,16 @@ CompleteAndTakeNextJob(work_queue* Queue, worker_thread_entry Completed) return Result; } -DO_QUEUE_WORK_UNTIL_DONE(Win32DoQueueWorkUntilDone) +COMPLETE_QUEUE_WORK(Win32DoQueueWorkUntilDone) { worker_thread_entry Entry = {}; Entry.IsValid = false; while (Queue->JobsCompleted < Queue->JobsCount) { - Entry = CompleteAndTakeNextJob(Queue, Entry); + Entry = CompleteAndTakeNextJob(Queue, Entry, Context); if (Entry.IsValid) { - Queue->Jobs[Entry.Index].WorkProc(ThreadID, Queue->Jobs[Entry.Index].Data); + Queue->Jobs[Entry.Index].WorkProc(Context, Queue->Jobs[Entry.Index].Data); } } } @@ -124,15 +465,17 @@ 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) { - Entry = CompleteAndTakeNextJob(ThreadInfo->Queue, Entry); + ClearArena(ThreadInfo->ThreadContext.Transient); + Entry = CompleteAndTakeNextJob(ThreadInfo->Queue, Entry, ThreadInfo->ThreadContext); if (Entry.IsValid) { - ThreadInfo->Queue->Jobs[Entry.Index].WorkProc(ThreadInfo->ID, + ThreadInfo->Queue->Jobs[Entry.Index].WorkProc(ThreadInfo->ThreadContext, ThreadInfo->Queue->Jobs[Entry.Index].Data); } else @@ -188,13 +531,13 @@ PLATFORM_GET_SOCKET_HANDLE(Win32GetSocketHandle) { s32 NewDictionaryMax = Win32SocketHandleMax + SOCKET_DICTIONARY_GROW_SIZE; s32 NewDictionaryDataSize = NewDictionaryMax * sizeof(win32_socket); - u8* DictionaryMemory = Win32Alloc(NewDictionaryDataSize); + u8* DictionaryMemory = (u8*)Win32Alloc(NewDictionaryDataSize, 0); Assert(DictionaryMemory); win32_socket* NewValues = (win32_socket*)(DictionaryMemory); if (SocketValues) { - GSMemCopy(SocketValues, NewValues, sizeof(win32_socket) * NewDictionaryMax); + CopyMemoryTo(SocketValues, NewValues, sizeof(win32_socket) * NewDictionaryMax); Win32Free((u8*)SocketValues, sizeof(win32_socket) * Win32SocketHandleCount); } SocketValues = NewValues; @@ -512,7 +855,7 @@ internal void DebugPrint (char* Format, ...) { char Buffer[256]; - string StringBuffer = MakeString(Buffer, 256); + gs_string StringBuffer = MakeString(Buffer, 256); va_list Args; va_start(Args, Format); PrintF(&StringBuffer, Format, Args); @@ -521,7 +864,7 @@ DebugPrint (char* Format, ...) } internal void -SetApplicationLinks (context* Context, win32_dll_refresh DLL, work_queue* WorkQueue) +SetApplicationLinks (context* Context, win32_dll_refresh DLL, gs_work_queue* WorkQueue) { if (DLL.IsValid) { @@ -539,27 +882,22 @@ SetApplicationLinks (context* Context, win32_dll_refresh DLL, work_queue* WorkQu } } +// TODO(Peter): :Redundant remove internal u8* DEBUGAlloc(s32 ElementSize, s32 ElementCount) { - return Win32Alloc(ElementSize * ElementCount); + return (u8*)Win32Alloc(ElementSize * ElementCount, 0); } +// TODO(Peter): :Redundant remove internal u8* Win32Realloc(u8* Buf, s32 OldSize, s32 NewSize) { - u8* NewMemory = Win32Alloc(NewSize); - GSMemCopy(Buf, NewMemory, OldSize); + u8* NewMemory = (u8*)Win32Alloc(NewSize, 0); + CopyMemoryTo(Buf, NewMemory, OldSize); return NewMemory; } -internal s32 -Win32GetThreadId() -{ - s32 Result = GetCurrentThreadId(); - return Result; -} - // NOTE(Peter): Only meant to take one of the values specified below: // IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM, // IDC_ICON, IDC_NO, IDC_SIZE, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, @@ -577,6 +915,36 @@ Win32LoadSystemCursor(char* CursorIdentifier) return Result; } +internal void +PrintMatrix(m44 M, gs_thread_context Context) +{ + gs_string PrintString = AllocatorAllocString(Context.Allocator, 256); + PrintF(&PrintString, "[\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n]\n", + M.Array[0], M.Array[1], M.Array[2], M.Array[3], + M.Array[4], M.Array[5], M.Array[6], M.Array[7], + M.Array[8], M.Array[9], M.Array[10], M.Array[11], + M.Array[12], M.Array[13], M.Array[14], M.Array[15]); + NullTerminate(&PrintString); + OutputDebugStringA(PrintString.Str); +} + +v4 PerspectiveDivide(v4 A) +{ + v4 Result = {0, 0, 0, 1}; + Result.x = A.x / A.w; + Result.y = A.y / A.w; + Result.z = A.z / A.w; + Result.w = A.w; + return Result; +} +v4 ToScreen(v4 P, rect2 WindowBounds) +{ + v4 Result = P; + Result.x = RemapR32(P.x, -1, 1, WindowBounds.Min.x, WindowBounds.Max.x); + Result.y = RemapR32(P.y, -1, 1, WindowBounds.Min.y, WindowBounds.Max.y); + return Result; +} + int WINAPI WinMain ( HINSTANCE HInstance, @@ -585,6 +953,171 @@ WinMain ( INT NCmdShow ) { + gs_thread_context ThreadContext = Win32CreateThreadContext(); + + { + m44 Before = m44{ + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15 + }; + m44 After = M44Transpose(Before); + OutputDebugStringA("Before:\n"); + PrintMatrix(Before, ThreadContext); + OutputDebugStringA("\n\n"); + OutputDebugStringA("After:\n"); + PrintMatrix(After, ThreadContext); + OutputDebugStringA("\n\n"); + + } + + { + v4 Before = {1, 2, 3, 4}; + m44 Transform = {}; + for (u32 i = 0; i < 16; i++) + { + Transform.Array[i] = i + 1; + } + v4 After = Transform * Before; + Assert(V4Mag(After - v4{30, 70, 110, 150}) < .00000001f); + } + + { // Translation + v4 Before = {0, 0, 0, 1}; + m44 Translation = M44Translation(v4{5, 5, 5, 0}); + v4 After = Translation * Before; + Assert((After == v4{5, 5, 5, 1})); + } + + { // X Rotation + v4 Before = {0, 5, 0, 1}; + m44 Forward = M44RotationX(HalfPiR32); + m44 Backward = M44RotationX(-HalfPiR32); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); + } + + { // Y Rotation + v4 Before = {5, 0, 0, 1}; + m44 Forward = M44RotationY(HalfPiR32); + m44 Backward = M44RotationY(-HalfPiR32); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); + } + + { // Z Rotation + v4 Before = {0, 5, 0, 1}; + m44 Forward = M44RotationZ(HalfPiR32); + m44 Backward = M44RotationZ(-HalfPiR32); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{-5, 0, 0, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{5, 0, 0, 1}) < .000001f); + } + + { // Combined X Rotation + v4 Before = {0, 5, 0, 1}; + m44 Forward = M44Rotation(v3{HalfPiR32, 0, 0}); + m44 Backward = M44Rotation(v3{-HalfPiR32, 0, 0}); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); + } + + { // Combined Y Rotation + v4 Before = {5, 0, 0, 1}; + m44 Forward = M44Rotation(v3{0, HalfPiR32, 0}); + m44 Backward = M44Rotation(v3{0, -HalfPiR32, 0}); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); + } + + { // Combined Z Rotation + v4 Before = {0, 5, 0, 1}; + m44 Forward = M44Rotation(v3{0, 0, HalfPiR32}); + m44 Backward = M44Rotation(v3{0, 0, -HalfPiR32}); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{-5, 0, 0, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{5, 0, 0, 1}) < .000001f); + } + + { // Translate then Rotate + v4 Before = v4{0, 0, 0, 1}; + + m44 Translation = M44Translation(v4{5, 0, 0, 0}); + m44 Rotation = M44Rotation(v3{0, 0, HalfPiR32}); + m44 Composite = Rotation * Translation; + + v4 Inbetween = Translation * Before; + v4 After = Rotation * Inbetween; + Assert(V4Mag(After - v4{0, 5, 0, 1}) < .000001f); + + After = Composite * Before; + Assert(V4Mag(After - v4{0, 5, 0, 1}) < .000001f); + } + + { // Two translations + v4 Before = v4{0, 0, 0, 1}; + m44 TranslationA = M44Translation(v4{5, 0, 0, 0}); + m44 TranslationB = M44Translation(v4{0, 5, 0, 0}); + v4 After = TranslationB * TranslationA * Before; + Assert(V4Mag(After - v4{5, 5, 0, 1}) < .000001f); + } + + { // Perspective Transform + rect2 WindowBounds = rect2{ + v2{0, 0}, + v2{1440.0f, 768.0f}, + }; + + m44 Matrix = M44Translation(v4{0, 0, -200, 0}) * M44Rotation(v3{0, DegToRadR32(45), 0}); + m44 Projection = M44ProjectionPerspective(45, RectAspectRatio(WindowBounds), 0.1f, 500); + + r32 Rad = 25; + v4 P0 = Matrix * v4{-Rad, -Rad, 0, 1}; + v4 P1 = Matrix * v4{Rad, -Rad, 0, 1}; + v4 P2 = Matrix * v4{Rad, Rad, 0, 1}; + v4 P3 = Matrix * v4{-Rad, Rad, 0, 1}; + + v4 P0P = Projection * P0; + v4 P1P = Projection * P1; + v4 P2P = Projection * P2; + v4 P3P = Projection * P3; + + v4 P0PD = PerspectiveDivide(P0P); + v4 P1PD = PerspectiveDivide(P1P); + v4 P2PD = PerspectiveDivide(P2P); + v4 P3PD = PerspectiveDivide(P3P); + + v4 P0S = ToScreen(P0PD, WindowBounds); + P0S.w = 1; + + v4 P1S = ToScreen(P1PD, WindowBounds); + P1S.w = 1; + + v4 P2S = ToScreen(P2PD, WindowBounds); + P2S.w = 1; + + v4 P3S = ToScreen(P3PD, WindowBounds); + P3S.w = 1; + + Assert(V4Mag(P0S - v4{630.11401, 256.88202, 0.99930286, 1}) < 0.00001f); + Assert(V4Mag(P1S - v4{795.28662, 277.52859, 0.99948108, 1}) < 0.00001f); + Assert(V4Mag(P2S - v4{795.28662, 490.47144, 0.99948108, 1}) < 0.00001f); + Assert(V4Mag(P3S - v4{630.11401, 511.11798, 0.99930286, 1}) < 0.00001f); + + //PushRenderQuad2D(RenderBuffer, P0S.xy, P1S.xy, P2S.xy, P3S.xy, WhiteV4); + } + MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); Win32UpdateWindowDimension(&MainWindow); @@ -612,7 +1145,7 @@ WinMain ( input_queue InputQueue; { s32 InputQueueMemorySize = sizeof(input_entry) * 32; - u8* InputQueueMemory = Win32Alloc(InputQueueMemorySize); + u8* InputQueueMemory = (u8*)Win32Alloc(InputQueueMemorySize, 0); InputQueue = InitializeInputQueue(InputQueueMemory, InputQueueMemorySize); } @@ -625,31 +1158,31 @@ WinMain ( WorkerThreads = (worker_thread_info*)malloc(sizeof(worker_thread_info) * PLATFORM_THREAD_COUNT); } - work_queue WorkQueue = {}; - WorkQueue.SemaphoreHandle = CreateSemaphoreEx(0, 0, PLATFORM_THREAD_COUNT, 0, 0, SEMAPHORE_ALL_ACCESS); + HANDLE WorkQueueSemaphoreHandle = CreateSemaphoreEx(0, 0, PLATFORM_THREAD_COUNT, 0, 0, SEMAPHORE_ALL_ACCESS); + + gs_work_queue WorkQueue = {}; + WorkQueue.SemaphoreHandle = &WorkQueueSemaphoreHandle; WorkQueue.JobsMax = 512; - WorkQueue.Jobs = (worker_thread_job*)Win32Alloc(sizeof(worker_thread_job) * WorkQueue.JobsMax); + WorkQueue.Jobs = (gs_threaded_job*)Win32Alloc(sizeof(gs_threaded_job) * WorkQueue.JobsMax, 0); WorkQueue.NextJobIndex = 0; WorkQueue.PushWorkOnQueue = Win32PushWorkOnQueue; - WorkQueue.DoQueueWorkUntilDone = Win32DoQueueWorkUntilDone; + WorkQueue.CompleteQueueWork = Win32DoQueueWorkUntilDone; WorkQueue.ResetWorkQueue = ResetWorkQueue; - OutputDebugStringA("Hellooooo\n"); - for (s32 i = 0; i < PLATFORM_THREAD_COUNT; i++) { // ID = 0 is reserved for this thread - WorkerThreads[i].ID = i + 1; WorkerThreads[i].Queue = &WorkQueue; WorkerThreads[i].Handle = CreateThread(0, 0, &WorkerThreadProc, (void*)&WorkerThreads[i], 0, 0); } - s32 InitialMemorySize = Megabytes(64); - u8* InitialMemory = Win32Alloc(InitialMemorySize); + s32 InitialMemorySize = MB(64); + u8* InitialMemory = (u8*)Win32Alloc(InitialMemorySize, 0); context Context = {}; + Context.ThreadContext = ThreadContext; Context.MemorySize = InitialMemorySize; Context.MemoryBase = InitialMemory; - Context.WindowBounds = rect{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; + Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; Context.Mouse = {0}; // Cursors @@ -663,12 +1196,6 @@ WinMain ( // Platform functions Context.GeneralWorkQueue = &WorkQueue; - Context.PlatformMemory.Alloc = Win32Alloc; - Context.PlatformMemory.Free = Win32Free; - Context.PlatformMemory.Realloc = Win32Realloc; - Context.FileHandler.ReadEntireFile = Win32ReadEntireFile; - Context.FileHandler.WriteEntireFile = Win32WriteEntireFile; - Context.FileHandler.GetFilePath = Win32SystemDialogueOpenFile; Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; Context.PlatformGetSocketHandle = Win32GetSocketHandle; Context.PlatformSetSocketOption = Win32SetSocketOption; @@ -692,8 +1219,8 @@ WinMain ( WSADATA WSAData; WSAStartup(MAKEWORD(2, 2), &WSAData); - s32 RenderMemorySize = Megabytes(12); - u8* RenderMemory = Win32Alloc(RenderMemorySize); + s32 RenderMemorySize = MB(12); + u8* RenderMemory = (u8*)Win32Alloc(RenderMemorySize, 0); render_command_buffer RenderBuffer = AllocateRenderCommandBuffer(RenderMemory, RenderMemorySize, Win32Realloc); Context.InitializeApplication(Context); @@ -733,7 +1260,7 @@ WinMain ( HandleWindowMessage(Message, &MainWindow, &InputQueue, &Context.Mouse); } - Context.WindowBounds = rect{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; + Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; RenderBuffer.ViewWidth = MainWindow.Width; RenderBuffer.ViewHeight = MainWindow.Height; Context.DeltaTime = LastFrameSecondsElapsed; diff --git a/src/app/win32_foldhaus_dll.h b/src/app/win32_foldhaus_dll.h index 01b6bea..26071e6 100644 --- a/src/app/win32_foldhaus_dll.h +++ b/src/app/win32_foldhaus_dll.h @@ -22,15 +22,15 @@ struct win32_dll_refresh }; internal int -Win32DLLStringLength(char* String) +Win32DLLgs_stringLength(char* gs_string) { - char* At = String; + char* At = gs_string; while (*At) { At++; }; - return At - String; + return At - gs_string; } internal int -Win32DLLConcatStrings(int ALength, char* A, int BLength, char* B, int DestLength, char* Dest) +Win32DLLConcatgs_strings(int ALength, char* A, int BLength, char* B, int DestLength, char* Dest) { char* Dst = Dest; char* AAt = A; @@ -112,14 +112,14 @@ InitializeDLLHotReloading(char* SourceDLLName, ExePath.Path = (char*)VirtualAlloc(NULL, ExePath.PathLength, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); GetApplicationPath(&ExePath); - Win32DLLConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32DLLStringLength(SourceDLLName), SourceDLLName, + Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32DLLgs_stringLength(SourceDLLName), SourceDLLName, MAX_PATH, Result.SourceDLLPath); - Win32DLLConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32DLLStringLength(WorkingDLLFileName), WorkingDLLFileName, + Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32DLLgs_stringLength(WorkingDLLFileName), WorkingDLLFileName, MAX_PATH, Result.WorkingDLLPath); - Win32DLLConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32DLLStringLength(LockFileName), LockFileName, + Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32DLLgs_stringLength(LockFileName), LockFileName, MAX_PATH, Result.LockFilePath); Win32Free((u8*)ExePath.Path, ExePath.PathLength); diff --git a/src/app/win32_foldhaus_fileio.h b/src/app/win32_foldhaus_fileio.h index 46a109a..a45c25e 100644 --- a/src/app/win32_foldhaus_fileio.h +++ b/src/app/win32_foldhaus_fileio.h @@ -8,138 +8,5 @@ // #ifndef WIN32_FOLDHAUS_FILEIO_H -PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile) -{ - platform_memory_result Result = {}; - Result.Error = PlatformMemory_NoError; - - Assert(IsNullTerminated(Path)); - HANDLE FileHandle = CreateFileA (Path.Memory, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (FileHandle != INVALID_HANDLE_VALUE) - { - DWORD FileSize = GetFileSize(FileHandle, NULL); - Result.Data.Base = (u8*)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (Result.Data.Base) - { - Result.Data.Size = FileSize; - - s32 BytesRead = 0; - if (ReadFile(FileHandle, (LPVOID)Result.Data.Base, FileSize, (LPDWORD)(&BytesRead), NULL)) - { - - } - else - { - u32 Error = GetLastError(); - VirtualFree(Result.Data.Base, 0, MEM_RELEASE); - Result.Data.Size = 0; - Result.Error = PlatformMemory_UnknownError; - } - } - else - { - Result.Error = PlatformMemory_UnknownError; - } - CloseHandle(FileHandle); - } - else - { - Result.Error = PlatformMemory_FileNotFound; - } - - return Result; -} - -PLATFORM_WRITE_ENTIRE_FILE(Win32WriteEntireFile) -{ - Assert(IsNullTerminated(Path)); - b32 Result = false; - HANDLE FileHandle = CreateFileA ( - Path.Memory, - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (FileHandle != INVALID_HANDLE_VALUE) - { - DWORD BytesWritten = 0; - - b32 WriteSuccess = WriteFile(FileHandle, - Contents, Size, - &BytesWritten, - NULL); - - if (WriteSuccess && BytesWritten == (u32)Size) - { - CloseHandle(FileHandle); - Result = true; - } - else - { - Result = false; - } - } - else - { - Result = false; - } - - return Result; -} - -internal FILETIME -GetFileLastWriteTime(char* Path) -{ - FILETIME Result = {}; - - WIN32_FIND_DATA FindData = {}; - HANDLE FileHandle = FindFirstFileA(Path, &FindData); - - if (FileHandle != INVALID_HANDLE_VALUE) - { - Result = FindData.ftLastWriteTime; - FindClose(FileHandle); - } - else - { - // TODO(Peter): :ErrorLogging - } - - return Result; -} - -PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile) -{ - b32 Result = false; - - PathBuffer->Memory[0] = 0; - - OPENFILENAMEA OpenFileName = {}; - OpenFileName.lStructSize = sizeof(OpenFileName); - OpenFileName.hwndOwner = NULL; - OpenFileName.lpstrFilter = FilterStrings; - OpenFileName.lpstrCustomFilter = NULL; // NOTE(Peter): for preserving last filter string chosen - OpenFileName.nMaxCustFilter = 0; // NOTE(Peter): ignored since we left CustomFilter null - OpenFileName.nFilterIndex = 1; - OpenFileName.lpstrFile = PathBuffer->Memory; - OpenFileName.nMaxFile = PathBuffer->Max; - OpenFileName.lpstrFileTitle = NULL; - OpenFileName.nMaxFileTitle = 0; // NOTE(Peter): Ignored since fileTitle is null - OpenFileName.lpstrInitialDir = NULL; - OpenFileName.lpstrTitle = NULL; - OpenFileName.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST; - OpenFileName.lpstrDefExt = NULL; - - Result = GetOpenFileNameA (&OpenFileName); - - PathBuffer->Length = CharArrayLength(PathBuffer->Memory); - - return Result; -} - #define WIN32_FOLDHAUS_FILEIO_H #endif // WIN32_FOLDHAUS_FILEIO_H \ No newline at end of file diff --git a/src/app/win32_foldhaus_memory.h b/src/app/win32_foldhaus_memory.h index c1c8c1c..100dd1a 100644 --- a/src/app/win32_foldhaus_memory.h +++ b/src/app/win32_foldhaus_memory.h @@ -8,17 +8,21 @@ // #ifndef WIN32_FOLDHAUS_MEMORY_H -PLATFORM_ALLOC(Win32Alloc) +ALLOCATOR_ALLOC(Win32Alloc) { u8* Result = (u8*)VirtualAlloc(NULL, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (ResultSize != 0) + { + *ResultSize = Size; + } return Result; } -PLATFORM_FREE(Win32Free) +ALLOCATOR_FREE(Win32Free) { - b32 Result = VirtualFree(Base, 0, MEM_RELEASE); + b32 Result = VirtualFree(Ptr, 0, MEM_RELEASE); if (!Result) { s32 Error = GetLastError(); @@ -26,18 +30,6 @@ PLATFORM_FREE(Win32Free) // to know what it could possibly be. InvalidCodePath; } - return Result; -} - -PLATFORM_REALLOC(Win32Realloc) -{ - u8* NewMemory = Win32Alloc(NewSize); - if (Base) - { - GSMemCopy(Base, NewMemory, OldSize); - Win32Free(Base, OldSize); - } - return NewMemory; } #define WIN32_FOLDHAUS_MEMORY_H diff --git a/src/gs_libs/gs_language.h b/src/gs_libs/gs_language.h index 9e12e25..b95b246 100644 --- a/src/gs_libs/gs_language.h +++ b/src/gs_libs/gs_language.h @@ -1,5 +1,6 @@ #ifndef GS_LANGUAGE_H +#if 0 #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) #include @@ -7,7 +8,7 @@ #include #elif defined(__APPLE__) && defined(__MAC__) -// TODO(Peter): +// TODO(Peter): #else // Std lib #include @@ -42,6 +43,8 @@ typedef long long int s64; typedef float r32; typedef double r64; +#endif + #ifndef _STDINT #define INT8_MIN (-128) @@ -268,15 +271,15 @@ GSLerpDef(r32) GSLerpDef(r64) #undef GSLerpDef -static r32 GSSqrt(r32 V) -{ +static r32 GSSqrt(r32 V) +{ r32 Result = _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); - return Result; + return Result; } #if 0 // TODO(Peter): Need a way to split the input into two f32's to supply to _mm_sqrt_sd -static r64 GSSqrt(r64 V) -{ +static r64 GSSqrt(r64 V) +{ r64 Result = _mm_cvtsd_f64(_mm_sqrt_sd(_mm_set_sd(V))); return Result; } @@ -366,9 +369,9 @@ RoundToNearestPowerOfTwo (u8 V) { u8 Result = 0; - if (IsPowerOfTwo(V)) - { - Result = V; + if (IsPowerOfTwo(V)) + { + Result = V; } else { @@ -387,9 +390,9 @@ RoundToNearestPowerOfTwo (u16 V) { u16 Result = 0; - if (IsPowerOfTwo(V)) - { - Result = V; + if (IsPowerOfTwo(V)) + { + Result = V; } else { @@ -409,9 +412,9 @@ RoundToNearestPowerOfTwo (u32 V) { u32 Result = 0; - if (IsPowerOfTwo(V)) - { - Result = V; + if (IsPowerOfTwo(V)) + { + Result = V; } else { @@ -432,9 +435,9 @@ RoundToNearestPowerOfTwo (u64 V) { u64 Result = 0; - if (IsPowerOfTwo(V)) - { - Result = V; + if (IsPowerOfTwo(V)) + { + Result = V; } else { diff --git a/src/gs_libs/gs_memory_arena.h b/src/gs_libs/gs_memory_arena.h index 119656c..4fbeb3b 100644 --- a/src/gs_libs/gs_memory_arena.h +++ b/src/gs_libs/gs_memory_arena.h @@ -314,7 +314,7 @@ PlatformRealloc(platform_memory_handler Platform, gs_mem_u8* Head, gs_mem_u32 Ol Result = PlatformAlloc(Platform, NewSize); if (Head != 0 && OldSize != 0) { - GSMemCopy(Head, Result, OldSize); + CopyMemoryTo(Head, Result, OldSize); PlatformFree(Platform, Head, OldSize); } } @@ -336,8 +336,6 @@ FreeMemoryArena(memory_arena* Arena) PlatformFree(Arena->PlatformMemory, (u8*)Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount); } -#define IsPowerOfTwo(v) ((v != 0) && ((v & (v - 1)) == 0)) - inline gs_mem_u32 GetAlignmentOffset (gs_mem_u64 Address, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) { diff --git a/src/gs_libs/gs_string.h b/src/gs_libs/gs_string.h index 9b3f4c0..6b4efca 100644 --- a/src/gs_libs/gs_string.h +++ b/src/gs_libs/gs_string.h @@ -6,18 +6,6 @@ #ifndef GS_STRING_H #include -//////////////////////////////////////////////////////////////// -// String -//////////////////////////////////////////////////////////////// - -struct string -{ - char* Memory; - s32 Length; - // TODO(Peter): Max -> LengthMax for clarity - s32 Max; -}; - //////////////////////////////////////////////////////////////// // String Tokenizing //////////////////////////////////////////////////////////////// @@ -115,75 +103,14 @@ struct token { token_type Type; u32 LineNumber; - string Text; + gs_string Text; token* Next; // TODO(Peter): Get rid of this }; -//////////////////////////////////////////////////////////////// -// String Memory -//////////////////////////////////////////////////////////////// - -struct slot_header -{ - slot_header* Next; - s32 Size; -}; - -struct slot_arena -{ - u8* Memory; - s32 SlotSize; - s32 SlotCount; - slot_header* FreeList; -}; - -struct contiguous_slot_count_result -{ - s32 Count; - slot_header* LastContiguousSlot; -}; - - //////////////////////////////////////////////////////////////// // String Function Declarations //////////////////////////////////////////////////////////////// -// Utility -#if !defined GS_LANGUAGE_H - -static void GSZeroMemory (u8* Memory, s32 Size); -static s32 GSMin (s32 A, s32 B); -static s32 GSAbs (s32 A); -static float GSAbsF (float A); -static float GSPowF (float N, s32 Power); - -#endif - -// Setup -#define PushString(arena, size) MakeString(PushArray(arena, char, size), 0, size); - -static void InitializeEmptyString (string* String, char* Data, s32 DataSize); -static void InitializeString(string* String, char* Data, s32 Used, s32 Max); -static string InitializeEmptyString (char* Data, s32 DataSize); -static string InitializeString (char* Data, s32 Used, s32 Max); -static void ClearString (string* String); - -// Character Values -static bool IsSlash (char C); -static bool IsNewline (char C); -static bool IsWhitespace (char C); -static bool IsNewlineOrWhitespace (char C); -static bool IsAlpha (char C); -static bool IsUpper (char C); -static bool IsLower (char C); -static char ToUpper (char C); -static char ToLower (char C); -static bool IsNumeric (char C); -static bool IsNumericExtended (char C); -static bool IsAlphaNumeric (char C); -static bool IsOperator (char C); -static bool CharsEqualCaseInsensitive(char A, char B); - // Tokenizing static void EatChar(tokenizer* T); static b32 AtValidPosition(tokenizer Tokenizer); @@ -205,290 +132,6 @@ static s32 EatPastCharacter(tokenizer* T, char Char); static char* EatNumber(char* C); static s32 EatNumber(tokenizer* T); -// Char/Char Array -static u32 CharToUInt (char C); -static s32 CharArrayLength (char* CharArray); -static bool CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength); -static bool CharArraysEqualUnsafe (char* A, char* B); -static void ReverseCharArray (char* Array, s32 Length); -#define FirstIndexOfCharInCharArray(array, find) IndexOfChar(array, 0, find) -static s32 IndexOfChar (char* Array, s32 Start, char Find); -#define FastLastIndexOfCharInCharArray(array, len, find) FastReverseIndexOfChar(array, len, 0, find) -static s32 FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find); -#define LastIndexOfCharInCharArray(array, find) ReverseIndexOfChar(array, 0, find) -static s32 ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find); -static b32 CharArrayContains(char* Array, char* CheckFor); -static b32 CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength); - -// String - -#define MakeStringBuffer(name, size) char name##Backbuffer[(size)]; string name = MakeString(name##Backbuffer, size); - -static string MakeString (char* Array, s32 Length, s32 Max); -static string MakeString (char* Array, s32 Length); -static string MakeString (char* Array); -static string MakeStringLiteral(char* Data); - -static bool StringsEqual (string A, string B); -static bool StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength); -static bool StringEqualsCharArray (string String, char* CharArray); -static s32 FindFirstChar (string String, char C); - -static void SetStringToChar (string* Dest, char C, s32 Count); -static void SetStringToCharArray (string* Dest, char* Source); - -static void ConcatString (string Source, string* Dest); -static void ConcatString (string Source, s32 Length, string* Dest); -static void ConcatCharToString(string* Dest, char C); -static void ConcatCharArrayToString (char* Source, string* Dest); -static void ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest); - -static void CopyStringTo (string Source, string* Dest); -static s32 CopyStringToCharArray (string Source, char* Dest, s32 DestLength); -static void CopyCharArrayToString (char* Src, string* Dest); -static void CopyCharArrayToString (char* Src, s32 SrcLength, string* Dest); -static s32 CopyCharArray (char* Source, char* Dest, s32 DestLength); -static s32 CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset); - -static void InsertChar (string* String, char Char, s32 Index); -static void InsertStringAt (string* Dest, string Source, s32 At); -static void RemoveCharAt (string* String, s32 Index); - -static s32 IndexOfChar(string String, char C); -static s32 LastIndexOfChar(string String, char C); -static s32 SearchForCharInSet(string String, char* Set); -static s32 ReverseSearchForCharInSet(string String, char* Set); -static string Substring (string* String, s32 Start, s32 End); -static string Substring (string* String, s32 Start); - -static b32 StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength); -static b32 StringContainsString(string SearchIn, string SearchFor); -static b32 StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength); -static b32 StringContainsStringCaseInsensitive(string SearchIn, string SearchFor); - -static void NullTerminate (string* String); - -static u32 HashString(string String); - -// Parsing -enum parse_type -{ - ParseType_UnsignedInt, - ParseType_SignedInt, - ParseType_Float, -}; - -struct parse_result -{ - parse_type Type; - char* OnePastLast; - union - { - u32 UnsignedIntValue; - s32 SignedIntValue; - r32 FloatValue; - }; -}; - -enum format_flags -{ - FormatFlags_LeftJustify = 0x1, - FormatFlags_ForceSign = 0x2, - FormatFlags_ForceSpaceInsteadOfSign = 0x4, - FormatFlags_ForceDecimalOrPrependOx = 0x8, - FormatFlags_PadWithZeroesInsteadOfSpaces = 0x16, -}; - -static parse_result ParseUnsignedInt (s32 Length, char* String); -static parse_result ParseSignedInt (s32 Length, char* String); -static parse_result ParseFloat (s32 Length, char* String); - -// PrintF - -#define StringExpand(str) (str).Length, (str).Memory -static void PrintFArgList(char* Dest, s32 DestMax, char* Format, va_list Args); -static void PrintF(string* String, char* Format, ...); - -// Printing Helper Functions -static u32 GetU32NumberOfCharactersNeeded(u32 Value, u32 Base = 10); -static u32 GetS32NumberOfCharactersNeeded(u32 Value, s32 Base = 10); - -//////////////////////////////////////////////////////////////// -// String Memory Function Declarations -//////////////////////////////////////////////////////////////// - -static s32 CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize); -static bool SlotsAreContiguous (slot_header* First, slot_header* Second); -static contiguous_slot_count_result CountContiguousSlots (slot_header* First); -static slot_header* GetSlotAtOffset(slot_header* First, s32 Offset); -static slot_header* InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart); -static void AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage); -static string AllocStringFromStringArena (s32 Size, slot_arena* Storage); -static void FreeToStringArena (string* String, slot_arena* Storage); -static void ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage); - -//////////////////////////////////////////////////////////////// -// String Utility Functions -//////////////////////////////////////////////////////////////// - -#if !defined GS_LANGUAGE_H - -static void -GSZeroMemory (u8* Memory, s32 Size) -{ - for (int i = 0; i < Size; i++) { Memory[i] = 0; } -} - -static s32 -GSMin (s32 A, s32 B) -{ - return (A < B ? A : B); -} - -static s32 -GSAbs (s32 A) -{ - return (A < 0 ? -A : A); -} - -static float -GSAbs (float A) -{ - return (A < 0 ? -A : A); -} - -static float -GSPow (float N, s32 Power) -{ - float Result = N; - for(s32 i = 1; i < Power; i++) { Result *= N; } - return Result; -} - -#endif - -//////////////////////////////////////////////////////////////// -// Init and Clear -//////////////////////////////////////////////////////////////// - -static void -InitializeEmptyString (string* String, char* Data, s32 DataSize) -{ - String->Memory = Data; - String->Max = DataSize; - String->Length = 0; -} - -static void -InitializeString(string* String, char* Data, s32 Used, s32 Max) -{ - String->Memory = Data; - String->Max = Max; - String->Length = Used; -} - -static string -InitializeEmptyString (char* Data, s32 DataSize) -{ - string Result = {}; - Result.Memory = Data; - Result.Max = DataSize; - Result.Length = 0; - return Result; -} - -static string -InitializeString (char* Data, s32 Used, s32 Max) -{ - string Result = {}; - Result.Memory = Data; - Result.Max = Max; - Result.Length = Used; - return Result; -} - -static void -ClearString (string* String) -{ - String->Memory = 0; - String->Max = 0; - String->Length = 0; -} - -//////////////////////////////////////////////////////////////// -// Char Value Types -//////////////////////////////////////////////////////////////// - -static bool IsNullTerminated(string Str) -{ - char LastChar = Str.Memory[Str.Length]; - bool Result = (LastChar == 0); - return Result; -} -static bool IsSlash (char C) { return ((C == '\\') || (C == '/')); } -static bool IsNewline (char C) { return (C == '\n') || (C == '\r'); } -static bool IsWhitespace (char C) { return (C == ' ') || (C == '\t'); } -static bool IsNewlineOrWhitespace (char C) { return (IsWhitespace(C) || IsNewline(C)); } -static bool IsAlpha (char C) -{ - // TODO(Peter): support UTF8 chars - return ((C >= 'A') && (C <= 'Z')) || ((C >= 'a') && (C <= 'z')) || (C == '_'); -} -static bool IsUpper (char C) -{ - return ((C >= 'A') && (C <= 'Z')); -} -static bool IsLower (char C) -{ - return ((C >= 'a') && (C <= 'z')); -} -static bool IsNumeric (char C) -{ - return (C >= '0') && (C <= '9'); -} -static bool IsNumericExtended (char C) -{ - return (IsNumeric(C) || (C == '-') || (C == 'x') || (C == 'f') || (C == '.')); -} -static bool IsAlphaNumeric (char C) -{ - return IsAlpha(C) || IsNumeric(C); -} -static bool IsOperator (char C) -{ - return ((C == '+') || - (C == '-') || - (C == '*') || - (C == '/') || - (C == '=') || - (C == '%') || - (C == '<') || - (C == '>')); -} -static char ToUpper (char A) -{ - char Result = A; - if (IsLower(A)) - { - Result += 'A' - 'a'; - } - return Result; -} -static char ToLower (char A) -{ - char Result = A; - if (IsUpper(A)) - { - Result -= 'A' - 'a'; - } - return Result; -} -static bool CharsEqualCaseInsensitive (char A, char B) -{ - b32 Result = (ToLower(A) == ToLower(B)); - return Result; -} - //////////////////////////////////////////////////////////////// // Tokenizing //////////////////////////////////////////////////////////////// @@ -669,1765 +312,7 @@ EatNumber(tokenizer* T) return T->At - TStart; } -//////////////////////////////////////////////////////////////// -// Basic Char Operations -//////////////////////////////////////////////////////////////// - -static u32 CharToUInt (char C) { - u32 Result = (C - '0'); - return Result; -} - -static s32 -CharArrayLength (char* Array) -{ - char* C = Array; - s32 Result = 0; - while (*C) - { - *C++; - Result++; - } - return Result; -} - -static s32 -NullTerminatedCharArrayLength (char* CharArray) -{ - char* Iter = CharArray; - while (*Iter) - { - *Iter++; - } - return (Iter - CharArray); -} - -static bool -CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength) -{ - bool Result = false; - if (ALength == BLength) - { - Result = true; - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < ALength; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - return Result; -} - -static bool -CharArraysEqualUnsafe (char* A, char* B) -{ - bool Result = true; - - char* AIter = A; - char* BIter = B; - while(*AIter && *BIter) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - if((*AIter && !*BIter) || (!*AIter && *BIter)) - { - Result = false; - } - - return Result; -} - -static bool -CharArraysEqualUpToLength (char* A, char* B, s32 Length) -{ - bool Result = true; - - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < Length; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - return Result; -} - -static void -ReverseCharArray (char* Array, s32 Length) -{ - char* ForwardIter = Array; - char* BackwardIter = Array + Length - 1; - for (s32 i = 0; i < (Length / 2); i++) - { - char F = *ForwardIter; - char B = *BackwardIter; - *ForwardIter++ = B; - *BackwardIter-- = F; - } -} - -static s32 -IndexOfChar (char* Array, s32 After, char Find) -{ - s32 Result = -1; - - s32 Counter = After; - char* Iter = Array + After; - while (*Iter) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - Counter++; - *Iter++; - } - - return Result; -} - -static s32 -FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find) -{ - s32 Result = -1; - - s32 Counter = Length - OffsetFromEnd; - char* Iter = Array + Length - OffsetFromEnd; - for (int i = 0; i < (Length - OffsetFromEnd); i++) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - - *Iter--; - Counter--; - } - - return Result; -} - -static s32 -ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find) -{ - s32 StringLength = NullTerminatedCharArrayLength(Array); - return FastReverseIndexOfChar(Array, StringLength, OffsetFromEnd, Find); -} - -static b32 -CharArrayContains(char* Array, char* CheckFor) -{ - b32 Result = false; - - char* Src = Array; - while (*Src) - { - if (*Src == *CheckFor) - { - char* A = CheckFor; - char* B = Src; - while (*B && *A && *A == *B) - { - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - - return Result; -} - -static b32 -CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength) -{ - b32 Result = false; - - if (ArrayLength >= CheckForLength) - { - char* Src = Array; - for (s32 s = 0; s < ArrayLength; s++) - { - if (*Src == *CheckFor && (s + CheckForLength <= ArrayLength)) - { - char* A = CheckFor; - char* B = Src; - for (s32 d = 0; d < CheckForLength; d++) - { - if (*B != *A) { break; } - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - } - - return Result; -} - -//////////////////////////////////////////////////////////////// -// Basic String Operations -//////////////////////////////////////////////////////////////// - -static bool -StringsEqual (string A, string B) -{ - bool Result = false; - - if (A.Length == B.Length) - { - Result = true; - char* AIter = A.Memory; - char* BIter = B.Memory; - for (s32 i = 0; i < A.Length; i++) - { - if (*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - - return Result; -} - -static string -MakeString (char* Array, s32 Length, s32 Max) -{ - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Max; - return Result; -} - -static string -MakeString (char* Array, s32 Length) -{ - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Length; - return Result; -} - -static string -MakeString (char* Array) -{ - s32 Length = CharArrayLength (Array); - return MakeString(Array, Length); -} - -static string -MakeStringLiteral (char* String) -{ - string Result = {}; - Result.Memory = String; - Result.Max = CharArrayLength(String); - Result.Length = Result.Max; - return Result; -} - -static bool -StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength) -{ - bool Result = false; - - if (CharArrayLength == String.Length) - { - Result = true; - - char* S = String.Memory; - char* C = CharArray; - for (s32 i = 0; i < String.Length; i++) - { - if (*C++ != *S++) - { - Result = false; - break; - } - } - } - - return Result; -} - -static bool -StringEqualsCharArray (string String, char* CharArray) -{ - s32 CLength = CharArrayLength(CharArray); - return StringEqualsCharArray(String, CharArray, CLength); -} - -static s32 -FindFirstChar (string String, char C) -{ - s32 Result = -1; - - char* Iter = String.Memory; - for (int i = 0; i < String.Length; i++) - { - if (*Iter++ == C) - { - Result = i; - break; - } - } - - return Result; -} - -static void -SetStringToChar (string* Dest, char C, s32 Count) -{ - Assert(Count <= Dest->Max); - - char* Iter = Dest->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = C; - } - Dest->Length = Count; -} - -static void -SetStringToCharArray (string* Dest, char* Source) -{ - Dest->Length = 0; - - char* Src = Source; - char* Dst = Dest->Memory; - while (*Src && Dest->Length < Dest->Max) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatString (string Source, string* Dest) -{ - Assert((Dest->Length + Source.Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Source.Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatString (string Source, s32 Length, string* Dest) -{ - Assert(Length <= Source.Length); - Assert((Dest->Length + Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatCharToString (string* Dest, char C) -{ - Assert(Dest->Length + 1 <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - *Dst = C; - Dest->Length++; -} - -static void -ConcatCharArrayToString (char* Source, string* Dest) -{ - Assert(CharArrayLength(Source) + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - while (Dest->Length < Dest->Max && - *Src) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest) -{ - Assert(SourceLength + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - for (int i = 0; i < SourceLength && Dest->Length < Dest->Max; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -CopyStringTo (string Source, string* Dest) -{ - char* Src = Source.Memory; - char* Dst = Dest->Memory; - s32 CopyLength = GSMin(Source.Length, Dest->Max); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - Dest->Length = Source.Length; -} - -static s32 -CopyStringToCharArray (string Source, char* Dest, s32 DestLength) -{ - char* Src = Source.Memory; - char* Dst = Dest; - s32 CopyLength = GSMin(Source.Length, DestLength); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - return CopyLength; -} - -static void -CopyCharArrayToString (char* Source, string* Dest) -{ - char* Src = Source; - char* Dst = Dest->Memory; - s32 Copied = 0; - while (*Src && Copied < Dest->Max) - { - *Dst++ = *Src++; - Copied++; - } - *Dst++ = 0; - Dest->Length = Copied; -} - -static void -CopyCharArrayToString (char* Source, s32 SourceLength, string* Dest) -{ - Assert(SourceLength <= Dest->Max); - - char* Src = Source; - char* Dst = Dest->Memory; - for (s32 i = 0; i < SourceLength; i++) - { - *Dst++ = *Src++; - } - *Dst++ = 0; - Dest->Length = SourceLength; -} - -static s32 -CopyCharArray (char* Source, char* Dest, s32 DestLength) -{ - char* Src = Source; - char* Dst = Dest; - s32 i = 0; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i; -} - -static s32 -CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset) -{ - Assert(Offset < DestLength); - - char* Src = Source; - char* Dst = Dest + Offset; - s32 i = Offset; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i - Offset; -} - -static void -InsertChar (string* String, char Char, s32 Index) -{ - Assert(Index >= 0 && Index < String->Max); - Assert(String->Length < String->Max); - - char* Src = String->Memory + String->Length - 1; - char* Dst = Src + 1; - for (int i = String->Length - 1; i >= Index; i--) - { - *Dst-- = *Src--; - } - - *(String->Memory + Index) = Char; - String->Length++; -} - -static void -RemoveCharAt (string* String, s32 Index) -{ - Assert(Index >= 0 && Index < String->Max); - - char* Dst = String->Memory + Index; - char* Src = Dst + 1; - for (int i = Index; i < String->Length; i++) - { - *Dst++ = *Src++; - } - *Dst = 0; - String->Length--; -} - -static s32 -IndexOfChar(string String, char C) -{ - s32 Result = -1; - char* At = String.Memory; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = i; - break; - } - At++; - } - return Result; -} - -static s32 -LastIndexOfChar(string String, char C) -{ - s32 Result = -1; - char* At = String.Memory + String.Length - 1; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = String.Length - i; - break; - } - At--; - } - return Result; -} - -static s32 -SearchForCharInSet(string String, char* Set) -{ - s32 Index = -1; - - char* At = String.Memory; - for (s32 i = 0; i < String.Length; i++) - { - char* Needle = Set; - while (*Needle) - { - if (*At == *Needle) - { - Index = String.Length - i; - break; - } - - Needle++; - } - - if (Index >= 0) - { - break; - } - - At++; - } - - return Index; -} - -static s32 -ReverseSearchForCharInSet(string String, char* Set) -{ - s32 Index = -1; - - for (s32 i = String.Length - 1; i >= 0; i--) - { - char* Needle = Set; - while (*Needle) - { - if (String.Memory[i] == *Needle) - { - Index = i; - break; - } - - Needle++; - } - - if (Index >= 0) - { - break; - } - } - - return Index; -} - -static string -Substring (string String, s32 Start, s32 End) -{ - Assert(Start >= 0 && End > Start && End <= String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = End - Start; - return Result; -} - -static string -Substring (string String, s32 Start) -{ - Assert(Start >= 0 && Start < String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = String.Length - Start; - return Result; -} - -static b32 -StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength) -{ - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (*InAt == *ForAt) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; -} - -static b32 -StringContainsString(string SearchIn, string SearchFor) -{ - return StringContainsCharArray(SearchIn, SearchFor.Memory, SearchFor.Length); -} - -static b32 -StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength) -{ - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (CharsEqualCaseInsensitive(*InAt, *ForAt)) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; -} - -static b32 -StringContainsStringCaseInsensitive(string SearchIn, string SearchFor) -{ - return StringContainsCharArrayCaseInsensitive(SearchIn, SearchFor.Memory, SearchFor.Length); -} - -static void -NullTerminate (string* String) -{ - Assert(String->Length + 1 <= String->Max); - *(String->Memory + String->Length) = 0; - String->Length++; -} - -// http://www.cse.yorku.ca/~oz/hash.html -// djb2 hash -static u32 -HashString(string String) -{ - u32 Hash = 5381; - for (s32 i = 0; i < String.Length; i++) - { - Hash = ((Hash << 5) + Hash) + (u32)String.Memory[i]; /* hash * 33 + c */ - } - return Hash; -} - -static void -InsertStringAt (string* Dest, string Source, s32 At) -{ - Assert(At + Source.Length < Dest->Max); - Assert(At < Dest->Length); - - char* Src = Dest->Memory + Dest->Length; - char* Dst = Dest->Memory + Source.Length + Dest->Length; - for (s32 i = Dest->Length - 1; i >= At; i--) - { - *--Dst = *--Src; - } - - Src = Source.Memory; - Dst = Dest->Memory + At; - for (s32 j = 0; j < Source.Length; j++) - { - *Dst++ = *Src++; - } - - Dest->Length += Source.Length; -} - -//////////////////////////////////////////////////////////////// -// String Parsing -//////////////////////////////////////////////////////////////// - -// NOTE(Peter): parameters are all in order Length, String because -// that matches the order of C's printf %.*s format specifier. This -// is convenient because you can use StringExpand to parse a string -// struct -// :StringExpandNote -static parse_result -ParseUnsignedInt (s32 Length, char* String) -{ - Assert(IsNumeric(*String)); - parse_result Result = {}; - Result.Type = ParseType_UnsignedInt; - - char* Iter = String; - u32 ResultValue = 0; - for (s32 i = 0; i < Length; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - Result.UnsignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseUnsignedIntUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseUnsignedInt(End - Start, String); -} - -// :StringExpandNote -static parse_result -ParseSignedInt (s32 Length, char* String) -{ - Assert(Length > 0); - parse_result Result = {}; - Result.Type = ParseType_SignedInt; - - s32 Negative = 1; - s32 LengthRemaining = Length; - s32 ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - ResultValue *= Negative; - - Result.SignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseSignedIntUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseSignedInt(End - Start, String); -} - -// :StringExpandNote -static parse_result -ParseFloat (s32 Length, char* String) -{ - parse_result Result = {}; - Result.Type = ParseType_Float; - - s32 Negative = 1; - s32 LengthRemaining = Length; - float ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - ResultValue = (float)CharToUInt(*Iter++) + (ResultValue * 10); - } - else if (*Iter == '.' || *Iter == 0) - { - LengthRemaining -= i; - break; - } - } - - if (*Iter == '.') - { - *Iter++; - float AfterPoint = 0; - s32 PlacesAfterPoint = 0; - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - AfterPoint = (float)CharToUInt(*Iter++) + (AfterPoint * 10); - PlacesAfterPoint++; - } - else - { - break; - } - } - - AfterPoint = AfterPoint / GSPow(10, PlacesAfterPoint); - ResultValue += AfterPoint; - } - - ResultValue *= Negative; - - Result.FloatValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseFloatUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseFloat(End - Start, String); -} - -static s32 -UIntToString (u32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) -{ - s32 Remaining = Int; - char* Iter = String; - while (Remaining > 0 && (Iter - String) < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - } - s32 CharsCopied = Iter - String; - ReverseCharArray(String, CharsCopied); - return CharsCopied; -} - -static s32 -IntToString (s32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) -{ - s32 Remaining = Int; - s32 CharsCopied = 0; - - char* Iter = String; - - bool Negative = Remaining < 0; - Remaining = GSAbs(Remaining); - - if (Remaining > 0) - { - while (Remaining > 0 && CharsCopied < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - CharsCopied++; - } - } - else if (Remaining == 0) - { - *Iter++ = '0'; - } - - if (Negative) - { - *Iter++ = '-'; - CharsCopied++; - } - - ReverseCharArray(String, CharsCopied); - return CharsCopied; -} - -static s32 -IntToString (s32 Int, char* String, s32 MaxLength, s32 Offset, b32 FormatFlags = 0, s32 MinimumWidth = 0) -{ - char* StringStart = String + Offset; - s32 LengthWritten = IntToString(Int, StringStart, MaxLength - Offset); - return LengthWritten; -} - -static s32 -FloatToString(float Float, char *String, s32 MaxLength, s32 AfterPoint = 0, b32 FormatFlags = 0, s32 MinimumWidth = 0) -{ - s32 IPart = (s32)Float; - float FPart = GSAbs(Float - (float)IPart); - - s32 i = IntToString(IPart, String, MaxLength); - - if (AfterPoint > 1) - { - String[i++] = '.'; - - s32 FPartInt = FPart * GSPow(10, AfterPoint); - i += IntToString(FPartInt, String, MaxLength, i, 0, 0); - } - - return i; -} - -//////////////////////////////////////////////////////////////// -// PrintF -//////////////////////////////////////////////////////////////// - -static void -OutChar (string* String, char C) -{ - if (String->Length < String->Max) - { - String->Memory[String->Length] = C; - String->Length++; - } -} - -char OctalDigits[] = "01234567"; -char DecimalDigits[] = "0123456789"; -char HexDigits[] = "0123456789ABCDEF"; - -static void -U64ToASCII (string* String, u64 Value, s32 Base, char* Digits) -{ - u64 ValueRemaining = Value; - char* Start = String->Memory + String->Length; - do { - s32 DigitsIndex = ValueRemaining % Base; - char Digit = Digits[DigitsIndex]; - OutChar(String, Digit); - ValueRemaining /= Base; - }while (ValueRemaining); - char* End = String->Memory + String->Length; - - while (Start < End) - { - End--; - char Temp = *End; - *End = *Start; - *Start = Temp; - *Start++; - } -} - -static void -F64ToASCII (string* String, r64 Value, s32 Precision) -{ - if (Value < 0) - { - OutChar(String, '-'); - Value = -Value; - } - - u64 IntegerPart = (u64)Value; - Value -= IntegerPart; - - U64ToASCII(String, IntegerPart, 10, DecimalDigits); - - OutChar(String, '.'); - - for (s32 i = 0; i < Precision; i++) - { - Value *= 10.f; - u32 DecimalPlace = Value; - Value -= DecimalPlace; - OutChar(String, DecimalDigits[DecimalPlace]); - } -} - -internal s64 -ReadVarArgsSignedInteger (s32 Width, va_list* Args) -{ - s64 Result = 0; - switch (Width) - { - case 1: { Result = (s64)va_arg(*Args, s8); } break; - case 2: { Result = (s64)va_arg(*Args, s16); } break; - case 4: { Result = (s64)va_arg(*Args, s32); } break; - case 8: { Result = (s64)va_arg(*Args, s64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal r64 -ReadVarArgsUnsignedInteger (s32 Width, va_list* Args) -{ - u64 Result = 0; - switch (Width) - { - case 1: { Result = (u64)va_arg(*Args, u8); } break; - case 2: { Result = (u64)va_arg(*Args, u16); } break; - case 4: { Result = (u64)va_arg(*Args, u32); } break; - case 8: { Result = (u64)va_arg(*Args, u64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal r64 -ReadVarArgsFloat (s32 Width, va_list* Args) -{ - r64 Result = 0; - switch (Width) - { - case 4: { Result = (r64)va_arg(*Args, r64); } break; - case 8: { Result = (r64)va_arg(*Args, r64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal s32 -PrintFArgsList (char* Dest, s32 DestMax, char* Format, va_list Args) -{ - char* DestAt = Dest; - - char* FormatAt = Format; - while (*FormatAt) - { - if (FormatAt[0] != '%') - { - *DestAt++ = *FormatAt++; - } - else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol - { - *DestAt++ = '%'; - FormatAt += 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 (IsNumeric(FormatAt[0])) - { - WidthSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Width = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - WidthSpecified = true; - Width = va_arg(Args, s32); - Assert(Width >= 0); - FormatAt++; - } - - // Precision - b32 PrecisionSpecified = false; - s32 Precision = 0; - - if (FormatAt[0] == '.') - { - FormatAt++; - if (IsNumeric(FormatAt[0])) - { - PrecisionSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Precision = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - PrecisionSpecified = true; - Precision = va_arg(Args, s32); - Assert(Precision >= 0); - FormatAt++; - } - } - - // Length - b32 LengthSpecified = false; - s32 Length = 4; - - if (FormatAt[0] == 'h' && FormatAt[1] == 'h') - { - LengthSpecified = true; - LengthSpecified = 1; - FormatAt += 2; - } - else if (FormatAt[0] == 'h') - { - LengthSpecified = true; - LengthSpecified = 2; - FormatAt++; - } - else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt += 2; - } - else if (FormatAt[0] == 'l') - { - LengthSpecified = true; - LengthSpecified = 4; - FormatAt++; - } - else if (FormatAt[0] == 'j') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt++; - } - else if (FormatAt[0] == 'z') - { - FormatAt++; - } - else if (FormatAt[0] == 't') - { - FormatAt++; - } - else if (FormatAt[0] == 'L') - { - FormatAt++; - } - - // Format Specifier - s32 DestLengthRemaining = DestMax - (DestAt - Dest); - - char Temp[64]; - string TempDest = MakeString(Temp, 0, 64); - - if (FormatAt[0] == 'd' || FormatAt[0] == 'i') - { - s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); - if (SignedInt < 0) - { - OutChar(&TempDest, '-'); - SignedInt *= -1; - } - U64ToASCII(&TempDest, (u64)SignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'u') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'o') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 8, OctalDigits); - } - else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 16, HexDigits); - } - else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') - { - r64 Float = ReadVarArgsFloat(Length, &Args); - s32 AfterPoint = 6; - if (PrecisionSpecified) - { - AfterPoint = Precision; - } - F64ToASCII(&TempDest, Float, AfterPoint); - } - else if (FormatAt[0] == 'c') - { - char InsertChar = va_arg(Args, char); - OutChar(&TempDest, InsertChar); - } - else if (FormatAt[0] == 's') - { - char* InsertString = va_arg(Args, char*); - - s32 InsertStringLength = CharArrayLength(InsertString); - if (PrecisionSpecified) - { - InsertStringLength = GSMin(InsertStringLength, Precision); - } - InsertStringLength = GSMin(DestLengthRemaining, InsertStringLength); - - for (s32 c = 0; c < InsertStringLength; c++) - { - OutChar(&TempDest, *InsertString++); - } - } - else if (FormatAt[0] == 'S') - { - string InsertString = va_arg(Args, string); - - for (s32 c = 0; c < InsertString.Length; c++) - { - OutChar(&TempDest, InsertString.Memory[c]); - } - } - else if (FormatAt[0] == 'p') - { - // TODO(Peter): Pointer Address - } - else - { - // NOTE(Peter): Non-specifier character found - InvalidCodePath; - } - - for (s32 i = 0; i < TempDest.Length; i++) - { - *DestAt++ = TempDest.Memory[i]; - } - - *FormatAt++; - } - } - - s32 FormattedLength = DestAt - Dest; - return FormattedLength; -} - -static void -PrintF (string* String, char* Format, ...) -{ - va_list Args; - va_start(Args, Format); - String->Length = 0; - String->Length += PrintFArgsList(String->Memory + String->Length, String->Max - String->Length, Format, Args); - va_end(Args); -} - -static void -AppendPrintF (string* String, char* Format, ...) -{ - va_list Args; - va_start(Args, Format); - String->Length += PrintFArgsList(String->Memory + String->Length, String->Max - String->Length, Format, Args); - va_end(Args); -} - -// Printing Helper Functions -static u32 -GetU32NumberOfCharactersNeeded(u32 Value, u32 Base) -{ - u32 Result = 0; - u32 ValueLeft = Value; - // NOTE(Peter): This is in a do while loop because even if the number is 0, - // it'll still take one character to display that. - do - { - Result += 1; - ValueLeft /= Base; - }while (ValueLeft > 0); - return Result; -} - -static u32 -GetS32NumberOfCharactersNeeded(s32 Value, s32 Base) -{ - u32 Result = 0; - s32 ValueLeft = Value; - if (Value < 0) - { - Result += 1; - ValueLeft = Value * -1; - } - // NOTE(Peter): This is in a do while loop because even if the number is 0, - // it'll still take one character to display that. - do - { - Result += 1; - ValueLeft /= Base; - }while (ValueLeft > 0); - return Result; -} - -//////////////////////////////////////////////////////////////// -// String Memory Function Definitions -//////////////////////////////////////////////////////////////// - -static s32 -CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize) -{ - s32 SlotCount = RequestedSize / SlotSize; - if (SlotCount * SlotSize < RequestedSize) - { - SlotCount += 1; - } - return SlotCount; -} - -static bool -SlotsAreContiguous (slot_header* First, slot_header* Second) -{ - bool Result = false; - u8* FirstSlotNextAddress = (u8*)First + First->Size; - u8* SecondAddress = (u8*)Second; - Result = FirstSlotNextAddress == SecondAddress; - return Result; -} - -static contiguous_slot_count_result -CountContiguousSlots (slot_header* First) -{ - Assert(First != 0); - - contiguous_slot_count_result Result = {}; - Result.Count = 1; - - slot_header* IterPrev = First; - slot_header* Iter = First->Next; - while (Iter && SlotsAreContiguous(IterPrev, Iter)) - { - Result.Count++; - IterPrev = Iter; - Iter = Iter->Next; - } - - Result.LastContiguousSlot = IterPrev; - return Result; -} - -static slot_header* -GetSlotAtOffset(slot_header* First, s32 Offset) -{ - slot_header* Iter = First; - s32 Count = 0; - while (Count < Offset && Iter) - { - Iter = Iter->Next; - Count++; - } - return Iter; -} - -static slot_header* -InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart) -{ - slot_header* List = ListStart; - if (NewSlot < List) - { - NewSlot->Next = List; - List = NewSlot; - } - else - { - slot_header* PrevIter = List; - slot_header* Iter = List->Next; - while (Iter && NewSlot > Iter) - { - PrevIter = Iter; - Iter = Iter->Next; - } - - Assert(PrevIter); - if (PrevIter) - { - PrevIter->Next = NewSlot; - } - - if (Iter) - { - NewSlot->Next = Iter; - } - } - return List; -} - -static void -AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage) -{ - s32 SlotCount = CalculateSlotCountFromSize(Size, Storage->SlotSize); - slot_header* Slot = Storage->FreeList; - slot_header* PrevSlot = 0; - while (Slot) - { - contiguous_slot_count_result ContiguousSlots = CountContiguousSlots(Slot); - if (ContiguousSlots.Count >= SlotCount) - { - slot_header* NextStartSlot = GetSlotAtOffset(Slot, SlotCount); - if (PrevSlot) - { - PrevSlot->Next = NextStartSlot; - } - else - { - Storage->FreeList = NextStartSlot; - } - break; - } - else - { - PrevSlot = Slot; - Slot = Slot->Next; - } - } - - if (Slot) - { - String->Memory = (char*)Slot; - GSZeroMemory((u8*)String->Memory, SlotCount * Storage->SlotSize); - String->Max = SlotCount * Storage->SlotSize; - String->Length = 0; - } -} - -static string -AllocStringFromStringArena (s32 Size, slot_arena* Storage) -{ - string Result = {0}; - AllocStringFromStringArena(&Result, Size, Storage); - return Result; -} - -static void -FreeToStringArena (string* String, slot_arena* Storage) -{ - u8* Base = (u8*)(String->Memory); - u8* End = Base + String->Max - 1; - u8* MemoryEnd = Storage->Memory + (Storage->SlotSize * Storage->SlotCount); - Assert((Base >= Storage->Memory) && (End < MemoryEnd)); - Assert((String->Max % Storage->SlotSize) == 0); - - s32 SizeReclaimed = 0; - slot_header* Slot = (slot_header*)Base; - while (SizeReclaimed < String->Max) - { - Slot->Size = Storage->SlotSize; - Storage->FreeList = InsertSlotIntoList(Slot, Storage->FreeList); - SizeReclaimed += Storage->SlotSize; - Slot = (slot_header*)(Base + SizeReclaimed); - } - - String->Memory = 0; - String->Length = 0; - String->Max = 0; -} - -static void -ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage) -{ - string NewString = AllocStringFromStringArena(NewSize, Storage); - CopyStringTo(*String, &NewString); - FreeToStringArena(String, Storage); - *String = NewString; -} - -#if defined(DEBUG) - -void DEBUGPrintChars (string* String, s32 Count) -{ - char* Iter = String->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = (char)('A' + i); - } - String->Length = Count; -} - -#ifdef DEBUG_GS_STRING - -#include - -static void -TestStrings() -{ - - slot_arena StringArena = {}; - - s32 TestCount = 0; - s32 SuccessCount = 0; - - DebugPrint("\n\n-------------------------------------------------\n Begin Testing Strings\n\n\n"); - - //////////////////////////////////////////////////////////////// - // Char Functions - - char ForwardArray[] = "Hello, Sailor"; - char BackwardArray[] = "roliaS ,olleH"; - TestClean(CharArraysEqual(ForwardArray, 13, ForwardArray, 13), "String Equality"); - TestClean(!CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "String Equality"); - - TestClean(IndexOfChar(ForwardArray, 0, ',') == 5, "Index Of Char"); - TestClean(IndexOfChar(ForwardArray, 5, 'l') == 10, "Index of Char (skipping first 5)"); - TestClean(FastReverseIndexOfChar(ForwardArray, 13, 0, 'o') == 11, "Fast Reverse Index Of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 0, 'o') == 11, "Reverse Index of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 3, 'o') == 4, "Reverse Index of Char (skipping last 3)"); - TestClean(LastIndexOfChar(ForwardArray, 'o') == 11, "Last Index of Char"); - - ReverseCharArray(ForwardArray, 13); - TestClean(CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "Reversing Char Array"); - - char UIntString[] = "1234"; - u32 UIntValue = 1234; - u32 ParsedUInt = ParseUnsignedInt(UIntString, 4); - TestClean((ParsedUInt == UIntValue), "String To U32"); - char StringifiedUInt[4] = {}; - UIntToString(UIntValue, StringifiedUInt, 4); - TestClean(CharArraysEqual(UIntString, 4, StringifiedUInt, 4), "U32 To String"); - - char IntString[] = "-1234"; - s32 IntValue = -1234; - s32 ParsedInt = ParseSignedInt(IntString, 5); - TestClean((ParsedInt == IntValue), "String To S32"); - char StringifiedInt[5] = {}; - IntToString(IntValue, StringifiedInt, 5); - TestClean(CharArraysEqual(IntString, 5, StringifiedInt, 5), "S32 to String"); - - char FloatString[] = "-1234.125"; - float FloatValue = -1234.125f; - float ParsedFloat = ParseFloat(FloatString, 8); - TestClean((ParsedFloat == FloatValue), "String To Float"); - char StringifiedFloat[10] = {}; - FloatToString(FloatValue, StringifiedFloat, 10, 3); - TestClean(CharArraysEqual(FloatString, 8, StringifiedFloat, 8), "Float To String"); - - - //////////////////////////////////////////////////////////////// - // - - StringArena.SlotSize = 256; - StringArena.SlotCount = 32; - StringArena.Memory = malloc(StringArena.SlotSize * StringArena.SlotCount); - slot_header* PrevSlotHeader = 0; - for (int i = StringArena.SlotCount - 1; i >= 0; i--) - { - u8* SlotBase = StringArena.Memory + (i * StringArena.SlotSize); - slot_header* SlotHeader = (slot_header*)SlotBase; - SlotHeader->Size = StringArena.SlotSize; - SlotHeader->Next = PrevSlotHeader; - - // TEST(peter): Should be true always, except on the first iteration, when there is no next slot - bool Contiguity = SlotsAreContiguous(SlotHeader, PrevSlotHeader); - TestClean((Contiguity || SlotHeader->Next == 0), "Contiguous Arenas"); - - PrevSlotHeader = SlotHeader; - } - StringArena.FreeList = PrevSlotHeader; - - // TEST(peter): Count Should equal StringArena.SlotCount - s32 ContiguousSlotsCountBefore = CountContiguousSlots(StringArena.FreeList).Count; - TestClean((ContiguousSlotsCountBefore == StringArena.SlotCount), "Contiguous Arenas"); - - // TEST(peter): Should be false - bool Contiguity = SlotsAreContiguous(StringArena.FreeList, StringArena.FreeList->Next->Next); - Contiguity = SlotsAreContiguous(StringArena.FreeList->Next->Next, StringArena.FreeList); - TestClean(!Contiguity, "Non Contiguous Arenas"); - - s32 Slots = CalculateSlotCountFromSize(10, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(256, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(345, 256); - TestClean(Slots == 2, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(1024, 256); - TestClean(Slots == 4, "Slot Sizing"); - - slot_header* HeaderTen = GetSlotAtOffset(StringArena.FreeList, 10); - slot_header* HeaderThree = GetSlotAtOffset(StringArena.FreeList, 3); - slot_header* HeaderFive = GetSlotAtOffset(StringArena.FreeList, 5); - - string StringA = AllocStringFromStringArena(10, &StringArena); - string StringB = AllocStringFromStringArena(345, &StringArena); - -#if 0 - // TEST(peter): Should TestClean - u8* RandomMemory = (u8*)malloc(256); - string RandomMemString = {}; - RandomMemString.Memory = (char*)RandomMemory; - RandomMemString.Max = 256; - FreeToStringArena(&RandomMemString, &StringArena); -#endif - FreeToStringArena(&StringA, &StringArena); - FreeToStringArena(&StringB, &StringArena); - // TEST(peter): After freeing both allocations, ContiguousSlotCountBefore and ContiguousSlotCountAfter should be equal - s32 ContiguousSlotCountAfter = CountContiguousSlots(StringArena.FreeList).Count; - TestClean(ContiguousSlotCountAfter == ContiguousSlotsCountBefore, "Add and REmove Slots from Arena"); - - // TEST(peter): Set up a free list where the first element is too small, so it has to traverse to find an appropriately - // sized block - // The slots will look list [256][used][256][256][256] etc.. - StringA = AllocStringFromStringArena(256, &StringArena); - StringB = AllocStringFromStringArena(256, &StringArena); - FreeToStringArena(&StringA, &StringArena); - u32 Contiguous = CountContiguousSlots(StringArena.FreeList).Count; // Should = 1; - string StringC = AllocStringFromStringArena(512, &StringArena); - slot_header* HeaderC = (slot_header*)(StringC.Memory); - - string ReallocTestString = AllocStringFromStringArena(256, &StringArena); - DEBUGPrintChars(&ReallocTestString, 24); - ReallocFromStringArena(&ReallocTestString, 512, &StringArena); - - - string TestString = AllocStringFromStringArena(10, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 20, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 10, &StringArena); - FreeToStringArena(&TestString, &StringArena); - - string EqualityStringA = AllocStringFromStringArena(345, &StringArena); - string EqualityStringB = AllocStringFromStringArena(415, &StringArena); - // Equality should succeed despite length differences - string EqualityStringC = AllocStringFromStringArena(256, &StringArena); - string EqualityStringD = AllocStringFromStringArena(256, &StringArena); // Equality should fail - string EqualityStringEmpty = {}; - - DEBUGPrintChars(&EqualityStringA, 24); - DEBUGPrintChars(&EqualityStringB, 24); - DEBUGPrintChars(&EqualityStringC, 24); - DEBUGPrintChars(&EqualityStringD, 12); - - bool ABEquality = StringsEqual(EqualityStringA, EqualityStringB); // Should Succeed - bool ACEquality = StringsEqual(EqualityStringA, EqualityStringC); // Should Succeed - bool ADEquality = StringsEqual(EqualityStringA, EqualityStringD); // Should Fail - bool AEEquality = StringsEqual(EqualityStringA, EqualityStringEmpty); // Should Fail - - TestClean(ABEquality, "String Equality"); - TestClean(ACEquality, "String Equality"); - TestClean(!ADEquality, "String Equality"); - TestClean(!AEEquality, "String Equality"); - - string CatStringA = AllocStringFromStringArena(256, &StringArena); - SetStringToCharArray(&CatStringA, "Hello "); - string CatStringB = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringB, "Sailor!"); - string CatStringResult = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringResult, "Hello Sailor!"); - ConcatString(&CatStringA, CatStringB); - TestClean(StringsEqual(CatStringA, CatStringResult), "Cat Strings"); - - s32 FirstSpaceIndex = FindFirstChar(CatStringA, ' '); - TestClean(FirstSpaceIndex == 5, "First Index"); - - SetStringToChar(&CatStringB, 'B', 5); - TestClean(StringEqualsCharArray(CatStringB, "BBBBB"), "SetStringToChar"); - - - DebugPrint("Results: Passed %d / %d\n\n\n", SuccessCount, TestCount); -} -#endif // DEBUG_GS_STRING - -#endif // DEBUG - #define GS_STRING_H -#endif // GS_STRING_H \ No newline at end of file +#endif // GS_STRING_H + + diff --git a/src/gs_libs/gs_string_builder.h b/src/gs_libs/gs_string_builder.h index e6e5df0..1102e97 100644 --- a/src/gs_libs/gs_string_builder.h +++ b/src/gs_libs/gs_string_builder.h @@ -37,7 +37,7 @@ GrowStringBuilder(string_builder* StringBuilder) { StringBuilder->Buffers = NewBuffer; StringBuilder->Head = NewBuffer; - } + } else { StringBuilder->Head->Next = NewBuffer; @@ -60,7 +60,7 @@ Write(string Text, string_builder* StringBuilder) // Copy what there is room for s32 SpaceAvailable = StringBuilder->Head->String.Max - StringBuilder->Head->String.Length; - ConcatString(TextLeft, GSMin(SpaceAvailable, TextLeft.Length), &StringBuilder->Head->String); + ConcatString(TextLeft, Min(SpaceAvailable, TextLeft.Length), &StringBuilder->Head->String); TextLeft.Memory += SpaceAvailable; TextLeft.Length -= SpaceAvailable; @@ -93,7 +93,7 @@ WriteStringBuilderToFile(string_builder StringBuilder, FILE* WriteFile) while (BufferAt) { string String = BufferAt->String; - fwrite(String.Memory, 1, String.Length, WriteFile); + fwrite(String.Str, 1, String.Length, WriteFile); BufferAt = BufferAt->Next; } } diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp new file mode 100644 index 0000000..d775d1e --- /dev/null +++ b/src/gs_libs/gs_types.cpp @@ -0,0 +1,3383 @@ +// +// File: gs_types.cpp +// Author: Peter Slattery +// Creation Date: 2020-04-18 +// +#ifndef GS_TYPES_CPP + +internal u32 +U32DivideRoundUp (u32 A, u32 B) +{ + r32 Result = (r32)A / (r32)B; + Result += .99999f; + return (u32)Result; +} + +inline bool XOR(bool A, bool B) { return (A == !B); } +inline bool XOR(b8 A, b8 B) { return (A == !B); } +inline bool XOR(b32 A, b32 B) { return (A == !B); } +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; +} +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; +} +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; +} +internal u64 +RoundUpTo64(u64 Value, u64 Alignment) +{ + 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; +} +internal u16 +PowU16(u16 X, u32 Power) +{ + 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; +} +internal u64 +PowU64(u64 X, u32 Power) +{ + 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; +} +internal s16 +PowS16(s16 X, u32 Power) +{ + 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; +} +internal s64 +PowS64(s64 X, u32 Power) +{ + 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; +} +internal r64 +PowR64(r64 X, u32 Power) +{ + 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)); +} +internal u16 +LerpU16(r32 T, u16 A, u16 B) +{ + 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)); +} +internal u64 +LerpU64(r32 T, u64 A, u64 B) +{ + 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)); +} +internal s16 +LerpS16(r32 T, s16 A, s16 B) +{ + 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)); +} +internal s64 +LerpS64(r32 T, s64 A, s64 B) +{ + 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)); +} +internal r64 +LerpR64(r32 T, r64 A, r64 B) +{ + 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)); +} +internal u16 +UnlerpU16(u16 Value, u16 Min, u16 Max) +{ + 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)); +} +internal u64 +UnlerpU64(u64 Value, u64 Min, u64 Max) +{ + 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)); +} +internal s16 +UnlerpS16(s16 Value, s16 Min, s16 Max) +{ + 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)); +} +internal s64 +UnlerpS64(s64 Value, s64 Min, s64 Max) +{ + return (s64)((r64)(Value - Min) / (r64)(Max - Min)); +} +internal r32 +UnlerpR32(r32 Value, r32 Min, r32 Max) +{ + return (Value - Min) / (Max - Min); +} +internal r64 +UnlerpR64(r64 Value, r64 Min, r64 Max) +{ + 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; +} +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; +} +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; +} +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; +} +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; +} +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; +} +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; +} +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; +} +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; +} +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; +} + +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; +} +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; +} +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; +} +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; +} +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; +} +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; +} +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; +} +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; +} +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; +} +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; +} + +internal r32 +FloorR32(r32 V) +{ + return (r32)((s64)V); +} +internal r64 +FloorR64(r64 V) +{ + return (r64)((s64)V); +} + +internal r32 +FractR32(r32 V) +{ + return V - FloorR32(V); +} +internal r64 +FractR64(r64 V) +{ + return V - FloorR64(V); +} + +internal r32 +SqrtR32(r32 V) +{ + return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); +} +internal u32 +SqrtU32(u32 V) +{ + return sqrt(V); +} + +internal r32 +SinR32(r32 Rad) +{ + return sinf(Rad); +} +internal r64 +SinR64(r64 Rad) +{ + return sin(Rad); +} + +internal r32 +CosR32(r32 Rad) +{ + return cosf(Rad); +} +internal r64 +CosR64(r64 Rad) +{ + return cos(Rad); +} + +internal r32 +TanR32(r32 Rad) +{ + return tanf(Rad); +} +internal r64 +TanR64(r64 Rad) +{ + return tan(Rad); +} + +internal r32 +ASinR32(r32 Rad) +{ + return asinf(Rad); +} +internal r64 +ASinR64(r64 Rad) +{ + return asin(Rad); +} + +internal r32 +ACosR32(r32 Rad) +{ + return acosf(Rad); +} +internal r64 +ACosR64(r64 Rad) +{ + return acos(Rad); +} + +internal r32 +ATanR32(r32 Rad) +{ + return atanf(Rad); +} +internal r64 +ATanR64(r64 Rad) +{ + return atan(Rad); +} + +/////////////////////////// +// +// Vector + +internal v2 +V2MultiplyPairwise(v2 A, v2 B) +{ + 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; +} + +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; +} + + +v2 operator- (v2 A) { return { -A.x, -A.y }; } +v3 operator- (v3 A) { return { -A.x, -A.y, -A.z }; } +v4 operator- (v4 A) { return { -A.x, -A.y, -A.z, -A.w }; } + +v2 operator+ (v2 A, v2 B) { return { A.x + B.x, A.y + B.y }; } +v3 operator+ (v3 A, v3 B) { return { A.x + B.x, A.y + B.y, A.z + B.z }; } +v4 operator+ (v4 A, v4 B) { return { A.x + B.x, A.y + B.y, A.z + B.z, A.w + B.w }; } + +v2 operator- (v2 A, v2 B) { return { A.x - B.x, A.y - B.y }; } +v3 operator- (v3 A, v3 B) { return { A.x - B.x, A.y - B.y, A.z - B.z }; } +v4 operator- (v4 A, v4 B) { return { A.x - B.x, A.y - B.y, A.z - B.z, A.w - B.w }; } + +void operator+= (v2& A, v2 B) { A.x += B.x; A.y += B.y; } +void operator+= (v3& A, v3 B) { A.x += B.x; A.y += B.y; A.z += B.z; } +void operator+= (v4& A, v4 B) { A.x += B.x; A.y += B.y; A.z += B.z; A.w += B.w; } + +void operator-= (v2& A, v2 B) { A.x -= B.x; A.y -= B.y; } +void operator-= (v3& A, v3 B) { A.x -= B.x; A.y -= B.y; A.z -= B.z; } +void operator-= (v4& A, v4 B) { A.x -= B.x; A.y -= B.y; A.z -= B.z; A.w -= B.w; } + +v2 operator* (v2 A, r32 B) { return { A.x * B, A.y * B }; } +v3 operator* (v3 A, r32 B) { return { A.x * B, A.y * B, A.z * B }; } +v4 operator* (v4 A, r32 B) { return { A.x * B, A.y * B, A.z * B, A.w * B }; } + +v2 operator/ (v2 A, r32 B) { return { A.x / B, A.y / B }; } +v3 operator/ (v3 A, r32 B) { return { A.x / B, A.y / B, A.z / B }; } +v4 operator/ (v4 A, r32 B) { return { A.x / B, A.y / B, A.z / B, A.w / B }; } + +void operator*= (v2& A, r32 B) { A.x *= B; A.y *= B; } +void operator*= (v3& A, r32 B) { A.x *= B; A.y *= B; A.z *= B; } +void operator*= (v4& A, r32 B) { A.x *= B; A.y *= B; A.z *= B; A.w *= B; } + +void operator/= (v2& A, r32 B) { A.x /= B; A.y /= B; } +void operator/= (v3& A, r32 B) { A.x /= B; A.y /= B; A.z /= B; } +void operator/= (v4& A, r32 B) { A.x /= B; A.y /= B; A.z /= B; A.w /= B; } + +bool operator == (v2 A, v2 B) { return ((A.x == B.x) && (A.y == B.y)); } +bool operator == (v3 A, v3 B) { return ((A.x == B.x) && (A.y == B.y) && (A.z == B.z)); } +bool operator == (v4 A, v4 B) { return ((A.x == B.x) && (A.y == B.y) && (A.z == B.z) && (A.w == B.w)); } + +bool operator != (v2 A, v2 B) { return !((A.x == B.x) && (A.y == B.y)); } +bool operator != (v3 A, v3 B) { return !((A.x == B.x) && (A.y == B.y) && (A.z == B.z)); } +bool operator != (v4 A, v4 B) { return !((A.x == B.x) && (A.y == B.y) && (A.z == B.z) && (A.w == B.w)); } + +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}; +} +#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 + +internal r32 V2MagSquared(v2 V) { return ((V.x * V.x) + (V.y * V.y)); } +internal r32 V3MagSquared(v3 V) { return ((V.x * V.x) + (V.y * V.y) + (V.z * V.z)); } +internal r32 V4MagSquared(v4 V) { return ((V.x * V.x) + (V.y * V.y) + (V.z * V.z) + (V.w * V.w)); } + +internal r32 V2Mag(v2 V) { return SqrtR32((V.x * V.x) + (V.y * V.y)); } +internal r32 V3Mag(v3 V) { return SqrtR32((V.x * V.x) + (V.y * V.y) + (V.z * V.z)); } +internal r32 V4Mag(v4 V) { return SqrtR32((V.x * V.x) + (V.y * V.y) + (V.z * V.z) + (V.w * V.w)); } + +internal r32 V2DistanceSquared(v2 A, v2 B) { return V2MagSquared(A - B); } +internal r32 V3DistanceSquared(v3 A, v3 B) { return V3MagSquared(A - B); } +internal r32 V4DistanceSquared(v4 A, v4 B) { return V4MagSquared(A - B); } + +internal r32 V2Distance(v2 A, v2 B) { return V2Mag(A - B); } +internal r32 V3Distance(v3 A, v3 B) { return V3Mag(A - B); } +internal r32 V4Distance(v4 A, v4 B) { return V4Mag(A - B); } + +internal v2 +V2Normalize(v2 A) +{ + r32 Magnitude = V2Mag(A); + return A / Magnitude; +} +internal v3 +V3Normalize(v3 A) +{ + r32 Magnitude = V3Mag(A); + return A / Magnitude; +} +internal v4 +V4Normalize(v4 A) +{ + r32 Magnitude = V4Mag(A); + return A / Magnitude; +} + +internal r32 V2Dot(v2 A, v2 B) { return ((A.x * B.x) + (A.y * B.y)); } +internal r32 V3Dot(v3 A, v3 B) { return ((A.x * B.x) + (A.y * B.y) + (A.z * B.z)); } +internal r32 V4Dot(v4 A, v4 B) { return ((A.x * B.x) + (A.y * B.y) + (A.z * B.z) + (A.w * B.w)); } + +internal v2 V2PerpendicularCW(v2 A) { return v2{A.y, -A.x}; } +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)); +} + +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; +} + +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; +} + +internal v2 +V2Lerp(v2 A, v2 B, r32 T) +{ + v2 Result = v2{ + LerpR32(A.x, B.x, T), + LerpR32(A.y, B.y, T), + }; + return Result; +} + +internal v3 +V3Lerp(v3 A, v3 B, r32 T) +{ + v3 Result = v3{ + LerpR32(A.x, B.x, T), + LerpR32(A.y, B.y, T), + LerpR32(A.z, B.z, T), + }; + return Result; +} + +internal v4 +V4Lerp(v4 A, v4 B, r32 T) +{ + v4 Result = v4{ + LerpR32(A.x, B.x, T), + LerpR32(A.y, B.y, T), + LerpR32(A.z, B.z, T), + LerpR32(A.w, B.w, T), + }; + 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; +} + +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; +} + +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; +} + +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; +} + +/////////////////////////// +// +// Ranges + +internal rect2 MakeRect2MinDim(v2 Min, v2 Dim) +{ + rect2 Result = {0}; + Result.Min = Min; + Result.Max = Min + Dim; + return Result; +} + +internal b32 ValueInRangeR32(r32 Min, r32 Max, r32 V) +{ + return ((V >= Min) && (V <= Max)); +} + +internal b32 ValueInRange1(range1 Range, r32 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)); +} +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)); +} +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)); +} + +#define PointIsInRect(range, point) ValueInRange2((range), (point)) + +internal r32 Range1SizeX(range1 Range) { return Range.Max - Range.Min; } +internal r32 Range2SizeX(range2 Range) { return Range.Max.x - Range.Min.x; } +internal r32 Range3SizeX(range3 Range) { return Range.Max.x - Range.Min.x; } +internal r32 Range4SizeX(range4 Range) { return Range.Max.x - Range.Min.x; } + +#define Rect2Width(r) Range2SizeX((r)) + +internal r32 Range2SizeY(range2 Range) { return Range.Max.y - Range.Min.y; } +internal r32 Range3SizeY(range3 Range) { return Range.Max.y - Range.Min.y; } +internal r32 Range4SizeY(range4 Range) { return Range.Max.y - Range.Min.y; } + +#define Rect2Height(r) Range2SizeY((r)) + +internal r32 Range3SizeZ(range3 Range) { return Range.Max.z - Range.Min.z; } +internal r32 Range4SizeZ(range4 Range) { return Range.Max.z - Range.Min.z; } + +internal r32 Range4SizeW(range4 Range) { return Range.Max.w - Range.Min.w; } + +internal r32 Range1Center(range1 Range) { return (Range.Max + Range.Min) / 2.0f; } +internal v2 Range2Center(range2 Range) { return (Range.Max + Range.Min) / 2.0f; } +internal v3 Range3Center(range3 Range) { return (Range.Max + Range.Min) / 2.0f; } +internal v4 Range4Center(range4 Range) { return (Range.Max + Range.Min) / 2.0f; } + +#define Rect2Center(r) Range2Center((r)) + +internal range1 Range1Offset(range1 Range, r32 Delta) { return range1{ Range.Min + Delta, Range.Max + Delta }; } +internal range2 Range2Offset(range2 Range, v2 Delta) { return range2{ Range.Min + Delta, Range.Max + Delta }; } +internal range3 Range3Offset(range3 Range, v3 Delta) { return range3{ Range.Min + Delta, Range.Max + Delta }; } +internal range4 Range4Offset(range4 Range, v4 Delta) { return range4{ Range.Min + Delta, Range.Max + Delta }; } + +#define Rect2Translate(r, d) Range2Offset((r), (d)) +#define Rect2TranslateX(r, dx) Range2Offset((r), v2{(dx), 0}) +#define Rect2TranslateY(r, dy) Range2Offset((r), v2{0, (dy)}) + +internal v2 RectTopLeft(rect2 Rect) +{ + return v2{ Rect.Min.x, Rect.Max.y }; +} +internal v2 RectTopRight(rect2 Rect) +{ + return Rect.Max; +} +internal v2 RectBottomLeft(rect2 Rect) +{ + return Rect.Min; +} +internal v2 RectBottomRight(rect2 Rect) +{ + return v2{ Rect.Max.x, Rect.Min.y }; +} + +internal r32 AspectRatio(r32 Width, r32 Height) { return Width / Height; } +internal r32 RectAspectRatio(rect2 Rect) { return Range2SizeX(Rect) / Range2SizeY(Rect); } + +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; +} +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 }; +} + +internal void +RectHSplitAtDistanceFromTop(rect2 Rect, r32 YDist, rect2* Top, rect2* 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); +} +internal void +RectVSplitAtDistanceFromRight(rect2 Rect, r32 XDist, rect2* Left, rect2* 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); +} +internal void +RectHSplitAtPercent(rect2 Rect, r32 YPercent, rect2* Top, rect2* 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); +} + +internal rect2 +RectInset(rect2 Outer, v2 Amount) +{ + rect2 Result = { Outer.Min + Amount, Outer.Max - Amount }; + return Result; +} +internal rect2 +RectInset(rect2 Outer, r32 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; +} +#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); + 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; +} + +internal v2 +Rect2GetRectLocalPoint(rect2 Rect, v2 Point) +{ + v2 Result = Point - Rect.Min; + return Result; +} + +/////////////////////////// +// +// Ray + +internal v4 +RayGetPointAlong(v4 RayOrigin, v4 RayDirection, r32 T) +{ + 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; +} + +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; +} +internal v4 +GetRayPlaneIntersectionPoint(v4_ray Ray, v4 PlanePoint, v4 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; +} +internal bool +RayIntersectsPlane(v4_ray Ray, v4 PlanePoint, v4 PlaneNormal, v4* OutPoint) +{ + return RayIntersectsPlane(Ray.Origin, Ray.Direction, PlanePoint, PlaneNormal, OutPoint); +} + +/////////////////////////// +// +// Matrices + +internal m44 +M44Identity() +{ + 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++) + { + for (u32 X = 0; X < 4; X++) + { + Result.Array[(X * 4) + Y] = M.Array[(Y * 4) + X]; + } + } + 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; +} + +// 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; +} + +internal m44 +M44Translation(v4 Offset) +{ + 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; +} + +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; +} + +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; +} + +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; +} + +internal m44 +M44Scale(v3 Scale) +{ + 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; +} + +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; +} + +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; +} + +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; +} + +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; +} + +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; +} + +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; +} + +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; +} + +/////////////////////////// +// +// Strings + +internal gs_const_string ConstString(char* Data, u64 Length) { return gs_const_string{Data, Length}; } +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; +} +internal gs_string MakeString(char* Data, u64 Length) +{ + return MakeString(Data, Length, Length); +} +internal gs_string MakeString(char* Data) +{ + u64 StringLength = CStringLength(Data); + return MakeString(Data, StringLength, StringLength); +} +internal gs_string MakeString(gs_const_string ConstString) +{ + 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; +} +internal gs_data StringToData(gs_string String) +{ + return StringToData(String.ConstString); +} + +internal bool IsSlash(char C) { return ((C == '/') || (C == '\\')); } +internal bool IsUpper(char C) { return(('A' <= C) && (C <= 'Z')); } +internal bool IsLower(char C) { return(('a' <= C) && (C <= 'z')); } +internal bool IsWhitespace(char C) { return (C == ' ' || C == '\n' || C == '\r' || C == '\t' || C == '\f' || C == '\v'); } +internal bool IsNewline(char C) { return (C == '\n') || (C == '\r'); } +internal bool IsNewlineOrWhitespace (char C) { return IsNewline(C) || IsWhitespace(C); } +internal bool IsBase8(char C) { return (C >= '0' && C <= '7'); } +internal bool IsBase10(char C) { return (C >= '0' && C <= '9'); } +internal bool IsBase16(char C) { return (C >= '0' && C <= '9') || (C >= 'A' && C <= 'F'); } +internal bool IsNumericDecimal(char C) { return IsBase10(C) || (C == '.'); } +internal bool IsNumericExtended(char C) { return IsNumericDecimal(C) || (C == 'x') || (C == 'f') || (C == '-'); } +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 == '>')); +} + +internal char +ToUpper(char 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; +} +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); +} + +internal bool +IsNullTerminated(gs_const_string String) +{ + return (String.Str[String.Length - 1] != 0); +} +internal bool +IsNullTerminated(gs_string String) +{ + 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; +} +internal char +GetChar(gs_string String, u64 I) +{ + 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; +} +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; +} +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; +} +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; +} +internal gs_const_string +GetStringBefore(gs_const_string String, u64 Cut) +{ + 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; +} +internal u64 +FindFirst(gs_const_string String, u64 StartIndex, char C) +{ + u64 Result = StartIndex; + for(; Result < String.Length && C != String.Str[Result]; Result++); + return Result; +} +internal u64 +FindFirst(gs_const_string String, char C) +{ + return FindFirst(String, 0, C); +} +internal u64 +FindLast(gs_const_string String, char C) +{ + s64 Result = String.Length - 1; + for(; Result >= 0 && C != String.Str[Result]; Result--); + return (u64)Result; +} +internal u64 +FindFirstFromSet(gs_const_string String, char* SetArray) +{ + gs_const_string Set = ConstString(SetArray); + u64 Result = String.Length - 1; + for(u64 At = 0; At < String.Length; At++) + { + char CharAt = String.Str[At]; + for (u64 SetAt = 0; SetAt < Set.Length; SetAt++) + { + if (CharAt == Set.Str[SetAt]) + { + Result = 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_last_from_set_complete; + } + } + } + find_last_from_set_complete: + return Result; +} + +internal u64 +FindLastFromSet(gs_const_string String, char* SetArray) +{ + gs_const_string Set = ConstString(SetArray); + u64 Result = String.Length - 1; + for(s64 At = Result; At >= 0; At--) + { + 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; + } + } + } + find_first_from_set_complete: + 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) + { + Result = true; + Length = Min(Length, A.Length); + for (u64 i = 0; i < Length; i++) + { + if (A.Str[i] != B.Str[i]) + { + Result = false; + break; + } + } + } + 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; +} +internal bool +StringEqualsCharArray(gs_const_string A, char* B, u64 Length) +{ + gs_const_string BStr = ConstString(B, Length); + return StringsEqual(A, BStr); +} +internal bool +StringsEqualUpToLength(gs_string A, gs_string B, u64 Length) +{ + return StringsEqualUpToLength(A.ConstString, B.ConstString, Length); +} +internal bool +StringsEqual(gs_string A, gs_string B) +{ + return StringsEqual(A.ConstString, B.ConstString); +} +internal bool +StringEqualsCharArray(gs_string A, char* B, u64 Length) +{ + gs_string BStr = MakeString(B, Length); + return StringsEqual(A, BStr); +} + +internal u64 +StringSizeLeft(gs_string String) +{ + 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++; + } +} + +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; +} +internal u64 +CharToUInt(char C, gs_const_string CharSet) +{ + return (u64)FindFirst(CharSet, C); +} +internal u64 +CharToUInt(char C) +{ + return (u64)CharToUInt(C, Base10Chars); +} +internal u64 +CharToUInt(char C, u64 Base) +{ + return CharToUInt(C, GetCharSetForBase(Base)); +} + +internal u64 +ParseUInt(gs_const_string String, u64 Base = 10, u64* ParsedLength = 0) +{ + u64 Result = 0; + gs_const_string CharSet = GetCharSetForBase(Base); + u64 i = 0; + for (; i < String.Length; i++) + { + u64 CharIndex = FindFirst(CharSet, String.Str[i]); + if (CharIndex < CharSet.Length) + { + Result = CharToUInt(String.Str[i], CharSet) + (Result * Base); + } + else + { + break; + } + } + if (ParsedLength != 0) + { + *ParsedLength = i; + } + return Result; +} +internal u64 +ParseUInt(u64 Length, char* String, u64 Base = 10, u64* ParsedLength = 0) +{ + return ParseUInt(ConstString(String, Length), Base, ParsedLength); +} +internal u64 +ParseUInt(char* String, u64 Base = 10, u64* ParsedLength = 0) +{ + 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; +} +internal s64 +ParseInt(char* String, u64 Base = 10, u64* ParsedLength = 0) +{ + return ParseInt(LitString(String), Base, ParsedLength); +} + +internal r64 +ParseFloat(gs_const_string String, u64* ParsedLength = 0) +{ + + u64 DecimalIndex = FindFirst(String, '.'); + u64 TempParsedLength = 0; + u64 PlacesAfterPoint = 0; + + gs_const_string IntegerString = GetStringBefore(String, DecimalIndex); + gs_const_string DecimalString = GetStringAfter(String, DecimalIndex + 1); + + r32 Polarity = 1; + if (IntegerString.Str[0] == '-') + { + IntegerString = GetStringAfter(IntegerString, 1); + Polarity = -1; + } + r64 Result = (r64)ParseInt(IntegerString, 10, &TempParsedLength); + + if (TempParsedLength == IntegerString.Length) + { + r64 AfterPoint = (r64)ParseUInt(DecimalString, 10, &PlacesAfterPoint); + r64 Decimal = (AfterPoint / PowR64(10, PlacesAfterPoint)); + Result = Result + Decimal; + Result *= Polarity; + } + + if (ParsedLength != 0) + { + *ParsedLength = TempParsedLength + PlacesAfterPoint; + if (DecimalIndex < String.Length) { *ParsedLength += 1; } + } + return Result; +} +internal r64 +ParseFloat(char* String, u64* ParsedLength = 0) +{ + 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; +} +internal u64 +AppendString(gs_string* Base, gs_string Appendix) +{ + return AppendString(Base, Appendix.ConstString); +} +internal void +NullTerminate(gs_string* String) +{ + 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; + } +} + +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); +} + +internal void +U64ToASCII(gs_string* String, u64 Value, u64 Base) +{ + U64ToASCII(String, Value, Base, GetCharSetForBase(Base)); +} + +internal void +R64ToASCII(gs_string* String, r64 Value, u64 Precision) +{ + 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++) + { + 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; +} + +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; +} + +internal r64 +ReadVarArgsFloat (s32 Width, va_list* Args) +{ + r64 Result = 0; + switch (Width) + { + case 4: { Result = (r64)va_arg(*Args, r64); } break; + case 8: { Result = (r64)va_arg(*Args, r64); } break; + InvalidDefaultCase; + } + return Result; +} + +internal s32 +PrintFArgsList (gs_string* String, char* Format, va_list Args) +{ + char* FormatAt = Format; + while (*FormatAt) + { + 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])) + { + // 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(String, (char)0); + FormatAt++; + } + else + { + 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; + 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 +PrintF (gs_string* String, char* Format, ...) +{ + 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); +} + +internal void +AppendPrintF (gs_string* String, char* Format, ...) +{ + 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); +} + +/////////////////////////// +// +// Memory + +internal gs_data +CreateData(u8* Memory, u64 Size) +{ + gs_data Result = {Memory, Size}; + return Result; +} +internal bool +DataIsNonEmpty(gs_data Data) +{ + 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 gs_data +AllocatorAlloc_(gs_allocator Allocator, u64 Size, char* Location) +{ + // TODO(Peter): Memory Profiling with Location + u64 SizeResult = 0; + void* Memory = Allocator.Alloc(Size, &SizeResult); + return CreateData((u8*)Memory, SizeResult); +} +internal void +AllocatorFree_(gs_allocator Allocator, void* Base, u64 Size, char* Location) +{ + // TODO(Peter): Memory Profiling with Location + if (Base != 0 && Size != 0) + { + Allocator.Free(Base, 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 + +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) +{ + // 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.Type = ArenaType; + Arena.Allocator = Allocator; + Arena.Parent = ParentArena; + Arena.MemoryChunkSize = ChunkSize; + Arena.MemoryAlignment = Alignment; + return Arena; +} + +internal gs_memory_arena +CreateMemoryArena(gs_allocator Allocator, u64 ChunkSize = KB(32), u64 Alignment = Bytes(8)) +{ + return CreateMemoryArena_(Arena_BaseArena, Allocator, ChunkSize, Alignment, 0); +} +internal gs_memory_arena +CreateMemorySubArena(gs_memory_arena* Parent, u64 ChunkSize = KB(32), u64 Alignment = Bytes(8)) +{ + return CreateMemoryArena_(Arena_SubArena, Parent->Allocator, ChunkSize, Alignment, Parent); +} + +internal gs_data PushSize_(gs_memory_arena* Arena, u64 Size, char* Location); + +internal void +FreeCursorList(gs_memory_cursor_list* List, gs_allocator Allocator) +{ + gs_memory_cursor_list* CursorAt = List; + while (CursorAt != 0) + { + gs_memory_cursor_list* Prev = CursorAt->Prev; + FreeCursorListEntry(Allocator, CursorAt); + CursorAt = Prev; + } +} + +internal gs_memory_cursor_list* +MemoryArenaNewCursor(gs_memory_arena* Arena, u64 MinSize, char* Location) +{ + // Allocate enough spcae for the minimum size needed + sizeo for the cursor list + u64 AllocSize = Max(MinSize, Arena->MemoryChunkSize) + sizeof(gs_memory_cursor_list); + + 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; + } + + // 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) + { + Arena->CursorList->Next = Result; + } + Arena->CursorList = Result; + return Result; +} + +internal gs_data +PushSize_(gs_memory_arena* Arena, u64 Size, char* Location) +{ + gs_data Result = {0}; + if (Size > 0) + { + 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); + } + } + Assert(CursorEntry != 0); + 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 +PopSize(gs_memory_arena* Arena, u64 Size) +{ + gs_allocator Allocator = Arena->Allocator; + gs_memory_cursor_list* CursorEntry = Arena->CursorList; + for (gs_memory_cursor_list* Prev = 0; + CursorEntry != 0 && Size != 0; + CursorEntry = Prev) + { + Prev = CursorEntry->Prev; + if (Size >= CursorEntry->Cursor.Position) + { + Size -= CursorEntry->Cursor.Position; + FreeCursorListEntry(Allocator, CursorEntry); + } + else + { + PopSizeOnCursor(&CursorEntry->Cursor, Size); + break; + } + } + Arena->CursorList = CursorEntry; +} +internal void +FreeMemoryArena(gs_memory_arena* Arena) +{ + gs_allocator Allocator = Arena->Allocator; + gs_memory_cursor_list* CursorEntry = Arena->CursorList; + for (gs_memory_cursor_list* Prev = 0; + CursorEntry != 0; + CursorEntry = Prev) + { + Prev = CursorEntry->Prev; + if (CursorEntry != 0) + { + FreeCursorListEntry(Allocator, CursorEntry); + } + } +} + +#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)); + +internal void +ClearArena(gs_memory_arena* Arena) +{ + 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; +} + +internal void +FreeArena(gs_memory_arena* Arena) +{ + FreeCursorList(Arena->CursorList, Arena->Allocator); +} + +/////////////////////////// +// +// Debug Print + +inline void +DebugPrint(debug_output Output, gs_const_string Message) +{ + Output.Print(Output, Message); +} + +inline void +DebugPrint(debug_output Output, char* Message) +{ + 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, 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, 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); +} + +#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 + +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); +} + +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 0 +// TODO: If you need a string builder come back here, otherwise this can stay 0'd out +// was getting in the way +internal void +StringBuilderWriteFArgsList(gs_string_builder* Builder, char* Format, va_list Args) +{ + char* FormatAt = Format; + while (*FormatAt) + { + 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])) + { + // 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; + } + 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); +} + +#endif // String builder + +/////////////////////////// +// +// File Handler + +internal u64 +FileHandlerGetFileInfo_NoOp(gs_file_handler FileHandler, gs_const_string Path) +{ + return 0; +} + +internal gs_file +FileHandlerReadFile_NoOp(gs_const_string Path) +{ + return gs_file{0}; +} + +internal bool +FileHandlerWriteFile_NoOp(gs_const_string Path, gs_data Data) +{ + return false; +} + +internal gs_const_string_array +FileHandlerEnumerateDirectory_NoOp(gs_const_string Path, bool Recursive, bool IncludeDirs) +{ + return gs_const_string_array{0}; +} + +internal gs_file_handler +CreateFileHandler(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) +{ + 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 NullTermPath = Path; + if (!IsNullTerminated(NullTermPath)) + { + AssertMessage("need to allocate a new string, Path to it, and null terminate"); + // TODO(Peter): Probably want to have some sort of temp memory, + // or be passing in a thread context, etc. + } + return NullTermPath; +} + +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; +} + +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; +} + +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; +} + +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); +} + +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); +} + +internal bool +FileNoError(gs_file File) +{ + bool Result = (File.Size > 0); + return Result; +} + +////////////////////////// +// +// Timing + +internal s64 +TimeHandlerGetWallClock(gs_time_handler TimeHandler) +{ + 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; +} + +/////////////////////////// +// +// Hashes + +internal u32 +HashDJB2ToU32(char* String) +{ + 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; +} + +internal u64 +HashDJB2ToU64(char* String) +{ + 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; +} + +/////////////////////////// +// +// Random Series + +internal gs_random_series +InitRandomSeries(u32 Seed) +{ + 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; +} + +internal r32 +NextRandomUnilateral(gs_random_series* Series) +{ + 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; +} + + +/////////////////////////// +// +// Sort + + +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++) + { + 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; + } + } + + 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++) + { + if (List->Radixes.Values[i] > Highest) + { + Highest = List->Radixes.Values[i]; + } + } + + u32 Iterations = 0; + while (Highest > 1) + { + ++Iterations; + Highest = Highest >> 1; + } + + RadixSortInPlace_(List, 0, List->Radixes.Count, Iterations); +} + + +/////////////////////////// +// +// Input + +inline bool +KeyIsMouseButton(gs_key Key) +{ + 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; +} +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; +} +inline bool +MouseButtonTransitionedDown(gs_mouse_state Mouse, gs_key Button) +{ + 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; +} +inline bool +MouseButtonIsDown(gs_mouse_state Mouse, gs_key Button) +{ + 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; +} +inline bool +MouseButtonTransitionedUp(gs_mouse_state Mouse, gs_key Button) +{ + 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; +} +inline bool +MouseButtonIsUp(gs_mouse_state Mouse, gs_key Button) +{ + 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; +} +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; +} +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; + } +} +internal void +AdvanceMouseButtonsState(gs_mouse_state* Mouse) +{ + AdvanceMouseButtonState(Mouse, gs_Key_MouseLeftButton); + AdvanceMouseButtonState(Mouse, gs_Key_MouseMiddleButton); + AdvanceMouseButtonState(Mouse, gs_Key_MouseRightButton); +} + +/////////////////////////// +// +// Network + + +static u32 +HostToNetU32(u32 In) +{ + unsigned char *s = (unsigned char *)&In; + u32 Result = (u32)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); + return Result; +} + +static u16 +HostToNetU16(u16 In) +{ + unsigned char *s = (unsigned char *)&In; + u16 Result = (u16)(s[0] << 8 | s[1]); + return Result; +} + + + + + + + + + + +#define GS_TYPES_CPP +#endif // GS_TYPES_CPP \ No newline at end of file diff --git a/src/gs_libs/gs_types.h b/src/gs_libs/gs_types.h new file mode 100644 index 0000000..8a9736e --- /dev/null +++ b/src/gs_libs/gs_types.h @@ -0,0 +1,1053 @@ +// +// File: gs_types.h +// Author: Peter Slattery +// Creation Date: 2020-04-18 +// +#ifndef GS_TYPES_H + +#if defined(__clang__) +# pragma GCC diagnostic ignored "-Wunused-value" +# pragma GCC diagnostic ignored "-Wvarargs" +# pragma GCC diagnostic ignored "-Wwritable-strings" +#endif + +#if defined(_MSC_VER) +# include +#endif + +// Someday, we home to remove these includes +#include +#if !defined(GUESS_INTS) +# include +#endif // !defined(GUESS_INTS) + +#include + +#define Glue_(a,b) a##b +#define Glue(a,b) Glue_(a,b) + +#define Stringify_(a) #a +#define Stringify(a) Stringify_(a) + +#define internal static +#define local_persist static +#define global static +#define local_const static const +#define global_const static const +#define external extern "C" + +#if defined(GUESS_INTS) +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long long s64; +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; +#else +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +#endif + +typedef s8 b8; +typedef s32 b32; +typedef s64 b64; + +typedef float r32; +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, +}; + +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), +}; + +internal u64 +BasicTypeSize(gs_basic_type Type) +{ + return gs_BasicTypeSizes[(u32)Type]; +} + +global_const u8 MaxU8 = 0xFF; +global_const u16 MaxU16 = 0xFFFF; +global_const u32 MaxU32 = 0xFFFFFFFF; +global_const u64 MaxU64 = 0xFFFFFFFFFFFFFFFF; + +global_const s8 MaxS8 = 127; +global_const s16 MaxS16 = 32767; +global_const s32 MaxS32 = 2147483647; +global_const s64 MaxS64 = 9223372036854775807; + +global_const s8 MinS8 = -127 - 1; +global_const s16 MinS16 = -32767 - 1; +global_const s32 MinS32 = -2147483647 - 1; +global_const s64 MinS64 = -9223372036854775807 - 1; + +global_const r32 MaxR32 = 3.402823466e+38f; +global_const r32 MinR32 = -MaxR32; +global_const r32 SmallestPositiveR32 = 1.1754943508e-38f; +global_const r32 EpsilonR32 = 5.96046448e-8f; + +global_const r32 PiR32 = 3.14159265359f; +global_const r32 HalfPiR32 = 1.5707963267f; +global_const r32 TauR32 = 6.28318530717f; + +global_const r64 MaxR64 = 1.79769313486231e+308; +global_const r64 MinR64 = -MaxR64; +global_const r64 SmallestPositiveR64 = 4.94065645841247e-324; +global_const r64 EpsilonR64 = 1.11022302462515650e-16; + +// TODO: va_start and va_arg replacements + +internal r32 +DegToRadR32(r32 Degrees) +{ + return (Degrees * (PiR32 / 180.0f)); +} + +internal r32 +RadToDegR32(r32 Radians) +{ + return (Radians * (180.0f / PiR32)); +} + +struct s8_array +{ + s8* Values; + u32 Count; + u32 CountMax; +}; + +struct s16_array +{ + s16* Values; + u32 Count; + u32 CountMax; +}; + +struct s32_array +{ + s32* Values; + u32 Count; + u32 CountMax; +}; + +struct s64_array +{ + s64* Values; + u32 Count; + u32 CountMax; +}; + +struct u8_array +{ + u8* Values; + u32 Count; + u32 CountMax; +}; + +struct u16_array +{ + u16* Values; + u32 Count; + u32 CountMax; +}; + +struct u32_array +{ + u32* Values; + u32 Count; + u32 CountMax; +}; + +struct u64_array +{ + u64* Values; + u32 Count; + u32 CountMax; +}; + + +#define PointerDifference(a,b) ((u8*)(a) - (u8*)(b)) +#define PointerToInt(a) PointerDifference(a, 0) +#define Member(type,member) (((type*)0)->member) +#define MemberOffset(type,member) PointerToInt(&Member(type,member)) + +// NOTE(Peter): Makes sure that s doesn't expand in some way that invalidates +// a nested if statement. +#define Statement(s) do{ s }while(0) + +// +// Asserts +// +// AssertAlways and AssertMessageAlways should be used sparingly, because they'll +// still assert in the final build +#define AssertBreak(m) (*((volatile s32*)0) = 0xFFFF) +#define AssertAlways(c) Statement( if (!(c)) { AssertBreak(c); } ) +#define AssertMessageAlways(m) AssertBreak(m) + +#if !SHIP_MODE +# define Assert(c) AssertAlways(c) +# define AssertMessage(m) AssertBreak(m) +# define InvalidDefaultCase default: { AssertBreak("invalid default case"); } break; +# define StaticAssert(c) \ +enum { \ +Glue(gs_AssertFail_, __LINE__) = 1 / (int)(!!(c)), \ +} +#else +# define Assert(c) +# define AssertMessage(m) +# define InvalidDefaultCase default: {} break; +# define StaticAssert(c) +#endif + +#define AssertImplies(a,b) Statement(if(a) { Assert(b); }) +#define InvalidCodePath AssertMessage("invalid code path") +#define NotImplemented AssertMessage("not implemented") +#define DontCompile ImAfraidICantDoThat + +#define LineNumberString Stringify(__LINE__) +#define FileNameAndLineNumberString_ __FILE__ ":" LineNumberString ":" +#define FileNameAndLineNumberString (char*)FileNameAndLineNumberString_ + +// + +#define Bytes(x) (x) +#define KB(x) ((x) << 10) +#define MB(x) ((x) << 20) +#define GB(x) ((x) << 30) +#define TB(x) (((u64)x) << 40) + +#define HasFlag(data, flag) (((data) & (flag)) != 0) +#define HasFlagOnly(data, flag) (((data) & (flag)) == (data)) +#define AddFlag(data, flag) ((data) |= (flag)) +#define RemoveFlag(data, flag) ((data) &= (~(flag))) + +#define Max(a,b) (((a) > (b)) ? (a) : (b)) +#define Min(a,b) (((a) > (b)) ? (b) : (a)) +#define Clamp_(a,x,b) ((x < a) ? a : ((x > b) ? b : x)) +#define Clamp(a,x,b) Clamp_((a), (x), (b)) +#define Clamp01(x) Clamp_(0.0f, (x), 1.0f) +#define Abs(x) (((x) < 0) ? ((x) * -1) : x) +#define Sign(x) ((x) < 0) ? -1 : 1; +#define IsPowerOfTwo(x) (((x) & ((x) - 1)) == 0) +#define IsOdd(x) (((x) & 1) != 0) + +internal void +ZeroMemory_(u8* Memory, u64 Size) +{ + 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]; + } +} + +#define StaticArrayLength(arr) sizeof(arr) / sizeof((arr)[0]) +#define ZeroMemoryBlock(mem,size) ZeroMemory_((u8*)(mem), (size)) +#define ZeroStruct(str) ZeroMemory_((str), sizeof(str)) +#define ZeroArray(arr, type, count) ZeroMemory_((u8*)(arr), sizeof(type) * (count)) + +#define CopyArray(from, to, type, count) CopyMemory_((u8*)(from), (u8*)(to), sizeof(type) * (count)) +#define CopyMemoryTo(from, to, size) CopyMemory_((u8*)(from), (u8*)(to), (size)) +// Singly Linked List Utilities + +#define SLLPush_(list_tail,new_ele) list_tail->Next = new_ele, list_tail = new_ele +#define SLLPush(list_tail,new_ele) (SLLPush_((list_tail), (new_ele))) + +#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 SLLInit(head,tail,first_ele) head=first_ele, tail=first_ele; + +#define SLLPushOrInit(first,last,new_ele) \ +if (last) { SLLPush(last, new_ele); } \ +else { SLLInit(first,last,new_ele); } + +// Vectors + +union v2 +{ + 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]; +}; + +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 v4_ray +{ + v4 Origin; + v4 Direction; +}; + +#define WhiteV4 v4{1, 1, 1, 1} +#define BlackV4 v4{0, 0, 0, 1} +#define RedV4 v4{1, 0, 0, 1} +#define GreenV4 v4{0, 1, 0, 1} +#define BlueV4 v4{0, 0, 1, 1} +#define YellowV4 v4{1, 1, 0, 1} +#define TealV4 v4{0, 1, 1, 1} +#define PinkV4 v4{1, 0, 1, 1} + +#define V2Expand(v) v.x, v.y +#define V3Expand(v) v.x, v.y, v.z +#define V4Expand(v) v.x, v.y, v.z, v.w + +struct v2_array +{ + v2* Vectors; + u32 Count; + u32 CountMax; +}; + +struct v3_array +{ + v3* Vectors; + u32 Count; + u32 CountMax; +}; + +struct v4_array +{ + v4* Vectors; + u32 Count; + u32 CountMax; +}; + +struct range1 +{ + r32 Min; + r32 Max; +}; + +struct range2 +{ + v2 Min; + v2 Max; +}; +typedef range2 rect2; + +struct range3 +{ + v3 Min; + v3 Max; +}; + +struct range4 +{ + v4 Min; + v4 Max; +}; + +struct range1_array +{ + range1* Ranges; + u32 Count; + u32 CountMax; +}; + +struct range2_array +{ + range2* Ranges; + u32 Count; + u32 CountMax; +}; + +struct range3_array +{ + range3* Ranges; + u32 Count; + u32 CountMax; +}; + +struct range4_array +{ + range4* Ranges; + u32 Count; + u32 CountMax; +}; + +#define Range1Expand(r) (r).Min, (r).Max +#define Range2Expand(r) (r).Min, (r).Max +#define Rect2Expand(r) (r).Min (r).Max +#define Range3Expand(r) (r).Min, (r).Max +#define Range4Expand(r) (r).Min, (r).Max + +// Matrices +// NOTE(Peter): All matrices are stored in row major order + +union m33 +{ + 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; + }; +}; + +struct m33_array +{ + m33* Matrices; + u32 Count; + u32 CountMax; +}; + +struct m44_array +{ + m44* Matrices; + u32 Count; + u32 CountMax; +}; + +////////////////////////// +// +// Strings + +struct gs_const_string +{ + union + { + char* Str; + u8* Data;; + }; + u64 Length; +}; + +struct gs_string +{ + union + { + gs_const_string ConstString; + struct + { + char* Str; + u64 Length; + }; + }; + u64 Size; +}; + +struct gs_const_string_array +{ + gs_const_string* Strings; + u64 Count; + u64 Used; +}; + +struct gs_string_array +{ + gs_string* Strings; + u64 Count; + u64 CountMax; +}; + +internal u64 +CStringLength(char* Str) +{ + char* At = Str; + while (*At) { At++; } + return PointerDifference(At, Str); +} + +#define StringExpand(str) (int)(str).Length, (str).Str +#define LitString(cstr) gs_const_string{(char*)(cstr), CStringLength((char*)cstr) } + +// The index of the character in these arrays corresponds to its value as a number in +// the relevant base, so you can do FindFirst on them with a char to get the int value +// ie. 3 is at index 3 in Base10Chars. +// ie. C is at index 12 in Base16Chars. +global_const gs_const_string Base8Chars = LitString("01234567"); +global_const gs_const_string Base10Chars = LitString("0123456789"); +global_const gs_const_string Base16Chars = LitString("0123456789ABCDEF"); + +////////////////////////// +// +// Thread Context + +typedef struct gs_thread_context gs_thread_context; + +////////////////////////// +// +// Memory + +struct gs_data +{ + u8* Memory; + u64 Size; +}; + +struct gs_data_array +{ + 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, +}; + +typedef s32 gs_scan_direction; +enum +{ + 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); + +struct gs_allocator +{ + allocator_allocate* Alloc; + allocator_free* Free; +}; + +struct gs_memory_cursor +{ + gs_data Data; + u64 Position; +}; + +struct gs_memory_cursor_list +{ + gs_memory_cursor Cursor; + gs_memory_cursor_list* Next; + gs_memory_cursor_list* Prev; +}; + +enum arena_type +{ + Arena_BaseArena, + Arena_SubArena, +}; + +struct gs_memory_arena +{ + arena_type Type; + gs_allocator Allocator; + gs_memory_arena* Parent; + + gs_memory_cursor_list* CursorList; + u64 MemoryChunkSize; + u64 MemoryAlignment; +}; + +struct gs_memory_arena_array +{ + gs_memory_arena* Arenas; + u32 Count; + u32 Size; +}; + +/////////////////////////////// +// +// String Builder +// + +struct gs_string_builder_buffer +{ + 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; +}; + +/////////////////////////////// +// +// Debug Output +// + +typedef struct debug_output debug_output; + +#define DEBUG_PRINT(name) void name(debug_output Output, gs_const_string Message) +typedef DEBUG_PRINT(debug_print); + +struct debug_output +{ + gs_memory_arena* Storage; + debug_print* Print; +}; + +/////////////////////////////// +// +// Dynamic Array +// +// I like having constant lookup times, along with growable arrays. :) +// NOTE(Peter): If you're using this, you probably want to write a Get +// procedure to auto cast the result to the type you want. I'm even providing a +// debug check for you to make sure that you're requesting a size that matches +// the ElementSize for extra safety. + +struct gs_dynarray_buffer +{ + u8* Memory; +}; + +struct gs_dynarray +{ + gs_memory_arena Arena; + + gs_dynarray_buffer* Buffers; + u64 BuffersCount; + u64 ElementCount; + + u64 ElementSize; + u64 ElementsPerBuffer; +}; + +struct gs_dynarray_handle +{ + 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; +}; + +/////////////////////////////// +// +// File IO + +// TODO(Peter): Error Handling Thought +// The gs_file_handler, gs_allocator, etc should contain pointers to a central error buffer +// where errors can be logged + +enum enumerate_directory_flag +{ + 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; +}; + +struct gs_file_info_array +{ + gs_file_info* Values; + u32 Count; + u32 MaxCount; +}; + +struct gs_file +{ + union + { + gs_data Data; + struct + { + u8* Memory; + u64 Size; + }; + }; + gs_file_info FileInfo; +}; + +typedef struct gs_file_handler gs_file_handler; + +#define GET_FILE_INFO(name) gs_file_info name(gs_file_handler FileHandler, gs_const_string Path) +typedef GET_FILE_INFO(file_handler_get_file_info); + +#define READ_ENTIRE_FILE(name) gs_file name(gs_file_handler FileHandler, gs_const_string Path, gs_data Memory) +typedef READ_ENTIRE_FILE(file_handler_read_entire_file); + +#define WRITE_ENTIRE_FILE(name) bool name(gs_file_handler FileHandler, gs_const_string Path, gs_data Data) +typedef WRITE_ENTIRE_FILE(file_handler_write_entire_file); + +#define ENUMERATE_DIRECTORY(name) gs_file_info_array name(gs_file_handler FileHandler, gs_memory_arena* Storage, gs_const_string Path, u32 Flags) +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; +}; + + +////////////////////////// +// +// Timing + +#define GET_WALL_CLOCK(name) s64 name() +typedef GET_WALL_CLOCK(get_wall_clock); + +#define GET_SECONDS_ELAPSED(name) r64 name(u64 StartCycles, u64 EndCycles) +typedef GET_SECONDS_ELAPSED(get_seconds_elapsed); + +struct gs_time_handler +{ + get_wall_clock* GetWallClock; + get_seconds_elapsed* GetSecondsElapsed; +}; + +/////////////////////////////// +// +// Random + +struct gs_random_series +{ + u32 Value; +}; + +/////////////////////////////// +// +// Sort + +struct gs_radix_list +{ + u64_array Radixes; + u64_array IDs; +}; + + +/////////////////////////////// +// +// Mouse/Keyboard Input + +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, +}; + +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, +}; + +enum gs_modifier_key_flags +{ + 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; +}; + +struct gs_input_event_buffer +{ + gs_input_event* Values; + u32 Count; + u32 MaxCount; +}; + +struct gs_mouse_state +{ + v2 Position; + b32 ButtonStates[3]; + v2 DownPosition; +}; + +#define MouseButton_IsDownBit 0 +#define MouseButton_WasDownBit 1 +#define MouseButton_IsDown 1 +#define MouseButton_IsNotDown 0 +#define MouseButton_WasDown 1 +#define MouseButton_WasNotDown 0 + +////////////////////////// +// +// Thread Context + +struct gs_thread_info +{ + 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; +}; + +// Threads & Work Queue + +typedef struct gs_work_queue gs_work_queue; + +struct gs_worker_thread +{ + gs_thread_context Context; + gs_work_queue* Queue; + b32 ShouldExit; +}; + +#define THREAD_PROC(name) void name(gs_thread_context Context, gs_data Data) +typedef THREAD_PROC(thread_proc); + +struct gs_threaded_job +{ + 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) +typedef PUSH_WORK_ON_QUEUE(push_work_on_queue); + +#define COMPLETE_QUEUE_WORK(name) void name(gs_work_queue* Queue, gs_thread_context Context) +typedef COMPLETE_QUEUE_WORK(complete_queue_work); + +#define RESET_WORK_QUEUE(name) void name(gs_work_queue* Queue) +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; + reset_work_queue* ResetWorkQueue; +}; + +#define GS_TYPES_H +#endif // GS_TYPES_H \ No newline at end of file diff --git a/src/gs_libs/gs_vector_matrix.h b/src/gs_libs/gs_vector_matrix.h index 1f187bc..c089100 100644 --- a/src/gs_libs/gs_vector_matrix.h +++ b/src/gs_libs/gs_vector_matrix.h @@ -105,25 +105,12 @@ union v4 union m33 { - struct - { - float a; float b; float c; - float d; float e; float f; - float g; float h; float i; - }; - float E[9]; + float E[3][3]; }; union m44 { - struct - { - float a; float b; float c; float d; - float e; float f; float g; float h; - float i; float j; float k; float l; - float m; float n; float o; float p; - }; - float E[16]; + float E[4][4]; }; ////////////////////////////////////// @@ -648,10 +635,10 @@ PointIsInRange (v2 _P, v2 _Min, v2 _Max) static bool PointIsInRangeSafe (v2 _P, v2 _Min, v2 _Max) { - s32 MinX = GSMin(_Min.x, _Max.x); - s32 MinY = GSMin(_Min.y, _Max.y); - s32 MaxX = GSMax(_Min.x, _Max.x); - s32 MaxY = GSMax(_Min.y, _Max.y); + s32 MinX = Min(_Min.x, _Max.x); + s32 MinY = Min(_Min.y, _Max.y); + s32 MaxX = Max(_Min.x, _Max.x); + s32 MaxY = Max(_Min.y, _Max.y); return (_P.x >= MinX && _P.x <= MaxX && _P.y >= MinY && _P.y <= MaxY); @@ -1438,11 +1425,11 @@ void TestVectorMatrixMultiplication () // Utility Functions TestClean((GSSqrt(4.f) == 2.f), "Vector Square Root"); - TestClean((GSLerp(0.f, 1.f, .5f) == .5f), "Vector Lerp"); - TestClean((GSMin(-.25f, 5.f) == -.25f), "Vector Min"); - TestClean((GSMax(-.25f, 5.f) == 5.f), "Vector Max"); - TestClean((GSClamp(-2.f, -3.f, 5.f) == -2.f), "Vector Clamp, Lower Than Range"); - TestClean((GSClamp(-2.f, 6.f, 5.f) == 5.f), "Vector Clamp, Higher Than Range"); + TestClean((Lerp(0.f, 1.f, .5f) == .5f), "Vector Lerp"); + TestClean((Min(-.25f, 5.f) == -.25f), "Vector Min"); + TestClean((Max(-.25f, 5.f) == 5.f), "Vector Max"); + TestClean((Clamp(-2.f, -3.f, 5.f) == -2.f), "Vector Clamp, Lower Than Range"); + TestClean((Clamp(-2.f, 6.f, 5.f) == 5.f), "Vector Clamp, Higher Than Range"); ////////////////////////////// // Vector Functions diff --git a/src/gs_libs/gs_win32.cpp b/src/gs_libs/gs_win32.cpp index e2df025..b96ae2e 100644 --- a/src/gs_libs/gs_win32.cpp +++ b/src/gs_libs/gs_win32.cpp @@ -27,7 +27,7 @@ struct window char* ClassName; s32 Width; s32 Height; - WNDPROC WindowEventHandler; + WNDPROC WindowEventHandler; WNDCLASS Class; HWND Handle; @@ -45,7 +45,7 @@ struct handle_window_msg_result #endif }; -global_variable win32_state GlobalWin32State; +global win32_state GlobalWin32State; // Utility internal s32 Win32StringLength(char* String); @@ -66,15 +66,14 @@ internal void Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer // Memory -internal PLATFORM_ALLOC(Win32Alloc); -internal PLATFORM_FREE(Win32Free); -internal PLATFORM_REALLOC(Win32Realloc); +internal ALLOCATOR_ALLOC(Win32Alloc); +internal ALLOCATOR_FREE(Win32Free); /// // Utils /// -internal s32 +internal s32 Win32StringLength(char* String) { char* At = String; @@ -82,7 +81,7 @@ Win32StringLength(char* String) return At - String; } -internal s32 +internal s32 Win32ConcatStrings(s32 ALength, char* A, s32 BLength, char* B, s32 DestLength, char* Dest) { char* Dst = Dest; @@ -110,7 +109,7 @@ Win32ConcatStrings(s32 ALength, char* A, s32 BLength, char* B, s32 DestLength, c /// internal window -Win32CreateWindow (HINSTANCE HInstance, char* WindowName, s32 Width, s32 Height, +Win32CreateWindow (HINSTANCE HInstance, char* WindowName, s32 Width, s32 Height, WNDPROC WindowEventHandler) { window Result = {}; @@ -131,14 +130,14 @@ Win32CreateWindow (HINSTANCE HInstance, char* WindowName, s32 Width, s32 Height, Result.Handle = CreateWindowEx( 0, Result.Class.lpszClassName, - WindowName, + WindowName, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, 0, - 0, + 0, HInstance, 0); Result.DeviceContext = GetDC(Result.Handle); @@ -276,9 +275,9 @@ Win32HandleWindowsEvents ( ) { handle_window_event_result EventResult = HandleWindowEventUnlessWouldUseDefault( - WindowHandle, - Msg, - wParam, + WindowHandle, + Msg, + wParam, lParam); if (!EventResult.Handled) @@ -298,92 +297,92 @@ Win32GetKeyCode (int Win32VirtualKey, bool NumpadValid, bool TranslateToChar) if (!TranslateToChar) { - if (Win32VirtualKey == VK_SPACE) { Result = KeyCode_Space; } + 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_LSHIFT) { Result = KeyCode_LeftShift; } else if (Win32VirtualKey == VK_RSHIFT) { Result = KeyCode_RightShift; } - else if (Win32VirtualKey == VK_LCONTROL) { Result = KeyCode_LeftCtrl; } + 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_) { Result = KeyCode_Fn; } - else if (Win32VirtualKey == VK_MENU) { Result = KeyCode_Alt; } - else if (Win32VirtualKey == VK_PRIOR) { Result = KeyCode_PageUp; } + 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_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_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; } + 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; } + 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 == 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 == 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 == 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; } + 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; } } @@ -501,14 +500,14 @@ HandleWindowsMessage ( // 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 + // 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); + printf("Translated Char Not Recognized: %c\n", TranslatedChar); } */ }break; @@ -570,14 +569,14 @@ Win32DisplayBufferInWindow(win32_offscreen_buffer* Win32Buffer, window Window) } ///////////////////////////////////////// -// +// // Open GL // ///////////////////////////////////////// -internal void -OpenGLRenderTriBuffer (u8* Vertecies, s32 VertexElements, +internal void +OpenGLRenderTriBuffer (u8* Vertecies, s32 VertexElements, u8* UVs, s32 UVElements, u8* Colors, s32 ColorsElements, s32 TriCount) @@ -599,7 +598,7 @@ OpenGLRenderTriBuffer (u8* Vertecies, s32 VertexElements, } internal void -OpenGLDraw3DTri (v4 P0, v4 P1, v4 P2, +OpenGLDraw3DTri (v4 P0, v4 P1, v4 P2, v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { @@ -621,7 +620,7 @@ OpenGLDraw3DTri (v4 P0, v4 P1, v4 P2, } internal void -OpenGLDraw2DTri (v2 P0, v2 P1, v2 P2, +OpenGLDraw2DTri (v2 P0, v2 P1, v2 P2, v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { @@ -668,14 +667,14 @@ SubmitTexture (u8* Memory, s32 Width, s32 Height) { s32 TextureHandle = NextTextureHandle++; glBindTexture(GL_TEXTURE_2D, TextureHandle); - glTexImage2D(GL_TEXTURE_2D, + glTexImage2D(GL_TEXTURE_2D, 0, // mip map level - GL_RGBA8, - Width, - Height, + GL_RGBA8, + Width, + Height, 0, // border - GL_RGBA, - GL_UNSIGNED_BYTE, + GL_RGBA, + GL_UNSIGNED_BYTE, Memory); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/src/meta/foldhaus_meta.cpp b/src/meta/foldhaus_meta.cpp index 3206405..47eb1a1 100644 --- a/src/meta/foldhaus_meta.cpp +++ b/src/meta/foldhaus_meta.cpp @@ -12,7 +12,7 @@ internal void GenerateNodeMetaInfo (gsm_code_generator* NodeTypeGen, string_builder* NodeSpecificationGen, string_builder* CallNodeProcGen, gs_meta_preprocessor Meta) { // TODO(Peter): Create a FilterTypesByTag function to create a contiguous array - // of type_definition** + // of type_definition** WriteF(NodeSpecificationGen, "static node_specification_ NodeSpecifications[] = {\n"); @@ -218,8 +218,8 @@ GeneratePanelMetaInfo(gs_meta_preprocessor Meta, string_builder* PanelEnumGen, s } WriteF(PanelEnumGen, "enum panel_type {\n"); - WriteF(PanelCodeGen, "global_variable s32 GlobalPanelDefsCount = %d;\n", Panels.Used); - WriteF(PanelCodeGen, "global_variable panel_definition GlobalPanelDefs[] = {\n"); + WriteF(PanelCodeGen, "global s32 GlobalPanelDefsCount = %d;\n", Panels.Used); + WriteF(PanelCodeGen, "global panel_definition GlobalPanelDefs[] = {\n"); for (u32 i = 0; i < Panels.Used; i++) { panel_elements* Panel = Panels.GetElementAtIndex(i); diff --git a/src/meta/gs_meta_error.h b/src/meta/gs_meta_error.h index 2648959..f4f1c68 100644 --- a/src/meta/gs_meta_error.h +++ b/src/meta/gs_meta_error.h @@ -14,13 +14,32 @@ struct errors u32 Used; }; -internal void +#define ErrorReallocArray(base, type, oldcount, newcount) (type*)ErrorRealloc_((u8*)(base), (u64)(sizeof(type) * oldcount), (u64)(sizeof(type) * newcount)) +internal u8* +ErrorRealloc_(u8* Base, u64 OldSize, u64 NewSize) +{ + Assert(NewSize > 0); + u8* Result = (u8*)malloc(NewSize); + if (Base != 0 && OldSize > 0) + { + GSMemCopy(Base, Result, OldSize); + free(Base); + } + return Result; +} + +internal void PushFError (errors* Errors, char* Format, ...) { if (Errors->Used >= (Errors->BuffersCount * ERROR_BUFFER_SIZE)) { +#if 0 Errors->BuffersCount += 1; Errors->Buffers = (error_buffer*)realloc(Errors->Buffers, sizeof(error_buffer*) * Errors->BuffersCount); +#else + Errors->Buffers = ErrorReallocArray(Errors->Buffers, error_buffer, Errors->BuffersCount, Errors->BuffersCount + 1); + Errors->BuffersCount += 1; +#endif error_buffer* NewBuffer = Errors->Buffers + (Errors->BuffersCount - 1); NewBuffer->Backbuffer = (char*)malloc(sizeof(char) * ERROR_MAX_LENGTH * ERROR_BUFFER_SIZE); @@ -28,8 +47,8 @@ PushFError (errors* Errors, char* Format, ...) for (u32 i = 0; i < ERROR_BUFFER_SIZE; i++) { - NewBuffer->Contents[i].Memory = NewBuffer->Backbuffer + (i * ERROR_MAX_LENGTH); - NewBuffer->Contents[i].Max = ERROR_MAX_LENGTH; + NewBuffer->Contents[i].Str = NewBuffer->Backbuffer + (i * ERROR_MAX_LENGTH); + NewBuffer->Contents[i].Size = ERROR_MAX_LENGTH; NewBuffer->Contents[i].Length = 0; } } diff --git a/src/meta/gs_meta_lexer.h b/src/meta/gs_meta_lexer.h index 557f245..60e6647 100644 --- a/src/meta/gs_meta_lexer.h +++ b/src/meta/gs_meta_lexer.h @@ -1,7 +1,7 @@ struct token_selection_spec { b32 MatchText; - string Text; + gs_string Text; }; internal s32 @@ -59,7 +59,7 @@ EatIdentifier (tokenizer* Tokenizer) { s32 Length = 0; - while (Tokenizer->At[0] && + while (Tokenizer->At[0] && (IsAlpha(Tokenizer->At[0]) || IsNumericExtended(Tokenizer->At[0]))) { ++Tokenizer->At; @@ -135,7 +135,7 @@ GetNextToken (tokenizer* Tokenizer) char C = Tokenizer->At[0]; ++Tokenizer->At; - if (C == 0) { Result.Type = Token_EndOfStream; } + if (C == 0) { Result.Type = Token_EndOfStream; } else if (C == '(') { Result.Type = Token_LeftParen; } else if (C == ')') { Result.Type = Token_RightParen; } else if (C == '[') { Result.Type = Token_LeftSquareBracket; } @@ -145,9 +145,9 @@ GetNextToken (tokenizer* Tokenizer) else if (C == ';') { Result.Type = Token_Semicolon; } else if (C == ',') { Result.Type = Token_Comma; } else if (C == '.') { Result.Type = Token_Period; } - else if (C == '-' && Tokenizer->At[0] && Tokenizer->At[0] == '>') - { - Result.Type = Token_PointerReference; + else if (C == '-' && Tokenizer->At[0] && Tokenizer->At[0] == '>') + { + Result.Type = Token_PointerReference; Result.Text.Length = 2; ++Tokenizer->At; } @@ -157,72 +157,72 @@ GetNextToken (tokenizer* Tokenizer) EatWhitespace(Tokenizer); if (TokenAtEquals(Tokenizer, "define")) - { - Result.Type = Token_PoundDefine; + { + Result.Type = Token_PoundDefine; EatPreprocessor(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "undef")) - { - Result.Type = Token_PoundUndef; + { + Result.Type = Token_PoundUndef; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "include")) - { - Result.Type = Token_PoundInclude; - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + { + Result.Type = Token_PoundInclude; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "ifdef")) - { - Result.Type = Token_PoundIfDef; + { + Result.Type = Token_PoundIfDef; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "ifndef")) - { - Result.Type = Token_PoundIfNDef; + { + Result.Type = Token_PoundIfNDef; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "if")) - { - Result.Type = Token_PoundIf; + { + Result.Type = Token_PoundIf; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "elif")) - { - Result.Type = Token_PoundElif; + { + Result.Type = Token_PoundElif; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "else")) - { - Result.Type = Token_PoundElse; + { + Result.Type = Token_PoundElse; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "endif")) - { - Result.Type = Token_PoundEndif; + { + Result.Type = Token_PoundEndif; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "error")) - { - Result.Type = Token_PoundError; + { + Result.Type = Token_PoundError; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "pragma")) - { - Result.Type = Token_PoundPragma; + { + Result.Type = Token_PoundPragma; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } } - else if (IsNumeric(C)) + else if (IsNumericExtended(C)) { Result.Type = Token_Number; @@ -233,7 +233,7 @@ GetNextToken (tokenizer* Tokenizer) else if (C == '\'') { Result.Type = Token_Char; - Result.Text.Memory = Tokenizer->At; + Result.Text.Str = Tokenizer->At; if (Tokenizer->At[0] && Tokenizer->At[0] == '\\') { ++Tokenizer->At; @@ -245,7 +245,7 @@ GetNextToken (tokenizer* Tokenizer) { Result.Type = Token_String; // replace the length added by the quote - Result.Text.Memory = Tokenizer->At; + Result.Text.Str = Tokenizer->At; Result.Text.Length = EatString(Tokenizer); } // NOTE(Peter): This is after comment parsing so that the division operator diff --git a/src/meta/gs_meta_type_table.h b/src/meta/gs_meta_type_table.h index 3eb2140..d0d32d9 100644 --- a/src/meta/gs_meta_type_table.h +++ b/src/meta/gs_meta_type_table.h @@ -10,7 +10,7 @@ enum type_definition_type TypeDef_Invalid, // NOTE(Peter): tokens with this type require fixup later - TypeDef_Unknown, + TypeDef_Unknown, TypeDef_Enum, TypeDef_Struct, TypeDef_Union, @@ -59,7 +59,7 @@ struct meta_tag struct variable_decl { - // NOTE(Peter): Because of the way the tokenizer works, we don't lex and parse + // NOTE(Peter): Because of the way the tokenizer works, we don't lex and parse // at the same time. This means that not all types will be able to be matched // up on the first pass through. A TypeIndex of -1 means we need to fixup that // type at a later time @@ -161,7 +161,7 @@ HashIdentifier(string Identifier) u32 IdentHash = HashString(Identifier); if (IdentHash == 0) { - // NOTE(Peter): We are excluding a has of zero so taht + // NOTE(Peter): We are excluding a has of zero so taht // the type_table_handle where BucketIndex and IndexInBucket // are both zero is an invalid handle IdentHash += 1; @@ -301,7 +301,7 @@ FindSlotForTypeIdentifier(u32 IdentHash, type_table* TypeTable) Result.IndexInBucket = Index; } - // NOTE(Peter): Because we are growing the hashtable, this should never be an invalid + // NOTE(Peter): Because we are growing the hashtable, this should never be an invalid // type handle Assert(TypeHandleIsValid(Result)); return Result; @@ -391,7 +391,7 @@ PushMetaTagOnTable(meta_tag Tag, type_table* TypeTable) } // Guaranteed to return a valid result -internal type_definition* +internal type_definition* GetTypeDefinition(type_table_handle Handle, type_table TypeTable) { Assert(TypeHandleIsValid(Handle)); @@ -404,7 +404,7 @@ GetTypeDefinition(type_table_handle Handle, type_table TypeTable) } // May return zero -internal type_definition* +internal type_definition* GetTypeDefinitionUnsafe(type_table_handle Handle, type_table TypeTable) { type_definition* Result = 0; @@ -426,7 +426,7 @@ GetMetaTag(type_table_handle Handle, type_table TypeTable) return Result; } -internal type_definition* +internal type_definition* GetTypeDefinition(string Identifier, type_table TypeTable) { type_definition* Result = 0; @@ -588,21 +588,21 @@ internal void FixupStructMember (variable_decl* Member, type_definition* MemberTypeDef, type_table TypeTable, errors* Errors) { // NOTE(Peter): There are a lot of cases where struct members which are pointers - // to other structs cause interesting behavior here. + // to other structs cause interesting behavior here. // For example: // struct foo { foo* Next; } // could cause infinite loops if we try and fixup all structs with a size of 0 - // which would happen in this case, because we wouldn't have parsed foo's size + // which would happen in this case, because we wouldn't have parsed foo's size // yet, but would begin fixing up foo because of the type of Next // Another example: // typedef struct bar bar; // struct foo { bar* Bar; } // struct bar { foo* Foo; } - // causes the exact same problem, but we cant detect it by just excluding - // fixing up StructIndex recursively. - // + // causes the exact same problem, but we cant detect it by just excluding + // fixing up StructIndex recursively. + // // TL;DR - // The solution I've chosen to go with is just exclude all pointer members from + // The solution I've chosen to go with is just exclude all pointer members from // causing recursive fixups. Those types should be fixed up at some point in the // process, and we already know how big a pointer is in memory, no matter the type if (!Member->Pointer) @@ -617,7 +617,7 @@ FixupStructMember (variable_decl* Member, type_definition* MemberTypeDef, type_t { FixUpUnionSize(Member->TypeHandle, TypeTable, Errors); } - else + else { if (MemberTypeDef->Type == TypeDef_Unknown) { @@ -672,7 +672,7 @@ FixUpStructSize (type_table_handle TypeHandle, type_table TypeTable, errors* Err { // NOTE(Peter): Because its recursive (it makes sure all type sizes become known // if it needs them) we should never get to the end of this function and not have - // the ability to tell how big something is. + // the ability to tell how big something is. // TODO(Peter): We don't parse all types yet however, so for now, this is just an alert, // not an assert; #if 0 From 62e22979f362c4cdbe231741a66e0c20d21ecf12 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 18 Jul 2020 12:27:36 -0700 Subject: [PATCH 13/43] Separated out the engine from the editor. --- build/build_app_msvc_win32_debug.bat | 2 +- src/app/{ => deprecated}/foldhaus_node.cpp | 0 src/app/{ => deprecated}/foldhaus_node.h | 0 src/app/{ => deprecated}/foldhaus_node_gui.h | 0 ...oldhaus_util_radialumia_file_converter.cpp | 0 .../{ => editor}/foldhaus_command_dispatch.h | 0 src/app/{ => editor}/foldhaus_interface.cpp | 0 .../{ => editor}/foldhaus_operation_mode.h | 0 src/app/{ => editor}/foldhaus_panel.h | 0 .../foldhaus_panel_animation_timeline.h | 0 .../panels/foldhaus_panel_dmx_view.h | 0 .../panels/foldhaus_panel_file_view.h | 0 .../panels/foldhaus_panel_hierarchy.h | 0 .../panels/foldhaus_panel_profiler.h | 0 .../panels/foldhaus_panel_sculpture_view.h | 0 .../animation/foldhaus_animation.h | 0 src/app/{ => engine}/artnet/artnet.h | 0 src/app/{ => engine}/assembly_parser.cpp | 0 src/app/{ => engine}/dmx/dmx.h | 0 src/app/{ => engine}/foldhaus_assembly.cpp | 0 src/app/{ => engine}/foldhaus_assembly.h | 0 .../{ => engine}/foldhaus_network_ordering.h | 0 src/app/{ => engine}/sacn/sacn.h | 0 src/app/first.cpp | 28 --------- src/app/foldhaus_app.cpp | 7 +-- src/app/foldhaus_app.h | 61 +++++++++---------- src/app/foldhaus_debug.h | 3 + src/app/{ => platform_osx}/gs_osx.mm | 0 src/app/{ => platform_osx}/gs_osx_fileio.mm | 0 src/app/{ => platform_osx}/gs_osx_lib.mm | 0 src/app/{ => platform_osx}/gs_osx_memory.mm | 0 src/app/{ => platform_osx}/gs_osx_opengl.mm | 0 src/app/{ => platform_osx}/gs_osx_time.mm | 0 src/app/{ => platform_osx}/gs_osx_window.mm | 0 .../{ => platform_win32}/win32_foldhaus.cpp | 8 +-- .../{ => platform_win32}/win32_foldhaus_dll.h | 0 .../win32_foldhaus_fileio.h | 0 .../win32_foldhaus_memory.h | 0 .../win32_foldhaus_timing.h | 0 39 files changed, 37 insertions(+), 72 deletions(-) rename src/app/{ => deprecated}/foldhaus_node.cpp (100%) rename src/app/{ => deprecated}/foldhaus_node.h (100%) rename src/app/{ => deprecated}/foldhaus_node_gui.h (100%) rename src/app/{ => deprecated}/foldhaus_util_radialumia_file_converter.cpp (100%) rename src/app/{ => editor}/foldhaus_command_dispatch.h (100%) rename src/app/{ => editor}/foldhaus_interface.cpp (100%) rename src/app/{ => editor}/foldhaus_operation_mode.h (100%) rename src/app/{ => editor}/foldhaus_panel.h (100%) rename src/app/{ => editor}/panels/foldhaus_panel_animation_timeline.h (100%) rename src/app/{ => editor}/panels/foldhaus_panel_dmx_view.h (100%) rename src/app/{ => editor}/panels/foldhaus_panel_file_view.h (100%) rename src/app/{ => editor}/panels/foldhaus_panel_hierarchy.h (100%) rename src/app/{ => editor}/panels/foldhaus_panel_profiler.h (100%) rename src/app/{ => editor}/panels/foldhaus_panel_sculpture_view.h (100%) rename src/app/{ => engine}/animation/foldhaus_animation.h (100%) rename src/app/{ => engine}/artnet/artnet.h (100%) rename src/app/{ => engine}/assembly_parser.cpp (100%) rename src/app/{ => engine}/dmx/dmx.h (100%) rename src/app/{ => engine}/foldhaus_assembly.cpp (100%) rename src/app/{ => engine}/foldhaus_assembly.h (100%) rename src/app/{ => engine}/foldhaus_network_ordering.h (100%) rename src/app/{ => engine}/sacn/sacn.h (100%) delete mode 100644 src/app/first.cpp rename src/app/{ => platform_osx}/gs_osx.mm (100%) rename src/app/{ => platform_osx}/gs_osx_fileio.mm (100%) rename src/app/{ => platform_osx}/gs_osx_lib.mm (100%) rename src/app/{ => platform_osx}/gs_osx_memory.mm (100%) rename src/app/{ => platform_osx}/gs_osx_opengl.mm (100%) rename src/app/{ => platform_osx}/gs_osx_time.mm (100%) rename src/app/{ => platform_osx}/gs_osx_window.mm (100%) rename src/app/{ => platform_win32}/win32_foldhaus.cpp (99%) rename src/app/{ => platform_win32}/win32_foldhaus_dll.h (100%) rename src/app/{ => platform_win32}/win32_foldhaus_fileio.h (100%) rename src/app/{ => platform_win32}/win32_foldhaus_memory.h (100%) rename src/app/{ => platform_win32}/win32_foldhaus_timing.h (100%) diff --git a/build/build_app_msvc_win32_debug.bat b/build/build_app_msvc_win32_debug.bat index 6151e16..1a4c884 100644 --- a/build/build_app_msvc_win32_debug.bat +++ b/build/build_app_msvc_win32_debug.bat @@ -25,7 +25,7 @@ set LastError=%ERRORLEVEL% del lock.tmp -cl %CommonCompilerFlags% %SourceCodePath%\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib +cl %CommonCompilerFlags% %SourceCodePath%\platform_win32\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib popd diff --git a/src/app/foldhaus_node.cpp b/src/app/deprecated/foldhaus_node.cpp similarity index 100% rename from src/app/foldhaus_node.cpp rename to src/app/deprecated/foldhaus_node.cpp diff --git a/src/app/foldhaus_node.h b/src/app/deprecated/foldhaus_node.h similarity index 100% rename from src/app/foldhaus_node.h rename to src/app/deprecated/foldhaus_node.h diff --git a/src/app/foldhaus_node_gui.h b/src/app/deprecated/foldhaus_node_gui.h similarity index 100% rename from src/app/foldhaus_node_gui.h rename to src/app/deprecated/foldhaus_node_gui.h diff --git a/src/app/foldhaus_util_radialumia_file_converter.cpp b/src/app/deprecated/foldhaus_util_radialumia_file_converter.cpp similarity index 100% rename from src/app/foldhaus_util_radialumia_file_converter.cpp rename to src/app/deprecated/foldhaus_util_radialumia_file_converter.cpp diff --git a/src/app/foldhaus_command_dispatch.h b/src/app/editor/foldhaus_command_dispatch.h similarity index 100% rename from src/app/foldhaus_command_dispatch.h rename to src/app/editor/foldhaus_command_dispatch.h diff --git a/src/app/foldhaus_interface.cpp b/src/app/editor/foldhaus_interface.cpp similarity index 100% rename from src/app/foldhaus_interface.cpp rename to src/app/editor/foldhaus_interface.cpp diff --git a/src/app/foldhaus_operation_mode.h b/src/app/editor/foldhaus_operation_mode.h similarity index 100% rename from src/app/foldhaus_operation_mode.h rename to src/app/editor/foldhaus_operation_mode.h diff --git a/src/app/foldhaus_panel.h b/src/app/editor/foldhaus_panel.h similarity index 100% rename from src/app/foldhaus_panel.h rename to src/app/editor/foldhaus_panel.h diff --git a/src/app/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h similarity index 100% rename from src/app/panels/foldhaus_panel_animation_timeline.h rename to src/app/editor/panels/foldhaus_panel_animation_timeline.h diff --git a/src/app/panels/foldhaus_panel_dmx_view.h b/src/app/editor/panels/foldhaus_panel_dmx_view.h similarity index 100% rename from src/app/panels/foldhaus_panel_dmx_view.h rename to src/app/editor/panels/foldhaus_panel_dmx_view.h diff --git a/src/app/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h similarity index 100% rename from src/app/panels/foldhaus_panel_file_view.h rename to src/app/editor/panels/foldhaus_panel_file_view.h diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/editor/panels/foldhaus_panel_hierarchy.h similarity index 100% rename from src/app/panels/foldhaus_panel_hierarchy.h rename to src/app/editor/panels/foldhaus_panel_hierarchy.h diff --git a/src/app/panels/foldhaus_panel_profiler.h b/src/app/editor/panels/foldhaus_panel_profiler.h similarity index 100% rename from src/app/panels/foldhaus_panel_profiler.h rename to src/app/editor/panels/foldhaus_panel_profiler.h diff --git a/src/app/panels/foldhaus_panel_sculpture_view.h b/src/app/editor/panels/foldhaus_panel_sculpture_view.h similarity index 100% rename from src/app/panels/foldhaus_panel_sculpture_view.h rename to src/app/editor/panels/foldhaus_panel_sculpture_view.h diff --git a/src/app/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h similarity index 100% rename from src/app/animation/foldhaus_animation.h rename to src/app/engine/animation/foldhaus_animation.h diff --git a/src/app/artnet/artnet.h b/src/app/engine/artnet/artnet.h similarity index 100% rename from src/app/artnet/artnet.h rename to src/app/engine/artnet/artnet.h diff --git a/src/app/assembly_parser.cpp b/src/app/engine/assembly_parser.cpp similarity index 100% rename from src/app/assembly_parser.cpp rename to src/app/engine/assembly_parser.cpp diff --git a/src/app/dmx/dmx.h b/src/app/engine/dmx/dmx.h similarity index 100% rename from src/app/dmx/dmx.h rename to src/app/engine/dmx/dmx.h diff --git a/src/app/foldhaus_assembly.cpp b/src/app/engine/foldhaus_assembly.cpp similarity index 100% rename from src/app/foldhaus_assembly.cpp rename to src/app/engine/foldhaus_assembly.cpp diff --git a/src/app/foldhaus_assembly.h b/src/app/engine/foldhaus_assembly.h similarity index 100% rename from src/app/foldhaus_assembly.h rename to src/app/engine/foldhaus_assembly.h diff --git a/src/app/foldhaus_network_ordering.h b/src/app/engine/foldhaus_network_ordering.h similarity index 100% rename from src/app/foldhaus_network_ordering.h rename to src/app/engine/foldhaus_network_ordering.h diff --git a/src/app/sacn/sacn.h b/src/app/engine/sacn/sacn.h similarity index 100% rename from src/app/sacn/sacn.h rename to src/app/engine/sacn/sacn.h diff --git a/src/app/first.cpp b/src/app/first.cpp deleted file mode 100644 index 3501ced..0000000 --- a/src/app/first.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include - -#include -#include - -typedef struct AppDel { - Class isa; - id window; -} AppDelegate; - -BOOL AppDel_didFinishLaunching(AppDelegate* self, SEL _command, id Notification) -{ - return YES; -} - -int main(int ArgCount, char** Args) -{ - Class NSApplicationClass = (Class)objc_getClass("NSApplication"); - Class AppDelegateClass = objc_allocateClassPair(NSApplicationClass, "AppDelegate", 0); - - SEL MethodSelector = sel_getUid("applicationDidFinishLaunching:"); - // NOTE(Peter): i = int, @ = object, : = method selector (SEL) - char MethodSignature[] = "i@:@"; - class_addMethod(AppDelegateClass, MethodSelector, (IMP)AppDel_didFinishLaunching, "i@:@"); - objc_registerClassPair(AppDelegateClass); - - return 0; -} \ No newline at end of file diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 5d05907..866f278 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -141,7 +141,6 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Interface.Style.RowHeight = ui_GetTextLineHeight(State->Interface); State->SACN = InitializeSACN(Context); - State->NetworkProtocolHeaderSize = STREAM_HEADER_SIZE; State->Camera.FieldOfView = 45.0f; State->Camera.AspectRatio = RectAspectRatio(State->WindowBounds); @@ -294,9 +293,6 @@ CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, } -#define HANDMADE_MATH_IMPLEMENTATION -#include "handmade_math.h" - UPDATE_AND_RENDER(UpdateAndRender) { DEBUG_TRACK_FUNCTION; @@ -440,12 +436,11 @@ UPDATE_AND_RENDER(UpdateAndRender) // Skipped for performance at the moment #if 0 - s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; for (u32 i = 0; i < State->Assemblies.Count; i++) { assembly* Assembly = &State->Assemblies.Values[i]; - dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, &State->LedSystem, HeaderSize, &State->Transient); + dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, &State->LedSystem, STREAM_HEADER_SIZE, &State->Transient); DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); } diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index cadf625..f01b555 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -13,24 +13,24 @@ #include "interface.h" -#include "foldhaus_network_ordering.h" -#include "dmx/dmx.h" -#include "sacn/sacn.h" +#include "engine/foldhaus_network_ordering.h" +#include "engine/dmx/dmx.h" +#include "engine/sacn/sacn.h" -#include "foldhaus_assembly.h" -#include "assembly_parser.cpp" +#include "engine/foldhaus_assembly.h" +#include "engine/assembly_parser.cpp" typedef struct app_state app_state; // TODO(Peter): something we can do later is to remove all reliance on app_state and context // from foldhaus_pane.h. It should just emit lists of things that the app can iterate over and // perform operations on, like panel_draw_requests = { bounds, panel* } etc. -#include "foldhaus_panel.h" +#include "editor/foldhaus_panel.h" -#include "foldhaus_command_dispatch.h" -#include "foldhaus_operation_mode.h" +#include "editor/foldhaus_command_dispatch.h" +#include "editor/foldhaus_operation_mode.h" -#include "animation/foldhaus_animation.h" +#include "engine/animation/foldhaus_animation.h" enum network_protocol { @@ -42,38 +42,33 @@ enum network_protocol struct app_state { - r32 CameraTheta; // TODO(Peter): @TEMPORARY - rect2 WindowBounds; - gs_memory_arena Permanent; gs_memory_arena Transient; - s32 NetworkProtocolHeaderSize; + // Engine + // network_protocol NetworkProtocol; - streaming_acn SACN; - led_system LedSystem; assembly_array Assemblies; + animation_system AnimationSystem; + event_log* GlobalLog; - camera Camera; - r32 PixelsToWorldScale; + // Interface + // + rect2 WindowBounds; operation_mode_system Modes; input_command_queue CommandQueue; ui_interface Interface; - - animation_system AnimationSystem; - gs_list_handle SelectedAnimationBlockHandle; - u32 SelectedAnimationLayer; - panel_system PanelSystem; panel* HotPanel; - //pattern_node_workspace NodeWorkspace; - - event_log* GlobalLog; + camera Camera; // TODO(Peter): move into the sculpture view + r32 PixelsToWorldScale; + gs_list_handle SelectedAnimationBlockHandle; // TODO(Peter): move into animation panel + u32 SelectedAnimationLayer; // TODO(Peter): move into animation panel }; internal void OpenColorPicker(app_state* State, v4* Address); @@ -180,7 +175,7 @@ TestPatternThree(led_buffer* Assembly, r32 Time) // END TEMPORARY PATTERNS -#include "foldhaus_assembly.cpp" +#include "engine/foldhaus_assembly.cpp" FOLDHAUS_INPUT_COMMAND_PROC(EndCurrentOperationMode) { @@ -208,16 +203,16 @@ struct panel_definition s32 InputCommandsCount; }; -#include "panels/foldhaus_panel_sculpture_view.h" -#include "panels/foldhaus_panel_profiler.h" -#include "panels/foldhaus_panel_dmx_view.h" -#include "panels/foldhaus_panel_animation_timeline.h" -#include "panels/foldhaus_panel_hierarchy.h" -#include "panels/foldhaus_panel_file_view.h" +#include "editor/panels/foldhaus_panel_sculpture_view.h" +#include "editor/panels/foldhaus_panel_profiler.h" +#include "editor/panels/foldhaus_panel_dmx_view.h" +#include "editor/panels/foldhaus_panel_animation_timeline.h" +#include "editor/panels/foldhaus_panel_hierarchy.h" +#include "editor/panels/foldhaus_panel_file_view.h" #include "generated/foldhaus_panels_generated.h" -#include "foldhaus_interface.cpp" +#include "editor/foldhaus_interface.cpp" #include "../meta/gs_meta_include.cpp" diff --git a/src/app/foldhaus_debug.h b/src/app/foldhaus_debug.h index c45ad69..ca26188 100644 --- a/src/app/foldhaus_debug.h +++ b/src/app/foldhaus_debug.h @@ -3,6 +3,9 @@ // Author: Peter Slattery // Creation Date: 2020-01-01 // +// DESCRIPTION: +// This file contains profiling capabilities for both the engine and app +// #ifndef FOLDHAUS_DEBUG_H #define SCOPE_NAME_LENGTH 256 diff --git a/src/app/gs_osx.mm b/src/app/platform_osx/gs_osx.mm similarity index 100% rename from src/app/gs_osx.mm rename to src/app/platform_osx/gs_osx.mm diff --git a/src/app/gs_osx_fileio.mm b/src/app/platform_osx/gs_osx_fileio.mm similarity index 100% rename from src/app/gs_osx_fileio.mm rename to src/app/platform_osx/gs_osx_fileio.mm diff --git a/src/app/gs_osx_lib.mm b/src/app/platform_osx/gs_osx_lib.mm similarity index 100% rename from src/app/gs_osx_lib.mm rename to src/app/platform_osx/gs_osx_lib.mm diff --git a/src/app/gs_osx_memory.mm b/src/app/platform_osx/gs_osx_memory.mm similarity index 100% rename from src/app/gs_osx_memory.mm rename to src/app/platform_osx/gs_osx_memory.mm diff --git a/src/app/gs_osx_opengl.mm b/src/app/platform_osx/gs_osx_opengl.mm similarity index 100% rename from src/app/gs_osx_opengl.mm rename to src/app/platform_osx/gs_osx_opengl.mm diff --git a/src/app/gs_osx_time.mm b/src/app/platform_osx/gs_osx_time.mm similarity index 100% rename from src/app/gs_osx_time.mm rename to src/app/platform_osx/gs_osx_time.mm diff --git a/src/app/gs_osx_window.mm b/src/app/platform_osx/gs_osx_window.mm similarity index 100% rename from src/app/gs_osx_window.mm rename to src/app/platform_osx/gs_osx_window.mm diff --git a/src/app/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp similarity index 99% rename from src/app/win32_foldhaus.cpp rename to src/app/platform_win32/win32_foldhaus.cpp index 65df438..8712d14 100644 --- a/src/app/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -11,15 +11,15 @@ #include #include -#include "../meta/gs_meta_include.h" -#include "foldhaus_platform.h" +#include "../../meta/gs_meta_include.h" +#include "../foldhaus_platform.h" -#include "../gs_libs/gs_win32.cpp" +#include "../../gs_libs/gs_win32.cpp" #include "win32_foldhaus_memory.h" #include "win32_foldhaus_dll.h" #include "win32_foldhaus_timing.h" -#include "foldhaus_renderer.cpp" +#include "../foldhaus_renderer.cpp" global b32 Running = false; global b32 WindowIsActive = false; diff --git a/src/app/win32_foldhaus_dll.h b/src/app/platform_win32/win32_foldhaus_dll.h similarity index 100% rename from src/app/win32_foldhaus_dll.h rename to src/app/platform_win32/win32_foldhaus_dll.h diff --git a/src/app/win32_foldhaus_fileio.h b/src/app/platform_win32/win32_foldhaus_fileio.h similarity index 100% rename from src/app/win32_foldhaus_fileio.h rename to src/app/platform_win32/win32_foldhaus_fileio.h diff --git a/src/app/win32_foldhaus_memory.h b/src/app/platform_win32/win32_foldhaus_memory.h similarity index 100% rename from src/app/win32_foldhaus_memory.h rename to src/app/platform_win32/win32_foldhaus_memory.h diff --git a/src/app/win32_foldhaus_timing.h b/src/app/platform_win32/win32_foldhaus_timing.h similarity index 100% rename from src/app/win32_foldhaus_timing.h rename to src/app/platform_win32/win32_foldhaus_timing.h From 078f4e3ed7f6fb52432bc2c4d56d6acb025c8867 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 18 Jul 2020 12:59:57 -0700 Subject: [PATCH 14/43] Fixed the sculpture view. --- .../panels/foldhaus_panel_sculpture_view.h | 88 ++++++------------- src/app/foldhaus_renderer.h | 1 + 2 files changed, 28 insertions(+), 61 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_sculpture_view.h b/src/app/editor/panels/foldhaus_panel_sculpture_view.h index b9a31af..415886d 100644 --- a/src/app/editor/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/editor/panels/foldhaus_panel_sculpture_view.h @@ -81,56 +81,46 @@ struct draw_leds_job_data }; internal void -DrawLEDsInBufferRangeJob (gs_thread_context Context, gs_data JobData) +DrawLedsInBuffer(led_buffer LedBuffer, s32 StartIndex, s32 OnePastLastIndex, render_quad_batch_constructor* Batch, quad_batch_constructor_reserved_range ReservedRange, r32 LedHalfWidth) { - DEBUG_TRACK_FUNCTION; - - draw_leds_job_data* Data = (draw_leds_job_data*)JobData.Memory; - - s32 LEDCount = Data->OnePastLastIndex - Data->StartIndex; - -#if 0 - // TODO(Peter): Why are we doing this here? Shouldn't we be able to tell what the range - // needs to be at the time of creation? That way its all on one thread and we're not - // worried about locking up. - quad_batch_constructor_reserved_range BatchReservedRange = ThreadSafeReserveRangeInQuadConstructor(Data->Batch, LEDCount * 2); -#endif - s32 TrisUsed = 0; - r32 HalfWidth = Data->LEDHalfWidth; - - v4 P0_In = v4{-HalfWidth, -HalfWidth, 0, 1}; - v4 P1_In = v4{HalfWidth, -HalfWidth, 0, 1}; - v4 P2_In = v4{HalfWidth, HalfWidth, 0, 1}; - v4 P3_In = v4{-HalfWidth, HalfWidth, 0, 1}; + 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}; - for (s32 LedIndex = Data->StartIndex; LedIndex < Data->OnePastLastIndex; LedIndex++) + Assert(OnePastLastIndex <= (s32)LedBuffer.LedCount); + for (s32 LedIndex = StartIndex; LedIndex < OnePastLastIndex; LedIndex++) { - pixel PixelColor = Data->LedBuffer.Colors[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 = Data->LedBuffer.Positions[LedIndex]; - m44 FaceCameraMatrix = M44LookAt(Position, Data->CameraPosition); + 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; - v4 P0 = (FaceCameraMatrix * P0_In) + PositionOffset; - v4 P1 = (FaceCameraMatrix * P1_In) + PositionOffset; - v4 P2 = (FaceCameraMatrix * P2_In) + PositionOffset; - v4 P3 = (FaceCameraMatrix * P3_In) + PositionOffset; - - SetTri3DInBatch(Data->Batch, Data->BatchReservedRange.Start + TrisUsed++, - P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); - SetTri3DInBatch(Data->Batch, Data->BatchReservedRange.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); +} + internal void DrawQuad(render_command_buffer* RenderBuffer, v4 C, r32 Rad, v4 Color) { @@ -147,13 +137,6 @@ internal void SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { DEBUG_TRACK_SCOPE(RenderSculpture); - - // TODO(Peter): @MajorFix - // NOTE(Peter): Just returning from this function to make sure that this isn't a problem as I go and try to fix - // the other panels - return; - - State->Camera.AspectRatio = RectAspectRatio(PanelBounds); PushRenderPerspective(RenderBuffer, PanelBounds, State->Camera); @@ -168,7 +151,6 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, BufferIndex); u32 JobsNeeded = U32DivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); -#if 1 u32 NextLEDIndex = 0; for (u32 Job = 0; Job < JobsNeeded; Job++) { @@ -181,30 +163,14 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend JobData->Batch = &RenderLEDsBatch; JobData->BatchReservedRange = ReserveRangeInQuadConstructor(JobData->Batch, JobLedCount * 2); JobData->LEDHalfWidth = .5f; - JobData->CameraPosition = ToV4Point(State->Camera.Position); - +#if 1 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); +#endif NextLEDIndex = JobData->OnePastLastIndex; } -#else - 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 = 0; - JobData->OnePastLastIndex = LedBuffer->LedCount; - s32 JobLedCount = JobData->OnePastLastIndex - JobData->StartIndex; - JobData->Batch = &RenderLEDsBatch; - JobData->BatchReservedRange = ReserveRangeInQuadConstructor(JobData->Batch, JobLedCount * 2); - JobData->LEDHalfWidth = .5f; - - JobData->CameraPosition = ToV4Point(State->Camera.Position); - - Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, (thread_proc*)DrawLEDsInBufferRangeJob, Data, ConstString("Sculpture Draw LEDS")); -#endif - - u32 f = 0; } // TODO(Peter): I don't like the fact that setting an orthographic view inside a panel render function diff --git a/src/app/foldhaus_renderer.h b/src/app/foldhaus_renderer.h index d563cf8..e316c71 100644 --- a/src/app/foldhaus_renderer.h +++ b/src/app/foldhaus_renderer.h @@ -327,6 +327,7 @@ ReserveRangeInQuadConstructor(render_quad_batch_constructor* Constructor, s32 Tr { quad_batch_constructor_reserved_range Result = {}; Result.OnePastLast = Constructor->Count + TrisNeeded; + Constructor->Count = Result.OnePastLast; Result.Start = Result.OnePastLast - TrisNeeded; return Result; } From 7c134774c3fe3b0ad786b9012e5ab5a22fa81285 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 18 Jul 2020 13:08:28 -0700 Subject: [PATCH 15/43] sculpture view cleanup --- src/app/editor/panels/foldhaus_panel_sculpture_view.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_sculpture_view.h b/src/app/editor/panels/foldhaus_panel_sculpture_view.h index 415886d..8ac383a 100644 --- a/src/app/editor/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/editor/panels/foldhaus_panel_sculpture_view.h @@ -150,7 +150,6 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend { led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, BufferIndex); u32 JobsNeeded = U32DivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); - u32 NextLEDIndex = 0; for (u32 Job = 0; Job < JobsNeeded; Job++) { @@ -177,7 +176,6 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend // 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]; @@ -198,7 +196,6 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend v2 BoxMax = LedOnScreenPosition + BoxHalfDim; PushRenderBoundingBox2D(RenderBuffer, BoxMin, BoxMax, 2.0f, TealV4); } - Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext); } From 1db836890f4ab253a794aaa044a13f674ee39517 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sun, 6 Sep 2020 20:33:28 -0700 Subject: [PATCH 16/43] Cleaned up world -> panel space conversion --- .../panels/foldhaus_panel_sculpture_view.h | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_sculpture_view.h b/src/app/editor/panels/foldhaus_panel_sculpture_view.h index 8ac383a..56d9ff0 100644 --- a/src/app/editor/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/editor/panels/foldhaus_panel_sculpture_view.h @@ -131,6 +131,28 @@ DrawQuad(render_command_buffer* RenderBuffer, v4 C, r32 Rad, v4 Color) 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; +} + GSMetaTag(panel_render); GSMetaTag(panel_type_sculpture_view); internal void @@ -183,14 +205,13 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend //__debugbreak(); v4 LedPosition = LedBuffer->Positions[FocusPixel]; - m44 Matrix = GetCameraPerspectiveProjectionMatrix(State->Camera) * GetCameraModelViewMatrix(State->Camera); - v4 LedProjectedPosition = Matrix * LedPosition; - v2 LedOnScreenPosition = LedProjectedPosition.xy; + v2 LedOnScreenPosition = SculptureView_WorldToScreenPosition(LedPosition, State->Camera, PanelBounds); gs_string Tempgs_string = PushString(&State->Transient, 256); PrintF(&Tempgs_string, "%f %f", LedOnScreenPosition.x, LedOnScreenPosition.y); DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4); + v2 BoxHalfDim = v2{ 25, 25 }; v2 BoxMin = LedOnScreenPosition - BoxHalfDim; v2 BoxMax = LedOnScreenPosition + BoxHalfDim; From 337b4ac271a2a36bc95dd8de5df5df31c49d92ef Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sun, 6 Sep 2020 21:10:36 -0700 Subject: [PATCH 17/43] Implemented tag based filtering of led strips --- src/app/engine/animation/foldhaus_animation.h | 2 +- src/app/engine/foldhaus_assembly.cpp | 39 ++++++++++++ src/app/engine/foldhaus_assembly.h | 7 +++ src/app/foldhaus_app.cpp | 8 +-- src/app/foldhaus_app.h | 59 +++++++++++++------ 5 files changed, 91 insertions(+), 24 deletions(-) diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 613a940..98a5c08 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -5,7 +5,7 @@ // #ifndef FOLDHAUS_ANIMATION -#define ANIMATION_PROC(name) void name(led_buffer* Assembly, r32 Time) +#define ANIMATION_PROC(name) void name(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) typedef ANIMATION_PROC(animation_proc); struct frame_range diff --git a/src/app/engine/foldhaus_assembly.cpp b/src/app/engine/foldhaus_assembly.cpp index 0d7ae9a..c01d44f 100644 --- a/src/app/engine/foldhaus_assembly.cpp +++ b/src/app/engine/foldhaus_assembly.cpp @@ -154,6 +154,45 @@ UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context) State->Assemblies.Values[AssemblyIndex] = State->Assemblies.Values[LastAssemblyIndex]; } +// Querying Assemblies + +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) + { + ValueHash = HashDJB2ToU32(StringExpand(TagValue)); + } + + for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++) + { + v2_strip StripAt = Assembly.Strips[StripIndex]; + for (u32 j = 0; j < StripAt.TagsCount; j++) + { + v2_tag TagAt = StripAt.Tags[j]; + 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.StripIndices[Result.Count++] = StripIndex; + } + } + } + } + + return Result; +} #define FOLDHAUS_ASSEMBLY_CPP #endif // FOLDHAUS_ASSEMBLY_CPP \ No newline at end of file diff --git a/src/app/engine/foldhaus_assembly.h b/src/app/engine/foldhaus_assembly.h index 7b47451..6005b4a 100644 --- a/src/app/engine/foldhaus_assembly.h +++ b/src/app/engine/foldhaus_assembly.h @@ -60,6 +60,13 @@ struct v2_strip v2_tag* Tags; }; +struct led_strip_list +{ + u32 Count; + u32 CountMax; + u32* StripIndices; +}; + struct assembly { gs_memory_arena Arena; diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 866f278..1e4f33b 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -153,7 +153,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->LedSystem = LedSystemInitialize(Context.ThreadContext.Allocator, 128); #if 1 - gs_const_string SculpturePath = ConstString("data/radialumia_v2.fold"); + gs_const_string SculpturePath = ConstString("data/blumen_lumen_v2.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, SculpturePath, State->GlobalLog); #endif @@ -364,17 +364,17 @@ UPDATE_AND_RENDER(UpdateAndRender) { case 1: { - TestPatternOne(&LayerLEDBuffers[Layer], SecondsIntoBlock); + TestPatternOne(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, &State->Transient); }break; case 2: { - TestPatternTwo(&LayerLEDBuffers[Layer], SecondsIntoBlock); + TestPatternTwo(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, &State->Transient); }break; case 3: { - TestPatternThree(&LayerLEDBuffers[Layer], SecondsIntoBlock); + TestPatternThree(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, &State->Transient); }break; // NOTE(Peter): Zero is invalid diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index f01b555..79d6cc9 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -73,22 +73,45 @@ struct app_state internal void OpenColorPicker(app_state* State, v4* Address); +#include "engine/foldhaus_assembly.cpp" + // BEGIN TEMPORARY PATTERNS internal void -TestPatternOne(led_buffer* Assembly, r32 Time) +TestPatternOne(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) { - for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) + led_strip_list StemStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("stem"), Transient); + + for (u32 i = 0; i < StemStrips.Count; i++) { - v4 LedPosition = Assembly->Positions[LedIndex]; + u32 StripIndex = StemStrips.StripIndices[i]; + v2_strip StripAt = Assembly.Strips[StripIndex]; + + for (u32 j = 0; j < StripAt.LedCount; j++) + { + u32 LedIndex = StripAt.LedLUT[j]; + v4 LedPosition = Leds->Positions[LedIndex]; + float PercentX = RemapClampedR32(LedPosition.x, -150.0f, 150.0f, 0.0f, 1.0f); + float PercentY = RemapClampedR32(LedPosition.y, -150.0f, 150.0f, 0.0f, 1.0f); + Leds->Colors[LedIndex].R = (u8)(PercentX * 255); + Leds->Colors[LedIndex].G = (u8)(PercentY * 255); + } + } + +#if 0 + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) + { + v4 LedPosition = Leds->Positions[LedIndex]; float PercentX = RemapClampedR32(LedPosition.x, -150.0f, 150.0f, 0.0f, 1.0f); float PercentY = RemapClampedR32(LedPosition.y, -150.0f, 150.0f, 0.0f, 1.0f); - Assembly->Colors[LedIndex].R = (u8)(PercentX * 255); - Assembly->Colors[LedIndex].G = (u8)(PercentY * 255); + Leds->Colors[LedIndex].R = (u8)(PercentX * 255); + Leds->Colors[LedIndex].G = (u8)(PercentY * 255); } +#endif + } internal void -TestPatternTwo(led_buffer* Assembly, r32 Time) +TestPatternTwo(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) { r32 PeriodicTime = (Time / PiR32) * 2; @@ -107,9 +130,9 @@ TestPatternTwo(led_buffer* Assembly, r32 Time) r32 OuterRadiusSquared = 1000000; r32 InnerRadiusSquared = 0; - for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) { - v4 Position = Assembly->Positions[LedIndex]; + v4 Position = Leds->Positions[LedIndex]; v4 ToFront = Position + FrontCenter; v4 ToBack = Position + BackCenter; @@ -125,22 +148,22 @@ TestPatternTwo(led_buffer* Assembly, r32 Time) { if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) { - Assembly->Colors[LedIndex] = Color; + Leds->Colors[LedIndex] = Color; } else { - //Assembly->Colors[LedIndex] = {}; + //Leds->Colors[LedIndex] = {}; } } else { - //Assembly->Colors[LedIndex] = {}; + //Leds->Colors[LedIndex] = {}; } } } internal void -TestPatternThree(led_buffer* Assembly, r32 Time) +TestPatternThree(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) { v4 GreenCenter = v4{0, 0, 150, 1}; r32 GreenRadius = Abs(SinR32(Time)) * 200; @@ -151,9 +174,9 @@ TestPatternThree(led_buffer* Assembly, r32 Time) r32 FadeDist = 35; - for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) { - v4 LedPosition = Assembly->Positions[LedIndex]; + v4 LedPosition = Leds->Positions[LedIndex]; u8 Red = 0; u8 Green = 0; u8 Blue = 0; @@ -167,16 +190,14 @@ TestPatternThree(led_buffer* Assembly, r32 Time) Red = (u8)(TealBrightness * 255); Blue = (u8)(TealBrightness * 255); - Assembly->Colors[LedIndex].R = Red; - Assembly->Colors[LedIndex].B = Green; - Assembly->Colors[LedIndex].G = Green; + Leds->Colors[LedIndex].R = Red; + Leds->Colors[LedIndex].B = Green; + Leds->Colors[LedIndex].G = Green; } } // END TEMPORARY PATTERNS -#include "engine/foldhaus_assembly.cpp" - FOLDHAUS_INPUT_COMMAND_PROC(EndCurrentOperationMode) { DeactivateCurrentOperationMode(&State->Modes); From 736b7ab85e115e33ab5392c1d0d0297ce401780c Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sun, 6 Sep 2020 21:18:49 -0700 Subject: [PATCH 18/43] Prevented array index out of bounds error when accessing animation procs form the GlobalAnimationClips array --- src/app/foldhaus_app.cpp | 25 ++++--------------------- src/todo.txt | 1 - 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 1e4f33b..4f6bbc1 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -359,27 +359,10 @@ UPDATE_AND_RENDER(UpdateAndRender) u32 FramesIntoBlock = CurrentFrame - Block.Range.Min; r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame; - // TODO(Peter): Temporary - switch(Block.AnimationProcHandle) - { - case 1: - { - TestPatternOne(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, &State->Transient); - }break; - - case 2: - { - TestPatternTwo(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, &State->Transient); - }break; - - case 3: - { - TestPatternThree(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, &State->Transient); - }break; - - // NOTE(Peter): Zero is invalid - InvalidDefaultCase; - } + + u32 AnimationProcIndex = Block.AnimationProcHandle - 1; + animation_proc* AnimationProc = GlobalAnimationClips[AnimationProcIndex].Proc; + AnimationProc(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, &State->Transient); } // Consolidate Temp Buffers diff --git a/src/todo.txt b/src/todo.txt index a9edcb9..be2a476 100644 --- a/src/todo.txt +++ b/src/todo.txt @@ -29,7 +29,6 @@ STREAM #1: 3D Overhaul - custom sculpture update functions (for motion) - placing sculptures - editing sculpture files (change universe output) - - led groups & subgroups - defined in file - motion - Sculpture View From 44486acca4fd793d47ea3af549416309ef29aa59 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sun, 6 Sep 2020 21:42:21 -0700 Subject: [PATCH 19/43] did a bunch of animation timeline todos - just simplifying function call signatures --- .../foldhaus_panel_animation_timeline.h | 63 +++++++++---------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index fcbf0c1..0cf63ab 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -289,7 +289,7 @@ AnimationTimeline_Cleanup(panel* Panel, app_state* State) } internal void -DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBuffer, frame_range VisibleFrames, rect2 BarBounds, mouse_state Mouse, app_state* State) +DrawFrameBar (animation_system* AnimationSystem, ui_interface Interface, frame_range VisibleFrames, rect2 BarBounds, app_state* State) { gs_string TempString = PushString(&State->Transient, 256); @@ -298,11 +298,11 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu r32 BarHeight = Rect2Height(BarBounds); r32 BarWidth = Rect2Width(BarBounds); - PushRenderQuad2D(RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); + PushRenderQuad2D(Interface.RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); // Mouse clicked inside frame nubmer bar -> change current frame on timeline - if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && - PointIsInRect(BarBounds, Mouse.DownPos)) + if (MouseButtonTransitionedDown(Interface.Mouse.LeftButtonState) && + PointIsInRect(BarBounds, Interface.Mouse.DownPos)) { StartDragTimeMarker(BarBounds, VisibleFrames, State); } @@ -317,7 +317,7 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu r32 FramePercent = FrameToPercentRange(Frame, VisibleFrames); r32 FrameX = LerpR32(FramePercent, BarBounds.Min.x, BarBounds.Max.x); v2 FrameTextPos = v2{FrameX, BarBounds.Min.y + 2}; - DrawString(RenderBuffer, TempString, State->Interface.Style.Font, FrameTextPos, WhiteV4); + DrawString(Interface.RenderBuffer, TempString, Interface.Style.Font, FrameTextPos, WhiteV4); } // Time Slider @@ -333,19 +333,19 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu r32 SliderHalfWidth = SliderWidth / 2.f; v2 HeadMin = v2{SliderX - SliderHalfWidth, BarBounds.Min.y}; v2 HeadMax = v2{SliderX + SliderHalfWidth, BarBounds.Max.y}; - PushRenderQuad2D(RenderBuffer, HeadMin, HeadMax, TimeSliderColor); - DrawString(RenderBuffer, TempString, State->Interface.Style.Font, HeadMin + v2{6, 4}, WhiteV4); + PushRenderQuad2D(Interface.RenderBuffer, HeadMin, HeadMax, TimeSliderColor); + DrawString(Interface.RenderBuffer, TempString, Interface.Style.Font, HeadMin + v2{6, 4}, WhiteV4); } } internal frame_range -DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_state* TimelineState, render_command_buffer* RenderBuffer, rect2 BarBounds, mouse_state Mouse) +DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_state* TimelineState, ui_interface Interface, rect2 BarBounds) { frame_range Result = {0}; r32 BarHeight = Rect2Height(BarBounds); r32 BarWidth = Rect2Width(BarBounds); - PushRenderQuad2D(RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); + PushRenderQuad2D(Interface.RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); r32 PlayableFrames = (r32)GetFrameCount(AnimationSystem->PlayableRange); v2 SliderBarDim = v2{25, BarHeight}; @@ -358,16 +358,16 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat rect2 SliderBarRange = rect2{ RangeMinSliderMin, RangeMinSliderMin + SliderBarDim }; - if (MouseButtonHeldDown(Mouse.LeftButtonState) || - MouseButtonTransitionedUp(Mouse.LeftButtonState)) + if (MouseButtonHeldDown(Interface.Mouse.LeftButtonState) || + MouseButtonTransitionedUp(Interface.Mouse.LeftButtonState)) { - v2 MouseDragOffset = Mouse.Pos - Mouse.DownPos; - if (PointIsInRect(SliderBarRange, Mouse.DownPos)) + v2 MouseDragOffset = Interface.Mouse.Pos - Interface.Mouse.DownPos; + if (PointIsInRect(SliderBarRange, Interface.Mouse.DownPos)) { r32 NewSliderX = RangeMinSliderMin.x + MouseDragOffset.x; RangeMinSliderMin.x = Clamp(BarBounds.Min.x, NewSliderX, RangeMaxSliderMin.x - SliderBarDim.x); } - if (PointIsInRect(SliderBarRange, Mouse.DownPos)) + if (PointIsInRect(SliderBarRange, Interface.Mouse.DownPos)) { r32 NewSliderX = RangeMaxSliderMin.x + MouseDragOffset.x; RangeMaxSliderMin.x = Clamp(RangeMinSliderMin.x + SliderBarDim.x, NewSliderX, BarBounds.Max.x - SliderBarDim.x); @@ -376,8 +376,8 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat v2 RangeMinSliderMax = v2{RangeMinSliderMin.x + 25, BarBounds.Max.y}; v2 RangeMaxSliderMax = v2{RangeMaxSliderMin.x + 25, BarBounds.Max.y}; - PushRenderQuad2D(RenderBuffer, RangeMinSliderMin, RangeMinSliderMax, v4{.8f, .8f, .8f, 1.f}); - PushRenderQuad2D(RenderBuffer, RangeMaxSliderMin, RangeMaxSliderMax, v4{.8f, .8f, .8f, 1.f}); + PushRenderQuad2D(Interface.RenderBuffer, RangeMinSliderMin, RangeMinSliderMax, v4{.8f, .8f, .8f, 1.f}); + PushRenderQuad2D(Interface.RenderBuffer, RangeMaxSliderMin, RangeMaxSliderMax, v4{.8f, .8f, .8f, 1.f}); // Convert Pixels Back To Frames and store VisibleMinPercentPlayable = (RangeMinSliderMin.x - BarBounds.Min.x) / BarWidth; @@ -386,7 +386,7 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat Result.Min = VisibleMinPercentPlayable * VisibleFrameCount; Result.Max = VisibleMaxPercentPlayable * VisibleFrameCount; - if (MouseButtonTransitionedUp(Mouse.LeftButtonState)) + if (MouseButtonTransitionedUp(Interface.Mouse.LeftButtonState)) { TimelineState->VisibleRange = Result; } @@ -396,8 +396,8 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat #define LAYER_HEIGHT 52 -internal void -DrawLayerMenu(animation_system* AnimationSystem, rect2 PanelDim, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) +internal u32 +DrawLayerMenu(animation_system* AnimationSystem, ui_interface Interface, rect2 PanelDim, u32 SelectedAnimationLayer) { v2 LayerDim = { Rect2Width(PanelDim), LAYER_HEIGHT }; v2 LayerListMin = PanelDim.Min + v2{0, 24}; @@ -408,19 +408,21 @@ DrawLayerMenu(animation_system* AnimationSystem, rect2 PanelDim, render_command_ LayerBounds.Min = { LayerListMin.x, LayerListMin.y + (LayerDim.y * LayerIndex) }; LayerBounds.Max = LayerBounds.Min + LayerDim; - if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && - PointIsInRect(LayerBounds, Mouse.Pos)) + if (MouseButtonTransitionedDown(Interface.Mouse.LeftButtonState) && + PointIsInRect(LayerBounds, Interface.Mouse.Pos)) { - State->SelectedAnimationLayer = LayerIndex; + SelectedAnimationLayer = LayerIndex; } v2 LayerTextPos = { LayerBounds.Min.x + 6, LayerBounds.Max.y - 16}; - if (State->SelectedAnimationLayer == LayerIndex) + if (SelectedAnimationLayer == LayerIndex) { - PushRenderBoundingBox2D(RenderBuffer, LayerBounds.Min, LayerBounds.Max, 1, WhiteV4); + PushRenderBoundingBox2D(Interface.RenderBuffer, LayerBounds.Min, LayerBounds.Max, 1, WhiteV4); } - DrawString(RenderBuffer, Layer->Name, State->Interface.Style.Font, LayerTextPos, WhiteV4); + DrawString(Interface.RenderBuffer, Layer->Name, Interface.Style.Font, LayerTextPos, WhiteV4); } + + return SelectedAnimationLayer; } internal rect2 @@ -462,16 +464,13 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta RectHSplitAtDistanceFromTop(TimelineBounds, 32, &TimelineFrameBarBounds, &TimelineBounds); RectHSplitAtDistanceFromBottom(TimelineBounds, 24, &TimelineBlockDisplayBounds, &TimelineRangeBarBounds); - // TODO(Peter): Clean Up - DrawLayerMenu(AnimationSystem, LayerMenuBounds, Interface->RenderBuffer, State, Interface->Mouse); + State->SelectedAnimationLayer = DrawLayerMenu(AnimationSystem, *Interface, LayerMenuBounds, State->SelectedAnimationLayer); frame_range AdjustedViewRange = {0}; - // TODO(Peter): Clean Up - AdjustedViewRange = DrawTimelineRangeBar(AnimationSystem, TimelineState, Interface->RenderBuffer, TimelineRangeBarBounds, Interface->Mouse); + AdjustedViewRange = DrawTimelineRangeBar(AnimationSystem, TimelineState, *Interface, TimelineRangeBarBounds); s32 VisibleFrameCount = AdjustedViewRange.Max - AdjustedViewRange.Min; - // TODO(Peter): Clean Up - DrawFrameBar(AnimationSystem, Interface->RenderBuffer, AdjustedViewRange, TimelineFrameBarBounds, Interface->Mouse, State); + DrawFrameBar(AnimationSystem, *Interface, AdjustedViewRange, TimelineFrameBarBounds, State); ui_FillRect(Interface, TimelineBlockDisplayBounds, v4{.25f, .25f, .25f, 1.0f}); @@ -500,7 +499,6 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta { BlockColor = PinkV4; } - // TODO(Peter): Clean Up rect2 BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer); if (PointIsInRect(BlockBounds, Interface->Mouse.Pos)) { @@ -567,7 +565,6 @@ DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedA AddAnimationBlockAtCurrentTime(i + 1, SelectedAnimationLayer, AnimationSystem); } } - // TODO(Peter): Fill up the rest of the area with empty list entries } GSMetaTag(panel_render); From cc41442923d7e66b3c5b46f1e0f5057cfbc237db Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 7 Sep 2020 11:12:58 -0700 Subject: [PATCH 20/43] added assembly_center field to assembly files and used it to place assemblies at construction time --- src/app/editor/panels/foldhaus_panel_animation_timeline.h | 3 ++- src/app/engine/assembly_parser.cpp | 3 +++ src/app/engine/foldhaus_assembly.cpp | 7 ++++--- src/app/engine/foldhaus_assembly.h | 1 + src/todo.txt | 2 -- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 0cf63ab..877cadc 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -12,6 +12,8 @@ global v4 TimeSliderColor = v4{.36f, .52f, .78f, 1.f}; struct animation_timeline_state { frame_range VisibleRange; + gs_list_handle SelectedAnimationBlockHandle; + u32 SelectedAnimationLayer; }; inline u32 @@ -510,7 +512,6 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta if (MouseDownAndNotHandled && ListHandleIsValid(DragBlockHandle)) { MouseDownAndNotHandled = false; - // TODO(Peter): Why are we passing state around? SelectAndBeginDragAnimationBlock(DragBlockHandle, AdjustedViewRange, TimelineBounds, State); } diff --git a/src/app/engine/assembly_parser.cpp b/src/app/engine/assembly_parser.cpp index 8e229e0..ea2b36c 100644 --- a/src/app/engine/assembly_parser.cpp +++ b/src/app/engine/assembly_parser.cpp @@ -9,6 +9,7 @@ enum assembly_field { AssemblyField_AssemblyName, AssemblyField_AssemblyScale, + AssemblyField_AssemblyCenter, AssemblyField_LedStripCount, AssemblyField_LedStrip, @@ -31,6 +32,7 @@ enum assembly_field global char* AssemblyFieldIdentifiers[] = { "assembly_name", // AssemblyField_AssemblyName "assembly_scale", // AssemblyField_AssemblyScale + "assembly_center", // AssemblyField_AssemblyCenter "led_strip_count", // AssemblyField_LedStripCount "led_strip", // AssemblyField_LedStrip @@ -384,6 +386,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena); Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer); + Assembly->Center = ReadV3Field(AssemblyField_AssemblyCenter, &Tokenizer); Assembly->StripCount = ReadIntField(AssemblyField_LedStripCount, &Tokenizer); Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount); diff --git a/src/app/engine/foldhaus_assembly.cpp b/src/app/engine/foldhaus_assembly.cpp index c01d44f..aa651b3 100644 --- a/src/app/engine/foldhaus_assembly.cpp +++ b/src/app/engine/foldhaus_assembly.cpp @@ -77,11 +77,13 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) } internal void -ConstructAssemblyFromDefinition (assembly* Assembly, gs_const_string AssemblyName, v4 RootPosition, led_system* LedSystem) +ConstructAssemblyFromDefinition (assembly* Assembly, gs_const_string AssemblyName, led_system* LedSystem) { 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++) @@ -127,8 +129,7 @@ LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, gs_memory_arena NewAssembly->Arena = CreateMemoryArena(Context.ThreadContext.Allocator); if (ParseAssemblyFile(NewAssembly, FileName, AssemblyFileText, Scratch)) { - v4 Offset = v4{0,0,0,0}; //TempAssemblyOffsets[Assemblies->Count % TempAssemblyOffsetsCount]; - ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, LedSystem); + ConstructAssemblyFromDefinition(NewAssembly, FileName, LedSystem); AllocatorFree(Context.ThreadContext.Allocator, AssemblyFile.Memory, AssemblyFile.Size); } else diff --git a/src/app/engine/foldhaus_assembly.h b/src/app/engine/foldhaus_assembly.h index 6005b4a..4a6cc85 100644 --- a/src/app/engine/foldhaus_assembly.h +++ b/src/app/engine/foldhaus_assembly.h @@ -75,6 +75,7 @@ struct assembly gs_string FilePath; r32 Scale; + v3 Center; s32 LedCountTotal; u32 LedBufferIndex; diff --git a/src/todo.txt b/src/todo.txt index be2a476..6da1111 100644 --- a/src/todo.txt +++ b/src/todo.txt @@ -24,10 +24,8 @@ STREAM #1: 3D Overhaul - leds always face camera - Sculptures - - store scale in the assembly definition file - cache led vertex buffers - custom sculpture update functions (for motion) - - placing sculptures - editing sculpture files (change universe output) - motion From c7522bfa4bc2c9fa4d948298a87fcea833f56c33 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 7 Sep 2020 12:37:32 -0700 Subject: [PATCH 21/43] Added a default tag to every strip specifying which assembly it is a part of --- src/app/engine/assembly_parser.cpp | 20 +++++++++++++---- src/app/engine/foldhaus_assembly.cpp | 11 +++++----- src/app/foldhaus_app.cpp | 3 +++ src/app/foldhaus_app.h | 25 ++++++++++++++------- src/todo.txt | 33 ++++++++++------------------ 5 files changed, 53 insertions(+), 39 deletions(-) diff --git a/src/app/engine/assembly_parser.cpp b/src/app/engine/assembly_parser.cpp index ea2b36c..d23b596 100644 --- a/src/app/engine/assembly_parser.cpp +++ b/src/app/engine/assembly_parser.cpp @@ -370,6 +370,15 @@ ReadStructClosing(assembly_tokenizer* T) return Result; } +internal void +StripSetTag(v2_strip* Strip, u32 TagIndex, gs_const_string TagName, gs_const_string TagValue) +{ + Assert(TagIndex < Strip->TagsCount); + v2_tag* TagAt = &Strip->Tags[TagIndex]; + TagAt->NameHash = HashDJB2ToU32(StringExpand(TagName)); + TagAt->ValueHash = HashDJB2ToU32(StringExpand(TagValue)); +} + internal bool ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileText, gs_memory_arena* Transient) { @@ -420,19 +429,21 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe StripAt->LedCount = ReadIntField(AssemblyField_LedCount, &Tokenizer); Assembly->LedCountTotal += StripAt->LedCount; + StripAt->TagsCount = ReadIntField(AssemblyField_TagsCount, &Tokenizer); + // NOTE(pjs): Always add one tag to the input to leave room for the assembly name + StripAt->TagsCount += 1; StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount); - for (u32 Tag = 0; Tag < StripAt->TagsCount; Tag++) + StripSetTag(StripAt, 0, ConstString("assembly"), Assembly->Name.ConstString); + for (u32 Tag = 1; Tag < StripAt->TagsCount; Tag++) { - v2_tag* TagAt = StripAt->Tags + Tag; if (ReadStructOpening(AssemblyField_Tag, &Tokenizer)) { // TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface // right now they are stored in temp memory and won't persist gs_string TagName = ReadStringField(AssemblyField_Name, &Tokenizer, Transient); gs_string TagValue = ReadStringField(AssemblyField_Value, &Tokenizer, Transient); - TagAt->NameHash = HashDJB2ToU32(StringExpand(TagName)); - TagAt->ValueHash = HashDJB2ToU32(StringExpand(TagValue)); + StripSetTag(StripAt, Tag, TagName.ConstString, TagValue.ConstString); if (!ReadStructClosing(&Tokenizer)) { TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); @@ -444,6 +455,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe } } + if (!ReadStructClosing(&Tokenizer)) { TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); diff --git a/src/app/engine/foldhaus_assembly.cpp b/src/app/engine/foldhaus_assembly.cpp index aa651b3..48ef8f6 100644 --- a/src/app/engine/foldhaus_assembly.cpp +++ b/src/app/engine/foldhaus_assembly.cpp @@ -77,7 +77,7 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) } internal void -ConstructAssemblyFromDefinition (assembly* Assembly, gs_const_string AssemblyName, led_system* LedSystem) +ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem) { Assembly->LedBufferIndex = LedSystemTakeFreeBuffer(LedSystem, Assembly->LedCountTotal); led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex); @@ -88,7 +88,6 @@ ConstructAssemblyFromDefinition (assembly* Assembly, gs_const_string AssemblyNam u32 LedsAdded = 0; for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++) { - //led_strip_definition StripDef = Definition.LedStrips[StripIdx]; v2_strip* StripAt = &Assembly->Strips[StripIdx]; StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount); @@ -120,16 +119,16 @@ LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, gs_memory_arena { gs_string AssemblyFileText = MakeString((char*)AssemblyFile.Memory); - Assert(Assemblies->Count < Assemblies->CountMax); - assembly* NewAssembly = &Assemblies->Values[Assemblies->Count++]; - s32 IndexOfLastSlash = FindLast(Path, '\\'); gs_const_string FileName = Substring(Path, IndexOfLastSlash + 1, Path.Length); + Assert(Assemblies->Count < Assemblies->CountMax); + assembly* NewAssembly = &Assemblies->Values[Assemblies->Count++]; NewAssembly->Arena = CreateMemoryArena(Context.ThreadContext.Allocator); + if (ParseAssemblyFile(NewAssembly, FileName, AssemblyFileText, Scratch)) { - ConstructAssemblyFromDefinition(NewAssembly, FileName, LedSystem); + ConstructAssemblyFromDefinition(NewAssembly, LedSystem); AllocatorFree(Context.ThreadContext.Allocator, AssemblyFile.Memory, AssemblyFile.Size); } else diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 4f6bbc1..35a1474 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -155,6 +155,9 @@ INITIALIZE_APPLICATION(InitializeApplication) #if 1 gs_const_string SculpturePath = ConstString("data/blumen_lumen_v2.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, SculpturePath, State->GlobalLog); + + SculpturePath = ConstString("data/radialumia_v2.fold"); + LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, SculpturePath, State->GlobalLog); #endif State->PixelsToWorldScale = .01f; diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 79d6cc9..c8e43c7 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -79,24 +79,33 @@ internal void OpenColorPicker(app_state* State, v4* Address); internal void TestPatternOne(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) { - led_strip_list StemStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("stem"), Transient); + led_strip_list BlumenStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Blumen Lumen"), Transient); + led_strip_list RadiaStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Radialumia"), Transient); - for (u32 i = 0; i < StemStrips.Count; i++) + for (u32 i = 0; i < BlumenStrips.Count; i++) { - u32 StripIndex = StemStrips.StripIndices[i]; + u32 StripIndex = BlumenStrips.StripIndices[i]; v2_strip StripAt = Assembly.Strips[StripIndex]; for (u32 j = 0; j < StripAt.LedCount; j++) { u32 LedIndex = StripAt.LedLUT[j]; - v4 LedPosition = Leds->Positions[LedIndex]; - float PercentX = RemapClampedR32(LedPosition.x, -150.0f, 150.0f, 0.0f, 1.0f); - float PercentY = RemapClampedR32(LedPosition.y, -150.0f, 150.0f, 0.0f, 1.0f); - Leds->Colors[LedIndex].R = (u8)(PercentX * 255); - Leds->Colors[LedIndex].G = (u8)(PercentY * 255); + Leds->Colors[LedIndex] = { 255, 0, 0 }; + } } + for (u32 i = 0; i < RadiaStrips.Count; i++) + { + u32 StripIndex = RadiaStrips.StripIndices[i]; + v2_strip StripAt = Assembly.Strips[StripIndex]; + + for (u32 j = 0; j < StripAt.LedCount; j++) + { + u32 LedIndex = StripAt.LedLUT[j]; + Leds->Colors[LedIndex] = { 0, 255, 0 }; + } + } #if 0 for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) { diff --git a/src/todo.txt b/src/todo.txt index 6da1111..3f3dca5 100644 --- a/src/todo.txt +++ b/src/todo.txt @@ -1,15 +1,5 @@ TODO FOLDHAUS -STREAM #0: Metaprogramming -- Metaprogramming - - fix memory layout (remeber to profile before and after) -- Make everything truly platform agnostic - - Application DLL - - math.h: present for trig functions (though this is part of the c-std lib, so it should be everywhere) - - windows.h: only thing left is InterlockedIncrement and InterlockedAdd - - Meta Layer - - ??? - STREAM #1: 3D Overhaul - Rendering (Working on this elsewhere) - OpenGL 3 @@ -24,6 +14,7 @@ STREAM #1: 3D Overhaul - leds always face camera - Sculptures + - implicitly add a tag equal to the sculpture name to each strip of leds - cache led vertex buffers - custom sculpture update functions (for motion) - editing sculpture files (change universe output) @@ -33,7 +24,6 @@ STREAM #1: 3D Overhaul - mouse spatial interaction - handles, and hover for info - debug capabilities (toggle strip/led/universe colors) -STREAM #2: Memory - Buckets & Lists - On second thought, I just really don't like these. Lets get rid of them, and put custom structures in place @@ -44,11 +34,11 @@ STREAM #2: Memory - Create a bar that displays the most recent error message - :ErrorLogging -STREAM #3: Nodes - Animation System - blending between animation - layers - layer masks by sculpture + - layer masks by tag / value - interface for animation system - add/remove layers - select blend modes @@ -57,17 +47,8 @@ STREAM #3: Nodes - clips can have parameters that drive them? - clips cannot overlap eachother on the same layer -- Node System - - automatic node layout - - blending node layouts - - workspace -> animation block - - generating node workspace as code - - compiling node workspace - - hotload compiled pattern sets - - Serialization - saving scenes - - saving node graphs - saving animation timelines - saving projects @@ -157,3 +138,13 @@ Name - Splash screen (like blender) (thisll be fun) - - Image importer (stb image? or find a png > bmp converter for the image you have) - - Display on startup + +STREAM #0: Metaprogramming +- Metaprogramming + - fix memory layout (remeber to profile before and after) +- Make everything truly platform agnostic + - Application DLL + - math.h: present for trig functions (though this is part of the c-std lib, so it should be everywhere) + - windows.h: only thing left is InterlockedIncrement and InterlockedAdd + - Meta Layer + - ??? From d08de9b99fe783ab54816779a38fa4969964337c Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 7 Sep 2020 12:47:12 -0700 Subject: [PATCH 22/43] Stopped freeing assembly file memory after load since its in the transient buffer anyways. --- src/app/engine/foldhaus_assembly.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/app/engine/foldhaus_assembly.cpp b/src/app/engine/foldhaus_assembly.cpp index 48ef8f6..afb3919 100644 --- a/src/app/engine/foldhaus_assembly.cpp +++ b/src/app/engine/foldhaus_assembly.cpp @@ -105,12 +105,6 @@ ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem) } } -// NOTE(Peter): These are here so that if we load 2+ sculptures, they don't all -// end up on top of one another. Purely aesthetic. Can remove once we implement -// scene editing tools -static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, 0, 75, 0} }; -s32 TempAssemblyOffsetsCount = 3; - internal void LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, gs_memory_arena* Scratch, context Context, gs_const_string Path, event_log* GlobalLog) { @@ -129,7 +123,6 @@ LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, gs_memory_arena if (ParseAssemblyFile(NewAssembly, FileName, AssemblyFileText, Scratch)) { ConstructAssemblyFromDefinition(NewAssembly, LedSystem); - AllocatorFree(Context.ThreadContext.Allocator, AssemblyFile.Memory, AssemblyFile.Size); } else { From 15a2cb080e6734bc23bbc95e2d20d57382b8346d Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 7 Sep 2020 13:42:00 -0700 Subject: [PATCH 23/43] Basic file lister functionality. Extended Win32EnumerateDirectory; it now includes folders if proper flags are set. --- src/app/editor/foldhaus_command_dispatch.h | 2 +- src/app/editor/foldhaus_interface.cpp | 12 ++-- src/app/editor/foldhaus_operation_mode.h | 2 +- .../foldhaus_panel_animation_timeline.h | 8 +-- .../editor/panels/foldhaus_panel_dmx_view.h | 2 +- .../editor/panels/foldhaus_panel_file_view.h | 55 +++++++++++++++---- .../editor/panels/foldhaus_panel_hierarchy.h | 16 +++--- .../editor/panels/foldhaus_panel_profiler.h | 4 +- .../panels/foldhaus_panel_sculpture_view.h | 6 +- src/app/foldhaus_app.cpp | 32 +++++------ src/app/foldhaus_app.h | 4 +- src/app/platform_win32/win32_foldhaus.cpp | 46 +++++++++------- src/gs_libs/gs_types.cpp | 30 +--------- src/gs_libs/gs_types.h | 1 + 14 files changed, 117 insertions(+), 103 deletions(-) diff --git a/src/app/editor/foldhaus_command_dispatch.h b/src/app/editor/foldhaus_command_dispatch.h index 3b2d8aa..e9db217 100644 --- a/src/app/editor/foldhaus_command_dispatch.h +++ b/src/app/editor/foldhaus_command_dispatch.h @@ -5,7 +5,7 @@ // #ifndef FOLDHAUS_COMMAND_DISPATCH_H -#define FOLDHAUS_INPUT_COMMAND_PROC(name) void name(app_state* State, input_entry Event, mouse_state Mouse) +#define FOLDHAUS_INPUT_COMMAND_PROC(name) void name(app_state* State, input_entry Event, mouse_state Mouse, context Context) typedef FOLDHAUS_INPUT_COMMAND_PROC(input_command_proc); // NOTE(Peter): Helper function so I don't have to remember the parameters to this define diff --git a/src/app/editor/foldhaus_interface.cpp b/src/app/editor/foldhaus_interface.cpp index e5e4e43..0c66cf4 100644 --- a/src/app/editor/foldhaus_interface.cpp +++ b/src/app/editor/foldhaus_interface.cpp @@ -20,7 +20,7 @@ enum panel_edit_mode }; internal void -SetPanelDefinition(panel* Panel, s32 NewPanelDefinitionIndex, app_state* State) +SetPanelDefinition(panel* Panel, s32 NewPanelDefinitionIndex, app_state* State, context Context) { s32 OldPanelDefinitionIndex = Panel->PanelDefinitionIndex; Panel->PanelDefinitionIndex = NewPanelDefinitionIndex; @@ -29,7 +29,7 @@ SetPanelDefinition(panel* Panel, s32 NewPanelDefinitionIndex, app_state* State) { GlobalPanelDefs[OldPanelDefinitionIndex].Cleanup(Panel, State); } - GlobalPanelDefs[NewPanelDefinitionIndex].Init(Panel, State); + GlobalPanelDefs[NewPanelDefinitionIndex].Init(Panel, State, Context); } // @@ -254,7 +254,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation) Panel->Left->Panel.PanelStateMemory = Panel->PanelStateMemory; Panel->Left->Panel.PanelStateMemorySize = Panel->PanelStateMemorySize; - SetPanelDefinition(&Panel->Right->Panel, Panel->PanelDefinitionIndex, State); + SetPanelDefinition(&Panel->Right->Panel, Panel->PanelDefinitionIndex, State, Context); DeactivateCurrentOperationMode(&State->Modes); } @@ -400,7 +400,7 @@ DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, mouse_state* Mo } internal void -DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterBounds, mouse_state Mouse, app_state* State) +DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterBounds, mouse_state Mouse, app_state* State, context Context) { PushRenderQuad2D(RenderBuffer, FooterBounds.Min, v2{FooterBounds.Max.x, FooterBounds.Min.y + 25}, v4{.5f, .5f, .5f, 1.f}); PushRenderQuad2D(RenderBuffer, FooterBounds.Min, FooterBounds.Min + v2{25, 25}, WhiteV4); @@ -431,7 +431,7 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterB gs_string DefName = MakeString(Def.PanelName, Def.PanelNameLength); if (ui_Button(&State->Interface, DefName, ButtonBounds)) { - SetPanelDefinition(Panel, i, State); + SetPanelDefinition(Panel, i, State, Context); Panel->PanelSelectionMenuOpen = false; } @@ -464,7 +464,7 @@ RenderPanel(panel* Panel, rect2 PanelBounds, rect2 WindowBounds, render_command_ Definition.Render(*Panel, PanelViewBounds, RenderBuffer, State, Context); PushRenderOrthographic(RenderBuffer, WindowBounds); - DrawPanelFooter(Panel, RenderBuffer, FooterBounds, Mouse, State); + DrawPanelFooter(Panel, RenderBuffer, FooterBounds, Mouse, State, Context); } internal void diff --git a/src/app/editor/foldhaus_operation_mode.h b/src/app/editor/foldhaus_operation_mode.h index 80c1641..e45606a 100644 --- a/src/app/editor/foldhaus_operation_mode.h +++ b/src/app/editor/foldhaus_operation_mode.h @@ -9,7 +9,7 @@ typedef struct operation_mode operation_mode; #define OPERATION_STATE_DEF(name) struct name -#define OPERATION_RENDER_PROC(name) void name(app_state* State, render_command_buffer* RenderBuffer, operation_mode Operation, mouse_state Mouse) +#define OPERATION_RENDER_PROC(name) void name(app_state* State, render_command_buffer* RenderBuffer, operation_mode Operation, mouse_state Mouse, context Context) typedef OPERATION_RENDER_PROC(operation_render_proc); struct operation_mode diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 877cadc..17a469b 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -152,7 +152,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) animation_block* AnimationBlock = State->AnimationSystem.Blocks.GetElementWithHandle(State->SelectedAnimationBlockHandle); if (!AnimationBlock) { - EndCurrentOperationMode(State, {}, Mouse); + EndCurrentOperationMode(State, {}, Mouse, Context); return; } @@ -274,7 +274,7 @@ s32 AnimationTimeline_CommandsCount = 2; GSMetaTag(panel_init); GSMetaTag(panel_type_animation_timeline); internal void -AnimationTimeline_Init(panel* Panel, app_state* State) +AnimationTimeline_Init(panel* Panel, app_state* State, context Context) { // TODO: :FreePanelMemory animation_timeline_state* TimelineState = PushStruct(&State->Permanent, animation_timeline_state); @@ -293,7 +293,7 @@ AnimationTimeline_Cleanup(panel* Panel, app_state* State) internal void DrawFrameBar (animation_system* AnimationSystem, ui_interface Interface, frame_range VisibleFrames, rect2 BarBounds, app_state* State) { - gs_string TempString = PushString(&State->Transient, 256); + gs_string TempString = PushString(State->Transient, 256); s32 VisibleFrameCount = VisibleFrames.Max - VisibleFrames.Min; @@ -455,7 +455,7 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V internal gs_list_handle DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect2 PanelBounds, gs_list_handle SelectedBlockHandle, ui_interface* Interface, app_state* State) { - gs_string Tempgs_string = PushString(&State->Transient, 256); + gs_string Tempgs_string = PushString(State->Transient, 256); gs_list_handle Result = SelectedBlockHandle; rect2 LayerMenuBounds, TimelineBounds; diff --git a/src/app/editor/panels/foldhaus_panel_dmx_view.h b/src/app/editor/panels/foldhaus_panel_dmx_view.h index 56d0352..7d9614e 100644 --- a/src/app/editor/panels/foldhaus_panel_dmx_view.h +++ b/src/app/editor/panels/foldhaus_panel_dmx_view.h @@ -18,7 +18,7 @@ s32 DMXView_CommandsCount = 0; GSMetaTag(panel_init); GSMetaTag(panel_type_dmx_view); internal void -DMXView_Init(panel* Panel, app_state* State) +DMXView_Init(panel* Panel, app_state* State, context Context) { } diff --git a/src/app/editor/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h index 2fd2953..c38fc08 100644 --- a/src/app/editor/panels/foldhaus_panel_file_view.h +++ b/src/app/editor/panels/foldhaus_panel_file_view.h @@ -8,21 +8,51 @@ struct file_view_state { gs_string WorkingDirectory; + gs_memory_arena FileNamesArena; + gs_file_info_array FileNames; }; input_command* FileView_Commands = 0; s32 FileView_CommandsCount = 0; +// TODO(pjs): 2 - On Change Dir function +// - clears the memory arena +// - enumerates the new directory in the memory arena + +internal void +FileViewUpdateWorkingDirectory(gs_const_string WorkingDirectory, file_view_state* State, context Context) +{ + ClearArena(&State->FileNamesArena); + + State->WorkingDirectory = PushString(&State->FileNamesArena, WorkingDirectory.Length + 2); + PrintF(&State->WorkingDirectory, "%S", WorkingDirectory); + if (State->WorkingDirectory.Str[State->WorkingDirectory.Length - 1] != '\\') + { + AppendPrintF(&State->WorkingDirectory, "\\"); + } + if (State->WorkingDirectory.Str[State->WorkingDirectory.Length - 1] != '*') + { + AppendPrintF(&State->WorkingDirectory, "*"); + } + + State->FileNames = EnumerateDirectory(Context.ThreadContext.FileHandler, &State->FileNamesArena, State->WorkingDirectory.ConstString, EnumerateDirectory_IncludeDirectories); +} + GSMetaTag(panel_init); GSMetaTag(panel_type_file_view); internal void -FileView_Init(panel* Panel, app_state* State) +FileView_Init(panel* Panel, app_state* State, context Context) { // TODO: :FreePanelMemory file_view_state* FileViewState = PushStruct(&State->Permanent, file_view_state); + Panel->PanelStateMemory = (u8*)FileViewState; + FileViewState->FileNamesArena = CreateMemoryArena(Context.ThreadContext.Allocator); + +#if 0 FileViewState->WorkingDirectory = MakeString(PushArray(&State->Permanent, char, 256), 256); PrintF(&FileViewState->WorkingDirectory, "C:\\"); - Panel->PanelStateMemory = (u8*)FileViewState; +#endif + FileViewUpdateWorkingDirectory(ConstString("C:\\projects\\Lumenarium\\src\\app"), FileViewState, Context); } GSMetaTag(panel_cleanup); @@ -38,16 +68,21 @@ GSMetaTag(panel_type_file_view); internal void FileView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - rect2 HeaderBounds = {0}; - HeaderBounds.Min = {PanelBounds.Min.x, PanelBounds.Max.y - 32}; - HeaderBounds.Max = PanelBounds.Max; + file_view_state* FileViewState = (file_view_state*)Panel.PanelStateMemory; + ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); - rect2 ListBounds = {0}; - ListBounds.Min = PanelBounds.Min; - ListBounds.Max = RectBottomRight(HeaderBounds); + // Header + rect2 HeaderBounds = ui_ReserveElementBounds(&Layout); + + // File Display + for (u32 i = 0; i < FileViewState->FileNames.Count; i++) + { + gs_file_info File = FileViewState->FileNames.Values[i]; + gs_string PathString = PushString(State->Transient, File.Path.Length); + PrintF(&PathString, "%S", File.Path); + ui_LayoutDrawString(&State->Interface, &Layout, PathString, State->Interface.Style.TextColor); + } - PushRenderQuad2D(RenderBuffer, HeaderBounds.Min, HeaderBounds.Max, PinkV4); - PushRenderQuad2D(RenderBuffer, ListBounds.Min, ListBounds.Max, RedV4); } diff --git a/src/app/editor/panels/foldhaus_panel_hierarchy.h b/src/app/editor/panels/foldhaus_panel_hierarchy.h index 5d0cca7..b8ad772 100644 --- a/src/app/editor/panels/foldhaus_panel_hierarchy.h +++ b/src/app/editor/panels/foldhaus_panel_hierarchy.h @@ -11,7 +11,7 @@ s32 HierarchyView_CommandsCount = 0; GSMetaTag(panel_init); GSMetaTag(panel_type_hierarchy); internal void -HierarchyView_Init(panel* Panel, app_state* State) +HierarchyView_Init(panel* Panel, app_state* State, context Context) { } @@ -30,10 +30,10 @@ internal void HierarchyView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); - gs_string Tempgs_string = PushString(&State->Transient, 256); + gs_string TempString = PushString(State->Transient, 256); u32 LineCount = (u32)(Rect2Height(PanelBounds) / Layout.RowHeight) + 1; u32 AssembliesToDraw = Min(LineCount, State->Assemblies.Count); - rect2* LineBounds = PushArray(&State->Transient, rect2, LineCount); + rect2* LineBounds = PushArray(State->Transient, rect2, LineCount); // Fill in alternating color rows for the backgrounds for (u32 Line = 0; Line < LineCount; Line++) @@ -46,12 +46,12 @@ HierarchyView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend for (u32 AssemblyIndex = 0; AssemblyIndex < AssembliesToDraw; AssemblyIndex++) { assembly Assembly = State->Assemblies.Values[AssemblyIndex]; - PrintF(&Tempgs_string, "%S", Assembly.Name); + PrintF(&TempString, "%S", Assembly.Name); ui_layout ItemLayout = ui_CreateLayout(State->Interface, LineBounds[AssemblyIndex]); ui_StartRow(&ItemLayout, 2); { - ui_LayoutDrawString(&State->Interface, &ItemLayout, Tempgs_string, State->Interface.Style.TextColor); + ui_LayoutDrawString(&State->Interface, &ItemLayout, TempString, State->Interface.Style.TextColor); if (ui_LayoutListButton(&State->Interface, &ItemLayout, MakeString("X"), AssemblyIndex)) { UnloadAssembly(AssemblyIndex, State, Context); @@ -63,10 +63,10 @@ HierarchyView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend if (AssembliesToDraw < LineCount) { // NOTE(Peter): Add assembly button - PrintF(&Tempgs_string, "+ Add Assembly"); - if (ui_ListButton(&State->Interface, Tempgs_string, LineBounds[AssembliesToDraw], AssembliesToDraw)) + PrintF(&TempString, "+ Add Assembly"); + if (ui_ListButton(&State->Interface, TempString, LineBounds[AssembliesToDraw], AssembliesToDraw)) { - gs_string FilePath = PushString(&State->Transient, 256); + gs_string FilePath = PushString(State->Transient, 256); // TODO(Peter): Took out file opening temporarily while I get things back up and running. // Ideally we can just write our own file lister using the new filehandler so that diff --git a/src/app/editor/panels/foldhaus_panel_profiler.h b/src/app/editor/panels/foldhaus_panel_profiler.h index bc18748..e7ee509 100644 --- a/src/app/editor/panels/foldhaus_panel_profiler.h +++ b/src/app/editor/panels/foldhaus_panel_profiler.h @@ -11,7 +11,7 @@ s32 ProfilerView_CommandsCount = 0; GSMetaTag(panel_init); GSMetaTag(panel_type_profiler); internal void -ProfilerView_Init(panel* Panel, app_state* State) +ProfilerView_Init(panel* Panel, app_state* State, context Context) { } @@ -139,7 +139,7 @@ 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_memory_arena* Memory = State->Transient; gs_string String = PushString(Memory, 256); v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 }; diff --git a/src/app/editor/panels/foldhaus_panel_sculpture_view.h b/src/app/editor/panels/foldhaus_panel_sculpture_view.h index 56d9ff0..30ede9c 100644 --- a/src/app/editor/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/editor/panels/foldhaus_panel_sculpture_view.h @@ -55,7 +55,7 @@ global s32 SculptureView_CommandsCount = 1; GSMetaTag(panel_init); GSMetaTag(panel_type_sculpture_view); internal void -SculptureView_Init(panel* Panel, app_state* State) +SculptureView_Init(panel* Panel, app_state* State, context Context) { } @@ -175,7 +175,7 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend u32 NextLEDIndex = 0; for (u32 Job = 0; Job < JobsNeeded; Job++) { - gs_data Data = PushSizeToData(&State->Transient, sizeof(draw_leds_job_data)); + 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; @@ -207,7 +207,7 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend v4 LedPosition = LedBuffer->Positions[FocusPixel]; v2 LedOnScreenPosition = SculptureView_WorldToScreenPosition(LedPosition, State->Camera, PanelBounds); - gs_string Tempgs_string = PushString(&State->Transient, 256); + gs_string Tempgs_string = PushString(State->Transient, 256); PrintF(&Tempgs_string, "%f %f", LedOnScreenPosition.x, LedOnScreenPosition.y); DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4); diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 35a1474..519554b 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -52,12 +52,12 @@ INITIALIZE_APPLICATION(InitializeApplication) *State = {}; State->Permanent = CreateMemoryArena(Context.ThreadContext.Allocator); - State->Transient = CreateMemoryArena(Context.ThreadContext.Allocator); + State->Transient = Context.ThreadContext.Transient; State->Assemblies.CountMax = 8; State->Assemblies.Values = PushArray(&State->Permanent, assembly, State->Assemblies.CountMax); - State->GlobalLog = PushStruct(&State->Transient, event_log); + State->GlobalLog = PushStruct(State->Transient, event_log); *State->GlobalLog = {0}; s32 CommandQueueSize = 32; @@ -154,10 +154,10 @@ INITIALIZE_APPLICATION(InitializeApplication) #if 1 gs_const_string SculpturePath = ConstString("data/blumen_lumen_v2.fold"); - LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, SculpturePath, State->GlobalLog); + LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog); SculpturePath = ConstString("data/radialumia_v2.fold"); - LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, SculpturePath, State->GlobalLog); + LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog); #endif State->PixelsToWorldScale = .01f; @@ -184,11 +184,11 @@ INITIALIZE_APPLICATION(InitializeApplication) InitializePanelSystem(&State->PanelSystem); panel* Panel = TakeNewPanel(&State->PanelSystem); - SetPanelDefinition(Panel, PanelType_SculptureView, State); + SetPanelDefinition(Panel, PanelType_SculptureView, State, Context); } internal void -HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse_state Mouse) +HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse_state Mouse, context Context) { DEBUG_TRACK_FUNCTION; @@ -240,7 +240,7 @@ HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse for (s32 CommandIdx = State->CommandQueue.Used - 1; CommandIdx >= 0; CommandIdx--) { command_queue_entry* Entry = &State->CommandQueue.Commands[CommandIdx]; - Entry->Command.Proc(State, Entry->Event, Mouse); + Entry->Command.Proc(State, Entry->Event, Mouse, Context); } ClearCommandQueue(&State->CommandQueue); @@ -305,13 +305,13 @@ UPDATE_AND_RENDER(UpdateAndRender) // 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); + ClearArena(State->Transient); Context->Mouse.CursorType = CursorType_Arrow; PushRenderClearScreen(RenderBuffer); State->Camera.AspectRatio = RectAspectRatio(Context->WindowBounds); - HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse); + HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse, *Context); if (State->AnimationSystem.TimelineShouldAdvance) { // TODO(Peter): Revisit this. This implies that the framerate of the animation system @@ -331,9 +331,9 @@ UPDATE_AND_RENDER(UpdateAndRender) r32 FrameTime = CurrentFrame * State->AnimationSystem.SecondsPerFrame; u32 CurrentBlocksMax = State->AnimationSystem.LayersCount; - b8* CurrentBlocksFilled = PushArray(&State->Transient, b8, CurrentBlocksMax); + b8* CurrentBlocksFilled = PushArray(State->Transient, b8, CurrentBlocksMax); ZeroArray(CurrentBlocksFilled, b8, CurrentBlocksMax); - animation_block* CurrentBlocks = PushArray(&State->Transient, animation_block, CurrentBlocksMax); + animation_block* CurrentBlocks = PushArray(State->Transient, animation_block, CurrentBlocksMax); for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) { @@ -345,7 +345,7 @@ UPDATE_AND_RENDER(UpdateAndRender) CurrentBlocks[Block.Layer] = Block; } - led_buffer* LayerLEDBuffers = PushArray(&State->Transient, led_buffer, CurrentBlocksMax); + led_buffer* LayerLEDBuffers = PushArray(State->Transient, led_buffer, CurrentBlocksMax); for (u32 AssemblyIndex = 0; AssemblyIndex < State->Assemblies.Count; AssemblyIndex++) { assembly* Assembly = &State->Assemblies.Values[AssemblyIndex]; @@ -358,14 +358,14 @@ UPDATE_AND_RENDER(UpdateAndRender) // Prep Temp Buffer LayerLEDBuffers[Layer] = *AssemblyLedBuffer; - LayerLEDBuffers[Layer].Colors = PushArray(&State->Transient, pixel, AssemblyLedBuffer->LedCount); + LayerLEDBuffers[Layer].Colors = PushArray(State->Transient, pixel, AssemblyLedBuffer->LedCount); u32 FramesIntoBlock = CurrentFrame - Block.Range.Min; r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame; u32 AnimationProcIndex = Block.AnimationProcHandle - 1; animation_proc* AnimationProc = GlobalAnimationClips[AnimationProcIndex].Proc; - AnimationProc(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, &State->Transient); + AnimationProc(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, State->Transient); } // Consolidate Temp Buffers @@ -468,7 +468,7 @@ UPDATE_AND_RENDER(UpdateAndRender) State->Interface.RenderBuffer = RenderBuffer; State->Interface.Mouse = Context->Mouse; - panel_layout PanelsToRender = GetPanelLayout(&State->PanelSystem, State->WindowBounds, &State->Transient); + panel_layout PanelsToRender = GetPanelLayout(&State->PanelSystem, State->WindowBounds, State->Transient); DrawAllPanels(PanelsToRender, RenderBuffer, &Context->Mouse, State, *Context); for (s32 m = 0; m < State->Modes.ActiveModesCount; m++) @@ -476,7 +476,7 @@ UPDATE_AND_RENDER(UpdateAndRender) operation_mode OperationMode = State->Modes.ActiveModes[m]; if (OperationMode.Render != 0) { - OperationMode.Render(State, RenderBuffer, OperationMode, Context->Mouse); + OperationMode.Render(State, RenderBuffer, OperationMode, Context->Mouse, *Context); } } diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index c8e43c7..4874fe8 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -43,7 +43,7 @@ enum network_protocol struct app_state { gs_memory_arena Permanent; - gs_memory_arena Transient; + gs_memory_arena* Transient; // Engine // @@ -212,7 +212,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndCurrentOperationMode) DeactivateCurrentOperationMode(&State->Modes); } -#define PANEL_INIT_PROC(name) void name(panel* Panel, app_state* State) +#define PANEL_INIT_PROC(name) void name(panel* Panel, app_state* State, context Context) typedef PANEL_INIT_PROC(panel_init_proc); #define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State) diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index 8712d14..eb89378 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -252,6 +252,25 @@ struct temp_file_list temp_file_list_entry* Last; }; +internal void +Win32SetFileInfoFromFindFileData(gs_file_info* Info, WIN32_FIND_DATA FindFileData, gs_const_string SearchPath, gs_memory_arena* Storage) +{ + u32 FileNameLength = CharArrayLength(FindFileData.cFileName); + + // NOTE(Peter): String Storage + // Storing the string in the final storage means we don't have to copy the string later, and all + // strings will be continguous in memory at the calling site, though they will be before the array + gs_string FileName = PushString(Storage, SearchPath.Length + FileNameLength + 1); + PrintF(&FileName, "%S%.*s", SearchPath, FileName.Size, FindFileData.cFileName); + NullTerminate(&FileName); + + Info->FileSize = Win32HighLowToU64(FindFileData.nFileSizeLow, FindFileData.nFileSizeHigh); + Info->CreationTime = Win32FileTimeToU64(FindFileData.ftCreationTime); + Info->LastWriteTime = Win32FileTimeToU64(FindFileData.ftLastWriteTime); + Info->Path = FileName.ConstString; + Info->IsDirectory = HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY); +} + internal u32 Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* TempList, gs_const_string Path, gs_memory_arena* Storage, b32 Flags) { @@ -266,6 +285,8 @@ Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* { do { + b32 AddFile = true; + if (HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) { if (HasFlag(Flags, EnumerateDirectory_Recurse)) @@ -280,29 +301,14 @@ Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* } } - if (HasFlag(Flags, EnumerateDirectory_IncludeDirectories)) - { - FilesCount += 1; - } + AddFile = HasFlag(Flags, EnumerateDirectory_IncludeDirectories); } - else + + if (AddFile) { temp_file_list_entry* File = PushStruct(FileHandler.Transient, temp_file_list_entry); - File->Info.FileSize = Win32HighLowToU64(FindFileData.nFileSizeLow, FindFileData.nFileSizeHigh); - File->Info.CreationTime = Win32FileTimeToU64(FindFileData.ftCreationTime); - File->Info.LastWriteTime = Win32FileTimeToU64(FindFileData.ftLastWriteTime); - File->Next = 0; - - u32 FileNameLength = CharArrayLength(FindFileData.cFileName); - - // NOTE(Peter): String Storage - // Storing the string in the final storage means we don't have to copy the string later, and all - // strings will be continguous in memory at the calling site, though they will be before the array - gs_string FileName = PushString(Storage, SearchPath.Length + FileNameLength + 1); - PrintF(&FileName, "%S%.*s", SearchPath, FileName.Size, FindFileData.cFileName); - NullTerminate(&FileName); - File->Info.Path = FileName.ConstString; - + *File = {0}; + Win32SetFileInfoFromFindFileData(&File->Info, FindFileData, SearchPath, Storage); SLLPushOrInit(TempList->First, TempList->Last, File); FilesCount += 1; } diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp index d775d1e..0e67295 100644 --- a/src/gs_libs/gs_types.cpp +++ b/src/gs_libs/gs_types.cpp @@ -1861,35 +1861,7 @@ PrintFArgsList (gs_string* String, char* Format, va_list Args) { 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(String, (char)0); - FormatAt++; - } - else - { - OutChar(String, *FormatAt++); - } + OutChar(String, *FormatAt++); } else { diff --git a/src/gs_libs/gs_types.h b/src/gs_libs/gs_types.h index 8a9736e..78a5dea 100644 --- a/src/gs_libs/gs_types.h +++ b/src/gs_libs/gs_types.h @@ -772,6 +772,7 @@ struct gs_file_info u64 FileSize; u64 CreationTime; u64 LastWriteTime; + b32 IsDirectory; }; struct gs_file_info_array From 6491a88d8af6da6bdccb7cd366b564a0ace5fec8 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 7 Sep 2020 14:28:41 -0700 Subject: [PATCH 24/43] File lister now handles .. in directory names --- .../editor/panels/foldhaus_panel_file_view.h | 29 +++++++++++++---- src/gs_libs/gs_types.cpp | 31 +++++++++++++------ 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h index c38fc08..d050a5f 100644 --- a/src/app/editor/panels/foldhaus_panel_file_view.h +++ b/src/app/editor/panels/foldhaus_panel_file_view.h @@ -15,17 +15,23 @@ struct file_view_state input_command* FileView_Commands = 0; s32 FileView_CommandsCount = 0; -// TODO(pjs): 2 - On Change Dir function -// - clears the memory arena -// - enumerates the new directory in the memory arena - internal void FileViewUpdateWorkingDirectory(gs_const_string WorkingDirectory, file_view_state* State, context Context) { ClearArena(&State->FileNamesArena); + gs_const_string SanitizedDirectory = WorkingDirectory; + + u32 LastSlashIndex = FindLast(SanitizedDirectory, '\\'); + gs_const_string LastDir = Substring(SanitizedDirectory, LastSlashIndex + 1, SanitizedDirectory.Length); + if (StringsEqual(LastDir, ConstString(".."))) + { + u32 SecondLastSlashIndex = FindLast(SanitizedDirectory, LastSlashIndex - 1, '\\'); + SanitizedDirectory = Substring(SanitizedDirectory, 0, SecondLastSlashIndex); + } + State->WorkingDirectory = PushString(&State->FileNamesArena, WorkingDirectory.Length + 2); - PrintF(&State->WorkingDirectory, "%S", WorkingDirectory); + PrintF(&State->WorkingDirectory, "%S", SanitizedDirectory); if (State->WorkingDirectory.Str[State->WorkingDirectory.Length - 1] != '\\') { AppendPrintF(&State->WorkingDirectory, "\\"); @@ -80,7 +86,18 @@ FileView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuf gs_file_info File = FileViewState->FileNames.Values[i]; gs_string PathString = PushString(State->Transient, File.Path.Length); PrintF(&PathString, "%S", File.Path); - ui_LayoutDrawString(&State->Interface, &Layout, PathString, State->Interface.Style.TextColor); + if (ui_LayoutListButton(&State->Interface, &Layout, PathString, i)) + { + if (File.IsDirectory) + { + FileViewUpdateWorkingDirectory(File.Path, FileViewState, Context); + } + else + { + // TODO(pjs): Select the file + } + } + //ui_LayoutDrawString(&State->Interface, &Layout, PathString, State->Interface.Style.TextColor); } } diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp index 0e67295..a86c01c 100644 --- a/src/gs_libs/gs_types.cpp +++ b/src/gs_libs/gs_types.cpp @@ -1366,7 +1366,7 @@ CharArrayLength (char* CS) internal bool IsNullTerminated(gs_const_string String) { - return (String.Str[String.Length - 1] != 0); + return (String.Str[String.Length] == 0); } internal bool IsNullTerminated(gs_string String) @@ -1455,13 +1455,21 @@ FindFirst(gs_const_string String, char C) { return FindFirst(String, 0, C); } + internal u64 -FindLast(gs_const_string String, char C) +FindLast(gs_const_string String, u64 StartIndex, char C) { - s64 Result = String.Length - 1; + s64 Result = StartIndex; for(; Result >= 0 && C != String.Str[Result]; Result--); return (u64)Result; } + +internal u64 +FindLast(gs_const_string String, char C) +{ + return FindLast(String, String.Length - 1, C); +} + internal u64 FindFirstFromSet(gs_const_string String, char* SetArray) { @@ -2968,14 +2976,19 @@ CreateFileHandler(file_handler_get_file_info* GetFileInfo, internal gs_const_string GetNullTerminatedPath(gs_file_handler FileHandler, gs_const_string Path) { - gs_const_string NullTermPath = Path; - if (!IsNullTerminated(NullTermPath)) + gs_const_string Result = {}; + if (!IsNullTerminated(Path)) { - AssertMessage("need to allocate a new string, Path to it, and null terminate"); - // TODO(Peter): Probably want to have some sort of temp memory, - // or be passing in a thread context, etc. + gs_string NullTermPath = PushString(FileHandler.Transient, Path.Length + 1); + PrintF(&NullTermPath, "%S", Path); + NullTerminate(&NullTermPath); + Result = NullTermPath.ConstString; } - return NullTermPath; + else + { + Result = Path; + } + return Result; } internal gs_file_info From 3a732f95b80b9e67bb71b4a588ac28c1698969d6 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 7 Sep 2020 14:29:32 -0700 Subject: [PATCH 25/43] File lister now handles . in directory names --- src/app/editor/panels/foldhaus_panel_file_view.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/editor/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h index d050a5f..739475a 100644 --- a/src/app/editor/panels/foldhaus_panel_file_view.h +++ b/src/app/editor/panels/foldhaus_panel_file_view.h @@ -29,6 +29,10 @@ FileViewUpdateWorkingDirectory(gs_const_string WorkingDirectory, file_view_state u32 SecondLastSlashIndex = FindLast(SanitizedDirectory, LastSlashIndex - 1, '\\'); SanitizedDirectory = Substring(SanitizedDirectory, 0, SecondLastSlashIndex); } + else if (StringsEqual(LastDir, ConstString("."))) + { + SanitizedDirectory = Substring(SanitizedDirectory, 0, LastSlashIndex); + } State->WorkingDirectory = PushString(&State->FileNamesArena, WorkingDirectory.Length + 2); PrintF(&State->WorkingDirectory, "%S", SanitizedDirectory); From 01a20f41e78d04d03cd8756256c82fc9e8a86877 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 7 Sep 2020 14:35:58 -0700 Subject: [PATCH 26/43] File lister now displays current directory at top, and omits it from file names --- .../editor/panels/foldhaus_panel_file_view.h | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h index 739475a..3db4c08 100644 --- a/src/app/editor/panels/foldhaus_panel_file_view.h +++ b/src/app/editor/panels/foldhaus_panel_file_view.h @@ -57,12 +57,7 @@ FileView_Init(panel* Panel, app_state* State, context Context) file_view_state* FileViewState = PushStruct(&State->Permanent, file_view_state); Panel->PanelStateMemory = (u8*)FileViewState; FileViewState->FileNamesArena = CreateMemoryArena(Context.ThreadContext.Allocator); - -#if 0 - FileViewState->WorkingDirectory = MakeString(PushArray(&State->Permanent, char, 256), 256); - PrintF(&FileViewState->WorkingDirectory, "C:\\"); -#endif - FileViewUpdateWorkingDirectory(ConstString("C:\\projects\\Lumenarium\\src\\app"), FileViewState, Context); + FileViewUpdateWorkingDirectory(ConstString("."), FileViewState, Context); } GSMetaTag(panel_cleanup); @@ -82,14 +77,17 @@ FileView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuf ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); // Header - rect2 HeaderBounds = ui_ReserveElementBounds(&Layout); + ui_LayoutDrawString(&State->Interface, &Layout, FileViewState->WorkingDirectory, v4{0, 1, 0, 1}); // File Display for (u32 i = 0; i < FileViewState->FileNames.Count; i++) { gs_file_info File = FileViewState->FileNames.Values[i]; - gs_string PathString = PushString(State->Transient, File.Path.Length); - PrintF(&PathString, "%S", File.Path); + + u32 LastSlashIndex = FindLast(File.Path, '\\'); + 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, &Layout, PathString, i)) { if (File.IsDirectory) @@ -101,7 +99,6 @@ FileView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuf // TODO(pjs): Select the file } } - //ui_LayoutDrawString(&State->Interface, &Layout, PathString, State->Interface.Style.TextColor); } } From 78d44b93487880fe29140acb0e569e250679d82d Mon Sep 17 00:00:00 2001 From: PS Date: Thu, 1 Oct 2020 15:30:24 -0700 Subject: [PATCH 27/43] Created addressed_data_buffer as a universal way for systems to send data over various output devices. Cleaned up old SACN code, removed dmx as its not needed in its own right anymore. --- src/app/engine/dmx/dmx.h | 57 -------- src/app/engine/foldhaus_addressed_data.h | 78 ++++++++++ src/app/engine/foldhaus_assembly.h | 2 + src/app/engine/sacn/sacn.h | 46 ++++++ src/app/foldhaus_app.cpp | 136 ++++-------------- src/app/foldhaus_app.h | 6 +- src/app/platform_win32/win32_foldhaus.cpp | 167 ++-------------------- src/app/platform_win32/win32_serial.h | 81 +++++++++++ src/gs_libs/gs_types.h | 2 +- src/todo.txt | 24 ---- 10 files changed, 247 insertions(+), 352 deletions(-) delete mode 100644 src/app/engine/dmx/dmx.h create mode 100644 src/app/engine/foldhaus_addressed_data.h create mode 100644 src/app/platform_win32/win32_serial.h diff --git a/src/app/engine/dmx/dmx.h b/src/app/engine/dmx/dmx.h deleted file mode 100644 index ed8e8b7..0000000 --- a/src/app/engine/dmx/dmx.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// File: DMX_H -// Author: Peter Slattery -// Creation Date: 2020-01-01 -// -#ifndef DMX_H - -struct dmx_buffer -{ - s32 Universe; - u8* Base; - s32 TotalSize; - s32 HeaderSize; -}; - -struct dmx_buffer_list -{ - dmx_buffer Buffer; - dmx_buffer_list* Next; -}; - -internal dmx_buffer_list* -DMXBufferListGetTail (dmx_buffer_list* List) -{ - dmx_buffer_list* Result = 0; - if (List->Next == 0) - { - Result = List; - } - else - { - Result = DMXBufferListGetTail(List->Next); - } - return Result; -} - -internal dmx_buffer_list* -DMXBufferListAppend (dmx_buffer_list* AppendTo, dmx_buffer_list* Append) -{ - dmx_buffer_list* Result = 0; - - if (AppendTo) - { - dmx_buffer_list* Tail = DMXBufferListGetTail(AppendTo); - Tail->Next = Append; - Result = AppendTo; - } - else - { - Result = Append; - } - - return Result; -} - -#define DMX_H -#endif // DMX_H \ No newline at end of file diff --git a/src/app/engine/foldhaus_addressed_data.h b/src/app/engine/foldhaus_addressed_data.h new file mode 100644 index 0000000..6436a0d --- /dev/null +++ b/src/app/engine/foldhaus_addressed_data.h @@ -0,0 +1,78 @@ +// +// File: foldhaus_addressed_data.h +// Author: Peter Slattery +// Creation Date: 2020-10-01 +// +// addressed_data_buffer is a generic buffer of data that also contains information +// regarding how it should be sent to a sculpture. +// This decouples the encoding step from the sending step. +// +#ifndef FOLDHAUS_ADDRESSED_DATA_H + +enum data_buffer_address_type +{ + AddressType_NetworkIP, + AddressType_Invalid, +}; + +struct addressed_data_buffer +{ + u8* Memory; + u32 MemorySize; + + data_buffer_address_type AddressType; + + // IP Address + u32 V4SendAddress; + u32 SendPort; + + addressed_data_buffer* Next; +}; + +struct addressed_data_buffer_list +{ + addressed_data_buffer* Root; + addressed_data_buffer* Head; +}; + +internal addressed_data_buffer* +AddressedDataBufferList_Push(addressed_data_buffer_list* List, u32 BufferSize, gs_memory_arena* Storage) +{ + addressed_data_buffer* Result = PushStruct(Storage, addressed_data_buffer); + *Result = {0}; + Result->MemorySize = BufferSize; + Result->Memory = PushArray(Storage, u8, Result->MemorySize); + + SLLPushOrInit(List->Root, List->Head, Result); + + return Result; +} + +internal void +AddressedDataBuffer_SetNetworkAddress(addressed_data_buffer* Buffer, u32 V4SendAddress, u32 SendPort) +{ + Buffer->AddressType = AddressType_NetworkIP; + Buffer->V4SendAddress = V4SendAddress; + Buffer->SendPort = SendPort; +} + +internal void +AddressedDataBuffer_Send(addressed_data_buffer Buffer, platform_socket_handle SendSocket, context Context) +{ + u32 V4SendAddress = Buffer.V4SendAddress; + Context.PlatformSendTo(SendSocket, Buffer.V4SendAddress, Buffer.SendPort, (const char*)Buffer.Memory, Buffer.MemorySize, 0); +} + +internal void +AddressedDataBufferList_SendAll(addressed_data_buffer_list OutputData, platform_socket_handle SendSocket, context Context) +{ + for (addressed_data_buffer* BufferAt = OutputData.Root; + BufferAt != 0; + BufferAt = BufferAt->Next) + { + AddressedDataBuffer_Send(*BufferAt, SendSocket, Context); + } +} + +#define FOLDHAUS_ADDRESSED_DATA_H +#endif // FOLDHAUS_ADDRESSED_DATA_H \ No newline at end of file diff --git a/src/app/engine/foldhaus_assembly.h b/src/app/engine/foldhaus_assembly.h index 4a6cc85..a4ebd0e 100644 --- a/src/app/engine/foldhaus_assembly.h +++ b/src/app/engine/foldhaus_assembly.h @@ -90,5 +90,7 @@ struct assembly_array assembly* Values; }; +internal led_buffer* LedSystemGetBuffer(led_system* System, u32 Index); + #define FOLDHAUS_ASSEMBLY_H #endif // FOLDHAUS_ASSEMBLY_H \ No newline at end of file diff --git a/src/app/engine/sacn/sacn.h b/src/app/engine/sacn/sacn.h index a871cea..766c11e 100644 --- a/src/app/engine/sacn/sacn.h +++ b/src/app/engine/sacn/sacn.h @@ -343,6 +343,52 @@ SACNGetUniverseSendAddress(s32 Universe) return V4Address; } +internal void +SACN_FillBufferWithLeds(u8* BufferStart, u32 BufferSize, v2_strip Strip, led_buffer LedBuffer) +{ + u8* DestChannel = BufferStart; + for (u32 i = 0; i < Strip.LedCount; i++) + { + u32 LedIndex = Strip.LedLUT[i]; + pixel Color = LedBuffer.Colors[LedIndex]; + + DestChannel[0] = Color.R; + DestChannel[1] = Color.G; + DestChannel[2] = Color.B; + DestChannel += 3; + } +} + +internal void +SACN_BuildOutputData(streaming_acn* SACN, addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem, gs_memory_arena* OutputStorage) +{ + SACNUpdateSequence(SACN); + + // TODO(pjs): 512 is a magic number - make it a constant? + s32 BufferHeaderSize = STREAM_HEADER_SIZE; + s32 BufferBodySize = 512; + s32 BufferSize = BufferHeaderSize + BufferBodySize; + + for (u32 AssemblyIdx = 0; AssemblyIdx < Assemblies.Count; AssemblyIdx++) + { + assembly Assembly = Assemblies.Values[AssemblyIdx]; + led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); + + for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) + { + v2_strip StripAt = Assembly.Strips[StripIdx]; + + u32 V4SendAddress = SACNGetUniverseSendAddress(StripAt.StartUniverse); + u32 SendPort = DEFAULT_STREAMING_ACN_PORT; + + addressed_data_buffer* Data = AddressedDataBufferList_Push(Output, BufferSize, OutputStorage); + AddressedDataBuffer_SetNetworkAddress(Data, V4SendAddress, SendPort); + + SACNPrepareBufferHeader(StripAt.StartUniverse, Data->Memory, Data->MemorySize, BufferHeaderSize, *SACN); + SACN_FillBufferWithLeds(Data->Memory + BufferHeaderSize, BufferBodySize, StripAt, *LedBuffer); + } + } +} #define SACN_H #endif // SACN_H \ No newline at end of file diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 519554b..b714b7a 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -8,35 +8,6 @@ #include "foldhaus_platform.h" #include "foldhaus_app.h" -struct send_sacn_job_data -{ - - platform_socket_handle SendSocket; - platform_send_to* SendTo; - dmx_buffer_list* DMXBuffers; -}; - -internal void -SACNSendDMXBufferListJob (s32 ThreadID, void* JobData) -{ - DEBUG_TRACK_FUNCTION; - - send_sacn_job_data* Data = (send_sacn_job_data*)JobData; - platform_socket_handle SendSocket = Data->SendSocket; - - dmx_buffer_list* DMXBufferAt = Data->DMXBuffers; - while (DMXBufferAt) - { - dmx_buffer Buffer = DMXBufferAt->Buffer; - - u32 V4SendAddress = SACNGetUniverseSendAddress(Buffer.Universe); - - Data->SendTo(SendSocket, V4SendAddress, DEFAULT_STREAMING_ACN_PORT, (const char*)Buffer.Base, Buffer.TotalSize, 0); - - DMXBufferAt = DMXBufferAt->Next; - } -} - //////////////////////////////////////////////////////////////////////// RELOAD_STATIC_DATA(ReloadStaticData) @@ -246,56 +217,6 @@ HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse ClearCommandQueue(&State->CommandQueue); } -internal dmx_buffer_list* -CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, gs_memory_arena* Arena) -{ - DEBUG_TRACK_FUNCTION; - - led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); - - dmx_buffer_list* Result = 0; - dmx_buffer_list* Head = 0; - - s32 BufferSize = BufferHeaderSize + 512; - - for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++) - { - v2_strip Strip = Assembly.Strips[StripIndex]; - - dmx_buffer_list* NewBuffer = PushStruct(Arena, dmx_buffer_list); - NewBuffer->Buffer.Universe = Strip.StartUniverse; - - NewBuffer->Buffer.Base = PushArray(Arena, u8, BufferSize); - NewBuffer->Buffer.TotalSize = BufferSize; - NewBuffer->Buffer.HeaderSize = BufferHeaderSize; - NewBuffer->Next = 0; - - // Append - if (!Result) { - Result = NewBuffer; - Head = Result; - } - Head->Next = NewBuffer; - Head = NewBuffer; - - u8* DestChannel = Head->Buffer.Base + BufferHeaderSize; - - for (u32 i = 0; i < Strip.LedCount; i++) - { - u32 LedIndex = Strip.LedLUT[i]; - pixel Color = LedBuffer->Colors[LedIndex]; - - DestChannel[0] = Color.R; - DestChannel[1] = Color.G; - DestChannel[2] = Color.B; - DestChannel += 3; - } - } - - return Result; -} - - UPDATE_AND_RENDER(UpdateAndRender) { DEBUG_TRACK_FUNCTION; @@ -420,44 +341,35 @@ UPDATE_AND_RENDER(UpdateAndRender) } } - // Skipped for performance at the moment -#if 0 - dmx_buffer_list* DMXBuffers = 0; - for (u32 i = 0; i < State->Assemblies.Count; i++) + addressed_data_buffer_list OutputData = {0}; + switch (State->NetworkProtocol) { - assembly* Assembly = &State->Assemblies.Values[i]; - dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, &State->LedSystem, STREAM_HEADER_SIZE, &State->Transient); - DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); + case NetworkProtocol_SACN: + { + SACN_BuildOutputData(&State->SACN, &OutputData, State->Assemblies, &State->LedSystem, State->Transient); + }break; + + case NetworkProtocol_UART: + { + //UART_BuildOutputData(&OutputData, State, State->Transient); + }break; + + case NetworkProtocol_ArtNet: + InvalidDefaultCase; } - //DEBUG_IF(GlobalDebugServices->Interface.SendSACNData) + if (0) { - switch (State->NetworkProtocol) - { - case NetworkProtocol_SACN: - { - SACNUpdateSequence(&State->SACN); - - dmx_buffer_list* CurrentDMXBuffer = DMXBuffers; - while (CurrentDMXBuffer) - { - dmx_buffer Buffer = CurrentDMXBuffer->Buffer; - SACNPrepareBufferHeader(Buffer.Universe, Buffer.Base, Buffer.TotalSize, Buffer.HeaderSize, State->SACN); - CurrentDMXBuffer = CurrentDMXBuffer->Next; - } - - send_sacn_job_data* Job = PushStruct(&State->Transient, send_sacn_job_data); - Job->SendSocket = State->SACN.SendSocket; - Job->SendTo = Context->PlatformSendTo; - Job->DMXBuffers = DMXBuffers; - - Context->GeneralWorkQueue->PushWorkOnQueue(Context->GeneralWorkQueue, SACNSendDMXBufferListJob, Job, "SACN Send Data Job"); - }break; - - InvalidDefaultCase; - } + // TODO(pjs): This should happen on another thread + AddressedDataBufferList_SendAll(OutputData, State->SACN.SendSocket, *Context); + + /* +Saved this lien as an example of pushing onto a queue + Context->GeneralWorkQueue->PushWorkOnQueue(Context->GeneralWorkQueue, SACNSendDMXBufferListJob, Job, "SACN Send Data Job"); +*/ } -#endif + + // Skipped for performance at the moment diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 4874fe8..e3b5532 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -14,12 +14,13 @@ #include "interface.h" #include "engine/foldhaus_network_ordering.h" -#include "engine/dmx/dmx.h" -#include "engine/sacn/sacn.h" #include "engine/foldhaus_assembly.h" #include "engine/assembly_parser.cpp" +#include "engine/foldhaus_addressed_data.h" +#include "engine/sacn/sacn.h" + typedef struct app_state app_state; // TODO(Peter): something we can do later is to remove all reliance on app_state and context @@ -36,6 +37,7 @@ enum network_protocol { NetworkProtocol_SACN, NetworkProtocol_ArtNet, + NetworkProtocol_UART, NetworkProtocol_Count, }; diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index eb89378..b835199 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -18,6 +18,7 @@ #include "win32_foldhaus_memory.h" #include "win32_foldhaus_dll.h" #include "win32_foldhaus_timing.h" +#include "win32_serial.h" #include "../foldhaus_renderer.cpp" @@ -951,6 +952,10 @@ v4 ToScreen(v4 P, rect2 WindowBounds) return Result; } +// +// Serial +// + int WINAPI WinMain ( HINSTANCE HInstance, @@ -961,168 +966,18 @@ WinMain ( { gs_thread_context ThreadContext = Win32CreateThreadContext(); - { - m44 Before = m44{ - 0, 1, 2, 3, - 4, 5, 6, 7, - 8, 9, 10, 11, - 12, 13, 14, 15 - }; - m44 After = M44Transpose(Before); - OutputDebugStringA("Before:\n"); - PrintMatrix(Before, ThreadContext); - OutputDebugStringA("\n\n"); - OutputDebugStringA("After:\n"); - PrintMatrix(After, ThreadContext); - OutputDebugStringA("\n\n"); - - } { - v4 Before = {1, 2, 3, 4}; - m44 Transform = {}; - for (u32 i = 0; i < 16; i++) - { - Transform.Array[i] = i + 1; - } - v4 After = Transform * Before; - Assert(V4Mag(After - v4{30, 70, 110, 150}) < .00000001f); + gs_const_string TestString = ConstString("Hello World!\nTesting\n"); + + HANDLE SerialPortHandle = Win32SerialPort_Open("COM5"); + Win32SerialPort_SetState(SerialPortHandle, 9600, 8, 0, 1); + Win32SerialPort_Write(SerialPortHandle, StringToData(TestString)); + Win32SerialPort_Close(SerialPortHandle); } - { // Translation - v4 Before = {0, 0, 0, 1}; - m44 Translation = M44Translation(v4{5, 5, 5, 0}); - v4 After = Translation * Before; - Assert((After == v4{5, 5, 5, 1})); - } - { // X Rotation - v4 Before = {0, 5, 0, 1}; - m44 Forward = M44RotationX(HalfPiR32); - m44 Backward = M44RotationX(-HalfPiR32); - v4 After = Forward * Before; - Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); - After = Backward * Before; - Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); - } - { // Y Rotation - v4 Before = {5, 0, 0, 1}; - m44 Forward = M44RotationY(HalfPiR32); - m44 Backward = M44RotationY(-HalfPiR32); - v4 After = Forward * Before; - Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); - After = Backward * Before; - Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); - } - - { // Z Rotation - v4 Before = {0, 5, 0, 1}; - m44 Forward = M44RotationZ(HalfPiR32); - m44 Backward = M44RotationZ(-HalfPiR32); - v4 After = Forward * Before; - Assert(V4Mag(After - v4{-5, 0, 0, 1}) < .000001f); - After = Backward * Before; - Assert(V4Mag(After - v4{5, 0, 0, 1}) < .000001f); - } - - { // Combined X Rotation - v4 Before = {0, 5, 0, 1}; - m44 Forward = M44Rotation(v3{HalfPiR32, 0, 0}); - m44 Backward = M44Rotation(v3{-HalfPiR32, 0, 0}); - v4 After = Forward * Before; - Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); - After = Backward * Before; - Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); - } - - { // Combined Y Rotation - v4 Before = {5, 0, 0, 1}; - m44 Forward = M44Rotation(v3{0, HalfPiR32, 0}); - m44 Backward = M44Rotation(v3{0, -HalfPiR32, 0}); - v4 After = Forward * Before; - Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); - After = Backward * Before; - Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); - } - - { // Combined Z Rotation - v4 Before = {0, 5, 0, 1}; - m44 Forward = M44Rotation(v3{0, 0, HalfPiR32}); - m44 Backward = M44Rotation(v3{0, 0, -HalfPiR32}); - v4 After = Forward * Before; - Assert(V4Mag(After - v4{-5, 0, 0, 1}) < .000001f); - After = Backward * Before; - Assert(V4Mag(After - v4{5, 0, 0, 1}) < .000001f); - } - - { // Translate then Rotate - v4 Before = v4{0, 0, 0, 1}; - - m44 Translation = M44Translation(v4{5, 0, 0, 0}); - m44 Rotation = M44Rotation(v3{0, 0, HalfPiR32}); - m44 Composite = Rotation * Translation; - - v4 Inbetween = Translation * Before; - v4 After = Rotation * Inbetween; - Assert(V4Mag(After - v4{0, 5, 0, 1}) < .000001f); - - After = Composite * Before; - Assert(V4Mag(After - v4{0, 5, 0, 1}) < .000001f); - } - - { // Two translations - v4 Before = v4{0, 0, 0, 1}; - m44 TranslationA = M44Translation(v4{5, 0, 0, 0}); - m44 TranslationB = M44Translation(v4{0, 5, 0, 0}); - v4 After = TranslationB * TranslationA * Before; - Assert(V4Mag(After - v4{5, 5, 0, 1}) < .000001f); - } - - { // Perspective Transform - rect2 WindowBounds = rect2{ - v2{0, 0}, - v2{1440.0f, 768.0f}, - }; - - m44 Matrix = M44Translation(v4{0, 0, -200, 0}) * M44Rotation(v3{0, DegToRadR32(45), 0}); - m44 Projection = M44ProjectionPerspective(45, RectAspectRatio(WindowBounds), 0.1f, 500); - - r32 Rad = 25; - v4 P0 = Matrix * v4{-Rad, -Rad, 0, 1}; - v4 P1 = Matrix * v4{Rad, -Rad, 0, 1}; - v4 P2 = Matrix * v4{Rad, Rad, 0, 1}; - v4 P3 = Matrix * v4{-Rad, Rad, 0, 1}; - - v4 P0P = Projection * P0; - v4 P1P = Projection * P1; - v4 P2P = Projection * P2; - v4 P3P = Projection * P3; - - v4 P0PD = PerspectiveDivide(P0P); - v4 P1PD = PerspectiveDivide(P1P); - v4 P2PD = PerspectiveDivide(P2P); - v4 P3PD = PerspectiveDivide(P3P); - - v4 P0S = ToScreen(P0PD, WindowBounds); - P0S.w = 1; - - v4 P1S = ToScreen(P1PD, WindowBounds); - P1S.w = 1; - - v4 P2S = ToScreen(P2PD, WindowBounds); - P2S.w = 1; - - v4 P3S = ToScreen(P3PD, WindowBounds); - P3S.w = 1; - - Assert(V4Mag(P0S - v4{630.11401, 256.88202, 0.99930286, 1}) < 0.00001f); - Assert(V4Mag(P1S - v4{795.28662, 277.52859, 0.99948108, 1}) < 0.00001f); - Assert(V4Mag(P2S - v4{795.28662, 490.47144, 0.99948108, 1}) < 0.00001f); - Assert(V4Mag(P3S - v4{630.11401, 511.11798, 0.99930286, 1}) < 0.00001f); - - //PushRenderQuad2D(RenderBuffer, P0S.xy, P1S.xy, P2S.xy, P3S.xy, WhiteV4); - } MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); Win32UpdateWindowDimension(&MainWindow); diff --git a/src/app/platform_win32/win32_serial.h b/src/app/platform_win32/win32_serial.h new file mode 100644 index 0000000..31f4d73 --- /dev/null +++ b/src/app/platform_win32/win32_serial.h @@ -0,0 +1,81 @@ +// +// File: win32_serial.h +// Author: Peter Slattery +// Creation Date: 2020-10-01 +// +#ifndef WIN32_SERIAL_H + +DCB +Win32SerialPort_GetState(HANDLE ComPortHandle) +{ + 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) +{ + DCB ControlSettings = Win32SerialPort_GetState(ComPortHandle); + //PrintCommState(ControlSettings); + + // TODO(pjs): Validate BaudRate - There's only certain rates that are valid right? + ControlSettings.BaudRate = BaudRate; + ControlSettings.ByteSize = ByteSize; + ControlSettings.Parity = Parity; + ControlSettings.StopBits = StopBits; + + bool Success = SetCommState(ComPortHandle, &ControlSettings); +} + +HANDLE +Win32SerialPort_Open(char* PortName) +{ + HANDLE 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); + + if (ComPortHandle == INVALID_HANDLE_VALUE) + { + // Error + s32 Error = GetLastError(); + InvalidCodePath; + } + + return ComPortHandle; +} + +void +Win32SerialPort_Close(HANDLE PortHandle) +{ + CloseHandle(PortHandle); +} + +void +Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer) +{ + DWORD BytesWritten = 0; + if (WriteFile(PortHandle, Buffer.Memory, Buffer.Size, &BytesWritten, NULL)) + { + if (BytesWritten != Buffer.Size) + { + OutputDebugString("Error: Entire buffer not written.\n"); + } + } + else + { + OutputDebugStringA("Error: Unable to write to port\n"); + } +} + +#define WIN32_SERIAL_H +#endif // WIN32_SERIAL_H \ No newline at end of file diff --git a/src/gs_libs/gs_types.h b/src/gs_libs/gs_types.h index 78a5dea..e36f2ed 100644 --- a/src/gs_libs/gs_types.h +++ b/src/gs_libs/gs_types.h @@ -292,7 +292,7 @@ CopyMemory_(u8* From, u8* To, u64 Size) #define StaticArrayLength(arr) sizeof(arr) / sizeof((arr)[0]) #define ZeroMemoryBlock(mem,size) ZeroMemory_((u8*)(mem), (size)) -#define ZeroStruct(str) ZeroMemory_((str), sizeof(str)) +#define ZeroStruct(str) ZeroMemory_((u8*)(str), sizeof(*str)) #define ZeroArray(arr, type, count) ZeroMemory_((u8*)(arr), sizeof(type) * (count)) #define CopyArray(from, to, type, count) CopyMemory_((u8*)(from), (u8*)(to), sizeof(type) * (count)) diff --git a/src/todo.txt b/src/todo.txt index 3f3dca5..e82c742 100644 --- a/src/todo.txt +++ b/src/todo.txt @@ -14,7 +14,6 @@ STREAM #1: 3D Overhaul - leds always face camera - Sculptures - - implicitly add a tag equal to the sculpture name to each strip of leds - cache led vertex buffers - custom sculpture update functions (for motion) - editing sculpture files (change universe output) @@ -53,8 +52,6 @@ STREAM #1: 3D Overhaul - saving projects STRAM #4: Completeness -- Win32 Platform Layer - - Enumerate Directory Contents (you started this in win32_foldhaus_fileio.h) - Platform Layer - Mac Platform Layer @@ -85,27 +82,6 @@ Assembly -> SACN interface BUGS - Typing a period into a float value doesn't register. Problem here is that we arent' translating key presses into characters at the win32 layer. Need to do that. -Switch To Nodes -- BUG: Connect a solid color node to output then try and pick a color. I think temporary node buffers are -- overwriting other data when they get evaluated. Bigger solution is to create a system of working -- led buffers that get assigned to nodes as needed. -- gonna need to remove output node from the node lister -- delete nodes -- - Simplify node storage -- - investigate if node connections can be operated on separately from the node headers -- - UpdatedThisFrame can probably go into each connection -- - Allow insertion/deletion within connection table -- - Allow inerstion/deletion within header table -- - maintain free list of connections and headers -- separate node functionality from drawing the nodes -- - pull node position, size, etc out into a parallel data structure. after split names: node_header, interface_node -- - create separate files: foldhaus_node_engine, foldhaus_node_gui -- - store interface_nodes in binary tree -- - allow panning and zooming around the node canvas -- - Investigate why we're giving nodes bounds :NodesDontNeedToKnowTheirBounds -- selector node (has a list of connections that it can switch between) -- evaluation step (one node at a time) - Hardening - Then we want to think about separating out mode render functions from mode update functions. Not sure its necessary but having something that operates like an update funciton but is called render is weird. Might want some sort of coroutine functionality in place, where modes can add and remove optional, parallel update functions From 0022efea8eb7e58f810b806a957eb06a1679d203 Mon Sep 17 00:00:00 2001 From: PS Date: Thu, 1 Oct 2020 15:41:32 -0700 Subject: [PATCH 28/43] Naming convention updates, separated out the work queue into its own file --- src/app/engine/sacn/sacn.h | 16 +- src/app/foldhaus_app.cpp | 56 ++- src/app/platform_win32/win32_foldhaus.cpp | 468 +----------------- .../platform_win32/win32_foldhaus_fileio.h | 242 +++++++++ ...win32_serial.h => win32_foldhaus_serial.h} | 0 src/app/platform_win32/win32_foldhaus_utils.h | 75 +++ .../win32_foldhaus_work_queue.h | 155 ++++++ 7 files changed, 513 insertions(+), 499 deletions(-) rename src/app/platform_win32/{win32_serial.h => win32_foldhaus_serial.h} (100%) create mode 100644 src/app/platform_win32/win32_foldhaus_utils.h create mode 100644 src/app/platform_win32/win32_foldhaus_work_queue.h diff --git a/src/app/engine/sacn/sacn.h b/src/app/engine/sacn/sacn.h index 766c11e..a12c4b8 100644 --- a/src/app/engine/sacn/sacn.h +++ b/src/app/engine/sacn/sacn.h @@ -292,7 +292,7 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, // internal streaming_acn -InitializeSACN (context Context) +SACN_Initialize (context Context) { streaming_acn SACN = {}; @@ -304,13 +304,13 @@ InitializeSACN (context Context) } internal void -SACNCleanup(streaming_acn* SACN, context Context) +SACN_Cleanup(streaming_acn* SACN, context Context) { Context.PlatformCloseSocket(SACN->SendSocket); } internal void -SACNUpdateSequence (streaming_acn* SACN) +SACN_UpdateSequence (streaming_acn* SACN) { // Never use 0 after the first one if (++SACN->SequenceIterator == 0) @@ -320,7 +320,7 @@ SACNUpdateSequence (streaming_acn* SACN) } internal void -SACNPrepareBufferHeader (s32 Universe, u8* Buffer, s32 BufferSize, s32 SizeReservedForHeader, streaming_acn SACN) +SACN_PrepareBufferHeader (s32 Universe, u8* Buffer, s32 BufferSize, s32 SizeReservedForHeader, streaming_acn SACN) { Assert(SizeReservedForHeader == STREAM_HEADER_SIZE); Assert(Buffer && BufferSize > 0); @@ -331,7 +331,7 @@ SACNPrepareBufferHeader (s32 Universe, u8* Buffer, s32 BufferSize, s32 SizeReser } internal u32 -SACNGetUniverseSendAddress(s32 Universe) +SACN_GetUniverseSendAddress(s32 Universe) { u8 MulticastAddressBuffer[4] = {}; MulticastAddressBuffer[0] = 239; @@ -362,7 +362,7 @@ SACN_FillBufferWithLeds(u8* BufferStart, u32 BufferSize, v2_strip Strip, led_buf internal void SACN_BuildOutputData(streaming_acn* SACN, addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem, gs_memory_arena* OutputStorage) { - SACNUpdateSequence(SACN); + SACN_UpdateSequence(SACN); // TODO(pjs): 512 is a magic number - make it a constant? s32 BufferHeaderSize = STREAM_HEADER_SIZE; @@ -378,13 +378,13 @@ SACN_BuildOutputData(streaming_acn* SACN, addressed_data_buffer_list* Output, as { v2_strip StripAt = Assembly.Strips[StripIdx]; - u32 V4SendAddress = SACNGetUniverseSendAddress(StripAt.StartUniverse); + u32 V4SendAddress = SACN_GetUniverseSendAddress(StripAt.StartUniverse); u32 SendPort = DEFAULT_STREAMING_ACN_PORT; addressed_data_buffer* Data = AddressedDataBufferList_Push(Output, BufferSize, OutputStorage); AddressedDataBuffer_SetNetworkAddress(Data, V4SendAddress, SendPort); - SACNPrepareBufferHeader(StripAt.StartUniverse, Data->Memory, Data->MemorySize, BufferHeaderSize, *SACN); + SACN_PrepareBufferHeader(StripAt.StartUniverse, Data->Memory, Data->MemorySize, BufferHeaderSize, *SACN); SACN_FillBufferWithLeds(Data->Memory + BufferHeaderSize, BufferBodySize, StripAt, *LedBuffer); } } diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index b714b7a..8914b3c 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -111,7 +111,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Interface.Style.Margin = v2{5, 5}; State->Interface.Style.RowHeight = ui_GetTextLineHeight(State->Interface); - State->SACN = InitializeSACN(Context); + State->SACN = SACN_Initialize(Context); State->Camera.FieldOfView = 45.0f; State->Camera.AspectRatio = RectAspectRatio(State->WindowBounds); @@ -341,37 +341,39 @@ UPDATE_AND_RENDER(UpdateAndRender) } } - addressed_data_buffer_list OutputData = {0}; - switch (State->NetworkProtocol) { - case NetworkProtocol_SACN: + // NOTE(pjs): Building data buffers to be sent out to the sculpture + + addressed_data_buffer_list OutputData = {0}; + switch (State->NetworkProtocol) { - SACN_BuildOutputData(&State->SACN, &OutputData, State->Assemblies, &State->LedSystem, State->Transient); - }break; + case NetworkProtocol_SACN: + { + SACN_BuildOutputData(&State->SACN, &OutputData, State->Assemblies, &State->LedSystem, State->Transient); + }break; + + case NetworkProtocol_UART: + { + //UART_BuildOutputData(&OutputData, State, State->Transient); + }break; + + case NetworkProtocol_ArtNet: + InvalidDefaultCase; + } - case NetworkProtocol_UART: + // NOTE(pjs): Executing the job to actually send the data + if (0) { - //UART_BuildOutputData(&OutputData, State, State->Transient); - }break; - - case NetworkProtocol_ArtNet: - InvalidDefaultCase; + // TODO(pjs): This should happen on another thread + AddressedDataBufferList_SendAll(OutputData, State->SACN.SendSocket, *Context); + + /* + Saved this lien as an example of pushing onto a queue + Context->GeneralWorkQueue->PushWorkOnQueue(Context->GeneralWorkQueue, SACNSendDMXBufferListJob, Job, "SACN Send Data Job"); + */ + } } - if (0) - { - // TODO(pjs): This should happen on another thread - AddressedDataBufferList_SendAll(OutputData, State->SACN.SendSocket, *Context); - - /* -Saved this lien as an example of pushing onto a queue - Context->GeneralWorkQueue->PushWorkOnQueue(Context->GeneralWorkQueue, SACNSendDMXBufferListJob, Job, "SACN Send Data Job"); -*/ - } - - // Skipped for performance at the moment - - PushRenderOrthographic(RenderBuffer, State->WindowBounds); PushRenderClearScreen(RenderBuffer); @@ -412,7 +414,7 @@ Saved this lien as an example of pushing onto a queue CLEANUP_APPLICATION(CleanupApplication) { app_state* State = (app_state*)Context.MemoryBase; - SACNCleanup(&State->SACN, Context); + SACN_Cleanup(&State->SACN, Context); } #define FOLDHAUS_APP_CPP diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index b835199..338f957 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -15,10 +15,13 @@ #include "../foldhaus_platform.h" #include "../../gs_libs/gs_win32.cpp" +#include "win32_foldhaus_utils.h" #include "win32_foldhaus_memory.h" +#include "win32_foldhaus_fileio.h" #include "win32_foldhaus_dll.h" #include "win32_foldhaus_timing.h" -#include "win32_serial.h" +#include "win32_foldhaus_work_queue.h" +#include "win32_foldhaus_serial.h" #include "../foldhaus_renderer.cpp" @@ -31,469 +34,6 @@ char DLLLockFileName[] = "lock.tmp"; window MainWindow; -// Utils - -internal gs_string -Win32DumpErrorAndPrepareMessageBoxString(gs_memory_arena* Arena, char* Format, ...) -{ - s32 Error = GetLastError(); - gs_string ErrorDump = PushString(Arena, 4096); - PrintF(&ErrorDump, - R"FOO(Win32 Error: %s\n -Error Code: %d\n - )FOO", - __FUNCTION__, - Error); - - va_list Args; - va_start(Args, Format); - PrintFArgsList(&ErrorDump, Format, Args); - va_end(Args); - - gs_data ErrorDumpData = StringToData(ErrorDump); - - HANDLE FileHandle = CreateFileA("./crashdump.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (FileHandle != INVALID_HANDLE_VALUE) - { - DWORD BytesWritten = 0; - if (WriteFile(FileHandle, ErrorDumpData.Memory, ErrorDumpData.Size, &BytesWritten, NULL)) - { - - } - CloseHandle(FileHandle); - } - - AppendPrintF(&ErrorDump, "Program will attempt to continue. See crashdump.txt for info"); - NullTerminate(&ErrorDump); - - return ErrorDump; -} - -DEBUG_PRINT(Win32DebugPrint) -{ - Assert(IsNullTerminated(Message)); - OutputDebugStringA(Message.Str); -} - -#define PrintLastError() PrintLastError_(__FILE__, __LINE__) -internal void -PrintLastError_(char* File, u32 Line) -{ - char DebugStringData[256]; - gs_string DebugString = MakeString(DebugStringData, 0, 256); - u32 Error = GetLastError(); - PrintF(&DebugString, "%s Line %d: Win32 Error %d\n\0", File, Line, Error); - OutputDebugStringA(DebugString.Str); -} - - -internal HINSTANCE -GetHInstance() -{ - HINSTANCE Result = GetModuleHandle(NULL); - if (Result == NULL) - { - PrintLastError(); - } - return Result; -} - -/////////////////////// -// -// Fie I/O - -internal u64 -Win32HighLowToU64(u32 LowPart, u32 HighPart) -{ - ULARGE_INTEGER Time = {}; - Time.LowPart = LowPart; - Time.HighPart = HighPart; - u64 Result = Time.QuadPart; - return Result; -} - -internal u64 -Win32FileTimeToU64(FILETIME FileTime) -{ - u64 Result = Win32HighLowToU64(FileTime.dwLowDateTime, FileTime.dwHighDateTime); - return Result; -} - -GET_FILE_INFO(Win32GetFileInfo) -{ - Assert(IsNullTerminated(Path)); - gs_file_info Result = {}; - HANDLE FileHandle = CreateFileA(Path.Str, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (FileHandle != INVALID_HANDLE_VALUE) - { - Result.Path = Path; - Result.FileSize = (u64)GetFileSize(FileHandle, NULL) + 1; - FILETIME CreationTime, LastWriteTime; - if (GetFileTime(FileHandle, &CreationTime, (LPFILETIME)0, &LastWriteTime)) - { - Result.CreationTime = Win32FileTimeToU64(CreationTime); - Result.LastWriteTime = Win32FileTimeToU64(LastWriteTime); - } - else - { - PrintLastError(); - } - CloseHandle(FileHandle); - } - return Result; -} - -READ_ENTIRE_FILE(Win32ReadEntireFile) -{ - Assert(DataIsNonEmpty(Memory)); - Assert(IsNullTerminated(Path)); - - gs_file Result = {0}; - u32 Error = 0; - Result.FileInfo.Path = Path; - - HANDLE FileHandle = CreateFileA(Path.Str, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (FileHandle != INVALID_HANDLE_VALUE) - { - DWORD BytesRead = 0; - if (ReadFile(FileHandle, (LPVOID)Memory.Memory, Memory.Size - 1, (LPDWORD)(&BytesRead), NULL)) - { - Memory.Memory[Memory.Size - 1] = 0; - Result.Data = Memory; - - gs_string AbsolutePath = PushString(FileHandler.Transient, 512); - AbsolutePath.Length = GetFullPathNameA(Path.Str, AbsolutePath.Size, AbsolutePath.Str, NULL); - if (AbsolutePath.Length == 0) - { - Error = GetLastError(); - InvalidCodePath; - } - Result.FileInfo.AbsolutePath = AbsolutePath.ConstString; - } - else - { - // NOTE(Peter): If we get to this error case, it means that the file exists, - // and was successfully opened, but we can't read from it. I'm choosing to - // treat this as a legitimate error at this point. - gs_string Message = Win32DumpErrorAndPrepareMessageBoxString(FileHandler.Transient, "Attempting to read file: %S", Path); - if (MessageBox(NULL, Message.Str, "Error", MB_OK) == IDOK) - { - PostQuitMessage(-1); - } - } - CloseHandle(FileHandle); - } - else - { - - } - - return Result; -} - -WRITE_ENTIRE_FILE(Win32WriteEntireFile) -{ - Assert(DataIsNonEmpty(Data)); - Assert(IsNullTerminated(Path)); - - bool Success = false; - HANDLE FileHandle = CreateFileA(Path.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)) - { - Success = (BytesWritten == Data.Size); - } - else - { - gs_string Message = Win32DumpErrorAndPrepareMessageBoxString(FileHandler.Transient, "Attempting to write to file: %S", Path); - MessageBox(NULL, Message.Str, "Error", MB_OK); - } - CloseHandle(FileHandle); - } - else - { - - } - - return Success; -} - -internal FILETIME -GetFileLastWriteTime(char* Path) -{ - FILETIME Result = {}; - - WIN32_FIND_DATA FindData = {}; - HANDLE FileHandle = FindFirstFileA(Path, &FindData); - - if (FileHandle != INVALID_HANDLE_VALUE) - { - Result = FindData.ftLastWriteTime; - FindClose(FileHandle); - } - else - { - // TODO(Peter): :ErrorLogging - } - - return Result; -} - -struct temp_file_list_entry -{ - gs_file_info Info; - temp_file_list_entry* Next; -}; - -struct temp_file_list -{ - temp_file_list_entry* First; - temp_file_list_entry* Last; -}; - -internal void -Win32SetFileInfoFromFindFileData(gs_file_info* Info, WIN32_FIND_DATA FindFileData, gs_const_string SearchPath, gs_memory_arena* Storage) -{ - u32 FileNameLength = CharArrayLength(FindFileData.cFileName); - - // NOTE(Peter): String Storage - // Storing the string in the final storage means we don't have to copy the string later, and all - // strings will be continguous in memory at the calling site, though they will be before the array - gs_string FileName = PushString(Storage, SearchPath.Length + FileNameLength + 1); - PrintF(&FileName, "%S%.*s", SearchPath, FileName.Size, FindFileData.cFileName); - NullTerminate(&FileName); - - Info->FileSize = Win32HighLowToU64(FindFileData.nFileSizeLow, FindFileData.nFileSizeHigh); - Info->CreationTime = Win32FileTimeToU64(FindFileData.ftCreationTime); - Info->LastWriteTime = Win32FileTimeToU64(FindFileData.ftLastWriteTime); - Info->Path = FileName.ConstString; - Info->IsDirectory = HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY); -} - -internal u32 -Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* TempList, gs_const_string Path, gs_memory_arena* Storage, b32 Flags) -{ - u32 FilesCount = 0; - - u32 IndexOfLastSlash = FindLastFromSet(Path, "\\/"); - gs_const_string SearchPath = Substring(Path, 0, IndexOfLastSlash + 1); - - WIN32_FIND_DATA FindFileData; - HANDLE SearchHandle = FindFirstFile(Path.Str, &FindFileData); - if (SearchHandle != INVALID_HANDLE_VALUE) - { - do - { - b32 AddFile = true; - - if (HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) - { - if (HasFlag(Flags, EnumerateDirectory_Recurse)) - { - gs_const_string SubDirName = ConstString(FindFileData.cFileName); - if (!StringsEqual(SubDirName, ConstString(".")) && - !StringsEqual(SubDirName, ConstString(".."))) - { - gs_string SubDirectoryPath = PushString(FileHandler.Transient, SearchPath.Length + SubDirName.Length + 3); - PrintF(&SubDirectoryPath, "%S%S/*\0", SearchPath, SubDirName); - FilesCount += Win32EnumerateDirectoryIntoTempList(FileHandler, TempList, SubDirectoryPath.ConstString, Storage, Flags); - } - } - - AddFile = HasFlag(Flags, EnumerateDirectory_IncludeDirectories); - } - - if (AddFile) - { - temp_file_list_entry* File = PushStruct(FileHandler.Transient, temp_file_list_entry); - *File = {0}; - Win32SetFileInfoFromFindFileData(&File->Info, FindFileData, SearchPath, Storage); - SLLPushOrInit(TempList->First, TempList->Last, File); - FilesCount += 1; - } - }while(FindNextFile(SearchHandle, &FindFileData)); - } - else - { - PrintLastError(); - } - - return FilesCount; -} - -ENUMERATE_DIRECTORY(Win32EnumerateDirectory) -{ - Assert(IsNullTerminated(Path)); - gs_file_info_array Result = {}; - - temp_file_list TempList = {}; - Result.MaxCount = Win32EnumerateDirectoryIntoTempList(FileHandler, &TempList, Path, Storage, Flags); - - Result.Values = PushArray(Storage, gs_file_info, Result.MaxCount); - for (temp_file_list_entry* FileAt = TempList.First; - FileAt != 0; - FileAt = FileAt->Next) - { - // NOTE(Peter): We don't copy the file name here because its already in Storage. - // See String Storage note above ^^ - Result.Values[Result.Count++] = FileAt->Info; - } - - return Result; -} - -/////////////////////// -// -// Job System - -struct worker_thread_entry -{ - b32 IsValid; - u32 Index; -}; - -struct worker_thread_info -{ - gs_thread_context ThreadContext; - HANDLE Handle; - gs_work_queue* Queue; -}; - -internal s32 -Win32GetThreadId() -{ - 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); - } - Result.FileHandler = CreateFileHandler(Win32GetFileInfo, - Win32ReadEntireFile, - Win32WriteEntireFile, - Win32EnumerateDirectory, - Result.Transient); - - return Result; -} - -PUSH_WORK_ON_QUEUE(Win32PushWorkOnQueue) -{ -#ifdef 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) - { - gs_string DebugString = MakeString((char*)malloc(256), 256); - for (u32 i = 0; i < Queue->JobsCount; i++) - { - PrintF(&DebugString, "%d %s\n", i, Queue->Jobs[i].JobName); - NullTerminate(&DebugString); - OutputDebugStringA(DebugString.Str); - } - } -#endif - Assert(Queue->JobsCount < Queue->JobsMax); - - gs_threaded_job* Job = Queue->Jobs + Queue->JobsCount; - Job->WorkProc = WorkProc; - Job->Data = Data; -#ifdef DEBUG - Job->JobName = JobName; -#endif - - // 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) - { - 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) - { - Result.Index = Index; - Result.IsValid = true; - break; - } - OriginalNextJobIndex = Queue->NextJobIndex; - } - - return Result; -} - -COMPLETE_QUEUE_WORK(Win32DoQueueWorkUntilDone) -{ - worker_thread_entry Entry = {}; - Entry.IsValid = false; - while (Queue->JobsCompleted < Queue->JobsCount) - { - Entry = CompleteAndTakeNextJob(Queue, Entry, Context); - if (Entry.IsValid) - { - 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) - { - 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); - } - } - - return 0; -} - PLATFORM_GET_GPU_TEXTURE_HANDLE(Win32GetGPUTextureHandle) { s32 Handle = SubmitTexture(Memory, Width, Height); diff --git a/src/app/platform_win32/win32_foldhaus_fileio.h b/src/app/platform_win32/win32_foldhaus_fileio.h index a45c25e..2c4059c 100644 --- a/src/app/platform_win32/win32_foldhaus_fileio.h +++ b/src/app/platform_win32/win32_foldhaus_fileio.h @@ -8,5 +8,247 @@ // #ifndef WIN32_FOLDHAUS_FILEIO_H +internal u64 +Win32HighLowToU64(u32 LowPart, u32 HighPart) +{ + ULARGE_INTEGER Time = {}; + Time.LowPart = LowPart; + Time.HighPart = HighPart; + u64 Result = Time.QuadPart; + return Result; +} + +internal u64 +Win32FileTimeToU64(FILETIME FileTime) +{ + u64 Result = Win32HighLowToU64(FileTime.dwLowDateTime, FileTime.dwHighDateTime); + return Result; +} + +GET_FILE_INFO(Win32GetFileInfo) +{ + Assert(IsNullTerminated(Path)); + gs_file_info Result = {}; + HANDLE FileHandle = CreateFileA(Path.Str, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + Result.Path = Path; + Result.FileSize = (u64)GetFileSize(FileHandle, NULL) + 1; + FILETIME CreationTime, LastWriteTime; + if (GetFileTime(FileHandle, &CreationTime, (LPFILETIME)0, &LastWriteTime)) + { + Result.CreationTime = Win32FileTimeToU64(CreationTime); + Result.LastWriteTime = Win32FileTimeToU64(LastWriteTime); + } + else + { + PrintLastError(); + } + CloseHandle(FileHandle); + } + return Result; +} + +READ_ENTIRE_FILE(Win32ReadEntireFile) +{ + Assert(DataIsNonEmpty(Memory)); + Assert(IsNullTerminated(Path)); + + gs_file Result = {0}; + u32 Error = 0; + Result.FileInfo.Path = Path; + + HANDLE FileHandle = CreateFileA(Path.Str, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD BytesRead = 0; + if (ReadFile(FileHandle, (LPVOID)Memory.Memory, Memory.Size - 1, (LPDWORD)(&BytesRead), NULL)) + { + Memory.Memory[Memory.Size - 1] = 0; + Result.Data = Memory; + + gs_string AbsolutePath = PushString(FileHandler.Transient, 512); + AbsolutePath.Length = GetFullPathNameA(Path.Str, AbsolutePath.Size, AbsolutePath.Str, NULL); + if (AbsolutePath.Length == 0) + { + Error = GetLastError(); + InvalidCodePath; + } + Result.FileInfo.AbsolutePath = AbsolutePath.ConstString; + } + else + { + // NOTE(Peter): If we get to this error case, it means that the file exists, + // and was successfully opened, but we can't read from it. I'm choosing to + // treat this as a legitimate error at this point. + gs_string Message = Win32DumpErrorAndPrepareMessageBoxString(FileHandler.Transient, "Attempting to read file: %S", Path); + if (MessageBox(NULL, Message.Str, "Error", MB_OK) == IDOK) + { + PostQuitMessage(-1); + } + } + CloseHandle(FileHandle); + } + else + { + + } + + return Result; +} + +WRITE_ENTIRE_FILE(Win32WriteEntireFile) +{ + Assert(DataIsNonEmpty(Data)); + Assert(IsNullTerminated(Path)); + + bool Success = false; + HANDLE FileHandle = CreateFileA(Path.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)) + { + Success = (BytesWritten == Data.Size); + } + else + { + gs_string Message = Win32DumpErrorAndPrepareMessageBoxString(FileHandler.Transient, "Attempting to write to file: %S", Path); + MessageBox(NULL, Message.Str, "Error", MB_OK); + } + CloseHandle(FileHandle); + } + else + { + + } + + return Success; +} + +internal FILETIME +GetFileLastWriteTime(char* Path) +{ + FILETIME Result = {}; + + WIN32_FIND_DATA FindData = {}; + HANDLE FileHandle = FindFirstFileA(Path, &FindData); + + if (FileHandle != INVALID_HANDLE_VALUE) + { + Result = FindData.ftLastWriteTime; + FindClose(FileHandle); + } + else + { + // TODO(Peter): :ErrorLogging + } + + return Result; +} + +struct temp_file_list_entry +{ + gs_file_info Info; + temp_file_list_entry* Next; +}; + +struct temp_file_list +{ + temp_file_list_entry* First; + temp_file_list_entry* Last; +}; + +internal void +Win32SetFileInfoFromFindFileData(gs_file_info* Info, WIN32_FIND_DATA FindFileData, gs_const_string SearchPath, gs_memory_arena* Storage) +{ + u32 FileNameLength = CharArrayLength(FindFileData.cFileName); + + // NOTE(Peter): String Storage + // Storing the string in the final storage means we don't have to copy the string later, and all + // strings will be continguous in memory at the calling site, though they will be before the array + gs_string FileName = PushString(Storage, SearchPath.Length + FileNameLength + 1); + PrintF(&FileName, "%S%.*s", SearchPath, FileName.Size, FindFileData.cFileName); + NullTerminate(&FileName); + + Info->FileSize = Win32HighLowToU64(FindFileData.nFileSizeLow, FindFileData.nFileSizeHigh); + Info->CreationTime = Win32FileTimeToU64(FindFileData.ftCreationTime); + Info->LastWriteTime = Win32FileTimeToU64(FindFileData.ftLastWriteTime); + Info->Path = FileName.ConstString; + Info->IsDirectory = HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY); +} + +internal u32 +Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* TempList, gs_const_string Path, gs_memory_arena* Storage, b32 Flags) +{ + u32 FilesCount = 0; + + u32 IndexOfLastSlash = FindLastFromSet(Path, "\\/"); + gs_const_string SearchPath = Substring(Path, 0, IndexOfLastSlash + 1); + + WIN32_FIND_DATA FindFileData; + HANDLE SearchHandle = FindFirstFile(Path.Str, &FindFileData); + if (SearchHandle != INVALID_HANDLE_VALUE) + { + do + { + b32 AddFile = true; + + if (HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) + { + if (HasFlag(Flags, EnumerateDirectory_Recurse)) + { + gs_const_string SubDirName = ConstString(FindFileData.cFileName); + if (!StringsEqual(SubDirName, ConstString(".")) && + !StringsEqual(SubDirName, ConstString(".."))) + { + gs_string SubDirectoryPath = PushString(FileHandler.Transient, SearchPath.Length + SubDirName.Length + 3); + PrintF(&SubDirectoryPath, "%S%S/*\0", SearchPath, SubDirName); + FilesCount += Win32EnumerateDirectoryIntoTempList(FileHandler, TempList, SubDirectoryPath.ConstString, Storage, Flags); + } + } + + AddFile = HasFlag(Flags, EnumerateDirectory_IncludeDirectories); + } + + if (AddFile) + { + temp_file_list_entry* File = PushStruct(FileHandler.Transient, temp_file_list_entry); + *File = {0}; + Win32SetFileInfoFromFindFileData(&File->Info, FindFileData, SearchPath, Storage); + SLLPushOrInit(TempList->First, TempList->Last, File); + FilesCount += 1; + } + }while(FindNextFile(SearchHandle, &FindFileData)); + } + else + { + PrintLastError(); + } + + return FilesCount; +} + +ENUMERATE_DIRECTORY(Win32EnumerateDirectory) +{ + Assert(IsNullTerminated(Path)); + gs_file_info_array Result = {}; + + temp_file_list TempList = {}; + Result.MaxCount = Win32EnumerateDirectoryIntoTempList(FileHandler, &TempList, Path, Storage, Flags); + + Result.Values = PushArray(Storage, gs_file_info, Result.MaxCount); + for (temp_file_list_entry* FileAt = TempList.First; + FileAt != 0; + FileAt = FileAt->Next) + { + // NOTE(Peter): We don't copy the file name here because its already in Storage. + // See String Storage note above ^^ + Result.Values[Result.Count++] = FileAt->Info; + } + + return Result; +} + #define WIN32_FOLDHAUS_FILEIO_H #endif // WIN32_FOLDHAUS_FILEIO_H \ No newline at end of file diff --git a/src/app/platform_win32/win32_serial.h b/src/app/platform_win32/win32_foldhaus_serial.h similarity index 100% rename from src/app/platform_win32/win32_serial.h rename to src/app/platform_win32/win32_foldhaus_serial.h diff --git a/src/app/platform_win32/win32_foldhaus_utils.h b/src/app/platform_win32/win32_foldhaus_utils.h new file mode 100644 index 0000000..5392c9f --- /dev/null +++ b/src/app/platform_win32/win32_foldhaus_utils.h @@ -0,0 +1,75 @@ +// +// File: win32_foldhaus_utils.h +// Author: Peter Slattery +// Creation Date: 2020-10-01 +// +#ifndef WIN32_FOLDHAUS_UTILS_H + +internal gs_string +Win32DumpErrorAndPrepareMessageBoxString(gs_memory_arena* Arena, char* Format, ...) +{ + s32 Error = GetLastError(); + gs_string ErrorDump = PushString(Arena, 4096); + PrintF(&ErrorDump, + R"FOO(Win32 Error: %s\n +Error Code: %d\n + )FOO", + __FUNCTION__, + Error); + + va_list Args; + va_start(Args, Format); + PrintFArgsList(&ErrorDump, Format, Args); + va_end(Args); + + gs_data ErrorDumpData = StringToData(ErrorDump); + + HANDLE FileHandle = CreateFileA("./crashdump.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD BytesWritten = 0; + if (WriteFile(FileHandle, ErrorDumpData.Memory, ErrorDumpData.Size, &BytesWritten, NULL)) + { + + } + CloseHandle(FileHandle); + } + + AppendPrintF(&ErrorDump, "Program will attempt to continue. See crashdump.txt for info"); + NullTerminate(&ErrorDump); + + return ErrorDump; +} + +DEBUG_PRINT(Win32DebugPrint) +{ + Assert(IsNullTerminated(Message)); + OutputDebugStringA(Message.Str); +} + +#define PrintLastError() PrintLastError_(__FILE__, __LINE__) +internal void +PrintLastError_(char* File, u32 Line) +{ + char DebugStringData[256]; + gs_string DebugString = MakeString(DebugStringData, 0, 256); + u32 Error = GetLastError(); + PrintF(&DebugString, "%s Line %d: Win32 Error %d\n\0", File, Line, Error); + OutputDebugStringA(DebugString.Str); +} + + +internal HINSTANCE +GetHInstance() +{ + HINSTANCE Result = GetModuleHandle(NULL); + if (Result == NULL) + { + PrintLastError(); + } + return Result; +} + + +#define WIN32_FOLDHAUS_UTILS_H +#endif // WIN32_FOLDHAUS_UTILS_H \ No newline at end of file diff --git a/src/app/platform_win32/win32_foldhaus_work_queue.h b/src/app/platform_win32/win32_foldhaus_work_queue.h new file mode 100644 index 0000000..2db58f3 --- /dev/null +++ b/src/app/platform_win32/win32_foldhaus_work_queue.h @@ -0,0 +1,155 @@ +// +// File: win32_foldhaus_work_queue.h +// Author: Peter Slattery +// Creation Date: 2020-10-01 +// +#ifndef WIN32_FOLDHAUS_WORK_QUEUE_H + +struct worker_thread_entry +{ + b32 IsValid; + u32 Index; +}; + +struct worker_thread_info +{ + gs_thread_context ThreadContext; + HANDLE Handle; + gs_work_queue* Queue; +}; + +internal s32 +Win32GetThreadId() +{ + 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); + } + Result.FileHandler = CreateFileHandler(Win32GetFileInfo, + Win32ReadEntireFile, + Win32WriteEntireFile, + Win32EnumerateDirectory, + Result.Transient); + + return Result; +} + +PUSH_WORK_ON_QUEUE(Win32PushWorkOnQueue) +{ +#ifdef 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) + { + gs_string DebugString = MakeString((char*)malloc(256), 256); + for (u32 i = 0; i < Queue->JobsCount; i++) + { + PrintF(&DebugString, "%d %s\n", i, Queue->Jobs[i].JobName); + NullTerminate(&DebugString); + OutputDebugStringA(DebugString.Str); + } + } +#endif + Assert(Queue->JobsCount < Queue->JobsMax); + + gs_threaded_job* Job = Queue->Jobs + Queue->JobsCount; + Job->WorkProc = WorkProc; + Job->Data = Data; +#ifdef DEBUG + Job->JobName = JobName; +#endif + + // 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) + { + 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) + { + Result.Index = Index; + Result.IsValid = true; + break; + } + OriginalNextJobIndex = Queue->NextJobIndex; + } + + return Result; +} + +COMPLETE_QUEUE_WORK(Win32DoQueueWorkUntilDone) +{ + worker_thread_entry Entry = {}; + Entry.IsValid = false; + while (Queue->JobsCompleted < Queue->JobsCount) + { + Entry = CompleteAndTakeNextJob(Queue, Entry, Context); + if (Entry.IsValid) + { + 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) + { + 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); + } + } + + return 0; +} + +#define WIN32_FOLDHAUS_WORK_QUEUE_H +#endif // WIN32_FOLDHAUS_WORK_QUEUE_H \ No newline at end of file From 83ed23280a0bf2c3fad780e0788c9c6d484341a8 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 3 Oct 2020 08:46:14 -0700 Subject: [PATCH 29/43] Cleaned up network interface, separated SACN out from the actual sending of data, implemented sending over COM ports (remains to be tested), and added information specifying data output modes for com ports to the assembly file format --- src/app/engine/assembly_parser.cpp | 84 ++++++- src/app/engine/foldhaus_addressed_data.h | 64 +++-- src/app/engine/foldhaus_assembly.cpp | 72 +++++- src/app/engine/foldhaus_assembly.h | 28 ++- src/app/engine/foldhaus_network_ordering.h | 48 ++-- .../engine/sacn/{sacn.h => foldhaus_sacn.h} | 13 +- src/app/engine/uart/foldhaus_uart.h | 155 ++++++++++++ src/app/foldhaus_app.cpp | 41 +--- src/app/foldhaus_app.h | 13 +- src/app/foldhaus_platform.h | 38 +-- src/app/platform_win32/win32_foldhaus.cpp | 229 +++++------------- .../platform_win32/win32_foldhaus_serial.h | 84 ++++++- .../platform_win32/win32_foldhaus_socket.h | 140 +++++++++++ src/gs_libs/gs_types.cpp | 3 + 14 files changed, 709 insertions(+), 303 deletions(-) rename src/app/engine/sacn/{sacn.h => foldhaus_sacn.h} (96%) create mode 100644 src/app/engine/uart/foldhaus_uart.h create mode 100644 src/app/platform_win32/win32_foldhaus_socket.h diff --git a/src/app/engine/assembly_parser.cpp b/src/app/engine/assembly_parser.cpp index d23b596..636c11c 100644 --- a/src/app/engine/assembly_parser.cpp +++ b/src/app/engine/assembly_parser.cpp @@ -5,17 +5,33 @@ // #ifndef ASSEMBLY_PARSER_CPP +// TODO(pjs): This is good for meta generation +// ie. It would be great to have +// // enum ident enum prefix +// BEGIN_GEN_ENUM(assembly_field, AssemblyField_) +// // value name gen string of the value name the paired string identifier +// ADD_ENUM_VALUE(AssemblyName, DO_GEN_STRING, "assembly_name") +// ADD_ENUM_VALUE(AssemblyScale, DO_GEN_STRING, "assembly_scale") +// END_GEN_ENUM(assembly_field) + enum assembly_field { AssemblyField_AssemblyName, AssemblyField_AssemblyScale, AssemblyField_AssemblyCenter, AssemblyField_LedStripCount, + AssemblyField_OutputMode, AssemblyField_LedStrip, - AssemblyField_ControlBoxId, - AssemblyField_StartUniverse, - AssemblyField_StartChannel, + + AssemblyField_OutputSACN, + AssemblyField_SACN_StartUniverse, + AssemblyField_SACN_StartChannel, + + AssemblyField_OutputUART, + AssemblyField_UART_Channel, + AssemblyField_UART_ComPort, + AssemblyField_PointPlacementType, AssemblyField_InterpolatePoints, AssemblyField_Start, @@ -34,12 +50,17 @@ global char* AssemblyFieldIdentifiers[] = { "assembly_scale", // AssemblyField_AssemblyScale "assembly_center", // AssemblyField_AssemblyCenter "led_strip_count", // AssemblyField_LedStripCount + "output_mode", // AssemblyField_OutputMode "led_strip", // AssemblyField_LedStrip - "control_box_id", // AssemblyField_ControlBoxId - "start_universe", // AssemblyField_StartUniverse - "start_channel", // AssemblyField_StartChannel + "output_sacn", // AssemblyField_OutputSACN + "start_universe", // AssemblyField_SACN_StartUniverse + "start_channel", // AssemblyField_SACN_StartChannel + + "output_uart", // AssemblyField_OutputUART + "channel", // AssemblyField_UART_Channel + "com_port", // AssemblyField_UART_ComPort "point_placement_type", // AssemblyField_PointPlacementType "interpolate_points", // AssemblyField_InterpolatePoints @@ -158,8 +179,11 @@ TokenizerPushError(assembly_tokenizer* T, char* ErrorString) EatToNewLine(T); } +#define PARSER_FIELD_REQUIRED true +#define PARSER_FIELD_OPTIONAL false + internal bool -ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T) +ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T, bool Required = true) { bool Result = false; if (AdvanceIfTokenEquals(T, AssemblyFieldIdentifiers[Field])) @@ -170,10 +194,12 @@ ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T) } else { + // We always throw an error if we get this far because we know you were trying to + // open the identifier TokenizerPushError(T, "Field identifier is missing a colon"); } } - else + else if (Required) { TokenizerPushError(T, "Field Identifier Invalid"); } @@ -350,10 +376,10 @@ ReadV3Field(assembly_field Field, assembly_tokenizer* T) } internal bool -ReadStructOpening(assembly_field Field, assembly_tokenizer* T) +ReadStructOpening(assembly_field Field, assembly_tokenizer* T, bool Required = true) { bool Result = false; - if (ReadFieldIdentifier(Field, T)) + if (ReadFieldIdentifier(Field, T, Required)) { if (AdvanceIfTokenEquals(T, "{")) { @@ -400,14 +426,46 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe Assembly->StripCount = ReadIntField(AssemblyField_LedStripCount, &Tokenizer); Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount); + gs_string OutputModeString = ReadStringField(AssemblyField_OutputMode, &Tokenizer, Transient); + if (StringsEqual(OutputModeString.ConstString, ConstString("UART"))) + { + Assembly->OutputMode = NetworkProtocol_UART; + } + else if (StringsEqual(OutputModeString.ConstString, ConstString("SACN"))) + { + Assembly->OutputMode = NetworkProtocol_SACN; + } + else + { + TokenizerPushError(&Tokenizer, "Invalid output mode specified."); + } + for (u32 i = 0; i < Assembly->StripCount; i++) { v2_strip* StripAt = Assembly->Strips + i; if (ReadStructOpening(AssemblyField_LedStrip, &Tokenizer)) { - StripAt->ControlBoxID = ReadIntField(AssemblyField_ControlBoxId, &Tokenizer); - StripAt->StartUniverse = ReadIntField(AssemblyField_StartUniverse, &Tokenizer); - StripAt->StartChannel = ReadIntField(AssemblyField_StartChannel, &Tokenizer); + if (ReadStructOpening(AssemblyField_OutputSACN, &Tokenizer, PARSER_FIELD_OPTIONAL)) + { + StripAt->SACNAddr.StartUniverse = ReadIntField(AssemblyField_SACN_StartUniverse, &Tokenizer); + StripAt->SACNAddr.StartChannel = ReadIntField(AssemblyField_SACN_StartChannel, &Tokenizer); + + if (!ReadStructClosing(&Tokenizer)) + { + TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + } + } + + if (ReadStructOpening(AssemblyField_OutputUART, &Tokenizer, PARSER_FIELD_OPTIONAL)) + { + StripAt->UARTAddr.Channel = (u8)ReadIntField(AssemblyField_UART_Channel, &Tokenizer); + StripAt->UARTAddr.ComPort = ReadStringField(AssemblyField_UART_ComPort, &Tokenizer, &Assembly->Arena).ConstString; + + if (!ReadStructClosing(&Tokenizer)) + { + TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + } + } // TODO(Peter): Need to store this gs_string PointPlacementType = ReadStringField(AssemblyField_PointPlacementType, &Tokenizer, &Assembly->Arena); diff --git a/src/app/engine/foldhaus_addressed_data.h b/src/app/engine/foldhaus_addressed_data.h index 6436a0d..79a84de 100644 --- a/src/app/engine/foldhaus_addressed_data.h +++ b/src/app/engine/foldhaus_addressed_data.h @@ -12,66 +12,86 @@ enum data_buffer_address_type { AddressType_NetworkIP, + AddressType_ComPort, AddressType_Invalid, }; struct addressed_data_buffer { - u8* Memory; - u32 MemorySize; + union + { + struct + { + u8* Memory; + u32 MemorySize; + }; + 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; }; -internal addressed_data_buffer* -AddressedDataBufferList_Push(addressed_data_buffer_list* List, u32 BufferSize, gs_memory_arena* Storage) +internal void +AddressedDataBufferList_Clear(addressed_data_buffer_list* List) { - addressed_data_buffer* Result = PushStruct(Storage, addressed_data_buffer); + List->Root = 0; + List->Head = 0; + ClearArena(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->MemorySize = BufferSize; - Result->Memory = PushArray(Storage, u8, Result->MemorySize); + 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; +} + internal void -AddressedDataBuffer_SetNetworkAddress(addressed_data_buffer* Buffer, u32 V4SendAddress, u32 SendPort) +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; } internal void -AddressedDataBuffer_Send(addressed_data_buffer Buffer, platform_socket_handle SendSocket, context Context) +AddressedDataBuffer_SetCOMPort(addressed_data_buffer* Buffer, gs_const_string ComPort) { - u32 V4SendAddress = Buffer.V4SendAddress; - Context.PlatformSendTo(SendSocket, Buffer.V4SendAddress, Buffer.SendPort, (const char*)Buffer.Memory, Buffer.MemorySize, 0); -} - -internal void -AddressedDataBufferList_SendAll(addressed_data_buffer_list OutputData, platform_socket_handle SendSocket, context Context) -{ - for (addressed_data_buffer* BufferAt = OutputData.Root; - BufferAt != 0; - BufferAt = BufferAt->Next) - { - AddressedDataBuffer_Send(*BufferAt, SendSocket, Context); - } + Buffer->AddressType = AddressType_ComPort; + Buffer->ComPort = ComPort; } #define FOLDHAUS_ADDRESSED_DATA_H diff --git a/src/app/engine/foldhaus_assembly.cpp b/src/app/engine/foldhaus_assembly.cpp index afb3919..5be7342 100644 --- a/src/app/engine/foldhaus_assembly.cpp +++ b/src/app/engine/foldhaus_assembly.cpp @@ -5,6 +5,72 @@ // #ifndef FOLDHAUS_ASSEMBLY_CPP +/////////////////////////// +// +// Assembly Array +// +/////////////////////////// + +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; +} + +internal u32 +AssemblyArray_Push(assembly_array* Array, assembly Assembly) +{ + Assert(Array->Count < Array->CountMax); + u32 Index = Array->Count++; + Array->Values[Index] = Assembly; + return Index; +} + +internal assembly* +AssemblyArray_Take(assembly_array* Array) +{ + 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]; +} + +typedef bool assembly_array_filter_proc(assembly A); +bool AssemblyFilter_OutputsViaSACN(assembly A) { return A.OutputMode == NetworkProtocol_SACN; } +bool AssemblyFilter_OutputsViaUART(assembly A) { return A.OutputMode == NetworkProtocol_UART; } + +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 At = Array.Values[i]; + if (Filter(At)) + { + AssemblyArray_Push(&Result, At); + } + } + + return Result; +} + +/////////////////////////// +// +// LedSystem +// +/////////////////////////// + internal led_system LedSystemInitialize(gs_allocator PlatformMemory, u32 BuffersMax) { @@ -116,8 +182,7 @@ LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, gs_memory_arena s32 IndexOfLastSlash = FindLast(Path, '\\'); gs_const_string FileName = Substring(Path, IndexOfLastSlash + 1, Path.Length); - Assert(Assemblies->Count < Assemblies->CountMax); - assembly* NewAssembly = &Assemblies->Values[Assemblies->Count++]; + assembly* NewAssembly = AssemblyArray_Take(Assemblies); NewAssembly->Arena = CreateMemoryArena(Context.ThreadContext.Allocator); if (ParseAssemblyFile(NewAssembly, FileName, AssemblyFileText, Scratch)) @@ -143,8 +208,7 @@ UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context) assembly* Assembly = &State->Assemblies.Values[AssemblyIndex]; LedSystemFreeBuffer(&State->LedSystem, Assembly->LedBufferIndex); FreeMemoryArena(&Assembly->Arena); - u32 LastAssemblyIndex = --State->Assemblies.Count; - State->Assemblies.Values[AssemblyIndex] = State->Assemblies.Values[LastAssemblyIndex]; + AssemblyArray_RemoveAt(&State->Assemblies, AssemblyIndex); } // Querying Assemblies diff --git a/src/app/engine/foldhaus_assembly.h b/src/app/engine/foldhaus_assembly.h index a4ebd0e..c702a3b 100644 --- a/src/app/engine/foldhaus_assembly.h +++ b/src/app/engine/foldhaus_assembly.h @@ -5,6 +5,15 @@ // #ifndef FOLDHAUS_ASSEMBLY_H +enum network_protocol +{ + NetworkProtocol_SACN, + NetworkProtocol_ArtNet, + NetworkProtocol_UART, + + NetworkProtocol_Count, +}; + union pixel { struct @@ -40,13 +49,24 @@ struct v2_tag u64 ValueHash; }; +struct strip_sacn_addr +{ + s32 StartUniverse; + s32 StartChannel; +}; + +struct strip_uart_addr +{ + u8 Channel; + gs_const_string ComPort; +}; + struct v2_strip { s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore - // TODO(Peter): Add in info for Serial, ArtNet, etc. - s32 StartUniverse; - s32 StartChannel; + strip_sacn_addr SACNAddr; + strip_uart_addr UARTAddr; // TODO(Peter): When we create more ways to calculate points, this needs to become // a type enum and a union @@ -81,6 +101,8 @@ struct assembly u32 StripCount; v2_strip* Strips; + + network_protocol OutputMode; }; struct assembly_array diff --git a/src/app/engine/foldhaus_network_ordering.h b/src/app/engine/foldhaus_network_ordering.h index 65b60c7..05e5afd 100644 --- a/src/app/engine/foldhaus_network_ordering.h +++ b/src/app/engine/foldhaus_network_ordering.h @@ -6,7 +6,7 @@ #ifndef FOLDHAUS_NETWORK_ORDERING_H // Packs a u8 to a known big endian buffer -inline u8* +inline u8* PackB1(u8* ptr, u8 val) { *ptr = val; @@ -14,14 +14,14 @@ PackB1(u8* ptr, u8 val) } //Unpacks a u8 from a known big endian buffer -inline u8 +inline u8 UpackB1(const u8* ptr) { return *ptr; } //Packs a u8 to a known little endian buffer -inline u8* +inline u8* PackL1(u8* ptr, u8 val) { *ptr = val; @@ -29,30 +29,40 @@ PackL1(u8* ptr, u8 val) } //Unpacks a u8 from a known little endian buffer -inline u8 +inline u8 UpackL1(const u8* ptr) { return *ptr; } //Packs a u16 to a known big endian buffer -inline u8* +inline u16 +PackB2(u16 Value) +{ + u16 Result = 0; + u8* Array = (u8*)&Result; + Array[1] = (u8)(Value & 0xFF); + Array[0] = (u8)((Value & 0xFF00) >> 8); + return Result; +} + +inline u8* PackB2(u8* ptr, u16 val) { - ptr[1] = (u8)(val & 0xff); + ptr[1] = (u8)(val & 0xff); ptr[0] = (u8)((val & 0xff00) >> 8); return ptr + sizeof(val); } //Unpacks a u16 from a known big endian buffer -inline u16 +inline u16 UpackB2(const u8* ptr) { return (u16)(ptr[1] | ptr[0] << 8); } //Packs a u16 to a known little endian buffer -inline u8* +inline u8* PackL2(u8* ptr, u16 val) { *((u16*)ptr) = val; @@ -60,14 +70,14 @@ PackL2(u8* ptr, u16 val) } //Unpacks a u16 from a known little endian buffer -inline u16 +inline u16 UpackL2(const u8* ptr) { return *((u16*)ptr); } //Packs a u32 to a known big endian buffer -inline u8* +inline u8* PackB4(u8* ptr, u32 val) { ptr[3] = (u8) (val & 0xff); @@ -78,14 +88,14 @@ PackB4(u8* ptr, u32 val) } //Unpacks a u32 from a known big endian buffer -inline u32 +inline u32 UpackB4(const u8* ptr) { return (u32)(ptr[3] | (ptr[2] << 8) | (ptr[1] << 16) | (ptr[0] << 24)); } //Packs a u32 to a known little endian buffer -inline u8* +inline u8* PackL4(u8* ptr, u32 val) { *((u32*)ptr) = val; @@ -93,14 +103,14 @@ PackL4(u8* ptr, u32 val) } //Unpacks a u32 from a known little endian buffer -inline u32 +inline u32 UpackL4(const u8* ptr) { return *((u32*)ptr); } //Packs a u64 to a known big endian buffer -inline u8* +inline u8* PackB8(u8* ptr, u64 val) { ptr[7] = (u8) (val & 0xff); @@ -115,17 +125,17 @@ PackB8(u8* ptr, u64 val) } //Unpacks a uint64 from a known big endian buffer -inline u64 +inline u64 UpackB8(const u8* ptr) { return ((u64)ptr[7]) | (((u64)ptr[6]) << 8) | (((u64)ptr[5]) << 16) | - (((u64)ptr[4]) << 24) | (((u64)ptr[3]) << 32) | - (((u64)ptr[2]) << 40) | (((u64)ptr[1]) << 48) | + (((u64)ptr[4]) << 24) | (((u64)ptr[3]) << 32) | + (((u64)ptr[2]) << 40) | (((u64)ptr[1]) << 48) | (((u64)ptr[0]) << 56); } //Packs a u64 to a known little endian buffer -inline u8* +inline u8* PackL8(u8* ptr, u64 val) { *((u64*)ptr) = val; @@ -133,7 +143,7 @@ PackL8(u8* ptr, u64 val) } //Unpacks a u64 from a known little endian buffer -inline u64 +inline u64 UpackL8(const u8* ptr) { return *((u64*)ptr); diff --git a/src/app/engine/sacn/sacn.h b/src/app/engine/sacn/foldhaus_sacn.h similarity index 96% rename from src/app/engine/sacn/sacn.h rename to src/app/engine/sacn/foldhaus_sacn.h index a12c4b8..6004361 100644 --- a/src/app/engine/sacn/sacn.h +++ b/src/app/engine/sacn/foldhaus_sacn.h @@ -208,6 +208,7 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, cid CID ) { + // TODO(pjs): Replace packing with gs_memory_cursor u8* Cursor = Buffer; @@ -285,6 +286,7 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, Cursor = PackB1(Cursor, StartCode); Assert(Cursor - Buffer == STREAM_HEADER_SIZE); + } // @@ -306,7 +308,6 @@ SACN_Initialize (context Context) internal void SACN_Cleanup(streaming_acn* SACN, context Context) { - Context.PlatformCloseSocket(SACN->SendSocket); } internal void @@ -360,7 +361,7 @@ SACN_FillBufferWithLeds(u8* BufferStart, u32 BufferSize, v2_strip Strip, led_buf } internal void -SACN_BuildOutputData(streaming_acn* SACN, addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem, gs_memory_arena* OutputStorage) +SACN_BuildOutputData(streaming_acn* SACN, addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem) { SACN_UpdateSequence(SACN); @@ -378,13 +379,13 @@ SACN_BuildOutputData(streaming_acn* SACN, addressed_data_buffer_list* Output, as { v2_strip StripAt = Assembly.Strips[StripIdx]; - u32 V4SendAddress = SACN_GetUniverseSendAddress(StripAt.StartUniverse); + u32 V4SendAddress = SACN_GetUniverseSendAddress(StripAt.SACNAddr.StartUniverse); u32 SendPort = DEFAULT_STREAMING_ACN_PORT; - addressed_data_buffer* Data = AddressedDataBufferList_Push(Output, BufferSize, OutputStorage); - AddressedDataBuffer_SetNetworkAddress(Data, V4SendAddress, SendPort); + addressed_data_buffer* Data = AddressedDataBufferList_Push(Output, BufferSize); + AddressedDataBuffer_SetNetworkAddress(Data, SACN->SendSocket, V4SendAddress, SendPort); - SACN_PrepareBufferHeader(StripAt.StartUniverse, Data->Memory, Data->MemorySize, BufferHeaderSize, *SACN); + SACN_PrepareBufferHeader(StripAt.SACNAddr.StartUniverse, Data->Memory, Data->MemorySize, BufferHeaderSize, *SACN); SACN_FillBufferWithLeds(Data->Memory + BufferHeaderSize, BufferBodySize, StripAt, *LedBuffer); } } diff --git a/src/app/engine/uart/foldhaus_uart.h b/src/app/engine/uart/foldhaus_uart.h new file mode 100644 index 0000000..a80b7ff --- /dev/null +++ b/src/app/engine/uart/foldhaus_uart.h @@ -0,0 +1,155 @@ +// +// File: foldhaus_uart.h +// Author: Peter Slattery +// Creation Date: 2020-10-01 +// +#ifndef FOLDHAUS_UART_H + +enum uart_record_type +{ + UART_SET_CHANNEL_WS2812 = 1, + UART_DRAW_ALL = 2, +}; + +// NOTE(pjs): these are data packet structures and need to have 1 byte packing +#pragma pack(push, 1) + +struct uart_header +{ + u8 MagicNumber[4]; + u8 Channel; + u8 RecordType; +}; + +struct uart_channel +{ + u8 ElementsCount; + + u8 RedIndex; + u8 GreenIndex; + u8 BlueIndex; + u8 WhiteIndex; + + u16 PixelsCount; +}; + +struct uart_footer +{ + u32 CRC; +}; + +#pragma pack(pop) + +global u32 UART_CRCTable[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +internal void +UART_FillHeader(uart_header* Header, u8 Channel, u8 RecordType) +{ + Header->MagicNumber[0] = 'U'; + Header->MagicNumber[1] = 'P'; + Header->MagicNumber[2] = 'X'; + Header->MagicNumber[3] = 'L'; + + Header->Channel = Channel; + Header->RecordType = RecordType; +} + +internal void +UART_FillFooter(uart_footer* Footer, u8* BufferStart) +{ + // Calculate the CRC + u32 CRC = 0xFFFFFFFF; + u32 BytesCount = (u8*)Footer - BufferStart; + for (u32 i = 0; i < BytesCount; i++) + { + u8 At = BufferStart[i]; + + // Cameron's Version + CRC = UART_CRCTable[(CRC ^ At) & 0x0F] ^ (CRC >> 4); + CRC = UART_CRCTable[(CRC ^ (At >> 4)) & 0x0F] ^ (CRC >> 4); + +#if 0 + // The Libraries Version + CRC = (UART_CRCTable[(CRC ^ At) & 0xFF] ^ (CRC >> 8)) & 0xFFFFFFFF; +#endif + } + + Footer->CRC = CRC; +} + +internal void +UART_SetChannelBuffer_Create(addressed_data_buffer_list* Output, 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); + + u32 BufferSize = sizeof(uart_header) + sizeof(uart_channel); + BufferSize += ChannelSettings.ElementsCount * ChannelSettings.PixelsCount; + BufferSize += sizeof(uart_footer); + + addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, BufferSize); + AddressedDataBuffer_SetCOMPort(Buffer, Strip.UARTAddr.ComPort); + + gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); + + uart_header* Header = PushStructOnCursor(&WriteCursor, uart_header); + UART_FillHeader(Header, Strip.UARTAddr.Channel, UART_SET_CHANNEL_WS2812); + + 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); + + OutputPixel[Channel->RedIndex] = Color.R; + OutputPixel[Channel->GreenIndex] = Color.G; + OutputPixel[Channel->BlueIndex] = Color.B; + + if (OutputPixel[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, Buffer->Memory); +} + +internal void +UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem) +{ + uart_channel ChannelSettings = {0}; + ChannelSettings.ElementsCount = 3; + ChannelSettings.RedIndex = 1; + ChannelSettings.GreenIndex = 2; + ChannelSettings.BlueIndex = 3; + ChannelSettings.WhiteIndex = 0; + + for (u32 AssemblyIdx = 0; AssemblyIdx < Assemblies.Count; AssemblyIdx++) + { + assembly Assembly = Assemblies.Values[AssemblyIdx]; + led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); + + for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) + { + v2_strip StripAt = Assembly.Strips[StripIdx]; + ChannelSettings.PixelsCount = StripAt.LedCount; + UART_SetChannelBuffer_Create(Output, ChannelSettings, StripAt, *LedBuffer); + } + } +} + +#define FOLDHAUS_UART_H +#endif // FOLDHAUS_UART_H \ No newline at end of file diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 8914b3c..ed12a0a 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -25,8 +25,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Permanent = CreateMemoryArena(Context.ThreadContext.Allocator); State->Transient = Context.ThreadContext.Transient; - State->Assemblies.CountMax = 8; - State->Assemblies.Values = PushArray(&State->Permanent, assembly, State->Assemblies.CountMax); + State->Assemblies = AssemblyArray_Create(8, &State->Permanent); State->GlobalLog = PushStruct(State->Transient, event_log); *State->GlobalLog = {0}; @@ -126,9 +125,6 @@ INITIALIZE_APPLICATION(InitializeApplication) #if 1 gs_const_string SculpturePath = ConstString("data/blumen_lumen_v2.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog); - - SculpturePath = ConstString("data/radialumia_v2.fold"); - LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog); #endif State->PixelsToWorldScale = .01f; @@ -343,38 +339,13 @@ UPDATE_AND_RENDER(UpdateAndRender) { // NOTE(pjs): Building data buffers to be sent out to the sculpture - - addressed_data_buffer_list OutputData = {0}; - switch (State->NetworkProtocol) - { - case NetworkProtocol_SACN: - { - SACN_BuildOutputData(&State->SACN, &OutputData, State->Assemblies, &State->LedSystem, State->Transient); - }break; - - case NetworkProtocol_UART: - { - //UART_BuildOutputData(&OutputData, State, State->Transient); - }break; - - case NetworkProtocol_ArtNet: - InvalidDefaultCase; - } - - // NOTE(pjs): Executing the job to actually send the data - if (0) - { - // TODO(pjs): This should happen on another thread - AddressedDataBufferList_SendAll(OutputData, State->SACN.SendSocket, *Context); - - /* - Saved this lien as an example of pushing onto a queue - Context->GeneralWorkQueue->PushWorkOnQueue(Context->GeneralWorkQueue, SACNSendDMXBufferListJob, Job, "SACN Send Data Job"); - */ - } + // 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); } - PushRenderOrthographic(RenderBuffer, State->WindowBounds); PushRenderClearScreen(RenderBuffer); diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index e3b5532..51938b4 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -18,8 +18,8 @@ #include "engine/foldhaus_assembly.h" #include "engine/assembly_parser.cpp" -#include "engine/foldhaus_addressed_data.h" -#include "engine/sacn/sacn.h" +#include "engine/sacn/foldhaus_sacn.h" +#include "engine/uart/foldhaus_uart.h" typedef struct app_state app_state; @@ -33,15 +33,6 @@ typedef struct app_state app_state; #include "engine/animation/foldhaus_animation.h" -enum network_protocol -{ - NetworkProtocol_SACN, - NetworkProtocol_ArtNet, - NetworkProtocol_UART, - - NetworkProtocol_Count, -}; - struct app_state { gs_memory_arena Permanent; diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index 4f066d4..96a7ec7 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -33,7 +33,18 @@ global debug_services* GlobalDebugServices; //#include "..\gs_libs\gs_vector_matrix.h" #include "..\gs_libs\gs_input.h" +struct platform_network_address +{ + s32 Family; + u16 Port; + u32 Address; +}; + +typedef s32 platform_socket_handle; +typedef s32 platform_network_address_handle; + #include "foldhaus_renderer.h" +#include "engine/foldhaus_addressed_data.h" typedef struct context context; @@ -42,7 +53,7 @@ typedef struct context context; #define INITIALIZE_APPLICATION(name) void name(context Context) typedef INITIALIZE_APPLICATION(initialize_application); -#define UPDATE_AND_RENDER(name) void name(context* Context, input_queue InputQueue, render_command_buffer* RenderBuffer) +#define UPDATE_AND_RENDER(name) void name(context* Context, input_queue InputQueue, render_command_buffer* RenderBuffer, addressed_data_buffer_list* OutputData) typedef UPDATE_AND_RENDER(update_and_render); #define RELOAD_STATIC_DATA(name) void name(context Context, debug_services* DebugServices) @@ -102,31 +113,9 @@ struct texture_buffer #define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) s32 name(u8* Memory, s32 Width, s32 Height) typedef PLATFORM_GET_GPU_TEXTURE_HANDLE(platform_get_gpu_texture_handle); -struct platform_network_address -{ - s32 Family; - u16 Port; - u32 Address; -}; - -typedef s32 platform_socket_handle; -typedef s32 platform_network_address_handle; - #define PLATFORM_GET_SOCKET_HANDLE(name) platform_socket_handle name(s32 Multicast_TimeToLive) typedef PLATFORM_GET_SOCKET_HANDLE(platform_get_socket_handle); -#define PLATFORM_GET_SEND_ADDRESS_HANDLE(name) platform_network_address_handle name(s32 AddressFamily, u16 Port, u32 Address) -typedef PLATFORM_GET_SEND_ADDRESS_HANDLE(platform_get_send_address); - -#define PLATFORM_SET_SOCKET_OPTION(name) s32 name(platform_socket_handle SocketHandle, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength) -typedef PLATFORM_SET_SOCKET_OPTION(platform_set_socket_option); - -#define PLATFORM_SEND_TO(name) s32 name(platform_socket_handle SocketHandle, u32 Address, u32 Port, const char* Buffer, s32 BufferLength, s32 Flags) -typedef PLATFORM_SEND_TO(platform_send_to); - -#define PLATFORM_CLOSE_SOCKET(name) void name(platform_socket_handle SocketHandle) -typedef PLATFORM_CLOSE_SOCKET(platform_close_socket); - // Font struct platform_font_info { @@ -209,9 +198,6 @@ struct context platform_draw_font_codepoint* PlatformDrawFontCodepoint; platform_get_socket_handle* PlatformGetSocketHandle; - platform_set_socket_option* PlatformSetSocketOption; - platform_send_to* PlatformSendTo; - platform_close_socket* PlatformCloseSocket; }; diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index 338f957..dc076eb 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -22,6 +22,7 @@ #include "win32_foldhaus_timing.h" #include "win32_foldhaus_work_queue.h" #include "win32_foldhaus_serial.h" +#include "win32_foldhaus_socket.h" #include "../foldhaus_renderer.cpp" @@ -40,105 +41,6 @@ PLATFORM_GET_GPU_TEXTURE_HANDLE(Win32GetGPUTextureHandle) return Handle; } -struct win32_socket -{ - SOCKET Socket; -}; - -#define SOCKET_DICTIONARY_GROW_SIZE 32 -s32 Win32SocketHandleMax; -s32 Win32SocketHandleCount; -win32_socket* SocketValues; - -PLATFORM_SET_SOCKET_OPTION(Win32SetSocketOption) -{ - s32 SocketIndex = (s32)SocketHandle; - Assert(SocketIndex < Win32SocketHandleCount); - int Error = setsockopt(SocketValues[SocketIndex].Socket, Level, Option, OptionValue, OptionLength); - if (Error == SOCKET_ERROR) - { - Error = WSAGetLastError(); - // TODO(Peter): :ErrorLogging - } - - return Error; -} - -PLATFORM_GET_SOCKET_HANDLE(Win32GetSocketHandle) -{ - // NOTE(Peter): These used to be passed in as paramters, but we only use this function - // with AF_INET, SOCK_DGRAM, and Protocol = 0. These are also platform specific values - // so I was having to include windows.h in the platform agnostic code to accomodate that - // function signature. - s32 AddressFamily = AF_INET; - s32 Type = SOCK_DGRAM; - s32 Protocol = 0; - - if (Win32SocketHandleCount >= Win32SocketHandleMax) - { - s32 NewDictionaryMax = Win32SocketHandleMax + SOCKET_DICTIONARY_GROW_SIZE; - s32 NewDictionaryDataSize = NewDictionaryMax * sizeof(win32_socket); - u8* DictionaryMemory = (u8*)Win32Alloc(NewDictionaryDataSize, 0); - Assert(DictionaryMemory); - - win32_socket* NewValues = (win32_socket*)(DictionaryMemory); - if (SocketValues) - { - CopyMemoryTo(SocketValues, NewValues, sizeof(win32_socket) * NewDictionaryMax); - Win32Free((u8*)SocketValues, sizeof(win32_socket) * Win32SocketHandleCount); - } - SocketValues = NewValues; - - Win32SocketHandleMax = NewDictionaryMax; - } - - Assert(Win32SocketHandleCount < Win32SocketHandleMax); - s32 NewSocketIndex = Win32SocketHandleCount++; - - SocketValues[NewSocketIndex].Socket = socket(AddressFamily, Type, Protocol); - - int Error = Win32SetSocketOption(NewSocketIndex, IPPROTO_IP, IP_MULTICAST_TTL, - (const char*)(&Multicast_TimeToLive), sizeof(Multicast_TimeToLive)); - - return (platform_socket_handle)NewSocketIndex; -} - -PLATFORM_SEND_TO(Win32SendTo) -{ - s32 SocketIndex = (s32)SocketHandle; - Assert(SocketIndex < Win32SocketHandleCount); - - sockaddr_in SockAddress = {}; - SockAddress.sin_family = AF_INET; - SockAddress.sin_port = HostToNetU16(Port); - SockAddress.sin_addr.s_addr = HostToNetU32(Address); - - s32 LengthSent = sendto(SocketValues[SocketIndex].Socket, Buffer, BufferLength, Flags, (sockaddr*)&SockAddress, sizeof(sockaddr_in)); - - if (LengthSent == SOCKET_ERROR) - { - s32 Error = WSAGetLastError(); - if (Error == 10051) - { - } - else - { - // TODO(Peter): :ErrorLogging - InvalidCodePath; - } - } - - return LengthSent; -} - -PLATFORM_CLOSE_SOCKET(Win32CloseSocket) -{ - s32 SocketIndex = (s32)SocketHandle; - Assert(SocketIndex < Win32SocketHandleCount); - - closesocket(SocketValues[SocketIndex].Socket); -} - HDC FontDrawingDC; HBITMAP FontBitmap; HFONT CurrentFont; @@ -462,40 +364,6 @@ Win32LoadSystemCursor(char* CursorIdentifier) return Result; } -internal void -PrintMatrix(m44 M, gs_thread_context Context) -{ - gs_string PrintString = AllocatorAllocString(Context.Allocator, 256); - PrintF(&PrintString, "[\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n]\n", - M.Array[0], M.Array[1], M.Array[2], M.Array[3], - M.Array[4], M.Array[5], M.Array[6], M.Array[7], - M.Array[8], M.Array[9], M.Array[10], M.Array[11], - M.Array[12], M.Array[13], M.Array[14], M.Array[15]); - NullTerminate(&PrintString); - OutputDebugStringA(PrintString.Str); -} - -v4 PerspectiveDivide(v4 A) -{ - v4 Result = {0, 0, 0, 1}; - Result.x = A.x / A.w; - Result.y = A.y / A.w; - Result.z = A.z / A.w; - Result.w = A.w; - return Result; -} -v4 ToScreen(v4 P, rect2 WindowBounds) -{ - v4 Result = P; - Result.x = RemapR32(P.x, -1, 1, WindowBounds.Min.x, WindowBounds.Max.x); - Result.y = RemapR32(P.y, -1, 1, WindowBounds.Min.y, WindowBounds.Max.y); - return Result; -} - -// -// Serial -// - int WINAPI WinMain ( HINSTANCE HInstance, @@ -506,19 +374,6 @@ WinMain ( { gs_thread_context ThreadContext = Win32CreateThreadContext(); - - { - gs_const_string TestString = ConstString("Hello World!\nTesting\n"); - - HANDLE SerialPortHandle = Win32SerialPort_Open("COM5"); - Win32SerialPort_SetState(SerialPortHandle, 9600, 8, 0, 1); - Win32SerialPort_Write(SerialPortHandle, StringToData(TestString)); - Win32SerialPort_Close(SerialPortHandle); - } - - - - MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); Win32UpdateWindowDimension(&MainWindow); @@ -528,12 +383,23 @@ WinMain ( OpenGLWindowInfo.DepthBits = 0; CreateOpenGLWindowContext(OpenGLWindowInfo, &MainWindow); + s32 InitialMemorySize = MB(64); + u8* InitialMemory = (u8*)Win32Alloc(InitialMemorySize, 0); + context Context = {}; + Context.ThreadContext = ThreadContext; + Context.MemorySize = InitialMemorySize; + Context.MemoryBase = InitialMemory; + Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; + Context.Mouse = {0}; + + gs_memory_arena PlatformPermanent = CreateMemoryArena(Context.ThreadContext.Allocator); + s64 PerformanceCountFrequency = GetPerformanceFrequency(); s64 LastFrameEnd = GetWallClock(); r32 TargetSecondsPerFrame = 1 / 60.0f; r32 LastFrameSecondsElapsed = 0.0f; - GlobalDebugServices = (debug_services*)malloc(sizeof(debug_services)); + GlobalDebugServices = PushStruct(&PlatformPermanent, debug_services); s32 DebugThreadCount = PLATFORM_THREAD_COUNT + 1; InitDebugServices(GlobalDebugServices, PerformanceCountFrequency, @@ -556,7 +422,7 @@ WinMain ( worker_thread_info* WorkerThreads = 0; if (PLATFORM_THREAD_COUNT > 0) { - WorkerThreads = (worker_thread_info*)malloc(sizeof(worker_thread_info) * PLATFORM_THREAD_COUNT); + WorkerThreads = PushArray(&PlatformPermanent, worker_thread_info, PLATFORM_THREAD_COUNT); } HANDLE WorkQueueSemaphoreHandle = CreateSemaphoreEx(0, 0, PLATFORM_THREAD_COUNT, 0, 0, SEMAPHORE_ALL_ACCESS); @@ -564,7 +430,7 @@ WinMain ( gs_work_queue WorkQueue = {}; WorkQueue.SemaphoreHandle = &WorkQueueSemaphoreHandle; WorkQueue.JobsMax = 512; - WorkQueue.Jobs = (gs_threaded_job*)Win32Alloc(sizeof(gs_threaded_job) * WorkQueue.JobsMax, 0); + WorkQueue.Jobs = PushArray(&PlatformPermanent, gs_threaded_job, WorkQueue.JobsMax); WorkQueue.NextJobIndex = 0; WorkQueue.PushWorkOnQueue = Win32PushWorkOnQueue; WorkQueue.CompleteQueueWork = Win32DoQueueWorkUntilDone; @@ -577,15 +443,6 @@ WinMain ( WorkerThreads[i].Handle = CreateThread(0, 0, &WorkerThreadProc, (void*)&WorkerThreads[i], 0, 0); } - s32 InitialMemorySize = MB(64); - u8* InitialMemory = (u8*)Win32Alloc(InitialMemorySize, 0); - context Context = {}; - Context.ThreadContext = ThreadContext; - Context.MemorySize = InitialMemorySize; - Context.MemoryBase = InitialMemory; - Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; - Context.Mouse = {0}; - // Cursors HCURSOR CursorArrow = Win32LoadSystemCursor(IDC_ARROW); HCURSOR CursorPointer = Win32LoadSystemCursor(IDC_HAND); @@ -599,9 +456,6 @@ WinMain ( Context.GeneralWorkQueue = &WorkQueue; Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; Context.PlatformGetSocketHandle = Win32GetSocketHandle; - Context.PlatformSetSocketOption = Win32SetSocketOption; - Context.PlatformSendTo = Win32SendTo; - Context.PlatformCloseSocket = Win32CloseSocket; Context.PlatformGetFontInfo = Win32GetFontInfo; Context.PlatformDrawFontCodepoint = Win32DrawFontCodepoint; @@ -619,11 +473,18 @@ WinMain ( WSADATA WSAData; WSAStartup(MAKEWORD(2, 2), &WSAData); + Win32Sockets = Win32SocketArray_Create(16, &PlatformPermanent); + + Win32SerialArray_Create(ThreadContext); s32 RenderMemorySize = MB(12); - u8* RenderMemory = (u8*)Win32Alloc(RenderMemorySize, 0); + u8* RenderMemory = PushSize(&PlatformPermanent, RenderMemorySize); render_command_buffer RenderBuffer = AllocateRenderCommandBuffer(RenderMemory, RenderMemorySize, Win32Realloc); + addressed_data_buffer_list OutputData = {}; + OutputData.Arena = AllocatorAllocStruct(Context.ThreadContext.Allocator, gs_memory_arena); + *OutputData.Arena = CreateMemoryArena(Context.ThreadContext.Allocator); + Context.InitializeApplication(Context); Running = true; @@ -666,11 +527,48 @@ WinMain ( RenderBuffer.ViewHeight = MainWindow.Height; Context.DeltaTime = LastFrameSecondsElapsed; - Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer); + Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData); RenderCommandBuffer(RenderBuffer); ClearRenderBuffer(&RenderBuffer); + if (true) + { + // NOTE(pjs): Send the network data + + // TODO(pjs): This should happen on another thread + /* + Saved this lien as an example of pushing onto a queue + Context->GeneralWorkQueue->PushWorkOnQueue(Context->GeneralWorkQueue, SACNSendDMXBufferListJob, Job, "SACN Send Data Job"); + */ + + for (addressed_data_buffer* BufferAt = OutputData.Root; + BufferAt != 0; + BufferAt = BufferAt->Next) + { + switch(BufferAt->AddressType) + { + case AddressType_NetworkIP: + { + Win32Socket_SendTo(BufferAt->SendSocket, + BufferAt->V4SendAddress, + BufferAt->SendPort, + (const char*)BufferAt->Memory, + BufferAt->MemorySize, + 0); + }break; + + case AddressType_ComPort: + { + HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 9600, 8, 0, 1); + Win32SerialPort_Write(SerialPort, BufferAt->Data); + }break; + + InvalidDefaultCase; + } + } + } + Context.Mouse.LeftButtonState = GetMouseButtonStateAdvanced(Context.Mouse.LeftButtonState); Context.Mouse.MiddleButtonState = GetMouseButtonStateAdvanced(Context.Mouse.MiddleButtonState); Context.Mouse.RightButtonState = GetMouseButtonStateAdvanced(Context.Mouse.RightButtonState); @@ -729,6 +627,11 @@ WinMain ( Context.CleanupApplication(Context); + for (s32 SocketIdx = 0; SocketIdx < Win32Sockets.Count; SocketIdx++) + { + Win32Socket_Close(Win32Sockets.Values + SocketIdx); + } + s32 CleanupResult = 0; do { CleanupResult = WSACleanup(); diff --git a/src/app/platform_win32/win32_foldhaus_serial.h b/src/app/platform_win32/win32_foldhaus_serial.h index 31f4d73..c5e356a 100644 --- a/src/app/platform_win32/win32_foldhaus_serial.h +++ b/src/app/platform_win32/win32_foldhaus_serial.h @@ -5,6 +5,11 @@ // #ifndef WIN32_SERIAL_H +global u32 Win32SerialHandlesCountMax; +global u32 Win32SerialHandlesCount; +global HANDLE* Win32SerialHandles; +global gs_string* Win32SerialPortNames; + DCB Win32SerialPort_GetState(HANDLE ComPortHandle) { @@ -44,7 +49,26 @@ Win32SerialPort_Open(char* PortName) 0, // Not overlapped I/O NULL); - if (ComPortHandle == INVALID_HANDLE_VALUE) + if (ComPortHandle != INVALID_HANDLE_VALUE) + { + COMMTIMEOUTS Timeouts = { 0 }; + Timeouts.ReadIntervalTimeout = 50; // in milliseconds + Timeouts.ReadTotalTimeoutConstant = 50; // in milliseconds + Timeouts.ReadTotalTimeoutMultiplier = 10; // in milliseconds + Timeouts.WriteTotalTimeoutConstant = 50; // in milliseconds + Timeouts.WriteTotalTimeoutMultiplier = 10; // in milliseconds + + if (SetCommTimeouts(ComPortHandle, &Timeouts)) + { + + } + else + { + s32 Error = GetLastError(); + InvalidCodePath; + } + } + else { // Error s32 Error = GetLastError(); @@ -63,6 +87,8 @@ Win32SerialPort_Close(HANDLE PortHandle) void Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer) { + Assert(PortHandle != INVALID_HANDLE_VALUE); + DWORD BytesWritten = 0; if (WriteFile(PortHandle, Buffer.Memory, Buffer.Size, &BytesWritten, NULL)) { @@ -74,8 +100,64 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer) else { OutputDebugStringA("Error: Unable to write to port\n"); + s32 Error = GetLastError(); + //InvalidCodePath; } } +///////////////////////// +// Win32SerialArray + +void +Win32SerialArray_Create(gs_thread_context Context) +{ + Win32SerialHandlesCountMax = 32; + Win32SerialHandlesCount = 0; + Win32SerialHandles = AllocatorAllocArray(Context.Allocator, HANDLE, Win32SerialHandlesCountMax); + Win32SerialPortNames = AllocatorAllocArray(Context.Allocator, gs_string, Win32SerialHandlesCountMax); + for (u32 i = 0; i < Win32SerialHandlesCountMax; i++) + { + Win32SerialPortNames[i] = AllocatorAllocString(Context.Allocator, 256); + } +} + +void +Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName) +{ + Assert(Win32SerialHandlesCount < Win32SerialHandlesCountMax); + u32 Index = Win32SerialHandlesCount++; + Win32SerialHandles[Index] = SerialHandle; + PrintF(&Win32SerialPortNames[Index], "%S", PortName); +} + +HANDLE +Win32SerialArray_Get(gs_const_string PortName) +{ + HANDLE PortHandle = INVALID_HANDLE_VALUE; + for (u32 i = 0; i < Win32SerialHandlesCount; i++) + { + if (StringsEqual(Win32SerialPortNames[i].ConstString, PortName)) + { + PortHandle = Win32SerialHandles[i]; + break; + } + } + return PortHandle; +} + +HANDLE +Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits) +{ + HANDLE PortHandle = Win32SerialArray_Get(PortName); + if (PortHandle == INVALID_HANDLE_VALUE) + { + Assert(IsNullTerminated(PortName)); + PortHandle = Win32SerialPort_Open(PortName.Str); + Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits); + Win32SerialArray_Push(PortHandle, PortName); + } + return PortHandle; +} + #define WIN32_SERIAL_H #endif // WIN32_SERIAL_H \ No newline at end of file diff --git a/src/app/platform_win32/win32_foldhaus_socket.h b/src/app/platform_win32/win32_foldhaus_socket.h new file mode 100644 index 0000000..18df318 --- /dev/null +++ b/src/app/platform_win32/win32_foldhaus_socket.h @@ -0,0 +1,140 @@ +// +// File: win32_foldhaus_socket.h +// Author: Peter Slattery +// Creation Date: 2020-10-03 +// +#ifndef WIN32_FOLDHAUS_SOCKET_H + +struct win32_socket +{ + SOCKET Socket; +}; + +struct win32_socket_array +{ + win32_socket* Values; + s32 CountMax; + s32 Count; +}; + +////////////////////// +// +// Win32 Socket Array + +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; +} + +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; +} + +internal win32_socket* +Win32SocketArray_Get(win32_socket_array Array, s32 Index) +{ + Assert(Index < Array.Count); + win32_socket* Result = Array.Values + Index; + return Result; +} + +////////////////////// +// +// Win32 Socket System + +global win32_socket_array Win32Sockets; + +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; +} + +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); +} + +PLATFORM_GET_SOCKET_HANDLE(Win32GetSocketHandle) +{ + // NOTE(Peter): These used to be passed in as paramters, but we only use this function + // with AF_INET, SOCK_DGRAM, and Protocol = 0. These are also platform specific values + // so I was having to include windows.h in the platform agnostic code to accomodate that + // function signature. + s32 AddressFamily = AF_INET; + s32 Type = SOCK_DGRAM; + s32 Protocol = 0; + + s32 Result = Win32SocketArray_Take(&Win32Sockets); + win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, Result); + Socket->Socket = socket(AddressFamily, Type, Protocol); + if (Socket->Socket != INVALID_SOCKET) + { + int Error = Win32Socket_SetOption(Socket, IPPROTO_IP, IP_MULTICAST_TTL, + (const char*)(&Multicast_TimeToLive), sizeof(Multicast_TimeToLive)); + } + else + { + s32 Error = WSAGetLastError(); + InvalidCodePath; + } + + return (platform_socket_handle)Result; +} + +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)); + + if (LengthSent == SOCKET_ERROR) + { + s32 Error = WSAGetLastError(); + if (Error == 10051) + { + } + else + { + // TODO(Peter): :ErrorLogging + InvalidCodePath; + } + } + + return LengthSent; +} + +internal void +Win32Socket_Close(win32_socket* Socket) +{ + closesocket(Socket->Socket); + Socket->Socket = INVALID_SOCKET; +} + +#define WIN32_FOLDHAUS_SOCKET_H +#endif // WIN32_FOLDHAUS_SOCKET_H \ No newline at end of file diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp index a86c01c..4db796a 100644 --- a/src/gs_libs/gs_types.cpp +++ b/src/gs_libs/gs_types.cpp @@ -2235,6 +2235,9 @@ PushSizeOnCursor_(gs_memory_cursor* Cursor, u64 Size, char* Location) #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) { From ecca6c691ad1f4367d408168f8e947b9cb2529ac Mon Sep 17 00:00:00 2001 From: PS Date: Mon, 5 Oct 2020 13:17:33 -0700 Subject: [PATCH 30/43] Speeding up COM writing --- src/app/engine/animation/foldhaus_animation.h | 11 +++ .../foldhaus_animation_serializer.cpp | 10 ++ src/app/engine/assembly_parser.cpp | 11 ++- src/app/engine/foldhaus_addressed_data.h | 1 + src/app/engine/foldhaus_assembly.h | 2 +- src/app/engine/uart/foldhaus_uart.h | 47 ++++++---- src/app/foldhaus_log.h | 1 + src/app/platform_win32/win32_foldhaus.cpp | 93 ++++++++++++------- .../platform_win32/win32_foldhaus_serial.h | 77 ++++++++++++--- 9 files changed, 186 insertions(+), 67 deletions(-) create mode 100644 src/app/engine/animation/foldhaus_animation_serializer.cpp diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 98a5c08..a7444b5 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -35,6 +35,17 @@ struct anim_layer blend_mode BlendMode; }; +struct animation +{ + anim_layer* Layers; + u32 LayersCount; + u32 LayersMax; + + gs_list Blocks; + + frame_range PlayableRange; +}; + #define ANIMATION_SYSTEM_LAYERS_MAX 128 #define ANIMATION_SYSTEM_BLOCKS_MAX 128 struct animation_system diff --git a/src/app/engine/animation/foldhaus_animation_serializer.cpp b/src/app/engine/animation/foldhaus_animation_serializer.cpp new file mode 100644 index 0000000..481b248 --- /dev/null +++ b/src/app/engine/animation/foldhaus_animation_serializer.cpp @@ -0,0 +1,10 @@ +// +// File: foldhaus_animation_serializer.cpp +// Author: Peter Slattery +// Creation Date: 2020-10-04 +// +#ifndef FOLDHAUS_ANIMATION_SERIALIZER_CPP + + +#define FOLDHAUS_ANIMATION_SERIALIZER_CPP +#endif // FOLDHAUS_ANIMATION_SERIALIZER_CPP \ No newline at end of file diff --git a/src/app/engine/assembly_parser.cpp b/src/app/engine/assembly_parser.cpp index 636c11c..006ae62 100644 --- a/src/app/engine/assembly_parser.cpp +++ b/src/app/engine/assembly_parser.cpp @@ -284,7 +284,7 @@ ReadInt(assembly_tokenizer* T) } internal gs_string -ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Arena) +ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Arena, bool ShouldNullTerminate = false) { gs_string Result = {}; if (ReadFieldIdentifier(Field, T)) @@ -293,8 +293,13 @@ ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Ar if (ReadFieldEnd(T)) { // Success - Result = PushString(Arena, ExistingString.Length); + u64 Length = ExistingString.Length + (ShouldNullTerminate ? 1 : 0); + Result = PushString(Arena, Length); PrintF(&Result, "%S", ExistingString); + if (ShouldNullTerminate) + { + NullTerminate(&Result); + } } } return Result; @@ -430,6 +435,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe if (StringsEqual(OutputModeString.ConstString, ConstString("UART"))) { Assembly->OutputMode = NetworkProtocol_UART; + Assembly->UARTComPort = ReadStringField(AssemblyField_UART_ComPort, &Tokenizer, &Assembly->Arena, true).ConstString; } else if (StringsEqual(OutputModeString.ConstString, ConstString("SACN"))) { @@ -459,7 +465,6 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe if (ReadStructOpening(AssemblyField_OutputUART, &Tokenizer, PARSER_FIELD_OPTIONAL)) { StripAt->UARTAddr.Channel = (u8)ReadIntField(AssemblyField_UART_Channel, &Tokenizer); - StripAt->UARTAddr.ComPort = ReadStringField(AssemblyField_UART_ComPort, &Tokenizer, &Assembly->Arena).ConstString; if (!ReadStructClosing(&Tokenizer)) { diff --git a/src/app/engine/foldhaus_addressed_data.h b/src/app/engine/foldhaus_addressed_data.h index 79a84de..47b70d7 100644 --- a/src/app/engine/foldhaus_addressed_data.h +++ b/src/app/engine/foldhaus_addressed_data.h @@ -61,6 +61,7 @@ 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; diff --git a/src/app/engine/foldhaus_assembly.h b/src/app/engine/foldhaus_assembly.h index c702a3b..55185e3 100644 --- a/src/app/engine/foldhaus_assembly.h +++ b/src/app/engine/foldhaus_assembly.h @@ -58,7 +58,6 @@ struct strip_sacn_addr struct strip_uart_addr { u8 Channel; - gs_const_string ComPort; }; struct v2_strip @@ -103,6 +102,7 @@ struct assembly v2_strip* Strips; network_protocol OutputMode; + gs_const_string UARTComPort; }; struct assembly_array diff --git a/src/app/engine/uart/foldhaus_uart.h b/src/app/engine/uart/foldhaus_uart.h index a80b7ff..7e36e00 100644 --- a/src/app/engine/uart/foldhaus_uart.h +++ b/src/app/engine/uart/foldhaus_uart.h @@ -81,25 +81,16 @@ UART_FillFooter(uart_footer* Footer, u8* BufferStart) } internal void -UART_SetChannelBuffer_Create(addressed_data_buffer_list* Output, uart_channel ChannelSettings, v2_strip Strip, led_buffer LedBuffer) +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); - u32 BufferSize = sizeof(uart_header) + sizeof(uart_channel); - BufferSize += ChannelSettings.ElementsCount * ChannelSettings.PixelsCount; - BufferSize += sizeof(uart_footer); - - addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, BufferSize); - AddressedDataBuffer_SetCOMPort(Buffer, Strip.UARTAddr.ComPort); - - gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); - - uart_header* Header = PushStructOnCursor(&WriteCursor, uart_header); + uart_header* Header = PushStructOnCursor(WriteCursor, uart_header); UART_FillHeader(Header, Strip.UARTAddr.Channel, UART_SET_CHANNEL_WS2812); - uart_channel* Channel = PushStructOnCursor(&WriteCursor, uart_channel); + uart_channel* Channel = PushStructOnCursor(WriteCursor, uart_channel); *Channel = ChannelSettings; for (u32 i = 0; i < Channel->PixelsCount; i++) @@ -107,7 +98,7 @@ UART_SetChannelBuffer_Create(addressed_data_buffer_list* Output, uart_channel Ch u32 LedIndex = Strip.LedLUT[i]; pixel Color = LedBuffer.Colors[LedIndex]; - u8* OutputPixel = PushArrayOnCursor(&WriteCursor, u8, 3); + u8* OutputPixel = PushArrayOnCursor(WriteCursor, u8, 3); OutputPixel[Channel->RedIndex] = Color.R; OutputPixel[Channel->GreenIndex] = Color.G; @@ -123,8 +114,18 @@ UART_SetChannelBuffer_Create(addressed_data_buffer_list* Output, uart_channel Ch } } - uart_footer* Footer = PushStructOnCursor(&WriteCursor, uart_footer); - UART_FillFooter(Footer, Buffer->Memory); + uart_footer* Footer = PushStructOnCursor(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); } internal void @@ -137,17 +138,31 @@ UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assembli ChannelSettings.BlueIndex = 3; ChannelSettings.WhiteIndex = 0; + // 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 = sizeof(uart_header) + sizeof(uart_channel) + sizeof(uart_footer); + for (u32 AssemblyIdx = 0; AssemblyIdx < Assemblies.Count; AssemblyIdx++) { assembly Assembly = Assemblies.Values[AssemblyIdx]; led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); + u32 TotalBufferSize = MessageBaseSize * Assembly.StripCount; // SetChannelBuffer messages + TotalBufferSize += MessageBaseSize; // DrawAll message + TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel + + addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize); + AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort); + gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); + for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) { v2_strip StripAt = Assembly.Strips[StripIdx]; ChannelSettings.PixelsCount = StripAt.LedCount; - UART_SetChannelBuffer_Create(Output, ChannelSettings, StripAt, *LedBuffer); + UART_SetChannelBuffer_Create(&WriteCursor, ChannelSettings, StripAt, *LedBuffer); } + + UART_DrawAll_Create(&WriteCursor); } } diff --git a/src/app/foldhaus_log.h b/src/app/foldhaus_log.h index 0cffd1a..5d1c936 100644 --- a/src/app/foldhaus_log.h +++ b/src/app/foldhaus_log.h @@ -44,5 +44,6 @@ PushLogEntry(event_log* Log, gs_string Message, log_entry_type Type) + #define FOLDHAUS_LOG_H #endif // FOLDHAUS_LOG_H \ No newline at end of file diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index dc076eb..d70938d 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -364,6 +364,58 @@ Win32LoadSystemCursor(char* CursorIdentifier) return Result; } +internal void +Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_list OutputData) +{ + DEBUG_TRACK_FUNCTION; + + u32 BuffersSent = 0; + + for (addressed_data_buffer* BufferAt = OutputData.Root; + BufferAt != 0; + BufferAt = BufferAt->Next) + { + switch(BufferAt->AddressType) + { + case AddressType_NetworkIP: + { + Win32Socket_SendTo(BufferAt->SendSocket, + BufferAt->V4SendAddress, + BufferAt->SendPort, + (const char*)BufferAt->Memory, + BufferAt->MemorySize, + 0); + }break; + + case AddressType_ComPort: + { + HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1); + if (SerialPort != INVALID_HANDLE_VALUE) + { + if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) + { + BuffersSent += 1; + } + } + }break; + + InvalidDefaultCase; + } + } + + gs_string OutputStr = AllocatorAllocString(Context.Allocator, 256); + PrintF(&OutputStr, "Buffers Sent: %d\n", BuffersSent); + NullTerminate(&OutputStr); + OutputDebugStringA(OutputStr.Str); +} + +internal void +Win32_SendAddressedDataBuffers_Job(gs_thread_context Context, gs_data Arg) +{ + addressed_data_buffer_list* OutputData = (addressed_data_buffer_list*)Arg.Memory; + Win32_SendAddressedDataBuffers(Context, *OutputData); +} + int WINAPI WinMain ( HINSTANCE HInstance, @@ -504,6 +556,8 @@ WinMain ( Context.ReloadStaticData(Context, GlobalDebugServices); } + AddressedDataBufferList_Clear(&OutputData); + { // Mouse Position POINT MousePos; GetCursorPos (&MousePos); @@ -534,39 +588,10 @@ WinMain ( if (true) { - // NOTE(pjs): Send the network data - - // TODO(pjs): This should happen on another thread - /* - Saved this lien as an example of pushing onto a queue - Context->GeneralWorkQueue->PushWorkOnQueue(Context->GeneralWorkQueue, SACNSendDMXBufferListJob, Job, "SACN Send Data Job"); - */ - - for (addressed_data_buffer* BufferAt = OutputData.Root; - BufferAt != 0; - BufferAt = BufferAt->Next) - { - switch(BufferAt->AddressType) - { - case AddressType_NetworkIP: - { - Win32Socket_SendTo(BufferAt->SendSocket, - BufferAt->V4SendAddress, - BufferAt->SendPort, - (const char*)BufferAt->Memory, - BufferAt->MemorySize, - 0); - }break; - - case AddressType_ComPort: - { - HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 9600, 8, 0, 1); - Win32SerialPort_Write(SerialPort, BufferAt->Data); - }break; - - InvalidDefaultCase; - } - } + gs_data ProcArg = {}; + ProcArg.Memory = (u8*)&OutputData; + ProcArg.Size = sizeof(OutputData); + Win32PushWorkOnQueue(&WorkQueue, Win32_SendAddressedDataBuffers_Job, ProcArg, ConstString("Send UART Data")); } Context.Mouse.LeftButtonState = GetMouseButtonStateAdvanced(Context.Mouse.LeftButtonState); @@ -610,6 +635,8 @@ WinMain ( SwapBuffers(DeviceContext); ReleaseDC(MainWindow.Handle, DeviceContext); + //Win32DoQueueWorkUntilDone(&WorkQueue, Context.ThreadContext); + s64 FinishedWorkTime = GetWallClock(); r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency); diff --git a/src/app/platform_win32/win32_foldhaus_serial.h b/src/app/platform_win32/win32_foldhaus_serial.h index c5e356a..fbf389f 100644 --- a/src/app/platform_win32/win32_foldhaus_serial.h +++ b/src/app/platform_win32/win32_foldhaus_serial.h @@ -13,6 +13,7 @@ global gs_string* Win32SerialPortNames; DCB Win32SerialPort_GetState(HANDLE ComPortHandle) { + DEBUG_TRACK_FUNCTION; DCB ControlSettings = {0}; ZeroStruct(&ControlSettings); ControlSettings.DCBlength = sizeof(ControlSettings); @@ -26,14 +27,45 @@ Win32SerialPort_GetState(HANDLE ComPortHandle) void Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits) { + DEBUG_TRACK_FUNCTION; DCB ControlSettings = Win32SerialPort_GetState(ComPortHandle); - //PrintCommState(ControlSettings); // TODO(pjs): Validate BaudRate - There's only certain rates that are valid right? ControlSettings.BaudRate = BaudRate; - ControlSettings.ByteSize = ByteSize; - ControlSettings.Parity = Parity; + + 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); } @@ -41,6 +73,7 @@ Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Par HANDLE Win32SerialPort_Open(char* PortName) { + DEBUG_TRACK_FUNCTION; HANDLE ComPortHandle = CreateFile(PortName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -52,11 +85,11 @@ Win32SerialPort_Open(char* PortName) if (ComPortHandle != INVALID_HANDLE_VALUE) { COMMTIMEOUTS Timeouts = { 0 }; - Timeouts.ReadIntervalTimeout = 50; // in milliseconds - Timeouts.ReadTotalTimeoutConstant = 50; // in milliseconds - Timeouts.ReadTotalTimeoutMultiplier = 10; // in milliseconds - Timeouts.WriteTotalTimeoutConstant = 50; // in milliseconds - Timeouts.WriteTotalTimeoutMultiplier = 10; // in milliseconds + 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 if (SetCommTimeouts(ComPortHandle, &Timeouts)) { @@ -65,14 +98,14 @@ Win32SerialPort_Open(char* PortName) else { s32 Error = GetLastError(); - InvalidCodePath; + // TODO(pjs): Error logging } } else { // Error s32 Error = GetLastError(); - InvalidCodePath; + // TODO(pjs): Error logging } return ComPortHandle; @@ -84,15 +117,18 @@ Win32SerialPort_Close(HANDLE PortHandle) CloseHandle(PortHandle); } -void +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)) { - if (BytesWritten != Buffer.Size) + Success = (BytesWritten == Buffer.Size); + if (!Success) { OutputDebugString("Error: Entire buffer not written.\n"); } @@ -103,6 +139,8 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer) s32 Error = GetLastError(); //InvalidCodePath; } + + return Success; } ///////////////////////// @@ -111,6 +149,8 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer) void Win32SerialArray_Create(gs_thread_context Context) { + DEBUG_TRACK_FUNCTION; + Win32SerialHandlesCountMax = 32; Win32SerialHandlesCount = 0; Win32SerialHandles = AllocatorAllocArray(Context.Allocator, HANDLE, Win32SerialHandlesCountMax); @@ -124,6 +164,8 @@ Win32SerialArray_Create(gs_thread_context Context) void Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName) { + DEBUG_TRACK_FUNCTION; + Assert(Win32SerialHandlesCount < Win32SerialHandlesCountMax); u32 Index = Win32SerialHandlesCount++; Win32SerialHandles[Index] = SerialHandle; @@ -133,6 +175,8 @@ Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName) HANDLE Win32SerialArray_Get(gs_const_string PortName) { + DEBUG_TRACK_FUNCTION; + HANDLE PortHandle = INVALID_HANDLE_VALUE; for (u32 i = 0; i < Win32SerialHandlesCount; i++) { @@ -148,13 +192,18 @@ Win32SerialArray_Get(gs_const_string PortName) HANDLE Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits) { + DEBUG_TRACK_FUNCTION; + HANDLE PortHandle = Win32SerialArray_Get(PortName); if (PortHandle == INVALID_HANDLE_VALUE) { Assert(IsNullTerminated(PortName)); PortHandle = Win32SerialPort_Open(PortName.Str); - Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits); - Win32SerialArray_Push(PortHandle, PortName); + if (PortHandle != INVALID_HANDLE_VALUE) + { + Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits); + Win32SerialArray_Push(PortHandle, PortName); + } } return PortHandle; } From b816474dd50d86c2d5adb47ebbf5aab9227211da Mon Sep 17 00:00:00 2001 From: PS Date: Fri, 9 Oct 2020 22:08:51 -0700 Subject: [PATCH 31/43] Successfully transitioned to discrete animations --- .../foldhaus_panel_animation_timeline.h | 199 +++++++++------- src/app/engine/animation/foldhaus_animation.h | 222 +++++++++++++----- src/app/foldhaus_app.cpp | 73 +++--- src/gs_libs/gs_types.cpp | 22 ++ 4 files changed, 347 insertions(+), 169 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 17a469b..3c2140b 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -34,11 +34,12 @@ GetXPositionFromFrameInAnimationPanel (u32 Frame, rect2 PanelBounds, frame_range } internal gs_list_handle -AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, u32 Layer, animation_system* System) +AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, u32 LayerHandle, animation_system* System) { u32 NewBlockStart = System->CurrentFrame; u32 NewBlockEnd = NewBlockStart + SecondsToFrames(3, *System); - gs_list_handle Result = AddAnimationBlock(NewBlockStart, NewBlockEnd, AnimationProcHandle, Layer, System); + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System); + gs_list_handle Result = Animation_AddBlock(ActiveAnim, NewBlockStart, NewBlockEnd, AnimationProcHandle, LayerHandle); return Result; } @@ -58,7 +59,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand) { if(ListHandleIsValid(State->SelectedAnimationBlockHandle)) { - RemoveAnimationBlock(State->SelectedAnimationBlockHandle, &State->AnimationSystem); + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); + Animation_RemoveBlock(ActiveAnim, State->SelectedAnimationBlockHandle); State->SelectedAnimationBlockHandle = {0}; } } @@ -135,6 +137,8 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) { drag_animation_clip_state* OpState = (drag_animation_clip_state*)Operation.OpStateMemory; + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); + r32 ClipInitialStartFrameXPercent = FrameToPercentRange(OpState->ClipRange.Min, OpState->VisibleRange); u32 ClipInitialStartFrameXPosition = LerpR32(ClipInitialStartFrameXPercent, OpState->TimelineBounds.Min.x, @@ -149,7 +153,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) u32 FrameAtMouseX = GetFrameFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->VisibleRange); s32 FrameOffset = (s32)FrameAtMouseX - (s32)FrameAtMouseDownX; - animation_block* AnimationBlock = State->AnimationSystem.Blocks.GetElementWithHandle(State->SelectedAnimationBlockHandle); + animation_block* AnimationBlock = ActiveAnim->Blocks.GetElementWithHandle(State->SelectedAnimationBlockHandle); if (!AnimationBlock) { EndCurrentOperationMode(State, {}, Mouse, Context); @@ -161,9 +165,9 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) s32 NewStartFrame = OpState->ClipRange.Min + FrameOffset; if (FrameOffset < 0) { - for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) + for (u32 i = 0; i < ActiveAnim->Blocks.Used; i++) { - gs_list_entry* OtherBlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i); + gs_list_entry* OtherBlockEntry = ActiveAnim->Blocks.GetEntryAtIndex(i); if (EntryIsFree(OtherBlockEntry)) { continue; } animation_block OtherBlock = OtherBlockEntry->Value; NewStartFrame = AttemptToSnapPosition(NewStartFrame, OtherBlock.Range.Max); @@ -183,9 +187,9 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) r32 NewEndFrame = OpState->ClipRange.Max + FrameOffset; if (FrameOffset > 0) { - for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) + for (u32 i = 0; i < ActiveAnim->Blocks.Used; i++) { - gs_list_entry* OtherBlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i); + gs_list_entry* OtherBlockEntry = ActiveAnim->Blocks.GetEntryAtIndex(i); if (EntryIsFree(OtherBlockEntry)) { continue; } animation_block OtherBlock = OtherBlockEntry->Value; NewEndFrame = AttemptToSnapPosition(NewEndFrame, OtherBlock.Range.Min); @@ -204,9 +208,9 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) { u32 NewStartFrame = OpState->ClipRange.Min + FrameOffset; u32 NewEndFrame = OpState->ClipRange.Max + FrameOffset; - for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) + for (u32 i = 0; i < ActiveAnim->Blocks.Used; i++) { - gs_list_entry* OtherBlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i); + gs_list_entry* OtherBlockEntry = ActiveAnim->Blocks.GetEntryAtIndex(i); if (EntryIsFree(OtherBlockEntry)) { continue; } animation_block OtherBlock = OtherBlockEntry->Value; @@ -228,8 +232,8 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) AnimationBlock->Range.Max = NewEndFrame; } - s32 PlayableStartFrame = State->AnimationSystem.PlayableRange.Min; - s32 PlayableEndFrame = State->AnimationSystem.PlayableRange.Max; + s32 PlayableStartFrame = ActiveAnim->PlayableRange.Min; + s32 PlayableEndFrame = ActiveAnim->PlayableRange.Max; AnimationBlock->Range.Min = (u32)Clamp(PlayableStartFrame, (s32)AnimationBlock->Range.Min, PlayableEndFrame); AnimationBlock->Range.Max = (u32)Clamp(PlayableStartFrame, (s32)AnimationBlock->Range.Max, PlayableEndFrame); } @@ -243,6 +247,7 @@ SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range Visible { SelectAnimationBlock(BlockHandle, State); + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); operation_mode* DragAnimationClipMode = ActivateOperationModeWithCommands(&State->Modes, DragAnimationClipCommands, UpdateDragAnimationClip); drag_animation_clip_state* OpState = CreateOperationState(DragAnimationClipMode, @@ -251,17 +256,20 @@ SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range Visible OpState->TimelineBounds = TimelineBounds; OpState->VisibleRange = VisibleRange; - animation_block* SelectedBlock = State->AnimationSystem.Blocks.GetElementWithHandle(BlockHandle); + animation_block* SelectedBlock = ActiveAnim->Blocks.GetElementWithHandle(BlockHandle); OpState->ClipRange = SelectedBlock->Range; } // ------------------- FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand) { + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); + panel_and_bounds ActivePanel = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, State->WindowBounds); - frame_range Range = State->AnimationSystem.PlayableRange; + frame_range Range = ActiveAnim->PlayableRange; u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel.Bounds, Range); - gs_list_handle NewBlockHandle = AddAnimationBlock(MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, State->SelectedAnimationLayer, &State->AnimationSystem); + + gs_list_handle NewBlockHandle = Animation_AddBlock(ActiveAnim, MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, State->SelectedAnimationLayer); SelectAnimationBlock(NewBlockHandle, State); } @@ -277,8 +285,9 @@ internal void AnimationTimeline_Init(panel* Panel, app_state* State, context Context) { // TODO: :FreePanelMemory + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); animation_timeline_state* TimelineState = PushStruct(&State->Permanent, animation_timeline_state); - TimelineState->VisibleRange = State->AnimationSystem.PlayableRange; + TimelineState->VisibleRange = ActiveAnim->PlayableRange; Panel->PanelStateMemory = (u8*)TimelineState; } @@ -300,8 +309,6 @@ DrawFrameBar (animation_system* AnimationSystem, ui_interface Interface, frame_r r32 BarHeight = Rect2Height(BarBounds); r32 BarWidth = Rect2Width(BarBounds); - PushRenderQuad2D(Interface.RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); - // Mouse clicked inside frame nubmer bar -> change current frame on timeline if (MouseButtonTransitionedDown(Interface.Mouse.LeftButtonState) && PointIsInRect(BarBounds, Interface.Mouse.DownPos)) @@ -309,6 +316,8 @@ DrawFrameBar (animation_system* AnimationSystem, ui_interface Interface, frame_r StartDragTimeMarker(BarBounds, VisibleFrames, State); } + PushRenderQuad2D(Interface.RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); + // Frame Ticks u32 TickCount = 10; for (u32 Tick = 0; Tick < TickCount; Tick++) @@ -323,7 +332,7 @@ DrawFrameBar (animation_system* AnimationSystem, ui_interface Interface, frame_r } // Time Slider - if (FrameIsInRange(AnimationSystem->CurrentFrame, VisibleFrames)) + if (FrameIsInRange(VisibleFrames, AnimationSystem->CurrentFrame)) { r32 FrameAtPercentVisibleRange = FrameToPercentRange(AnimationSystem->CurrentFrame, VisibleFrames); r32 SliderX = LerpR32(FrameAtPercentVisibleRange, BarBounds.Min.x, BarBounds.Max.x); @@ -340,91 +349,117 @@ DrawFrameBar (animation_system* AnimationSystem, ui_interface Interface, frame_r } } -internal frame_range -DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_state* TimelineState, ui_interface Interface, rect2 BarBounds) +internal bool +MinMaxRangeSlider(v2 HandleValues, rect2 SliderBounds, r32 MinValue, r32 MaxValue, ui_interface Interface, v2* OutHandleValues) { - frame_range Result = {0}; + // Should Update only gets set to true when the user is finished interacting (ie. on mouse up) + // this allows the continuous use of the value of a handle while it is being dragged, and allows + // for you to know when exactly to update the stored value - r32 BarHeight = Rect2Height(BarBounds); - r32 BarWidth = Rect2Width(BarBounds); - PushRenderQuad2D(Interface.RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); + bool ShouldUpdate = false; + *OutHandleValues = HandleValues; - r32 PlayableFrames = (r32)GetFrameCount(AnimationSystem->PlayableRange); - v2 SliderBarDim = v2{25, BarHeight}; + v4 BGColor = v4{.16f, .16f, .16f, 1.f}; + v4 HandleColor = v4{.8f, .8f, .8f, 1.f}; - // Convert Frames To Pixels - r32 VisibleMinPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Min, AnimationSystem->PlayableRange); - r32 VisibleMaxPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Max, AnimationSystem->PlayableRange); - v2 RangeMinSliderMin = v2{BarBounds.Min.x + (VisibleMinPercentPlayable * Rect2Width(BarBounds)), BarBounds.Min.y}; - v2 RangeMaxSliderMin = v2{BarBounds.Min.x + (VisibleMaxPercentPlayable * Rect2Width(BarBounds)) - 25, BarBounds.Min.y}; - - rect2 SliderBarRange = rect2{ RangeMinSliderMin, RangeMinSliderMin + SliderBarDim }; + v2 HandleDim = v2{25, Rect2Height(SliderBounds)}; + r32 MinHandleX = RemapR32(HandleValues.x, MinValue, MaxValue, SliderBounds.Min.x, SliderBounds.Max.x); + r32 MaxHandleX = RemapR32(HandleValues.y, MinValue, MaxValue, SliderBounds.Min.x, SliderBounds.Max.x); + rect2 MinHandleBounds = MakeRect2CenterDim(v2{ MinHandleX, Rect2Center(SliderBounds).y }, HandleDim); + rect2 MaxHandleBounds = MakeRect2CenterDim(v2{ MaxHandleX, Rect2Center(SliderBounds).y }, HandleDim); + // Drag the handles if (MouseButtonHeldDown(Interface.Mouse.LeftButtonState) || MouseButtonTransitionedUp(Interface.Mouse.LeftButtonState)) { v2 MouseDragOffset = Interface.Mouse.Pos - Interface.Mouse.DownPos; - if (PointIsInRect(SliderBarRange, Interface.Mouse.DownPos)) + + // TODO(pjs): We need to make sure that the min handle is always the lower one, etc. + // TODO(pjs): We need to range clamp the handles + if (PointIsInRect(MinHandleBounds, Interface.Mouse.DownPos)) { - r32 NewSliderX = RangeMinSliderMin.x + MouseDragOffset.x; - RangeMinSliderMin.x = Clamp(BarBounds.Min.x, NewSliderX, RangeMaxSliderMin.x - SliderBarDim.x); + MinHandleBounds = Rect2TranslateX(MinHandleBounds, MouseDragOffset.x); } - if (PointIsInRect(SliderBarRange, Interface.Mouse.DownPos)) + else if (PointIsInRect(MaxHandleBounds, Interface.Mouse.DownPos)) { - r32 NewSliderX = RangeMaxSliderMin.x + MouseDragOffset.x; - RangeMaxSliderMin.x = Clamp(RangeMinSliderMin.x + SliderBarDim.x, NewSliderX, BarBounds.Max.x - SliderBarDim.x); + MaxHandleBounds = Rect2TranslateX(MaxHandleBounds, MouseDragOffset.x); } } + + // Draw Background + PushRenderQuad2D(Interface.RenderBuffer, SliderBounds.Min, SliderBounds.Max, BGColor); - v2 RangeMinSliderMax = v2{RangeMinSliderMin.x + 25, BarBounds.Max.y}; - v2 RangeMaxSliderMax = v2{RangeMaxSliderMin.x + 25, BarBounds.Max.y}; - PushRenderQuad2D(Interface.RenderBuffer, RangeMinSliderMin, RangeMinSliderMax, v4{.8f, .8f, .8f, 1.f}); - PushRenderQuad2D(Interface.RenderBuffer, RangeMaxSliderMin, RangeMaxSliderMax, v4{.8f, .8f, .8f, 1.f}); + // Draw Handles + PushRenderQuad2D(Interface.RenderBuffer, MinHandleBounds.Min, MinHandleBounds.Max, HandleColor); + PushRenderQuad2D(Interface.RenderBuffer, MaxHandleBounds.Min, MaxHandleBounds.Max, HandleColor); - // Convert Pixels Back To Frames and store - VisibleMinPercentPlayable = (RangeMinSliderMin.x - BarBounds.Min.x) / BarWidth; - VisibleMaxPercentPlayable = (RangeMaxSliderMax.x - BarBounds.Min.x) / BarWidth; - u32 VisibleFrameCount = GetFrameCount(AnimationSystem->PlayableRange); - Result.Min = VisibleMinPercentPlayable * VisibleFrameCount; - Result.Max = VisibleMaxPercentPlayable * VisibleFrameCount; + // Update the output range value + r32 MinHandleXOut = Rect2Center(MinHandleBounds).x; + r32 MaxHandleXOut = Rect2Center(MaxHandleBounds).x; + + r32 MinHandleValue = RemapR32(MinHandleXOut, SliderBounds.Min.x, SliderBounds.Max.x, MinValue, MaxValue); + r32 MaxHandleValue = RemapR32(MaxHandleXOut, SliderBounds.Min.x, SliderBounds.Max.x, MinValue, MaxValue); + + *OutHandleValues = v2{ Min(MinHandleValue, MaxHandleValue), Max(MinHandleValue, MaxHandleValue) }; if (MouseButtonTransitionedUp(Interface.Mouse.LeftButtonState)) { - TimelineState->VisibleRange = Result; + ShouldUpdate = true; } - return Result; + return ShouldUpdate; +} + + +internal frame_range +DrawTimelineRangeBar (animation_system* AnimationSystem, animation Animation, animation_timeline_state* TimelineState, ui_interface Interface, rect2 BarBounds) +{ + frame_range VisibleRangeAfterInteraction = {}; + r32 MinFrame = (r32)Animation.PlayableRange.Min; + r32 MaxFrame = (r32)Animation.PlayableRange.Max; + + v2 RangeHandles = v2{ (r32)TimelineState->VisibleRange.Min, (r32)TimelineState->VisibleRange.Max }; + + bool ApplyUpdate = MinMaxRangeSlider(RangeHandles, BarBounds, MinFrame, MaxFrame, Interface, &RangeHandles); + VisibleRangeAfterInteraction.Min = (s32)RangeHandles.x; + VisibleRangeAfterInteraction.Max = (s32)RangeHandles.y; + + if (ApplyUpdate) + { + TimelineState->VisibleRange = VisibleRangeAfterInteraction; + } + + return VisibleRangeAfterInteraction; } #define LAYER_HEIGHT 52 -internal u32 -DrawLayerMenu(animation_system* AnimationSystem, ui_interface Interface, rect2 PanelDim, u32 SelectedAnimationLayer) +internal void +DrawLayerMenu(animation_system* AnimationSystem, animation ActiveAnim, ui_interface Interface, rect2 PanelDim, u32* SelectedAnimationLayer) { v2 LayerDim = { Rect2Width(PanelDim), LAYER_HEIGHT }; v2 LayerListMin = PanelDim.Min + v2{0, 24}; - for (u32 LayerIndex = 0; LayerIndex < AnimationSystem->LayersCount; LayerIndex++) + for (u32 i = 0; i < ActiveAnim.Layers.Count; i++) { - anim_layer* Layer = AnimationSystem->Layers + LayerIndex; + anim_layer* Layer = ActiveAnim.Layers.Values + i; + rect2 LayerBounds = {0}; - LayerBounds.Min = { LayerListMin.x, LayerListMin.y + (LayerDim.y * LayerIndex) }; + LayerBounds.Min = { LayerListMin.x, LayerListMin.y + (LayerDim.y * i) }; LayerBounds.Max = LayerBounds.Min + LayerDim; if (MouseButtonTransitionedDown(Interface.Mouse.LeftButtonState) && PointIsInRect(LayerBounds, Interface.Mouse.Pos)) { - SelectedAnimationLayer = LayerIndex; + *SelectedAnimationLayer = i; } v2 LayerTextPos = { LayerBounds.Min.x + 6, LayerBounds.Max.y - 16}; - if (SelectedAnimationLayer == LayerIndex) + if (*SelectedAnimationLayer == i) { PushRenderBoundingBox2D(Interface.RenderBuffer, LayerBounds.Min, LayerBounds.Max, 1, WhiteV4); } DrawString(Interface.RenderBuffer, Layer->Name, Interface.Style.Font, LayerTextPos, WhiteV4); } - - return SelectedAnimationLayer; } internal rect2 @@ -458,19 +493,22 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta gs_string Tempgs_string = PushString(State->Transient, 256); gs_list_handle Result = SelectedBlockHandle; + // TODO(pjs): Animation Selection + animation CurrAnimation = AnimationSystem->Animations.Values[0]; + rect2 LayerMenuBounds, TimelineBounds; RectVSplitAtDistanceFromLeft(PanelBounds, 256, &LayerMenuBounds, &TimelineBounds); // In Top To Bottom Order - rect2 TimelineFrameBarBounds, TimelineBlockDisplayBounds, TimelineRangeBarBounds; + rect2 TimelineFrameBarBounds; + rect2 TimelineBlockDisplayBounds; + rect2 TimelineRangeBarBounds; RectHSplitAtDistanceFromTop(TimelineBounds, 32, &TimelineFrameBarBounds, &TimelineBounds); RectHSplitAtDistanceFromBottom(TimelineBounds, 24, &TimelineBlockDisplayBounds, &TimelineRangeBarBounds); - State->SelectedAnimationLayer = DrawLayerMenu(AnimationSystem, *Interface, LayerMenuBounds, State->SelectedAnimationLayer); + DrawLayerMenu(AnimationSystem, CurrAnimation, *Interface, LayerMenuBounds, &State->SelectedAnimationLayer); - frame_range AdjustedViewRange = {0}; - AdjustedViewRange = DrawTimelineRangeBar(AnimationSystem, TimelineState, *Interface, TimelineRangeBarBounds); - s32 VisibleFrameCount = AdjustedViewRange.Max - AdjustedViewRange.Min; + frame_range AdjustedViewRange = DrawTimelineRangeBar(AnimationSystem, CurrAnimation, TimelineState, *Interface, TimelineRangeBarBounds); DrawFrameBar(AnimationSystem, *Interface, AdjustedViewRange, TimelineFrameBarBounds, State); @@ -479,17 +517,17 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta // Animation Blocks b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState); gs_list_handle DragBlockHandle = {0}; - for (u32 i = 0; i < AnimationSystem->Blocks.Used; i++) + for (u32 i = 0; i < CurrAnimation.Blocks.Used; i++) { - gs_list_entry* AnimationBlockEntry = AnimationSystem->Blocks.GetEntryAtIndex(i); + gs_list_entry* AnimationBlockEntry = CurrAnimation.Blocks.GetEntryAtIndex(i); if (EntryIsFree(AnimationBlockEntry)) { continue; } gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle; animation_block AnimationBlockAt = AnimationBlockEntry->Value; // If either end is in the range, we should draw it - b32 RangeIsVisible = (FrameIsInRange(AnimationBlockAt.Range.Min, AdjustedViewRange) || - FrameIsInRange(AnimationBlockAt.Range.Max, AdjustedViewRange)); + b32 RangeIsVisible = (FrameIsInRange(AdjustedViewRange, AnimationBlockAt.Range.Min) || + FrameIsInRange(AdjustedViewRange, AnimationBlockAt.Range.Max)); // If neither end is in the range, but the ends surround the visible range, // we should still draw it. RangeIsVisible |= (AnimationBlockAt.Range.Min <= AdjustedViewRange.Min && @@ -516,7 +554,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta } // Time Slider - if (FrameIsInRange(AnimationSystem->CurrentFrame, AdjustedViewRange)) + if (FrameIsInRange(AdjustedViewRange, AnimationSystem->CurrentFrame)) { r32 FrameAtPercentVisibleRange = FrameToPercentRange(AnimationSystem->CurrentFrame, AdjustedViewRange); r32 SliderX = LerpR32(FrameAtPercentVisibleRange, TimelineBounds.Min.x, TimelineBounds.Max.x); @@ -554,7 +592,7 @@ animation_clip GlobalAnimationClips[] = { }; internal void -DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayer, animation_system* AnimationSystem) +DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayerHandle, animation_system* AnimationSystem) { ui_layout Layout = ui_CreateLayout(*Interface, PanelBounds); for (s32 i = 0; i < GlobalAnimationClipsCount; i++) @@ -563,7 +601,7 @@ DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedA gs_string ClipName = MakeString(Clip.Name, Clip.NameLength); if (ui_LayoutListEntry(Interface, &Layout, ClipName, i)) { - AddAnimationBlockAtCurrentTime(i + 1, SelectedAnimationLayer, AnimationSystem); + AddAnimationBlockAtCurrentTime(i + 1, SelectedAnimationLayerHandle, AnimationSystem); } } } @@ -574,14 +612,15 @@ internal void AnimationTimeline_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { animation_timeline_state* TimelineState = (animation_timeline_state*)Panel.PanelStateMemory; + // TODO(pjs): SelectedAnimationBlockHandle should be a property of animation_timeline_state + // unless its used elsewhere. Audit later gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; - ui_interface* Interface = &State->Interface; animation_system* AnimationSystem = &State->AnimationSystem; rect2 TitleBarBounds, PanelContentsBounds; - RectHSplitAtDistanceFromTop(PanelBounds, Interface->Style.RowHeight, &TitleBarBounds, &PanelContentsBounds); rect2 AnimationListBounds, TimelineBounds; + RectHSplitAtDistanceFromTop(PanelBounds, Interface->Style.RowHeight, &TitleBarBounds, &PanelContentsBounds); RectVSplitAtDistanceFromLeft(PanelContentsBounds, 300, &AnimationListBounds, &TimelineBounds); ui_FillRect(Interface, TitleBarBounds, Interface->Style.PanelBGColors[0]); @@ -589,13 +628,15 @@ AnimationTimeline_Render(panel Panel, rect2 PanelBounds, render_command_buffer* ui_StartRow(&TitleBarLayout, 3); { if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Pause"))) - { - State->AnimationSystem.TimelineShouldAdvance = true; - } - if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Play"))) { State->AnimationSystem.TimelineShouldAdvance = false; } + + if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Play"), (State->AnimationSystem.TimelineShouldAdvance ? PinkV4 : BlackV4), v4{.3f, .3f, .3f, 1.0f}, TealV4)) + { + State->AnimationSystem.TimelineShouldAdvance = true; + } + if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Stop"))) { State->AnimationSystem.TimelineShouldAdvance = false; diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index a7444b5..8da6b92 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -35,27 +35,47 @@ struct anim_layer blend_mode BlendMode; }; +struct anim_layer_array +{ + anim_layer* Values; + u32 Count; + u32 CountMax; +}; + struct animation { - anim_layer* Layers; - u32 LayersCount; - u32 LayersMax; - + anim_layer_array Layers; gs_list Blocks; frame_range PlayableRange; }; +struct animation_array +{ + animation* Values; + u32 Count; + u32 CountMax; +}; + +struct animation_frame +{ + // NOTE(pjs): These are all parallel arrays of equal length + animation_block* Blocks; + b8* BlocksFilled; + + u32 BlocksCountMax; + u32 BlocksCount; +}; + #define ANIMATION_SYSTEM_LAYERS_MAX 128 #define ANIMATION_SYSTEM_BLOCKS_MAX 128 struct animation_system { gs_memory_arena* Storage; + animation_array Animations; - gs_list Blocks; - anim_layer* Layers; - u32 LayersCount; - u32 LayersMax; + frame_range PlayableRange_; + gs_list Blocks_; // NOTE(Peter): The frame currently being displayed/processed. you // can see which frame you're on by looking at the time slider on the timeline @@ -65,10 +85,107 @@ struct animation_system r32 SecondsPerFrame; b32 TimelineShouldAdvance; - // Timeline - frame_range PlayableRange; }; +////////////////////////// +// +// Anim Layers Array + +internal anim_layer_array +AnimLayerArray_Create(gs_memory_arena* Storage, u32 CountMax) +{ + anim_layer_array Result = {0}; + Result.CountMax = CountMax; + Result.Values = PushArray(Storage, anim_layer, Result.CountMax); + return Result; +} + +internal u32 +AnimLayerArray_Push(anim_layer_array* Array, anim_layer Value) +{ + Assert(Array->Count < Array->CountMax); + u32 Index = Array->Count++; + Array->Values[Index] = Value; + return Index; +} + +internal u32 +AnimLayerArray_Remove(anim_layer_array* Array, u32 Index) +{ + Assert(Index < Array->Count); + for (u32 i = Index; i < Array->Count - 1; i++) + { + Array->Values[i] = Array->Values[i + 1]; + } +} + +////////////////////////// +// +// Animation Array + +internal animation_array +AnimationArray_Create(gs_memory_arena* Storage, u32 CountMax) +{ + animation_array Result = {0}; + Result.CountMax = CountMax; + Result.Values = PushArray(Storage, animation, Result.CountMax); + return Result; +} + +internal u32 +AnimationArray_Push(animation_array* Array, animation Value) +{ + Assert(Array->Count < Array->CountMax); + u32 Index = Array->Count++; + Array->Values[Index] = Value; + return Index; +} + +////////////////////////// +// +// Animation + +internal u32 +Animation_AddLayer(animation* Animation, anim_layer Layer) +{ + return AnimLayerArray_Push(&Animation->Layers, Layer); +} + +internal u32 +Animation_AddLayer (animation* Animation, gs_string Name, blend_mode BlendMode, animation_system* System) +{ + anim_layer NewLayer = {0}; + NewLayer.Name = PushStringF(System->Storage, 256, "%S", Name); + NewLayer.BlendMode = BlendMode; + + return Animation_AddLayer(Animation, NewLayer); +} + +internal void +Animation_RemoveLayer (animation* Animation, u32 LayerIndex) +{ + AnimLayerArray_Remove(&Animation->Layers, LayerIndex); + for (u32 i = Animation->Blocks.Used -= 1; i >= 0; i--) + { + gs_list_entry* Entry = Animation->Blocks.GetEntryAtIndex(i); + if (EntryIsFree(Entry)) { continue; } + + animation_block* Block = &Entry->Value; + if (Block->Layer > LayerIndex) + { + Block->Layer -= 1; + } + else if (Block->Layer == LayerIndex) + { + Animation->Blocks.FreeElementAtIndex(i); + } + } +} + +////////////////////////// +// +// + internal u32 SecondsToFrames(r32 Seconds, animation_system System) { @@ -77,7 +194,7 @@ SecondsToFrames(r32 Seconds, animation_system System) } inline b32 -FrameIsInRange(s32 Frame, frame_range Range) +FrameIsInRange(frame_range Range, s32 Frame) { b32 Result = (Frame >= Range.Min) && (Frame <= Range.Max); return Result; @@ -123,67 +240,64 @@ ClampFrameToRange(s32 Frame, frame_range Range) // Blocks internal gs_list_handle -AddAnimationBlock(u32 StartFrame, s32 EndFrame, u32 AnimationProcHandle, u32 Layer, animation_system* AnimationSystem) +Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, u32 AnimationProcHandle, u32 LayerIndex) { - gs_list_handle Result = {0}; + Assert(LayerIndex < Animation->Layers.Count); + animation_block NewBlock = {0}; NewBlock.Range.Min = StartFrame; NewBlock.Range.Max = EndFrame; NewBlock.AnimationProcHandle = AnimationProcHandle; - NewBlock.Layer = Layer; - Result = AnimationSystem->Blocks.PushElementOnList(NewBlock); + NewBlock.Layer = LayerIndex; + + gs_list_handle Result = Animation->Blocks.PushElementOnList(NewBlock); return Result; } internal void -RemoveAnimationBlock(gs_list_handle AnimationBlockHandle, animation_system* AnimationSystem) +Animation_RemoveBlock(animation* Animation, gs_list_handle AnimationBlockHandle) { Assert(ListHandleIsValid(AnimationBlockHandle)); - AnimationSystem->Blocks.FreeElementWithHandle(AnimationBlockHandle); + Animation->Blocks.FreeElementWithHandle(AnimationBlockHandle); } // Layers -internal u32 -AddLayer (gs_string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite) + +// System + +internal animation* +AnimationSystem_GetActiveAnimation(animation_system* System) { - // NOTE(Peter): If this assert fires its time to make the layer buffer system - // resizable. - Assert(AnimationSystem->LayersCount < AnimationSystem->LayersMax); + // TODO(pjs): need a way to specify the active animation + return System->Animations.Values + 0; +} + +internal animation_frame +AnimationSystem_CalculateAnimationFrame(animation_system* System, gs_memory_arena* Arena) +{ + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System); + + animation_frame Result = {0}; + Result.BlocksCountMax = ActiveAnim->Layers.Count; + Result.Blocks = PushArray(Arena, animation_block, Result.BlocksCountMax); + Result.BlocksFilled = PushArray(Arena, b8, Result.BlocksCountMax); + + for (u32 i = 0; i < ActiveAnim->Blocks.Used; i++) + { + gs_list_entry* BlockEntry = ActiveAnim->Blocks.GetEntryAtIndex(i); + if (EntryIsFree(BlockEntry)) { continue; } + + animation_block Block = BlockEntry->Value; + + if (FrameIsInRange(Block.Range, System->CurrentFrame)){ continue; } + + Result.BlocksFilled[Block.Layer] = true; + Result.Blocks[Block.Layer] = Block; + Result.BlocksCount++; + } - u32 Result = 0; - Result = AnimationSystem->LayersCount++; - anim_layer* NewLayer = AnimationSystem->Layers + Result; - *NewLayer = {0}; - NewLayer->Name = MakeString(PushArray(AnimationSystem->Storage, char, Name.Length), Name.Length); - PrintF(&NewLayer->Name, "%S", Name); - NewLayer->BlendMode = BlendMode; return Result; } -internal void -RemoveLayer (u32 LayerIndex, animation_system* AnimationSystem) -{ - Assert(LayerIndex < AnimationSystem->LayersMax); - Assert(LayerIndex < AnimationSystem->LayersCount); - for (u32 i = LayerIndex; i < AnimationSystem->LayersCount - 1; i++) - { - AnimationSystem->Layers[i] = AnimationSystem->Layers[i + 1]; - } - for (u32 i = AnimationSystem->Blocks.Used -= 1; i >= 0; i--) - { - gs_list_entry* Entry = AnimationSystem->Blocks.GetEntryAtIndex(i); - if (EntryIsFree(Entry)) { continue; } - animation_block* Block = &Entry->Value; - if (Block->Layer > LayerIndex) - { - Block->Layer -= 1; - } - else if (Block->Layer == LayerIndex) - { - AnimationSystem->Blocks.FreeElementAtIndex(i); - } - } - AnimationSystem->LayersCount -= 1; -} #define FOLDHAUS_ANIMATION #endif // FOLDHAUS_ANIMATION \ No newline at end of file diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index ed12a0a..e2b4756 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -136,16 +136,25 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Modes = OperationModeSystemInit(&State->Permanent, Context.ThreadContext); { // Animation PLAYGROUND + State->AnimationSystem = {}; State->AnimationSystem.Storage = &State->Permanent; + State->AnimationSystem.Animations = AnimationArray_Create(State->AnimationSystem.Storage, 32); + State->AnimationSystem.SecondsPerFrame = 1.f / 24.f; - State->AnimationSystem.PlayableRange.Min = 0; - State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem); - State->AnimationSystem.LayersMax = 32; - State->AnimationSystem.Layers = PushArray(&State->Permanent, anim_layer, State->AnimationSystem.LayersMax); - AddLayer(MakeString("Base Layer"), &State->AnimationSystem, BlendMode_Overwrite); - AddLayer(MakeString("Color Layer"), &State->AnimationSystem, BlendMode_Multiply); - AddLayer(MakeString("Sparkles"), &State->AnimationSystem, BlendMode_Add); + + animation Anim = {0}; + Anim.Layers.CountMax = 8; + Anim.Layers.Values = PushArray(State->AnimationSystem.Storage, anim_layer, Anim.Layers.CountMax); + Anim.PlayableRange.Min = 0; + Anim.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem); + Animation_AddLayer(&Anim, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem); + Animation_AddLayer(&Anim, MakeString("Color Layer"), BlendMode_Multiply, &State->AnimationSystem); + Animation_AddLayer(&Anim, MakeString("Sparkles"), BlendMode_Add, &State->AnimationSystem); + + AnimationArray_Push(&State->AnimationSystem.Animations, Anim); + + } // End Animation Playground @@ -230,14 +239,18 @@ UPDATE_AND_RENDER(UpdateAndRender) HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse, *Context); - if (State->AnimationSystem.TimelineShouldAdvance) { - // TODO(Peter): Revisit this. This implies that the framerate of the animation system - // is tied to the framerate of the simulation. That seems correct to me, but I'm not sure - State->AnimationSystem.CurrentFrame += 1; - // Loop back to the beginning - if (State->AnimationSystem.CurrentFrame > State->AnimationSystem.PlayableRange.Max) - { - State->AnimationSystem.CurrentFrame = 0; + { + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); + if (State->AnimationSystem.TimelineShouldAdvance) { + // TODO(Peter): Revisit this. This implies that the framerate of the animation system + // is tied to the framerate of the simulation. That seems correct to me, but I'm not sure + State->AnimationSystem.CurrentFrame += 1; + + // Loop back to the beginning + if (State->AnimationSystem.CurrentFrame > ActiveAnim->PlayableRange.Max) + { + State->AnimationSystem.CurrentFrame = 0; + } } } @@ -247,31 +260,18 @@ UPDATE_AND_RENDER(UpdateAndRender) State->AnimationSystem.LastUpdatedFrame = CurrentFrame; r32 FrameTime = CurrentFrame * State->AnimationSystem.SecondsPerFrame; - u32 CurrentBlocksMax = State->AnimationSystem.LayersCount; - b8* CurrentBlocksFilled = PushArray(State->Transient, b8, CurrentBlocksMax); - ZeroArray(CurrentBlocksFilled, b8, CurrentBlocksMax); - animation_block* CurrentBlocks = PushArray(State->Transient, animation_block, CurrentBlocksMax); + animation_frame CurrFrame = AnimationSystem_CalculateAnimationFrame(&State->AnimationSystem, State->Transient); - for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) - { - gs_list_entry* BlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i); - if (EntryIsFree(BlockEntry)) { continue; } - animation_block Block = BlockEntry->Value; - if (CurrentFrame < Block.Range.Min || CurrentFrame > Block.Range.Max) { continue; } - CurrentBlocksFilled[Block.Layer] = true; - CurrentBlocks[Block.Layer] = Block; - } - - led_buffer* LayerLEDBuffers = PushArray(State->Transient, led_buffer, CurrentBlocksMax); + led_buffer* LayerLEDBuffers = PushArray(State->Transient, led_buffer, CurrFrame.BlocksCountMax); for (u32 AssemblyIndex = 0; AssemblyIndex < State->Assemblies.Count; AssemblyIndex++) { assembly* Assembly = &State->Assemblies.Values[AssemblyIndex]; led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly->LedBufferIndex); - for (u32 Layer = 0; Layer < CurrentBlocksMax; Layer++) + for (u32 Layer = 0; Layer < CurrFrame.BlocksCountMax; Layer++) { - if (!CurrentBlocksFilled[Layer]) { continue; } - animation_block Block = CurrentBlocks[Layer]; + if (!CurrFrame.BlocksFilled[Layer]) { continue; } + animation_block Block = CurrFrame.Blocks[Layer]; // Prep Temp Buffer LayerLEDBuffers[Layer] = *AssemblyLedBuffer; @@ -287,11 +287,12 @@ UPDATE_AND_RENDER(UpdateAndRender) // Consolidate Temp Buffers // We do this in reverse order so that they go from top to bottom - for (u32 Layer = 0; Layer < CurrentBlocksMax; Layer++) + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); + for (u32 Layer = 0; Layer < CurrFrame.BlocksCountMax; Layer++) { - if (!CurrentBlocksFilled[Layer]) { continue; } + if (!CurrFrame.BlocksFilled[Layer]) { continue; } - switch (State->AnimationSystem.Layers[Layer].BlendMode) + switch (ActiveAnim->Layers.Values[Layer].BlendMode) { case BlendMode_Overwrite: { diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp index 4db796a..bbcb97a 100644 --- a/src/gs_libs/gs_types.cpp +++ b/src/gs_libs/gs_types.cpp @@ -743,6 +743,15 @@ internal rect2 MakeRect2MinDim(v2 Min, v2 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; +} + internal b32 ValueInRangeR32(r32 Min, r32 Max, r32 V) { return ((V >= Min) && (V <= Max)); @@ -2442,6 +2451,19 @@ FreeMemoryArena(gs_memory_arena* Arena) #define PushArray(arena, type, count) (type*)(PushSize_((arena), sizeof(type) * (count), FileNameAndLineNumberString).Memory) #define PushString(arena, length) MakeString(PushArray((arena), char, (length)), 0, (length)); +internal gs_string +PushStringF(gs_memory_arena* Arena, u32 MaxLength, char* Format, ...) +{ + gs_string Result = PushString(Arena, MaxLength); + + va_list Args; + va_start(Args, Format); + PrintFArgsList(&Result, Format, Args); + va_end(Args); + + return Result; +} + internal void ClearArena(gs_memory_arena* Arena) { From 1940483620ee7c9c2a148fe46371272870017fe7 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 10 Oct 2020 00:10:51 -0700 Subject: [PATCH 32/43] Wrote a file serializer and parser for animations --- .../foldhaus_panel_animation_timeline.h | 14 - src/app/engine/animation/foldhaus_animation.h | 70 ++++ .../animation/foldhaus_animation_parser.cpp | 10 + .../foldhaus_animation_serializer.cpp | 179 ++++++++ src/app/engine/foldhaus_parser.h | 18 + src/app/engine/foldhaus_serializer.h | 384 ++++++++++++++++++ src/app/foldhaus_app.cpp | 6 +- src/app/foldhaus_app.h | 10 + 8 files changed, 675 insertions(+), 16 deletions(-) create mode 100644 src/app/engine/animation/foldhaus_animation_parser.cpp create mode 100644 src/app/engine/foldhaus_parser.h create mode 100644 src/app/engine/foldhaus_serializer.h diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 3c2140b..016ff00 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -577,20 +577,6 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta return Result; } -struct animation_clip -{ - char* Name; - s32 NameLength; - animation_proc* Proc; -}; - -s32 GlobalAnimationClipsCount = 3; -animation_clip GlobalAnimationClips[] = { - { "Test Pattern One", 16, TestPatternOne }, - { "Test Pattern Two", 16, TestPatternTwo }, - { "Test Pattern Three", 18, TestPatternThree }, -}; - internal void DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayerHandle, animation_system* AnimationSystem) { diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 8da6b92..840f314 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -29,6 +29,13 @@ enum blend_mode BlendMode_Count, }; +global gs_const_string BlendModeStrings[] = { + ConstString("Overwrite"), + ConstString("Add"), + ConstString("Multiply"), + ConstString("Count"), +}; + struct anim_layer { gs_string Name; @@ -44,6 +51,8 @@ struct anim_layer_array struct animation { + gs_string Name; + anim_layer_array Layers; gs_list Blocks; @@ -87,6 +96,67 @@ struct animation_system }; +// TODO(pjs): Better name - something like animation_prototype +struct animation_clip +{ + char* Name; + s32 NameLength; + animation_proc* Proc; +}; + +// Serialization + +enum animation_field +{ + AnimField_FileIdent, + AnimField_AnimName, + AnimField_LayersCount, + AnimField_BlocksCount, + + AnimField_PlayableRange, + AnimField_PlayableRangeMin, + AnimField_PlayableRangeMax, + + AnimField_LayersArray, + AnimField_Layer, + AnimField_LayerName, + AnimField_LayerBlendMode, + + AnimField_BlocksArray, + AnimField_Block, + AnimField_BlockFrameRange, + AnimField_BlockFrameRangeMin, + AnimField_BlockFrameRangeMax, + AnimField_BlockLayerIndex, + AnimField_BlockAnimName, + + AnimField_Count, +}; + +global gs_const_string AnimationFieldStrings[] = { + ConstString("lumenarium_animation_file"), // AnimField_FileIdent + ConstString("animation_name"),// AnimField_AnimName + ConstString("layers_count"),// AnimField_LayersCount + ConstString("blocks_count"),// AnimField_BlocksCount + + ConstString("playable_range"),// AnimField_PlayableRange + ConstString("min"),// AnimField_PlayableRangeMin + ConstString("max"),// AnimField_PlayableRangeMax + + ConstString("layers"),// AnimField_LayersArray + ConstString("layer"),// AnimField_Layer + ConstString("name"),// AnimField_LayerName + ConstString("blend"),// AnimField_LayerBlendMode + + ConstString("blocks"),// AnimField_BlocksArray + ConstString("block"),// AnimField_Block + ConstString("frame_range"),// AnimField_BlockFrameRange + ConstString("min"),// AnimField_BlockFrameRangeMin + ConstString("max"),// AnimField_BlockFrameRangeMax + ConstString("layer_index"),// AnimField_BlockLayerIndex + ConstString("animation_name"),// AnimField_BlockAnimName +}; + ////////////////////////// // // Anim Layers Array diff --git a/src/app/engine/animation/foldhaus_animation_parser.cpp b/src/app/engine/animation/foldhaus_animation_parser.cpp new file mode 100644 index 0000000..16233e6 --- /dev/null +++ b/src/app/engine/animation/foldhaus_animation_parser.cpp @@ -0,0 +1,10 @@ +// +// File: foldhaus_animation_parser.cpp +// Author: Peter Slattery +// Creation Date: 2020-10-09 +// +#ifndef FOLDHAUS_ANIMATION_PARSER_CPP + + +#define FOLDHAUS_ANIMATION_PARSER_CPP +#endif // FOLDHAUS_ANIMATION_PARSER_CPP \ No newline at end of file diff --git a/src/app/engine/animation/foldhaus_animation_serializer.cpp b/src/app/engine/animation/foldhaus_animation_serializer.cpp index 481b248..d66f3ee 100644 --- a/src/app/engine/animation/foldhaus_animation_serializer.cpp +++ b/src/app/engine/animation/foldhaus_animation_serializer.cpp @@ -5,6 +5,185 @@ // #ifndef FOLDHAUS_ANIMATION_SERIALIZER_CPP +internal gs_string +AnimSerializer_Serialize(animation Anim, animation_clip* GlobalClips, gs_memory_arena* Arena) +{ + serializer Serializer = {0}; + Serializer.String = PushString(Arena, 4096); + Serializer.Identifiers = AnimationFieldStrings; + Serializer.IdentifiersCount = AnimField_Count; + + Serializer_WriteF(&Serializer, "%S;\n", AnimationFieldStrings[AnimField_FileIdent]); + Serializer_WriteStringValue(&Serializer, AnimField_AnimName, Anim.Name.ConstString); + Serializer_WriteValue(&Serializer, AnimField_LayersCount, Anim.Layers.Count); + Serializer_WriteValue(&Serializer, AnimField_BlocksCount, Anim.Blocks.Used); + + Serializer_OpenStruct(&Serializer, AnimField_PlayableRange); + { + Serializer_WriteValue(&Serializer, AnimField_PlayableRangeMin, (u32)Anim.PlayableRange.Min); + Serializer_WriteValue(&Serializer, AnimField_PlayableRangeMax, (u32)Anim.PlayableRange.Max); + } + Serializer_CloseStruct(&Serializer); + + Serializer_OpenStruct(&Serializer, AnimField_LayersArray); + for (u32 i = 0; i < Anim.Layers.Count; i++) + { + anim_layer LayerAt = Anim.Layers.Values[i]; + Serializer_OpenStruct(&Serializer, AnimField_Layer); + { + Serializer_WriteStringValue(&Serializer, AnimField_LayerName, LayerAt.Name.ConstString); + Serializer_WriteStringValue(&Serializer, AnimField_LayerBlendMode, BlendModeStrings[LayerAt.BlendMode]); + } + Serializer_CloseStruct(&Serializer); + } + Serializer_CloseStruct(&Serializer); + + + Serializer_OpenStruct(&Serializer, AnimField_BlocksArray); + for (u32 i = 0; i < Anim.Blocks.Used; i++) + { + gs_list_entry* AnimationBlockEntry = Anim.Blocks.GetEntryAtIndex(i); + if (EntryIsFree(AnimationBlockEntry)) { continue; } + gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle; + animation_block AnimationBlockAt = AnimationBlockEntry->Value; + + // TODO(pjs): Systematize the AnimationProcHandle + // :AnimProcHandle + u32 AnimationProcIndex = AnimationBlockAt.AnimationProcHandle - 1; + animation_clip Animation = GlobalClips[AnimationProcIndex]; + + Serializer_OpenStruct(&Serializer, AnimField_Block); + { + Serializer_OpenStruct(&Serializer, AnimField_BlockFrameRange); + { + Serializer_WriteValue(&Serializer, AnimField_BlockFrameRangeMin, (u32)AnimationBlockAt.Range.Min); + Serializer_WriteValue(&Serializer, AnimField_BlockFrameRangeMax, (u32)AnimationBlockAt.Range.Max); + } + Serializer_CloseStruct(&Serializer); + + Serializer_WriteValue(&Serializer, AnimField_BlockLayerIndex, AnimationBlockAt.Layer); + Serializer_WriteStringValue(&Serializer, AnimField_BlockAnimName, ConstString(Animation.Name)); + } + Serializer_CloseStruct(&Serializer); + } + Serializer_CloseStruct(&Serializer); + + return Serializer.String; +} + +internal animation +AnimParser_Parse(gs_string File, animation_clip* GlobalClips, gs_memory_arena* Arena, u32 AnimClipsCount, animation_clip* AnimClips) +{ + animation Result = {0}; + + parser Parser = {0}; + Parser.String = File; + Parser.At = Parser.String.Str; + Parser.Identifiers = AnimationFieldStrings; + Parser.IdentifiersCount = AnimField_Count; + Parser.Arena = Arena; + + if (Parser_ReadString(&Parser, AnimationFieldStrings[AnimField_FileIdent])) + { + Result.Name = Parser_ReadStringValue(&Parser, AnimField_AnimName); + + Result.Layers.CountMax = Parser_ReadU32Value(&Parser, AnimField_LayersCount); + Result.Layers.Values = PushArray(Arena, anim_layer, Result.Layers.CountMax); + + // TODO(pjs): We're not using this now because Blocks are built on gs_list or something, + // but I want to replace that eventually, so this is here to preallocate the blocks we need + u32 BlocksCount = Parser_ReadU32Value(&Parser, AnimField_BlocksCount); + + if (Parser_ReadOpenStruct(&Parser, AnimField_PlayableRange)) + { + Result.PlayableRange.Min = Parser_ReadU32Value(&Parser, AnimField_PlayableRangeMin); + Result.PlayableRange.Max = Parser_ReadU32Value(&Parser, AnimField_PlayableRangeMax); + } + else + { + // TODO(pjs): Error + } + + if (Parser_ReadOpenStruct(&Parser, AnimField_LayersArray)) + { + while (!Parser_ReadCloseStruct(&Parser)) + { + anim_layer Layer = {0}; + if (Parser_ReadOpenStruct(&Parser, AnimField_Layer)) + { + Layer.Name = Parser_ReadStringValue(&Parser, AnimField_LayerName); + + gs_string BlendModeName = Parser_ReadStringValue(&Parser, AnimField_LayerBlendMode); + for (u32 i = 0; i < BlendMode_Count; i++) + { + if (StringsEqual(BlendModeName.ConstString, BlendModeStrings[i])) + { + Layer.BlendMode = (blend_mode)i; + break; + } + } + + if (Parser_ReadCloseStruct(&Parser)) + { + Animation_AddLayer(&Result, Layer); + } + else + { + // TODO(pjs): Error + } + } + } + } + + if (Parser_ReadOpenStruct(&Parser, AnimField_BlocksArray)) + { + while(!Parser_ReadCloseStruct(&Parser)) + { + animation_block Block = {0}; + + if (Parser_ReadOpenStruct(&Parser, AnimField_Block)) + { + if (Parser_ReadOpenStruct(&Parser, AnimField_BlockFrameRange)) + { + Block.Range.Min = Parser_ReadU32Value(&Parser, AnimField_BlockFrameRangeMin); + Block.Range.Max = Parser_ReadU32Value(&Parser, AnimField_BlockFrameRangeMax); + + Parser_ReadCloseStruct(&Parser); + } + else + { + // TODO(pjs): Error + } + + Block.Layer = Parser_ReadU32Value(&Parser, AnimField_BlockLayerIndex); + + // TODO(pjs): AnimName -> Animation Proc Handle + gs_string AnimName = Parser_ReadStringValue(&Parser, AnimField_BlockAnimName); + Block.AnimationProcHandle = 0; + for (u32 i = 0; i < AnimClipsCount; i++) + { + if (StringEqualsCharArray(AnimName.ConstString, AnimClips[i].Name, CStringLength(AnimClips[i].Name))) + { + Block.AnimationProcHandle = i + 1; + break; + } + } + + if (Parser_ReadCloseStruct(&Parser)) + { + Result.Blocks.PushElementOnList(Block); + } + else + { + // TODO(pjs): Error + } + } + } + } + } + + return Result; +} #define FOLDHAUS_ANIMATION_SERIALIZER_CPP #endif // FOLDHAUS_ANIMATION_SERIALIZER_CPP \ No newline at end of file diff --git a/src/app/engine/foldhaus_parser.h b/src/app/engine/foldhaus_parser.h new file mode 100644 index 0000000..709f375 --- /dev/null +++ b/src/app/engine/foldhaus_parser.h @@ -0,0 +1,18 @@ +// +// File: foldhaus_parser.h +// Author: Peter Slattery +// Creation Date: 2020-10-09 +// +#ifndef FOLDHAUS_PARSER_H + +struct parser +{ + gs_string String; + gs_const_string* Identifiers; + u32 IdentifiersCount; +}; + + + +#define FOLDHAUS_PARSER_H +#endif // FOLDHAUS_PARSER_H \ No newline at end of file diff --git a/src/app/engine/foldhaus_serializer.h b/src/app/engine/foldhaus_serializer.h new file mode 100644 index 0000000..b82ee62 --- /dev/null +++ b/src/app/engine/foldhaus_serializer.h @@ -0,0 +1,384 @@ +// +// File: foldhaus_serializer.h +// Author: Peter Slattery +// Creation Date: 2020-10-09 +// +#ifndef FOLDHAUS_SERIALIZER_H + +struct serializer +{ + gs_string String; + u32 Indent; + gs_const_string* Identifiers; + u32 IdentifiersCount; +}; + +internal gs_const_string +Serializer_GetIdent(serializer* Serializer, u32 Index) +{ + gs_const_string Result = Serializer->Identifiers[Index]; + return Result; +} + +// Serializing + +internal void +Serializer_WriteIndent(serializer* Serializer) +{ + for (u32 i = 0; i < Serializer->Indent; i++) + { + AppendPrintF(&Serializer->String, " "); + } +} + +internal void +Serializer_WriteF(serializer* Serializer, char* Format, ...) +{ + Serializer_WriteIndent(Serializer); + + va_list Args; + va_start(Args, Format); + PrintFArgsList(&Serializer->String, Format, Args); + va_end(Args); +} + +internal void +Serializer_OpenStruct(serializer* Serializer, gs_const_string StructName) +{ + Serializer_WriteF(Serializer, "%S:{\n", StructName); + Serializer->Indent++; +} + +internal void +Serializer_OpenStruct(serializer* Serializer, u32 StructIdentifier) +{ + gs_const_string Ident = Serializer_GetIdent(Serializer, StructIdentifier); + Serializer_WriteF(Serializer, "%S:{\n", Ident); + Serializer->Indent++; +} + +internal void +Serializer_CloseStruct(serializer* Serializer) +{ + Serializer->Indent--; + Serializer_WriteF(Serializer, "};\n"); +} + +internal void +Serializer_WriteValue(serializer* Serializer, gs_const_string Ident, gs_const_string Value) +{ + Serializer_WriteF(Serializer, "%S: %S;\n", Ident, Value); +} + +internal void +Serializer_WriteValue(serializer* Serializer, u32 IdentIndex, gs_const_string Value) +{ + gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex); + Serializer_WriteValue(Serializer, Ident, Value); +} + +internal void +Serializer_WriteValue(serializer* Serializer, gs_const_string Ident, u32 Value) +{ + Serializer_WriteF(Serializer, "%S: %d;\n", Ident, Value); +} + +internal void +Serializer_WriteValue(serializer* Serializer, u32 IdentIndex, u32 Value) +{ + gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex); + Serializer_WriteValue(Serializer, Ident, Value); +} + +internal void +Serializer_WriteValue(serializer* Serializer, gs_const_string Ident, r32 Value) +{ + Serializer_WriteF(Serializer, "%S: %f;\n", Ident, Value); +} + +internal void +Serializer_WriteValue(serializer* Serializer, u32 IdentIndex, r32 Value) +{ + gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex); + Serializer_WriteValue(Serializer, Ident, Value); +} + +internal void +Serializer_WriteStringValue(serializer* Serializer, gs_const_string Ident, gs_const_string Value) +{ + Serializer_WriteF(Serializer, "%S: \"%S\";\n", Ident, Value); +} + +internal void +Serializer_WriteStringValue(serializer* Serializer, u32 IdentIndex, gs_const_string Value) +{ + gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex); + Serializer_WriteStringValue(Serializer, Ident, Value); +} + +internal void +Serializer_WriteV3Value(serializer* Serializer, gs_const_string Ident, v3 Value) +{ + Serializer_WriteF(Serializer, "%S: (%f, %f, %f);\n", Ident, Value.x, Value.y, Value.z); +} + +internal void +Serializer_WriteV3Value(serializer* Serializer, u32 IdentIndex, v3 Value) +{ + gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex); + Serializer_WriteV3Value(Serializer, Ident, Value); +} + +// Parsing + +struct parser +{ + gs_string String; + + gs_const_string* Identifiers; + u32 IdentifiersCount; + + u32 Line; + + char* LineStart; + char* At; + + gs_memory_arena* Arena; +}; + +internal gs_const_string +Parser_GetIdent(parser Parser, u32 Index) +{ + gs_const_string Result = Parser.Identifiers[Index]; + return Result; +} + +internal bool +Parser_AtValidPosition(parser Parser) +{ + u64 Offset = Parser.At - Parser.String.Str; + bool Result = (Offset < Parser.String.Length); + return Result; +} + +internal void +Parser_AdvanceChar(parser* P) +{ + if (IsNewline(P->At[0])) + { + P->Line += 1; + P->LineStart = P->At + 1; + } + P->At++; +} + +internal void +Parser_EatWhitespace(parser* P) +{ + while(Parser_AtValidPosition(*P) && IsNewlineOrWhitespace(P->At[0])) + { + Parser_AdvanceChar(P); + } +} + +internal void +Parser_EatToNewLine(parser* P) +{ + while(Parser_AtValidPosition(*P) && !IsNewline(P->At[0])) + { + Parser_AdvanceChar(P); + } + Parser_EatWhitespace(P); +} + +internal bool +Parser_AdvanceIfTokenEquals(parser* P, gs_const_string Value) +{ + bool Result = true; + + char* PAt = P->At; + char* VAt = Value.Str; + while (*VAt != 0) + { + if (*PAt != *VAt) + { + Result = false; + break; + } + PAt += 1; + VAt += 1; + } + + // TODO(Peter): What if the token is a subset of Value? ie. this would return true for + // T->At = hello_world and Value = hello_ + // But the next token we read would fail + + if (Result) + { + P->At = PAt; + Parser_EatWhitespace(P); + } + return Result; +} + +internal bool +Parser_AdvanceIfLineEnd(parser* P) +{ + bool Result = Parser_AdvanceIfTokenEquals(P, ConstString(";")); + return Result; +} + +internal bool +Parser_ReadString(parser* P, gs_const_string String) +{ + // string; + bool Result = Parser_AdvanceIfTokenEquals(P, String); + Result &= Parser_AdvanceIfLineEnd(P); + return Result; +} + +internal bool +Parser_ReadString(parser* P, u32 IdentIndex) +{ + gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); + return Parser_ReadString(P, Ident); +} + +internal gs_string +Parser_ReadStringValue(parser* P, gs_const_string Ident) +{ + // ident: "value"; + gs_string Result = {}; + if (Parser_AdvanceIfTokenEquals(P, Ident) && + Parser_AdvanceIfTokenEquals(P, ConstString(":")) && + Parser_AdvanceIfTokenEquals(P, ConstString("\""))) + { + gs_const_string FileString = {0}; + FileString.Str = P->At; + + while (Parser_AtValidPosition(*P) && P->At[0] != '"') + { + Parser_AdvanceChar(P); + } + + FileString.Length = P->At - FileString.Str; + if (Parser_AdvanceIfTokenEquals(P, ConstString("\"")) && + Parser_AdvanceIfLineEnd(P)) + { + Result = PushStringF(P->Arena, FileString.Length, "%S", FileString); + } + else + { + // TODO(pjs): Error + } + } + + return Result; +} + +internal gs_string +Parser_ReadStringValue(parser* P, u32 IdentIndex) +{ + gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); + return Parser_ReadStringValue(P, Ident); +} + +internal bool +Parser_ReadOpenStruct(parser* P, gs_const_string Ident) +{ + // ident: { + bool Result = Parser_AdvanceIfTokenEquals(P, Ident); + Result &= Parser_AdvanceIfTokenEquals(P, ConstString(":")); + Result &= Parser_AdvanceIfTokenEquals(P, ConstString("{")); + return Result; +} + +internal bool +Parser_ReadOpenStruct(parser* P, u32 IdentIndex) +{ + gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); + return Parser_ReadOpenStruct(P, Ident); +} + +internal bool +Parser_ReadCloseStruct(parser* P) +{ + // } + bool Result = Parser_AdvanceIfTokenEquals(P, ConstString("}")); + Result &= Parser_AdvanceIfLineEnd(P); + return Result; +} + +internal gs_const_string +Parser_ReadNumberString(parser* P) +{ + gs_const_string Result = {}; + Result.Str = P->At; + while(Parser_AtValidPosition(*P) && IsNumericExtended(P->At[0])) + { + Parser_AdvanceChar(P); + } + Result.Length = P->At - Result.Str; + return Result; +} + +internal u32 +Parser_ReadU32Value(parser* P, gs_const_string Ident) +{ + // ident: value; + u32 Result = 0; + if (Parser_AdvanceIfTokenEquals(P, Ident) && + Parser_AdvanceIfTokenEquals(P, ConstString(":"))) + { + gs_const_string NumStr = Parser_ReadNumberString(P); + if (Parser_AdvanceIfLineEnd(P)) + { + Result = (u32)ParseInt(NumStr); + } + else + { + // TODO(pjs): Error + } + } + + return Result; +} + +internal u32 +Parser_ReadU32Value(parser* P, u32 IdentIndex) +{ + gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); + return Parser_ReadU32Value(P, Ident); +} + +internal r32 +Parser_ReadR32Value(parser* P, gs_const_string Ident) +{ + // ident: value; + r32 Result = 0; + if (Parser_AdvanceIfTokenEquals(P, Ident) && + Parser_AdvanceIfTokenEquals(P, ConstString(":"))) + { + gs_const_string NumStr = Parser_ReadNumberString(P); + if (Parser_AdvanceIfLineEnd(P)) + { + Result = (r32)ParseFloat(NumStr); + } + else + { + // TODO(pjs): Error + } + } + return Result; +} + +internal u32 +Parser_ReadR32Value(parser* P, u32 IdentIndex) +{ + gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); + return Parser_ReadR32Value(P, Ident); +} + + +#define FOLDHAUS_SERIALIZER_H +#endif // FOLDHAUS_SERIALIZER_H \ No newline at end of file diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index e2b4756..7dd6042 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -144,6 +144,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->AnimationSystem.SecondsPerFrame = 1.f / 24.f; animation Anim = {0}; + Anim.Name = PushStringF(&State->Permanent, 256, "test_anim_one"); Anim.Layers.CountMax = 8; Anim.Layers.Values = PushArray(State->AnimationSystem.Storage, anim_layer, Anim.Layers.CountMax); Anim.PlayableRange.Min = 0; @@ -152,9 +153,9 @@ INITIALIZE_APPLICATION(InitializeApplication) Animation_AddLayer(&Anim, MakeString("Color Layer"), BlendMode_Multiply, &State->AnimationSystem); Animation_AddLayer(&Anim, MakeString("Sparkles"), BlendMode_Add, &State->AnimationSystem); + Animation_AddBlock(&Anim, 22, 123, 2, 1); + AnimationArray_Push(&State->AnimationSystem.Animations, Anim); - - } // End Animation Playground @@ -280,6 +281,7 @@ UPDATE_AND_RENDER(UpdateAndRender) u32 FramesIntoBlock = CurrentFrame - Block.Range.Min; r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame; + // :AnimProcHandle u32 AnimationProcIndex = Block.AnimationProcHandle - 1; animation_proc* AnimationProc = GlobalAnimationClips[AnimationProcIndex].Proc; AnimationProc(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, State->Transient); diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 51938b4..1675b20 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -8,6 +8,8 @@ #include "../meta/gs_meta_include.h" #include "../meta/gs_meta_lexer.h" +#include "engine/foldhaus_serializer.h" + #include "../gs_libs/gs_font.h" #include "foldhaus_log.h" @@ -32,6 +34,7 @@ typedef struct app_state app_state; #include "editor/foldhaus_operation_mode.h" #include "engine/animation/foldhaus_animation.h" +#include "engine/animation/foldhaus_animation_serializer.cpp" struct app_state { @@ -226,6 +229,13 @@ struct panel_definition s32 InputCommandsCount; }; +s32 GlobalAnimationClipsCount = 3; +animation_clip GlobalAnimationClips[] = { + { "Test Pattern One", 16, TestPatternOne }, + { "Test Pattern Two", 16, TestPatternTwo }, + { "Test Pattern Three", 18, TestPatternThree }, +}; + #include "editor/panels/foldhaus_panel_sculpture_view.h" #include "editor/panels/foldhaus_panel_profiler.h" #include "editor/panels/foldhaus_panel_dmx_view.h" From 55284cde25f49d039b0d18354ea6d1ee27be3f49 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 10 Oct 2020 16:52:00 -0700 Subject: [PATCH 33/43] Created serial_monitor, and debugged uart functionality. It is now working --- build/build_app_msvc_win32_debug.bat | 2 + .../deprecated/foldhaus_panel_node_graph.h | 6 +- src/app/editor/foldhaus_panel.h | 38 ++- .../foldhaus_panel_animation_timeline.h | 2 +- src/app/engine/animation/foldhaus_animation.h | 3 - .../animation/foldhaus_animation_parser.cpp | 10 - src/app/engine/foldhaus_assembly.cpp | 7 - src/app/engine/foldhaus_assembly.h | 9 +- src/app/engine/uart/foldhaus_uart.cpp | 95 ++++++++ src/app/engine/uart/foldhaus_uart.h | 112 ++------- src/app/foldhaus_app.cpp | 5 +- src/app/foldhaus_app.h | 1 + src/app/platform_win32/win32_foldhaus.cpp | 28 +++ .../platform_win32/win32_foldhaus_serial.h | 31 +++ src/serial_monitor/first.cpp | 221 ++++++++++++++++++ 15 files changed, 422 insertions(+), 148 deletions(-) delete mode 100644 src/app/engine/animation/foldhaus_animation_parser.cpp create mode 100644 src/app/engine/uart/foldhaus_uart.cpp create mode 100644 src/serial_monitor/first.cpp diff --git a/build/build_app_msvc_win32_debug.bat b/build/build_app_msvc_win32_debug.bat index 1a4c884..a60ed6c 100644 --- a/build/build_app_msvc_win32_debug.bat +++ b/build/build_app_msvc_win32_debug.bat @@ -27,6 +27,8 @@ del lock.tmp cl %CommonCompilerFlags% %SourceCodePath%\platform_win32\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib +cl %CommonCompilerFlags% %ProjectDevPath%\src\serial_monitor\first.cpp /Feserial_monitor.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib + popd call %MyPath%\_postbuild_win32.bat \ No newline at end of file diff --git a/src/app/deprecated/foldhaus_panel_node_graph.h b/src/app/deprecated/foldhaus_panel_node_graph.h index 6830d2f..fceb052 100644 --- a/src/app/deprecated/foldhaus_panel_node_graph.h +++ b/src/app/deprecated/foldhaus_panel_node_graph.h @@ -111,7 +111,7 @@ OPERATION_STATE_DEF(connect_nodes_operation_state) OPERATION_RENDER_PROC(UpdateConnectNodeOperation) { - panel_and_bounds NodeGraphPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds); + panel_with_layout NodeGraphPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds); node_graph_state* GraphState = (node_graph_state*)NodeGraphPanel.Panel->PanelStateMemory; GraphState->Layout.InProgressConnectionEnd = Mouse.Pos; @@ -121,7 +121,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndConnectNodesOperation) { connect_nodes_operation_state* OpState = GetCurrentOperationState(State->Modes, connect_nodes_operation_state); - panel_and_bounds NodeGraphPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds); + panel_with_layout NodeGraphPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds); node_graph_state* GraphState = (node_graph_state*)NodeGraphPanel.Panel->PanelStateMemory; GraphState->Layout.ConnectionIsInProgress = false; @@ -157,7 +157,7 @@ BeginConnectNodesOperation(visual_port VisualPort, u32 VisualPortIndex, mouse_st OpState->VisualPort = VisualPort; OpState->VisualPortIndex = VisualPortIndex; - panel_and_bounds NodeGraphPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds); + panel_with_layout NodeGraphPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds); node_graph_state* GraphState = (node_graph_state*)NodeGraphPanel.Panel->PanelStateMemory; GraphState->Layout.ConnectionIsInProgress = true; diff --git a/src/app/editor/foldhaus_panel.h b/src/app/editor/foldhaus_panel.h index 53415f1..c1a2248 100644 --- a/src/app/editor/foldhaus_panel.h +++ b/src/app/editor/foldhaus_panel.h @@ -24,6 +24,8 @@ typedef struct panel_entry panel_entry; struct panel { + // TODO(pjs): We want this to be a list, so that you can push sub panels on + // and let them return to you, to perform certain tasks, like loading a file s32 PanelDefinitionIndex; panel_split_direction SplitDirection; @@ -154,11 +156,11 @@ FreePanelAtIndex(s32 Index, panel_system* PanelSystem) } internal void -SplitPanelVertically(panel* Parent, r32 Percent, panel_system* PanelSystem) +SplitPanel(panel* Parent, r32 Percent, panel_split_direction SplitDirection, panel_system* PanelSystem) { if (Percent >= 0.0f && Percent <= 1.0f) { - Parent->SplitDirection = PanelSplit_Vertical; + Parent->SplitDirection = SplitDirection; Parent->SplitPercent = Percent; Parent->Left = TakeNewPanelEntry(PanelSystem); @@ -169,20 +171,16 @@ SplitPanelVertically(panel* Parent, r32 Percent, panel_system* PanelSystem) } } +internal void +SplitPanelVertically(panel* Parent, r32 Percent, panel_system* PanelSystem) +{ + SplitPanel(Parent, Percent, PanelSplit_Vertical, PanelSystem); +} + internal void SplitPanelHorizontally(panel* Parent, r32 Percent, panel_system* PanelSystem) { - if (Percent >= 0.0f && Percent <= 1.0f) - { - Parent->SplitDirection = PanelSplit_Horizontal; - Parent->SplitPercent = Percent; - - Parent->Bottom = TakeNewPanelEntry(PanelSystem); - Parent->Bottom->Panel.PanelDefinitionIndex = Parent->PanelDefinitionIndex; - - Parent->Top = TakeNewPanelEntry(PanelSystem); - Parent->Top->Panel.PanelDefinitionIndex = Parent->PanelDefinitionIndex; - } + SplitPanel(Parent, Percent, PanelSplit_Horizontal, PanelSystem); } internal void @@ -290,16 +288,10 @@ GetPanelLayout(panel_system* System, rect2 WindowBounds, gs_memory_arena* Storag return Result; } -struct panel_and_bounds -{ - panel* Panel; - rect2 Bounds; -}; - -internal panel_and_bounds +internal panel_with_layout GetPanelContainingPoint(v2 Point, panel* Panel, rect2 PanelBounds) { - panel_and_bounds Result = {0}; + panel_with_layout Result = {0}; if (Panel->SplitDirection == PanelSplit_NoSplit) { @@ -338,10 +330,10 @@ GetPanelContainingPoint(v2 Point, panel* Panel, rect2 PanelBounds) return Result; } -internal panel_and_bounds +internal panel_with_layout GetPanelContainingPoint(v2 Point, panel_system* PanelSystem, rect2 WindowBounds) { - panel_and_bounds Result = {0}; + panel_with_layout Result = {0}; if (PanelSystem->PanelsUsed > 0) { Result = GetPanelContainingPoint(Point, &PanelSystem->Panels[0].Panel, WindowBounds); diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 016ff00..6f4f5cf 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -265,7 +265,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand) { animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); - panel_and_bounds ActivePanel = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, State->WindowBounds); + panel_with_layout ActivePanel = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, State->WindowBounds); frame_range Range = ActiveAnim->PlayableRange; u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel.Bounds, Range); diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 840f314..00d4278 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -83,9 +83,6 @@ struct animation_system gs_memory_arena* Storage; animation_array Animations; - frame_range PlayableRange_; - gs_list Blocks_; - // NOTE(Peter): The frame currently being displayed/processed. you // can see which frame you're on by looking at the time slider on the timeline // panel diff --git a/src/app/engine/animation/foldhaus_animation_parser.cpp b/src/app/engine/animation/foldhaus_animation_parser.cpp deleted file mode 100644 index 16233e6..0000000 --- a/src/app/engine/animation/foldhaus_animation_parser.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// -// File: foldhaus_animation_parser.cpp -// Author: Peter Slattery -// Creation Date: 2020-10-09 -// -#ifndef FOLDHAUS_ANIMATION_PARSER_CPP - - -#define FOLDHAUS_ANIMATION_PARSER_CPP -#endif // FOLDHAUS_ANIMATION_PARSER_CPP \ No newline at end of file diff --git a/src/app/engine/foldhaus_assembly.cpp b/src/app/engine/foldhaus_assembly.cpp index 5be7342..fce8922 100644 --- a/src/app/engine/foldhaus_assembly.cpp +++ b/src/app/engine/foldhaus_assembly.cpp @@ -128,13 +128,6 @@ LedSystemFreeBuffer(led_system* System, u32 BufferIndex) *Buffer = {}; } -internal led_buffer* -LedSystemGetBuffer(led_system* System, u32 Index) -{ - led_buffer* Result = &System->Buffers[Index]; - return Result; -} - internal void LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) { diff --git a/src/app/engine/foldhaus_assembly.h b/src/app/engine/foldhaus_assembly.h index 55185e3..aa422f3 100644 --- a/src/app/engine/foldhaus_assembly.h +++ b/src/app/engine/foldhaus_assembly.h @@ -112,7 +112,14 @@ struct assembly_array assembly* Values; }; -internal led_buffer* LedSystemGetBuffer(led_system* System, u32 Index); + +internal led_buffer* +LedSystemGetBuffer(led_system* System, u32 Index) +{ + led_buffer* Result = &System->Buffers[Index]; + return Result; +} + #define FOLDHAUS_ASSEMBLY_H #endif // FOLDHAUS_ASSEMBLY_H \ No newline at end of file diff --git a/src/app/engine/uart/foldhaus_uart.cpp b/src/app/engine/uart/foldhaus_uart.cpp new file mode 100644 index 0000000..1e7f635 --- /dev/null +++ b/src/app/engine/uart/foldhaus_uart.cpp @@ -0,0 +1,95 @@ +// +// File: foldhaus_uart.cpp +// Author: Peter Slattery +// Creation Date: 2020-10-10 +// +#ifndef FOLDHAUS_UART_CPP + + +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); + + uart_header* Header = PushStructOnCursor(WriteCursor, uart_header); + UART_FillHeader(Header, Strip.UARTAddr.Channel, UART_SET_CHANNEL_WS2812); + + 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 + OutputPixel[0] = Color.R; + OutputPixel[1] = Color.G; + OutputPixel[2] = Color.B; + + 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); +} + +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); +} + +internal void +UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem) +{ + 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 = sizeof(uart_header) + sizeof(uart_channel) + sizeof(uart_footer); + + for (u32 AssemblyIdx = 0; AssemblyIdx < Assemblies.Count; AssemblyIdx++) + { + assembly Assembly = Assemblies.Values[AssemblyIdx]; + led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); + + u32 TotalBufferSize = MessageBaseSize * Assembly.StripCount; // SetChannelBuffer messages + TotalBufferSize += MessageBaseSize; // DrawAll message + TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel + + addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize); + AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort); + gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); + + for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) + { + v2_strip StripAt = Assembly.Strips[StripIdx]; + ChannelSettings.PixelsCount = StripAt.LedCount; + UART_SetChannelBuffer_Create(&WriteCursor, ChannelSettings, StripAt, *LedBuffer); + } + + UART_DrawAll_Create(&WriteCursor); + } +} + + +#define FOLDHAUS_UART_CPP +#endif // FOLDHAUS_UART_CPP \ No newline at end of file diff --git a/src/app/engine/uart/foldhaus_uart.h b/src/app/engine/uart/foldhaus_uart.h index 7e36e00..f866efc 100644 --- a/src/app/engine/uart/foldhaus_uart.h +++ b/src/app/engine/uart/foldhaus_uart.h @@ -16,7 +16,7 @@ enum uart_record_type struct uart_header { - u8 MagicNumber[4]; + s8 MagicNumber[4]; u8 Channel; u8 RecordType; }; @@ -24,12 +24,7 @@ struct uart_header struct uart_channel { u8 ElementsCount; - - u8 RedIndex; - u8 GreenIndex; - u8 BlueIndex; - u8 WhiteIndex; - + u8 ColorPackingOrder; u16 PixelsCount; }; @@ -57,113 +52,34 @@ UART_FillHeader(uart_header* Header, u8 Channel, u8 RecordType) Header->RecordType = RecordType; } -internal void -UART_FillFooter(uart_footer* Footer, u8* BufferStart) +internal u32 +UART_CalculateCRC(u8* BufferStart, u8* BufferEnd) { // Calculate the CRC u32 CRC = 0xFFFFFFFF; - u32 BytesCount = (u8*)Footer - BufferStart; + u32 BytesCount = (u8*)BufferEnd - BufferStart; for (u32 i = 0; i < BytesCount; i++) { u8 At = BufferStart[i]; - +#if 0 // Cameron's Version CRC = UART_CRCTable[(CRC ^ At) & 0x0F] ^ (CRC >> 4); CRC = UART_CRCTable[(CRC ^ (At >> 4)) & 0x0F] ^ (CRC >> 4); - -#if 0 - // The Libraries Version - CRC = (UART_CRCTable[(CRC ^ At) & 0xFF] ^ (CRC >> 8)) & 0xFFFFFFFF; +#else + // https://github.com/simap/pixelblaze_output_expander/blob/master/firmware/Core/Src/uart.c + u32 TableIndex = (CRC ^ At) & 0xFF; + CRC = (UART_CRCTable[TableIndex] ^ (CRC >> 8)) & 0xFFFFFFFF; #endif } - Footer->CRC = CRC; + CRC = CRC ^ 0xFFFFFFFF; + return CRC; } internal void -UART_SetChannelBuffer_Create(gs_memory_cursor* WriteCursor, uart_channel ChannelSettings, v2_strip Strip, led_buffer LedBuffer) +UART_FillFooter(uart_footer* Footer, u8* BufferStart) { - // 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 = PushStructOnCursor(WriteCursor, uart_header); - UART_FillHeader(Header, Strip.UARTAddr.Channel, UART_SET_CHANNEL_WS2812); - - 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); - - OutputPixel[Channel->RedIndex] = Color.R; - OutputPixel[Channel->GreenIndex] = Color.G; - OutputPixel[Channel->BlueIndex] = Color.B; - - if (OutputPixel[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); -} - -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); -} - -internal void -UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem) -{ - uart_channel ChannelSettings = {0}; - ChannelSettings.ElementsCount = 3; - ChannelSettings.RedIndex = 1; - ChannelSettings.GreenIndex = 2; - ChannelSettings.BlueIndex = 3; - ChannelSettings.WhiteIndex = 0; - - // 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 = sizeof(uart_header) + sizeof(uart_channel) + sizeof(uart_footer); - - for (u32 AssemblyIdx = 0; AssemblyIdx < Assemblies.Count; AssemblyIdx++) - { - assembly Assembly = Assemblies.Values[AssemblyIdx]; - led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); - - u32 TotalBufferSize = MessageBaseSize * Assembly.StripCount; // SetChannelBuffer messages - TotalBufferSize += MessageBaseSize; // DrawAll message - TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel - - addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize); - AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort); - gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); - - for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) - { - v2_strip StripAt = Assembly.Strips[StripIdx]; - ChannelSettings.PixelsCount = StripAt.LedCount; - UART_SetChannelBuffer_Create(&WriteCursor, ChannelSettings, StripAt, *LedBuffer); - } - - UART_DrawAll_Create(&WriteCursor); - } + Footer->CRC = UART_CalculateCRC(BufferStart, (u8*)Footer); } #define FOLDHAUS_UART_H diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 7dd6042..5644aa3 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -153,9 +153,10 @@ INITIALIZE_APPLICATION(InitializeApplication) Animation_AddLayer(&Anim, MakeString("Color Layer"), BlendMode_Multiply, &State->AnimationSystem); Animation_AddLayer(&Anim, MakeString("Sparkles"), BlendMode_Add, &State->AnimationSystem); - Animation_AddBlock(&Anim, 22, 123, 2, 1); + Animation_AddBlock(&Anim, 22, 123, 2, 0); AnimationArray_Push(&State->AnimationSystem.Animations, Anim); + } // End Animation Playground @@ -179,7 +180,7 @@ HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse } else { - panel_and_bounds PanelWithMouseOverIt = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, WindowBounds); + panel_with_layout PanelWithMouseOverIt = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, WindowBounds); if (!PanelWithMouseOverIt.Panel) { return; } State->HotPanel = PanelWithMouseOverIt.Panel; diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 1675b20..8c653da 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -22,6 +22,7 @@ #include "engine/sacn/foldhaus_sacn.h" #include "engine/uart/foldhaus_uart.h" +#include "engine/uart/foldhaus_uart.cpp" typedef struct app_state app_state; diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index d70938d..d11e851 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -426,6 +426,34 @@ WinMain ( { gs_thread_context ThreadContext = Win32CreateThreadContext(); +#if 0 + u32 LedCount = 48; + u32 MessageBaseSize = sizeof(uart_header) + sizeof(uart_channel) + sizeof(uart_footer); + MessageBaseSize += sizeof(u8) * 3 * LedCount; + gs_data MessageBuffer = PushSizeToData(ThreadContext.Transient); + + gs_memory_cursor WriteCursor = CreateMemoryCursor(MessageBuffer); + + uart_header* Header = PushStructOnCursor(WriteCursor, uart_header); + UART_FillHeader(Header, Strip.UARTAddr.Channel, UART_SET_CHANNEL_WS2812); + uart_channel* Channel = PushStructOnCursor(WriteCursor, uart_channel); + *Channel = ChannelSettings; + + for (u32 i = 0; i < LedCount; i++) + { + u8* OutputPixel = PushArrayOnCursor(WriteCursor, u8, 3); + OutputPixel[Channel->RedIndex] = (u8)(i); + OutputPixel[Channel->GreenIndex] = 0; + OutputPixel[Channel->BlueIndex] = 0; + } + + uart_footer* Footer = PushStructOnCursor(WriteCursor, uart_footer); + UART_FillFooter(Footer, (u8*)Header); + +#endif + + + MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); Win32UpdateWindowDimension(&MainWindow); diff --git a/src/app/platform_win32/win32_foldhaus_serial.h b/src/app/platform_win32/win32_foldhaus_serial.h index fbf389f..0368547 100644 --- a/src/app/platform_win32/win32_foldhaus_serial.h +++ b/src/app/platform_win32/win32_foldhaus_serial.h @@ -143,6 +143,37 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer) return Success; } +bool +Win32SerialPort_SetRead(HANDLE PortHandle) +{ + 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) + { + 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); + } + //Read data and store in a buffer + + return ReadSize; +} + ///////////////////////// // Win32SerialArray diff --git a/src/serial_monitor/first.cpp b/src/serial_monitor/first.cpp new file mode 100644 index 0000000..1f0c6d6 --- /dev/null +++ b/src/serial_monitor/first.cpp @@ -0,0 +1,221 @@ +// +// File: first.cpp +// Author: Peter Slattery +// Creation Date: 2020-10-10 +// +#ifndef FIRST_CPP + + +#include "../gs_libs/gs_types.h" +#include "../gs_libs/gs_types.cpp" + +#define DEBUG_TRACK_FUNCTION + +#include +#include + +//#include "../app/foldhaus_platform.h" +//#include "../gs_libs/gs_win32.cpp" +#include "../app/platform_win32/win32_foldhaus_utils.h" +#include "../app/platform_win32/win32_foldhaus_memory.h" +#include "../app/platform_win32/win32_foldhaus_fileio.h" +#include "../app/platform_win32/win32_foldhaus_serial.h" +#include "../app/platform_win32/win32_foldhaus_work_queue.h" + +#include "../app/engine/uart/foldhaus_uart.h" + +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; +} + +void +CreateMessage(gs_data* Data, u8 Count) +{ + gs_memory_cursor WriteCursor = CreateMemoryCursor(*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 = 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)); + } + + 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)); + + Data->Size = ((u8*)DrawAllFooter - (u8*)FirstHeaderAddr) + sizeof(uart_footer); +} + +int main(int ArgCount, char** Args) +{ + gs_thread_context Ctx = Win32CreateThreadContext(); + + HANDLE SerialHandle = Win32SerialPort_Open("\\\\.\\COM9"); + Win32SerialPort_SetState(SerialHandle, 2000000, 8, 0, 1); + + gs_const_string OutFileName = ConstString("./serial_dump.data"); + + + if (false) + { + 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) + { + 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; + } + } + CloseHandle(FileHandle); + Win32SerialPort_Close(SerialHandle); + + } + else if (true) + { + gs_data Data = PushSizeToData(Ctx.Transient, KB(32)); + + u8 Count = 0; + while(true) + { + CreateMessage(&Data, ++Count); + Win32SerialPort_Write(SerialHandle, Data); + Sleep(100); + } + } + 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); + } + } + + return 0; +} + + +#define FIRST_CPP +#endif // FIRST_CPP \ No newline at end of file From e4266ba1efc83d5600613fffc495fa50f1481385 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 10 Oct 2020 17:22:31 -0700 Subject: [PATCH 34/43] assembly_parser now uses the standard parser --- src/app/engine/assembly_parser.cpp | 455 ++++----------------------- src/app/engine/foldhaus_serializer.h | 68 +++- 2 files changed, 125 insertions(+), 398 deletions(-) diff --git a/src/app/engine/assembly_parser.cpp b/src/app/engine/assembly_parser.cpp index 006ae62..e6b1a02 100644 --- a/src/app/engine/assembly_parser.cpp +++ b/src/app/engine/assembly_parser.cpp @@ -45,362 +45,36 @@ enum assembly_field AssemblyField_Count, }; -global char* AssemblyFieldIdentifiers[] = { - "assembly_name", // AssemblyField_AssemblyName - "assembly_scale", // AssemblyField_AssemblyScale - "assembly_center", // AssemblyField_AssemblyCenter - "led_strip_count", // AssemblyField_LedStripCount - "output_mode", // AssemblyField_OutputMode +global gs_const_string AssemblyFieldIdentifiers[] = { + ConstString("assembly_name"), // AssemblyField_AssemblyName + ConstString("assembly_scale"), // AssemblyField_AssemblyScale + ConstString("assembly_center"), // AssemblyField_AssemblyCenter + ConstString("led_strip_count"), // AssemblyField_LedStripCount + ConstString("output_mode"), // AssemblyField_OutputMode - "led_strip", // AssemblyField_LedStrip + ConstString("led_strip"), // AssemblyField_LedStrip - "output_sacn", // AssemblyField_OutputSACN - "start_universe", // AssemblyField_SACN_StartUniverse - "start_channel", // AssemblyField_SACN_StartChannel + ConstString("output_sacn"), // AssemblyField_OutputSACN + ConstString("start_universe"), // AssemblyField_SACN_StartUniverse + ConstString("start_channel"), // AssemblyField_SACN_StartChannel - "output_uart", // AssemblyField_OutputUART - "channel", // AssemblyField_UART_Channel - "com_port", // AssemblyField_UART_ComPort + ConstString("output_uart"), // AssemblyField_OutputUART + ConstString("channel"), // AssemblyField_UART_Channel + ConstString("com_port"), // AssemblyField_UART_ComPort - "point_placement_type", // AssemblyField_PointPlacementType - "interpolate_points", // AssemblyField_InterpolatePoints - "start", // AssemblyField_Start - "end", // AssemblyField_End + ConstString("point_placement_type"), // AssemblyField_PointPlacementType + ConstString("interpolate_points"), // AssemblyField_InterpolatePoints + ConstString("start"), // AssemblyField_Start + ConstString("end"), // AssemblyField_End - "led_count", // AssemblyField_LedCount + ConstString("led_count"), // AssemblyField_LedCount - "tags_count", // AssemblyField_TagCount - "tag", // AssemblyField_Tag - "name", // AssemblyField_Name - "value", // AssemblyField_Value + ConstString("tags_count"), // AssemblyField_TagCount + ConstString("tag"), // AssemblyField_Tag + ConstString("name"), // AssemblyField_Name + ConstString("value"), // AssemblyField_Value }; -struct assembly_error_list -{ - gs_string String; - assembly_error_list* Next; -}; - -struct assembly_tokenizer -{ - gs_string Text; - char* At; - - gs_const_string FileName; - u32 LineNumber; - - bool ParsingIsValid; - - gs_memory_arena* ErrorArena; - assembly_error_list* ErrorsRoot; - assembly_error_list* ErrorsTail; -}; - -internal bool -AtValidPosition(assembly_tokenizer* T) -{ - u64 Offset = T->At - T->Text.Str; - bool Result = (Offset < T->Text.Length); - return Result; -} - -internal void -AdvanceChar(assembly_tokenizer* T) -{ - if (IsNewline(T->At[0])) - { - T->LineNumber += 1; - } - T->At++; -} - -internal void -EatWhitespace(assembly_tokenizer* T) -{ - while(AtValidPosition(T) && IsNewlineOrWhitespace(T->At[0])) - { - AdvanceChar(T); - } -} - -internal void -EatToNewLine(assembly_tokenizer* T) -{ - while(AtValidPosition(T) && !IsNewline(T->At[0])) - { - AdvanceChar(T); - } - EatWhitespace(T); -} - -internal bool -AdvanceIfTokenEquals(assembly_tokenizer* T, char* Value) -{ - bool Result = true; - - char* TAt = T->At; - char* VAt = Value; - while (*VAt != 0) - { - if (*TAt != *VAt) - { - Result = false; - break; - } - TAt += 1; - VAt += 1; - } - - // TODO(Peter): What if the token is a subset of Value? ie. this would return true for - // T->At = hello_world and Value = hello_ - // But the next token we read would fail - - if (Result) - { - T->At = TAt; - EatWhitespace(T); - } - return Result; -} - -internal void -TokenizerPushError(assembly_tokenizer* T, char* ErrorString) -{ - // NOTE(Peter): We can make this more expressive if we need to - assembly_error_list* Error = PushStruct(T->ErrorArena, assembly_error_list); - Error->String = PushString(T->ErrorArena, 512); - PrintF(&Error->String, "%S(%d): %s", T->FileName, T->LineNumber, ErrorString); - SLLPushOrInit(T->ErrorsRoot, T->ErrorsTail, Error); - T->ParsingIsValid = false; - - // NOTE(Peter): I'm not sure this is the best idea, but at least this way, - // if there's multiple errors, you'll get a number of them, rather than - // a bunch of erroneous errors happening on the same line - EatToNewLine(T); -} - -#define PARSER_FIELD_REQUIRED true -#define PARSER_FIELD_OPTIONAL false - -internal bool -ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T, bool Required = true) -{ - bool Result = false; - if (AdvanceIfTokenEquals(T, AssemblyFieldIdentifiers[Field])) - { - if (AdvanceIfTokenEquals(T, ":")) - { - Result = true; - } - else - { - // We always throw an error if we get this far because we know you were trying to - // open the identifier - TokenizerPushError(T, "Field identifier is missing a colon"); - } - } - else if (Required) - { - TokenizerPushError(T, "Field Identifier Invalid"); - } - return Result; -} - -internal bool -ReadFieldEnd(assembly_tokenizer* T) -{ - bool Result = AdvanceIfTokenEquals(T, ";"); - if (Result) - { - EatWhitespace(T); - } - else - { - TokenizerPushError(T, "Missing a semicolon"); - } - return Result; -} - -internal gs_string -ReadString(assembly_tokenizer* T) -{ - gs_string Result = {}; - if (AdvanceIfTokenEquals(T, "\"")) - { - char* StringStart = T->At; - while(AtValidPosition(T) && T->At[0] != '\"') - { - T->At++; - } - Result.Str = StringStart; - Result.Size = T->At - StringStart; - Result.Length = Result.Size; - if (AdvanceIfTokenEquals(T, "\"")) - { - // Success - } - else - { - TokenizerPushError(T, "String not closed with a \""); - } - } - else - { - TokenizerPushError(T, "Expecting a string, but none was found"); - } - return Result; -} - -internal gs_string -GetNumberString(assembly_tokenizer* T) -{ - gs_string Result = {}; - Result.Str = T->At; - while(AtValidPosition(T) && IsNumericExtended(T->At[0])) - { - AdvanceChar(T); - } - Result.Length = T->At - Result.Str; - Result.Size = Result.Length; - return Result; -} - -internal r32 -ReadFloat(assembly_tokenizer* T) -{ - r32 Result = 0; - gs_string NumberString = GetNumberString(T); - Result = (r32)ParseFloat(NumberString.ConstString); - return Result; -} - -internal s32 -ReadInt(assembly_tokenizer* T) -{ - s32 Result = 0; - gs_string NumberString = GetNumberString(T); - Result = (r32)ParseInt(NumberString.ConstString); - return Result; -} - -internal gs_string -ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Arena, bool ShouldNullTerminate = false) -{ - gs_string Result = {}; - if (ReadFieldIdentifier(Field, T)) - { - gs_string ExistingString = ReadString(T); - if (ReadFieldEnd(T)) - { - // Success - u64 Length = ExistingString.Length + (ShouldNullTerminate ? 1 : 0); - Result = PushString(Arena, Length); - PrintF(&Result, "%S", ExistingString); - if (ShouldNullTerminate) - { - NullTerminate(&Result); - } - } - } - return Result; -} - -internal r32 -ReadFloatField(assembly_field Field, assembly_tokenizer* T) -{ - r32 Result = 0.0f; - if (ReadFieldIdentifier(Field, T)) - { - Result = ReadFloat(T); - if (!ReadFieldEnd(T)) - { - T->ParsingIsValid = false; - } - } - return Result; -} - -internal s32 -ReadIntField(assembly_field Field, assembly_tokenizer* T) -{ - r32 Result = 0.0f; - if (ReadFieldIdentifier(Field, T)) - { - Result = ReadInt(T); - if (!ReadFieldEnd(T)) - { - T->ParsingIsValid = false; - } - } - return Result; -} - -internal v3 -ReadV3Field(assembly_field Field, assembly_tokenizer* T) -{ - v3 Result = {}; - if (ReadFieldIdentifier(Field, T)) - { - if (AdvanceIfTokenEquals(T, "(")) - { - Result.x = ReadFloat(T); - if (AdvanceIfTokenEquals(T, ",")) - { - Result.y = ReadFloat(T); - if (AdvanceIfTokenEquals(T, ",")) - { - Result.z = ReadFloat(T); - if (AdvanceIfTokenEquals(T, ")")) - { - if (!ReadFieldEnd(T)) - { - T->ParsingIsValid = false; - } - } - else - { - TokenizerPushError(T, "Vector 3 doesn't end with a ')'"); - } - } - else - { - TokenizerPushError(T, "Vector 3: unable to read a field"); - } - } - else - { - TokenizerPushError(T, "Vector 3: unable to read a field"); - } - } - else - { - TokenizerPushError(T, "Vector 3: unable to read a field"); - } - } - return Result; -} - -internal bool -ReadStructOpening(assembly_field Field, assembly_tokenizer* T, bool Required = true) -{ - bool Result = false; - if (ReadFieldIdentifier(Field, T, Required)) - { - if (AdvanceIfTokenEquals(T, "{")) - { - Result = true; - } - } - return Result; -} - -internal bool -ReadStructClosing(assembly_tokenizer* T) -{ - bool Result = AdvanceIfTokenEquals(T, "};"); - return Result; -} - internal void StripSetTag(v2_strip* Strip, u32 TagIndex, gs_const_string TagName, gs_const_string TagValue) { @@ -415,27 +89,26 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe { Assembly->LedCountTotal = 0; - r32 Value = ParseFloat(ConstString("-2.355")); + parser Parser = {0}; + Parser.String = FileText; + Parser.Identifiers = &AssemblyFieldIdentifiers[0]; + Parser.IdentifiersCount = AssemblyField_Count; + Parser.At = Parser.String.Str; + Parser.LineStart = Parser.At; + Parser.Arena = &Assembly->Arena; - assembly_tokenizer Tokenizer = {}; - Tokenizer.Text = FileText; - Tokenizer.At = Tokenizer.Text.Str; - Tokenizer.ParsingIsValid = true; - Tokenizer.ErrorArena = Transient; - Tokenizer.FileName = FileName; + Assembly->Name = Parser_ReadStringValue(&Parser, AssemblyField_AssemblyName); + Assembly->Scale = Parser_ReadR32Value(&Parser, AssemblyField_AssemblyScale); + Assembly->Center = Parser_ReadV3Value(&Parser, AssemblyField_AssemblyCenter); + Assembly->StripCount = Parser_ReadU32Value(&Parser, AssemblyField_LedStripCount); - Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena); - Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer); - Assembly->Center = ReadV3Field(AssemblyField_AssemblyCenter, &Tokenizer); - - Assembly->StripCount = ReadIntField(AssemblyField_LedStripCount, &Tokenizer); Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount); - gs_string OutputModeString = ReadStringField(AssemblyField_OutputMode, &Tokenizer, Transient); + gs_string OutputModeString = Parser_ReadStringValue(&Parser, AssemblyField_OutputMode); if (StringsEqual(OutputModeString.ConstString, ConstString("UART"))) { Assembly->OutputMode = NetworkProtocol_UART; - Assembly->UARTComPort = ReadStringField(AssemblyField_UART_ComPort, &Tokenizer, &Assembly->Arena, true).ConstString; + Assembly->UARTComPort = Parser_ReadStringValue(&Parser, AssemblyField_UART_ComPort, true).ConstString; } else if (StringsEqual(OutputModeString.ConstString, ConstString("SACN"))) { @@ -443,45 +116,44 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe } else { - TokenizerPushError(&Tokenizer, "Invalid output mode specified."); + //TokenizerPushError(&Tokenizer, "Invalid output mode specified."); } for (u32 i = 0; i < Assembly->StripCount; i++) { v2_strip* StripAt = Assembly->Strips + i; - if (ReadStructOpening(AssemblyField_LedStrip, &Tokenizer)) + if (Parser_ReadOpenStruct(&Parser, AssemblyField_LedStrip)) { - if (ReadStructOpening(AssemblyField_OutputSACN, &Tokenizer, PARSER_FIELD_OPTIONAL)) + if (Parser_ReadOpenStruct(&Parser, AssemblyField_OutputSACN)) { - StripAt->SACNAddr.StartUniverse = ReadIntField(AssemblyField_SACN_StartUniverse, &Tokenizer); - StripAt->SACNAddr.StartChannel = ReadIntField(AssemblyField_SACN_StartChannel, &Tokenizer); + StripAt->SACNAddr.StartUniverse = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartUniverse); + StripAt->SACNAddr.StartChannel = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartChannel); - if (!ReadStructClosing(&Tokenizer)) + if (!Parser_ReadCloseStruct(&Parser)) { - TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); } } - if (ReadStructOpening(AssemblyField_OutputUART, &Tokenizer, PARSER_FIELD_OPTIONAL)) + if (Parser_ReadOpenStruct(&Parser, AssemblyField_OutputUART)) { - StripAt->UARTAddr.Channel = (u8)ReadIntField(AssemblyField_UART_Channel, &Tokenizer); + StripAt->UARTAddr.Channel = (u8)Parser_ReadU32Value(&Parser, AssemblyField_UART_Channel); - if (!ReadStructClosing(&Tokenizer)) + if (!Parser_ReadCloseStruct(&Parser)) { - TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); } } // TODO(Peter): Need to store this - gs_string PointPlacementType = ReadStringField(AssemblyField_PointPlacementType, &Tokenizer, &Assembly->Arena); + gs_string PointPlacementType = Parser_ReadStringValue(&Parser, AssemblyField_PointPlacementType); // TODO(Peter): Switch on value of PointPlacementType - if (ReadStructOpening(AssemblyField_InterpolatePoints, &Tokenizer)) + if (Parser_ReadOpenStruct(&Parser, AssemblyField_InterpolatePoints)) { - StripAt->StartPosition = ReadV3Field(AssemblyField_Start, &Tokenizer); - StripAt->EndPosition = ReadV3Field(AssemblyField_End, &Tokenizer); - if (!ReadStructClosing(&Tokenizer)) + StripAt->StartPosition = Parser_ReadV3Value(&Parser, AssemblyField_Start); + StripAt->EndPosition = Parser_ReadV3Value(&Parser, AssemblyField_End); + if (!Parser_ReadCloseStruct(&Parser)) { - Tokenizer.ParsingIsValid = false; // TODO(Peter): @ErrorHandling // Have this function prepend the filename and line number. // Create an error display popup window, or an error log window that takes over a panel automatically @@ -489,48 +161,47 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe } } - StripAt->LedCount = ReadIntField(AssemblyField_LedCount, &Tokenizer); + StripAt->LedCount = Parser_ReadU32Value(&Parser, AssemblyField_LedCount); Assembly->LedCountTotal += StripAt->LedCount; - - StripAt->TagsCount = ReadIntField(AssemblyField_TagsCount, &Tokenizer); + StripAt->TagsCount = Parser_ReadU32Value(&Parser, AssemblyField_TagsCount); // NOTE(pjs): Always add one tag to the input to leave room for the assembly name StripAt->TagsCount += 1; StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount); StripSetTag(StripAt, 0, ConstString("assembly"), Assembly->Name.ConstString); for (u32 Tag = 1; Tag < StripAt->TagsCount; Tag++) { - if (ReadStructOpening(AssemblyField_Tag, &Tokenizer)) + if (Parser_ReadOpenStruct(&Parser, AssemblyField_Tag)) { // TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface // right now they are stored in temp memory and won't persist - gs_string TagName = ReadStringField(AssemblyField_Name, &Tokenizer, Transient); - gs_string TagValue = ReadStringField(AssemblyField_Value, &Tokenizer, Transient); + gs_string TagName = Parser_ReadStringValue(&Parser, AssemblyField_Name); + gs_string TagValue = Parser_ReadStringValue(&Parser, AssemblyField_Value); StripSetTag(StripAt, Tag, TagName.ConstString, TagValue.ConstString); - if (!ReadStructClosing(&Tokenizer)) + if (!Parser_ReadCloseStruct(&Parser)) { - TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); } } else { - TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); + //TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); } } - if (!ReadStructClosing(&Tokenizer)) + if (!Parser_ReadCloseStruct(&Parser)) { - TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); } } else { - TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); + //TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); } } - return Tokenizer.ParsingIsValid; + return true; //Tokenizer.ParsingIsValid; } #define ASSEMBLY_PARSER_CPP diff --git a/src/app/engine/foldhaus_serializer.h b/src/app/engine/foldhaus_serializer.h index b82ee62..3a1849e 100644 --- a/src/app/engine/foldhaus_serializer.h +++ b/src/app/engine/foldhaus_serializer.h @@ -245,7 +245,7 @@ Parser_ReadString(parser* P, u32 IdentIndex) } internal gs_string -Parser_ReadStringValue(parser* P, gs_const_string Ident) +Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminate = false) { // ident: "value"; gs_string Result = {}; @@ -265,7 +265,16 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident) if (Parser_AdvanceIfTokenEquals(P, ConstString("\"")) && Parser_AdvanceIfLineEnd(P)) { - Result = PushStringF(P->Arena, FileString.Length, "%S", FileString); + u32 StringLength = FileString.Length; + if (ShouldNullTerminate) + { + StringLength += 1; + } + Result = PushStringF(P->Arena, StringLength, "%S", FileString); + if (ShouldNullTerminate) + { + NullTerminate(&Result); + } } else { @@ -277,10 +286,10 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident) } internal gs_string -Parser_ReadStringValue(parser* P, u32 IdentIndex) +Parser_ReadStringValue(parser* P, u32 IdentIndex, bool ShouldNullTerminate = false) { gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); - return Parser_ReadStringValue(P, Ident); + return Parser_ReadStringValue(P, Ident, ShouldNullTerminate); } internal bool @@ -351,6 +360,15 @@ Parser_ReadU32Value(parser* P, u32 IdentIndex) return Parser_ReadU32Value(P, Ident); } +internal r32 +Parser_ReadR32(parser* P) +{ + r32 Result = 0; + gs_const_string NumStr = Parser_ReadNumberString(P); + Result = (r32)ParseFloat(NumStr); + return Result; +} + internal r32 Parser_ReadR32Value(parser* P, gs_const_string Ident) { @@ -359,15 +377,16 @@ Parser_ReadR32Value(parser* P, gs_const_string Ident) if (Parser_AdvanceIfTokenEquals(P, Ident) && Parser_AdvanceIfTokenEquals(P, ConstString(":"))) { - gs_const_string NumStr = Parser_ReadNumberString(P); + r32 Value = Parser_ReadR32(P); if (Parser_AdvanceIfLineEnd(P)) { - Result = (r32)ParseFloat(NumStr); + Result = Value; } else { // TODO(pjs): Error } + } return Result; } @@ -379,6 +398,43 @@ Parser_ReadR32Value(parser* P, u32 IdentIndex) return Parser_ReadR32Value(P, Ident); } +internal v3 +Parser_ReadV3Value(parser* P, gs_const_string Ident) +{ + v3 Result = {0}; + if (Parser_AdvanceIfTokenEquals(P, Ident) && + Parser_AdvanceIfTokenEquals(P, ConstString(":")) && + Parser_AdvanceIfTokenEquals(P, ConstString("("))) + { + r32 X = Parser_ReadR32(P); + Parser_AdvanceIfTokenEquals(P, ConstString(",")); + + r32 Y = Parser_ReadR32(P); + Parser_AdvanceIfTokenEquals(P, ConstString(",")); + + r32 Z = Parser_ReadR32(P); + if (Parser_AdvanceIfTokenEquals(P, ConstString(")")) && + Parser_AdvanceIfLineEnd(P)) + { + Result.x = X; + Result.y = Y; + Result.z = Z; + } + else + { + // TODO(pjs): error + } + } + return Result; +} + +internal v3 +Parser_ReadV3Value(parser* P, u32 IdentIndex) +{ + gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); + return Parser_ReadV3Value(P, Ident); +} + #define FOLDHAUS_SERIALIZER_H #endif // FOLDHAUS_SERIALIZER_H \ No newline at end of file From 43d3426a584bfabb969a35b4a9b70bf7837b2529 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 10 Oct 2020 17:23:39 -0700 Subject: [PATCH 35/43] renamed assembly_parser -> foldhaus_assembly_parser for consistency --- .../{assembly_parser.cpp => foldhaus_assembly_parser.cpp} | 8 ++++---- src/app/foldhaus_app.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/app/engine/{assembly_parser.cpp => foldhaus_assembly_parser.cpp} (98%) diff --git a/src/app/engine/assembly_parser.cpp b/src/app/engine/foldhaus_assembly_parser.cpp similarity index 98% rename from src/app/engine/assembly_parser.cpp rename to src/app/engine/foldhaus_assembly_parser.cpp index e6b1a02..3f95b16 100644 --- a/src/app/engine/assembly_parser.cpp +++ b/src/app/engine/foldhaus_assembly_parser.cpp @@ -1,9 +1,9 @@ // -// File: assembly_parser.cpp +// File: foldhaus_assembly_parser.cpp // Author: Peter Slattery // Creation Date: 2020-01-01 // -#ifndef ASSEMBLY_PARSER_CPP +#ifndef FOLDHAUS_ASSEMBLY_PARSER_CPP // TODO(pjs): This is good for meta generation // ie. It would be great to have @@ -204,5 +204,5 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe return true; //Tokenizer.ParsingIsValid; } -#define ASSEMBLY_PARSER_CPP -#endif // ASSEMBLY_PARSER_CPP \ No newline at end of file +#define FOLDHAUS_ASSEMBLY_PARSER_CPP +#endif // FOLDHAUS_ASSEMBLY_PARSER_CPP \ No newline at end of file diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 8c653da..9fe672a 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -18,7 +18,7 @@ #include "engine/foldhaus_network_ordering.h" #include "engine/foldhaus_assembly.h" -#include "engine/assembly_parser.cpp" +#include "engine/foldhaus_assembly_parser.cpp" #include "engine/sacn/foldhaus_sacn.h" #include "engine/uart/foldhaus_uart.h" From 0ba59d376790da6947ab3f59e33287c5fcaaf6d4 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 10 Oct 2020 17:46:50 -0700 Subject: [PATCH 36/43] added error reporting to the parser --- src/app/engine/foldhaus_serializer.h | 60 ++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/src/app/engine/foldhaus_serializer.h b/src/app/engine/foldhaus_serializer.h index 3a1849e..a55ea2e 100644 --- a/src/app/engine/foldhaus_serializer.h +++ b/src/app/engine/foldhaus_serializer.h @@ -131,6 +131,12 @@ Serializer_WriteV3Value(serializer* Serializer, u32 IdentIndex, v3 Value) // Parsing +struct parser_error +{ + gs_string Message; + parser_error* Next; +}; + struct parser { gs_string String; @@ -144,8 +150,26 @@ struct parser char* At; gs_memory_arena* Arena; + gs_memory_arena* Transient; + + parser_error* ErrorsRoot; + parser_error* ErrorsHead; }; +internal void +Parser_PushErrorF(parser* Parser, char* Format, ...) +{ + parser_error* Error = PushStruct(Parser->Transient, parser_error); + Error->Message = PushString(Parser->Transient, 1024); + + va_list Args; + va_start(Args, Format); + PrintFArgsList(&Error->Message, Format, Args); + va_end(Args); + + SLLPushOrInit(Parser->ErrorsRoot, Parser->ErrorsHead, Error); +} + internal gs_const_string Parser_GetIdent(parser Parser, u32 Index) { @@ -278,9 +302,13 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminat } else { - // TODO(pjs): Error + Parser_PushErrorF(P, "String doesn't have a closing quote, or line doesn't end with a semicolon"); } } + else + { + Parser_PushErrorF(P, "String doesn't begin correctly"); + } return Result; } @@ -346,9 +374,13 @@ Parser_ReadU32Value(parser* P, gs_const_string Ident) } else { - // TODO(pjs): Error + Parser_PushErrorF(P, "U32 Value doesn't end with semicolon"); } } + else + { + Parser_PushErrorF(P, "U32 value doesn't begin properly"); + } return Result; } @@ -384,10 +416,14 @@ Parser_ReadR32Value(parser* P, gs_const_string Ident) } else { - // TODO(pjs): Error + Parser_PushErrorF(P, "R32 Value doesn't end with semicolon"); } - } + else + { + Parser_PushErrorF(P, "R32 value doesn't begin properly"); + } + return Result; } @@ -407,10 +443,16 @@ Parser_ReadV3Value(parser* P, gs_const_string Ident) Parser_AdvanceIfTokenEquals(P, ConstString("("))) { r32 X = Parser_ReadR32(P); - Parser_AdvanceIfTokenEquals(P, ConstString(",")); + if (!Parser_AdvanceIfTokenEquals(P, ConstString(","))) + { + Parser_PushErrorF(P, "V3 Value doesn't have comma separated values"); + } r32 Y = Parser_ReadR32(P); - Parser_AdvanceIfTokenEquals(P, ConstString(",")); + if (!Parser_AdvanceIfTokenEquals(P, ConstString(","))) + { + Parser_PushErrorF(P, "V3 Value doesn't have comma separated values"); + } r32 Z = Parser_ReadR32(P); if (Parser_AdvanceIfTokenEquals(P, ConstString(")")) && @@ -422,9 +464,13 @@ Parser_ReadV3Value(parser* P, gs_const_string Ident) } else { - // TODO(pjs): error + Parser_PushErrorF(P, "V3 Value doesn't end correctly"); } } + else + { + Parser_PushErrorF(P, "V3 Value doesn't begin correctly"); + } return Result; } From bfd50c91297e501a12a44f6e7168038485660588 Mon Sep 17 00:00:00 2001 From: PS Date: Sun, 11 Oct 2020 20:54:38 -0700 Subject: [PATCH 37/43] implemented segmented led strips --- .../panels/foldhaus_panel_sculpture_view.h | 2 +- src/app/engine/foldhaus_assembly.cpp | 53 +++- src/app/engine/foldhaus_assembly.h | 83 +++++- src/app/engine/foldhaus_assembly_parser.cpp | 262 +++++++++++++----- src/app/engine/foldhaus_parser.h | 18 -- src/app/engine/foldhaus_serializer.h | 171 ++++++++---- src/app/engine/uart/foldhaus_uart.cpp | 2 +- src/app/foldhaus_app.cpp | 2 +- src/app/platform_win32/win32_foldhaus.cpp | 15 +- 9 files changed, 451 insertions(+), 157 deletions(-) delete mode 100644 src/app/engine/foldhaus_parser.h diff --git a/src/app/editor/panels/foldhaus_panel_sculpture_view.h b/src/app/editor/panels/foldhaus_panel_sculpture_view.h index 30ede9c..a4f7246 100644 --- a/src/app/editor/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/editor/panels/foldhaus_panel_sculpture_view.h @@ -166,7 +166,7 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend u32 MaxLEDsPerJob = 2048; render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal); - u32 FocusPixel = 256; + u32 FocusPixel = 100; for (u32 BufferIndex = 0; BufferIndex < State->LedSystem.BuffersCount; BufferIndex++) { diff --git a/src/app/engine/foldhaus_assembly.cpp b/src/app/engine/foldhaus_assembly.cpp index fce8922..f183f4c 100644 --- a/src/app/engine/foldhaus_assembly.cpp +++ b/src/app/engine/foldhaus_assembly.cpp @@ -135,6 +135,46 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) 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 LedsAdded = 0; + + switch (GenData.Method) + { + 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] = LedIndex; + } + }break; + + case StripGeneration_Sequence: + { + strip_gen_sequence Sequence = GenData.Sequence; + for (u32 i = 0; i < Sequence.ElementsCount; i++) + { + __debugbreak(); + strip_gen_data SegmentGenData = Sequence.Elements[i]; + LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, SegmentGenData, RootPosition, LedStartIndex + LedsAdded); + } + }break; + + InvalidDefaultCase; + } + + return LedsAdded; +} + internal void ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem) { @@ -150,17 +190,8 @@ ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem) v2_strip* StripAt = &Assembly->Strips[StripIdx]; StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount); - v4 WS_StripStart = RootPosition + ToV4Point(StripAt->StartPosition * Assembly->Scale); - v4 WS_StripEnd = RootPosition + ToV4Point(StripAt->EndPosition * Assembly->Scale); - - v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)StripAt->LedCount; - for (u32 Step = 0; Step < StripAt->LedCount; Step++) - { - s32 LedIndex = LedsAdded++; - v4 LedPosition = WS_StripStart + (SingleStep * Step); - LedBufferSetLed(LedBuffer, LedIndex, LedPosition); - StripAt->LedLUT[Step] = LedIndex; - } + strip_gen_data GenData = StripAt->GenerationData; + LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, GenData, RootPosition, LedsAdded); } } diff --git a/src/app/engine/foldhaus_assembly.h b/src/app/engine/foldhaus_assembly.h index aa422f3..94982a5 100644 --- a/src/app/engine/foldhaus_assembly.h +++ b/src/app/engine/foldhaus_assembly.h @@ -58,6 +58,41 @@ struct strip_sacn_addr 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 +}; + +enum strip_gen_method +{ + 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; +}; + +struct strip_gen_sequence +{ + strip_gen_data* Elements; + u32 ElementsCount; +}; + +struct strip_gen_data +{ + strip_gen_method Method; + + strip_gen_interpolate_points InterpolatePoints; + strip_gen_sequence Sequence; }; struct v2_strip @@ -67,10 +102,7 @@ struct v2_strip strip_sacn_addr SACNAddr; strip_uart_addr UARTAddr; - // TODO(Peter): When we create more ways to calculate points, this needs to become - // a type enum and a union - v3 StartPosition; - v3 EndPosition; + strip_gen_data GenerationData; u32 LedCount; u32* LedLUT; @@ -86,6 +118,21 @@ struct led_strip_list 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, +}; + struct assembly { gs_memory_arena Arena; @@ -102,7 +149,8 @@ struct assembly v2_strip* Strips; network_protocol OutputMode; - gs_const_string UARTComPort; + network_port_mode NetPortMode; + gs_string UARTComPort; }; struct assembly_array @@ -120,6 +168,31 @@ LedSystemGetBuffer(led_system* System, u32 Index) return Result; } +internal u32 +StripGenData_CountLeds(strip_gen_data Data) +{ + u32 Result = 0; + + switch (Data.Method) + { + 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; + } + + return Result; +} #define FOLDHAUS_ASSEMBLY_H #endif // FOLDHAUS_ASSEMBLY_H \ No newline at end of file diff --git a/src/app/engine/foldhaus_assembly_parser.cpp b/src/app/engine/foldhaus_assembly_parser.cpp index 3f95b16..ff2cbc0 100644 --- a/src/app/engine/foldhaus_assembly_parser.cpp +++ b/src/app/engine/foldhaus_assembly_parser.cpp @@ -33,10 +33,16 @@ enum assembly_field AssemblyField_UART_ComPort, AssemblyField_PointPlacementType, + AssemblyField_InterpolatePoints, AssemblyField_Start, AssemblyField_End, AssemblyField_LedCount, + + AssemblyField_SegmentSequence, + AssemblyField_SegmentSequenceLength, + AssemblyField_Segment, + AssemblyField_TagsCount, AssemblyField_Tag, AssemblyField_Name, @@ -63,12 +69,16 @@ global gs_const_string AssemblyFieldIdentifiers[] = { ConstString("com_port"), // AssemblyField_UART_ComPort ConstString("point_placement_type"), // AssemblyField_PointPlacementType + ConstString("interpolate_points"), // AssemblyField_InterpolatePoints ConstString("start"), // AssemblyField_Start ConstString("end"), // AssemblyField_End - ConstString("led_count"), // AssemblyField_LedCount + ConstString("segment_sequence"), // AssemblyField_SegmentSequence + ConstString("segment_count"), // AssemblyField_SegmentSequenceLength + ConstString("segment"), // AssemblyField_Segment + ConstString("tags_count"), // AssemblyField_TagCount ConstString("tag"), // AssemblyField_Tag ConstString("name"), // AssemblyField_Name @@ -84,6 +94,170 @@ StripSetTag(v2_strip* Strip, u32 TagIndex, gs_const_string TagName, gs_const_str TagAt->ValueHash = HashDJB2ToU32(StringExpand(TagValue)); } +internal strip_sacn_addr +AssemblyParser_ReadSACNAddr(parser* Parser, assembly Assembly) +{ + strip_sacn_addr Result = {0}; + + if (Parser_ReadOpenStruct(Parser, AssemblyField_OutputSACN)) + { + Result.StartUniverse = Parser_ReadU32Value(Parser, AssemblyField_SACN_StartUniverse); + Result.StartChannel = Parser_ReadU32Value(Parser, AssemblyField_SACN_StartChannel); + + if (!Parser_ReadCloseStruct(Parser)) + { + //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + } + } + + return Result; +} + +internal strip_uart_addr +AssemblyParser_ReadUARTAddr(parser* Parser, assembly Assembly) +{ + strip_uart_addr Result = {0}; + + if (Parser_ReadOpenStruct(Parser, AssemblyField_OutputUART)) + { + Result.Channel = (u8)Parser_ReadU32Value(Parser, AssemblyField_UART_Channel); + + bool HasNetPort = Parser_ReadStringValue(Parser, AssemblyField_UART_ComPort, &Result.ComPort, true); + if (Assembly.NetPortMode == NetworkPortMode_PortPerStrip && !HasNetPort) + { + Parser_PushErrorF(Parser, "NetPortMode for assembly is PortPerStrip, but this strip doesn't have an output port."); + } + + if (!Parser_ReadCloseStruct(Parser)) + { + Parser_PushErrorF(Parser, "Struct doesn't close where expected"); + } + } + + return Result; +} + +internal void +AssemblyParser_ReadTag(parser* Parser, v2_strip* StripAt, u32 TagIndex) +{ + if (Parser_ReadOpenStruct(Parser, AssemblyField_Tag)) + { + // TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface + // right now they are stored in temp memory and won't persist + gs_string TagName = Parser_ReadStringValue(Parser, AssemblyField_Name); + gs_string TagValue = Parser_ReadStringValue(Parser, AssemblyField_Value); + StripSetTag(StripAt, TagIndex, TagName.ConstString, TagValue.ConstString); + if (!Parser_ReadCloseStruct(Parser)) + { + Parser_PushErrorF(Parser, "Tag struct doesn't close where expected"); + } + } + else + { + Parser_PushErrorF(Parser, "Expected a tag struct, but none was found."); + } +} + + +internal void +AssemblyParser_ReadTagList(parser* Parser, v2_strip* StripAt, assembly* Assembly) +{ + StripAt->TagsCount = Parser_ReadU32Value(Parser, AssemblyField_TagsCount); + // NOTE(pjs): Always add one tag to the input to leave room for the assembly name + StripAt->TagsCount += 1; + StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount); + + StripSetTag(StripAt, 0, ConstString("assembly"), Assembly->Name.ConstString); + + for (u32 Tag = 1; Tag < StripAt->TagsCount; Tag++) + { + AssemblyParser_ReadTag(Parser, StripAt, Tag); + } +} + +internal strip_gen_data AssemblyParser_ReadStripGenData(parser* Parser, assembly* Assembly); + +internal strip_gen_interpolate_points +AssemblyParser_ReadInterpolatePoints(parser* Parser) +{ + strip_gen_interpolate_points Result = {0}; + if (Parser_ReadOpenStruct(Parser, AssemblyField_InterpolatePoints)) + { + Result.StartPosition = Parser_ReadV3Value(Parser, AssemblyField_Start); + Result.EndPosition = Parser_ReadV3Value(Parser, AssemblyField_End); + Result.LedCount = Parser_ReadU32Value(Parser, AssemblyField_LedCount); + if (!Parser_ReadCloseStruct(Parser)) + { + // TODO(pjs): + } + } + else + { + // TODO(pjs): + } + return Result; +} + +internal strip_gen_sequence +AssemblyParser_ReadSequence(parser* Parser, assembly* Assembly) +{ + strip_gen_sequence Result = {0}; + if (Parser_ReadOpenStruct(Parser, AssemblyField_SegmentSequence)) + { + Result.ElementsCount = Parser_ReadU32Value(Parser, AssemblyField_SegmentSequenceLength); + Result.Elements = PushArray(&Assembly->Arena, strip_gen_data, Result.ElementsCount); + for (u32 i = 0; i < Result.ElementsCount; i++) + { + Result.Elements[i] = AssemblyParser_ReadStripGenData(Parser, Assembly); + } + if (!Parser_ReadCloseStruct(Parser)) + { + // TODO(pjs): + } + } + else + { + // TODO(pjs): + } + return Result; +} + +internal strip_gen_data +AssemblyParser_ReadStripGenData(parser* Parser, assembly* Assembly) +{ + strip_gen_data Result = {0}; + + if (Parser_ReadOpenStruct(Parser, AssemblyField_Segment)) + { + gs_string PointPlacementType = Parser_ReadStringValue(Parser, AssemblyField_PointPlacementType); + + // TODO(pjs): We want to store enum strings in some unified way + // :EnumStringsGen + if (StringsEqual(PointPlacementType.ConstString, ConstString("InterpolatePoints"))) + { + Result.Method = StripGeneration_InterpolatePoints; + Result.InterpolatePoints = AssemblyParser_ReadInterpolatePoints(Parser); + } + else if (StringsEqual(PointPlacementType.ConstString, + ConstString("SegmentSequence"))) + { + Result.Method = StripGeneration_Sequence; + Result.Sequence = AssemblyParser_ReadSequence(Parser, Assembly); + } + else + { + Parser_PushErrorF(Parser, "Incorrect Point Placement Type found for segment"); + } + + if (!Parser_ReadCloseStruct(Parser)) + { + Parser_PushErrorF(Parser, "Strip Gen Data did not close the struct where expected"); + } + } + + return Result; +} + internal bool ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileText, gs_memory_arena* Transient) { @@ -96,19 +270,26 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe Parser.At = Parser.String.Str; Parser.LineStart = Parser.At; Parser.Arena = &Assembly->Arena; + Parser.Transient = Transient; Assembly->Name = Parser_ReadStringValue(&Parser, AssemblyField_AssemblyName); Assembly->Scale = Parser_ReadR32Value(&Parser, AssemblyField_AssemblyScale); Assembly->Center = Parser_ReadV3Value(&Parser, AssemblyField_AssemblyCenter); Assembly->StripCount = Parser_ReadU32Value(&Parser, AssemblyField_LedStripCount); - Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount); gs_string OutputModeString = Parser_ReadStringValue(&Parser, AssemblyField_OutputMode); if (StringsEqual(OutputModeString.ConstString, ConstString("UART"))) { Assembly->OutputMode = NetworkProtocol_UART; - Assembly->UARTComPort = Parser_ReadStringValue(&Parser, AssemblyField_UART_ComPort, true).ConstString; + if (Parser_ReadStringValue(&Parser, AssemblyField_UART_ComPort, &Assembly->UARTComPort, true)) + { + Assembly->NetPortMode = NetworkPortMode_GlobalPort; + } + else + { + Assembly->NetPortMode = NetworkPortMode_PortPerStrip; + } } else if (StringsEqual(OutputModeString.ConstString, ConstString("SACN"))) { @@ -116,7 +297,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe } else { - //TokenizerPushError(&Tokenizer, "Invalid output mode specified."); + Parser_PushErrorF(&Parser, "Invalid output mode specified for assembly."); } for (u32 i = 0; i < Assembly->StripCount; i++) @@ -124,83 +305,26 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe v2_strip* StripAt = Assembly->Strips + i; if (Parser_ReadOpenStruct(&Parser, AssemblyField_LedStrip)) { - if (Parser_ReadOpenStruct(&Parser, AssemblyField_OutputSACN)) - { - StripAt->SACNAddr.StartUniverse = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartUniverse); - StripAt->SACNAddr.StartChannel = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartChannel); - - if (!Parser_ReadCloseStruct(&Parser)) - { - //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); - } - } + StripAt->SACNAddr = AssemblyParser_ReadSACNAddr(&Parser, *Assembly); + StripAt->UARTAddr = AssemblyParser_ReadUARTAddr(&Parser, *Assembly); + StripAt->GenerationData = AssemblyParser_ReadStripGenData(&Parser, Assembly); + StripAt->LedCount = StripGenData_CountLeds(StripAt->GenerationData); + AssemblyParser_ReadTagList(&Parser, StripAt, Assembly); - if (Parser_ReadOpenStruct(&Parser, AssemblyField_OutputUART)) - { - StripAt->UARTAddr.Channel = (u8)Parser_ReadU32Value(&Parser, AssemblyField_UART_Channel); - - if (!Parser_ReadCloseStruct(&Parser)) - { - //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); - } - } - - // TODO(Peter): Need to store this - gs_string PointPlacementType = Parser_ReadStringValue(&Parser, AssemblyField_PointPlacementType); - // TODO(Peter): Switch on value of PointPlacementType - if (Parser_ReadOpenStruct(&Parser, AssemblyField_InterpolatePoints)) - { - StripAt->StartPosition = Parser_ReadV3Value(&Parser, AssemblyField_Start); - StripAt->EndPosition = Parser_ReadV3Value(&Parser, AssemblyField_End); - if (!Parser_ReadCloseStruct(&Parser)) - { - // TODO(Peter): @ErrorHandling - // Have this function prepend the filename and line number. - // Create an error display popup window, or an error log window that takes over a panel automatically - // TokenizerPushError(&Tokenizer, "Unable to read - } - } - - StripAt->LedCount = Parser_ReadU32Value(&Parser, AssemblyField_LedCount); Assembly->LedCountTotal += StripAt->LedCount; - StripAt->TagsCount = Parser_ReadU32Value(&Parser, AssemblyField_TagsCount); - // NOTE(pjs): Always add one tag to the input to leave room for the assembly name - StripAt->TagsCount += 1; - StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount); - StripSetTag(StripAt, 0, ConstString("assembly"), Assembly->Name.ConstString); - for (u32 Tag = 1; Tag < StripAt->TagsCount; Tag++) - { - if (Parser_ReadOpenStruct(&Parser, AssemblyField_Tag)) - { - // TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface - // right now they are stored in temp memory and won't persist - gs_string TagName = Parser_ReadStringValue(&Parser, AssemblyField_Name); - gs_string TagValue = Parser_ReadStringValue(&Parser, AssemblyField_Value); - StripSetTag(StripAt, Tag, TagName.ConstString, TagValue.ConstString); - if (!Parser_ReadCloseStruct(&Parser)) - { - //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); - } - } - else - { - //TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); - } - } - - if (!Parser_ReadCloseStruct(&Parser)) { - //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + Parser_PushErrorF(&Parser, "Strip struct doesn't close where expected"); } } else { - //TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); + Parser_PushErrorF(&Parser, "Expected a strip struct but none was found"); } } + // TODO(pjs): invalidate the file if its incorrect return true; //Tokenizer.ParsingIsValid; } diff --git a/src/app/engine/foldhaus_parser.h b/src/app/engine/foldhaus_parser.h deleted file mode 100644 index 709f375..0000000 --- a/src/app/engine/foldhaus_parser.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// File: foldhaus_parser.h -// Author: Peter Slattery -// Creation Date: 2020-10-09 -// -#ifndef FOLDHAUS_PARSER_H - -struct parser -{ - gs_string String; - gs_const_string* Identifiers; - u32 IdentifiersCount; -}; - - - -#define FOLDHAUS_PARSER_H -#endif // FOLDHAUS_PARSER_H \ No newline at end of file diff --git a/src/app/engine/foldhaus_serializer.h b/src/app/engine/foldhaus_serializer.h index a55ea2e..06f9d71 100644 --- a/src/app/engine/foldhaus_serializer.h +++ b/src/app/engine/foldhaus_serializer.h @@ -134,11 +134,17 @@ Serializer_WriteV3Value(serializer* Serializer, u32 IdentIndex, v3 Value) struct parser_error { gs_string Message; + + gs_string FileName; + u32 LineNumber; + parser_error* Next; }; struct parser { + gs_string FileName; + gs_string String; gs_const_string* Identifiers; @@ -160,7 +166,11 @@ internal void Parser_PushErrorF(parser* Parser, char* Format, ...) { parser_error* Error = PushStruct(Parser->Transient, parser_error); + Error->FileName = Parser->FileName; + Error->LineNumber = Parser->Line; + Error->Message = PushString(Parser->Transient, 1024); + PrintF(&Error->Message, "File: %S Line: %d - ", Error->FileName, Error->LineNumber); va_list Args; va_start(Args, Format); @@ -268,11 +278,13 @@ Parser_ReadString(parser* P, u32 IdentIndex) return Parser_ReadString(P, Ident); } -internal gs_string -Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminate = false) +internal bool +Parser_ReadStringValue(parser* P, gs_const_string Ident, gs_string* Output, bool ShouldNullTerminate = false) { + Assert(Output != 0); + // ident: "value"; - gs_string Result = {}; + bool Result = false; if (Parser_AdvanceIfTokenEquals(P, Ident) && Parser_AdvanceIfTokenEquals(P, ConstString(":")) && Parser_AdvanceIfTokenEquals(P, ConstString("\""))) @@ -294,10 +306,12 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminat { StringLength += 1; } - Result = PushStringF(P->Arena, StringLength, "%S", FileString); + + Result = true; + *Output = PushStringF(P->Arena, StringLength, "%S", FileString); if (ShouldNullTerminate) { - NullTerminate(&Result); + NullTerminate(Output); } } else @@ -305,14 +319,25 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminat Parser_PushErrorF(P, "String doesn't have a closing quote, or line doesn't end with a semicolon"); } } - else - { - Parser_PushErrorF(P, "String doesn't begin correctly"); - } return Result; } +internal bool +Parser_ReadStringValue(parser* P, u32 IdentIndex, gs_string* Result, bool ShouldNullTerminate = false) +{ + gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); + return Parser_ReadStringValue(P, Ident, Result, ShouldNullTerminate); +} + +internal gs_string +Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminate = false) +{ + gs_string Result = {0}; + Parser_ReadStringValue(P, Ident, &Result, ShouldNullTerminate); + return Result; +} + internal gs_string Parser_ReadStringValue(parser* P, u32 IdentIndex, bool ShouldNullTerminate = false) { @@ -346,42 +371,66 @@ Parser_ReadCloseStruct(parser* P) return Result; } +internal bool +Parser_ReadNumberString(parser* P, gs_const_string* Output) +{ + Assert(Output != 0); + + bool Success = false; + + if (IsNumericExtended(P->At[0])) + { + char* NumStart = P->At; + while(Parser_AtValidPosition(*P) && IsNumericExtended(P->At[0])) + { + Parser_AdvanceChar(P); + } + + Output->Str = NumStart; + Output->Length = P->At - NumStart; + Success = true; + } + + return Success; +} + internal gs_const_string Parser_ReadNumberString(parser* P) { - gs_const_string Result = {}; - Result.Str = P->At; - while(Parser_AtValidPosition(*P) && IsNumericExtended(P->At[0])) - { - Parser_AdvanceChar(P); - } - Result.Length = P->At - Result.Str; + gs_const_string Result = {0}; + Parser_ReadNumberString(P, &Result); return Result; } -internal u32 -Parser_ReadU32Value(parser* P, gs_const_string Ident) +internal bool +Parser_ReadU32Value(parser* P, gs_const_string Ident, u32* Result) { // ident: value; - u32 Result = 0; + bool Success = false; + if (Parser_AdvanceIfTokenEquals(P, Ident) && Parser_AdvanceIfTokenEquals(P, ConstString(":"))) { gs_const_string NumStr = Parser_ReadNumberString(P); if (Parser_AdvanceIfLineEnd(P)) { - Result = (u32)ParseInt(NumStr); + *Result = (u32)ParseInt(NumStr); + Success = true; } else { Parser_PushErrorF(P, "U32 Value doesn't end with semicolon"); } } - else - { - Parser_PushErrorF(P, "U32 value doesn't begin properly"); - } + return Success; +} + +internal u32 +Parser_ReadU32Value(parser* P, gs_const_string Ident) +{ + u32 Result = 0; + Parser_ReadU32Value(P, Ident, &Result); return Result; } @@ -392,52 +441,72 @@ Parser_ReadU32Value(parser* P, u32 IdentIndex) return Parser_ReadU32Value(P, Ident); } +internal bool +Parser_ReadR32(parser* P, r32* Result) +{ + bool Success = false; + gs_const_string NumStr = {0}; + if (Parser_ReadNumberString(P, &NumStr)) + { + *Result = (r32)ParseFloat(NumStr); + Success = true; + } + return Success; +} + internal r32 Parser_ReadR32(parser* P) { r32 Result = 0; - gs_const_string NumStr = Parser_ReadNumberString(P); - Result = (r32)ParseFloat(NumStr); + Parser_ReadR32(P, &Result); return Result; } -internal r32 -Parser_ReadR32Value(parser* P, gs_const_string Ident) +internal bool +Parser_ReadR32Value(parser* P, gs_const_string Ident, r32* Result) { // ident: value; - r32 Result = 0; + bool Success = false; if (Parser_AdvanceIfTokenEquals(P, Ident) && Parser_AdvanceIfTokenEquals(P, ConstString(":"))) { r32 Value = Parser_ReadR32(P); if (Parser_AdvanceIfLineEnd(P)) { - Result = Value; + *Result = Value; + Success = true; } else { Parser_PushErrorF(P, "R32 Value doesn't end with semicolon"); } } - else - { - Parser_PushErrorF(P, "R32 value doesn't begin properly"); - } + return Success; +} + +internal r32 +Parser_ReadR32Value(parser* P, gs_const_string Ident) +{ + r32 Result = 0; + Parser_ReadR32Value(P, Ident, &Result); return Result; } -internal u32 +internal r32 Parser_ReadR32Value(parser* P, u32 IdentIndex) { + r32 Result = 0; gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); - return Parser_ReadR32Value(P, Ident); + Parser_ReadR32Value(P, Ident, &Result); + return Result; } -internal v3 -Parser_ReadV3Value(parser* P, gs_const_string Ident) +internal bool +Parser_ReadV3Value(parser* P, gs_const_string Ident, v3* Result) { - v3 Result = {0}; + Assert(Result != 0); + bool Success = false; if (Parser_AdvanceIfTokenEquals(P, Ident) && Parser_AdvanceIfTokenEquals(P, ConstString(":")) && Parser_AdvanceIfTokenEquals(P, ConstString("("))) @@ -458,27 +527,35 @@ Parser_ReadV3Value(parser* P, gs_const_string Ident) if (Parser_AdvanceIfTokenEquals(P, ConstString(")")) && Parser_AdvanceIfLineEnd(P)) { - Result.x = X; - Result.y = Y; - Result.z = Z; + Result->x = X; + Result->y = Y; + Result->z = Z; + Success = true; } else { Parser_PushErrorF(P, "V3 Value doesn't end correctly"); } } - else - { - Parser_PushErrorF(P, "V3 Value doesn't begin correctly"); - } + + return Success; +} + +internal v3 +Parser_ReadV3Value(parser* P, gs_const_string Ident) +{ + v3 Result = {0}; + Parser_ReadV3Value(P, Ident, &Result); return Result; } internal v3 Parser_ReadV3Value(parser* P, u32 IdentIndex) { + v3 Result = {0}; gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); - return Parser_ReadV3Value(P, Ident); + Parser_ReadV3Value(P, Ident, &Result); + return Result; } diff --git a/src/app/engine/uart/foldhaus_uart.cpp b/src/app/engine/uart/foldhaus_uart.cpp index 1e7f635..d523f6d 100644 --- a/src/app/engine/uart/foldhaus_uart.cpp +++ b/src/app/engine/uart/foldhaus_uart.cpp @@ -76,7 +76,7 @@ UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assembli TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize); - AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort); + AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort.ConstString); gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 5644aa3..86fb097 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -123,7 +123,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->LedSystem = LedSystemInitialize(Context.ThreadContext.Allocator, 128); #if 1 - gs_const_string SculpturePath = ConstString("data/blumen_lumen_v2.fold"); + gs_const_string SculpturePath = ConstString("data/blumen_lumen_silver_spring.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog); #endif diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index d11e851..653dbe6 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -389,14 +389,21 @@ Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_ case AddressType_ComPort: { - HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1); - if (SerialPort != INVALID_HANDLE_VALUE) + if (BufferAt->ComPort.Length > 0) { - if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) + HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1); + if (SerialPort != INVALID_HANDLE_VALUE) { - BuffersSent += 1; + if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) + { + BuffersSent += 1; + } } } + else + { + OutputDebugStringA("Skipping data buffer because its COM Port isn't set"); + } }break; InvalidDefaultCase; From 85b99b17a25f288169191157e913215eee2d70a4 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 17 Oct 2020 12:43:05 -0700 Subject: [PATCH 38/43] basically removed the need for the meta system from the codebase, and implemented pushing new panel types on a LIFO queue with return memory destinations --- src/app/editor/foldhaus_interface.cpp | 32 ++++--- src/app/editor/foldhaus_panel.h | 86 ++++++++++++++++--- .../foldhaus_panel_animation_timeline.h | 23 +++-- .../editor/panels/foldhaus_panel_dmx_view.h | 2 +- .../editor/panels/foldhaus_panel_file_view.h | 6 +- .../editor/panels/foldhaus_panel_hierarchy.h | 2 +- .../editor/panels/foldhaus_panel_profiler.h | 2 +- .../panels/foldhaus_panel_sculpture_view.h | 3 +- .../editor/panels/foldhaus_panel_types.cpp | 17 ++++ src/app/editor/panels/foldhaus_panel_types.h | 17 ++++ .../{ => assembly}/foldhaus_assembly.cpp | 1 - .../engine/{ => assembly}/foldhaus_assembly.h | 0 .../foldhaus_assembly_parser.cpp | 0 src/app/foldhaus_app.cpp | 5 +- src/app/foldhaus_app.h | 13 +-- src/app/generated/foldhaus_panels_generated.h | 18 ---- src/gs_libs/gs_types.cpp | 10 +++ src/meta/foldhaus_meta.cpp | 1 - 18 files changed, 175 insertions(+), 63 deletions(-) create mode 100644 src/app/editor/panels/foldhaus_panel_types.cpp create mode 100644 src/app/editor/panels/foldhaus_panel_types.h rename src/app/engine/{ => assembly}/foldhaus_assembly.cpp (99%) rename src/app/engine/{ => assembly}/foldhaus_assembly.h (100%) rename src/app/engine/{ => assembly}/foldhaus_assembly_parser.cpp (100%) diff --git a/src/app/editor/foldhaus_interface.cpp b/src/app/editor/foldhaus_interface.cpp index 0c66cf4..4160ab2 100644 --- a/src/app/editor/foldhaus_interface.cpp +++ b/src/app/editor/foldhaus_interface.cpp @@ -20,16 +20,23 @@ enum panel_edit_mode }; internal void -SetPanelDefinition(panel* Panel, s32 NewPanelDefinitionIndex, app_state* State, context Context) +SetPanelType_(panel* Panel, s32 NewPanelTypeIndex, app_state* State, context Context) { - s32 OldPanelDefinitionIndex = Panel->PanelDefinitionIndex; - Panel->PanelDefinitionIndex = NewPanelDefinitionIndex; + + s32 OldPanelDefinitionIndex = Panel_GetCurrentTypeIndex(Panel); + Panel_SetCurrentTypeIndex(Panel, NewPanelTypeIndex, {0}); if(OldPanelDefinitionIndex >= 0) { GlobalPanelDefs[OldPanelDefinitionIndex].Cleanup(Panel, State); } - GlobalPanelDefs[NewPanelDefinitionIndex].Init(Panel, State, Context); +} + +internal void +SetAndInitPanelType(panel* Panel, s32 NewPanelTypeIndex, app_state* State, context Context) +{ + SetPanelType_(Panel, NewPanelTypeIndex, State, Context); + GlobalPanelDefs[NewPanelTypeIndex].Init(Panel, State, Context); } // @@ -250,11 +257,11 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation) SplitPanelHorizontally(Panel, YPercent, &State->PanelSystem); } - Panel->Left->Panel.PanelDefinitionIndex = Panel->PanelDefinitionIndex; - Panel->Left->Panel.PanelStateMemory = Panel->PanelStateMemory; - Panel->Left->Panel.PanelStateMemorySize = Panel->PanelStateMemorySize; + s32 PanelTypeIndex = Panel_GetCurrentTypeIndex(Panel); + gs_data PanelStateMemory = Panel_GetCurrentTypeStateMemory_(Panel); + Panel_SetCurrentTypeIndex(&Panel->Left->Panel, PanelTypeIndex, PanelStateMemory); - SetPanelDefinition(&Panel->Right->Panel, Panel->PanelDefinitionIndex, State, Context); + SetAndInitPanelType(&Panel->Right->Panel, PanelTypeIndex, State, Context); DeactivateCurrentOperationMode(&State->Modes); } @@ -431,7 +438,7 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterB gs_string DefName = MakeString(Def.PanelName, Def.PanelNameLength); if (ui_Button(&State->Interface, DefName, ButtonBounds)) { - SetPanelDefinition(Panel, i, State, Context); + SetAndInitPanelType(Panel, i, State, Context); Panel->PanelSelectionMenuOpen = false; } @@ -449,7 +456,8 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterB internal void RenderPanel(panel* Panel, rect2 PanelBounds, rect2 WindowBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) { - Assert(Panel->PanelDefinitionIndex >= 0); + s32 PanelType = Panel_GetCurrentTypeIndex(Panel); + Assert(PanelType >= 0); rect2 FooterBounds = rect2{ PanelBounds.Min, @@ -460,8 +468,8 @@ RenderPanel(panel* Panel, rect2 PanelBounds, rect2 WindowBounds, render_command_ PanelBounds.Max, }; - panel_definition Definition = GlobalPanelDefs[Panel->PanelDefinitionIndex]; - Definition.Render(*Panel, PanelViewBounds, RenderBuffer, State, Context); + panel_definition Definition = GlobalPanelDefs[PanelType]; + Definition.Render(Panel, PanelViewBounds, RenderBuffer, State, Context); PushRenderOrthographic(RenderBuffer, WindowBounds); DrawPanelFooter(Panel, RenderBuffer, FooterBounds, Mouse, State, Context); diff --git a/src/app/editor/foldhaus_panel.h b/src/app/editor/foldhaus_panel.h index c1a2248..100b230 100644 --- a/src/app/editor/foldhaus_panel.h +++ b/src/app/editor/foldhaus_panel.h @@ -9,8 +9,6 @@ // #ifndef FOLDHAUS_PANEL_H -typedef struct panel panel; - enum panel_split_direction { PanelSplit_NoSplit, @@ -24,9 +22,15 @@ typedef struct panel_entry panel_entry; struct panel { + // TODO(pjs): We want this to be a list, so that you can push sub panels on // and let them return to you, to perform certain tasks, like loading a file - s32 PanelDefinitionIndex; + //s32 PanelDefinitionIndex; +#define PANEL_TYPE_INDICES_COUNT_MAX 4 + s32 TypeIndicesCount; + s32 TypeIndices[PANEL_TYPE_INDICES_COUNT_MAX]; + gs_data ReturnDestMemory[PANEL_TYPE_INDICES_COUNT_MAX]; + gs_data TypeStateMemory[PANEL_TYPE_INDICES_COUNT_MAX]; panel_split_direction SplitDirection; r32 SplitPercent; @@ -35,9 +39,6 @@ struct panel // Probably belongs in a more generalized PanelInterfaceState or something b32 PanelSelectionMenuOpen; - u8* PanelStateMemory; - u32 PanelStateMemorySize; - union{ panel_entry* Left; panel_entry* Top; @@ -119,10 +120,7 @@ TakeNewPanel(panel_system* PanelSystem) panel* Result = 0; panel_entry* FreeEntry = TakeNewPanelEntry(PanelSystem); Result = &FreeEntry->Panel; - *Result = {0}; - Result->PanelDefinitionIndex = -1; - return Result; } @@ -155,6 +153,70 @@ FreePanelAtIndex(s32 Index, panel_system* PanelSystem) PanelSystem->FreeList.Free.Next = EntryToFree; } +internal void +Panel_SetCurrentTypeIndex(panel* Panel, s32 NewPanelType, gs_data TypeStateMemory, gs_data ReturnDestMemory = {0}) +{ + u32 CurrentTypeIndex = 0; + if (Panel->TypeIndicesCount != 0) + { + CurrentTypeIndex = Panel->TypeIndicesCount - 1; + } + else + { + CurrentTypeIndex = Panel->TypeIndicesCount++; + } + + Panel->TypeIndices[CurrentTypeIndex] = NewPanelType; + Panel->TypeStateMemory[CurrentTypeIndex] = TypeStateMemory; + Panel->ReturnDestMemory[CurrentTypeIndex] = ReturnDestMemory; +} + +internal s32 +Panel_GetCurrentTypeIndex(panel* Panel) +{ + s32 Result = -1; + if (Panel->TypeIndicesCount != 0) + { + Result = Panel->TypeIndices[Panel->TypeIndicesCount - 1]; + } + return Result; +} + +internal void +Panel_SetCurrentTypeStateMemory(panel* Panel, gs_data StateMemory) +{ + u32 CurrentTypeIndex = 0; + if (Panel->TypeIndicesCount != 0) + { + CurrentTypeIndex = Panel->TypeIndicesCount - 1; + } + else + { + CurrentTypeIndex = Panel->TypeIndicesCount++; + } + Panel->TypeStateMemory[CurrentTypeIndex] = StateMemory; +} + +#define Panel_GetCurrentTypeStateMemory(p, type) (type*)Panel_GetCurrentTypeStateMemory_(p).Memory +internal gs_data +Panel_GetCurrentTypeStateMemory_(panel* Panel) +{ + gs_data Result = {0}; + if (Panel->TypeIndicesCount != 0) + { + Result = Panel->TypeStateMemory[Panel->TypeIndicesCount - 1]; + } + return Result; +} + +internal void +Panel_PushTypeWithReturn(panel* Panel, s32 NewPanelType, gs_data ReturnDestMemory) +{ + Assert(Panel->TypeIndicesCount < PANEL_TYPE_INDICES_COUNT_MAX); + u32 NewTypeIndex = Panel->TypeIndicesCount++; + Panel_SetCurrentTypeIndex(Panel, NewPanelType, ReturnDestMemory); +} + internal void SplitPanel(panel* Parent, r32 Percent, panel_split_direction SplitDirection, panel_system* PanelSystem) { @@ -163,11 +225,13 @@ SplitPanel(panel* Parent, r32 Percent, panel_split_direction SplitDirection, pan Parent->SplitDirection = SplitDirection; Parent->SplitPercent = Percent; + s32 ParentTypeIndex = Panel_GetCurrentTypeIndex(Parent); + gs_data ParentStateMemory = Panel_GetCurrentTypeStateMemory_(Parent); Parent->Left = TakeNewPanelEntry(PanelSystem); - Parent->Left->Panel.PanelDefinitionIndex = Parent->PanelDefinitionIndex; + Panel_SetCurrentTypeIndex(&Parent->Left->Panel, ParentTypeIndex, ParentStateMemory); Parent->Right = TakeNewPanelEntry(PanelSystem); - Parent->Right->Panel.PanelDefinitionIndex = Parent->PanelDefinitionIndex; + Panel_SetCurrentTypeIndex(&Parent->Right->Panel, ParentTypeIndex, ParentStateMemory); } } diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 6f4f5cf..5e8bddb 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -6,7 +6,7 @@ #ifndef FOLDHAUS_PANEL_ANIMATION_TIMELINE_H // Colors -global v4 TimeSliderColor = v4{.36f, .52f, .78f, 1.f}; +global v4 TimeSliderColor = GreenV4; //v4{.36f, .52f, .78f, 1.f}; // struct animation_timeline_state @@ -288,7 +288,8 @@ AnimationTimeline_Init(panel* Panel, app_state* State, context Context) animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); animation_timeline_state* TimelineState = PushStruct(&State->Permanent, animation_timeline_state); TimelineState->VisibleRange = ActiveAnim->PlayableRange; - Panel->PanelStateMemory = (u8*)TimelineState; + + Panel_SetCurrentTypeStateMemory(Panel, StructToData(TimelineState, animation_timeline_state)); } GSMetaTag(panel_cleanup); @@ -595,9 +596,9 @@ DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedA GSMetaTag(panel_render); GSMetaTag(panel_type_animation_timeline); internal void -AnimationTimeline_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - animation_timeline_state* TimelineState = (animation_timeline_state*)Panel.PanelStateMemory; + animation_timeline_state* TimelineState = Panel_GetCurrentTypeStateMemory(Panel, animation_timeline_state); // TODO(pjs): SelectedAnimationBlockHandle should be a property of animation_timeline_state // unless its used elsewhere. Audit later gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; @@ -611,7 +612,7 @@ AnimationTimeline_Render(panel Panel, rect2 PanelBounds, render_command_buffer* ui_FillRect(Interface, TitleBarBounds, Interface->Style.PanelBGColors[0]); ui_layout TitleBarLayout = ui_CreateLayout(*Interface, TitleBarBounds); - ui_StartRow(&TitleBarLayout, 3); + ui_StartRow(&TitleBarLayout, 4); { if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Pause"))) { @@ -628,6 +629,18 @@ AnimationTimeline_Render(panel Panel, rect2 PanelBounds, render_command_buffer* State->AnimationSystem.TimelineShouldAdvance = false; State->AnimationSystem.CurrentFrame = 0; } + + if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Load"))) + { + // TODO(pjs): You were working on #6 on your todo list. + // below is a "write the interface first" example of how you'd like to be able to + // activate a file panel from within another panel. + gs_data ReturnDestination = {}; + Panel_PushTypeWithReturn(Panel, PanelType_FileView, ReturnDestination); + // TODO(pjs): I think we want to be able to specify a return command that gets called when the + // pushed panel state returns to this one + // something like: AnimPanel_HandleLoadedAnimationFile + } } ui_EndRow(&TitleBarLayout); diff --git a/src/app/editor/panels/foldhaus_panel_dmx_view.h b/src/app/editor/panels/foldhaus_panel_dmx_view.h index 7d9614e..d7213ee 100644 --- a/src/app/editor/panels/foldhaus_panel_dmx_view.h +++ b/src/app/editor/panels/foldhaus_panel_dmx_view.h @@ -74,7 +74,7 @@ DrawSACNUniversePixels (render_command_buffer* RenderBuffer, sacn_universe* ToDr GSMetaTag(panel_render); GSMetaTag(panel_type_dmx_view); internal void -DMXView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +DMXView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { #if 0 // :NoLongerFunctionalSACNCodeButThatsOk diff --git a/src/app/editor/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h index 3db4c08..a1b9d98 100644 --- a/src/app/editor/panels/foldhaus_panel_file_view.h +++ b/src/app/editor/panels/foldhaus_panel_file_view.h @@ -55,7 +55,7 @@ FileView_Init(panel* Panel, app_state* State, context Context) { // TODO: :FreePanelMemory file_view_state* FileViewState = PushStruct(&State->Permanent, file_view_state); - Panel->PanelStateMemory = (u8*)FileViewState; + Panel_SetCurrentTypeStateMemory(Panel, StructToData(FileViewState, file_view_state)); FileViewState->FileNamesArena = CreateMemoryArena(Context.ThreadContext.Allocator); FileViewUpdateWorkingDirectory(ConstString("."), FileViewState, Context); } @@ -71,9 +71,9 @@ FileView_Cleanup(panel* Panel, app_state* State) GSMetaTag(panel_render); GSMetaTag(panel_type_file_view); internal void -FileView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - file_view_state* FileViewState = (file_view_state*)Panel.PanelStateMemory; + file_view_state* FileViewState = Panel_GetCurrentTypeStateMemory(Panel, file_view_state); ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); // Header diff --git a/src/app/editor/panels/foldhaus_panel_hierarchy.h b/src/app/editor/panels/foldhaus_panel_hierarchy.h index b8ad772..3654cdb 100644 --- a/src/app/editor/panels/foldhaus_panel_hierarchy.h +++ b/src/app/editor/panels/foldhaus_panel_hierarchy.h @@ -27,7 +27,7 @@ HierarchyView_Cleanup(panel* Panel, app_state* State) GSMetaTag(panel_render); GSMetaTag(panel_type_hierarchy); internal void -HierarchyView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +HierarchyView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); gs_string TempString = PushString(State->Transient, 256); diff --git a/src/app/editor/panels/foldhaus_panel_profiler.h b/src/app/editor/panels/foldhaus_panel_profiler.h index e7ee509..90fbafa 100644 --- a/src/app/editor/panels/foldhaus_panel_profiler.h +++ b/src/app/editor/panels/foldhaus_panel_profiler.h @@ -137,7 +137,7 @@ RenderProfiler_ListVisualization(ui_interface* Interface, ui_layout Layout, debu GSMetaTag(panel_render); GSMetaTag(panel_type_profiler); internal void -ProfilerView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +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); diff --git a/src/app/editor/panels/foldhaus_panel_sculpture_view.h b/src/app/editor/panels/foldhaus_panel_sculpture_view.h index a4f7246..6bc24a5 100644 --- a/src/app/editor/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/editor/panels/foldhaus_panel_sculpture_view.h @@ -156,7 +156,7 @@ SculptureView_WorldToScreenPosition(v4 WorldPosition, camera Camera, rect2 Panel GSMetaTag(panel_render); GSMetaTag(panel_type_sculpture_view); internal void -SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +SculptureView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { DEBUG_TRACK_SCOPE(RenderSculpture); State->Camera.AspectRatio = RectAspectRatio(PanelBounds); @@ -203,7 +203,6 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend assembly Assembly = State->Assemblies.Values[0]; led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex); - //__debugbreak(); v4 LedPosition = LedBuffer->Positions[FocusPixel]; v2 LedOnScreenPosition = SculptureView_WorldToScreenPosition(LedPosition, State->Camera, PanelBounds); diff --git a/src/app/editor/panels/foldhaus_panel_types.cpp b/src/app/editor/panels/foldhaus_panel_types.cpp new file mode 100644 index 0000000..9c006fa --- /dev/null +++ b/src/app/editor/panels/foldhaus_panel_types.cpp @@ -0,0 +1,17 @@ +// +// File: foldhaus_panel_types.cpp +// Author: Peter Slattery +// Creation Date: 2020-10-17 +// +#ifndef FOLDHAUS_PANEL_TYPES_CPP +global s32 GlobalPanelDefsCount = 6; +global panel_definition GlobalPanelDefs[] = { + { "File View", 9, FileView_Init, FileView_Cleanup, FileView_Render, FileView_Commands, FileView_CommandsCount }, + { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands, SculptureView_CommandsCount }, + { "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, AnimationTimeline_Commands, AnimationTimeline_CommandsCount }, + { "Dmx View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, DMXView_Commands, DMXView_CommandsCount }, + { "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, HierarchyView_Commands, HierarchyView_CommandsCount }, + { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, ProfilerView_Commands, ProfilerView_CommandsCount }, +}; +#define FOLDHAUS_PANEL_TYPES_CPP +#endif // FOLDHAUS_PANEL_TYPES_CPP \ No newline at end of file diff --git a/src/app/editor/panels/foldhaus_panel_types.h b/src/app/editor/panels/foldhaus_panel_types.h new file mode 100644 index 0000000..7b1164b --- /dev/null +++ b/src/app/editor/panels/foldhaus_panel_types.h @@ -0,0 +1,17 @@ +// +// File: foldhaus_panel_types.h +// Author: Peter Slattery +// Creation Date: 2020-10-17 +// +#ifndef FOLDHAUS_PANEL_TYPES_H +enum panel_type { + PanelType_FileView, + PanelType_SculptureView, + PanelType_AnimationTimeline, + PanelType_DMXView, + PanelType_HierarchyView, + PanelType_NodeGraph, + PanelType_ProfilerView, +}; +#define FOLDHAUS_PANEL_TYPES_H +#endif // FOLDHAUS_PANEL_TYPES_H \ No newline at end of file diff --git a/src/app/engine/foldhaus_assembly.cpp b/src/app/engine/assembly/foldhaus_assembly.cpp similarity index 99% rename from src/app/engine/foldhaus_assembly.cpp rename to src/app/engine/assembly/foldhaus_assembly.cpp index f183f4c..1d68fdb 100644 --- a/src/app/engine/foldhaus_assembly.cpp +++ b/src/app/engine/assembly/foldhaus_assembly.cpp @@ -163,7 +163,6 @@ Assembly_ConstructStrip(assembly* Assembly, led_buffer* LedBuffer, v2_strip* Str strip_gen_sequence Sequence = GenData.Sequence; for (u32 i = 0; i < Sequence.ElementsCount; i++) { - __debugbreak(); strip_gen_data SegmentGenData = Sequence.Elements[i]; LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, SegmentGenData, RootPosition, LedStartIndex + LedsAdded); } diff --git a/src/app/engine/foldhaus_assembly.h b/src/app/engine/assembly/foldhaus_assembly.h similarity index 100% rename from src/app/engine/foldhaus_assembly.h rename to src/app/engine/assembly/foldhaus_assembly.h diff --git a/src/app/engine/foldhaus_assembly_parser.cpp b/src/app/engine/assembly/foldhaus_assembly_parser.cpp similarity index 100% rename from src/app/engine/foldhaus_assembly_parser.cpp rename to src/app/engine/assembly/foldhaus_assembly_parser.cpp diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 86fb097..b992ff4 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -162,7 +162,7 @@ INITIALIZE_APPLICATION(InitializeApplication) InitializePanelSystem(&State->PanelSystem); panel* Panel = TakeNewPanel(&State->PanelSystem); - SetPanelDefinition(Panel, PanelType_SculptureView, State, Context); + SetAndInitPanelType(Panel, PanelType_SculptureView, State, Context); } internal void @@ -184,7 +184,8 @@ HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse if (!PanelWithMouseOverIt.Panel) { return; } State->HotPanel = PanelWithMouseOverIt.Panel; - panel_definition PanelDefinition = GlobalPanelDefs[PanelWithMouseOverIt.Panel->PanelDefinitionIndex]; + s32 PanelTypeIndex = Panel_GetCurrentTypeIndex(PanelWithMouseOverIt.Panel); + panel_definition PanelDefinition = GlobalPanelDefs[PanelTypeIndex]; if (!PanelDefinition.InputCommands) { return; } ActiveCommands.Commands = PanelDefinition.InputCommands; diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 9fe672a..a368bf7 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -17,8 +17,8 @@ #include "engine/foldhaus_network_ordering.h" -#include "engine/foldhaus_assembly.h" -#include "engine/foldhaus_assembly_parser.cpp" +#include "engine/assembly/foldhaus_assembly.h" +#include "engine/assembly/foldhaus_assembly_parser.cpp" #include "engine/sacn/foldhaus_sacn.h" #include "engine/uart/foldhaus_uart.h" @@ -70,7 +70,7 @@ struct app_state internal void OpenColorPicker(app_state* State, v4* Address); -#include "engine/foldhaus_assembly.cpp" +#include "engine/assembly/foldhaus_assembly.cpp" // BEGIN TEMPORARY PATTERNS internal void @@ -215,7 +215,7 @@ typedef PANEL_INIT_PROC(panel_init_proc); #define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State) typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); -#define PANEL_RENDER_PROC(name) void name(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +#define PANEL_RENDER_PROC(name) void name(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) typedef PANEL_RENDER_PROC(panel_render_proc); // NOTE(Peter): This is used by the meta system to generate panel type info @@ -237,6 +237,8 @@ animation_clip GlobalAnimationClips[] = { { "Test Pattern Three", 18, TestPatternThree }, }; +#include "editor/panels/foldhaus_panel_types.h" + #include "editor/panels/foldhaus_panel_sculpture_view.h" #include "editor/panels/foldhaus_panel_profiler.h" #include "editor/panels/foldhaus_panel_dmx_view.h" @@ -244,7 +246,8 @@ animation_clip GlobalAnimationClips[] = { #include "editor/panels/foldhaus_panel_hierarchy.h" #include "editor/panels/foldhaus_panel_file_view.h" -#include "generated/foldhaus_panels_generated.h" +#include "editor/panels/foldhaus_panel_types.cpp" +//#include "generated/foldhaus_panels_generated.h" #include "editor/foldhaus_interface.cpp" diff --git a/src/app/generated/foldhaus_panels_generated.h b/src/app/generated/foldhaus_panels_generated.h index 67ca2a3..e69de29 100644 --- a/src/app/generated/foldhaus_panels_generated.h +++ b/src/app/generated/foldhaus_panels_generated.h @@ -1,18 +0,0 @@ -enum panel_type { - PanelType_FileView, - PanelType_SculptureView, - PanelType_AnimationTimeline, - PanelType_DMXView, - PanelType_HierarchyView, - PanelType_NodeGraph, - PanelType_ProfilerView, -}; -global s32 GlobalPanelDefsCount = 6; -global panel_definition GlobalPanelDefs[] = { - { "File View", 9, FileView_Init, FileView_Cleanup, FileView_Render, FileView_Commands, FileView_CommandsCount }, - { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands, SculptureView_CommandsCount }, - { "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, AnimationTimeline_Commands, AnimationTimeline_CommandsCount }, - { "Dmx View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, DMXView_Commands, DMXView_CommandsCount }, - { "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, HierarchyView_Commands, HierarchyView_CommandsCount }, - { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, ProfilerView_Commands, ProfilerView_CommandsCount }, -}; diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp index bbcb97a..12bd157 100644 --- a/src/gs_libs/gs_types.cpp +++ b/src/gs_libs/gs_types.cpp @@ -5,6 +5,16 @@ // #ifndef GS_TYPES_CPP +#define StructToData(ptr, type) StructToData_((u8*)(ptr), sizeof(type)) +internal gs_data +StructToData_(u8* Memory, u64 Size) +{ + gs_data Result = {0}; + Result.Memory = Memory; + Result.Size = Size; + return Result; +} + internal u32 U32DivideRoundUp (u32 A, u32 B) { diff --git a/src/meta/foldhaus_meta.cpp b/src/meta/foldhaus_meta.cpp index 47eb1a1..f298f2d 100644 --- a/src/meta/foldhaus_meta.cpp +++ b/src/meta/foldhaus_meta.cpp @@ -348,7 +348,6 @@ int main(int ArgCount, char* Args[]) FinishMetaprogram(&Meta); - //__debugbreak(); return 0; } From 121e9efa93f525b4dccbc4021c9f1a85b8d56866 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 17 Oct 2020 13:12:40 -0700 Subject: [PATCH 39/43] Fixed animations so they are no longer updating when the current frame is not in range --- src/app/editor/foldhaus_panel.h | 24 +++++++++---------- src/app/engine/animation/foldhaus_animation.h | 16 +++++++------ src/app/foldhaus_app.cpp | 2 +- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/app/editor/foldhaus_panel.h b/src/app/editor/foldhaus_panel.h index 100b230..190a118 100644 --- a/src/app/editor/foldhaus_panel.h +++ b/src/app/editor/foldhaus_panel.h @@ -182,6 +182,18 @@ Panel_GetCurrentTypeIndex(panel* Panel) return Result; } +#define Panel_GetCurrentTypeStateMemory(p, type) (type*)Panel_GetCurrentTypeStateMemory_(p).Memory +internal gs_data +Panel_GetCurrentTypeStateMemory_(panel* Panel) +{ + gs_data Result = {0}; + if (Panel->TypeIndicesCount != 0) + { + Result = Panel->TypeStateMemory[Panel->TypeIndicesCount - 1]; + } + return Result; +} + internal void Panel_SetCurrentTypeStateMemory(panel* Panel, gs_data StateMemory) { @@ -197,18 +209,6 @@ Panel_SetCurrentTypeStateMemory(panel* Panel, gs_data StateMemory) Panel->TypeStateMemory[CurrentTypeIndex] = StateMemory; } -#define Panel_GetCurrentTypeStateMemory(p, type) (type*)Panel_GetCurrentTypeStateMemory_(p).Memory -internal gs_data -Panel_GetCurrentTypeStateMemory_(panel* Panel) -{ - gs_data Result = {0}; - if (Panel->TypeIndicesCount != 0) - { - Result = Panel->TypeStateMemory[Panel->TypeIndicesCount - 1]; - } - return Result; -} - internal void Panel_PushTypeWithReturn(panel* Panel, s32 NewPanelType, gs_data ReturnDestMemory) { diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 00d4278..7650ce0 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -260,10 +260,10 @@ SecondsToFrames(r32 Seconds, animation_system System) return Result; } -inline b32 +inline bool FrameIsInRange(frame_range Range, s32 Frame) { - b32 Result = (Frame >= Range.Min) && (Frame <= Range.Max); + bool Result = (Frame >= Range.Min) && (Frame <= Range.Max); return Result; } @@ -348,6 +348,7 @@ AnimationSystem_CalculateAnimationFrame(animation_system* System, gs_memory_aren Result.BlocksCountMax = ActiveAnim->Layers.Count; Result.Blocks = PushArray(Arena, animation_block, Result.BlocksCountMax); Result.BlocksFilled = PushArray(Arena, b8, Result.BlocksCountMax); + ZeroArray(Result.BlocksFilled, b8, Result.BlocksCountMax); for (u32 i = 0; i < ActiveAnim->Blocks.Used; i++) { @@ -356,11 +357,12 @@ AnimationSystem_CalculateAnimationFrame(animation_system* System, gs_memory_aren animation_block Block = BlockEntry->Value; - if (FrameIsInRange(Block.Range, System->CurrentFrame)){ continue; } - - Result.BlocksFilled[Block.Layer] = true; - Result.Blocks[Block.Layer] = Block; - Result.BlocksCount++; + if (FrameIsInRange(Block.Range, System->CurrentFrame)) + { + Result.BlocksFilled[Block.Layer] = true; + Result.Blocks[Block.Layer] = Block; + Result.BlocksCount++; + } } return Result; diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index b992ff4..8c028a9 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -258,7 +258,7 @@ UPDATE_AND_RENDER(UpdateAndRender) } s32 CurrentFrame = State->AnimationSystem.CurrentFrame; - if (CurrentFrame != State->AnimationSystem.LastUpdatedFrame) + if (true || CurrentFrame != State->AnimationSystem.LastUpdatedFrame) { State->AnimationSystem.LastUpdatedFrame = CurrentFrame; r32 FrameTime = CurrentFrame * State->AnimationSystem.SecondsPerFrame; From 8eb3044422bf393addd70eb531dd5181b20c13e1 Mon Sep 17 00:00:00 2001 From: PS Date: Sun, 18 Oct 2020 13:57:04 -0700 Subject: [PATCH 40/43] implemented an animation handle system for identifying animation blocks --- .../foldhaus_panel_animation_timeline.h | 60 +++++----- src/app/engine/animation/foldhaus_animation.h | 104 ++++++++++++++---- src/app/foldhaus_app.cpp | 6 +- src/app/foldhaus_app.h | 2 +- src/app/foldhaus_platform.h | 19 ++-- 5 files changed, 127 insertions(+), 64 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 5e8bddb..e242a12 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -33,18 +33,18 @@ GetXPositionFromFrameInAnimationPanel (u32 Frame, rect2 PanelBounds, frame_range return XPositionAtFrame; } -internal gs_list_handle +internal handle AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, u32 LayerHandle, animation_system* System) { u32 NewBlockStart = System->CurrentFrame; u32 NewBlockEnd = NewBlockStart + SecondsToFrames(3, *System); animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System); - gs_list_handle Result = Animation_AddBlock(ActiveAnim, NewBlockStart, NewBlockEnd, AnimationProcHandle, LayerHandle); - return Result; + handle AnimHandle = Animation_AddBlock(ActiveAnim, NewBlockStart, NewBlockEnd, AnimationProcHandle, LayerHandle); + return AnimHandle; } internal void -SelectAnimationBlock(gs_list_handle BlockHandle, app_state* State) +SelectAnimationBlock(handle BlockHandle, app_state* State) { State->SelectedAnimationBlockHandle = BlockHandle; } @@ -57,11 +57,16 @@ DeselectCurrentAnimationBlock(app_state* State) FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand) { - if(ListHandleIsValid(State->SelectedAnimationBlockHandle)) + handle SelectedAnimHandle = State->SelectedAnimationBlockHandle; + animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); + if(SelectedAnimHandle.Index < ActiveAnim->Blocks_.Count && + ActiveAnim->Blocks_.Generations[SelectedAnimHandle.Index] == SelectedAnimHandle.Generation) { - animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); Animation_RemoveBlock(ActiveAnim, State->SelectedAnimationBlockHandle); State->SelectedAnimationBlockHandle = {0}; + // TODO(pjs): Introduce an animation_block_selection in this file + // it should have a handle to the animation, block, and a HasSelection flag + // as it is now, you kind of always have the first block selected } } @@ -153,7 +158,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) u32 FrameAtMouseX = GetFrameFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->VisibleRange); s32 FrameOffset = (s32)FrameAtMouseX - (s32)FrameAtMouseDownX; - animation_block* AnimationBlock = ActiveAnim->Blocks.GetElementWithHandle(State->SelectedAnimationBlockHandle); + animation_block* AnimationBlock = Animation_GetBlockFromHandle(ActiveAnim, State->SelectedAnimationBlockHandle); if (!AnimationBlock) { EndCurrentOperationMode(State, {}, Mouse, Context); @@ -243,7 +248,7 @@ input_command DragAnimationClipCommands [] = { }; internal void -SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range VisibleRange, rect2 TimelineBounds, app_state* State) +SelectAndBeginDragAnimationBlock(handle BlockHandle, frame_range VisibleRange, rect2 TimelineBounds, app_state* State) { SelectAnimationBlock(BlockHandle, State); @@ -256,7 +261,7 @@ SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range Visible OpState->TimelineBounds = TimelineBounds; OpState->VisibleRange = VisibleRange; - animation_block* SelectedBlock = ActiveAnim->Blocks.GetElementWithHandle(BlockHandle); + animation_block* SelectedBlock = Animation_GetBlockFromHandle(ActiveAnim, BlockHandle); OpState->ClipRange = SelectedBlock->Range; } // ------------------- @@ -269,7 +274,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand) frame_range Range = ActiveAnim->PlayableRange; u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel.Bounds, Range); - gs_list_handle NewBlockHandle = Animation_AddBlock(ActiveAnim, MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, State->SelectedAnimationLayer); + handle NewBlockHandle = Animation_AddBlock(ActiveAnim, MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, State->SelectedAnimationLayer); SelectAnimationBlock(NewBlockHandle, State); } @@ -488,11 +493,11 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V return BlockBounds; } -internal gs_list_handle -DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect2 PanelBounds, gs_list_handle SelectedBlockHandle, ui_interface* Interface, app_state* State) +internal handle +DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect2 PanelBounds, handle SelectedBlockHandle, ui_interface* Interface, app_state* State) { gs_string Tempgs_string = PushString(State->Transient, 256); - gs_list_handle Result = SelectedBlockHandle; + handle Result = SelectedBlockHandle; // TODO(pjs): Animation Selection animation CurrAnimation = AnimationSystem->Animations.Values[0]; @@ -517,38 +522,35 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta // Animation Blocks b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState); - gs_list_handle DragBlockHandle = {0}; - for (u32 i = 0; i < CurrAnimation.Blocks.Used; i++) + handle DragBlockHandle = {0}; + for (u32 i = 0; i < CurrAnimation.Blocks_.Count; i++) { - gs_list_entry* AnimationBlockEntry = CurrAnimation.Blocks.GetEntryAtIndex(i); - if (EntryIsFree(AnimationBlockEntry)) { continue; } - - gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle; - animation_block AnimationBlockAt = AnimationBlockEntry->Value; + animation_block* AnimationBlockAt = CurrAnimation.Blocks_.Values + i; // If either end is in the range, we should draw it - b32 RangeIsVisible = (FrameIsInRange(AdjustedViewRange, AnimationBlockAt.Range.Min) || - FrameIsInRange(AdjustedViewRange, AnimationBlockAt.Range.Max)); + b32 RangeIsVisible = (FrameIsInRange(AdjustedViewRange, AnimationBlockAt->Range.Min) || + FrameIsInRange(AdjustedViewRange, AnimationBlockAt->Range.Max)); // If neither end is in the range, but the ends surround the visible range, // we should still draw it. - RangeIsVisible |= (AnimationBlockAt.Range.Min <= AdjustedViewRange.Min && - AnimationBlockAt.Range.Max>= AdjustedViewRange.Max); + RangeIsVisible |= (AnimationBlockAt->Range.Min <= AdjustedViewRange.Min && + AnimationBlockAt->Range.Max>= AdjustedViewRange.Max); if (RangeIsVisible) { v4 BlockColor = BlackV4; - if (GSListHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) + if (SelectedBlockHandle.Index == i && SelectedBlockHandle.Generation == CurrAnimation.Blocks_.Generations[i]) { BlockColor = PinkV4; } - rect2 BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer); + rect2 BlockBounds = DrawAnimationBlock(*AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer); if (PointIsInRect(BlockBounds, Interface->Mouse.Pos)) { - DragBlockHandle = CurrentBlockHandle; + DragBlockHandle.Index = i; + DragBlockHandle.Generation = CurrAnimation.Blocks_.Generations[i]; } } } - if (MouseDownAndNotHandled && ListHandleIsValid(DragBlockHandle)) + if (MouseDownAndNotHandled && Handle_IsValid(DragBlockHandle)) { MouseDownAndNotHandled = false; SelectAndBeginDragAnimationBlock(DragBlockHandle, AdjustedViewRange, TimelineBounds, State); @@ -601,7 +603,7 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* animation_timeline_state* TimelineState = Panel_GetCurrentTypeStateMemory(Panel, animation_timeline_state); // TODO(pjs): SelectedAnimationBlockHandle should be a property of animation_timeline_state // unless its used elsewhere. Audit later - gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; + handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; ui_interface* Interface = &State->Interface; animation_system* AnimationSystem = &State->AnimationSystem; diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 7650ce0..45037af 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -21,6 +21,14 @@ struct animation_block u32 Layer; }; +struct animation_block_array +{ + u32* Generations; + animation_block* Values; + u32 Count; + u32 CountMax; +}; + enum blend_mode { BlendMode_Overwrite, @@ -55,6 +63,7 @@ struct animation anim_layer_array Layers; gs_list Blocks; + animation_block_array Blocks_; frame_range PlayableRange; }; @@ -154,6 +163,42 @@ global gs_const_string AnimationFieldStrings[] = { ConstString("animation_name"),// AnimField_BlockAnimName }; +////////////////////////// +// +// Anim Block Array + +internal animation_block_array +AnimBlockArray_Create(gs_memory_arena* Storage, u32 CountMax) +{ + animation_block_array Result = {0}; + Result.CountMax = CountMax; + Result.Values = PushArray(Storage, animation_block, Result.CountMax); + Result.Generations = PushArray(Storage, u32, Result.CountMax); + return Result; +} + +internal handle +AnimBlockArray_Push(animation_block_array* Array, animation_block Value) +{ + Assert(Array->Count < Array->CountMax); + handle Result = {0}; + Result.Index = Array->Count++; + // NOTE(pjs): pre-increment so that generation 0 is always invalid + Result.Generation = ++Array->Generations[Result.Index]; + + Array->Values[Result.Index] = Value; + + return Result; +} + +internal void +AnimBlockArray_Remove(animation_block_array* Array, handle Handle) +{ + Assert(Handle.Index < Array->Count); + Assert(Handle_IsValid(Handle)); + Array->Generations[Handle.Index]++; +} + ////////////////////////// // // Anim Layers Array @@ -176,7 +221,7 @@ AnimLayerArray_Push(anim_layer_array* Array, anim_layer Value) return Index; } -internal u32 +internal void AnimLayerArray_Remove(anim_layer_array* Array, u32 Index) { Assert(Index < Array->Count); @@ -249,6 +294,41 @@ Animation_RemoveLayer (animation* Animation, u32 LayerIndex) } } +internal handle +Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, u32 AnimationProcHandle, u32 LayerIndex) +{ + Assert(LayerIndex < Animation->Layers.Count); + + animation_block NewBlock = {0}; + NewBlock.Range.Min = StartFrame; + NewBlock.Range.Max = EndFrame; + NewBlock.AnimationProcHandle = AnimationProcHandle; + NewBlock.Layer = LayerIndex; + + handle Handle = AnimBlockArray_Push(&Animation->Blocks_, NewBlock); + return Handle; +} + +internal void +Animation_RemoveBlock(animation* Animation, handle AnimHandle) +{ + AnimBlockArray_Remove(&Animation->Blocks_, AnimHandle); +} + +internal animation_block* +Animation_GetBlockFromHandle(animation* Animation, handle AnimHandle) +{ + animation_block* Result = 0; + + if (AnimHandle.Generation != 0 && + Animation->Blocks_.Generations[AnimHandle.Index] == AnimHandle.Generation) + { + Result = Animation->Blocks_.Values + AnimHandle.Index; + } + + return Result; +} + ////////////////////////// // // @@ -306,28 +386,6 @@ ClampFrameToRange(s32 Frame, frame_range Range) // Blocks -internal gs_list_handle -Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, u32 AnimationProcHandle, u32 LayerIndex) -{ - Assert(LayerIndex < Animation->Layers.Count); - - animation_block NewBlock = {0}; - NewBlock.Range.Min = StartFrame; - NewBlock.Range.Max = EndFrame; - NewBlock.AnimationProcHandle = AnimationProcHandle; - NewBlock.Layer = LayerIndex; - - gs_list_handle Result = Animation->Blocks.PushElementOnList(NewBlock); - return Result; -} - -internal void -Animation_RemoveBlock(animation* Animation, gs_list_handle AnimationBlockHandle) -{ - Assert(ListHandleIsValid(AnimationBlockHandle)); - Animation->Blocks.FreeElementWithHandle(AnimationBlockHandle); -} - // Layers // System diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 8c028a9..744e4f1 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -145,8 +145,8 @@ INITIALIZE_APPLICATION(InitializeApplication) animation Anim = {0}; Anim.Name = PushStringF(&State->Permanent, 256, "test_anim_one"); - Anim.Layers.CountMax = 8; - Anim.Layers.Values = PushArray(State->AnimationSystem.Storage, anim_layer, Anim.Layers.CountMax); + Anim.Layers = AnimLayerArray_Create(State->AnimationSystem.Storage, 8); + Anim.Blocks_ = AnimBlockArray_Create(State->AnimationSystem.Storage, 8); Anim.PlayableRange.Min = 0; Anim.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem); Animation_AddLayer(&Anim, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem); @@ -258,7 +258,7 @@ UPDATE_AND_RENDER(UpdateAndRender) } s32 CurrentFrame = State->AnimationSystem.CurrentFrame; - if (true || CurrentFrame != State->AnimationSystem.LastUpdatedFrame) + if (CurrentFrame != State->AnimationSystem.LastUpdatedFrame) { State->AnimationSystem.LastUpdatedFrame = CurrentFrame; r32 FrameTime = CurrentFrame * State->AnimationSystem.SecondsPerFrame; diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index a368bf7..689f4d0 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -64,7 +64,7 @@ struct app_state camera Camera; // TODO(Peter): move into the sculpture view r32 PixelsToWorldScale; - gs_list_handle SelectedAnimationBlockHandle; // TODO(Peter): move into animation panel + handle SelectedAnimationBlockHandle; // TODO(Peter): move into animation panel u32 SelectedAnimationLayer; // TODO(Peter): move into animation panel }; diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index 96a7ec7..e5db04c 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -12,21 +12,24 @@ #include "..\gs_libs\gs_types.h" #include "..\gs_libs\gs_types.cpp" -//#define GS_LANGUAGE_NO_PROFILER_DEFINES -//#include "..\gs_libs\gs_language.h" +struct handle +{ + u32 Generation; + u32 Index; +}; +inline bool +Handle_IsValid(handle Handle) +{ + bool Result = (Handle.Generation != 0); + return Result; +} -//#include "..\gs_libs\gs_radix_sort.h" #include "..\gs_libs\gs_list.h" #include "..\gs_libs\gs_bucket.h" -//#define GS_MEMORY_TRACK_ALLOCATIONS -//#include "..\gs_libs\gs_memory_arena.h" - #include "..\gs_libs\gs_string.h" - - #include "foldhaus_debug.h" global debug_services* GlobalDebugServices; From 5c183d9c5fe6eba63ecc58d70aa070b03cd71b9a Mon Sep 17 00:00:00 2001 From: PS Date: Sun, 18 Oct 2020 15:31:53 -0700 Subject: [PATCH 41/43] implemented switching to a file browser, used it in the animation window and in the assembly hierarchy, and moved everything over to a linear array of animation blocks --- src/app/editor/foldhaus_interface.cpp | 36 +--- src/app/editor/foldhaus_panel.h | 188 +++++++++++------- .../foldhaus_panel_animation_timeline.h | 36 ++-- .../editor/panels/foldhaus_panel_file_view.h | 16 +- .../editor/panels/foldhaus_panel_hierarchy.h | 24 +-- src/app/engine/animation/foldhaus_animation.h | 90 +++++---- .../foldhaus_animation_serializer.cpp | 12 +- src/app/foldhaus_app.cpp | 8 +- src/app/foldhaus_app.h | 30 +-- 9 files changed, 222 insertions(+), 218 deletions(-) diff --git a/src/app/editor/foldhaus_interface.cpp b/src/app/editor/foldhaus_interface.cpp index 4160ab2..28a24c2 100644 --- a/src/app/editor/foldhaus_interface.cpp +++ b/src/app/editor/foldhaus_interface.cpp @@ -19,26 +19,6 @@ enum panel_edit_mode PanelEdit_Count, }; -internal void -SetPanelType_(panel* Panel, s32 NewPanelTypeIndex, app_state* State, context Context) -{ - - s32 OldPanelDefinitionIndex = Panel_GetCurrentTypeIndex(Panel); - Panel_SetCurrentTypeIndex(Panel, NewPanelTypeIndex, {0}); - - if(OldPanelDefinitionIndex >= 0) - { - GlobalPanelDefs[OldPanelDefinitionIndex].Cleanup(Panel, State); - } -} - -internal void -SetAndInitPanelType(panel* Panel, s32 NewPanelTypeIndex, app_state* State, context Context) -{ - SetPanelType_(Panel, NewPanelTypeIndex, State, Context); - GlobalPanelDefs[NewPanelTypeIndex].Init(Panel, State, Context); -} - // // Drag Panel Border Operation Mode @@ -249,19 +229,19 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation) if (XDistance > YDistance) { r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / Rect2Width(PanelBounds); - SplitPanelVertically(Panel, XPercent, &State->PanelSystem); + SplitPanelVertically(Panel, XPercent, &State->PanelSystem, State, Context); } else { r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / Rect2Height(PanelBounds); - SplitPanelHorizontally(Panel, YPercent, &State->PanelSystem); + SplitPanelHorizontally(Panel, YPercent, &State->PanelSystem, State, Context); } - s32 PanelTypeIndex = Panel_GetCurrentTypeIndex(Panel); - gs_data PanelStateMemory = Panel_GetCurrentTypeStateMemory_(Panel); - Panel_SetCurrentTypeIndex(&Panel->Left->Panel, PanelTypeIndex, PanelStateMemory); + s32 PanelTypeIndex = Panel->TypeIndex; + gs_data PanelStateMemory = Panel->StateMemory; + Panel_SetCurrentType(&Panel->Left->Panel, &State->PanelSystem, PanelTypeIndex, PanelStateMemory, State, Context); - SetAndInitPanelType(&Panel->Right->Panel, PanelTypeIndex, State, Context); + SetAndInitPanelType(&Panel->Right->Panel, &State->PanelSystem, PanelTypeIndex, State, Context); DeactivateCurrentOperationMode(&State->Modes); } @@ -438,7 +418,7 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterB gs_string DefName = MakeString(Def.PanelName, Def.PanelNameLength); if (ui_Button(&State->Interface, DefName, ButtonBounds)) { - SetAndInitPanelType(Panel, i, State, Context); + SetAndInitPanelType(Panel, &State->PanelSystem, i, State, Context); Panel->PanelSelectionMenuOpen = false; } @@ -456,7 +436,7 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterB internal void RenderPanel(panel* Panel, rect2 PanelBounds, rect2 WindowBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) { - s32 PanelType = Panel_GetCurrentTypeIndex(Panel); + s32 PanelType = Panel->TypeIndex; Assert(PanelType >= 0); rect2 FooterBounds = rect2{ diff --git a/src/app/editor/foldhaus_panel.h b/src/app/editor/foldhaus_panel.h index 190a118..658a8a3 100644 --- a/src/app/editor/foldhaus_panel.h +++ b/src/app/editor/foldhaus_panel.h @@ -19,18 +19,19 @@ enum panel_split_direction }; typedef struct panel_entry panel_entry; +typedef struct panel panel; + +#define PANEL_MODAL_OVERRIDE_CALLBACK(name) void name(panel* ReturningFrom, app_state* State, context Context) +typedef PANEL_MODAL_OVERRIDE_CALLBACK(panel_modal_override_callback); struct panel { + s32 TypeIndex; + gs_data StateMemory; - // TODO(pjs): We want this to be a list, so that you can push sub panels on - // and let them return to you, to perform certain tasks, like loading a file - //s32 PanelDefinitionIndex; -#define PANEL_TYPE_INDICES_COUNT_MAX 4 - s32 TypeIndicesCount; - s32 TypeIndices[PANEL_TYPE_INDICES_COUNT_MAX]; - gs_data ReturnDestMemory[PANEL_TYPE_INDICES_COUNT_MAX]; - gs_data TypeStateMemory[PANEL_TYPE_INDICES_COUNT_MAX]; + panel_entry* ModalOverride; + panel* IsModalOverrideFor; // TODO(pjs): I don't like that this is panel* but ModalOverride is panel_entry* + panel_modal_override_callback* ModalOverrideCB; panel_split_direction SplitDirection; r32 SplitPercent; @@ -60,9 +61,33 @@ struct panel_entry free_panel Free; }; +#define PANEL_INIT_PROC(name) void name(panel* Panel, app_state* State, context Context) +typedef PANEL_INIT_PROC(panel_init_proc); + +#define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State) +typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); + +#define PANEL_RENDER_PROC(name) void name(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +typedef PANEL_RENDER_PROC(panel_render_proc); + +// NOTE(Peter): This is used by the meta system to generate panel type info +struct panel_definition +{ + char* PanelName; + s32 PanelNameLength; + panel_init_proc* Init; + panel_cleanup_proc* Cleanup; + panel_render_proc* Render; + input_command* InputCommands; + s32 InputCommandsCount; +}; + #define PANELS_MAX 16 struct panel_system { + panel_definition* PanelDefs; + u32 PanelDefsCount; + panel_entry Panels[PANELS_MAX]; u32 PanelsUsed; @@ -92,9 +117,11 @@ struct panel_layout ///////////////////////////////// internal void -InitializePanelSystem(panel_system* PanelSystem) +InitializePanelSystem(panel_system* PanelSystem, panel_definition* PanelDefs, u32 PanelDefsCount) { PanelSystem->FreeList.Free.Next = &PanelSystem->FreeList; + PanelSystem->PanelDefs = PanelDefs; + PanelSystem->PanelDefsCount = PanelDefsCount; } internal panel_entry* @@ -114,16 +141,6 @@ TakeNewPanelEntry(panel_system* PanelSystem) return FreeEntry; } -internal panel* -TakeNewPanel(panel_system* PanelSystem) -{ - panel* Result = 0; - panel_entry* FreeEntry = TakeNewPanelEntry(PanelSystem); - Result = &FreeEntry->Panel; - *Result = {0}; - return Result; -} - internal void FreePanelEntry(panel_entry* Entry, panel_system* PanelSystem) { @@ -153,98 +170,111 @@ FreePanelAtIndex(s32 Index, panel_system* PanelSystem) PanelSystem->FreeList.Free.Next = EntryToFree; } -internal void -Panel_SetCurrentTypeIndex(panel* Panel, s32 NewPanelType, gs_data TypeStateMemory, gs_data ReturnDestMemory = {0}) +internal panel_entry* +Panel_GetModalOverride(panel_entry* PanelEntry) { - u32 CurrentTypeIndex = 0; - if (Panel->TypeIndicesCount != 0) + panel_entry* Result = PanelEntry; + if (PanelEntry->Panel.ModalOverride != 0) { - CurrentTypeIndex = Panel->TypeIndicesCount - 1; + Result = Panel_GetModalOverride(PanelEntry->Panel.ModalOverride); } - else + return Result; +} + +internal panel* +Panel_GetModalOverride(panel* Panel) +{ + panel* Result = Panel; + if (Panel->ModalOverride != 0) { - CurrentTypeIndex = Panel->TypeIndicesCount++; + Result = &Panel_GetModalOverride(Panel->ModalOverride)->Panel; } + return Result; +} + +internal void +Panel_PushModalOverride(panel* Root, panel_entry* Override, panel_modal_override_callback* Callback) +{ + Root->ModalOverride = Override; + Root->ModalOverrideCB = Callback; + Override->Panel.IsModalOverrideFor = Root; +} + +internal void +Panel_PopModalOverride(panel* Parent, panel_system* System) +{ + // TODO(pjs): Free the overrided panel + FreePanelEntry(Parent->ModalOverride, System); + Parent->ModalOverride = 0; +} + +internal void +Panel_SetCurrentType(panel* Panel, panel_system* System, s32 NewPanelType, gs_data TypeStateMemory, app_state* State, context Context) +{ + s32 OldTypeIndex = Panel->TypeIndex; - Panel->TypeIndices[CurrentTypeIndex] = NewPanelType; - Panel->TypeStateMemory[CurrentTypeIndex] = TypeStateMemory; - Panel->ReturnDestMemory[CurrentTypeIndex] = ReturnDestMemory; -} - -internal s32 -Panel_GetCurrentTypeIndex(panel* Panel) -{ - s32 Result = -1; - if (Panel->TypeIndicesCount != 0) + Panel->TypeIndex = NewPanelType; + Panel->StateMemory = TypeStateMemory; + + if(OldTypeIndex >= 0) { - Result = Panel->TypeIndices[Panel->TypeIndicesCount - 1]; + System->PanelDefs[OldTypeIndex].Cleanup(Panel, State); } - return Result; } -#define Panel_GetCurrentTypeStateMemory(p, type) (type*)Panel_GetCurrentTypeStateMemory_(p).Memory +internal void +SetAndInitPanelType(panel* Panel, panel_system* System, s32 NewPanelTypeIndex, app_state* State, context Context) +{ + gs_data EmptyStateData = {0}; + Panel_SetCurrentType(Panel, System, NewPanelTypeIndex, EmptyStateData, State, Context); + System->PanelDefs[NewPanelTypeIndex].Init(Panel, State, Context); +} + +#define Panel_GetStateStruct(p, type) (type*)Panel_GetStateMemory((p), sizeof(type)).Memory internal gs_data -Panel_GetCurrentTypeStateMemory_(panel* Panel) +Panel_GetStateMemory(panel* Panel, u64 Size) { - gs_data Result = {0}; - if (Panel->TypeIndicesCount != 0) - { - Result = Panel->TypeStateMemory[Panel->TypeIndicesCount - 1]; - } + Assert(Panel->StateMemory.Size == Size); + gs_data Result = Panel->StateMemory; return Result; } -internal void -Panel_SetCurrentTypeStateMemory(panel* Panel, gs_data StateMemory) +internal panel_entry* +PanelSystem_PushPanel(panel_system* PanelSystem, s32 PanelTypeIndex, app_state* State, context Context) { - u32 CurrentTypeIndex = 0; - if (Panel->TypeIndicesCount != 0) - { - CurrentTypeIndex = Panel->TypeIndicesCount - 1; - } - else - { - CurrentTypeIndex = Panel->TypeIndicesCount++; - } - Panel->TypeStateMemory[CurrentTypeIndex] = StateMemory; + panel_entry* PanelEntry = TakeNewPanelEntry(PanelSystem); + SetAndInitPanelType(&PanelEntry->Panel, PanelSystem, PanelTypeIndex, State, Context); + return PanelEntry; } internal void -Panel_PushTypeWithReturn(panel* Panel, s32 NewPanelType, gs_data ReturnDestMemory) -{ - Assert(Panel->TypeIndicesCount < PANEL_TYPE_INDICES_COUNT_MAX); - u32 NewTypeIndex = Panel->TypeIndicesCount++; - Panel_SetCurrentTypeIndex(Panel, NewPanelType, ReturnDestMemory); -} - -internal void -SplitPanel(panel* Parent, r32 Percent, panel_split_direction SplitDirection, panel_system* PanelSystem) +SplitPanel(panel* Parent, r32 Percent, panel_split_direction SplitDirection, panel_system* PanelSystem, app_state* State, context Context) { if (Percent >= 0.0f && Percent <= 1.0f) { Parent->SplitDirection = SplitDirection; Parent->SplitPercent = Percent; - s32 ParentTypeIndex = Panel_GetCurrentTypeIndex(Parent); - gs_data ParentStateMemory = Panel_GetCurrentTypeStateMemory_(Parent); + s32 ParentTypeIndex = Parent->TypeIndex; + gs_data ParentStateMemory = Parent->StateMemory; Parent->Left = TakeNewPanelEntry(PanelSystem); - Panel_SetCurrentTypeIndex(&Parent->Left->Panel, ParentTypeIndex, ParentStateMemory); + Panel_SetCurrentType(&Parent->Left->Panel, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context); Parent->Right = TakeNewPanelEntry(PanelSystem); - Panel_SetCurrentTypeIndex(&Parent->Right->Panel, ParentTypeIndex, ParentStateMemory); + Panel_SetCurrentType(&Parent->Right->Panel, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context); } } internal void -SplitPanelVertically(panel* Parent, r32 Percent, panel_system* PanelSystem) +SplitPanelVertically(panel* Parent, r32 Percent, panel_system* PanelSystem, app_state* State, context Context) { - SplitPanel(Parent, Percent, PanelSplit_Vertical, PanelSystem); + SplitPanel(Parent, Percent, PanelSplit_Vertical, PanelSystem, State, Context); } internal void -SplitPanelHorizontally(panel* Parent, r32 Percent, panel_system* PanelSystem) +SplitPanelHorizontally(panel* Parent, r32 Percent, panel_system* PanelSystem, app_state* State, context Context) { - SplitPanel(Parent, Percent, PanelSplit_Horizontal, PanelSystem); + SplitPanel(Parent, Percent, PanelSplit_Horizontal, PanelSystem, State, Context); } internal void @@ -321,13 +351,17 @@ LayoutPanel(panel* Panel, rect2 PanelBounds, panel_layout* Layout) if (Panel->SplitDirection == PanelSplit_NoSplit) { panel_with_layout* WithLayout = Layout->Panels + Layout->PanelsCount++; - WithLayout->Panel = Panel; + WithLayout->Panel = Panel_GetModalOverride(Panel); WithLayout->Bounds = PanelBounds; } else if (Panel->SplitDirection == PanelSplit_Horizontal) { rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); + + panel* TopPanel = Panel_GetModalOverride(&Panel->Top->Panel); + panel* BottomPanel = Panel_GetModalOverride(&Panel->Bottom->Panel); + LayoutPanel(&Panel->Top->Panel, TopPanelBounds, Layout); LayoutPanel(&Panel->Bottom->Panel, BottomPanelBounds, Layout); } @@ -335,6 +369,10 @@ LayoutPanel(panel* Panel, rect2 PanelBounds, panel_layout* Layout) { rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); + + panel* LeftPanel = Panel_GetModalOverride(&Panel->Top->Panel); + panel* RightPanel = Panel_GetModalOverride(&Panel->Bottom->Panel); + LayoutPanel(&Panel->Left->Panel, LeftPanelBounds, Layout); LayoutPanel(&Panel->Right->Panel, RightPanelBounds, Layout); } diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index e242a12..91f01fa 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -170,11 +170,9 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) s32 NewStartFrame = OpState->ClipRange.Min + FrameOffset; if (FrameOffset < 0) { - for (u32 i = 0; i < ActiveAnim->Blocks.Used; i++) + for (u32 i = 0; i < ActiveAnim->Blocks_.Count; i++) { - gs_list_entry* OtherBlockEntry = ActiveAnim->Blocks.GetEntryAtIndex(i); - if (EntryIsFree(OtherBlockEntry)) { continue; } - animation_block OtherBlock = OtherBlockEntry->Value; + animation_block OtherBlock = ActiveAnim->Blocks_.Values[i]; NewStartFrame = AttemptToSnapPosition(NewStartFrame, OtherBlock.Range.Max); } } @@ -192,11 +190,9 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) r32 NewEndFrame = OpState->ClipRange.Max + FrameOffset; if (FrameOffset > 0) { - for (u32 i = 0; i < ActiveAnim->Blocks.Used; i++) + for (u32 i = 0; i < ActiveAnim->Blocks_.Count; i++) { - gs_list_entry* OtherBlockEntry = ActiveAnim->Blocks.GetEntryAtIndex(i); - if (EntryIsFree(OtherBlockEntry)) { continue; } - animation_block OtherBlock = OtherBlockEntry->Value; + animation_block OtherBlock = ActiveAnim->Blocks_.Values[i]; NewEndFrame = AttemptToSnapPosition(NewEndFrame, OtherBlock.Range.Min); } } @@ -213,11 +209,9 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) { u32 NewStartFrame = OpState->ClipRange.Min + FrameOffset; u32 NewEndFrame = OpState->ClipRange.Max + FrameOffset; - for (u32 i = 0; i < ActiveAnim->Blocks.Used; i++) + for (u32 i = 0; i < ActiveAnim->Blocks_.Count; i++) { - gs_list_entry* OtherBlockEntry = ActiveAnim->Blocks.GetEntryAtIndex(i); - if (EntryIsFree(OtherBlockEntry)) { continue; } - animation_block OtherBlock = OtherBlockEntry->Value; + animation_block OtherBlock = ActiveAnim->Blocks_.Values[i];; u32 SnapFramesAmount = 0; if (FrameOffset > 0) @@ -294,7 +288,7 @@ AnimationTimeline_Init(panel* Panel, app_state* State, context Context) animation_timeline_state* TimelineState = PushStruct(&State->Permanent, animation_timeline_state); TimelineState->VisibleRange = ActiveAnim->PlayableRange; - Panel_SetCurrentTypeStateMemory(Panel, StructToData(TimelineState, animation_timeline_state)); + Panel->StateMemory = StructToData(TimelineState, animation_timeline_state); } GSMetaTag(panel_cleanup); @@ -580,6 +574,13 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta return Result; } +PANEL_MODAL_OVERRIDE_CALLBACK(LoadAnimationFileCallback) +{ + Assert(ReturningFrom->TypeIndex == PanelType_FileView); + file_view_state* FileViewState = Panel_GetStateStruct(ReturningFrom, file_view_state); + gs_file_info FileInfo = FileViewState->SelectedFile; +} + internal void DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayerHandle, animation_system* AnimationSystem) { @@ -600,7 +601,7 @@ GSMetaTag(panel_type_animation_timeline); internal void AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - animation_timeline_state* TimelineState = Panel_GetCurrentTypeStateMemory(Panel, animation_timeline_state); + animation_timeline_state* TimelineState = Panel_GetStateStruct(Panel, animation_timeline_state); // TODO(pjs): SelectedAnimationBlockHandle should be a property of animation_timeline_state // unless its used elsewhere. Audit later handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; @@ -634,11 +635,8 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Load"))) { - // TODO(pjs): You were working on #6 on your todo list. - // below is a "write the interface first" example of how you'd like to be able to - // activate a file panel from within another panel. - gs_data ReturnDestination = {}; - Panel_PushTypeWithReturn(Panel, PanelType_FileView, ReturnDestination); + panel_entry* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context); + Panel_PushModalOverride(Panel, FileBrowser, LoadAnimationFileCallback); // TODO(pjs): I think we want to be able to specify a return command that gets called when the // pushed panel state returns to this one // something like: AnimPanel_HandleLoadedAnimationFile diff --git a/src/app/editor/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h index a1b9d98..78cbd47 100644 --- a/src/app/editor/panels/foldhaus_panel_file_view.h +++ b/src/app/editor/panels/foldhaus_panel_file_view.h @@ -10,6 +10,8 @@ struct file_view_state gs_string WorkingDirectory; gs_memory_arena FileNamesArena; gs_file_info_array FileNames; + + gs_file_info SelectedFile; }; input_command* FileView_Commands = 0; @@ -55,7 +57,7 @@ FileView_Init(panel* Panel, app_state* State, context Context) { // TODO: :FreePanelMemory file_view_state* FileViewState = PushStruct(&State->Permanent, file_view_state); - Panel_SetCurrentTypeStateMemory(Panel, StructToData(FileViewState, file_view_state)); + Panel->StateMemory = StructToData(FileViewState, file_view_state); FileViewState->FileNamesArena = CreateMemoryArena(Context.ThreadContext.Allocator); FileViewUpdateWorkingDirectory(ConstString("."), FileViewState, Context); } @@ -73,7 +75,7 @@ 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_GetCurrentTypeStateMemory(Panel, file_view_state); + file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state); ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); // Header @@ -96,7 +98,15 @@ FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBu } else { - // TODO(pjs): Select the file + FileViewState->SelectedFile = File; + + Assert(Panel->IsModalOverrideFor != 0); + panel* ReturnTo = Panel->IsModalOverrideFor; + if (ReturnTo->ModalOverrideCB) + { + ReturnTo->ModalOverrideCB(Panel, State, Context); + } + Panel_PopModalOverride(ReturnTo, &State->PanelSystem); } } } diff --git a/src/app/editor/panels/foldhaus_panel_hierarchy.h b/src/app/editor/panels/foldhaus_panel_hierarchy.h index 3654cdb..fdecc36 100644 --- a/src/app/editor/panels/foldhaus_panel_hierarchy.h +++ b/src/app/editor/panels/foldhaus_panel_hierarchy.h @@ -24,6 +24,15 @@ HierarchyView_Cleanup(panel* Panel, app_state* State) } +PANEL_MODAL_OVERRIDE_CALLBACK(LoadAssemblyCallback) +{ + Assert(ReturningFrom->TypeIndex == PanelType_FileView); + file_view_state* FileViewState = Panel_GetStateStruct(ReturningFrom, file_view_state); + gs_file_info FileInfo = FileViewState->SelectedFile; + + LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, FileInfo.Path, State->GlobalLog); +} + GSMetaTag(panel_render); GSMetaTag(panel_type_hierarchy); internal void @@ -66,19 +75,8 @@ HierarchyView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* Ren PrintF(&TempString, "+ Add Assembly"); if (ui_ListButton(&State->Interface, TempString, LineBounds[AssembliesToDraw], AssembliesToDraw)) { - gs_string FilePath = PushString(State->Transient, 256); - - // TODO(Peter): Took out file opening temporarily while I get things back up and running. - // Ideally we can just write our own file lister using the new filehandler so that - // execution doesn't suspend while we try and open a file - InvalidCodePath; -#if 0 - b32 Success = GetFilePath(Context, &FilePath, "Foldhaus Files\0*.fold\0\0"); - if (Success) - { - LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, FilePath.ConstString, State->GlobalLog); - } -#endif + panel_entry* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context); + Panel_PushModalOverride(Panel, FileBrowser, LoadAssemblyCallback); } } } diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 45037af..cb564a7 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -62,7 +62,6 @@ struct animation gs_string Name; anim_layer_array Layers; - gs_list Blocks; animation_block_array Blocks_; frame_range PlayableRange; @@ -199,6 +198,17 @@ AnimBlockArray_Remove(animation_block_array* Array, handle Handle) Array->Generations[Handle.Index]++; } +internal void +AnimBlockArray_RemoveAt(animation_block_array* Array, u32 Index) +{ + Assert(Index < Array->Count); + + handle Handle = {}; + Handle.Index = Index; + Handle.Generation = Array->Generations[Index]; + AnimBlockArray_Remove(Array, Handle); +} + ////////////////////////// // // Anim Layers Array @@ -257,43 +267,6 @@ AnimationArray_Push(animation_array* Array, animation Value) // // Animation -internal u32 -Animation_AddLayer(animation* Animation, anim_layer Layer) -{ - return AnimLayerArray_Push(&Animation->Layers, Layer); -} - -internal u32 -Animation_AddLayer (animation* Animation, gs_string Name, blend_mode BlendMode, animation_system* System) -{ - anim_layer NewLayer = {0}; - NewLayer.Name = PushStringF(System->Storage, 256, "%S", Name); - NewLayer.BlendMode = BlendMode; - - return Animation_AddLayer(Animation, NewLayer); -} - -internal void -Animation_RemoveLayer (animation* Animation, u32 LayerIndex) -{ - AnimLayerArray_Remove(&Animation->Layers, LayerIndex); - for (u32 i = Animation->Blocks.Used -= 1; i >= 0; i--) - { - gs_list_entry* Entry = Animation->Blocks.GetEntryAtIndex(i); - if (EntryIsFree(Entry)) { continue; } - - animation_block* Block = &Entry->Value; - if (Block->Layer > LayerIndex) - { - Block->Layer -= 1; - } - else if (Block->Layer == LayerIndex) - { - Animation->Blocks.FreeElementAtIndex(i); - } - } -} - internal handle Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, u32 AnimationProcHandle, u32 LayerIndex) { @@ -329,6 +302,40 @@ Animation_GetBlockFromHandle(animation* Animation, handle AnimHandle) return Result; } +internal u32 +Animation_AddLayer(animation* Animation, anim_layer Layer) +{ + return AnimLayerArray_Push(&Animation->Layers, Layer); +} + +internal u32 +Animation_AddLayer (animation* Animation, gs_string Name, blend_mode BlendMode, animation_system* System) +{ + anim_layer NewLayer = {0}; + NewLayer.Name = PushStringF(System->Storage, 256, "%S", Name); + NewLayer.BlendMode = BlendMode; + + return Animation_AddLayer(Animation, NewLayer); +} + +internal void +Animation_RemoveLayer (animation* Animation, u32 LayerIndex) +{ + AnimLayerArray_Remove(&Animation->Layers, LayerIndex); + for (u32 i = Animation->Blocks_.Count - 1; i >= 0; i--) + { + animation_block* Block = Animation->Blocks_.Values + i; + if (Block->Layer > LayerIndex) + { + Block->Layer -= 1; + } + else if (Block->Layer == LayerIndex) + { + AnimBlockArray_RemoveAt(&Animation->Blocks_, i); + } + } +} + ////////////////////////// // // @@ -408,12 +415,9 @@ AnimationSystem_CalculateAnimationFrame(animation_system* System, gs_memory_aren Result.BlocksFilled = PushArray(Arena, b8, Result.BlocksCountMax); ZeroArray(Result.BlocksFilled, b8, Result.BlocksCountMax); - for (u32 i = 0; i < ActiveAnim->Blocks.Used; i++) + for (u32 i = 0; i < ActiveAnim->Blocks_.Count; i++) { - gs_list_entry* BlockEntry = ActiveAnim->Blocks.GetEntryAtIndex(i); - if (EntryIsFree(BlockEntry)) { continue; } - - animation_block Block = BlockEntry->Value; + animation_block Block = ActiveAnim->Blocks_.Values[i]; if (FrameIsInRange(Block.Range, System->CurrentFrame)) { diff --git a/src/app/engine/animation/foldhaus_animation_serializer.cpp b/src/app/engine/animation/foldhaus_animation_serializer.cpp index d66f3ee..57d6221 100644 --- a/src/app/engine/animation/foldhaus_animation_serializer.cpp +++ b/src/app/engine/animation/foldhaus_animation_serializer.cpp @@ -16,7 +16,7 @@ AnimSerializer_Serialize(animation Anim, animation_clip* GlobalClips, gs_memory_ Serializer_WriteF(&Serializer, "%S;\n", AnimationFieldStrings[AnimField_FileIdent]); Serializer_WriteStringValue(&Serializer, AnimField_AnimName, Anim.Name.ConstString); Serializer_WriteValue(&Serializer, AnimField_LayersCount, Anim.Layers.Count); - Serializer_WriteValue(&Serializer, AnimField_BlocksCount, Anim.Blocks.Used); + Serializer_WriteValue(&Serializer, AnimField_BlocksCount, Anim.Blocks_.Count); Serializer_OpenStruct(&Serializer, AnimField_PlayableRange); { @@ -40,12 +40,10 @@ AnimSerializer_Serialize(animation Anim, animation_clip* GlobalClips, gs_memory_ Serializer_OpenStruct(&Serializer, AnimField_BlocksArray); - for (u32 i = 0; i < Anim.Blocks.Used; i++) + for (u32 i = 0; i < Anim.Blocks_.Count; i++) { - gs_list_entry* AnimationBlockEntry = Anim.Blocks.GetEntryAtIndex(i); - if (EntryIsFree(AnimationBlockEntry)) { continue; } - gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle; - animation_block AnimationBlockAt = AnimationBlockEntry->Value; + // TODO(pjs): Handle free'd animation blocks + animation_block AnimationBlockAt = Anim.Blocks_.Values[i]; // TODO(pjs): Systematize the AnimationProcHandle // :AnimProcHandle @@ -171,7 +169,7 @@ AnimParser_Parse(gs_string File, animation_clip* GlobalClips, gs_memory_arena* A if (Parser_ReadCloseStruct(&Parser)) { - Result.Blocks.PushElementOnList(Block); + AnimBlockArray_Push(&Result.Blocks_, Block); } else { diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 744e4f1..b578796 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -136,7 +136,6 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Modes = OperationModeSystemInit(&State->Permanent, Context.ThreadContext); { // Animation PLAYGROUND - State->AnimationSystem = {}; State->AnimationSystem.Storage = &State->Permanent; State->AnimationSystem.Animations = AnimationArray_Create(State->AnimationSystem.Storage, 32); @@ -160,9 +159,8 @@ INITIALIZE_APPLICATION(InitializeApplication) } // End Animation Playground - InitializePanelSystem(&State->PanelSystem); - panel* Panel = TakeNewPanel(&State->PanelSystem); - SetAndInitPanelType(Panel, PanelType_SculptureView, State, Context); + InitializePanelSystem(&State->PanelSystem, GlobalPanelDefs, GlobalPanelDefsCount); + PanelSystem_PushPanel(&State->PanelSystem, PanelType_SculptureView, State, Context); } internal void @@ -184,7 +182,7 @@ HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse if (!PanelWithMouseOverIt.Panel) { return; } State->HotPanel = PanelWithMouseOverIt.Panel; - s32 PanelTypeIndex = Panel_GetCurrentTypeIndex(PanelWithMouseOverIt.Panel); + s32 PanelTypeIndex = PanelWithMouseOverIt.Panel->TypeIndex; panel_definition PanelDefinition = GlobalPanelDefs[PanelTypeIndex]; if (!PanelDefinition.InputCommands) { return; } diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 689f4d0..05bd69f 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -26,14 +26,14 @@ typedef struct app_state app_state; +#include "editor/foldhaus_command_dispatch.h" +#include "editor/foldhaus_operation_mode.h" + // TODO(Peter): something we can do later is to remove all reliance on app_state and context // from foldhaus_pane.h. It should just emit lists of things that the app can iterate over and // perform operations on, like panel_draw_requests = { bounds, panel* } etc. #include "editor/foldhaus_panel.h" -#include "editor/foldhaus_command_dispatch.h" -#include "editor/foldhaus_operation_mode.h" - #include "engine/animation/foldhaus_animation.h" #include "engine/animation/foldhaus_animation_serializer.cpp" @@ -209,27 +209,6 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndCurrentOperationMode) DeactivateCurrentOperationMode(&State->Modes); } -#define PANEL_INIT_PROC(name) void name(panel* Panel, app_state* State, context Context) -typedef PANEL_INIT_PROC(panel_init_proc); - -#define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State) -typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); - -#define PANEL_RENDER_PROC(name) void name(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) -typedef PANEL_RENDER_PROC(panel_render_proc); - -// NOTE(Peter): This is used by the meta system to generate panel type info -struct panel_definition -{ - char* PanelName; - s32 PanelNameLength; - panel_init_proc* Init; - panel_cleanup_proc* Cleanup; - panel_render_proc* Render; - input_command* InputCommands; - s32 InputCommandsCount; -}; - s32 GlobalAnimationClipsCount = 3; animation_clip GlobalAnimationClips[] = { { "Test Pattern One", 16, TestPatternOne }, @@ -239,12 +218,13 @@ animation_clip GlobalAnimationClips[] = { #include "editor/panels/foldhaus_panel_types.h" +#include "editor/panels/foldhaus_panel_file_view.h" #include "editor/panels/foldhaus_panel_sculpture_view.h" #include "editor/panels/foldhaus_panel_profiler.h" #include "editor/panels/foldhaus_panel_dmx_view.h" #include "editor/panels/foldhaus_panel_animation_timeline.h" #include "editor/panels/foldhaus_panel_hierarchy.h" -#include "editor/panels/foldhaus_panel_file_view.h" + #include "editor/panels/foldhaus_panel_types.cpp" //#include "generated/foldhaus_panels_generated.h" From 85f7aab6214986746c129a9f7507bc999f8ce62a Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 24 Oct 2020 13:28:10 -0700 Subject: [PATCH 42/43] Animation loading --- .../foldhaus_panel_animation_timeline.h | 12 +++++--- .../editor/panels/foldhaus_panel_file_view.h | 28 +++++++++++++------ src/app/engine/animation/foldhaus_animation.h | 3 +- .../foldhaus_animation_serializer.cpp | 13 ++++++--- src/app/foldhaus_app.cpp | 1 - 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 91f01fa..47404d4 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -494,7 +494,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta handle Result = SelectedBlockHandle; // TODO(pjs): Animation Selection - animation CurrAnimation = AnimationSystem->Animations.Values[0]; + animation CurrAnimation = *AnimationSystem_GetActiveAnimation(AnimationSystem); rect2 LayerMenuBounds, TimelineBounds; RectVSplitAtDistanceFromLeft(PanelBounds, 256, &LayerMenuBounds, &TimelineBounds); @@ -579,6 +579,13 @@ PANEL_MODAL_OVERRIDE_CALLBACK(LoadAnimationFileCallback) Assert(ReturningFrom->TypeIndex == PanelType_FileView); file_view_state* FileViewState = Panel_GetStateStruct(ReturningFrom, file_view_state); gs_file_info FileInfo = FileViewState->SelectedFile; + + gs_file AnimFile = ReadEntireFile(Context.ThreadContext.FileHandler, FileInfo.Path); + gs_string AnimFileString = MakeString((char*)AnimFile.Data.Memory, AnimFile.Data.Size); + animation NewAnim = AnimParser_Parse(AnimFileString, State->AnimationSystem.Storage, GlobalAnimationClipsCount, GlobalAnimationClips); + + u32 NewAnimIndex = AnimationArray_Push(&State->AnimationSystem.Animations, NewAnim); + State->AnimationSystem.ActiveAnimationIndex = NewAnimIndex; } internal void @@ -637,9 +644,6 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* { panel_entry* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context); Panel_PushModalOverride(Panel, FileBrowser, LoadAnimationFileCallback); - // TODO(pjs): I think we want to be able to specify a return command that gets called when the - // pushed panel state returns to this one - // something like: AnimPanel_HandleLoadedAnimationFile } } ui_EndRow(&TitleBarLayout); diff --git a/src/app/editor/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h index 78cbd47..e369e7f 100644 --- a/src/app/editor/panels/foldhaus_panel_file_view.h +++ b/src/app/editor/panels/foldhaus_panel_file_view.h @@ -14,7 +14,19 @@ struct file_view_state gs_file_info SelectedFile; }; -input_command* FileView_Commands = 0; +internal void +FileView_Exit_(panel* FileViewPanel, app_state* State, context Context) +{ + 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; s32 FileView_CommandsCount = 0; internal void @@ -78,6 +90,11 @@ FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBu file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state); ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); + if (ui_LayoutButton(&State->Interface, &Layout, MakeString("Exit"))) + { + FileView_Exit_(Panel, State, Context); + } + // Header ui_LayoutDrawString(&State->Interface, &Layout, FileViewState->WorkingDirectory, v4{0, 1, 0, 1}); @@ -99,14 +116,7 @@ FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBu else { FileViewState->SelectedFile = File; - - Assert(Panel->IsModalOverrideFor != 0); - panel* ReturnTo = Panel->IsModalOverrideFor; - if (ReturnTo->ModalOverrideCB) - { - ReturnTo->ModalOverrideCB(Panel, State, Context); - } - Panel_PopModalOverride(ReturnTo, &State->PanelSystem); + FileView_Exit_(Panel, State, Context); } } } diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index cb564a7..81e2080 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -94,6 +94,7 @@ struct animation_system // NOTE(Peter): The frame currently being displayed/processed. you // can see which frame you're on by looking at the time slider on the timeline // panel + u32 ActiveAnimationIndex; s32 CurrentFrame; s32 LastUpdatedFrame; r32 SecondsPerFrame; @@ -401,7 +402,7 @@ internal animation* AnimationSystem_GetActiveAnimation(animation_system* System) { // TODO(pjs): need a way to specify the active animation - return System->Animations.Values + 0; + return System->Animations.Values + System->ActiveAnimationIndex; } internal animation_frame diff --git a/src/app/engine/animation/foldhaus_animation_serializer.cpp b/src/app/engine/animation/foldhaus_animation_serializer.cpp index 57d6221..ac9954e 100644 --- a/src/app/engine/animation/foldhaus_animation_serializer.cpp +++ b/src/app/engine/animation/foldhaus_animation_serializer.cpp @@ -70,7 +70,7 @@ AnimSerializer_Serialize(animation Anim, animation_clip* GlobalClips, gs_memory_ } internal animation -AnimParser_Parse(gs_string File, animation_clip* GlobalClips, gs_memory_arena* Arena, u32 AnimClipsCount, animation_clip* AnimClips) +AnimParser_Parse(gs_string File, gs_memory_arena* Arena, u32 AnimClipsCount, animation_clip* AnimClips) { animation Result = {0}; @@ -88,14 +88,19 @@ AnimParser_Parse(gs_string File, animation_clip* GlobalClips, gs_memory_arena* A Result.Layers.CountMax = Parser_ReadU32Value(&Parser, AnimField_LayersCount); Result.Layers.Values = PushArray(Arena, anim_layer, Result.Layers.CountMax); - // TODO(pjs): We're not using this now because Blocks are built on gs_list or something, - // but I want to replace that eventually, so this is here to preallocate the blocks we need - u32 BlocksCount = Parser_ReadU32Value(&Parser, AnimField_BlocksCount); + Result.Blocks_.CountMax = Parser_ReadU32Value(&Parser, AnimField_BlocksCount); + Result.Blocks_.Generations = PushArray(Arena, u32, Result.Blocks_.CountMax); + Result.Blocks_.Values = PushArray(Arena, animation_block, Result.Blocks_.CountMax); if (Parser_ReadOpenStruct(&Parser, AnimField_PlayableRange)) { Result.PlayableRange.Min = Parser_ReadU32Value(&Parser, AnimField_PlayableRangeMin); Result.PlayableRange.Max = Parser_ReadU32Value(&Parser, AnimField_PlayableRangeMax); + + if (Parser_ReadCloseStruct(&Parser)) + { + // TODO(pjs): Error + } } else { diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index b578796..af0c7ae 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -155,7 +155,6 @@ INITIALIZE_APPLICATION(InitializeApplication) Animation_AddBlock(&Anim, 22, 123, 2, 0); AnimationArray_Push(&State->AnimationSystem.Animations, Anim); - } // End Animation Playground From a88d6753278ee937cbc6631831f3d6f2c98a6d55 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 24 Oct 2020 13:50:34 -0700 Subject: [PATCH 43/43] removed gs_list and gs_bucket from the app --- .../editor/panels/foldhaus_panel_animation_timeline.h | 3 +-- src/app/foldhaus_platform.h | 3 --- src/todo.txt | 4 ---- src/todo_done.txt | 9 +++++++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 47404d4..a37dc78 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -12,7 +12,7 @@ global v4 TimeSliderColor = GreenV4; //v4{.36f, .52f, .78f, 1.f}; struct animation_timeline_state { frame_range VisibleRange; - gs_list_handle SelectedAnimationBlockHandle; + handle SelectedAnimationBlockHandle; u32 SelectedAnimationLayer; }; @@ -493,7 +493,6 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta gs_string Tempgs_string = PushString(State->Transient, 256); handle Result = SelectedBlockHandle; - // TODO(pjs): Animation Selection animation CurrAnimation = *AnimationSystem_GetActiveAnimation(AnimationSystem); rect2 LayerMenuBounds, TimelineBounds; diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index e5db04c..96c8685 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -25,9 +25,6 @@ Handle_IsValid(handle Handle) return Result; } -#include "..\gs_libs\gs_list.h" -#include "..\gs_libs\gs_bucket.h" - #include "..\gs_libs\gs_string.h" #include "foldhaus_debug.h" diff --git a/src/todo.txt b/src/todo.txt index e82c742..6c1bc22 100644 --- a/src/todo.txt +++ b/src/todo.txt @@ -23,9 +23,6 @@ STREAM #1: 3D Overhaul - mouse spatial interaction - handles, and hover for info - debug capabilities (toggle strip/led/universe colors) -- Buckets & Lists - - On second thought, I just really don't like these. Lets get rid of them, and put custom structures in place - - Internal Log File NOTE: This should not be a part of the debug system - Save output log to a file continuously @@ -48,7 +45,6 @@ STREAM #1: 3D Overhaul - Serialization - saving scenes - - saving animation timelines - saving projects STRAM #4: Completeness diff --git a/src/todo_done.txt b/src/todo_done.txt index b957c7c..6aae2d4 100644 --- a/src/todo_done.txt +++ b/src/todo_done.txt @@ -1,3 +1,8 @@ +x saving animation timelines +x Buckets & Lists + x On second thought, I just really don't like these. Lets get rid of them, and put custom structures in place + + BUGS x if there is nothing in the filtered list when searching for a node, hitting enter still selects one x Search lister - returning from a filtered list that has zero elements to one that has a few, hotItem = -1 @@ -27,11 +32,11 @@ x Add Text Alignment to DrawString x Move nodes over to referencing eachother based on a UID system /Debug -x Make debug scope tracking thread safe - was throwing an error in stringsequal but that stopped. +x Make debug scope tracking thread safe - was throwing an error in stringsequal but that stopped. x Keep an eye out. x Sort Scope Tracking x got the profiler view rudimentarily working -x reimplement the scope list view. +x reimplement the scope list view. x start tracking debug interface state somehow and it would be good to separate that out from global debug state Switch To Nodes