Added basic asset system. Began navigation view.
parent
b50ab896bb
commit
9797426dee
|
@ -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
|
|
@ -4,7 +4,7 @@
|
|||
#define CORE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <intrin.h>
|
||||
//#include <intrin.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#include "third_party/stb_sprintf.h"
|
||||
#include "../third_party/stb_sprintf.h"
|
||||
|
||||
//~ sixten: Char funcitons
|
||||
|
||||
|
|
|
@ -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",
|
||||
};
|
||||
|
|
@ -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];
|
||||
|
20
code/vn.cpp
20
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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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)",`;
|
||||
}
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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,33 +267,44 @@ 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;
|
||||
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)
|
||||
{
|
||||
//- sixten: build branches
|
||||
UI_WidthFill UI_Height(UI_Percent(1, 0)) UI_Row() UI_FillPadding UI_Column() UI_FillPadding
|
||||
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(UI_ButtonF("%S#%i", Branch->Name, BranchIndex).Clicked)
|
||||
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)
|
||||
{
|
||||
|
@ -307,11 +325,155 @@ static void BuildScene(scene_view *View)
|
|||
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);
|
||||
|
||||
UI_Parent(Box)
|
||||
{
|
||||
if(SV_CurrentlyInProc())
|
||||
{
|
||||
BuildProcView(View, Box);
|
||||
}
|
||||
else
|
||||
{
|
||||
//- sixten: render environmental objects
|
||||
BuildNavView(View, Box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -710,9 +716,16 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis)
|
|||
r32 Size = Parent->ComputedDim.E[Axis];
|
||||
// sixten: if the size is zero, try to find it.
|
||||
if(Size == 0.0)
|
||||
{
|
||||
if(ForceCalculate)
|
||||
{
|
||||
Size = UI_CalculateBoxSize(Parent, Axis, ForceCalculate);
|
||||
}
|
||||
else
|
||||
{
|
||||
Size = DimOfRange(Parent->Rect).E[Axis];
|
||||
}
|
||||
}
|
||||
Result = Size*Box->SemanticSize[Axis].Value;
|
||||
}
|
||||
else
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,7 +423,15 @@ 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);
|
||||
|
||||
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_Size(UI_ChildrenSum(SpaceT, 1), UI_Percent(1, 1)) UI_Column()
|
||||
{
|
||||
UI_Spacer(UI_Percent(1-OpenT, 1));
|
||||
|
||||
v4 BackgroundColor = ViewIsCurrent ? (PanelIsCurrent ? Theme_HighlightBorderColor : Theme_BorderColor) : ColorFromHex(0x353738FF);
|
||||
|
||||
|
@ -410,11 +446,11 @@ static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View)
|
|||
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_Parent(TabBox) UI_Padding(UI_Pixels(5, 1))
|
||||
{
|
||||
UI_Size(UI_TextContent(1, 1), UI_Percent(1, 1)) UI_Label(Name);
|
||||
UI_Spacer(UI_Pixels(5, 1));
|
||||
|
@ -456,6 +492,7 @@ static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View)
|
|||
W_BeginDrag(&Payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void W_BuildPanelHeader(workspace_panel *Panel)
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 941 KiB After Width: | Height: | Size: 537 KiB |
|
@ -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;
|
||||
}
|
|
@ -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"};
|
||||
}
|
|
@ -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!";
|
||||
}
|
Loading…
Reference in New Issue