diff --git a/code/build_win32.bat b/code/build_win32.bat index 73765ed..2a15fa4 100644 --- a/code/build_win32.bat +++ b/code/build_win32.bat @@ -12,5 +12,5 @@ cl %CommonCompilerOptions% ../code/win32_main.cpp /link user32.lib gdi32.lib win xcopy /y /q win32_main.exe vn.exe del win32_main.* - del *.pdb +del *.pdb popd \ No newline at end of file diff --git a/code/core/core.h b/code/core/core.h index 9934a61..be4a359 100644 --- a/code/core/core.h +++ b/code/core/core.h @@ -4,7 +4,7 @@ #define CORE_H #include -#include +//#include #include #include @@ -50,10 +50,18 @@ typedef intptr_t smm; #define global static #define persist static -#pragma section(".roglob", read) -#define read_only __declspec(allocate(".roglob")) +#if _WIN32 +# pragma section(".roglob", read) +# define read_only __declspec(allocate(".roglob")) +#else +# define read_only +#endif -#define per_thread __declspec(thread) +#if _WIN32 +# define per_thread __declspec(thread) +#else +# define per_thread __thread +#endif #define fallthrough @@ -186,6 +194,7 @@ auto __Temp = (Element)->Next->Prev;\ #define DeferLoop(Start, End) for(s32 ___ = ((Start), 0); ___ == 0; ++___, (End)) +#if 0 //- sixten: Atomics inline u64 AtomicExchangeU64(u64 volatile *Value, u64 New) @@ -218,6 +227,7 @@ inline void EndTicketMutex(ticket_mutex *Mutex) { AtomicAddU64(&Mutex->Serving, 1); } +#endif //- sixten: Axes enum axis2 diff --git a/code/core/core_math.cpp b/code/core/core_math.cpp index 7155e05..8fb8e4e 100644 --- a/code/core/core_math.cpp +++ b/code/core/core_math.cpp @@ -42,6 +42,18 @@ inline v2_r32 operator*=(v2_r32 &A, v2_r32 B) { return A = A * B; } inline v2_r32 operator/=(v2_r32 &A, v2_r32 B) { return A = A / B; } inline v2_r32 operator*=(v2_r32 &A, r32 B) { return A = A * B; } +inline b32 operator==(v2_r32 A, v2_r32 B) +{ + b32 Result = A.x == B.x && A.y == B.y; + return(Result); +} + +inline b32 operator!=(v2_r32 A, v2_r32 B) +{ + b32 Result = A.x != B.x || A.y != B.y; + return(Result); +} + inline r32 Inner(v2_r32 A, v2_r32 B) { r32 Result = A.x*B.x + A.y*B.y; @@ -73,6 +85,12 @@ inline v2_r32 NOZ(v2_r32 V) return(Result); } +inline v2_r32 Hadamard(v2_r32 A, v2_r32 B) +{ + v2_r32 Result = {A.x*B.x, A.y*B.y}; + return(Result); +} + inline v2_r32 LinearBlend(v2_r32 A, v2_r32 B, r32 x) { v2_r32 Result = A+(B-A)*x; diff --git a/code/core/core_math.h b/code/core/core_math.h index c1404a6..92d50ca 100644 --- a/code/core/core_math.h +++ b/code/core/core_math.h @@ -228,10 +228,13 @@ inline v2_r32 operator-=(v2_r32 &A, v2_r32 B); inline v2_r32 operator*=(v2_r32 &A, v2_r32 B); inline v2_r32 operator/=(v2_r32 &A, v2_r32 B); inline v2_r32 operator*=(v2_r32 &A, r32 B); +inline b32 operator==(v2_r32 A, v2_r32 B); +inline b32 operator!=(v2_r32 A, v2_r32 B); inline r32 Inner(v2_r32 A, v2_r32 B); inline r32 LengthSquared(v2_r32 V); inline r32 Length(v2_r32 V); inline v2_r32 NOZ(v2_r32 V); +inline v2_r32 Hadamard(v2_r32 A, v2_r32 B); inline v2_r32 LinearBlend(v2_r32 A, v2_r32 B, r32 x); inline v2_r32 Min(v2_r32 A, v2_r32 B); inline v2_r32 Max(v2_r32 A, v2_r32 B); diff --git a/code/core/core_memory.cpp b/code/core/core_memory.cpp index 9a27509..5ebb3c5 100644 --- a/code/core/core_memory.cpp +++ b/code/core/core_memory.cpp @@ -3,7 +3,7 @@ static void Copy(void *Dest, void *Source, umm Count) { - if(Count <= S64_Max) + if(Count <= S32_Max) { u8 *Dest8 = (u8 *)Dest; u8 *Source8 = (u8 *)Source; @@ -17,7 +17,7 @@ static void Copy(void *Dest, void *Source, umm Count) static void CopyReverse(void *Dest, void *Source, umm Count) { - if(Count <= S64_Max) + if(Count <= S32_Max) { u8 *Dest8 = (u8 *)Dest + Count; u8 *Source8 = (u8 *)Source + Count; @@ -31,7 +31,7 @@ static void CopyReverse(void *Dest, void *Source, umm Count) static void Fill(void *Dest, u8 Value, umm Count) { - if(Count <= S64_Max) + if(Count <= S32_Max) { u8 *Dest8 = (u8 *)Dest; diff --git a/code/core/core_string.cpp b/code/core/core_string.cpp index ca7825a..677a9f7 100644 --- a/code/core/core_string.cpp +++ b/code/core/core_string.cpp @@ -1,5 +1,5 @@ #define STB_SPRINTF_IMPLEMENTATION -#include "third_party/stb_sprintf.h" +#include "../third_party/stb_sprintf.h" //~ sixten: Char funcitons diff --git a/code/generated/vn_assets.meta.c b/code/generated/vn_assets.meta.c new file mode 100644 index 0000000..35f0e83 --- /dev/null +++ b/code/generated/vn_assets.meta.c @@ -0,0 +1,27 @@ +char * AssetPathLUT[5] = +{ +"", +"backgrounds/test.jpg", +"characters/test_normal.png", +"characters/test_happy.png", +"characters/monika_leaning.png", +}; + +bool AssetIsPermanentLUT[5] = +{ +false, +false, +false, +false, +false, +}; + +char * AssetNameLUT[5] = +{ +"None", +"DemoBackground", +"ArthurNormal", +"ArthurHappy", +"MonikaLeaning", +}; + diff --git a/code/generated/vn_assets.meta.h b/code/generated/vn_assets.meta.h new file mode 100644 index 0000000..26a6296 --- /dev/null +++ b/code/generated/vn_assets.meta.h @@ -0,0 +1,16 @@ +enum asset_id +{ +AssetID_None, +AssetID_DemoBackground, +AssetID_ArthurNormal, +AssetID_ArthurHappy, +AssetID_MonikaLeaning, +AssetID_COUNT, +}; + +extern char * AssetPathLUT[5]; + +extern bool AssetIsPermanentLUT[5]; + +extern char * AssetNameLUT[5]; + diff --git a/code/vn.cpp b/code/vn.cpp index ffa9cb8..1751eef 100644 --- a/code/vn.cpp +++ b/code/vn.cpp @@ -18,6 +18,7 @@ global debug_settings *DEBUG_DebugSettings = 0; #include "generated/vn_character.meta.h" +#include "vn_asset.h" #include "vn_tokenizer.h" #include "vn_config.h" #include "vn_font.h" @@ -35,6 +36,7 @@ global debug_settings *DEBUG_DebugSettings = 0; #include "generated/vn_character.meta.c" +#include "vn_asset.cpp" #include "vn_tokenizer.cpp" #include "vn_config.cpp" #include "vn_render.cpp" @@ -54,6 +56,8 @@ struct vn_state arena *Arena; arena *FrameArena; + assets Assets; + glyph_atlas *GlyphAtlas; config *Config; @@ -125,7 +129,10 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender) State->Config = CreateConfig(); //- sixten: load assets - State->BackgroundTexture = CreateTextureFromPath(RenderCommands, StrLit("data/backgrounds/ddlc-club.png")); + State->Assets.AllocateTexture = RenderCommands->AllocateTexture; + LoadPermanentAssets(&State->Assets); + + State->BackgroundTexture = TextureFromAssetID(AssetID_DemoBackground); //- sixten: setup config binds and load current config { @@ -141,19 +148,19 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender) Config_ReadFile(State->Config, StrLit("config.vn")); } - //- sixten: load startup scene scene_view *SceneView = &State->SceneView; SV_Init(SceneView, State->Arena); + //- sixten: load startup scene temporary_memory Scratch = GetScratch(); string SceneInput = Platform_ReadEntireFile(Scratch.Arena, StrLit("data/scene.vns")); compiled_scene Scene = S_ScriptFromText(Scratch.Arena, SceneInput); SV_SetCurrentSource(&Scene); ReleaseScratch(Scratch); - SceneView->TestHappy = CreateTextureFromPath(RenderCommands, StrLit("data/characters/test_happy.png")); - SceneView->TestNormal = CreateTextureFromPath(RenderCommands, StrLit("data/characters/test_normal.png")); - SceneView->MonikaLeaning = CreateTextureFromPath(RenderCommands, StrLit("data/characters/monika_leaning.png")); + SceneView->TestHappy = TextureFromAssetID(AssetID_ArthurHappy); + SceneView->TestNormal = TextureFromAssetID(AssetID_ArthurNormal); + SceneView->MonikaLeaning = TextureFromAssetID(AssetID_MonikaLeaning); SceneView->BackgroundTexture = State->BackgroundTexture; @@ -172,8 +179,9 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender) //- sixten: begin new frame ArenaClear(State->FrameArena); + SetAssets(&State->Assets); AC_NewFrame(&State->AnimationCurveState, Input->dtForFrame); - UI_NewFrame(&State->UI, Input->EventList, Input->MouseP, State->GlyphAtlas); + UI_NewFrame(&State->UI, Input->EventList, Input->MouseP, Input->dtForFrame, State->GlyphAtlas); SV_NewFrame(&State->SceneView, Input->EventList, Input->dtForFrame); //- sixten: check for toggle between modes diff --git a/code/vn_asset.cpp b/code/vn_asset.cpp new file mode 100644 index 0000000..ddebaab --- /dev/null +++ b/code/vn_asset.cpp @@ -0,0 +1,78 @@ +global assets *Global_Assets; + +static assets *GetAssets() +{ + return(Global_Assets); +} + +static void SetAssets(assets *Assets) +{ + Global_Assets = Assets; +} + +static void LoadAsset(asset_id ID) +{ + assets *Assets = GetAssets(); + Assert(ID >= AssetID_None && ID < AssetID_COUNT); + + asset *Asset = Assets->Assets + ID; + + if(!Asset->IsLoaded) + { + temporary_memory Scratch = GetScratch(); + + string Filepath = PushFormat(Scratch.Arena, "data/%s", AssetPathLUT[ID]); + platform_file_handle File = Platform.OpenFile(Filepath, PlatformAccess_Read); + if(File.IsValid) + { + u64 DataCount = Platform.GetFileSize(File); + u8 *Data = PushArray(Scratch.Arena, u8, DataCount); + Platform.ReadFile(File, Data, 0, DataCount); + + s32 Width, Height, BPP; + u8 *TextureData = stbi_load_from_memory(Data, DataCount, &Width, &Height, &BPP, 0); + + render_texture_format TextureFormat = Render_TextureFormat_Invalid; + switch(BPP) + { + InvalidDefaultCase; + case 1: { TextureFormat = Render_TextureFormat_R8; } break; + case 3: { TextureFormat = Render_TextureFormat_RGB8; } break; + case 4: { TextureFormat = Render_TextureFormat_RGBA8; } break; + } + + Asset->Handle = Assets->AllocateTexture(V2S32(Width, Height), TextureFormat, true, TextureData); + + stbi_image_free(TextureData); + + Platform.CloseFile(File); + } + + ReleaseScratch(Scratch); + } +} +static void LoadPermanentAssets(assets *Assets) +{ + SetAssets(Assets); + + //- sixten: assign ID to all assets & load all permanent ones + for(int Index = 0; Index < AssetID_COUNT; ++Index) + { + asset_id ID = (asset_id)Index; + asset *Asset = Assets->Assets + Index; + Asset->ID = ID; + + if(ID != AssetID_None) + { + LoadAsset(ID); + } + } +} + +static render_handle TextureFromAssetID(asset_id ID) +{ + Assert(ID >= AssetID_None && ID < AssetID_COUNT); + + asset *Asset = GetAssets()->Assets + ID; + return(Asset->Handle); +} \ No newline at end of file diff --git a/code/vn_asset.h b/code/vn_asset.h new file mode 100644 index 0000000..0a42b29 --- /dev/null +++ b/code/vn_asset.h @@ -0,0 +1,23 @@ +#include "generated/vn_assets.meta.h" +#include "generated/vn_assets.meta.c" + +struct asset +{ + asset_id ID; + b32 IsLoaded; + render_handle Handle; +}; + +struct assets +{ + asset Assets[AssetID_COUNT]; + + render_allocate_texture *AllocateTexture; +}; + +static assets *GetAssets(); +static void SetAssets(assets *Assets); + +static void LoadAsset(asset_id ID); +static void LoadPermanentAssets(assets *Assets); +static render_handle TextureFromAssetID(asset_id ID); \ No newline at end of file diff --git a/code/vn_assets.md b/code/vn_assets.md new file mode 100644 index 0000000..5ac4a1e --- /dev/null +++ b/code/vn_assets.md @@ -0,0 +1,44 @@ +@table(Name, Path, IsPermanent) assets_desc: +{ + { None, "", false } + + //////////////////////////////// + //~ sixten: backgrounds + { DemoBackground, "backgrounds/test.jpg", false } + + //////////////////////////////// + //~ sixten: characters + + //- sixten: arthur + { ArthurNormal, "characters/test_normal.png", false } + { ArthurHappy, "characters/test_happy.png", false } + + //- sixten: monika + { MonikaLeaning, "characters/monika_leaning.png", false } + +} + + +@table_gen_enum asset_id: +{ + @expand(assets_desc s) `AssetID_$(s.Name),`; + `AssetID_COUNT,`; +} + +@table_gen_data(`char *`) AssetPathLUT: +{ + @expand(assets_desc s) + `"$(s.Path)",`; +} + +@table_gen_data(`bool`) AssetIsPermanentLUT: +{ + @expand(assets_desc s) + `$(s.IsPermanent),`; +} + +@table_gen_data(`char *`) AssetNameLUT: +{ + @expand(assets_desc s) + `"$(s.Name)",`; +} \ No newline at end of file diff --git a/code/vn_scene.cpp b/code/vn_scene.cpp index d6eed89..7e2ed82 100644 --- a/code/vn_scene.cpp +++ b/code/vn_scene.cpp @@ -898,11 +898,16 @@ static scene_value S_PopStackAndImplicitConvert(scene_runtime *Runtime) return(Result); } +static void S_SetCurrentProc(scene_runtime *Runtime, scene_proc *Proc) +{ + Runtime->CurrentProc = Proc; + Runtime->IP = 0; + Runtime->BranchCount = 0; +} + static void S_ResetRuntime(scene_runtime *Runtime) { - Runtime->IP = 0; - Runtime->CurrentProc = 0; - Runtime->BranchCount = 0; + S_SetCurrentProc(Runtime, 0); Fill(Runtime->GlobalVariableBuckets, 0, sizeof(Runtime->GlobalVariableBuckets)); ZeroStruct(&Runtime->GlobalVariableFreeList); @@ -1045,8 +1050,7 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, arena *FrameArena, b32 scene_proc *Dest = S_FindProcByName(Compiled, JumpDest); if(Dest) { - Runtime->CurrentProc = Dest; - Runtime->IP = 0; + S_SetCurrentProc(Runtime, Dest); } else { @@ -1083,7 +1087,7 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, arena *FrameArena, b32 if(Offset.Kind == S_ValueKind_Offset) { branch_case *Branch = &Runtime->Branches[Runtime->BranchCount]; - Branch->Name = Substring(Compiled->Source, BranchName.SourceRef); + Branch->Name = Substring(Compiled->Source, Pad(BranchName.SourceRef, -1)); Branch->Offset = Offset.Offset; Runtime->BranchCount += 1; } @@ -1142,7 +1146,7 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, arena *FrameArena, b32 if(State.Kind == S_ValueKind_Nil) { - Action->State = CR_State_None; + Action->State = CR_State_Invalid; } else { diff --git a/code/vn_scene_view.cpp b/code/vn_scene_view.cpp index 8392ceb..1453b5b 100644 --- a/code/vn_scene_view.cpp +++ b/code/vn_scene_view.cpp @@ -218,12 +218,9 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneTextboxDrawCallback) } -UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback) +static void SV_DrawBackground(scene_view *SceneView, ui_box *Box, render_group *Group) { - scene_view *SceneView = (scene_view *)Data; - v2 RenderDim = DimOfRange(Box->Rect); - r32 GlobalScale = CalculateGlobalScaleFromDim(RenderDim); //- sixten: render background // sixten(TODO, but soon): Currently we add Box->Rect.Min to everything, but that should really be a transform @@ -242,6 +239,16 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback) PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, SceneView->BackgroundTexture); #endif +} + +UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback) +{ + scene_view *SceneView = (scene_view *)Data; + + SV_DrawBackground(SceneView, Box, Group); + v2 RenderDim = DimOfRange(Box->Rect); + r32 GlobalScale = CalculateGlobalScaleFromDim(RenderDim); + //- sixten: render characters for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1) { @@ -260,58 +267,213 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback) } } -static void BuildScene(scene_view *View) +static b32 BuildSceneBranchButton(string Text, r32 GlobalScale) { + UI_SetNextFontSize(GlobalScale); + UI_SetNextFont(Font_Fancy); + UI_SetNextCornerRadius(5.0f); + + b32 Result = UI_Button(Text).Clicked; + return(Result); +} + +static void BuildProcView(scene_view *View, ui_box *Box) +{ + temporary_memory Scratch = GetScratch(); + + r32 GlobalScale = CalculateGlobalScaleFromRootBox(Box); + r32 ActiveScale = GlobalScale * 0.75f; + scene_runtime *Runtime = &View->Runtime; textbox *Textbox = &View->Textbox; + + //- sixten: build branches + UI_FillPadding UI_WidthFill UI_Height(UI_Pixels(2*ActiveScale, 1)) UI_Row() UI_FillPadding UI_Column() UI_FillPadding + { + b32 FoundOffset = false; + s64 Offset = 0; + for(s32 BranchIndex = 0; BranchIndex < Runtime->BranchCount; BranchIndex += 1) + { + branch_case *Branch = &Runtime->Branches[BranchIndex]; + if(BuildSceneBranchButton(PushFormat(Scratch.Arena, "%S#%i", Branch->Name, BranchIndex), ActiveScale)) + { + Offset = Branch->Offset; + FoundOffset = true; + } + + if(BranchIndex != Runtime->BranchCount - 1) + { + UI_Spacer(UI_Em(1, 1)); + } + } + if(FoundOffset) + { + Runtime->IP += 1+Offset; + Runtime->BranchCount = 0; + } + } + + //- sixten: build textbox + UI_Size(UI_Percent(1, 1), UI_Percent(0.3, 1)) + { + ui_box *TextBox = UI_MakeBox(0, StrLit("Scene Textbox")); + + scene_textbox_data *TextboxData = PushStruct(UI_FrameArena(), scene_textbox_data); + TextboxData->Textbox = Textbox; + TextboxData->SceneViewBox = Box; + TextboxData->Name = View->LastTalkingCharacter; + TextboxData->NameT = View->CharacterIsTalkingT; + UI_EquipBoxCustomDrawCallback(TextBox, BuildSceneTextboxDrawCallback, TextboxData); + } + + ReleaseScratch(Scratch); +} + +struct scene_nav_item_info +{ + scene_nav_item *Item; + ui_signal Signal; +}; + +UI_CUSTOM_DRAW_CALLBACK(BuildNavItemDrawCallback) +{ + scene_nav_item_info *Info = (scene_nav_item_info *)Data; + render_handle Texture = TextureFromAssetID(Info->Item->TextureID); + v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture)); + + range2_r32 DestRect = Range2R32(Box->Rect.Min, Box->Rect.Max); + range2_r32 SourceRect = Range2R32(V2R32(0, 0), TextureDim); + + v4_r32 Color = LinearBlend(Color_Grey, Color_White, Info->Signal.Hovering); + + PushTexturedQuad(Group, DestRect, SourceRect, Color, Color, Color, Color, 0, 0, 0, Texture); +} + +inline u32 U32FromRawR32(r32 Value) +{ + u32 Result = *(u32 *)&Value; + return(Result); +} + +static ui_signal SV_BuildNavItem(scene_nav_item *Item, r32 GlobalScale, v2_r32 GlobalDim) +{ + r32 AppliedScale = GlobalScale*Item->Scale; + + scene_nav_item_info *Data = PushStruct(UI_FrameArena(), scene_nav_item_info); + Data->Item = Item; + + render_handle Texture = TextureFromAssetID(Item->TextureID); + + v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture)); + v2_r32 TextureOrigin = Hadamard(TextureDim, Item->Origin); + + v2_r32 OffsetP = GlobalDim*(V2R32(1, 1) + Item->P)*0.5f; + v2_r32 OriginP = TextureOrigin*AppliedScale; + v2_r32 Dim = TextureDim*AppliedScale; + range2_r32 Dest = Range2R32(OffsetP-OriginP, OffsetP-OriginP+Dim); + + UI_SetNextFixedP(Dest.Min); + UI_SetNextSize(UI_Pixels(Dim.x, 1), UI_Pixels(Dim.y, 1)); + UI_SetNextHoverCursor(PlatformCursor_Hand); + + ui_box *ItemBox = UI_MakeBoxF(UI_BoxFlag_Clickable|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, + "View Item Box %i %S %p", + (U32FromRawR32(Item->Scale)<<4)+ + (U32FromRawR32(Item->Origin.x)<<17)+ + (U32FromRawR32(Item->Origin.y)<<11), + Item->HoverText, Item); + UI_EquipBoxCustomDrawCallback(ItemBox, BuildNavItemDrawCallback, Data); + + ui_signal Signal = UI_SignalFromBox(ItemBox); + Data->Signal = Signal; + + return(Signal); +} + +static ui_signal BuildNavItemAndLabel(scene_nav_item *Item, r32 GlobalScale, v2_r32 GlobalDim) +{ + ui_signal Signal = SV_BuildNavItem(Item, GlobalScale, GlobalDim); + if(Signal.Hovering) + { + UI_FontSize(GlobalScale*0.5f) UI_Font(Font_Fancy) UI_CornerRadius(4.0f) + UI_TooltipLabel(Item->HoverText, UI_MouseP()); + } + return(Signal); +} + +scene_nav_item Items[] = +{ + { + AssetID_ArthurHappy, + 0.01f, + V2R32(0.5f, 1.0f), + V2R32(0.15f, 0.6f), + StrLit("Talk to Arthur"), + { + S_NavAction_Proc, + StrLit("arthur_talk"), + } + }, + { + AssetID_MonikaLeaning, + 0.02f, + V2R32(0.5f, 1.0f), + V2R32(-0.4f, 0.6f), + StrLit("Talk to Monika"), + { + S_NavAction_Scene, + StrLit("ddlc"), + }, + }, +}; + +static void BuildNavView(scene_view *View, ui_box *Box) +{ + r32 GlobalScale = CalculateGlobalScaleFromRootBox(Box); + + for(int ItemIndex = 0; ItemIndex < ArrayCount(Items); ++ItemIndex) + { + scene_nav_item *Item = Items+ItemIndex; + if(BuildNavItemAndLabel(Item, GlobalScale, DimOfRange(Box->Rect)).Clicked) + { + // sixten: apply the action + if(Item->Action.Kind == S_NavAction_Proc) + { + S_SetCurrentProc(&View->Runtime, S_FindProcByName(&View->Runtime.Compiled, Item->Action.Content)); + } + else if(Item->Action.Kind == S_NavAction_Scene) + { + temporary_memory Scratch = GetScratch(); + string Filepath = PushFormat(Scratch.Arena, "data/%S.vns", Item->Action.Content);; + + string SceneInput = Platform_ReadEntireFile(Scratch.Arena, Filepath); + compiled_scene Scene = S_ScriptFromText(Scratch.Arena, SceneInput); + SV_SetCurrentSource(&Scene); + + ReleaseScratch(Scratch); + } + } + } +} + +static void BuildScene(scene_view *View) +{ UI_SetNextWidth(UI_Percent(1, 0)); UI_SetNextHeight(UI_Percent(1, 0)); UI_SetNextLayoutAxis(Axis2_Y); ui_box *Box = UI_MakeBox(0, StrLit("Scene View")); UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View); - if(SV_CurrentlyInProc()) + UI_Parent(Box) { - UI_Parent(Box) + if(SV_CurrentlyInProc()) { - //- sixten: build branches - UI_WidthFill UI_Height(UI_Percent(1, 0)) UI_Row() UI_FillPadding UI_Column() UI_FillPadding - { - b32 FoundOffset = false; - s64 Offset = 0; - for(s32 BranchIndex = 0; BranchIndex < Runtime->BranchCount; BranchIndex += 1) - { - branch_case *Branch = &Runtime->Branches[BranchIndex]; - if(UI_ButtonF("%S#%i", Branch->Name, BranchIndex).Clicked) - { - Offset = Branch->Offset; - FoundOffset = true; - } - } - if(FoundOffset) - { - Runtime->IP += 1+Offset; - Runtime->BranchCount = 0; - } - } - - //- sixten: build textbox - UI_Size(UI_Percent(1, 1), UI_Percent(0.3, 1)) - { - ui_box *TextBox = UI_MakeBox(0, StrLit("Scene Textbox")); - - scene_textbox_data *TextboxData = PushStruct(UI_FrameArena(), scene_textbox_data); - TextboxData->Textbox = Textbox; - TextboxData->SceneViewBox = Box; - TextboxData->Name = View->LastTalkingCharacter; - TextboxData->NameT = View->CharacterIsTalkingT; - UI_EquipBoxCustomDrawCallback(TextBox, BuildSceneTextboxDrawCallback, TextboxData); - } + BuildProcView(View, Box); + } + else + { + BuildNavView(View, Box); } - } - else - { - //- sixten: render environmental objects } } @@ -542,7 +704,10 @@ static void SV_UpdateInDialog(arena *FrameArena) } else { - Data->Info = SV_CharacterTextureFromAction(Action); + if(Action->State != CR_State_Invalid) + { + Data->Info = SV_CharacterTextureFromAction(Action);; + } Data->Talking = true; SceneView->CharacterIsTalking = true; @@ -575,6 +740,12 @@ static void SV_Update(arena *FrameArena) { scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex; + if(!SV_CurrentlyInProc()) + { + Data->Active = false; + Data->Talking = false; + } + AC_AnimateValueDirect(Data->Active, 0.5f, &Data->ActiveT); AC_AnimateValueDirect(Data->Talking, 0.4f, &Data->TalkingT); diff --git a/code/vn_scene_view.h b/code/vn_scene_view.h index 6abe779..7c64db7 100644 --- a/code/vn_scene_view.h +++ b/code/vn_scene_view.h @@ -32,6 +32,46 @@ struct scene_view_character_data r32 PctP; }; +enum scene_nav_action_kind +{ + S_NavAction_None, + S_NavAction_Proc, + S_NavAction_Scene, +}; + +struct scene_nav_action +{ + scene_nav_action_kind Kind; + string Content; +}; + +struct scene_nav_item +{ + asset_id TextureID; + r32 Scale; + v2_r32 Origin; + v2_r32 P; + string HoverText; + scene_nav_action Action; +}; + +global read_only scene_nav_item G_DefaultSceneNavItem = +{ + AssetID_ArthurNormal, + 0.01f, + V2R32(0.5f, 1.0f), + V2R32(0.0f, 0.0f), + StrLit(""), + S_NavAction_None +}; + +struct scene_nav +{ + scene_nav_item *Items; + s32 ItemCount; + s32 ItemMax; +}; + struct scene_view { arena *SceneArena; @@ -71,7 +111,11 @@ static void SV_Init(scene_view *View, arena *TextboxArena); static b32 SV_CurrentlyInProc(void); +static void SV_DrawBackground(scene_view *SceneView, ui_box *Box, render_group *Group); + +static ui_signal SV_BuildNavItem(scene_nav_item * Item, r32 GlobalScale, v2_r32 GlobalDim); static void SV_BuildSceneView(vn_input *Input); + static void SV_Update(arena *FrameArena); #endif //VN_SCENE_VIEW_H diff --git a/code/vn_ui.cpp b/code/vn_ui.cpp index 93e324c..4a65dd3 100644 --- a/code/vn_ui.cpp +++ b/code/vn_ui.cpp @@ -120,6 +120,11 @@ inline void *UI_GetDragDataPointer(void) return(Result); } +static r64 UI_Time(void) +{ + return(UI_GetState()->Time); +} + inline ui_key UI_EmptyKey(void) { ui_key Key = {}; @@ -468,6 +473,7 @@ static ui_signal UI_SignalFromBox(ui_box *Box) } Signal.MouseP = UI->MouseP; + Signal.dMouseP = UI->dMouseP; Signal.DragDelta = UI->MouseP - UI->DragStartP; Signal.Box = Box; @@ -677,9 +683,9 @@ static void UI_DrawBox(ui_box *Box, render_group *Group, glyph_atlas *GlyphAtlas } -static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis); +static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis, b32 ForceCalculate); -static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis) +static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis, b32 ForceCalculate = false) { r32 Result = 0; @@ -711,7 +717,14 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis) // sixten: if the size is zero, try to find it. if(Size == 0.0) { - Size = DimOfRange(Parent->Rect).E[Axis]; + if(ForceCalculate) + { + Size = UI_CalculateBoxSize(Parent, Axis, ForceCalculate); + } + else + { + Size = DimOfRange(Parent->Rect).E[Axis]; + } } Result = Size*Box->SemanticSize[Axis].Value; } @@ -725,7 +738,7 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis) case UI_SizeKind_ChildrenSum: { - Result = UI_CalculateChildrenSum(Box, Axis)*Box->SemanticSize[Axis].Value; + Result = UI_CalculateChildrenSum(Box, Axis, ForceCalculate)*Box->SemanticSize[Axis].Value; } break; InvalidDefaultCase; @@ -734,7 +747,13 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis) return(Result); } -static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis) +static v2_r32 UI_CalculateBoxDim(ui_box *Box) +{ + v2_r32 Result = V2R32(UI_CalculateBoxSize(Box, Axis2_X, true), UI_CalculateBoxSize(Box, Axis2_Y, true)); + return(Result); +} + +static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis, b32 ForceCalculate = false) { r32 Result = 0; @@ -744,7 +763,7 @@ static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis) Child != 0; Child = Child->Next) { - Result += UI_CalculateBoxSize(Child, Axis); + Result += UI_CalculateBoxSize(Child, Axis, ForceCalculate); } } else @@ -753,7 +772,7 @@ static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis) Child != 0; Child = Child->Next) { - Result = Max(Result, UI_CalculateBoxSize(Child, Axis)); + Result = Max(Result, UI_CalculateBoxSize(Child, Axis, ForceCalculate)); } } return(Result); @@ -778,8 +797,8 @@ static void UI_LayoutBox(ui_box *Box) { if(Child->Flags & UI_BoxFlag_AnimatePosition) { - Child->ApproachingRelativeP.x = AC_AnimateValueF(Child->ComputedRelativeP.x, Child->ComputedRelativeP.x, 0.1, "Box P.X %p", Child); - Child->ApproachingRelativeP.y = AC_AnimateValueF(Child->ComputedRelativeP.y, Child->ComputedRelativeP.y, 0.1, "Box P.Y %p", Child); + Child->ApproachingRelativeP.x = AC_AnimateValueF(Child->ComputedRelativeP.x, Child->ComputedRelativeP.x, 0.5, "Box P.X %p", Child); + Child->ApproachingRelativeP.y = AC_AnimateValueF(Child->ComputedRelativeP.y, Child->ComputedRelativeP.y, 0.5, "Box P.Y %p", Child); Child->Rect.Min = Box->Rect.Min + Child->ApproachingRelativeP + Box->Offset; Child->Rect.Max = Child->Rect.Min + Child->ComputedDim; @@ -891,14 +910,16 @@ inline void UI_ScanForHotAndActive(ui_box *Box, b32 *FoundHot, b32 *FoundActive) } } -static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, glyph_atlas *GlyphAtlas) +static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, r32 dtForFrame, glyph_atlas *GlyphAtlas) { UI_SetState(UI); ArenaClear(UI->FrameArena); UI->EventList = EventList; + UI->dMouseP = MouseP - UI->MouseP; UI->MouseP = MouseP; + UI->Time += dtForFrame; UI->GlyphAtlas = GlyphAtlas; diff --git a/code/vn_ui.h b/code/vn_ui.h index b2f2902..0946b29 100644 --- a/code/vn_ui.h +++ b/code/vn_ui.h @@ -116,6 +116,7 @@ struct ui_signal { ui_box *Box; v2 MouseP; + v2 dMouseP; v2 DragDelta; v2 Scroll; b8 Clicked; @@ -145,6 +146,8 @@ struct ui ui_key Hot; ui_key Active; + r64 Time; + ui_key NextHot; b32 NextHotSet; @@ -154,6 +157,7 @@ struct ui ui_style_stacks Stacks; platform_event_list *EventList; + v2 dMouseP; v2 MouseP; glyph_atlas *GlyphAtlas; @@ -182,6 +186,9 @@ inline void UI_GetDragDataPayload(void *Data); inline void UI_StoreDragPointer(void *Data); inline void *UI_GetDragDataPointer(void); +//- sixten: Helpers +static r64 UI_Time(void); + //- sixten: Key functions static ui_key UI_EmptyKey(void); static ui_key UI_SeedKey(ui_key Key, ui_key Seed); @@ -203,6 +210,6 @@ static void UI_Init(ui *UI); static void UI_BeginBuild(ui *UI, v2 ScreenDim); static void UI_EndBuild(void); static void UI_RenderFrame(render_group *RenderGroup); -static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, glyph_atlas *GlyphAtlas); +static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, r32 dtForFrame, glyph_atlas *GlyphAtlas); #endif //VN_UI_H diff --git a/code/vn_ui_utils.cpp b/code/vn_ui_utils.cpp index e347000..05ed5e6 100644 --- a/code/vn_ui_utils.cpp +++ b/code/vn_ui_utils.cpp @@ -237,13 +237,13 @@ static void UI_ScrollBegin(r32 *X, r32 *Y, ui_box_flags Flags, string Name) if(AllowOnX) { ScrollFlags |= UI_BoxFlag_OverflowX; - UI_SetNextOffsetX(-(*X)); + UI_SetNextOffsetX(-AC_AnimateValueF(*X, *X, 0.2f, "Scroll %S X", Name)); } if(AllowOnY) { ScrollFlags |= UI_BoxFlag_OverflowY; - UI_SetNextOffsetY(-(*Y)); + UI_SetNextOffsetY(-AC_AnimateValueF(*Y, *Y, 0.2f, "Scroll %S Y", Name)); } UI_SetNextSize(AllowOnX?UI_ChildrenSum(1, 1):UI_Percent(1, 0), @@ -261,6 +261,8 @@ static void UI_ScrollEnd(r32 *X, r32 *Y, ui_box_flags Flags, string Name) b32 AllowOnX = (X != 0); b32 AllowOnY = (Y != 0); + r32 ScrollAmount = UI_TopFontSize()*4.0f; + ui_box *ScrollableBox = UI_TopParent(); ui_signal ScrollableBoxSignal = UI_SignalFromBox(ScrollableBox); { @@ -293,7 +295,20 @@ static void UI_ScrollEnd(r32 *X, r32 *Y, ui_box_flags Flags, string Name) r32 StartOffset = UI_GetDragR32(); r32 EndOffset = StartOffset + Signal.DragDelta.x/ScrollScale; - AC_AnimateValueDirect(EndOffset, 0.2, X); + *X = EndOffset; + } + else + { + for(platform_event *Event = UI_EventList()->First; + Event != 0; + Event = Event->Next) + { + if(Event->Type == PlatformEvent_MouseScroll && Event->Scroll.x != 0) + { + *X -= Event->Scroll.x*ScrollAmount; + Platform_ConsumeEvent(UI_EventList(), Event); + } + } } } } @@ -331,7 +346,20 @@ static void UI_ScrollEnd(r32 *X, r32 *Y, ui_box_flags Flags, string Name) r32 StartOffset = UI_GetDragR32(); r32 EndOffset = StartOffset + Signal.DragDelta.y/ScrollScale; - AC_AnimateValueDirect(EndOffset, 0.2, Y); + *Y = EndOffset; + } + else + { + for(platform_event *Event = UI_EventList()->First; + Event != 0; + Event = Event->Next) + { + if(Event->Type == PlatformEvent_MouseScroll && Event->Scroll.y != 0) + { + *Y -= Event->Scroll.y*ScrollAmount; + Platform_ConsumeEvent(UI_EventList(), Event); + } + } } } } diff --git a/code/vn_workspace.cpp b/code/vn_workspace.cpp index cba0e22..5c366f5 100644 --- a/code/vn_workspace.cpp +++ b/code/vn_workspace.cpp @@ -1,6 +1,8 @@ #include "vn_workspace_commands.cpp" #include "vn_workspace_view.cpp" +#include "vn_workspace_file_lister.cpp" #include "vn_workspace_text_editor.cpp" +#include "vn_workspace_nav_editor.cpp" //- sixten: State management per_thread workspace *ThreadLocal_Workspace; @@ -10,7 +12,8 @@ static workspace_keybind Workspace_Keybinds[] = {Key_P, PlatformModifier_Ctrl, W_Command_SplitPanelHorizontal}, {Key_L, PlatformModifier_Ctrl, W_Command_SplitPanelVertical}, - {Key_O, PlatformModifier_Ctrl, W_Command_OpenView, W_View_TextEditor}, + {Key_O, PlatformModifier_Ctrl, W_Command_OpenView, W_ViewKind_FileLister}, + {Key_P, PlatformModifier_Ctrl|PlatformModifier_Shift, W_Command_OpenView, W_ViewKind_Settings}, #if VN_INTERNAL {Key_U, PlatformModifier_Ctrl|PlatformModifier_Shift, W_Command_ToggleRenderUIDebugRects}, @@ -27,13 +30,8 @@ static workspace *W_GetState(void) return(ThreadLocal_Workspace); } -static arena *W_FrameArena(void) -{ - return(ThreadLocal_Workspace->FrameArena); -} - //- sixten: Commands -static void W_IssueCommand(workspace_command_sig *Sig, u64 Argument = 0) +static void W_IssueCommand(workspace_command_sig *Sig, u64 Argument) { workspace_command *Result = 0; @@ -71,6 +69,8 @@ static void W_ProcessCommands(void) Fill(ToRemove, 0, sizeof(workspace_command)); DLLInsertLast(Workspace->FirstFreeCommand, Workspace->LastFreeCommand, ToRemove); } + + ArenaClear(Workspace->CommandDataArena); } static void W_ProcessKeyBinds() @@ -125,7 +125,7 @@ static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu) if(Signal.Clicked) { Workspace->Menu = Menu; - Workspace->MenuTransition = 0; + Workspace->MenuT = 0; } } else @@ -134,7 +134,7 @@ static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu) { if(Workspace->Menu != Menu) { - Workspace->MenuTransition = 0; + Workspace->MenuT = 0; } Workspace->Menu = Menu; @@ -195,14 +195,14 @@ static void W_BuildToolbar(void) if(Workspace->Menu != W_ToolbarMenu_None) { - r32 MenuTransition = Workspace->MenuTransition; + r32 MenuT = Workspace->MenuT; UI_SetNextTooltip(); UI_SetNextFixedX(Workspace->MenuP.x); UI_SetNextFixedY(Workspace->MenuP.y); UI_SetNextLayoutAxis(Axis2_Y); UI_SetNextWidth(UI_Pixels(250, 1)); - UI_SetNextHeight(UI_ChildrenSum(MenuTransition, 1)); + UI_SetNextHeight(UI_ChildrenSum(MenuT, 1)); ui_box *Dropdown = UI_MakeBoxF(UI_BoxFlag_DrawBackground | UI_BoxFlag_DrawDropShadow | UI_BoxFlag_Clip | @@ -231,31 +231,16 @@ static void W_BuildToolbar(void) } else if(Workspace->Menu == W_ToolbarMenu_View) { - workspace_panel *CurrentPanel = Workspace->CurrentPanel; + workspace_view_kind ViewKind = W_ViewKind_None; + if(W_BuildMenuItem(FontIcon_None, "Welcome", "").Clicked) {ViewKind = W_ViewKind_Startup;} + if(W_BuildMenuItem(FontIcon_Pencil, "File Lister", "Ctrl + O").Clicked) {ViewKind = W_ViewKind_FileLister;} + if(W_BuildMenuItem(FontIcon_Users, "Navigation Editor", "").Clicked) {ViewKind = W_ViewKind_NavEditor;} + if(W_BuildMenuItem(FontIcon_Terminal, "Scene View", "").Clicked) {ViewKind = W_ViewKind_SceneView;} + if(W_BuildMenuItem(FontIcon_Wrench, "Settings", "Ctrl + Shift + P").Clicked) {ViewKind = W_ViewKind_Settings;} - // sixten(TODO): The views should be created at the end of the frame i.e. this should be done via - // commmands instead. (since we want all things that deals with major state changes to occur at a fixed - // point in our programs execution) - - if(W_BuildMenuItem(FontIcon_None, "Welcome", "").Clicked) + if(ViewKind != W_ViewKind_None) { - W_CreateNewView(W_View_Startup, CurrentPanel); - Workspace->Menu = W_ToolbarMenu_None; - } - if(W_BuildMenuItem(FontIcon_Pencil, "Script Editor", "Ctrl + O").Clicked) - { - W_CreateNewView(W_View_TextEditor, CurrentPanel); - Workspace->Menu = W_ToolbarMenu_None; - } - if(W_BuildMenuItem(FontIcon_Terminal, "Scene View", "").Clicked) - { - W_CreateNewView(W_View_SceneView, CurrentPanel); - Workspace->Menu = W_ToolbarMenu_None; - } - - if(W_BuildMenuItem(FontIcon_Wrench, "Settings", "").Clicked) - { - W_CreateNewView(W_View_Settings, CurrentPanel); + W_IssueCommand(W_Command_OpenView, ViewKind); Workspace->Menu = W_ToolbarMenu_None; } } @@ -268,7 +253,7 @@ static void W_BuildToolbar(void) } } - AC_AnimateValueDirect(1, 0.1, &Workspace->MenuTransition); + AC_AnimateValueDirect(1, 0.1, &Workspace->MenuT); // sixten: Unless the mouse press was captured, we close the menu. if(Platform_KeyPress(Workspace->EventList, Key_MouseLeft)) @@ -316,6 +301,40 @@ static void W_DeletePanel(workspace_panel *Panel) DLLInsertLast(Workspace->FirstFreePanel, Workspace->LastFreePanel, Panel); } +static void W_PanelViewPush(workspace_panel_view_list *List, workspace_panel_view *PanelView) +{ + DLLInsertLast(List->First, List->Last, PanelView); + List->Count += 1; +} + +static void W_PanelViewRemove(workspace_panel_view_list *List, workspace_panel_view *PanelView) +{ + DLLRemove(List->First, List->Last, PanelView); + List->Count -= 1; +} + +static workspace_panel_view *W_CreatePanelView(void) +{ + workspace *Workspace = W_GetState(); + workspace_panel_view *PanelView = Workspace->PanelViewFreeList.First; + if(PanelView) + { + W_PanelViewRemove(&Workspace->PanelViewFreeList, PanelView); + } + else + { + PanelView = PushStruct(Workspace->PanelViewArena, workspace_panel_view); + } + return(PanelView); +} + +static void W_DeletePanelView(workspace_panel_view *PanelView) +{ + workspace *Workspace = W_GetState(); + ZeroStruct(PanelView); + W_PanelViewPush(&Workspace->PanelViewFreeList, PanelView); +} + static void W_SplitPanel(workspace_panel *Panel, axis2 Axis) { workspace *Workspace = W_GetState(); @@ -366,14 +385,23 @@ static void W_SplitPanel(workspace_panel *Panel, axis2 Axis) } } +static b32 W_ViewIsDragged(workspace_view *View) +{ + workspace *Workspace = W_GetState(); + b32 Result = (Workspace->DragPayloadState != W_DragPayload_Inactive && Workspace->DragPayload.View == View) && + UI_GetState()->DragStartP != UI_MouseP(); + return(Result); +} + inline void W_BeginDrag(workspace_drag_payload *Payload) { workspace *Workspace = W_GetState(); - // sixten(TODO): Right now, if you spam-click a draggable item, you can trigger this + // sixten(no longer a todo): Right now, if you spam-click a draggable item, you can trigger this // assertion. I don't know what I want to do about this at the moment, but I'm sure // future me will have a soulution at hand. ^.^ - Assert(Workspace->DragPayloadState == W_DragPayload_Inactive); + // Assert(Workspace->DragPayloadState == W_DragPayload_Inactive); + // sixten(from the future): I have concluded that this should never be an issue. Workspace->DragPayload = *Payload; Workspace->DragPayloadState = W_DragPayload_Active; @@ -395,65 +423,74 @@ static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View) b32 ViewIsCurrent = (Panel->CurrentView == View); b32 PanelIsCurrent = (Workspace->CurrentPanel == Panel); - string Name = W_GetViewName(View); + string Name = W_GetViewName(UI_FrameArena(), View); - v4 BackgroundColor = ViewIsCurrent ? (PanelIsCurrent ? Theme_HighlightBorderColor : Theme_BorderColor) : ColorFromHex(0x353738FF); + b32 Open = !(W_ViewIsDragged(View) && Workspace->DragPayloadState != W_DragPayload_Released); + r32 OpenT = AC_AnimateValueF(Open, 0.0f, 0.3f, "Workspace Tab Item %p", View); + r32 SpaceT = AC_AnimateValueF(Open, 1.0f, 0.3f, "Workspace Tab Item Space %p", View); - UI_SetNextWidth(UI_ChildrenSum(1, 1)); - UI_SetNextHeight(UI_Percent(1, 1)); - UI_SetNextBackgroundColor(BackgroundColor); - UI_SetNextBorderColor(LinearBlend(UI_TopBackgroundColor(), Color_Grey, 0.5)); - UI_SetNextLayoutAxis(Axis2_X); - UI_SetNextCornerRadius(0.0); - - ui_box *TabBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground | - UI_BoxFlag_DrawDropShadow | - UI_BoxFlag_HotAnimation | - UI_BoxFlag_ActiveAnimation | - UI_BoxFlag_Clickable, - "Workspace Panel Tab Item %S#%p", Name, View); - - UI_Parent(TabBox) - UI_Padding(UI_Pixels(5, 1)) + UI_Size(UI_ChildrenSum(SpaceT, 1), UI_Percent(1, 1)) UI_Column() { - UI_Size(UI_TextContent(1, 1), UI_Percent(1, 1)) UI_Label(Name); - UI_Spacer(UI_Pixels(5, 1)); + UI_Spacer(UI_Percent(1-OpenT, 1)); - // sixten: Build close button + v4 BackgroundColor = ViewIsCurrent ? (PanelIsCurrent ? Theme_HighlightBorderColor : Theme_BorderColor) : ColorFromHex(0x353738FF); + + UI_SetNextWidth(UI_ChildrenSum(1, 1)); + UI_SetNextHeight(UI_Percent(1, 1)); + UI_SetNextBackgroundColor(BackgroundColor); + UI_SetNextBorderColor(LinearBlend(UI_TopBackgroundColor(), Color_Grey, 0.5)); + UI_SetNextLayoutAxis(Axis2_X); + UI_SetNextCornerRadius(0.0); + + ui_box *TabBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground | + UI_BoxFlag_DrawDropShadow | + UI_BoxFlag_HotAnimation | + UI_BoxFlag_ActiveAnimation | + UI_BoxFlag_Clip | + UI_BoxFlag_Clickable, + "Workspace Panel Tab Item %S#%p", Name, View); + + UI_Parent(TabBox) UI_Padding(UI_Pixels(5, 1)) { - UI_SetNextFont(Font_Icons); - UI_SetNextSize(UI_TextContent(1, 1), UI_Percent(1, 1)); - UI_SetNextHoverCursor(PlatformCursor_Hand); + UI_Size(UI_TextContent(1, 1), UI_Percent(1, 1)) UI_Label(Name); + UI_Spacer(UI_Pixels(5, 1)); - ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "%U", FontIcon_Cancel); - - CloseBox->TextColor = LinearBlend(TabBox->BackgroundColor, Color_Black, 0.3 - CloseBox->HotTransition*0.8); - - ui_signal Signal = UI_SignalFromBox(CloseBox); - if(Signal.Clicked) + // sixten: Build close button { - W_IssueCommand(W_Command_CloseView, PointerToU64(View)); + UI_SetNextFont(Font_Icons); + UI_SetNextSize(UI_TextContent(1, 1), UI_Percent(1, 1)); + UI_SetNextHoverCursor(PlatformCursor_Hand); + + ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "%U", FontIcon_Cancel); + + CloseBox->TextColor = LinearBlend(TabBox->BackgroundColor, Color_Black, 0.3 - CloseBox->HotTransition*0.8); + + ui_signal Signal = UI_SignalFromBox(CloseBox); + if(Signal.Clicked) + { + W_IssueCommand(W_Command_CloseView, PointerToU64(View)); + } } } - } - - ui_signal Signal = UI_SignalFromBox(TabBox); - if(Signal.Clicked) - { - Workspace->CurrentPanel = Panel; - Panel->CurrentView = View; - } - - // sixten: Handle dragging the view. - if(Signal.Dragging) - { - if(Signal.Pressed) + + ui_signal Signal = UI_SignalFromBox(TabBox); + if(Signal.Clicked) { - workspace_drag_payload Payload = {}; - Payload.View = View; - Payload.Key = TabBox->Key; - - W_BeginDrag(&Payload); + Workspace->CurrentPanel = Panel; + Panel->CurrentView = View; + } + + // sixten: Handle dragging the view. + if(Signal.Dragging) + { + if(Signal.Pressed) + { + workspace_drag_payload Payload = {}; + Payload.View = View; + Payload.Key = TabBox->Key; + + W_BeginDrag(&Payload); + } } } } @@ -483,15 +520,11 @@ static void W_BuildPanelHeader(workspace_panel *Panel) UI_SetNextSize(UI_Pixels(30, 1), UI_Pixels(30, 1)); UI_SetNextFont(Font_Icons); - UI_SetNextBorderColor(ColorFromHex(0xA6514288)); - UI_SetNextBackgroundColor(ColorFromHex(0xC24630BB)); UI_SetNextCornerRadius(4); UI_SetNextHoverCursor(PlatformCursor_Hand); ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_HotAnimation | UI_BoxFlag_ActiveAnimation | - //UI_BoxFlag_DrawBackground | - //UI_BoxFlag_DrawBorder | UI_BoxFlag_DrawText | UI_BoxFlag_Clickable, "%U", FontIcon_Cancel); @@ -727,7 +760,7 @@ static void W_BuildDragPayload() workspace *Workspace = W_GetState(); workspace_drag_payload Payload; - if(W_GetDragPayload(&Payload)) + if(W_GetDragPayload(&Payload) && W_ViewIsDragged(Payload.View)) { if(Workspace->DragPayloadState == W_DragPayload_Released) { @@ -738,7 +771,7 @@ static void W_BuildDragPayload() { workspace_view *DraggedView = Payload.View; UI_SetNextCornerRadius(4); - UI_TooltipLabel(W_GetViewName(DraggedView), UI_MouseP()); + UI_TooltipLabel(W_GetViewName(UI_FrameArena(), DraggedView), UI_MouseP()); } else { @@ -755,36 +788,35 @@ static void W_Init(workspace *Workspace) { W_SetState(Workspace); - Workspace->FrameArena = ArenaAlloc(Kilobytes(32), true); Workspace->CommandArena = ArenaAlloc(Kilobytes(4), true); + Workspace->CommandDataArena = ArenaAlloc(Kilobytes(4), true); Workspace->PanelArena = ArenaAlloc(Kilobytes(4), true); Workspace->RootPanel = Workspace->CurrentPanel = W_CreateNewPanel(0); if(DEBUG_DebugSettings->ShowWelcomeMessage) { - W_CreateNewView(W_View_Startup, Workspace->RootPanel); + W_CreateNewView(W_ViewKind_Startup, Workspace->RootPanel); } // sixten: build text editor / scene view layout if(0) { - W_CreateNewView(W_View_TextEditor, Workspace->RootPanel); + W_CreateNewView(W_ViewKind_TextEditor, Workspace->RootPanel); W_SplitPanel(Workspace->RootPanel, Axis2_X); - W_CreateNewView(W_View_SceneView, Workspace->RootPanel->Last); + W_CreateNewView(W_ViewKind_SceneView, Workspace->RootPanel->Last); } + W_CreateNewView(W_ViewKind_NavEditor, Workspace->RootPanel); } -static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands, - vn_input *Input, glyph_atlas *GlyphAtlas) +static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands, vn_input *Input, glyph_atlas *GlyphAtlas) { - W_SetState(Workspace); - ArenaClear(Workspace->FrameArena); - Workspace->Input = Input; Workspace->EventList = Input->EventList; + W_SetState(Workspace); + // sixten: Process the keybinds and commands. W_ProcessKeyBinds(); W_ProcessCommands(); @@ -801,12 +833,10 @@ static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands, // sixten: Build the UI. { - W_BuildToolbar(); + W_BuildDragPayload(); + W_BuildToolbar(); UI_SetNextSize(UI_Percent(1, 1), UI_Percent(1, 0)); W_BuildPanel(Workspace->RootPanel); - - W_BuildDragPayload(); } - } \ No newline at end of file diff --git a/code/vn_workspace.h b/code/vn_workspace.h index ab86bb2..9bb4732 100644 --- a/code/vn_workspace.h +++ b/code/vn_workspace.h @@ -15,6 +15,21 @@ enum workspace_toolbar_menu W_ToolbarMenu_Window, }; +struct workspace_panel_view +{ + struct workspace_panel *Parent; + workspace_panel_view *Next; + workspace_panel_view *Prev; + struct workspace_view *View; +}; + +struct workspace_panel_view_list +{ + workspace_panel_view *First; + workspace_panel_view *Last; + s64 Count; +}; + struct workspace_panel { workspace_panel *First; @@ -23,10 +38,10 @@ struct workspace_panel workspace_panel *Prev; workspace_panel *Parent; - struct workspace_view *FirstView; - struct workspace_view *LastView; + workspace_view *FirstView; + workspace_view *LastView; - struct workspace_view *CurrentView; + workspace_view *CurrentView; axis2 SplitAxis; r32 PercentOfParent; @@ -70,11 +85,9 @@ struct workspace vn_input *Input; platform_event_list *EventList; - // sixten: General Purpose Allocation - arena *FrameArena; - // sixten: Command Allocation arena *CommandArena; + arena *CommandDataArena; workspace_command *FirstFreeCommand; workspace_command *LastFreeCommand; @@ -90,15 +103,20 @@ struct workspace workspace_drag_payload_state DragPayloadState; workspace_drag_payload DragPayload; + arena *PanelViewArena; + workspace_panel_view_list PanelViewFreeList; + workspace_toolbar_menu Menu; v2 MenuP; - r32 MenuTransition; + r32 MenuT; workspace_panel *RootPanel; workspace_panel *CurrentPanel; }; +#include "vn_workspace_file_lister.h" #include "vn_workspace_text_editor.h" +#include "vn_workspace_nav_editor.h" #include "vn_workspace_view.h" //////////////////////////////// @@ -107,10 +125,9 @@ struct workspace //- sixten: State management static void W_SetState(workspace *Workspace); static workspace *W_GetState(void); -static arena *W_FrameArena(void); //- sixten: Commands -static void W_IssueCommand(workspace_command_sig *Sig, u64 Argument); +static void W_IssueCommand(workspace_command_sig *Sig, u64 Argument = 0); static void W_ProcessCommands(void); //- sixten: Panels @@ -118,6 +135,15 @@ static workspace_panel *W_CreateNewPanel(workspace_panel *Parent); static void W_DeletePanel(workspace_panel *Panel); static void W_SplitPanel(workspace_panel *Panel, axis2 Axis); +//- sixten: Views +static b32 W_ViewIsDragged(workspace_view *View); + +//- sixten: Panel Views +static void W_PanelViewPush(workspace_panel_view_list *List, workspace_panel_view *PanelView); +static void W_PanelViewRemove(workspace_panel_view_list *List, workspace_panel_view *PanelView); +static workspace_panel_view *W_CreatePanelView(void); +static void W_DeletePanelView(workspace_panel_view *PanelView); + //- sixten: Builder code static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu); static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut); diff --git a/code/vn_workspace_commands.cpp b/code/vn_workspace_commands.cpp index 58e295f..61aa3ce 100644 --- a/code/vn_workspace_commands.cpp +++ b/code/vn_workspace_commands.cpp @@ -91,7 +91,7 @@ WORKSPACE_COMMAND(W_Command_ClosePanel) WORKSPACE_COMMAND(W_Command_OpenView) { workspace *Workspace = W_GetState(); - W_CreateNewView((workspace_view_type)Argument, Workspace->CurrentPanel); + W_CreateNewView((workspace_view_kind)Argument, Workspace->CurrentPanel); } WORKSPACE_COMMAND(W_Command_CloseView) @@ -108,18 +108,66 @@ WORKSPACE_COMMAND(W_Command_CloseView) W_DestroyView(View); } +WORKSPACE_COMMAND(W_Command_OpenFile) +{ + temporary_memory Scratch = GetScratch(); + + workspace *Workspace = W_GetState(); + workspace_file_lister_action *Action = (workspace_file_lister_action *)U64ToPointer(Argument); + + string Filepath = PushFormat(Scratch.Arena, "%S/%S", Action->Path, Action->Name); + + platform_file_handle File = Platform.OpenFile(Filepath, PlatformAccess_Read); + if(File.IsValid) + { + // sixten: retrieve file extension + string FileExtension = Substring(Action->Name, Range1S64(LastIndexOf(Action->Name, '.')+1, Action->Name.Count)); + if(AreEqual(FileExtension, StrLit("vns"))) + { + s64 FileSize = Platform.GetFileSize(File); + string ReplaceString = MakeString(PushArrayNoClear(Scratch.Arena, u8, FileSize+1), FileSize); + ReplaceString.Data[FileSize] = 0; + Platform.ReadFile(File, ReplaceString.Data, 0, FileSize); + + ReplaceString = RemoveAll(Scratch.Arena, ReplaceString, '\r'); + + workspace_view *View = W_CreateNewView(W_ViewKind_TextEditor, Workspace->CurrentPanel); + workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data; + + MutableStringReplaceRange(&Editor->Text, ReplaceString, Range1S64(0, 0)); + W_TextEditorApplyChanges(Editor); + Editor->FileName = PushString(View->Arena, Action->Name); + Editor->FilePath = PushString(View->Arena, Action->Path); + } + else if(AreEqual(FileExtension, StrLit("vnn"))) + { + s64 FileSize = Platform.GetFileSize(File); + string Contents = MakeString(PushArrayNoClear(Scratch.Arena, u8, FileSize), FileSize); + Platform.ReadFile(File, Contents.Data, 0, Contents.Count); + + workspace_view *View = W_CreateNewView(W_ViewKind_NavEditor, Workspace->CurrentPanel); + W_SetupNavEditor(View, Contents); + } + else + { + workspace_view *View = W_CreateNewView(W_ViewKind_Error, Workspace->CurrentPanel); + workspace_view_error *Error = (workspace_view_error *)View->Data; + Error->Message = PushFormat(View->Arena, "Unknown file extension: %S", FileExtension); + } + + Platform.CloseFile(File); + } + else + { + // sixten: what happens now?? + } + + ReleaseScratch(Scratch); +} + #if VN_INTERNAL WORKSPACE_COMMAND(W_Command_ToggleRenderUIDebugRects) { DEBUG_DebugSettings->RenderUIDebugRects = !DEBUG_DebugSettings->RenderUIDebugRects; } #endif - -WORKSPACE_COMMAND(W_Command_Test) -{ - for(s32 Index = 0; Index < 10000; Index += 1) - { - W_IssueCommand(W_Command_OpenView, W_View_TextEditor); - W_IssueCommand(W_Command_CloseView, 0); - } -} \ No newline at end of file diff --git a/code/vn_workspace_file_lister.cpp b/code/vn_workspace_file_lister.cpp new file mode 100644 index 0000000..05c1057 --- /dev/null +++ b/code/vn_workspace_file_lister.cpp @@ -0,0 +1,246 @@ +static workspace_file_lister_action *W_FileListerActionCopy(arena *Arena, workspace_file_lister_action *Action) +{ + workspace_file_lister_action *Result = PushStruct(Arena, workspace_file_lister_action); + Result->HasRequestedFile = Action->HasRequestedFile; + Result->Path = PushString(Arena, Action->Path); + Result->Name = PushString(Arena, Action->Name); + return(Result); +} + +UI_CUSTOM_DRAW_CALLBACK(W_FileListerInputCallback) +{ + workspace_view_file_lister *Lister = (workspace_view_file_lister *)Data; + s64 ClampedCursor = Clamp(0, Box->String.Count, Lister->InputEditState.Cursor); + s64 ClampedMark = Clamp(0, Box->String.Count, Lister->InputEditState.Mark); + string ToCursor = MakeString(Box->String.Data, ClampedCursor); + string ToMark = MakeString(Box->String.Data, ClampedMark); + + r32 TargetCursorX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToCursor); + r32 TargetMarkerX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToMark); + + r32 CursorX = AC_AnimateValueF(TargetCursorX, 0, 0.175, "Workspace View Input Cursor %p", Box); + r32 MarkerX = AC_AnimateValueF(TargetMarkerX, 0, 0.175, "Workspace View Input Mark %p", Box); + + v2 BoxDim = DimOfRange(Box->Rect); + + // sixten: Draw selection + { + v2 Offset = V2(7.5, (BoxDim.y - Box->FontSize) / 2); + v2 Dim = V2(0, Box->FontSize); + if(CursorX > MarkerX) + { + Offset.x += MarkerX; + Dim.x = CursorX - MarkerX; + } + else + { + Offset.x += CursorX; + Dim.x = MarkerX - CursorX; + } + + v2 P = Box->Rect.Min + Offset; + v4 Color = V4(0.4, 0.7, 0.8, 0.3); + PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0); + } + + // sixten: Draw cursor + { + range1_r32 CursorSpan = Range1R32(CursorX, TargetCursorX); + r32 Height = Box->FontSize + 4; + v2 Offset = V2(7.5F + CursorSpan.Min, (BoxDim.y - Height) / 2); + v2 Dim = V2(1.25F + CursorSpan.Max - CursorSpan.Min, Height); + + v2 P = Box->Rect.Min + Offset; + v4 Color = V4(0.3, 1, 0.3, 0.7); + PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0); + } +} + +static b32 W_BuildFileListerItem(string Text, u32 Icon, b32 Selected, b32 EnterPressed) +{ + b32 Result = false; + UI_SetNextLayoutAxis(Axis2_X); + UI_SetNextHoverCursor(PlatformCursor_Hand); + r32 SelectedT = AC_AnimateValueF(Selected, 0, 0.3f, "Lister Item %S", Text); + UI_SetNextBackgroundColor(LinearBlend(Theme_BackgroundColor, Theme_HighlightBorderColor, SelectedT*0.5)); + UI_SetNextBorderColor(LinearBlend(Theme_BorderColor, Theme_HighlightBorderColor, SelectedT)); + ui_box *Container = UI_MakeBoxF(UI_BoxFlag_DrawBorder | + UI_BoxFlag_DrawBackground | + UI_BoxFlag_Clickable | + UI_BoxFlag_HotAnimation | + UI_BoxFlag_ActiveAnimation| + UI_BoxFlag_DrawDropShadow, + "File Lister %S", Text); + UI_Parent(Container) + { + UI_Width(UI_Em(2, 1)) UI_Font(Font_Icons) UI_LabelF("%U", Icon); + UI_Width(UI_TextContent(0, 1)) UI_Label(Text); + } + + ui_signal Signal = UI_SignalFromBox(Container); + if(Signal.Clicked || Selected&&EnterPressed) + { + Result = true; + } + return(Result); +} + +static workspace_file_lister_action W_BuildFileLister(workspace_view *View) +{ + workspace_view_file_lister *Lister = (workspace_view_file_lister *)View->Data; + + workspace_file_lister_action ListerAction = {}; + temporary_memory Scratch = GetScratch(); + UI_Size(UI_Percent(1, 1), UI_Percent(1, 1)) + { + + b32 EnterPressed = Platform_KeyPress(UI_EventList(), Key_Return); + s32 SelectedItemDelta = 0; + + s32 ListerCount = 0; + + //- sixten: filename input field + if(W_ViewIsCurrent(View)) + { + for(platform_event *Event = UI_EventList()->First; Event != 0; Event = Event->Next) + { + if((Event->Type == PlatformEvent_Press || Event->Type == PlatformEvent_Text) && (Event->Codepoint != '/' && Event->Codepoint != '\\')) + { + text_action Action = SingleLineTextActionFromEvent(Event); + if(IsValid(&Action)) + { + text_op Op = TextOpFromAction(Scratch.Arena, MakeString(Lister->Input, Lister->InputUsed), &Lister->InputEditState, &Action); + if(Op.NewCursor >= 0 && Op.NewMark >= 0) + { + string Left = MakeString(Lister->Input, Op.Range.Min); + string Right = MakeString(Lister->Input + Op.Range.Max, Lister->InputUsed - Op.Range.Max); + + u64 NewStringSize = Left.Count + Right.Count + Op.ReplaceString.Count; + char *NewString = PushArray(Scratch.Arena, char, NewStringSize); + Copy(NewString, Left.Data, Left.Count); + Copy(NewString + Left.Count, Op.ReplaceString.Data, Op.ReplaceString.Count); + Copy(NewString + Left.Count + Op.ReplaceString.Count, Right.Data, Right.Count); + Lister->InputUsed = Minimum(ArrayCount(Lister->Input), NewStringSize); + Copy(Lister->Input, NewString, Lister->InputUsed); + + Lister->InputEditState.Cursor = Minimum(Op.NewCursor, Lister->InputUsed); + Lister->InputEditState.Mark = Minimum(Op.NewMark, Lister->InputUsed); + Platform_ConsumeEvent(UI_EventList(), Event); + } + } + } + + if(Event->Type == PlatformEvent_Press && (Event->Key == Key_Up || Event->Key == Key_Down)) + { + SelectedItemDelta = Event->Key == Key_Up ? -1 : 1; + } + } + } + + //- sixten: build navbar + UI_Height(UI_Em(2, 1)) UI_Row(UI_BoxFlag_DrawBorder) + { + UI_SetNextBackgroundColor(ColorFromHex(0x2D5790FF)); + UI_SetNextWidth(UI_TextContent(20, 1)); + UI_MakeBox(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawText, Lister->Path); + + UI_SetNextWidth(UI_TextContent(15, 1)); + ui_box *InputBox = UI_MakeBox(UI_BoxFlag_DrawText, StrLit("Text Lister Lister Input")); + UI_EquipBoxText(InputBox, MakeString(Lister->Input, Lister->InputUsed)); + UI_EquipBoxCustomDrawCallback(InputBox, W_FileListerInputCallback, Lister); + + UI_Padding(UI_Percent(1, 0)); + + UI_SetNextWidth(UI_TextContent(20, 1)); + if(UI_ButtonF("Open/Create").Clicked || EnterPressed) + { + ListerAction.HasRequestedFile = true; + ListerAction.Name = MakeString(Lister->Input, Lister->InputUsed); + ListerAction.Path = Lister->Path; + } + } + + UI_Scroll(0, &Lister->Scroll) + { + UI_Height(UI_Em(2, 1)) + { + //- sixten: display "parent directory button" + s64 LastSlash = LastIndexOf(Lister->Path, '/'); + if(LastSlash != -1) + { + b32 BackspacePressed = Lister->InputUsed == 0 && Platform_KeyPress(UI_EventList(), Key_Backspace); + if(W_BuildFileListerItem(StrLit("Parent Directory"), FontIcon_Reply, Lister->SelectedItem == ListerCount, EnterPressed) || + BackspacePressed) + { + Lister->Path = Prefix(Lister->Path, LastSlash); + Lister->InputUsed = 0; + Lister->SelectedItem = -1; + } + ListerCount += 1; + } + platform_file_info FileInfo; + platform_file_iter *FileIter; + + string Name = MakeString(Lister->Input, Lister->InputUsed); + string FullPath = PushFormat(Scratch.Arena, "%S/%S", Lister->Path, Name); + + //- sixten: display directories + { + FileIter = Platform.BeginFileIter(Scratch.Arena, FullPath); + for(;Platform.AdvanceFileIter(Scratch.Arena, FileIter, &FileInfo);) + { + if(FileInfo.IsDirectory) + { + if(W_BuildFileListerItem(FileInfo.Name, FontIcon_Folder, Lister->SelectedItem == ListerCount, EnterPressed)) + { + Lister->Path = PushFormat(View->Arena, "%S/%S", Lister->Path, FileInfo.Name); + Lister->InputUsed = 0; + Lister->SelectedItem = -1; + ListerAction.HasRequestedFile = false; // sixten: if we have selected a folder, but typed a name we want to open the folder. + } + ListerCount += 1; + } + } + } + Platform.EndFileIter(FileIter); + + //- sixten: display files + { + FileIter = Platform.BeginFileIter(Scratch.Arena, FullPath); + for(;Platform.AdvanceFileIter(Scratch.Arena, FileIter, &FileInfo);) + { + if(!FileInfo.IsDirectory) + { + if(W_BuildFileListerItem(FileInfo.Name, FontIcon_Document, Lister->SelectedItem == ListerCount, EnterPressed)) + { + ListerAction.HasRequestedFile = true; + Lister->SelectedItem = -1; + ListerAction.Name = PushString(View->Arena, FileInfo.Name); + ListerAction.Path = Lister->Path; + } + ListerCount += 1; + } + } + } + + //- sixten: update selected item + if(SelectedItemDelta != 0) + { + Lister->SelectedItem += SelectedItemDelta; + if(Lister->SelectedItem < 0) + { + Lister->SelectedItem += ListerCount; + } + else if(Lister->SelectedItem >= ListerCount) + { + Lister->SelectedItem -= ListerCount; + } + } + + Platform.EndFileIter(FileIter); + } + } + } + ReleaseScratch(Scratch); + return(ListerAction); +} diff --git a/code/vn_workspace_file_lister.h b/code/vn_workspace_file_lister.h new file mode 100644 index 0000000..b6918c3 --- /dev/null +++ b/code/vn_workspace_file_lister.h @@ -0,0 +1,26 @@ +#ifndef VN_WORKSPACE_FILE_LISTER_H +#define VN_WORKSPACE_FILE_LISTER_H + +struct workspace_file_lister_action +{ + b32 HasRequestedFile; + string Path; + string Name; +}; + +struct workspace_view_file_lister +{ + string Path; + r32 Scroll; + u8 Input[256]; + s32 InputUsed; + text_edit_state InputEditState; + s32 SelectedItem; +}; + +static workspace_file_lister_action *W_FileListerActionCopy(arena *Arena, workspace_file_lister_action *Action); + +static b32 W_BuildFileListerItem(string Text, u32 Icon, b32 Selected, b32 EnterPressed); +static workspace_file_lister_action W_BuildFileLister(workspace_view *View); + +#endif //VN_WORKSPACE_FILE_LISTER_H diff --git a/code/vn_workspace_nav_editor.cpp b/code/vn_workspace_nav_editor.cpp new file mode 100644 index 0000000..b510e37 --- /dev/null +++ b/code/vn_workspace_nav_editor.cpp @@ -0,0 +1,160 @@ +UI_CUSTOM_DRAW_CALLBACK(BuildNavViewDrawCallback) +{ + scene_view *SceneView = (scene_view *)Data; + SV_DrawBackground(SceneView, Box, Group); +} + +static scene_nav_item_node *W_SceneNavItemNodeAlloc(arena *Arena, workspace_view_nav_editor *Editor) +{ + scene_nav_item_node *Result = Editor->FirstFree; + if(Result) + { + DLLRemove(Editor->FirstFree, Editor->LastFree, Result); + *Result = {}; + } + else + { + Result = PushStruct(Arena, scene_nav_item_node); + } + + DLLInsertLast(Editor->Items.First, Editor->Items.Last, Result); + Editor->Items.Count += 1; + return(Result); +} + +static void W_SceneNavItemNodeRelease(workspace_view_nav_editor *Editor, scene_nav_item_node *Node) +{ + DLLInsertLast(Editor->FirstFree, Editor->LastFree, Node); + Editor->Items.Count -= 1; +} + +static void W_SetupNavEditor(workspace_view *View, string FileContents) +{ + //- sixten(TODO): deserialize data +} + +static void W_BuildNavEditor(workspace_view *View) +{ + workspace_view_nav_editor *Editor = (workspace_view_nav_editor *)View->Data; + scene_view *SceneView = SV_GetState(); + + UI_BackgroundColor(V4(0.25, 0.25, 0.25, 1)) + UI_BorderColor(V4(0.45, 0.45, 0.45, 1)) + UI_WidthFill UI_Height(UI_Em(2.0f, 1.0f)) + UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, "Workspace Nav Editor Toolbar")) + { + UI_Width(UI_TextContent(10, 1.0f)) UI_Font(Font_Icons) if(UI_ButtonF("%U", FontIcon_UserPlus).Clicked) + { + scene_nav_item_node *NewNode = W_SceneNavItemNodeAlloc(View->Arena, Editor); + NewNode->Item = G_DefaultSceneNavItem; + } + } + + UI_Row() + { + //- sixten: build inspector panel + UI_Width(UI_Percent(0.2f, 1.0f)) UI_HeightFill + UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBorder, StrLit("Workspace Nav Editor Inspector"))) + { + scene_nav_item_node *SelectedItem = Editor->SelectedItem; + if(SelectedItem) + { + } + else UI_WidthFill + { + UI_LabelF("No item selected."); + } + } + + //- sixten: build nav view + UI_Row() + { + //- sixten: calculate nav view size + r32 VerticalPad = 0; + r32 HorizontalPad = 0; + { + ui_box *ParentBox = UI_TopParent(); + v2_r32 ParentDim = DimOfRange(ParentBox->Rect); + + r32 WidthOverHeight = ParentDim.x / ParentDim.y; + r32 TargetRatio = 16.0f / 9.0f; + if(WidthOverHeight > TargetRatio) + { + VerticalPad = ParentDim.x - ParentDim.y*TargetRatio; + } + else + { + HorizontalPad = ParentDim.y - ParentDim.x/TargetRatio; + } + } + //- sixten: do the building of the nav view + UI_Padding(UI_Pixels(VerticalPad/2, 1)) + { + UI_Column() UI_Padding(UI_Pixels(HorizontalPad/2, 1)) + { + UI_SetNextWidth(UI_Percent(1, 0)); + UI_SetNextHeight(UI_Percent(1, 0)); + UI_SetNextLayoutAxis(Axis2_Y); + + ui_box *Box = UI_MakeBox(UI_BoxFlag_Clip, StrLit("Nav View")); + UI_EquipBoxCustomDrawCallback(Box, BuildNavViewDrawCallback, SceneView); + + v2_r32 BoxDim = UI_CalculateBoxDim(Box); + r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim); + + //- sixten: build all nav items + s32 ItemIndex = 0; + for(scene_nav_item_node *Node = Editor->Items.First; Node != 0; Node = Node->Next, ItemIndex += 1) + { + scene_nav_item *Item = &Node->Item; + + //- sixten: calculate item position + r32 AppliedScale = GlobalScale*Item->Scale; + render_handle Texture = TextureFromAssetID(Item->TextureID); + v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture)); + v2_r32 TextureOrigin = Hadamard(TextureDim, Item->Origin); + v2_r32 Dim = TextureDim*AppliedScale; + v2_r32 OriginP = TextureOrigin*AppliedScale; + + //- sixten: build the item + scene_nav_item_info *Data = PushStruct(UI_FrameArena(), scene_nav_item_info); + Data->Item = Item; + + UI_SetNextHoverCursor(PlatformCursor_Hand); + UI_SetNextSize(UI_Pixels(Dim.x, 1), UI_Pixels(Dim.y, 1)); + ui_box *ItemBox = UI_MakeBoxF(UI_BoxFlag_Clickable|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, + "View Item Box %i", ItemIndex); + UI_EquipBoxCustomDrawCallback(ItemBox, BuildNavItemDrawCallback, Data); + + //- sixten: handle signals + { + ui_signal Signal = UI_SignalFromBox(ItemBox); + Data->Signal = Signal; + + //- sixten: inspect pressed item + if(Signal.Pressed) + { + Editor->SelectedItem = Node; + } + + //- sixten: handle dragging + if(Signal.Dragging) + { + if(Signal.Pressed) + { + UI_StoreDragV2(Item->P); + } + + Item->P = UI_GetDragV2() + Signal.DragDelta/BoxDim*2; + } + } + + //- sixten: apply the calculated position + v2_r32 OffsetP = BoxDim*(V2R32(1, 1) + Item->P)*0.5f; + ItemBox->FixedP = (OffsetP-OriginP); + } + } + } + } + } +} \ No newline at end of file diff --git a/code/vn_workspace_nav_editor.h b/code/vn_workspace_nav_editor.h new file mode 100644 index 0000000..2c6476a --- /dev/null +++ b/code/vn_workspace_nav_editor.h @@ -0,0 +1,37 @@ +/* date = November 5th 2023 4:38 pm */ + +#ifndef VN_WORKSPACE_NAV_EDITOR_H +#define VN_WORKSPACE_NAV_EDITOR_H + +struct scene_nav_item_node +{ + scene_nav_item_node *Next; + scene_nav_item_node *Prev; + + scene_nav_item Item; +}; + +struct scene_nav_item_list +{ + scene_nav_item_node *First; + scene_nav_item_node *Last; + u64 Count; +}; + +struct workspace_view_nav_editor +{ + //- sixten: items + scene_nav_item_list Items; + scene_nav_item_node *FirstFree; + scene_nav_item_node *LastFree; + + scene_nav_item_node *SelectedItem; +}; + +static scene_nav_item_node *W_SceneNavItemNodeAlloc(arena *Arena, workspace_view_nav_editor *Editor); +static void W_SceneNavItemNodeRelease(workspace_view_nav_editor *Editor, scene_nav_item_node *Node); + +static void W_SetupNavEditor(workspace_view *View, string FileContents); +static void W_BuildNavEditor(workspace_view *View); + +#endif //VN_WORKSPACE_NAV_EDITOR_H diff --git a/code/vn_workspace_text_editor.cpp b/code/vn_workspace_text_editor.cpp index 7690dc6..f7f3618 100644 --- a/code/vn_workspace_text_editor.cpp +++ b/code/vn_workspace_text_editor.cpp @@ -377,238 +377,6 @@ static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback) } ReleaseScratch(Scratch); } -UI_CUSTOM_DRAW_CALLBACK(W_TextEditorListerInputCallback) -{ - workspace_view_text_editor *Editor = (workspace_view_text_editor *)Data; - s64 ClampedCursor = Clamp(0, Box->String.Count, Editor->ListerInputEditState.Cursor); - s64 ClampedMark = Clamp(0, Box->String.Count, Editor->ListerInputEditState.Mark); - string ToCursor = MakeString(Box->String.Data, ClampedCursor); - string ToMark = MakeString(Box->String.Data, ClampedMark); - - r32 TargetCursorX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToCursor); - r32 TargetMarkerX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToMark); - - r32 CursorX = AC_AnimateValueF(TargetCursorX, 0, 0.175, "Workspace View Input Cursor %p", Box); - r32 MarkerX = AC_AnimateValueF(TargetMarkerX, 0, 0.175, "Workspace View Input Mark %p", Box); - - v2 BoxDim = DimOfRange(Box->Rect); - - // sixten: Draw selection - { - v2 Offset = V2(7.5, (BoxDim.y - Box->FontSize) / 2); - v2 Dim = V2(0, Box->FontSize); - if(CursorX > MarkerX) - { - Offset.x += MarkerX; - Dim.x = CursorX - MarkerX; - } - else - { - Offset.x += CursorX; - Dim.x = MarkerX - CursorX; - } - - v2 P = Box->Rect.Min + Offset; - v4 Color = V4(0.4, 0.7, 0.8, 0.3); - PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0); - } - - // sixten: Draw cursor - { - range1_r32 CursorSpan = Range1R32(CursorX, TargetCursorX); - r32 Height = Box->FontSize + 4; - v2 Offset = V2(7.5F + CursorSpan.Min, (BoxDim.y - Height) / 2); - v2 Dim = V2(1.25F + CursorSpan.Max - CursorSpan.Min, Height); - - v2 P = Box->Rect.Min + Offset; - v4 Color = V4(0.3, 1, 0.3, 0.7); - PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0); - } -} - -static b32 W_BuildTextEditorListerItem(string Text, u32 Icon, b32 Selected, b32 EnterPressed) -{ - b32 Result = false; - UI_SetNextLayoutAxis(Axis2_X); - UI_SetNextHoverCursor(PlatformCursor_Hand); - r32 SelectedT = AC_AnimateValueF(Selected, 0, 0.3f, "Lister Item %S", Text); - UI_SetNextBackgroundColor(LinearBlend(Theme_BackgroundColor, Theme_HighlightBorderColor, SelectedT*0.5)); - UI_SetNextBorderColor(LinearBlend(Theme_BorderColor, Theme_HighlightBorderColor, SelectedT)); - ui_box *Container = UI_MakeBoxF(UI_BoxFlag_DrawBorder | - UI_BoxFlag_DrawBackground | - UI_BoxFlag_Clickable | - UI_BoxFlag_HotAnimation | - UI_BoxFlag_ActiveAnimation| - UI_BoxFlag_DrawDropShadow, - "File Lister %S", Text); - UI_Parent(Container) - { - UI_Width(UI_Em(2, 1)) UI_Font(Font_Icons) UI_LabelF("%U", Icon); - UI_Width(UI_TextContent(0, 1)) UI_Label(Text); - } - - ui_signal Signal = UI_SignalFromBox(Container); - if(Signal.Clicked || Selected&&EnterPressed) - { - Result = true; - } - return(Result); -} - -static workspace_text_editor_lister_action W_BuildTextEditorLister(workspace_view *View, workspace_view_text_editor *Editor) -{ - workspace_text_editor_lister_action ListerAction = {}; - temporary_memory Scratch = GetScratch(); - UI_Size(UI_Percent(1, 1), UI_Percent(1, 1)) UI_Scroll(0, &Editor->ListerScroll) - { - UI_Height(UI_Em(2, 1)) - { - b32 EnterPressed = Platform_KeyPress(UI_EventList(), Key_Return); - s32 SelectedItemDelta = 0; - - //- sixten: filename input field - if(W_ViewIsCurrent(View)) - { - for(platform_event *Event = UI_EventList()->First; Event != 0; Event = Event->Next) - { - if((Event->Type == PlatformEvent_Press || Event->Type == PlatformEvent_Text) && (Event->Codepoint != '/' && Event->Codepoint != '\\')) - { - text_action Action = SingleLineTextActionFromEvent(Event); - if(IsValid(&Action)) - { - text_op Op = TextOpFromAction(Scratch.Arena, MakeString(Editor->ListerInput, Editor->ListerInputUsed), &Editor->ListerInputEditState, &Action); - if(Op.NewCursor >= 0 && Op.NewMark >= 0) - { - string Left = MakeString(Editor->ListerInput, Op.Range.Min); - string Right = MakeString(Editor->ListerInput + Op.Range.Max, Editor->ListerInputUsed - Op.Range.Max); - - u64 NewStringSize = Left.Count + Right.Count + Op.ReplaceString.Count; - char *NewString = PushArray(Scratch.Arena, char, NewStringSize); - Copy(NewString, Left.Data, Left.Count); - Copy(NewString + Left.Count, Op.ReplaceString.Data, Op.ReplaceString.Count); - Copy(NewString + Left.Count + Op.ReplaceString.Count, Right.Data, Right.Count); - Editor->ListerInputUsed = Minimum(ArrayCount(Editor->ListerInput), NewStringSize); - Copy(Editor->ListerInput, NewString, Editor->ListerInputUsed); - - Editor->ListerInputEditState.Cursor = Minimum(Op.NewCursor, Editor->ListerInputUsed); - Editor->ListerInputEditState.Mark = Minimum(Op.NewMark, Editor->ListerInputUsed); - Platform_ConsumeEvent(UI_EventList(), Event); - } - } - } - - if(Event->Type == PlatformEvent_Press && (Event->Key == Key_Up || Event->Key == Key_Down)) - { - SelectedItemDelta = Event->Key == Key_Up ? -1 : 1; - } - } - } - - //- sixten: build navbar - UI_Row(UI_BoxFlag_DrawBorder) - { - UI_SetNextBackgroundColor(ColorFromHex(0x2D5790FF)); - UI_SetNextWidth(UI_TextContent(20, 1)); - UI_MakeBox(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawText, Editor->Path); - - UI_SetNextWidth(UI_TextContent(15, 1)); - ui_box *InputBox = UI_MakeBox(UI_BoxFlag_DrawText, StrLit("Text Editor Lister Input")); - UI_EquipBoxText(InputBox, MakeString(Editor->ListerInput, Editor->ListerInputUsed)); - UI_EquipBoxCustomDrawCallback(InputBox, W_TextEditorListerInputCallback, Editor); - - UI_Padding(UI_Percent(1, 0)); - - UI_SetNextWidth(UI_TextContent(20, 1)); - if(UI_ButtonF("Open/Create").Clicked || EnterPressed) - { - ListerAction.HasRequestedFile = true; - ListerAction.Name = MakeString(Editor->ListerInput, Editor->ListerInputUsed); - ListerAction.Path = Editor->Path; - } - } - - s32 ListerCount = 0; - - //- sixten: display "parent directory button" - s64 LastSlash = LastIndexOf(Editor->Path, '/'); - if(LastSlash != -1) - { - b32 BackspacePressed = Editor->ListerInputUsed == 0 && Platform_KeyPress(UI_EventList(), Key_Backspace); - if(W_BuildTextEditorListerItem(StrLit("Parent Directory"), FontIcon_Reply, Editor->SelectedItem == ListerCount, EnterPressed) || - BackspacePressed) - { - Editor->Path = Prefix(Editor->Path, LastSlash); - Editor->ListerInputUsed = 0; - Editor->SelectedItem = -1; - } - ListerCount += 1; - } - platform_file_info FileInfo; - platform_file_iter *FileIter; - - string Name = MakeString(Editor->ListerInput, Editor->ListerInputUsed); - string FullPath = PushFormat(Scratch.Arena, "%S/%S", Editor->Path, Name); - - //- sixten: display directories - { - FileIter = Platform.BeginFileIter(Scratch.Arena, FullPath); - for(;Platform.AdvanceFileIter(Scratch.Arena, FileIter, &FileInfo);) - { - if(FileInfo.IsDirectory) - { - if(W_BuildTextEditorListerItem(FileInfo.Name, FontIcon_Folder, Editor->SelectedItem == ListerCount, EnterPressed)) - { - Editor->Path = PushFormat(View->Arena, "%S/%S", Editor->Path, FileInfo.Name); - Editor->ListerInputUsed = 0; - Editor->SelectedItem = -1; - ListerAction.HasRequestedFile = false; // sixten: if we have selected a folder, but typed a name we want to open the folder. - } - ListerCount += 1; - } - } - } - Platform.EndFileIter(FileIter); - - //- sixten: display files - { - FileIter = Platform.BeginFileIter(Scratch.Arena, FullPath); - for(;Platform.AdvanceFileIter(Scratch.Arena, FileIter, &FileInfo);) - { - if(!FileInfo.IsDirectory) - { - if(W_BuildTextEditorListerItem(FileInfo.Name, FontIcon_Document, Editor->SelectedItem == ListerCount, EnterPressed)) - { - ListerAction.HasRequestedFile = true; - Editor->SelectedItem = -1; - ListerAction.Name = PushString(View->Arena, FileInfo.Name); - ListerAction.Path = Editor->Path; - } - ListerCount += 1; - } - } - } - - //- sixten: update selected item - if(SelectedItemDelta != 0) - { - Editor->SelectedItem += SelectedItemDelta; - if(Editor->SelectedItem < 0) - { - Editor->SelectedItem += ListerCount; - } - else if(Editor->SelectedItem >= ListerCount) - { - Editor->SelectedItem -= ListerCount; - } - } - - Platform.EndFileIter(FileIter); - } - } - ReleaseScratch(Scratch); - return(ListerAction); -} - static b32 W_ProcessTextEditorEvent(workspace_view_text_editor *Editor, platform_event *Event) { b32 CursorHasBeenModified = false; @@ -685,48 +453,6 @@ static void W_BuildTextEditor(workspace_view *View) s32 LineMarginDigitsRequired = 6; r32 LineMarginWidth = (LineMarginDigitsRequired)*GlyphAdvance; - b32 InFileListMode = AreEqual(Editor->FileName, StrLit("")); - if(InFileListMode) - { - //- sixten: handle esc to close - if(Platform_KeyPress(UI_EventList(), Key_Escape)) - { - W_IssueCommand(W_Command_CloseView, PointerToU64(View)); - } - - //- sixten: build & handle file lister - workspace_text_editor_lister_action Action = W_BuildTextEditorLister(View, Editor); - if(Action.HasRequestedFile) - { - //- sixten: try to load file - string FullPath = PushFormat(Scratch.Arena, "%S/%S", Action.Path, Action.Name); - platform_file_handle File = Platform.OpenFile(FullPath, PlatformAccess_Read); - - if(File.IsValid) - { - s64 FileSize = Platform.GetFileSize(File); - string ReplaceString = MakeString(PushArray(Scratch.Arena, u8, FileSize+1), FileSize); - Platform.ReadFile(File, ReplaceString.Data, 0, ReplaceString.Count); - - ReplaceString = RemoveAll(Scratch.Arena, ReplaceString, '\r'); - - MutableStringReplaceRange(&Editor->Text, ReplaceString, Range1S64(0, 0)); - W_TextEditorApplyChanges(Editor); - Editor->FileName = Action.Name; - Editor->FilePath = Action.Path; - - Platform.CloseFile(File); - } - else - { - Editor->FileName = Action.Name; - Editor->FilePath = Action.Path; - - Editor->SelectedItem = -1; - } - } - } - else { //- sixten: build & handle the text editor ui_box *EditorBox = 0; @@ -921,6 +647,7 @@ static void W_BuildTextEditor(workspace_view *View) UI_BorderColor(V4(0.45, 0.45, 0.45, 1)) UI_CornerRadius(2) { + // sixten(TODO): MAKE THESE BUTTONS ACTUALLY DO STUFF!!! if(W_BuildMenuItem(FontIcon_Gamepad, "Run in scene view", "").Clicked) { SV_SetCurrentSource(&Editor->Compiled); diff --git a/code/vn_workspace_text_editor.h b/code/vn_workspace_text_editor.h index 586499a..f22a3d2 100644 --- a/code/vn_workspace_text_editor.h +++ b/code/vn_workspace_text_editor.h @@ -44,13 +44,6 @@ struct workspace_text_data range1_s64_array Lines; }; -struct workspace_text_editor_lister_action -{ - b32 HasRequestedFile; - string Path; - string Name; -}; - struct workspace_view_text_editor { // sixten: processed text @@ -83,14 +76,6 @@ struct workspace_view_text_editor b32 DropdownActive; v2 DropdownP; r32 DropdownTransition; - - // sixten: file lister - string Path; - r32 ListerScroll; - u8 ListerInput[256]; - s32 ListerInputUsed; - text_edit_state ListerInputEditState; - s32 SelectedItem; }; //////////////////////////////// @@ -117,8 +102,7 @@ static void W_SaveTextEditorToFile(workspace_view_text_editor *Editor); //~ sixten: Workspace Text Editor Builder Functions static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback); -static b32 W_BuildTextEditorListerItem(string Text, u32 Icon, b32 Selected, b32 EnterPressed); -static workspace_text_editor_lister_action W_BuildTextEditorLister(workspace_view *View, workspace_view_text_editor *Editor); + static b32 W_ProcessTextEditorEvent(workspace_view_text_editor *Editor, platform_event *Event); static void W_BuildTextEditorInfoBar(workspace_view_text_editor *Editor); static void W_BuildTextEditor(workspace_view *View); diff --git a/code/vn_workspace_view.cpp b/code/vn_workspace_view.cpp index b58069f..166dad4 100644 --- a/code/vn_workspace_view.cpp +++ b/code/vn_workspace_view.cpp @@ -1,20 +1,28 @@ //- sixten: Views -inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel *Parent) +inline workspace_view *W_CreateNewView(workspace_view_kind Kind, workspace_panel *Parent) { arena *Arena = ArenaAlloc(Kilobytes(4), true); workspace_view *View = PushStruct(Arena, workspace_view); View->Arena = Arena; - View->Type = Type; + View->Kind = Kind; View->Parent = Parent; - switch(View->Type) + switch(View->Kind) { - case W_View_Settings: + case W_ViewKind_Settings: { View->Data = PushStruct(View->Arena, workspace_view_settings); } break; - case W_View_TextEditor: + case W_ViewKind_FileLister: + { + workspace_view_file_lister *Lister = PushStruct(View->Arena, workspace_view_file_lister); + View->Data = Lister; + + Lister->SelectedItem = -1; + } break; + + case W_ViewKind_TextEditor: { View->Data = PushStruct(View->Arena, workspace_view_text_editor); @@ -27,13 +35,21 @@ inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel Editor->History.At = &Editor->History.Sentinel; Editor->SavePoint = Editor->History.At; - Editor->SelectedItem = -1; - workspace_text_data TextData = W_TextDataFromString(Editor->ProcessingArena, Editor->Text.String); Editor->Tokens = TextData.Tokens; Editor->Lines = TextData.Lines; } break; + case W_ViewKind_NavEditor: + { + View->Data = PushStruct(View->Arena, workspace_view_nav_editor); + } break; + + case W_ViewKind_Error: + { + View->Data = PushStruct(View->Arena, workspace_view_error); + } break; + default: break; } @@ -49,9 +65,9 @@ inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel inline void W_DestroyView(workspace_view *View) { - switch(View->Type) + switch(View->Kind) { - case W_View_TextEditor: + case W_ViewKind_TextEditor: { workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data; ArenaRelease(Editor->ProcessingArena); @@ -74,14 +90,14 @@ inline b32 W_ViewIsCurrent(workspace_view *View) return(Result); } -inline string W_GetViewName(workspace_view *View) +inline string W_GetViewName(arena *Arena, workspace_view *View) { string Result = StrLit("Unnamed view"); - switch(View->Type) + switch(View->Kind) { - case W_View_Startup: { Result = StrLit("Welcome"); } break; - case W_View_Settings: { Result = StrLit("Settings"); } break; - case W_View_TextEditor: + case W_ViewKind_Startup: { Result = StrLit("Welcome"); } break; + case W_ViewKind_Settings: { Result = StrLit("Settings"); } break; + case W_ViewKind_TextEditor: { workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data; if(AreEqual(Editor->FileName, StrLit(""))) @@ -93,15 +109,19 @@ inline string W_GetViewName(workspace_view *View) //if(Editor->History.At == &Editor->History.Sentinel) if(Editor->History.At == Editor->SavePoint) { - Result = PushString(W_FrameArena(), Editor->FileName); + Result = PushString(Arena, Editor->FileName); } else { - Result = PushFormat(W_FrameArena(), "* %S", Editor->FileName); + Result = PushFormat(Arena, "* %S", Editor->FileName); } } } break; - case W_View_SceneView: { Result = StrLit("Scene View"); } break; + case W_ViewKind_SceneView: { Result = StrLit("Scene View"); } break; + case W_ViewKind_NavEditor: { Result = StrLit("Navigation Editor"); } break; + case W_ViewKind_FileLister: { Result = StrLit("File Lister"); } break; + case W_ViewKind_Error: { Result = StrLit("Error"); } break; + default: {} break; } return(Result); @@ -332,9 +352,11 @@ static void W_BuildView(workspace_view *View) UI_Parent(ViewBox) UI_Size(UI_Percent(1, 0), UI_Percent(1, 0)) { - switch(View->Type) + switch(View->Kind) { - case W_View_Startup: + case W_ViewKind_None: {} break; + + case W_ViewKind_Startup: { UI_Row() UI_Padding(UI_Pixels(50, 0)) UI_Width(UI_ChildrenSum(1, 1)) UI_Column() UI_Padding(UI_Pixels(50, 0)) @@ -352,20 +374,58 @@ static void W_BuildView(workspace_view *View) } } break; - case W_View_Settings: + case W_ViewKind_Settings: { W_BuildSettings(View); } break; - case W_View_TextEditor: + case W_ViewKind_TextEditor: { W_BuildTextEditor(View); } break; - case W_View_SceneView: + case W_ViewKind_SceneView: { W_BuildSceneView(View); } break; + case W_ViewKind_NavEditor: + { + W_BuildNavEditor(View); + } break; + case W_ViewKind_FileLister: + { + workspace_file_lister_action Action = W_BuildFileLister(View); + if(Action.HasRequestedFile) + { + workspace_file_lister_action *ActionOnDataArena = W_FileListerActionCopy(W_GetState()->CommandDataArena, &Action); + W_IssueCommand(W_Command_OpenFile, PointerToU64(ActionOnDataArena)); + + W_IssueCommand(W_Command_CloseView, PointerToU64(View)); + } + } break; + + case W_ViewKind_Error: + { + workspace_view_error *Error = (workspace_view_error *)View->Data; + UI_WidthFill UI_HeightFill + UI_Column() + { + UI_Label(Error->Message); + + UI_Height(UI_Em(2, 1)) UI_Row() + { + UI_Spacer(UI_Percent(1, 0)); + + UI_Width(UI_TextContent(15, 1)) UI_CornerRadius(4.0f) + if(UI_Button(StrLit("Close View")).Clicked) + { + W_IssueCommand(W_Command_CloseView, PointerToU64(View)); + } + UI_Spacer(UI_Em(1, 1)); + } + UI_Spacer(UI_Em(1, 1)); + } + } break; } } diff --git a/code/vn_workspace_view.h b/code/vn_workspace_view.h index 9a027e5..89a1a08 100644 --- a/code/vn_workspace_view.h +++ b/code/vn_workspace_view.h @@ -9,21 +9,30 @@ struct workspace_view { arena *Arena; - enum workspace_view_type Type; workspace_panel *Parent; workspace_view *Next; workspace_view *Prev; + enum workspace_view_kind Kind; void *Data; }; -enum workspace_view_type +enum workspace_view_kind { - W_View_Startup, - W_View_Settings, - W_View_TextEditor, - W_View_SceneView, + W_ViewKind_None, + W_ViewKind_Startup, + W_ViewKind_Settings, + W_ViewKind_FileLister, + W_ViewKind_TextEditor, + W_ViewKind_SceneView, + W_ViewKind_NavEditor, + W_ViewKind_Error, +}; + +struct workspace_view_error +{ + string Message; }; enum workspace_settings_category @@ -46,10 +55,10 @@ struct workspace_view_settings //~ sixten: Workspace View Functions //- sixten: Views -inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel *Parent); +inline workspace_view *W_CreateNewView(workspace_view_kind Type, workspace_panel *Parent); inline void W_DestroyView(workspace_view *View); inline b32 W_ViewIsCurrent(workspace_view *View); -inline string W_GetViewName(workspace_view *View); +inline string W_GetViewName(arena *Arena, workspace_view *View); //- sixten: Builder code static void W_ViewListerInputCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data); diff --git a/code/win32_main.cpp b/code/win32_main.cpp index 9df75ad..be58e7d 100644 --- a/code/win32_main.cpp +++ b/code/win32_main.cpp @@ -777,7 +777,7 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i { HWND Window = CreateWindowEx(0, WindowClass.lpszClassName, - "vn - October 2023 Build", + "vn - December 2023 Build", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, diff --git a/data/backgrounds/test.jpg b/data/backgrounds/test.jpg index 5a7cc08..f7233e1 100644 Binary files a/data/backgrounds/test.jpg and b/data/backgrounds/test.jpg differ diff --git a/data/ddlc.vns b/data/ddlc.vns index 686ba0a..9e6a975 100644 --- a/data/ddlc.vns +++ b/data/ddlc.vns @@ -6,6 +6,4 @@ proc main "We used to walk to school together on days like this, but starting around high school she would oversleep more and more frequently, and I would get tired of waiting up."; "But if she's going to chase after me like this, I almost feel better off running away."; "However, I just sigh and idle in front of the crosswalk and let Sayori catch up to me."; - - jump main; } \ No newline at end of file diff --git a/data/scene.vnn b/data/scene.vnn new file mode 100644 index 0000000..dcec2fa --- /dev/null +++ b/data/scene.vnn @@ -0,0 +1,17 @@ +{ + TextureID = "ArthurHappy"; + Scale = 0.01; + Origin = {0.5, 1.0}; + P = {0.15, 0.6}; + HoverText = "Talk to Arthur"; + Action = {Proc, "arthur_talk"}; +} + +{ + TextureID = "MonikaLeaning"; + Scale = 0.02; + Origin = {0.5, 1.0}; + P = {-0.4, 0.6}; + HoverText = "Talk to Monika"; + Action = {Proc, "monika_talk"}; +} diff --git a/data/scene.vns b/data/scene.vns index 009557e..bce6e46 100644 --- a/data/scene.vns +++ b/data/scene.vns @@ -12,12 +12,34 @@ proc main { @monika(leaning) "Really? Him?!?!"; @monika(leaning) "If you say so..."; - @monika(none); jump main; } "Okay!" { - @arthur(none); } } +} + +proc arthur_talk +{ + @arthur(normal) "Hi! Thanks for talking to me."; + @arthur "Do you want my rundown once again?"; + branch + { + "Yes!" + { + @arthur "Okay then!"; + jump main; + } + + "No" + { + @arthur "Alright!"; + } + } +} + +proc monika_talk +{ + @monika(leaning) "Okay everyone!"; } \ No newline at end of file