diff --git a/build/build_app_msvc_win32_debug.bat b/build/build_app_msvc_win32_debug.bat index d69d5db..663ae28 100644 --- a/build/build_app_msvc_win32_debug.bat +++ b/build/build_app_msvc_win32_debug.bat @@ -34,6 +34,11 @@ cl %CommonCompilerFlags% %ProjectDevPath%\src\serial_monitor\first.cpp /Feserial cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp /Fegen_blumen_lumen.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib +REM COMPILE AND RUN TESTS +cl %CommonCompilerFlags% %ProjectDevPath%\src\tests\sanity_tests.cpp /Fesanity_tests.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib + +sanity_tests.exe + popd call %MyPath%\_postbuild_win32.bat \ No newline at end of file diff --git a/src/app/blumen_lumen.cpp b/src/app/blumen_lumen.cpp index 68aa25a..4f9791c 100644 --- a/src/app/blumen_lumen.cpp +++ b/src/app/blumen_lumen.cpp @@ -126,7 +126,9 @@ BlumenLumen_CustomInit(app_state* State, context Context) BLState->MicListenJobData.OutgoingMsgQueue = &BLState->OutgoingMsgQueue; BLState->MicListenJobData.ListenSocket = CreateSocket(Context.SocketManager, "127.0.0.1", "20185"); +#if 0 BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData); +#endif gs_const_string SculpturePath = ConstString("data/test_blumen.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog); diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 92ee12c..6464628 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -792,6 +792,29 @@ TimeRange_Render(animation_timeline_state* TimelineState, rect2 Bounds, render_c } } +internal void +AnimInfoView_SaveAnimFile (gs_const_string Path, app_state* State, context Context) +{ + u32 ActiveAnimIndex = State->AnimationSystem.ActiveAnimationIndex; + animation ActiveAnimation = State->AnimationSystem.Animations.Values[ActiveAnimIndex]; + + gs_string FileText = AnimSerializer_Serialize(ActiveAnimation, State->Patterns, State->Transient); + + if (!WriteEntireFile(Context.ThreadContext.FileHandler, Path, StringToData(FileText))) + { + InvalidCodePath; + } +} + +PANEL_MODAL_OVERRIDE_CALLBACK(AnimInfoView_SaveAnimFileCallback) +{ + Assert(ReturningFrom->TypeIndex == PanelType_FileView); + file_view_state* FileViewState = Panel_GetStateStruct(ReturningFrom, file_view_state); + gs_file_info FileInfo = FileViewState->SelectedFile; + + AnimInfoView_SaveAnimFile(FileInfo.Path, State, Context); +} + internal void AnimInfoView_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* Panel, render_command_buffer* RenderBuffer, app_state* State, context Context) { @@ -833,10 +856,14 @@ AnimInfoView_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel // need to use the file browser to create a file u32 ActiveAnimIndex = State->AnimationSystem.ActiveAnimationIndex; animation ActiveAnimation = State->AnimationSystem.Animations.Values[ActiveAnimIndex]; - gs_string FileText = AnimSerializer_Serialize(ActiveAnimation, State->Patterns, State->Transient); - if (WriteEntireFile(Context.ThreadContext.FileHandler, ActiveAnimation.FileInfo.Path, StringToData(FileText))) + + if (!ActiveAnimation.FileInfo.Path.Str) { - InvalidCodePath; + panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context); + FileView_SetMode(FileBrowser, FileViewMode_Save); + Panel_PushModalOverride(Panel, FileBrowser, AnimInfoView_SaveAnimFileCallback); + } else { + AnimInfoView_SaveAnimFile(ActiveAnimation.FileInfo.Path, State, Context); } } if (ui_Button(Interface, MakeString("Load"))) diff --git a/src/app/editor/panels/foldhaus_panel_file_view.h b/src/app/editor/panels/foldhaus_panel_file_view.h index eaf5013..aee1c19 100644 --- a/src/app/editor/panels/foldhaus_panel_file_view.h +++ b/src/app/editor/panels/foldhaus_panel_file_view.h @@ -49,30 +49,31 @@ s32 FileView_CommandsCount = 0; internal void FileView_UpdateWorkingDirectory(gs_const_string WorkingDirectory, file_view_state* State, context Context) { + // NOTE(pjs): make sure we're only passing valid directory paths to the + // function + char LastChar = WorkingDirectory.Str[WorkingDirectory.Length - 1]; + Assert(LastChar == '\\' || LastChar == '/'); ClearArena(&State->FileNamesArena); - gs_const_string SanitizedDirectory = WorkingDirectory; - - u32 LastSlashIndex = FindLast(SanitizedDirectory, '\\'); - gs_const_string LastDir = Substring(SanitizedDirectory, LastSlashIndex + 1, SanitizedDirectory.Length); - if (StringsEqual(LastDir, ConstString(".."))) + gs_string SanitizedDir = PushString(Context.ThreadContext.Transient, WorkingDirectory.Length + 2); + SanitizePath(WorkingDirectory, &SanitizedDir, Context.ThreadContext.Transient); + if (SanitizedDir.Str[SanitizedDir.Length - 1] != '\\') { - u32 SecondLastSlashIndex = FindLast(SanitizedDirectory, LastSlashIndex - 1, '\\'); - SanitizedDirectory = Substring(SanitizedDirectory, 0, SecondLastSlashIndex); - } - else if (StringsEqual(LastDir, ConstString(".")) && LastDir.Length > 1) - { - SanitizedDirectory = Substring(SanitizedDirectory, 0, LastSlashIndex); + AppendPrintF(&SanitizedDir, "\\"); } - gs_file_info NewWorkingDirectory = GetFileInfo(Context.ThreadContext.FileHandler, SanitizedDirectory); - if (NewWorkingDirectory.IsDirectory) + gs_file_info NewWorkingDir = GetFileInfo(Context.ThreadContext.FileHandler, SanitizedDir.ConstString); + if (NewWorkingDir.IsDirectory) { + AppendPrintF(&SanitizedDir, "*"); + NullTerminate(&SanitizedDir); + + State->FileNames = EnumerateDirectory(Context.ThreadContext.FileHandler, &State->FileNamesArena, SanitizedDir.ConstString, EnumerateDirectory_IncludeDirectories); + // NOTE(pjs): we might be printing from State->WorkingDirectory to State->WorkingDirectory // in some cases. Shouldn't be a problem but it is unnecessary - PrintF(&State->WorkingDirectory, "%S", WorkingDirectory); + PrintF(&State->WorkingDirectory, "%S", SanitizedDir.ConstString); - State->FileNames = EnumerateDirectory(Context.ThreadContext.FileHandler, &State->FileNamesArena, State->WorkingDirectory.ConstString, EnumerateDirectory_IncludeDirectories); } } @@ -88,7 +89,7 @@ FileView_Init(panel* Panel, app_state* State, context Context) // TODO(pjs): this shouldn't be stored in permanent FileViewState->WorkingDirectory = PushString(&State->Permanent, 256); - FileView_UpdateWorkingDirectory(ConstString("."), FileViewState, Context); + FileView_UpdateWorkingDirectory(ConstString(".\\"), FileViewState, Context); } GSMetaTag(panel_cleanup); @@ -105,14 +106,26 @@ internal void FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state); - Assert(FileViewState->Mode == FileViewMode_Save); ui_PushLayout(&State->Interface, PanelBounds, LayoutDirection_TopDown, MakeString("FileView Layout")); { - if (ui_Button(&State->Interface, MakeString("Exit"))) + + ui_BeginRow(&State->Interface, 3); { - FileView_Exit_(Panel, State, Context); + if (FileViewState->Mode == FileViewMode_Save) + { + if (ui_Button(&State->Interface, MakeString("Save"))) + { + FileView_Exit_(Panel, State, Context); + } + } + + if (ui_Button(&State->Interface, MakeString("Exit"))) + { + FileView_Exit_(Panel, State, Context); + } } + ui_EndRow(&State->Interface); // Header if (ui_TextEntry(&State->Interface, MakeString("pwd"), &FileViewState->WorkingDirectory)) @@ -137,7 +150,7 @@ FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBu { gs_file_info File = FileViewState->FileNames.Values[i]; - u32 LastSlashIndex = FindLast(File.Path, '\\'); + u32 LastSlashIndex = FindLast(File.Path, File.Path.Length - 2, '\\'); gs_const_string FileName = Substring(File.Path, LastSlashIndex + 1, File.Path.Length); gs_string PathString = PushString(State->Transient, FileName.Length); PrintF(&PathString, "%S", FileName); @@ -150,8 +163,19 @@ FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBu } else { - FileViewState->SelectedFile = File; - FileView_Exit_(Panel, State, Context); + switch (FileViewState->Mode) + { + FileViewState->SelectedFile = File; + case FileViewMode_Load: + { + FileView_Exit_(Panel, State, Context); + } break; + + case FileViewMode_Save: + { + + } break; + } } } } diff --git a/src/app/editor/panels/foldhaus_panel_hierarchy.h b/src/app/editor/panels/foldhaus_panel_hierarchy.h index 13d45fe..7979512 100644 --- a/src/app/editor/panels/foldhaus_panel_hierarchy.h +++ b/src/app/editor/panels/foldhaus_panel_hierarchy.h @@ -69,7 +69,7 @@ HierarchyView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* Ren if (ui_Button(&State->Interface, MakeString("+ Add Assembly"))) { panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context); - FileView_SetMode(FileBrowser, FileViewMode_Save); + FileView_SetMode(FileBrowser, FileViewMode_Load); Panel_PushModalOverride(Panel, FileBrowser, LoadAssemblyCallback); } ui_EndRow(&State->Interface); diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 13f5dc5..9112a93 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -57,7 +57,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->LedSystem = LedSystem_Create(Context.ThreadContext.Allocator, 128); State->AssemblyDebugState = AssemblyDebug_Create(&State->Permanent); State->AssemblyDebugState.Brightness = 255; - State->AssemblyDebugState.Override = ADS_Override_AllBlue; + State->AssemblyDebugState.Override = ADS_Override_None; GlobalDebugServices->Interface.RenderSculpture = true; @@ -80,7 +80,7 @@ INITIALIZE_APPLICATION(InitializeApplication) Panel_SetType(Profiler, &State->PanelSystem, PanelType_ProfilerView, State, Context); panel* Hierarchy = LeftPanel->Left; - Panel_SetType(Hierarchy, &State->PanelSystem, PanelType_HierarchyView, State, Context); + Panel_SetType(Hierarchy, &State->PanelSystem, PanelType_AssemblyDebug, State, Context); } diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index 7f10ab0..35a539d 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -11,6 +11,7 @@ #include "..\gs_libs\gs_types.h" #include "..\gs_libs\gs_types.cpp" +#include "..\gs_libs\gs_path.h" struct handle { diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index df968c8..e959107 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -523,6 +523,8 @@ SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext) return Result; } +#include "../../gs_libs/gs_path.h" + int WINAPI WinMain ( HINSTANCE HInstance, @@ -533,6 +535,11 @@ WinMain ( { gs_thread_context ThreadContext = Win32CreateThreadContext(); + gs_file_info A = GetFileInfo(ThreadContext.FileHandler, ConstString("C:\\projects\\Lumenarium")); + + gs_file_info B = GetFileInfo(ThreadContext.FileHandler, ConstString("C:\\projects\\Lumenarium\\")); + + if (!SetWorkingDirectory(HInstance, ThreadContext)) return 1; MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); @@ -629,7 +636,7 @@ WinMain ( Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData); - bool Multithread = false; + bool Multithread = true; if (Multithread) { for (addressed_data_buffer* At = OutputData.Root; diff --git a/src/app/platform_win32/win32_foldhaus_fileio.h b/src/app/platform_win32/win32_foldhaus_fileio.h index 95163ea..a4f3edf 100644 --- a/src/app/platform_win32/win32_foldhaus_fileio.h +++ b/src/app/platform_win32/win32_foldhaus_fileio.h @@ -178,28 +178,39 @@ Win32SetFileInfoFromFindFileData(gs_file_info* Info, WIN32_FIND_DATA FindFileDat { 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); + + // 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 + 2); + PrintF(&FileName, "%S%.*s", SearchPath, FileName.Size, FindFileData.cFileName); + if (Info->IsDirectory) + { + AppendPrintF(&FileName, "\\"); + } + NullTerminate(&FileName); + + Info->Path = FileName.ConstString; } internal u32 Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* TempList, gs_const_string Path, gs_memory_arena* Storage, b32 Flags) { u32 FilesCount = 0; + Assert(Path.Str[Path.Length - 1] != '\\' && + Path.Str[Path.Length - 1] != '/'); + gs_const_string SearchPath = Path; - s64 IndexOfLastSlash = FindLastFromSet(Path, "\\/"); - Assert(IndexOfLastSlash >= 0); - gs_const_string SearchPath = Substring(Path, 0, IndexOfLastSlash + 1); + gs_const_string SearchPathDir = SearchPath; + s64 LastSlash = FindLastFromSet(SearchPath, "\\/"); + if (LastSlash >= 0) + { + SearchPathDir = Substring(SearchPath, 0, LastSlash + 1); + } WIN32_FIND_DATA FindFileData; HANDLE SearchHandle = FindFirstFile(Path.Str, &FindFileData); @@ -211,15 +222,18 @@ Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* if (HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) { + gs_const_string SubDirName = ConstString(FindFileData.cFileName); + bool IsNav = (StringsEqual(SubDirName, ConstString(".")) || + StringsEqual(SubDirName, ConstString(".."))); + if (HasFlag(Flags, EnumerateDirectory_Recurse)) { - gs_const_string SubDirName = ConstString(FindFileData.cFileName); - if (!StringsEqual(SubDirName, ConstString(".")) && - !StringsEqual(SubDirName, ConstString(".."))) + if (!IsNav) { 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); + FilesCount += Win32EnumerateDirectoryIntoTempList(FileHandler, TempList, SubDirectoryPath.ConstString, + Storage, Flags); } } @@ -230,7 +244,7 @@ Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* { temp_file_list_entry* File = PushStruct(FileHandler.Transient, temp_file_list_entry); *File = {0}; - Win32SetFileInfoFromFindFileData(&File->Info, FindFileData, SearchPath, Storage); + Win32SetFileInfoFromFindFileData(&File->Info, FindFileData, SearchPathDir, Storage); SLLPushOrInit(TempList->First, TempList->Last, File); FilesCount += 1; } diff --git a/src/app/platform_win32/win32_foldhaus_serial.h b/src/app/platform_win32/win32_foldhaus_serial.h index 71b4c99..7f21539 100644 --- a/src/app/platform_win32/win32_foldhaus_serial.h +++ b/src/app/platform_win32/win32_foldhaus_serial.h @@ -146,6 +146,11 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer) // ie. the usb stick was removed }break; + case ERROR_ACCESS_DENIED: + { + // ?? + }break; + case ERROR_INVALID_HANDLE: InvalidDefaultCase; } diff --git a/src/sculpture_gen/gen_blumen_lumen.cpp b/src/sculpture_gen/gen_blumen_lumen.cpp index dce5c4a..d1f4462 100644 --- a/src/sculpture_gen/gen_blumen_lumen.cpp +++ b/src/sculpture_gen/gen_blumen_lumen.cpp @@ -191,7 +191,7 @@ int main(int ArgCount, char** Args) u32 BloomInnerChannels[] = { FSC(0, 0), FSC(0, 1), FSC(0, 2), FSC(0, 3), FSC(0, 4), FSC(0, 5) }; flower_desc F0 = {}; F0.Pos = v3{-1, 0, 0}; - F0.ComPort = "\\\\.\\COM4"; + F0.ComPort = "\\\\.\\COM11"; F0.FlowerTagValue = "left"; F0.StemChannels = StemChannels; F0.BloomOuterChannels = BloomOuterChannels; @@ -200,7 +200,7 @@ int main(int ArgCount, char** Args) flower_desc F1 = {}; F1.Pos = v3{0, 0, 0}; - F1.ComPort = "\\\\.\\COM5"; + F1.ComPort = "\\\\.\\COM12"; F1.FlowerTagValue = "center"; F1.StemChannels = StemChannels; F1.BloomInnerChannels = BloomInnerChannels;