Added basic asset system. Began navigation view.

main
sixtenhugosson 2023-12-07 16:50:57 +01:00
parent b50ab896bb
commit 9797426dee
34 changed files with 1424 additions and 532 deletions

View File

@ -12,5 +12,5 @@ cl %CommonCompilerOptions% ../code/win32_main.cpp /link user32.lib gdi32.lib win
xcopy /y /q win32_main.exe vn.exe xcopy /y /q win32_main.exe vn.exe
del win32_main.* del win32_main.*
del *.pdb del *.pdb
popd popd

View File

@ -4,7 +4,7 @@
#define CORE_H #define CORE_H
#include <stdint.h> #include <stdint.h>
#include <intrin.h> //#include <intrin.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@ -50,10 +50,18 @@ typedef intptr_t smm;
#define global static #define global static
#define persist static #define persist static
#pragma section(".roglob", read) #if _WIN32
#define read_only __declspec(allocate(".roglob")) # 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 #define fallthrough
@ -186,6 +194,7 @@ auto __Temp = (Element)->Next->Prev;\
#define DeferLoop(Start, End) for(s32 ___ = ((Start), 0); ___ == 0; ++___, (End)) #define DeferLoop(Start, End) for(s32 ___ = ((Start), 0); ___ == 0; ++___, (End))
#if 0
//- sixten: Atomics //- sixten: Atomics
inline u64 AtomicExchangeU64(u64 volatile *Value, u64 New) inline u64 AtomicExchangeU64(u64 volatile *Value, u64 New)
@ -218,6 +227,7 @@ inline void EndTicketMutex(ticket_mutex *Mutex)
{ {
AtomicAddU64(&Mutex->Serving, 1); AtomicAddU64(&Mutex->Serving, 1);
} }
#endif
//- sixten: Axes //- sixten: Axes
enum axis2 enum axis2

View File

@ -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, v2_r32 B) { return A = A / B; }
inline v2_r32 operator*=(v2_r32 &A, 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) inline r32 Inner(v2_r32 A, v2_r32 B)
{ {
r32 Result = A.x*B.x + A.y*B.y; r32 Result = A.x*B.x + A.y*B.y;
@ -73,6 +85,12 @@ inline v2_r32 NOZ(v2_r32 V)
return(Result); 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) inline v2_r32 LinearBlend(v2_r32 A, v2_r32 B, r32 x)
{ {
v2_r32 Result = A+(B-A)*x; v2_r32 Result = A+(B-A)*x;

View File

@ -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, v2_r32 B); inline v2_r32 operator/=(v2_r32 &A, v2_r32 B);
inline v2_r32 operator*=(v2_r32 &A, 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 Inner(v2_r32 A, v2_r32 B);
inline r32 LengthSquared(v2_r32 V); inline r32 LengthSquared(v2_r32 V);
inline r32 Length(v2_r32 V); inline r32 Length(v2_r32 V);
inline v2_r32 NOZ(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 LinearBlend(v2_r32 A, v2_r32 B, r32 x);
inline v2_r32 Min(v2_r32 A, v2_r32 B); inline v2_r32 Min(v2_r32 A, v2_r32 B);
inline v2_r32 Max(v2_r32 A, v2_r32 B); inline v2_r32 Max(v2_r32 A, v2_r32 B);

View File

@ -3,7 +3,7 @@
static void Copy(void *Dest, void *Source, umm Count) static void Copy(void *Dest, void *Source, umm Count)
{ {
if(Count <= S64_Max) if(Count <= S32_Max)
{ {
u8 *Dest8 = (u8 *)Dest; u8 *Dest8 = (u8 *)Dest;
u8 *Source8 = (u8 *)Source; 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) static void CopyReverse(void *Dest, void *Source, umm Count)
{ {
if(Count <= S64_Max) if(Count <= S32_Max)
{ {
u8 *Dest8 = (u8 *)Dest + Count; u8 *Dest8 = (u8 *)Dest + Count;
u8 *Source8 = (u8 *)Source + 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) static void Fill(void *Dest, u8 Value, umm Count)
{ {
if(Count <= S64_Max) if(Count <= S32_Max)
{ {
u8 *Dest8 = (u8 *)Dest; u8 *Dest8 = (u8 *)Dest;

View File

@ -1,5 +1,5 @@
#define STB_SPRINTF_IMPLEMENTATION #define STB_SPRINTF_IMPLEMENTATION
#include "third_party/stb_sprintf.h" #include "../third_party/stb_sprintf.h"
//~ sixten: Char funcitons //~ sixten: Char funcitons

View File

@ -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",
};

View File

@ -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];

View File

@ -18,6 +18,7 @@ global debug_settings *DEBUG_DebugSettings = 0;
#include "generated/vn_character.meta.h" #include "generated/vn_character.meta.h"
#include "vn_asset.h"
#include "vn_tokenizer.h" #include "vn_tokenizer.h"
#include "vn_config.h" #include "vn_config.h"
#include "vn_font.h" #include "vn_font.h"
@ -35,6 +36,7 @@ global debug_settings *DEBUG_DebugSettings = 0;
#include "generated/vn_character.meta.c" #include "generated/vn_character.meta.c"
#include "vn_asset.cpp"
#include "vn_tokenizer.cpp" #include "vn_tokenizer.cpp"
#include "vn_config.cpp" #include "vn_config.cpp"
#include "vn_render.cpp" #include "vn_render.cpp"
@ -54,6 +56,8 @@ struct vn_state
arena *Arena; arena *Arena;
arena *FrameArena; arena *FrameArena;
assets Assets;
glyph_atlas *GlyphAtlas; glyph_atlas *GlyphAtlas;
config *Config; config *Config;
@ -125,7 +129,10 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
State->Config = CreateConfig(); State->Config = CreateConfig();
//- sixten: load assets //- 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 //- 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")); Config_ReadFile(State->Config, StrLit("config.vn"));
} }
//- sixten: load startup scene
scene_view *SceneView = &State->SceneView; scene_view *SceneView = &State->SceneView;
SV_Init(SceneView, State->Arena); SV_Init(SceneView, State->Arena);
//- sixten: load startup scene
temporary_memory Scratch = GetScratch(); temporary_memory Scratch = GetScratch();
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, StrLit("data/scene.vns")); string SceneInput = Platform_ReadEntireFile(Scratch.Arena, StrLit("data/scene.vns"));
compiled_scene Scene = S_ScriptFromText(Scratch.Arena, SceneInput); compiled_scene Scene = S_ScriptFromText(Scratch.Arena, SceneInput);
SV_SetCurrentSource(&Scene); SV_SetCurrentSource(&Scene);
ReleaseScratch(Scratch); ReleaseScratch(Scratch);
SceneView->TestHappy = CreateTextureFromPath(RenderCommands, StrLit("data/characters/test_happy.png")); SceneView->TestHappy = TextureFromAssetID(AssetID_ArthurHappy);
SceneView->TestNormal = CreateTextureFromPath(RenderCommands, StrLit("data/characters/test_normal.png")); SceneView->TestNormal = TextureFromAssetID(AssetID_ArthurNormal);
SceneView->MonikaLeaning = CreateTextureFromPath(RenderCommands, StrLit("data/characters/monika_leaning.png")); SceneView->MonikaLeaning = TextureFromAssetID(AssetID_MonikaLeaning);
SceneView->BackgroundTexture = State->BackgroundTexture; SceneView->BackgroundTexture = State->BackgroundTexture;
@ -172,8 +179,9 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
//- sixten: begin new frame //- sixten: begin new frame
ArenaClear(State->FrameArena); ArenaClear(State->FrameArena);
SetAssets(&State->Assets);
AC_NewFrame(&State->AnimationCurveState, Input->dtForFrame); 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); SV_NewFrame(&State->SceneView, Input->EventList, Input->dtForFrame);
//- sixten: check for toggle between modes //- sixten: check for toggle between modes

78
code/vn_asset.cpp 100644
View File

@ -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);
}

23
code/vn_asset.h 100644
View File

@ -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);

44
code/vn_assets.md 100644
View File

@ -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)",`;
}

View File

@ -898,11 +898,16 @@ static scene_value S_PopStackAndImplicitConvert(scene_runtime *Runtime)
return(Result); 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) static void S_ResetRuntime(scene_runtime *Runtime)
{ {
Runtime->IP = 0; S_SetCurrentProc(Runtime, 0);
Runtime->CurrentProc = 0;
Runtime->BranchCount = 0;
Fill(Runtime->GlobalVariableBuckets, 0, sizeof(Runtime->GlobalVariableBuckets)); Fill(Runtime->GlobalVariableBuckets, 0, sizeof(Runtime->GlobalVariableBuckets));
ZeroStruct(&Runtime->GlobalVariableFreeList); 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); scene_proc *Dest = S_FindProcByName(Compiled, JumpDest);
if(Dest) if(Dest)
{ {
Runtime->CurrentProc = Dest; S_SetCurrentProc(Runtime, Dest);
Runtime->IP = 0;
} }
else else
{ {
@ -1083,7 +1087,7 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, arena *FrameArena, b32
if(Offset.Kind == S_ValueKind_Offset) if(Offset.Kind == S_ValueKind_Offset)
{ {
branch_case *Branch = &Runtime->Branches[Runtime->BranchCount]; 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; Branch->Offset = Offset.Offset;
Runtime->BranchCount += 1; 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) if(State.Kind == S_ValueKind_Nil)
{ {
Action->State = CR_State_None; Action->State = CR_State_Invalid;
} }
else else
{ {

View File

@ -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); v2 RenderDim = DimOfRange(Box->Rect);
r32 GlobalScale = CalculateGlobalScaleFromDim(RenderDim);
//- sixten: render background //- sixten: render background
// sixten(TODO, but soon): Currently we add Box->Rect.Min to everything, but that should really be a transform // 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); PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, SceneView->BackgroundTexture);
#endif #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 //- sixten: render characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1) 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; scene_runtime *Runtime = &View->Runtime;
textbox *Textbox = &View->Textbox; 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_SetNextWidth(UI_Percent(1, 0));
UI_SetNextHeight(UI_Percent(1, 0)); UI_SetNextHeight(UI_Percent(1, 0));
UI_SetNextLayoutAxis(Axis2_Y); UI_SetNextLayoutAxis(Axis2_Y);
ui_box *Box = UI_MakeBox(0, StrLit("Scene View")); ui_box *Box = UI_MakeBox(0, StrLit("Scene View"));
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View); UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View);
if(SV_CurrentlyInProc()) UI_Parent(Box)
{ {
UI_Parent(Box) if(SV_CurrentlyInProc())
{ {
//- sixten: build branches BuildProcView(View, Box);
UI_WidthFill UI_Height(UI_Percent(1, 0)) UI_Row() UI_FillPadding UI_Column() UI_FillPadding }
{ else
b32 FoundOffset = false; {
s64 Offset = 0; BuildNavView(View, Box);
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);
}
} }
}
else
{
//- sixten: render environmental objects
} }
} }
@ -542,7 +704,10 @@ static void SV_UpdateInDialog(arena *FrameArena)
} }
else else
{ {
Data->Info = SV_CharacterTextureFromAction(Action); if(Action->State != CR_State_Invalid)
{
Data->Info = SV_CharacterTextureFromAction(Action);;
}
Data->Talking = true; Data->Talking = true;
SceneView->CharacterIsTalking = true; SceneView->CharacterIsTalking = true;
@ -575,6 +740,12 @@ static void SV_Update(arena *FrameArena)
{ {
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex; 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->Active, 0.5f, &Data->ActiveT);
AC_AnimateValueDirect(Data->Talking, 0.4f, &Data->TalkingT); AC_AnimateValueDirect(Data->Talking, 0.4f, &Data->TalkingT);

View File

@ -32,6 +32,46 @@ struct scene_view_character_data
r32 PctP; 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 struct scene_view
{ {
arena *SceneArena; arena *SceneArena;
@ -71,7 +111,11 @@ static void SV_Init(scene_view *View, arena *TextboxArena);
static b32 SV_CurrentlyInProc(void); 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_BuildSceneView(vn_input *Input);
static void SV_Update(arena *FrameArena); static void SV_Update(arena *FrameArena);
#endif //VN_SCENE_VIEW_H #endif //VN_SCENE_VIEW_H

View File

@ -120,6 +120,11 @@ inline void *UI_GetDragDataPointer(void)
return(Result); return(Result);
} }
static r64 UI_Time(void)
{
return(UI_GetState()->Time);
}
inline ui_key UI_EmptyKey(void) inline ui_key UI_EmptyKey(void)
{ {
ui_key Key = {}; ui_key Key = {};
@ -468,6 +473,7 @@ static ui_signal UI_SignalFromBox(ui_box *Box)
} }
Signal.MouseP = UI->MouseP; Signal.MouseP = UI->MouseP;
Signal.dMouseP = UI->dMouseP;
Signal.DragDelta = UI->MouseP - UI->DragStartP; Signal.DragDelta = UI->MouseP - UI->DragStartP;
Signal.Box = Box; 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; 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. // sixten: if the size is zero, try to find it.
if(Size == 0.0) 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; Result = Size*Box->SemanticSize[Axis].Value;
} }
@ -725,7 +738,7 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis)
case UI_SizeKind_ChildrenSum: case UI_SizeKind_ChildrenSum:
{ {
Result = UI_CalculateChildrenSum(Box, Axis)*Box->SemanticSize[Axis].Value; Result = UI_CalculateChildrenSum(Box, Axis, ForceCalculate)*Box->SemanticSize[Axis].Value;
} break; } break;
InvalidDefaultCase; InvalidDefaultCase;
@ -734,7 +747,13 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis)
return(Result); 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; r32 Result = 0;
@ -744,7 +763,7 @@ static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis)
Child != 0; Child != 0;
Child = Child->Next) Child = Child->Next)
{ {
Result += UI_CalculateBoxSize(Child, Axis); Result += UI_CalculateBoxSize(Child, Axis, ForceCalculate);
} }
} }
else else
@ -753,7 +772,7 @@ static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis)
Child != 0; Child != 0;
Child = Child->Next) Child = Child->Next)
{ {
Result = Max(Result, UI_CalculateBoxSize(Child, Axis)); Result = Max(Result, UI_CalculateBoxSize(Child, Axis, ForceCalculate));
} }
} }
return(Result); return(Result);
@ -778,8 +797,8 @@ static void UI_LayoutBox(ui_box *Box)
{ {
if(Child->Flags & UI_BoxFlag_AnimatePosition) 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.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.1, "Box P.Y %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.Min = Box->Rect.Min + Child->ApproachingRelativeP + Box->Offset;
Child->Rect.Max = Child->Rect.Min + Child->ComputedDim; 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); UI_SetState(UI);
ArenaClear(UI->FrameArena); ArenaClear(UI->FrameArena);
UI->EventList = EventList; UI->EventList = EventList;
UI->dMouseP = MouseP - UI->MouseP;
UI->MouseP = MouseP; UI->MouseP = MouseP;
UI->Time += dtForFrame;
UI->GlyphAtlas = GlyphAtlas; UI->GlyphAtlas = GlyphAtlas;

View File

@ -116,6 +116,7 @@ struct ui_signal
{ {
ui_box *Box; ui_box *Box;
v2 MouseP; v2 MouseP;
v2 dMouseP;
v2 DragDelta; v2 DragDelta;
v2 Scroll; v2 Scroll;
b8 Clicked; b8 Clicked;
@ -145,6 +146,8 @@ struct ui
ui_key Hot; ui_key Hot;
ui_key Active; ui_key Active;
r64 Time;
ui_key NextHot; ui_key NextHot;
b32 NextHotSet; b32 NextHotSet;
@ -154,6 +157,7 @@ struct ui
ui_style_stacks Stacks; ui_style_stacks Stacks;
platform_event_list *EventList; platform_event_list *EventList;
v2 dMouseP;
v2 MouseP; v2 MouseP;
glyph_atlas *GlyphAtlas; glyph_atlas *GlyphAtlas;
@ -182,6 +186,9 @@ inline void UI_GetDragDataPayload(void *Data);
inline void UI_StoreDragPointer(void *Data); inline void UI_StoreDragPointer(void *Data);
inline void *UI_GetDragDataPointer(void); inline void *UI_GetDragDataPointer(void);
//- sixten: Helpers
static r64 UI_Time(void);
//- sixten: Key functions //- sixten: Key functions
static ui_key UI_EmptyKey(void); static ui_key UI_EmptyKey(void);
static ui_key UI_SeedKey(ui_key Key, ui_key Seed); 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_BeginBuild(ui *UI, v2 ScreenDim);
static void UI_EndBuild(void); static void UI_EndBuild(void);
static void UI_RenderFrame(render_group *RenderGroup); 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 #endif //VN_UI_H

View File

@ -237,13 +237,13 @@ static void UI_ScrollBegin(r32 *X, r32 *Y, ui_box_flags Flags, string Name)
if(AllowOnX) if(AllowOnX)
{ {
ScrollFlags |= UI_BoxFlag_OverflowX; ScrollFlags |= UI_BoxFlag_OverflowX;
UI_SetNextOffsetX(-(*X)); UI_SetNextOffsetX(-AC_AnimateValueF(*X, *X, 0.2f, "Scroll %S X", Name));
} }
if(AllowOnY) if(AllowOnY)
{ {
ScrollFlags |= UI_BoxFlag_OverflowY; 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), 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 AllowOnX = (X != 0);
b32 AllowOnY = (Y != 0); b32 AllowOnY = (Y != 0);
r32 ScrollAmount = UI_TopFontSize()*4.0f;
ui_box *ScrollableBox = UI_TopParent(); ui_box *ScrollableBox = UI_TopParent();
ui_signal ScrollableBoxSignal = UI_SignalFromBox(ScrollableBox); 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 StartOffset = UI_GetDragR32();
r32 EndOffset = StartOffset + Signal.DragDelta.x/ScrollScale; 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 StartOffset = UI_GetDragR32();
r32 EndOffset = StartOffset + Signal.DragDelta.y/ScrollScale; 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);
}
}
} }
} }
} }

View File

@ -1,6 +1,8 @@
#include "vn_workspace_commands.cpp" #include "vn_workspace_commands.cpp"
#include "vn_workspace_view.cpp" #include "vn_workspace_view.cpp"
#include "vn_workspace_file_lister.cpp"
#include "vn_workspace_text_editor.cpp" #include "vn_workspace_text_editor.cpp"
#include "vn_workspace_nav_editor.cpp"
//- sixten: State management //- sixten: State management
per_thread workspace *ThreadLocal_Workspace; per_thread workspace *ThreadLocal_Workspace;
@ -10,7 +12,8 @@ static workspace_keybind Workspace_Keybinds[] =
{Key_P, PlatformModifier_Ctrl, W_Command_SplitPanelHorizontal}, {Key_P, PlatformModifier_Ctrl, W_Command_SplitPanelHorizontal},
{Key_L, PlatformModifier_Ctrl, W_Command_SplitPanelVertical}, {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 #if VN_INTERNAL
{Key_U, PlatformModifier_Ctrl|PlatformModifier_Shift, W_Command_ToggleRenderUIDebugRects}, {Key_U, PlatformModifier_Ctrl|PlatformModifier_Shift, W_Command_ToggleRenderUIDebugRects},
@ -27,13 +30,8 @@ static workspace *W_GetState(void)
return(ThreadLocal_Workspace); return(ThreadLocal_Workspace);
} }
static arena *W_FrameArena(void)
{
return(ThreadLocal_Workspace->FrameArena);
}
//- sixten: Commands //- 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; workspace_command *Result = 0;
@ -71,6 +69,8 @@ static void W_ProcessCommands(void)
Fill(ToRemove, 0, sizeof(workspace_command)); Fill(ToRemove, 0, sizeof(workspace_command));
DLLInsertLast(Workspace->FirstFreeCommand, Workspace->LastFreeCommand, ToRemove); DLLInsertLast(Workspace->FirstFreeCommand, Workspace->LastFreeCommand, ToRemove);
} }
ArenaClear(Workspace->CommandDataArena);
} }
static void W_ProcessKeyBinds() static void W_ProcessKeyBinds()
@ -125,7 +125,7 @@ static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu)
if(Signal.Clicked) if(Signal.Clicked)
{ {
Workspace->Menu = Menu; Workspace->Menu = Menu;
Workspace->MenuTransition = 0; Workspace->MenuT = 0;
} }
} }
else else
@ -134,7 +134,7 @@ static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu)
{ {
if(Workspace->Menu != Menu) if(Workspace->Menu != Menu)
{ {
Workspace->MenuTransition = 0; Workspace->MenuT = 0;
} }
Workspace->Menu = Menu; Workspace->Menu = Menu;
@ -195,14 +195,14 @@ static void W_BuildToolbar(void)
if(Workspace->Menu != W_ToolbarMenu_None) if(Workspace->Menu != W_ToolbarMenu_None)
{ {
r32 MenuTransition = Workspace->MenuTransition; r32 MenuT = Workspace->MenuT;
UI_SetNextTooltip(); UI_SetNextTooltip();
UI_SetNextFixedX(Workspace->MenuP.x); UI_SetNextFixedX(Workspace->MenuP.x);
UI_SetNextFixedY(Workspace->MenuP.y); UI_SetNextFixedY(Workspace->MenuP.y);
UI_SetNextLayoutAxis(Axis2_Y); UI_SetNextLayoutAxis(Axis2_Y);
UI_SetNextWidth(UI_Pixels(250, 1)); 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_box *Dropdown = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
UI_BoxFlag_DrawDropShadow | UI_BoxFlag_DrawDropShadow |
UI_BoxFlag_Clip | UI_BoxFlag_Clip |
@ -231,31 +231,16 @@ static void W_BuildToolbar(void)
} }
else if(Workspace->Menu == W_ToolbarMenu_View) 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 if(ViewKind != W_ViewKind_None)
// 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)
{ {
W_CreateNewView(W_View_Startup, CurrentPanel); W_IssueCommand(W_Command_OpenView, ViewKind);
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);
Workspace->Menu = W_ToolbarMenu_None; 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. // sixten: Unless the mouse press was captured, we close the menu.
if(Platform_KeyPress(Workspace->EventList, Key_MouseLeft)) if(Platform_KeyPress(Workspace->EventList, Key_MouseLeft))
@ -316,6 +301,40 @@ static void W_DeletePanel(workspace_panel *Panel)
DLLInsertLast(Workspace->FirstFreePanel, Workspace->LastFreePanel, 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) static void W_SplitPanel(workspace_panel *Panel, axis2 Axis)
{ {
workspace *Workspace = W_GetState(); 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) inline void W_BeginDrag(workspace_drag_payload *Payload)
{ {
workspace *Workspace = W_GetState(); 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 // 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. ^.^ // 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->DragPayload = *Payload;
Workspace->DragPayloadState = W_DragPayload_Active; 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 ViewIsCurrent = (Panel->CurrentView == View);
b32 PanelIsCurrent = (Workspace->CurrentPanel == Panel); 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_Size(UI_ChildrenSum(SpaceT, 1), UI_Percent(1, 1)) UI_Column()
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_TextContent(1, 1), UI_Percent(1, 1)) UI_Label(Name); UI_Spacer(UI_Percent(1-OpenT, 1));
UI_Spacer(UI_Pixels(5, 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_Size(UI_TextContent(1, 1), UI_Percent(1, 1)) UI_Label(Name);
UI_SetNextSize(UI_TextContent(1, 1), UI_Percent(1, 1)); UI_Spacer(UI_Pixels(5, 1));
UI_SetNextHoverCursor(PlatformCursor_Hand);
ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "%U", FontIcon_Cancel); // sixten: Build close button
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_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); ui_signal Signal = UI_SignalFromBox(TabBox);
if(Signal.Clicked) if(Signal.Clicked)
{
Workspace->CurrentPanel = Panel;
Panel->CurrentView = View;
}
// sixten: Handle dragging the view.
if(Signal.Dragging)
{
if(Signal.Pressed)
{ {
workspace_drag_payload Payload = {}; Workspace->CurrentPanel = Panel;
Payload.View = View; Panel->CurrentView = View;
Payload.Key = TabBox->Key; }
W_BeginDrag(&Payload); // 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_SetNextSize(UI_Pixels(30, 1), UI_Pixels(30, 1));
UI_SetNextFont(Font_Icons); UI_SetNextFont(Font_Icons);
UI_SetNextBorderColor(ColorFromHex(0xA6514288));
UI_SetNextBackgroundColor(ColorFromHex(0xC24630BB));
UI_SetNextCornerRadius(4); UI_SetNextCornerRadius(4);
UI_SetNextHoverCursor(PlatformCursor_Hand); UI_SetNextHoverCursor(PlatformCursor_Hand);
ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_HotAnimation | ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_HotAnimation |
UI_BoxFlag_ActiveAnimation | UI_BoxFlag_ActiveAnimation |
//UI_BoxFlag_DrawBackground |
//UI_BoxFlag_DrawBorder |
UI_BoxFlag_DrawText | UI_BoxFlag_DrawText |
UI_BoxFlag_Clickable, UI_BoxFlag_Clickable,
"%U", FontIcon_Cancel); "%U", FontIcon_Cancel);
@ -727,7 +760,7 @@ static void W_BuildDragPayload()
workspace *Workspace = W_GetState(); workspace *Workspace = W_GetState();
workspace_drag_payload Payload; workspace_drag_payload Payload;
if(W_GetDragPayload(&Payload)) if(W_GetDragPayload(&Payload) && W_ViewIsDragged(Payload.View))
{ {
if(Workspace->DragPayloadState == W_DragPayload_Released) if(Workspace->DragPayloadState == W_DragPayload_Released)
{ {
@ -738,7 +771,7 @@ static void W_BuildDragPayload()
{ {
workspace_view *DraggedView = Payload.View; workspace_view *DraggedView = Payload.View;
UI_SetNextCornerRadius(4); UI_SetNextCornerRadius(4);
UI_TooltipLabel(W_GetViewName(DraggedView), UI_MouseP()); UI_TooltipLabel(W_GetViewName(UI_FrameArena(), DraggedView), UI_MouseP());
} }
else else
{ {
@ -755,36 +788,35 @@ static void W_Init(workspace *Workspace)
{ {
W_SetState(Workspace); W_SetState(Workspace);
Workspace->FrameArena = ArenaAlloc(Kilobytes(32), true);
Workspace->CommandArena = ArenaAlloc(Kilobytes(4), true); Workspace->CommandArena = ArenaAlloc(Kilobytes(4), true);
Workspace->CommandDataArena = ArenaAlloc(Kilobytes(4), true);
Workspace->PanelArena = ArenaAlloc(Kilobytes(4), true); Workspace->PanelArena = ArenaAlloc(Kilobytes(4), true);
Workspace->RootPanel = Workspace->CurrentPanel = W_CreateNewPanel(0); Workspace->RootPanel = Workspace->CurrentPanel = W_CreateNewPanel(0);
if(DEBUG_DebugSettings->ShowWelcomeMessage) 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 // sixten: build text editor / scene view layout
if(0) if(0)
{ {
W_CreateNewView(W_View_TextEditor, Workspace->RootPanel); W_CreateNewView(W_ViewKind_TextEditor, Workspace->RootPanel);
W_SplitPanel(Workspace->RootPanel, Axis2_X); 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, static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands, vn_input *Input, glyph_atlas *GlyphAtlas)
vn_input *Input, glyph_atlas *GlyphAtlas)
{ {
W_SetState(Workspace);
ArenaClear(Workspace->FrameArena);
Workspace->Input = Input; Workspace->Input = Input;
Workspace->EventList = Input->EventList; Workspace->EventList = Input->EventList;
W_SetState(Workspace);
// sixten: Process the keybinds and commands. // sixten: Process the keybinds and commands.
W_ProcessKeyBinds(); W_ProcessKeyBinds();
W_ProcessCommands(); W_ProcessCommands();
@ -801,12 +833,10 @@ static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands,
// sixten: Build the UI. // sixten: Build the UI.
{ {
W_BuildToolbar(); W_BuildDragPayload();
W_BuildToolbar();
UI_SetNextSize(UI_Percent(1, 1), UI_Percent(1, 0)); UI_SetNextSize(UI_Percent(1, 1), UI_Percent(1, 0));
W_BuildPanel(Workspace->RootPanel); W_BuildPanel(Workspace->RootPanel);
W_BuildDragPayload();
} }
} }

View File

@ -15,6 +15,21 @@ enum workspace_toolbar_menu
W_ToolbarMenu_Window, 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 struct workspace_panel
{ {
workspace_panel *First; workspace_panel *First;
@ -23,10 +38,10 @@ struct workspace_panel
workspace_panel *Prev; workspace_panel *Prev;
workspace_panel *Parent; workspace_panel *Parent;
struct workspace_view *FirstView; workspace_view *FirstView;
struct workspace_view *LastView; workspace_view *LastView;
struct workspace_view *CurrentView; workspace_view *CurrentView;
axis2 SplitAxis; axis2 SplitAxis;
r32 PercentOfParent; r32 PercentOfParent;
@ -70,11 +85,9 @@ struct workspace
vn_input *Input; vn_input *Input;
platform_event_list *EventList; platform_event_list *EventList;
// sixten: General Purpose Allocation
arena *FrameArena;
// sixten: Command Allocation // sixten: Command Allocation
arena *CommandArena; arena *CommandArena;
arena *CommandDataArena;
workspace_command *FirstFreeCommand; workspace_command *FirstFreeCommand;
workspace_command *LastFreeCommand; workspace_command *LastFreeCommand;
@ -90,15 +103,20 @@ struct workspace
workspace_drag_payload_state DragPayloadState; workspace_drag_payload_state DragPayloadState;
workspace_drag_payload DragPayload; workspace_drag_payload DragPayload;
arena *PanelViewArena;
workspace_panel_view_list PanelViewFreeList;
workspace_toolbar_menu Menu; workspace_toolbar_menu Menu;
v2 MenuP; v2 MenuP;
r32 MenuTransition; r32 MenuT;
workspace_panel *RootPanel; workspace_panel *RootPanel;
workspace_panel *CurrentPanel; workspace_panel *CurrentPanel;
}; };
#include "vn_workspace_file_lister.h"
#include "vn_workspace_text_editor.h" #include "vn_workspace_text_editor.h"
#include "vn_workspace_nav_editor.h"
#include "vn_workspace_view.h" #include "vn_workspace_view.h"
//////////////////////////////// ////////////////////////////////
@ -107,10 +125,9 @@ struct workspace
//- sixten: State management //- sixten: State management
static void W_SetState(workspace *Workspace); static void W_SetState(workspace *Workspace);
static workspace *W_GetState(void); static workspace *W_GetState(void);
static arena *W_FrameArena(void);
//- sixten: Commands //- 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); static void W_ProcessCommands(void);
//- sixten: Panels //- sixten: Panels
@ -118,6 +135,15 @@ static workspace_panel *W_CreateNewPanel(workspace_panel *Parent);
static void W_DeletePanel(workspace_panel *Panel); static void W_DeletePanel(workspace_panel *Panel);
static void W_SplitPanel(workspace_panel *Panel, axis2 Axis); 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 //- sixten: Builder code
static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu); static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu);
static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut); static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut);

View File

@ -91,7 +91,7 @@ WORKSPACE_COMMAND(W_Command_ClosePanel)
WORKSPACE_COMMAND(W_Command_OpenView) WORKSPACE_COMMAND(W_Command_OpenView)
{ {
workspace *Workspace = W_GetState(); 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) WORKSPACE_COMMAND(W_Command_CloseView)
@ -108,18 +108,66 @@ WORKSPACE_COMMAND(W_Command_CloseView)
W_DestroyView(View); 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 #if VN_INTERNAL
WORKSPACE_COMMAND(W_Command_ToggleRenderUIDebugRects) WORKSPACE_COMMAND(W_Command_ToggleRenderUIDebugRects)
{ {
DEBUG_DebugSettings->RenderUIDebugRects = !DEBUG_DebugSettings->RenderUIDebugRects; DEBUG_DebugSettings->RenderUIDebugRects = !DEBUG_DebugSettings->RenderUIDebugRects;
} }
#endif #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);
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}
}
}
}
}

View File

@ -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

View File

@ -377,238 +377,6 @@ static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback)
} }
ReleaseScratch(Scratch); 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) static b32 W_ProcessTextEditorEvent(workspace_view_text_editor *Editor, platform_event *Event)
{ {
b32 CursorHasBeenModified = false; b32 CursorHasBeenModified = false;
@ -685,48 +453,6 @@ static void W_BuildTextEditor(workspace_view *View)
s32 LineMarginDigitsRequired = 6; s32 LineMarginDigitsRequired = 6;
r32 LineMarginWidth = (LineMarginDigitsRequired)*GlyphAdvance; 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 //- sixten: build & handle the text editor
ui_box *EditorBox = 0; 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_BorderColor(V4(0.45, 0.45, 0.45, 1))
UI_CornerRadius(2) UI_CornerRadius(2)
{ {
// sixten(TODO): MAKE THESE BUTTONS ACTUALLY DO STUFF!!!
if(W_BuildMenuItem(FontIcon_Gamepad, "Run in scene view", "").Clicked) if(W_BuildMenuItem(FontIcon_Gamepad, "Run in scene view", "").Clicked)
{ {
SV_SetCurrentSource(&Editor->Compiled); SV_SetCurrentSource(&Editor->Compiled);

View File

@ -44,13 +44,6 @@ struct workspace_text_data
range1_s64_array Lines; range1_s64_array Lines;
}; };
struct workspace_text_editor_lister_action
{
b32 HasRequestedFile;
string Path;
string Name;
};
struct workspace_view_text_editor struct workspace_view_text_editor
{ {
// sixten: processed text // sixten: processed text
@ -83,14 +76,6 @@ struct workspace_view_text_editor
b32 DropdownActive; b32 DropdownActive;
v2 DropdownP; v2 DropdownP;
r32 DropdownTransition; 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 //~ sixten: Workspace Text Editor Builder Functions
static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback); 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 b32 W_ProcessTextEditorEvent(workspace_view_text_editor *Editor, platform_event *Event);
static void W_BuildTextEditorInfoBar(workspace_view_text_editor *Editor); static void W_BuildTextEditorInfoBar(workspace_view_text_editor *Editor);
static void W_BuildTextEditor(workspace_view *View); static void W_BuildTextEditor(workspace_view *View);

View File

@ -1,20 +1,28 @@
//- sixten: Views //- 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); arena *Arena = ArenaAlloc(Kilobytes(4), true);
workspace_view *View = PushStruct(Arena, workspace_view); workspace_view *View = PushStruct(Arena, workspace_view);
View->Arena = Arena; View->Arena = Arena;
View->Type = Type; View->Kind = Kind;
View->Parent = Parent; 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); View->Data = PushStruct(View->Arena, workspace_view_settings);
} break; } 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); 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->History.At = &Editor->History.Sentinel;
Editor->SavePoint = Editor->History.At; Editor->SavePoint = Editor->History.At;
Editor->SelectedItem = -1;
workspace_text_data TextData = W_TextDataFromString(Editor->ProcessingArena, Editor->Text.String); workspace_text_data TextData = W_TextDataFromString(Editor->ProcessingArena, Editor->Text.String);
Editor->Tokens = TextData.Tokens; Editor->Tokens = TextData.Tokens;
Editor->Lines = TextData.Lines; Editor->Lines = TextData.Lines;
} break; } 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; default: break;
} }
@ -49,9 +65,9 @@ inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel
inline void W_DestroyView(workspace_view *View) 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; workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data;
ArenaRelease(Editor->ProcessingArena); ArenaRelease(Editor->ProcessingArena);
@ -74,14 +90,14 @@ inline b32 W_ViewIsCurrent(workspace_view *View)
return(Result); return(Result);
} }
inline string W_GetViewName(workspace_view *View) inline string W_GetViewName(arena *Arena, workspace_view *View)
{ {
string Result = StrLit("Unnamed view"); string Result = StrLit("Unnamed view");
switch(View->Type) switch(View->Kind)
{ {
case W_View_Startup: { Result = StrLit("Welcome"); } break; case W_ViewKind_Startup: { Result = StrLit("Welcome"); } break;
case W_View_Settings: { Result = StrLit("Settings"); } break; case W_ViewKind_Settings: { Result = StrLit("Settings"); } break;
case W_View_TextEditor: case W_ViewKind_TextEditor:
{ {
workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data; workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data;
if(AreEqual(Editor->FileName, StrLit(""))) 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->History.Sentinel)
if(Editor->History.At == Editor->SavePoint) if(Editor->History.At == Editor->SavePoint)
{ {
Result = PushString(W_FrameArena(), Editor->FileName); Result = PushString(Arena, Editor->FileName);
} }
else else
{ {
Result = PushFormat(W_FrameArena(), "* %S", Editor->FileName); Result = PushFormat(Arena, "* %S", Editor->FileName);
} }
} }
} break; } 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); return(Result);
@ -332,9 +352,11 @@ static void W_BuildView(workspace_view *View)
UI_Parent(ViewBox) UI_Parent(ViewBox)
UI_Size(UI_Percent(1, 0), UI_Percent(1, 0)) 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_Row() UI_Padding(UI_Pixels(50, 0))
UI_Width(UI_ChildrenSum(1, 1)) UI_Column() 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; } break;
case W_View_Settings: case W_ViewKind_Settings:
{ {
W_BuildSettings(View); W_BuildSettings(View);
} break; } break;
case W_View_TextEditor: case W_ViewKind_TextEditor:
{ {
W_BuildTextEditor(View); W_BuildTextEditor(View);
} break; } break;
case W_View_SceneView: case W_ViewKind_SceneView:
{ {
W_BuildSceneView(View); W_BuildSceneView(View);
} break; } 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;
} }
} }

View File

@ -9,21 +9,30 @@
struct workspace_view struct workspace_view
{ {
arena *Arena; arena *Arena;
enum workspace_view_type Type;
workspace_panel *Parent; workspace_panel *Parent;
workspace_view *Next; workspace_view *Next;
workspace_view *Prev; workspace_view *Prev;
enum workspace_view_kind Kind;
void *Data; void *Data;
}; };
enum workspace_view_type enum workspace_view_kind
{ {
W_View_Startup, W_ViewKind_None,
W_View_Settings, W_ViewKind_Startup,
W_View_TextEditor, W_ViewKind_Settings,
W_View_SceneView, 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 enum workspace_settings_category
@ -46,10 +55,10 @@ struct workspace_view_settings
//~ sixten: Workspace View Functions //~ sixten: Workspace View Functions
//- sixten: Views //- 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 void W_DestroyView(workspace_view *View);
inline b32 W_ViewIsCurrent(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 //- sixten: Builder code
static void W_ViewListerInputCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data); static void W_ViewListerInputCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data);

View File

@ -777,7 +777,7 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
{ {
HWND Window = CreateWindowEx(0, HWND Window = CreateWindowEx(0,
WindowClass.lpszClassName, WindowClass.lpszClassName,
"vn - October 2023 Build", "vn - December 2023 Build",
WS_OVERLAPPEDWINDOW, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 941 KiB

After

Width:  |  Height:  |  Size: 537 KiB

View File

@ -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."; "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."; "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."; "However, I just sigh and idle in front of the crosswalk and let Sayori catch up to me.";
jump main;
} }

17
data/scene.vnn 100644
View File

@ -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"};
}

View File

@ -12,12 +12,34 @@ proc main
{ {
@monika(leaning) "Really? Him?!?!"; @monika(leaning) "Really? Him?!?!";
@monika(leaning) "If you say so..."; @monika(leaning) "If you say so...";
@monika(none);
jump main; jump main;
} }
"Okay!" "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!";
}