Reimplemented chaining arenas.

Added global variables.
Various fixes.
main
sixtenhugosson 2023-10-29 11:00:34 +01:00
parent 6e93783b03
commit b50ab896bb
71 changed files with 1147 additions and 1535 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
build/ build/
release/

View File

@ -0,0 +1,45 @@
UI_Column()
{
UI_Spacer(UI_Em(1, 1));
UI_Height(UI_Em(1, 1)) UI_Row()
{
UI_Width(UI_TextContent(15, 1)) UI_LabelF("Scrollbar T:");
UI_SetNextWidth(UI_Em(20, 1));
UI_SetNextCornerRadius(UI_TopFontSize()*0.5f);
ui_box *Container = UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, "Scrollable");
UI_Parent(Container)
{
UI_SetNextCornerRadius(UI_TopFontSize()*0.5f);
UI_SetNextSize(UI_Em(1, 1), UI_Em(1, 1));
UI_SetNextFixedX((DimOfRange(Container->Rect).x-UI_TopFontSize())*ScrollbarT);
ui_box *Box = UI_MakeBoxF(UI_BoxFlag_DrawBackground|
UI_BoxFlag_DrawBorder|
UI_BoxFlag_HotAnimation|
UI_BoxFlag_ActiveAnimation|
UI_BoxFlag_Clickable|
UI_BoxFlag_FloatingX|
0, "Dragable");
ui_signal Signal = UI_SignalFromBox(Box);
if(Signal.Dragging)
{
if(Signal.Pressed)
{
UI_StoreDragR32(ScrollbarT);
}
r32 StartT = UI_GetDragR32();
r32 EndT = StartT + Signal.DragDelta.x/(DimOfRange(Container->Rect).x-UI_TopFontSize());
ScrollbarT = Clamp01(EndT);
}
}
UI_Width(UI_TextContent(30, 1)) UI_Height(UI_Em(2, 1))
{
if(UI_ButtonF("Reset Dialog").Pressed)
{
Time = 0.0f;
}
}
}
}

View File

@ -10,4 +10,5 @@ codegen ../code/
cl %CommonCompilerOptions% ../code/vn.cpp /LD /link /export:VN_UpdateAndRender /incremental:no cl %CommonCompilerOptions% ../code/vn.cpp /LD /link /export:VN_UpdateAndRender /incremental:no
cl %CommonCompilerOptions% ../code/win32_main.cpp /link user32.lib gdi32.lib winmm.lib opengl32.lib cl %CommonCompilerOptions% ../code/win32_main.cpp /link user32.lib gdi32.lib winmm.lib opengl32.lib
popd popd

View File

@ -0,0 +1,16 @@
@echo off
set CommonCompilerOptions=/Zi /FC /nologo /DW32_LINK_SINGLE=1 /DVN_INTERNAL=0 /DVN_SLOW=0 /DVN_USE_INSTANCING=1 /O2 /W4 /WX /we4062 /wd4996 /wd4201 /wd4305 /wd4244 /wd4100 /wd4505 /std:c++17
if not exist "../release" mkdir "../release"
pushd "../release/"
rem cl /Zi /nologo /FC ../code/third_party/codegen/codegen.c
"../build/codegen" ../code/
cl %CommonCompilerOptions% ../code/win32_main.cpp /link user32.lib gdi32.lib winmm.lib opengl32.lib
xcopy /y /q win32_main.exe vn.exe
del win32_main.*
del *.pdb
popd

View File

@ -0,0 +1,11 @@
@echo off
set CommonCompilerOptions=/fsanitize=address /Zi /FC /nologo /DVN_ASAN_ENABLED=1 /DW32_LINK_SINGLE=1 /DVN_INTERNAL=1 /DVN_SLOW=1 /DVN_USE_INSTANCING=1 /Oi /W4 /WX /we4062 /wd4996 /wd4201 /wd4305 /wd4244 /wd4100 /wd4505 /std:c++17
if not exist "../build" mkdir "../build"
pushd "../build/"
rem cl /Zi /nologo /FC ../code/third_party/codegen/codegen.c
codegen ../code/
cl %CommonCompilerOptions% ../code/win32_main.cpp /link user32.lib gdi32.lib winmm.lib opengl32.lib /subsystem:console
popd

View File

@ -222,8 +222,8 @@ inline void EndTicketMutex(ticket_mutex *Mutex)
//- sixten: Axes //- sixten: Axes
enum axis2 enum axis2
{ {
Axis2_X, Axis2_X = 0,
Axis2_Y, Axis2_Y = 1,
Axis2_Count Axis2_Count
}; };

View File

@ -631,8 +631,14 @@ inline range2_r32 Intersection(range2_r32 A, range2_r32 B)
inline v2_r32 CornerFromRange(range2_r32 Range, corner Corner) inline v2_r32 CornerFromRange(range2_r32 Range, corner Corner)
{ {
v2_r32 Result = V2R32((Corner & (1 << Axis2_X))?Range.Min.x:Range.Max.x, v2_r32 Result = V2R32((Corner & (1 << Axis2_X))?Range.Max.x:Range.Min.x,
(Corner & (1 << Axis2_Y))?Range.Min.y:Range.Max.y); (Corner & (1 << Axis2_Y))?Range.Max.y:Range.Min.y);
return(Result);
}
inline range2_r32 Pad(range2_r32 Range, v2_r32 Value)
{
range2_r32 Result = Range2R32(Range.Min-Value, Range.Max+Value);
return(Result); return(Result);
} }
@ -670,8 +676,8 @@ inline range2_s32 Intersection(range2_s32 A, range2_s32 B)
inline v2_s32 CornerFromRange(range2_s32 Range, corner Corner) inline v2_s32 CornerFromRange(range2_s32 Range, corner Corner)
{ {
v2_s32 Result = V2S32((Corner & (1 << Axis2_X))?Range.Min.x:Range.Max.x, v2_s32 Result = V2S32((Corner & (1 << Axis2_X))?Range.Max.x:Range.Min.x,
(Corner & (1 << Axis2_Y))?Range.Min.y:Range.Max.y); (Corner & (1 << Axis2_Y))?Range.Max.y:Range.Min.y);
return(Result); return(Result);
} }
@ -709,7 +715,7 @@ inline range2_s64 Intersection(range2_s64 A, range2_s64 B)
inline v2_s64 CornerFromRange(range2_s64 Range, corner Corner) inline v2_s64 CornerFromRange(range2_s64 Range, corner Corner)
{ {
v2_s64 Result = V2S64((Corner & (1 << Axis2_X))?Range.Min.x:Range.Max.x, v2_s64 Result = V2S64((Corner & (1 << Axis2_X))?Range.Max.x:Range.Min.x,
(Corner & (1 << Axis2_Y))?Range.Min.y:Range.Max.y); (Corner & (1 << Axis2_Y))?Range.Max.y:Range.Min.y);
return(Result); return(Result);
} }

View File

@ -355,6 +355,7 @@ inline b32 Contains(range2_r32 Range, v2_r32 Value);
inline v2_r32 DimOfRange(range2_r32 Range); inline v2_r32 DimOfRange(range2_r32 Range);
inline range2_r32 Intersection(range2_r32 A, range2_r32 B); inline range2_r32 Intersection(range2_r32 A, range2_r32 B);
inline v2_r32 CornerFromRange(range2_r32 Range, corner Corner); inline v2_r32 CornerFromRange(range2_r32 Range, corner Corner);
inline range2_r32 Pad(range2_r32 Range, v2_r32 Value);
inline range2_s32 Range2S32(v2_s32 A, v2_s32 B); inline range2_s32 Range2S32(v2_s32 A, v2_s32 B);
inline b32 InRange(range2_s32 Range, v2_s32 Value); inline b32 InRange(range2_s32 Range, v2_s32 Value);

View File

@ -42,90 +42,192 @@ static void Fill(void *Dest, u8 Value, umm Count)
} }
} }
#if VN_ASAN_ENABLED
#include <sanitizer/asan_interface.h>
#endif
//////////////////////////////// ////////////////////////////////
//- sixten: Memory Arena Functions //- sixten: Memory Arena Functions
static memory_arena *ArenaAllocate(u64 Size) static arena *ArenaAlloc(u64 Size, b32 Chaining)
{ {
u64 RoundedSize = Size+Megabytes(64)-1; arena *Arena = 0;
RoundedSize -= RoundedSize&Megabytes(64); if(Chaining)
void *Memory = Platform.Reserve(RoundedSize); {
u64 InitialCommitSize = MEMORY_ARENA_COMMIT_SIZE; void *Memory = Platform.Allocate(Size);
Platform.Commit(Memory, InitialCommitSize); Arena = (arena *)Memory;
memory_arena *Arena = (memory_arena *)Memory;
Arena->Position = sizeof(memory_arena); #if VN_ASAN_ENABLED
Arena->CommitPosition = InitialCommitSize; ASAN_POISON_MEMORY_REGION(Arena, Size);
ASAN_UNPOISON_MEMORY_REGION(Arena, sizeof(arena));
#endif
Arena->Chaining = true;
SenDLLInit(Arena);
}
else
{
u64 RoundedSize = Size+Megabytes(64)-1;
RoundedSize -= RoundedSize&Megabytes(64);
void *Memory = Platform.Reserve(RoundedSize);
u64 InitialCommitSize = MEMORY_ARENA_COMMIT_SIZE;
Platform.Commit(Memory, InitialCommitSize);
Arena = (arena *)Memory;
}
Arena->Position = sizeof(arena);
Arena->Size = Size; Arena->Size = Size;
Arena->Align = 8; Arena->Align = 8;
return(Arena); return(Arena);
} }
static void ArenaRelease(memory_arena *Arena) static void ArenaRelease(arena *Arena)
{ {
Platform.Release(Arena); if(Arena->Chaining)
{
arena *Node = Arena->Prev;
for(;Node != Arena;)
{
arena *Next = Node->Prev;
Platform.Deallocate(Node);
Node = Next;
}
#if VN_ASAN_ENABLED
ASAN_POISON_MEMORY_REGION(Arena, Arena->Size);
#endif
Platform.Deallocate(Arena);
}
else
{
Platform.Release(Arena);
}
} }
static void *ArenaPushNoClear(memory_arena *Arena, u64 Size) static void *ArenaPushNoClear(arena *Arena, u64 Size)
{ {
void *Result = 0; void *Result = 0;
if(Arena->Position + Size <= Arena->Size) if(Arena->Chaining)
{ {
u8 *Base = (u8 *)Arena; if(Size <= Arena->Size)
u64 PostAlignPos = (Arena->Position+Arena->Align-1);
PostAlignPos -= PostAlignPos%Arena->Align;
u64 Align = PostAlignPos - Arena->Position;
Result = Base + Arena->Position + Align;
Arena->Position += Size + Align;
if(Arena->CommitPosition < Arena->Position)
{ {
u64 ToCommit = Arena->Position - Arena->CommitPosition; arena *Target = Arena->Prev; // sixten: We always append to the end of the list.
ToCommit += MEMORY_ARENA_COMMIT_SIZE - 1; if(Target->Position + Size > Target->Size)
ToCommit -= ToCommit%MEMORY_ARENA_COMMIT_SIZE; {
Platform.Commit(Base + Arena->CommitPosition, ToCommit); arena *New = ArenaAlloc(Arena->Size, true);
Arena->CommitPosition += ToCommit; New->NotFirst = true;
SenDLLInsertLast(Arena, New);
Target = New;
}
u8 *Base = (u8 *)Target;
u64 PostAlignPos = (Target->Position+Target->Align-1);
PostAlignPos -= PostAlignPos%Target->Align;
Result = Base + PostAlignPos;
Target->Position = PostAlignPos+Size;
#if VN_ASAN_ENABLED
ASAN_UNPOISON_MEMORY_REGION(Result, Size);
#endif
}
else
{
// sixten(NOTE): We can't really do anything in this situation.
} }
} }
else else
{ {
InvalidCodepath; if(Arena->Position + Size <= Arena->Size)
{
u8 *Base = (u8 *)Arena;
u64 PostAlignPos = (Arena->Position+Arena->Align-1);
PostAlignPos -= PostAlignPos%Arena->Align;
u64 Align = PostAlignPos - Arena->Position;
Result = Base + Arena->Position + Align;
Arena->Position += Size + Align;
if(Arena->CommitPosition < Arena->Position)
{
u64 ToCommit = Arena->Position - Arena->CommitPosition;
ToCommit += MEMORY_ARENA_COMMIT_SIZE - 1;
ToCommit -= ToCommit%MEMORY_ARENA_COMMIT_SIZE;
Platform.Commit(Base + Arena->CommitPosition, ToCommit);
Arena->CommitPosition += ToCommit;
}
}
else
{
InvalidCodepath;
}
} }
return(Result); return(Result);
} }
static void *ArenaPush(memory_arena *Arena, u64 Size) static void *ArenaPush(arena *Arena, u64 Size)
{ {
void *Result = ArenaPushNoClear(Arena, Size); void *Result = ArenaPushNoClear(Arena, Size);
Fill(Result, 0, Size); Fill(Result, 0, Size);
return(Result); return(Result);
} }
static void ArenaPopTo(memory_arena *Arena, u64 Position) static void ArenaPopTo(arena *Arena, u64 Position)
{ {
u64 MinPosition = sizeof(*Arena); if(Arena->Chaining)
u64 NewPosition = Maximum(MinPosition, Position);
Arena->Position = NewPosition;
u64 CommitAlignedPosition = Arena->Position+MEMORY_ARENA_COMMIT_SIZE-1;
CommitAlignedPosition -= CommitAlignedPosition%MEMORY_ARENA_COMMIT_SIZE;
if(CommitAlignedPosition + MEMORY_ARENA_DECOMMIT_THRESHOLD <= Arena->CommitPosition)
{ {
u8 *Base = (u8 *)Arena; // sixten: find the relevant arena
u64 ToDecommit = Arena->CommitPosition-CommitAlignedPosition; arena *Target = Arena;
Platform.Decommit(Base+CommitAlignedPosition, ToDecommit); for(int ArenaIndex = 0; ArenaIndex < Position/Arena->Size; ++ArenaIndex)
Arena->CommitPosition -= ToDecommit; {
Target = Arena->Next;
}
// sixten: deallocate all arenas that are no longer needed
{
arena *Node = Arena->Prev;
while(Node != Target)
{
arena *Prev = Node->Prev;
SenDLLRemove(Node);
#if VN_ASAN_ENABLED
ASAN_POISON_MEMORY_REGION(Node, Node->Size);
#endif
Platform.Deallocate(Node);
Node = Prev;
}
}
Target->Position = Position%Arena->Size;
#if VN_ASAN_ENABLED
u64 UnpoisonPosition = Target->Position;
ASAN_POISON_MEMORY_REGION(Target, Target->Size);
ASAN_UNPOISON_MEMORY_REGION(Target, UnpoisonPosition);
#endif
}
else
{
u64 MinPosition = sizeof(*Arena);
u64 NewPosition = Maximum(MinPosition, Position);
Arena->Position = NewPosition;
u64 CommitAlignedPosition = Arena->Position+MEMORY_ARENA_COMMIT_SIZE-1;
CommitAlignedPosition -= CommitAlignedPosition%MEMORY_ARENA_COMMIT_SIZE;
if(CommitAlignedPosition + MEMORY_ARENA_DECOMMIT_THRESHOLD <= Arena->CommitPosition)
{
u8 *Base = (u8 *)Arena;
u64 ToDecommit = Arena->CommitPosition-CommitAlignedPosition;
Platform.Decommit(Base+CommitAlignedPosition, ToDecommit);
Arena->CommitPosition -= ToDecommit;
}
} }
} }
static void ArenaPop(memory_arena *Arena, u64 Amount) static void ArenaPop(arena *Arena, u64 Amount)
{ {
ArenaPopTo(Arena, Max(Arena->Position-Amount, (s64)sizeof(memory_arena))); ArenaPopTo(Arena, Max(Arena->Position-Amount, (s64)sizeof(arena)));
} }
static void ArenaClear(memory_arena *Arena) static void ArenaClear(arena *Arena)
{ {
ArenaPopTo(Arena, sizeof(*Arena)); ArenaPopTo(Arena, sizeof(*Arena));
} }
static void ArenaSetAlign(memory_arena *Arena, u64 Align) static void ArenaSetAlign(arena *Arena, u64 Align)
{ {
Arena->Align = Align; Arena->Align = Align;
} }
@ -133,7 +235,7 @@ static void ArenaSetAlign(memory_arena *Arena, u64 Align)
//////////////////////////////// ////////////////////////////////
//- sixten: Temporary Memory Functions //- sixten: Temporary Memory Functions
static temporary_memory BeginTemporaryMemory(memory_arena *Arena) static temporary_memory BeginTemporaryMemory(arena *Arena)
{ {
temporary_memory Temp; temporary_memory Temp;
Temp.Arena = Arena; Temp.Arena = Arena;

View File

@ -3,6 +3,23 @@
#ifndef CORE_MEMORY_H #ifndef CORE_MEMORY_H
#define CORE_MEMORY_H #define CORE_MEMORY_H
/*
The arenas can be used in two modes:
1. Fixed Size:
This is primarily intended for when you need a contigous buffer of memory, it reserves a large chunk
of virtual address space (if applicable) and partitions it to the user.
2. Chaining:
This is the workaround for WASM not supporting memory mapping. It allocates in chunks based on the initial
size requested in the ArenaAlloc call. Internally it just consists of a cyclic doubly linked list.
Potential alternatives:
If you pass in a size of 0 in ArenaAlloc, you get a chaining arena with set chunk size that can extend if
a PushSize call requests more than the prespecified standard. (ex. 4KB chunks, but if you load a file then
that becomes its own chunk)
*/
//////////////////////////////// ////////////////////////////////
//- sixten: Common Memory Functions //- sixten: Common Memory Functions
@ -15,18 +32,22 @@ static void Fill(void *Dest, u8 Value, umm Count);
//////////////////////////////// ////////////////////////////////
//- sixten: Memory Arena Types //- sixten: Memory Arena Types
struct memory_arena struct arena
{ {
u64 Position; u64 Position;
u64 CommitPosition; u64 CommitPosition;
u64 Size; u64 Size;
u64 Align; u64 Align;
u64 Unused[4]; b32 Chaining;
b32 NotFirst;
arena *Next;
arena *Prev;
u64 Unused[1];
}; };
struct temporary_memory struct temporary_memory
{ {
memory_arena *Arena; arena *Arena;
u64 Position; u64 Position;
}; };
@ -38,14 +59,14 @@ struct temporary_memory
//////////////////////////////// ////////////////////////////////
//- sixten: Memory Arena Functions //- sixten: Memory Arena Functions
static memory_arena *ArenaAllocate(u64 Size); static arena *ArenaAlloc(u64 Size, b32 Chaining = false);
static void ArenaRelease(memory_arena *Arena); static void ArenaRelease(arena *Arena);
static void *ArenaPushNoClear(memory_arena *Arena, u64 Size); static void *ArenaPushNoClear(arena *Arena, u64 Size);
static void *ArenaPush(memory_arena *Arena, u64 Size); static void *ArenaPush(arena *Arena, u64 Size);
static void ArenaPopTo(memory_arena *Arena, u64 Position); static void ArenaPopTo(arena *Arena, u64 Position);
static void ArenaPop(memory_arena *Arena, u64 Amount); static void ArenaPop(arena *Arena, u64 Amount);
static void ArenaClear(memory_arena *Arena); static void ArenaClear(arena *Arena);
static void ArenaSetAlign(memory_arena *Arena, u64 Align); static void ArenaSetAlign(arena *Arena, u64 Align);
#define PushArray(Arena, type, Count) (type *)ArenaPush((Arena), sizeof(type)*(Count)) #define PushArray(Arena, type, Count) (type *)ArenaPush((Arena), sizeof(type)*(Count))
#define PushArrayNoClear(Arena, type, Count) (type *)ArenaPushNoClear((Arena), sizeof(type)*(Count)) #define PushArrayNoClear(Arena, type, Count) (type *)ArenaPushNoClear((Arena), sizeof(type)*(Count))
#define PushStruct(Arena, type) (type *)ArenaPush((Arena), sizeof(type)) #define PushStruct(Arena, type) (type *)ArenaPush((Arena), sizeof(type))
@ -54,7 +75,7 @@ static void ArenaSetAlign(memory_arena *Arena, u64 Align);
//////////////////////////////// ////////////////////////////////
//- sixten: Temporary Memory Functions //- sixten: Temporary Memory Functions
static temporary_memory BeginTemporaryMemory(memory_arena *Arena); static temporary_memory BeginTemporaryMemory(arena *Arena);
static void EndTemporaryMemory(temporary_memory Temp); static void EndTemporaryMemory(temporary_memory Temp);
#endif //CORE_MEMORY_H #endif //CORE_MEMORY_H

View File

@ -195,7 +195,7 @@ static s64 LastIndexOf(string String, string Sub)
//- sixten: Allocation //- sixten: Allocation
static string PushString(memory_arena *Arena, string String) static string PushString(arena *Arena, string String)
{ {
string Result; string Result;
Result.Data = PushArrayNoClear(Arena, u8, String.Count); Result.Data = PushArrayNoClear(Arena, u8, String.Count);
@ -205,7 +205,7 @@ static string PushString(memory_arena *Arena, string String)
return(Result); return(Result);
} }
static string PushFormatVariadic(memory_arena *Arena, char *Format, va_list Arguments) static string PushFormatVariadic(arena *Arena, char *Format, va_list Arguments)
{ {
va_list ArgumentsCopy; va_list ArgumentsCopy;
va_copy(ArgumentsCopy, Arguments); va_copy(ArgumentsCopy, Arguments);
@ -220,7 +220,7 @@ static string PushFormatVariadic(memory_arena *Arena, char *Format, va_list Argu
return(Result); return(Result);
} }
static string PushFormat(memory_arena *Arena, char *Format, ...) static string PushFormat(arena *Arena, char *Format, ...)
{ {
va_list Arguments; va_list Arguments;
va_start(Arguments, Format); va_start(Arguments, Format);
@ -230,7 +230,7 @@ static string PushFormat(memory_arena *Arena, char *Format, ...)
return(Result); return(Result);
} }
static string PushCString(memory_arena *Arena, char *CString) static string PushCString(arena *Arena, char *CString)
{ {
string String = MakeString(CString); string String = MakeString(CString);
string Result = PushString(Arena, String); string Result = PushString(Arena, String);
@ -266,7 +266,7 @@ static s64 ConvertStringToS64(string String)
return(Result); return(Result);
} }
static string ConvertS64ToString(memory_arena *Arena, s64 Value) static string ConvertS64ToString(arena *Arena, s64 Value)
{ {
b32 IsNegative = (Value < 0); b32 IsNegative = (Value < 0);
if(IsNegative) if(IsNegative)
@ -297,7 +297,7 @@ static string ConvertS64ToString(memory_arena *Arena, s64 Value)
return(String); return(String);
} }
static string StringFromCodepoint(memory_arena *Arena, u32 Codepoint) static string StringFromCodepoint(arena *Arena, u32 Codepoint)
{ {
char Buffer[5] = {}; char Buffer[5] = {};
UTF8FromCodepoint((u8 *)Buffer, Codepoint); UTF8FromCodepoint((u8 *)Buffer, Codepoint);
@ -317,7 +317,7 @@ static r64 DoubleFromString(string String)
//- sixten: Replacing //- sixten: Replacing
static string RemoveAll(memory_arena *Arena, string Text, char ToRemove) static string RemoveAll(arena *Arena, string Text, char ToRemove)
{ {
//- sixten: get new count //- sixten: get new count
s64 Occurrences = 0; s64 Occurrences = 0;
@ -377,7 +377,7 @@ static s64 StringLength16(u16 *String)
//~ sixten: String list //~ sixten: String list
static void AppendString(string_list *List, string String, memory_arena *Arena) static void AppendString(string_list *List, string String, arena *Arena)
{ {
string_node *Node = PushStruct(Arena, string_node); string_node *Node = PushStruct(Arena, string_node);
Node->String = String; Node->String = String;
@ -387,7 +387,7 @@ static void AppendString(string_list *List, string String, memory_arena *Arena)
DLLInsertLast(List->First, List->Last, Node); DLLInsertLast(List->First, List->Last, Node);
} }
static string JoinStringList(string_list *List, memory_arena *Arena) static string JoinStringList(string_list *List, arena *Arena)
{ {
u8 *Buffer = PushArray(Arena, u8, List->TotalCount + 1); u8 *Buffer = PushArray(Arena, u8, List->TotalCount + 1);
Buffer[List->TotalCount] = 0; Buffer[List->TotalCount] = 0;
@ -420,7 +420,7 @@ static string_chunk_list MakeStringChunkList(s64 ChunkSize)
return(Result); return(Result);
} }
static string JoinStringChunkList(memory_arena *Arena, string_chunk_list *List) static string JoinStringChunkList(arena *Arena, string_chunk_list *List)
{ {
string Result = {}; string Result = {};
Result.Count = List->TotalCount; Result.Count = List->TotalCount;
@ -438,7 +438,7 @@ static string JoinStringChunkList(memory_arena *Arena, string_chunk_list *List)
} }
// sixten(TODO): Incomplete, remove maybe? // sixten(TODO): Incomplete, remove maybe?
static void ReplaceRange(memory_arena *Arena, string_chunk_list *List, string Text, range1_s64 Range) static void ReplaceRange(arena *Arena, string_chunk_list *List, string Text, range1_s64 Range)
{ {
s64 NewTotalCount = Max(0ULL, List->TotalCount - DimOfRange(Range)) + Text.Count; s64 NewTotalCount = Max(0ULL, List->TotalCount - DimOfRange(Range)) + Text.Count;
@ -714,7 +714,7 @@ static s64 UTF8FromCodepoint(u8 *Out, u32 Codepoint)
return(Length); return(Length);
} }
static string String8FromString16(memory_arena *Arena, string16 String) static string String8FromString16(arena *Arena, string16 String)
{ {
s64 AllocGuess = String.Count*3+1; s64 AllocGuess = String.Count*3+1;
u8 *Memory = PushArray(Arena, u8, AllocGuess); u8 *Memory = PushArray(Arena, u8, AllocGuess);
@ -738,7 +738,7 @@ static string String8FromString16(memory_arena *Arena, string16 String)
return(Result); return(Result);
} }
static string16 String16FromString8(memory_arena *Arena, string String) static string16 String16FromString8(arena *Arena, string String)
{ {
s64 AllocGuess = String.Count*2+1; s64 AllocGuess = String.Count*2+1;
u16 *Memory = PushArray(Arena, u16, AllocGuess); u16 *Memory = PushArray(Arena, u16, AllocGuess);
@ -843,7 +843,7 @@ static text_range TextRange(text_point A, text_point B)
//////////////////////////////// ////////////////////////////////
//~ sixten: 1D Interval List & Array Functions //~ sixten: 1D Interval List & Array Functions
static void Range1S64ListPush(memory_arena *Arena, range1_s64_list *List, range1_s64 Range) static void Range1S64ListPush(arena *Arena, range1_s64_list *List, range1_s64 Range)
{ {
range1_s64_node *Node = PushStructNoClear(Arena, range1_s64_node); range1_s64_node *Node = PushStructNoClear(Arena, range1_s64_node);
Node->Range = Range; Node->Range = Range;
@ -851,7 +851,7 @@ static void Range1S64ListPush(memory_arena *Arena, range1_s64_list *List, range1
List->Count += 1; List->Count += 1;
} }
static range1_s64_array Range1S64ArrayFromList(memory_arena *Arena, range1_s64_list *List) static range1_s64_array Range1S64ArrayFromList(arena *Arena, range1_s64_list *List)
{ {
range1_s64_array Result = {}; range1_s64_array Result = {};
Result.Count = List->Count; Result.Count = List->Count;

View File

@ -93,21 +93,21 @@ static s64 LastIndexOf(string String, string Sub);
//- sixten: Allocation //- sixten: Allocation
static string PushString(memory_arena *Arena, string String); static string PushString(arena *Arena, string String);
static string PushFormatVariadic(memory_arena *Arena, char *Format, va_list Arguments); static string PushFormatVariadic(arena *Arena, char *Format, va_list Arguments);
static string PushFormat(memory_arena *Arena, char *Format, ...); static string PushFormat(arena *Arena, char *Format, ...);
static string PushCString(memory_arena *Arena, char *String); static string PushCString(arena *Arena, char *String);
//- sixten: Conversion //- sixten: Conversion
static s64 ConvertStringToS64(string String); static s64 ConvertStringToS64(string String);
static string ConvertS64ToString(memory_arena *Arena, s64 Value); static string ConvertS64ToString(arena *Arena, s64 Value);
static string StringFromCodepoint(memory_arena *Arena, u32 Codepoint); static string StringFromCodepoint(arena *Arena, u32 Codepoint);
static r64 DoubleFromString(string String); static r64 DoubleFromString(string String);
//- sixten: Replacing //- sixten: Replacing
static string RemoveAll(memory_arena *Arena, string Text, char ToRemove); static string RemoveAll(arena *Arena, string Text, char ToRemove);
//- sixten: "C Style" strings //- sixten: "C Style" strings
@ -115,18 +115,10 @@ static s64 StringLength(char *String);
static s64 StringLength16(u16 *String); static s64 StringLength16(u16 *String);
#if 0
/////////////////////////////////////
//~ sixten: String Chunk Functions
static string_chunk_list MakeStringChunkList(s64 ChunkSize);
static string JoinStringChunkList(memory_arena *Arena, string_chunk_list *List);
static void ReplaceRange(memory_arena *Arena, string_chunk_list *List, string Text, range1_s64 Range);
#endif
//~ sixten: String list //~ sixten: String list
static void AppendString(string_list *List, string String, memory_arena *Arena); static void AppendString(string_list *List, string String, arena *Arena);
static string JoinStringList(string_list *List, memory_arena *Arena); static string JoinStringList(string_list *List, arena *Arena);
//~ sixten: Unicode //~ sixten: Unicode
@ -145,8 +137,8 @@ static u32 EncodeUTF16Codepoint(u16 *Dest, u32 Codepoint);
static s64 UTF8FromCodepoint(u8 *Out, u32 Codepoint); static s64 UTF8FromCodepoint(u8 *Out, u32 Codepoint);
static string String8FromString16(memory_arena *Arena, string16 String); static string String8FromString16(arena *Arena, string16 String);
static string16 String16FromString8(memory_arena *Arena, string String); static string16 String16FromString8(arena *Arena, string String);
//~ sixten: Text point //~ sixten: Text point
@ -190,8 +182,8 @@ struct range1_s64_array
//////////////////////////////// ////////////////////////////////
//~ sixten: 1D Interval List & Array Functions //~ sixten: 1D Interval List & Array Functions
static void Range1S64ListPush(memory_arena *Arena, range1_s64_list *List, range1_s64 Range); static void Range1S64ListPush(arena *Arena, range1_s64_list *List, range1_s64 Range);
static range1_s64_array Range1S64ArrayFromList(memory_arena *Arena, range1_s64_list *List); static range1_s64_array Range1S64ArrayFromList(arena *Arena, range1_s64_list *List);
static s64 OffsetFromTextPoint(string Text, range1_s64_array Lines, text_point Point); static s64 OffsetFromTextPoint(string Text, range1_s64_array Lines, text_point Point);
#endif //CORE_STRING_H #endif //CORE_STRING_H

View File

@ -5,7 +5,7 @@ static thread_context AllocateThreadContext(void)
thread_context Context = {}; thread_context Context = {};
for(s64 ArenaIndex = 0; ArenaIndex < ArrayCount(Context.Arenas); ArenaIndex += 1) for(s64 ArenaIndex = 0; ArenaIndex < ArrayCount(Context.Arenas); ArenaIndex += 1)
{ {
Context.Arenas[ArenaIndex] = ArenaAllocate(Gigabytes(1)); Context.Arenas[ArenaIndex] = ArenaAlloc(Megabytes(2), true);
} }
return(Context); return(Context);
} }
@ -20,7 +20,7 @@ static thread_context *GetThreadContext(void)
return(ThreadLocal_ThreadContext); return(ThreadLocal_ThreadContext);
} }
static temporary_memory GetScratch(memory_arena **Conflicts, u64 ConflictCount) static temporary_memory GetScratch(arena **Conflicts, u64 ConflictCount)
{ {
temporary_memory Scratch = {}; temporary_memory Scratch = {};
thread_context *Context = GetThreadContext(); thread_context *Context = GetThreadContext();
@ -34,7 +34,7 @@ static temporary_memory GetScratch(memory_arena **Conflicts, u64 ConflictCount)
ConflictIndex < ConflictCount; ConflictIndex < ConflictCount;
++ConflictIndex) ++ConflictIndex)
{ {
memory_arena *Conflict = Conflicts[ConflictIndex]; arena *Conflict = Conflicts[ConflictIndex];
if(Conflict == Context->Arenas[ArenaIndex]) if(Conflict == Context->Arenas[ArenaIndex])
{ {
FoundConflict = true; FoundConflict = true;

View File

@ -5,7 +5,7 @@
struct thread_context struct thread_context
{ {
memory_arena *Arenas[2]; arena *Arenas[2];
}; };
//- sixten: Thread state management //- sixten: Thread state management
@ -13,7 +13,7 @@ static void SetThreadContext(thread_context *Context);
static thread_context *GetThreadContext(void); static thread_context *GetThreadContext(void);
//- sixten: Scratch //- sixten: Scratch
static temporary_memory GetScratch(memory_arena **Conflicts = 0, u64 ConflictCount = 0); static temporary_memory GetScratch(arena **Conflicts = 0, u64 ConflictCount = 0);
#define ReleaseScratch(Scratch) EndTemporaryMemory(Scratch) #define ReleaseScratch(Scratch) EndTemporaryMemory(Scratch)
#endif //CORE_THREAD_CONTEXT_H #endif //CORE_THREAD_CONTEXT_H

View File

@ -5,6 +5,7 @@ if(0) {}
else if(AreEqual(String, StrLit("none"))) { Result = CR_State_None; } else if(AreEqual(String, StrLit("none"))) { Result = CR_State_None; }
else if(AreEqual(String, StrLit("normal"))) { Result = CR_State_Normal; } else if(AreEqual(String, StrLit("normal"))) { Result = CR_State_Normal; }
else if(AreEqual(String, StrLit("happy"))) { Result = CR_State_Happy; } else if(AreEqual(String, StrLit("happy"))) { Result = CR_State_Happy; }
else if(AreEqual(String, StrLit("leaning"))) { Result = CR_State_Leaning; }
return(Result); return(Result);
} }

View File

@ -4,5 +4,6 @@ CR_State_Invalid = 0,
CR_State_None, CR_State_None,
CR_State_Normal, CR_State_Normal,
CR_State_Happy, CR_State_Happy,
CR_State_Leaning,
}; };

View File

@ -2,6 +2,8 @@
#define PLATFORM_RELEASE(name) void name(void *Pointer) #define PLATFORM_RELEASE(name) void name(void *Pointer)
#define PLATFORM_COMMIT(name) void name(void *Pointer, u64 Size) #define PLATFORM_COMMIT(name) void name(void *Pointer, u64 Size)
#define PLATFORM_DECOMMIT(name) void name(void *Pointer, u64 Size) #define PLATFORM_DECOMMIT(name) void name(void *Pointer, u64 Size)
#define PLATFORM_ALLOCATE(name) void * name(u64 Size)
#define PLATFORM_DEALLOCATE(name) void name(void *Pointer)
#define PLATFORM_OPEN_FILE(name) platform_file_handle name(string Path, platform_access_flags FileAccess) #define PLATFORM_OPEN_FILE(name) platform_file_handle name(string Path, platform_access_flags FileAccess)
#define PLATFORM_CLOSE_FILE(name) void name(platform_file_handle Handle) #define PLATFORM_CLOSE_FILE(name) void name(platform_file_handle Handle)
#define PLATFORM_READ_FILE(name) void name(platform_file_handle Handle, void *Dest, u64 Offset, u64 Size) #define PLATFORM_READ_FILE(name) void name(platform_file_handle Handle, void *Dest, u64 Offset, u64 Size)
@ -10,16 +12,18 @@
#define PLATFORM_SET_CURSOR(name) void name(platform_cursor Cursor) #define PLATFORM_SET_CURSOR(name) void name(platform_cursor Cursor)
#define PLATFORM_TOGGLE_FULLSCREEN(name) void name(void) #define PLATFORM_TOGGLE_FULLSCREEN(name) void name(void)
#define PLATFORM_SHOW_MESSAGE(name) void name(string Message, platform_message_type Type) #define PLATFORM_SHOW_MESSAGE(name) void name(string Message, platform_message_type Type)
#define PLATFORM_BEGIN_FILE_ITER(name) platform_file_iter * name(memory_arena *Arena, string Path) #define PLATFORM_BEGIN_FILE_ITER(name) platform_file_iter * name(arena *Arena, string Path)
#define PLATFORM_ADVANCE_FILE_ITER(name) b32 name(memory_arena *Arena, platform_file_iter *Iter, platform_file_info *OutInfo) #define PLATFORM_ADVANCE_FILE_ITER(name) b32 name(arena *Arena, platform_file_iter *Iter, platform_file_info *OutInfo)
#define PLATFORM_END_FILE_ITER(name) void name(platform_file_iter *Iter) #define PLATFORM_END_FILE_ITER(name) void name(platform_file_iter *Iter)
#define PLATFORM_SET_CLIPBOARD(name) void name(string String) #define PLATFORM_SET_CLIPBOARD(name) void name(string String)
#define PLATFORM_GET_CLIPBOARD(name) string name(memory_arena *Arena) #define PLATFORM_GET_CLIPBOARD(name) string name(arena *Arena)
typedef PLATFORM_RESERVE(platform_reserve); typedef PLATFORM_RESERVE(platform_reserve);
typedef PLATFORM_RELEASE(platform_release); typedef PLATFORM_RELEASE(platform_release);
typedef PLATFORM_COMMIT(platform_commit); typedef PLATFORM_COMMIT(platform_commit);
typedef PLATFORM_DECOMMIT(platform_decommit); typedef PLATFORM_DECOMMIT(platform_decommit);
typedef PLATFORM_ALLOCATE(platform_allocate);
typedef PLATFORM_DEALLOCATE(platform_deallocate);
typedef PLATFORM_OPEN_FILE(platform_open_file); typedef PLATFORM_OPEN_FILE(platform_open_file);
typedef PLATFORM_CLOSE_FILE(platform_close_file); typedef PLATFORM_CLOSE_FILE(platform_close_file);
typedef PLATFORM_READ_FILE(platform_read_file); typedef PLATFORM_READ_FILE(platform_read_file);
@ -40,6 +44,8 @@ platform_reserve *Reserve;
platform_release *Release; platform_release *Release;
platform_commit *Commit; platform_commit *Commit;
platform_decommit *Decommit; platform_decommit *Decommit;
platform_allocate *Allocate;
platform_deallocate *Deallocate;
platform_open_file *OpenFile; platform_open_file *OpenFile;
platform_close_file *CloseFile; platform_close_file *CloseFile;
platform_read_file *ReadFile; platform_read_file *ReadFile;
@ -60,6 +66,8 @@ Platform.Reserve = PlatformName##_Reserve;\
Platform.Release = PlatformName##_Release;\ Platform.Release = PlatformName##_Release;\
Platform.Commit = PlatformName##_Commit;\ Platform.Commit = PlatformName##_Commit;\
Platform.Decommit = PlatformName##_Decommit;\ Platform.Decommit = PlatformName##_Decommit;\
Platform.Allocate = PlatformName##_Allocate;\
Platform.Deallocate = PlatformName##_Deallocate;\
Platform.OpenFile = PlatformName##_OpenFile;\ Platform.OpenFile = PlatformName##_OpenFile;\
Platform.CloseFile = PlatformName##_CloseFile;\ Platform.CloseFile = PlatformName##_CloseFile;\
Platform.ReadFile = PlatformName##_ReadFile;\ Platform.ReadFile = PlatformName##_ReadFile;\

View File

@ -106,7 +106,7 @@ static RENDER_ALLOCATE_TEXTURE(OpenGL_AllocateTexture)
if(GenerateMipmap) if(GenerateMipmap)
{ {
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} }
else else

View File

@ -308,6 +308,12 @@ static void stbsp__lead_sign(stbsp__uint32 fl, char *sign)
static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit) static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit)
{ {
#if VN_ASAN_ENABLED && _WIN32
// sixten(NOTE): MSVC has no way of handling functions that disable ASAN, thus we need alternatives:
stbsp__uint32 l = 0;
while(limit-- && *s++) l++;
return l;
#else
char const * sn = s; char const * sn = s;
// get up to 4-byte alignment // get up to 4-byte alignment
@ -344,6 +350,7 @@ static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uin
} }
return (stbsp__uint32)(sn - s); return (stbsp__uint32)(sn - s);
#endif
} }
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va) STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va)

View File

@ -16,19 +16,25 @@ struct debug_settings
global debug_settings *DEBUG_DebugSettings = 0; global debug_settings *DEBUG_DebugSettings = 0;
#endif #endif
#include "generated/vn_character.meta.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"
#include "vn_text_op.h" #include "vn_text_op.h"
#include "vn_ui.h" #include "vn_ui.h"
#include "vn_ui_utils.h" #include "vn_ui_utils.h"
#include "vn_character.h"
#include "vn_scene.h" #include "vn_scene.h"
#include "vn_scene_view.h" #include "vn_scene_view.h"
#include "vn_workspace.h"
#include "vn_animation_curve.h" #include "vn_animation_curve.h"
#include "vn_theme_dark.h" #include "vn_theme_dark.h"
#if VN_INTERNAL
#include "vn_workspace.h"
#endif
#include "generated/vn_character.meta.c"
#include "vn_tokenizer.cpp" #include "vn_tokenizer.cpp"
#include "vn_config.cpp" #include "vn_config.cpp"
#include "vn_render.cpp" #include "vn_render.cpp"
@ -38,29 +44,30 @@ global debug_settings *DEBUG_DebugSettings = 0;
#include "vn_animation_curve.cpp" #include "vn_animation_curve.cpp"
#include "vn_scene.cpp" #include "vn_scene.cpp"
#include "vn_scene_view.cpp" #include "vn_scene_view.cpp"
#if VN_INTERNAL
#include "vn_workspace.cpp" #include "vn_workspace.cpp"
#include "vn_character.cpp" #endif
struct vn_state struct vn_state
{ {
memory_arena *Arena; arena *Arena;
memory_arena *FrameArena; arena *FrameArena;
glyph_atlas *GlyphAtlas; glyph_atlas *GlyphAtlas;
config *Config; config *Config;
ui UI; ui UI;
workspace Workspace;
animation_curve_state AnimationCurveState; animation_curve_state AnimationCurveState;
b32 EditorMode; b32 EditorMode;
character_registry CharacterRegistry;
render_handle BackgroundTexture; render_handle BackgroundTexture;
scene_view SceneView; scene_view SceneView;
#if VN_INTERNAL #if VN_INTERNAL
workspace Workspace;
debug_settings DebugSettings; debug_settings DebugSettings;
#endif #endif
}; };
@ -109,16 +116,16 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
//- sixten: initialize application state //- sixten: initialize application state
if(!Memory->State) if(!Memory->State)
{ {
memory_arena *Arena = ArenaAllocate(Gigabytes(1)); arena *Arena = ArenaAlloc(Kilobytes(24), true);
State = Memory->State = PushStruct(Arena, vn_state); State = Memory->State = PushStruct(Arena, vn_state);
State->Arena = Arena; State->Arena = Arena;
State->FrameArena = ArenaAllocate(Gigabytes(1)); State->FrameArena = ArenaAlloc(Megabytes(1), true);
State->GlyphAtlas = CreateGlyphAtlas(RenderCommands); State->GlyphAtlas = CreateGlyphAtlas(RenderCommands);
State->Config = CreateConfig(); State->Config = CreateConfig();
//- sixten: load assets //- sixten: load assets
State->BackgroundTexture = CreateTextureFromPath(RenderCommands, StrLit("data/backgrounds/test.png")); State->BackgroundTexture = CreateTextureFromPath(RenderCommands, StrLit("data/backgrounds/ddlc-club.png"));
//- sixten: setup config binds and load current config //- sixten: setup config binds and load current config
{ {
@ -139,20 +146,23 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
SV_Init(SceneView, State->Arena); SV_Init(SceneView, State->Arena);
temporary_memory Scratch = GetScratch(); temporary_memory Scratch = GetScratch();
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, StrLit("data/character.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 = CreateTextureFromPath(RenderCommands, StrLit("data/characters/test_happy.png"));
SceneView->TestNormal = CreateTextureFromPath(RenderCommands, StrLit("data/characters/test_normal.png")); SceneView->TestNormal = CreateTextureFromPath(RenderCommands, StrLit("data/characters/test_normal.png"));
SceneView->MonikaLeaning = CreateTextureFromPath(RenderCommands, StrLit("data/characters/monika_leaning.png"));
SceneView->BackgroundTexture = State->BackgroundTexture; SceneView->BackgroundTexture = State->BackgroundTexture;
CR_Init(&State->CharacterRegistry);
UI_Init(&State->UI); UI_Init(&State->UI);
W_Init(&State->Workspace);
AC_Init(&State->AnimationCurveState); AC_Init(&State->AnimationCurveState);
#if VN_INTERNAL
W_Init(&State->Workspace);
#endif
return; return;
} }
@ -175,14 +185,18 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
//- sixten: build the ui //- sixten: build the ui
UI_BeginBuild(RenderCommands->RenderDim); UI_BeginBuild(RenderCommands->RenderDim);
{ {
#if VN_INTERNAL
if(State->EditorMode) if(State->EditorMode)
{ {
W_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas); W_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas);
} }
else else
{ {
#endif
SV_BuildSceneView(Input); SV_BuildSceneView(Input);
#if VN_INTERNAL
} }
#endif
} }
UI_EndBuild(); UI_EndBuild();
@ -211,6 +225,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
UI_RenderFrame(&Group, State->GlyphAtlas); UI_RenderFrame(&Group, State->GlyphAtlas);
#if VN_INTERNAL
if(DEBUG_DebugSettings->ListHotAndActive) if(DEBUG_DebugSettings->ListHotAndActive)
{ {
PushText(&Group, State->GlyphAtlas, Font_Regular, V2(5, RenderCommands->RenderDim.y - 20), 15, Color_Grey, PushText(&Group, State->GlyphAtlas, Font_Regular, V2(5, RenderCommands->RenderDim.y - 20), 15, Color_Grey,
@ -218,5 +233,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
PushText(&Group, State->GlyphAtlas, Font_Regular, V2(5, RenderCommands->RenderDim.y - 40), 15, Color_Grey, PushText(&Group, State->GlyphAtlas, Font_Regular, V2(5, RenderCommands->RenderDim.y - 40), 15, Color_Grey,
PushFormat(State->UI.FrameArena, "Active: %S:%llu", UI_BoxStringFromKey(UI_ActiveKey()), UI_ActiveKey())); PushFormat(State->UI.FrameArena, "Active: %S:%llu", UI_BoxStringFromKey(UI_ActiveKey()), UI_ActiveKey()));
} }
#endif
} }
} }

View File

@ -15,7 +15,7 @@ inline void AC_SetState(animation_curve_state *State)
static void AC_Init(animation_curve_state *State) static void AC_Init(animation_curve_state *State)
{ {
State->Arena = ArenaAllocate(Gigabytes(1)); State->Arena = ArenaAlloc(Kilobytes(32), true);
} }
inline animation_curve_key AC_GenerateKeyFromString(string String) inline animation_curve_key AC_GenerateKeyFromString(string String)

View File

@ -30,7 +30,7 @@ struct animation_curve_bucket
struct animation_curve_state struct animation_curve_state
{ {
memory_arena *Arena; arena *Arena;
u32 CurrentFrame; u32 CurrentFrame;
r32 dtForFrame; r32 dtForFrame;

View File

@ -1,109 +0,0 @@
#include "generated/vn_character.meta.c"
global character_registry *Global_CharacterRegistry = 0;
////////////////////////////////
//~ sixten: Character String Chunk Functions
static character_string_list CR_CharacterStringListAlloc(character_registry *Registry, string String)
{
character_string_list Result = {};
s64 ChunksNeeded = (String.Count + CHARACTER_STRING_CHUNK_DATA_SIZE - 1) / CHARACTER_STRING_CHUNK_DATA_SIZE;
s64 BytesLeft = String.Count;
u64 StringIndex = 0;
for(s64 ChunkIndex = 0; ChunkIndex < ChunksNeeded; ChunkIndex += 1)
{
character_string_chunk *Chunk = Registry->FirstFreeChunk;
if(Chunk)
{
Registry->FirstFreeChunk = Chunk->Next;
}
else
{
Chunk = PushStructNoClear(Registry->StringArena, character_string_chunk);
}
u64 ToCopy = Min(BytesLeft, CHARACTER_STRING_CHUNK_DATA_SIZE);
Copy(Chunk->Data, String.Data+StringIndex, ToCopy);
QueuePush(Result.First, Result.Last, Chunk);
Result.ChunkCount += 1;
Result.StringCount += ToCopy;
BytesLeft -= ToCopy;
StringIndex += ToCopy;
}
return(Result);
}
static character_string_list CR_CharacterStringListRelease(character_registry *Registry, character_string_list *List)
{
for(character_string_chunk *Chunk = List->First, *Next = 0; Chunk != 0; Chunk = Next)
{
Next = Chunk->Next;
Chunk->Next = Registry->FirstFreeChunk;
Registry->FirstFreeChunk = Chunk;
}
ZeroStruct(List);
}
static string CR_StringFromList(memory_arena *Arena, character_string_list *List)
{
string Result;
Result.Count = List->StringCount;
Result.Data = PushArrayNoClear(Arena, u8, Result.Count);
s64 StringIndex = 0;
s64 BytesLeft = List->StringCount;
for(character_string_chunk *Chunk = List->First; Chunk != 0; Chunk = Chunk->Next)
{
s64 ToCopy = Min(BytesLeft, CHARACTER_STRING_CHUNK_DATA_SIZE);
Copy(Result.Data+StringIndex, Chunk->Data, ToCopy);
StringIndex += ToCopy;
BytesLeft -= ToCopy;
}
return(Result);
}
////////////////////////////////
//~ sixten: Character Registry Functions
static void CR_SetState(character_registry *State)
{
Global_CharacterRegistry = State;
}
static character_registry *CR_GetState(void)
{
return(Global_CharacterRegistry);
}
static character_list CR_GetCharacters(void)
{
return(CR_GetState()->Characters);
}
static void CR_Init(character_registry *State)
{
CR_SetState(State);
State->Arena = ArenaAllocate(Megabytes(32));
}
static character_entry *CR_EntryFromName(string Name)
{
character_entry *Entry = 0;
character_registry *Registry = CR_GetState();
for(character_entry *Iter = Registry->Characters.First; Iter != 0; Iter = Iter->Next)
{
if(AreEqual(Name, Iter->Name))
{
Entry = Iter;
break;
}
}
if(!Entry)
{
Entry = PushStruct(Registry->Arena, character_entry);
Entry->Name = PushString(Registry->Arena, Name);
DLLInsertLast(Registry->Characters.First, Registry->Characters.Last, Entry);
}
return(Entry);
}

View File

@ -1,71 +0,0 @@
/* date = August 30th 2023 6:28 pm */
#ifndef VN_CHARACTER_H
#define VN_CHARACTER_H
#include "generated/vn_character.meta.h"
////////////////////////////////
//~ sixten: Character String Chunk Types
#define CHARACTER_STRING_CHUNK_DATA_SIZE (64 - sizeof(character_string_chunk *))
struct character_string_chunk
{
character_string_chunk *Next;
u8 Data[CHARACTER_STRING_CHUNK_DATA_SIZE];
};
CTAssert(sizeof(character_string_chunk) == 64);
struct character_string_list
{
character_string_chunk *First;
character_string_chunk *Last;
u64 ChunkCount;
s64 StringCount;
};
////////////////////////////////
//~ sixten: Character Registry Types
struct character_entry
{
character_entry *Next;
character_entry *Prev;
string Name;
};
struct character_list
{
character_entry *First;
character_entry *Last;
s64 Count;
};
struct character_registry
{
memory_arena *Arena;
character_list Characters;
memory_arena *StringArena;
character_string_chunk *FirstFreeChunk;
};
////////////////////////////////
//~ sixten: Character String Chunk Functions
static character_string_list CR_CharacterStringListAlloc(character_registry *Registry, string String);
static character_string_list CR_CharacterStringListRelease(character_registry *Registry, character_string_list *List);
static string CR_StringFromList(memory_arena *Arena, character_string_list *List);
////////////////////////////////
//~ sixten: Character Registry Functions
static void CR_SetState(character_registry *State);
static character_registry *CR_GetState(void);
static character_list CR_GetCharacters(void);
static void CR_Init(void);
static character_entry *CR_EntryFromName(string Name);
////////////////////////////////
//~ sixten: Misc. Character Functions
static character_state CR_CharacterStateFromString(string Input);
static string CR_StringFromCharacterState(character_state State);
#endif //VN_CHARACTER_H

View File

@ -3,6 +3,7 @@
{ "none", None }, { "none", None },
{ "normal", Normal }, { "normal", Normal },
{ "happy", Happy }, { "happy", Happy },
{ "leaning", Leaning },
} }
@table_gen @table_gen

View File

@ -1,6 +1,6 @@
static config *CreateConfig(void) static config *CreateConfig(void)
{ {
memory_arena *Arena = ArenaAllocate(Gigabytes(1)); arena *Arena = ArenaAlloc(Kilobytes(4), true);
config *Config = PushStruct(Arena, config); config *Config = PushStruct(Arena, config);
Config->Arena = Arena; Config->Arena = Arena;
return(Config); return(Config);
@ -74,7 +74,7 @@ inline void Config_BindB32(config *Config, string Name, b32 *Target, b32 Default
Config_BindEntry(Config, Name, Config_Entry_B32, Target); Config_BindEntry(Config, Name, Config_Entry_B32, Target);
} }
static void Config_ParseError(string Message, string FileText, s64 Offset, memory_arena *Arena) static void Config_ParseError(string Message, string FileText, s64 Offset, arena *Arena)
{ {
text_point Point = TextPointFromOffset(FileText, Offset); text_point Point = TextPointFromOffset(FileText, Offset);
string String = PushFormat(Arena, "Config: At %i:%i - %S", Point.Line, Point.Column, Message); string String = PushFormat(Arena, "Config: At %i:%i - %S", Point.Line, Point.Column, Message);
@ -211,7 +211,7 @@ static void Config_ReadFile(config *Config, string Path)
//////////////////////////////// ////////////////////////////////
//~ sixten: Config Parse Type Functions //~ sixten: Config Parse Type Functions
static void Config_ParseListPush(memory_arena *Arena, config_parse_list *List, string Name) static void Config_ParseListPush(arena *Arena, config_parse_list *List, string Name)
{ {
config_parse_node *Node = PushStruct(Arena, config_parse_node); config_parse_node *Node = PushStruct(Arena, config_parse_node);
Node->Name = Name; Node->Name = Name;
@ -229,7 +229,7 @@ static void Config_ParseListPop(config_parse_list *List)
} }
} }
static string Config_ParseListJoin(memory_arena *Arena, config_parse_list *List) static string Config_ParseListJoin(arena *Arena, config_parse_list *List)
{ {
s64 TotalCount = List->TotalCountPlusOne - 1; s64 TotalCount = List->TotalCountPlusOne - 1;
string Result = MakeString(PushArray(Arena, u8, List->TotalCountPlusOne), TotalCount); string Result = MakeString(PushArray(Arena, u8, List->TotalCountPlusOne), TotalCount);

View File

@ -32,7 +32,7 @@ struct config_entry_bucket
struct config struct config
{ {
memory_arena *Arena; arena *Arena;
config_entry_bucket EntryBuckets[32]; config_entry_bucket EntryBuckets[32];
// sixten(NOTE): Keeps track of the order in which the entries were declared. (Used during saving) // sixten(NOTE): Keeps track of the order in which the entries were declared. (Used during saving)
@ -81,8 +81,8 @@ static void Config_WriteFile(config *Config);
//////////////////////////////// ////////////////////////////////
//~ sixten: Config Parse Type Functions //~ sixten: Config Parse Type Functions
static void Config_ParseListPush(memory_arena *Arena, config_parse_list *List, string Name); static void Config_ParseListPush(arena *Arena, config_parse_list *List, string Name);
static void Config_ParseListPop(config_parse_list *List); static void Config_ParseListPop(config_parse_list *List);
static string Config_ParseListJoin(memory_arena *Arena, config_parse_list *List); static string Config_ParseListJoin(arena *Arena, config_parse_list *List);
#endif //VN_CONFIG_H #endif //VN_CONFIG_H

View File

@ -104,7 +104,7 @@ static glyph_atlas *CreateGlyphAtlas(vn_render_commands *RenderCommands,
s32 BitmapSize = DEFAULT_GLYPH_ATLAS_DIM, s32 BitmapSize = DEFAULT_GLYPH_ATLAS_DIM,
s32 GlyphSize = MAX_GLYPH_SIZE) s32 GlyphSize = MAX_GLYPH_SIZE)
{ {
memory_arena *Arena = ArenaAllocate(Megabytes(128)); arena *Arena = ArenaAlloc(Megabytes(1), true);
glyph_atlas *Atlas = PushStruct(Arena, glyph_atlas); glyph_atlas *Atlas = PushStruct(Arena, glyph_atlas);
Atlas->Arena = Arena; Atlas->Arena = Arena;
@ -117,14 +117,12 @@ static glyph_atlas *CreateGlyphAtlas(vn_render_commands *RenderCommands,
Atlas->RenderCommands = RenderCommands; Atlas->RenderCommands = RenderCommands;
Atlas->Texture = RenderCommands->AllocateTexture(V2S32(BitmapSize, BitmapSize), Render_TextureFormat_R8, false, 0); Atlas->Texture = RenderCommands->AllocateTexture(V2S32(BitmapSize, BitmapSize), Render_TextureFormat_R8, false, 0);
Atlas->Fonts[Font_Regular].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/Roboto-Regular.ttf")); Atlas->Fonts[Font_Regular].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("data/fonts/Roboto-Regular.ttf"));
Atlas->Fonts[Font_Bold].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/Roboto-Bold.ttf")); Atlas->Fonts[Font_Bold].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("data/fonts/Roboto-Bold.ttf"));
Atlas->Fonts[Font_Monospace].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/DejaVuSansMono.ttf")); Atlas->Fonts[Font_Monospace].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("data/fonts/DejaVuSansMono.ttf"));
Atlas->Fonts[Font_MonospaceOblique].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/DejaVuSansMono-Oblique.ttf")); Atlas->Fonts[Font_MonospaceOblique].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("data/fonts/DejaVuSansMono-Oblique.ttf"));
Atlas->Fonts[Font_Hand].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/PatrickHand-Regular.ttf")); Atlas->Fonts[Font_Fancy].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("data/fonts/Merriweather-Regular.ttf"));
Atlas->Fonts[Font_Fancy].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/Merriweather-Regular.ttf")); Atlas->Fonts[Font_Icons].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("data/fonts/icons.ttf"));
Atlas->Fonts[Font_Japanese].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/NotoSansJP-Regular.ttf"));
Atlas->Fonts[Font_Icons].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/icons.ttf"));
for(s32 FontIndex = 0; for(s32 FontIndex = 0;
FontIndex < Font_Count; FontIndex < Font_Count;

View File

@ -9,9 +9,7 @@ enum font_id
Font_Bold, Font_Bold,
Font_Monospace, Font_Monospace,
Font_MonospaceOblique, Font_MonospaceOblique,
Font_Hand,
Font_Fancy, Font_Fancy,
Font_Japanese,
Font_Icons, Font_Icons,
Font_Count, Font_Count,
@ -110,7 +108,7 @@ struct loaded_font
struct glyph_atlas struct glyph_atlas
{ {
memory_arena *Arena; arena *Arena;
s32 MaxGlyphCount; s32 MaxGlyphCount;
s32 GlyphsUsed; s32 GlyphsUsed;

View File

@ -50,7 +50,7 @@ inline b32 Platform_KeyRelease(platform_event_list *EventList, platform_key Key,
return(Result); return(Result);
} }
static string Platform_ReadEntireFile(memory_arena *Arena, string Path) static string Platform_ReadEntireFile(arena *Arena, string Path)
{ {
string Result = {}; string Result = {};

View File

@ -95,6 +95,8 @@ enum platform_key
Key_Backspace, Key_Delete, Key_Backspace, Key_Delete,
Key_Escape,
Key_MouseLeft, Key_MouseMiddle, Key_MouseRight, Key_MouseLeft, Key_MouseMiddle, Key_MouseRight,
}; };

View File

@ -4,6 +4,8 @@
{ Release release RELEASE `void` `void *Pointer` } { Release release RELEASE `void` `void *Pointer` }
{ Commit commit COMMIT `void` `void *Pointer, u64 Size` } { Commit commit COMMIT `void` `void *Pointer, u64 Size` }
{ Decommit decommit DECOMMIT `void` `void *Pointer, u64 Size` } { Decommit decommit DECOMMIT `void` `void *Pointer, u64 Size` }
{ Allocate allocate ALLOCATE `void *` `u64 Size` }
{ Deallocate deallocate DEALLOCATE `void` `void *Pointer` }
{ OpenFile open_file OPEN_FILE `platform_file_handle` `string Path, platform_access_flags FileAccess` } { OpenFile open_file OPEN_FILE `platform_file_handle` `string Path, platform_access_flags FileAccess` }
{ CloseFile close_file CLOSE_FILE `void` `platform_file_handle Handle` } { CloseFile close_file CLOSE_FILE `void` `platform_file_handle Handle` }
{ ReadFile read_file READ_FILE `void` `platform_file_handle Handle, void *Dest, u64 Offset, u64 Size` } { ReadFile read_file READ_FILE `void` `platform_file_handle Handle, void *Dest, u64 Offset, u64 Size` }
@ -12,11 +14,11 @@
{ SetCursor set_cursor SET_CURSOR `void` `platform_cursor Cursor` } { SetCursor set_cursor SET_CURSOR `void` `platform_cursor Cursor` }
{ ToggleFullscreen toggle_fullscreen TOGGLE_FULLSCREEN `void` `void` } { ToggleFullscreen toggle_fullscreen TOGGLE_FULLSCREEN `void` `void` }
{ ShowMessage show_message SHOW_MESSAGE `void` `string Message, platform_message_type Type` } { ShowMessage show_message SHOW_MESSAGE `void` `string Message, platform_message_type Type` }
{ BeginFileIter begin_file_iter BEGIN_FILE_ITER `platform_file_iter *` `memory_arena *Arena, string Path` } { BeginFileIter begin_file_iter BEGIN_FILE_ITER `platform_file_iter *` `arena *Arena, string Path` }
{ AdvanceFileIter advance_file_iter ADVANCE_FILE_ITER `b32` `memory_arena *Arena, platform_file_iter *Iter, platform_file_info *OutInfo` } { AdvanceFileIter advance_file_iter ADVANCE_FILE_ITER `b32` `arena *Arena, platform_file_iter *Iter, platform_file_info *OutInfo` }
{ EndFileIter end_file_iter END_FILE_ITER `void` `platform_file_iter *Iter` } { EndFileIter end_file_iter END_FILE_ITER `void` `platform_file_iter *Iter` }
{ SetClipboard set_clipboard SET_CLIPBOARD `void` `string String` } { SetClipboard set_clipboard SET_CLIPBOARD `void` `string String` }
{ GetClipboard get_clipboard GET_CLIPBOARD `string` `memory_arena *Arena` } { GetClipboard get_clipboard GET_CLIPBOARD `string` `arena *Arena` }
} }
@table_gen @table_gen

View File

@ -21,11 +21,11 @@ static void S_ParseError(scene_compiler *Compiler, char *Message, s64 TokenOffse
static void S_EmitByte(scene_compiler *Compiler, u8 Byte) static void S_EmitByte(scene_compiler *Compiler, u8 Byte)
{ {
scene_emission_target *Target = &Compiler->TargetStack[Compiler->TargetStackIndex]; scene_emission_target *Target = &Compiler->TargetStack[Compiler->TargetStackIndex];
scene_annotated_bytecode_bucket *Bucket = Target->Bucket; scene_bytecode_bucket *Bucket = Target->Bucket;
scene_annotated_bytecode_chunk *Chunk = Bucket->Last; scene_bytecode_chunk *Chunk = Bucket->Last;
if(!Chunk || Chunk->Count >= ArrayCount(Chunk->Data) || (Target->Type == S_EmissionTarget_Named && !AreEqual(Chunk->Name, Target->Name))) if(!Chunk || Chunk->Count >= ArrayCount(Chunk->Data) || (Target->Type == S_EmissionTarget_Named && !AreEqual(Chunk->Name, Target->Name)))
{ {
Chunk = PushStruct(Target->Arena, scene_annotated_bytecode_chunk); Chunk = PushStruct(Target->Arena, scene_bytecode_chunk);
Chunk->Name = Target->Name; Chunk->Name = Target->Name;
QueuePush(Bucket->First, Bucket->Last, Chunk); QueuePush(Bucket->First, Bucket->Last, Chunk);
@ -43,9 +43,9 @@ static void S_EmitU32(scene_compiler *Compiler, u32 Value)
S_EmitByte(Compiler, Value >> 24); S_EmitByte(Compiler, Value >> 24);
} }
static void S_EmitBucket(scene_compiler *Compiler, scene_annotated_bytecode_bucket *Bucket) static void S_EmitBucket(scene_compiler *Compiler, scene_bytecode_bucket *Bucket)
{ {
for(scene_annotated_bytecode_chunk *Chunk = Bucket->First; Chunk != 0; Chunk = Chunk->Next) for(scene_bytecode_chunk *Chunk = Bucket->First; Chunk != 0; Chunk = Chunk->Next)
{ {
for(s64 Index = 0; Index < Chunk->Count; Index += 1) for(s64 Index = 0; Index < Chunk->Count; Index += 1)
{ {
@ -91,12 +91,12 @@ static void S_PopEmissionTarget(scene_compiler *Compiler)
Compiler->TargetStackIndex -= 1; Compiler->TargetStackIndex -= 1;
} }
static scene_annotated_bytecode_chunk *S_FindBytecodeChunkByName(scene_compiler *Compiler, string Name) static scene_bytecode_chunk *S_FindBytecodeChunkByName(scene_compiler *Compiler, string Name)
{ {
scene_annotated_bytecode_chunk *Result = 0; scene_bytecode_chunk *Result = 0;
u64 Hash = HashString(Name); u64 Hash = HashString(Name);
scene_annotated_bytecode_bucket *Bucket = &Compiler->ProcBuckets[Hash%ArrayCount(Compiler->ProcBuckets)]; scene_bytecode_bucket *Bucket = &Compiler->ProcBuckets[Hash%ArrayCount(Compiler->ProcBuckets)];
for(scene_annotated_bytecode_chunk *Chunk = Bucket->First; Chunk != 0; Chunk = Chunk->Next) for(scene_bytecode_chunk *Chunk = Bucket->First; Chunk != 0; Chunk = Chunk->Next)
{ {
if(AreEqual(Chunk->Name, Name)) if(AreEqual(Chunk->Name, Name))
{ {
@ -194,7 +194,7 @@ static void S_ParseProcedure(scene_compiler *Compiler)
if(!Compiler->InPanicMode) if(!Compiler->InPanicMode)
{ {
string Name = T_StringFromToken(Compiler->Text, NameToken); string Name = T_StringFromToken(Compiler->Text, NameToken);
scene_annotated_bytecode_bucket *Bucket = &Compiler->ProcBuckets[HashString(Name)%ArrayCount(Compiler->ProcBuckets)]; scene_bytecode_bucket *Bucket = &Compiler->ProcBuckets[HashString(Name)%ArrayCount(Compiler->ProcBuckets)];
S_SetEmissionTarget(Compiler, S_NamedEmissionTarget(Compiler->Arena, Bucket, Name)); S_SetEmissionTarget(Compiler, S_NamedEmissionTarget(Compiler->Arena, Bucket, Name));
for(;Compiler->At < Compiler->TokensEnd;) for(;Compiler->At < Compiler->TokensEnd;)
@ -468,7 +468,7 @@ static void S_ParseBranchStatement(scene_compiler *Compiler)
ReleaseScratch(Scratch); ReleaseScratch(Scratch);
} }
static scene_branch_case *S_ParseBranchCase(scene_compiler *Compiler, memory_arena *Arena) static scene_branch_case *S_ParseBranchCase(scene_compiler *Compiler, arena *Arena)
{ {
scene_branch_case *Branch = PushStruct(Arena, scene_branch_case); scene_branch_case *Branch = PushStruct(Arena, scene_branch_case);
Branch->Name = S_ConsumeToken(Compiler, TokenKind_StringLiteral, "Expected branch label at start of branch case."); Branch->Name = S_ConsumeToken(Compiler, TokenKind_StringLiteral, "Expected branch label at start of branch case.");
@ -524,7 +524,7 @@ static void S_ParseNumber(scene_compiler *Compiler, b32 CanAssign)
static void S_ParseString(scene_compiler *Compiler, b32 CanAssign) static void S_ParseString(scene_compiler *Compiler, b32 CanAssign)
{ {
S_EmitConstant(Compiler, S_MakeSourceRef(Compiler->At[-1])); S_EmitConstant(Compiler, S_MakeSourceRef(Pad(Compiler->At[-1].Range, -1)));
} }
static void S_ParseGrouping(scene_compiler *Compiler, b32 CanAssign) static void S_ParseGrouping(scene_compiler *Compiler, b32 CanAssign)
@ -600,19 +600,19 @@ static void S_ParsePrecedence(scene_compiler *Compiler, scene_precedence Precede
struct proc_from_chunks_result struct proc_from_chunks_result
{ {
scene_proc *Proc; scene_proc *Proc;
scene_annotated_bytecode_chunk *NextChunk; scene_bytecode_chunk *NextChunk;
}; };
static proc_from_chunks_result S_ProcFromChunks(memory_arena *Arena, scene_annotated_bytecode_chunk *First) static proc_from_chunks_result S_ProcFromChunks(arena *Arena, scene_bytecode_chunk *First)
{ {
Assert(First != 0); Assert(First != 0);
string ChunkName = First->Name; string ChunkName = First->Name;
//- sixten: find required bytes //- sixten: find required bytes
s64 RequiredBytes = 0; s64 RequiredBytes = 0;
scene_annotated_bytecode_chunk *NextChunk = 0; scene_bytecode_chunk *NextChunk = 0;
{ {
scene_annotated_bytecode_chunk *Chunk = First; scene_bytecode_chunk *Chunk = First;
for(;Chunk != 0 && AreEqual(Chunk->Name, ChunkName); Chunk = Chunk->Next) for(;Chunk != 0 && AreEqual(Chunk->Name, ChunkName); Chunk = Chunk->Next)
{ {
RequiredBytes += Chunk->Count; RequiredBytes += Chunk->Count;
@ -627,7 +627,7 @@ static proc_from_chunks_result S_ProcFromChunks(memory_arena *Arena, scene_annot
//- sixten: copy over data from chunks //- sixten: copy over data from chunks
u8 *Dest = Proc->Data; u8 *Dest = Proc->Data;
for(scene_annotated_bytecode_chunk *Chunk = First; Chunk != NextChunk; Chunk = Chunk->Next) for(scene_bytecode_chunk *Chunk = First; Chunk != NextChunk; Chunk = Chunk->Next)
{ {
Copy(Dest, Chunk->Data, Chunk->Count); Copy(Dest, Chunk->Data, Chunk->Count);
Dest += Chunk->Count; Dest += Chunk->Count;
@ -642,7 +642,7 @@ static proc_from_chunks_result S_ProcFromChunks(memory_arena *Arena, scene_annot
return(Result); return(Result);
} }
static compiled_scene S_ScriptFromText(memory_arena *Arena, string Text) static compiled_scene S_ScriptFromText(arena *Arena, string Text)
{ {
compiled_scene Result = {}; compiled_scene Result = {};
@ -679,11 +679,18 @@ static compiled_scene S_ScriptFromText(memory_arena *Arena, string Text)
} }
} }
//- sixten: bake global scope
if(Compiler.GlobalScope.First)
{
proc_from_chunks_result ProcResult = S_ProcFromChunks(Arena, Compiler.GlobalScope.First);
Result.GlobalScope = ProcResult.Proc;
}
//- sixten: bake compiled chunks //- sixten: bake compiled chunks
for(s64 BucketIndex = 0; BucketIndex < ArrayCount(Compiler.ProcBuckets); BucketIndex += 1) for(s64 BucketIndex = 0; BucketIndex < ArrayCount(Compiler.ProcBuckets); BucketIndex += 1)
{ {
scene_annotated_bytecode_bucket *Bucket = &Compiler.ProcBuckets[BucketIndex]; scene_bytecode_bucket *Bucket = &Compiler.ProcBuckets[BucketIndex];
for(scene_annotated_bytecode_chunk *Chunk = Bucket->First; Chunk != 0;) for(scene_bytecode_chunk *Chunk = Bucket->First; Chunk != 0;)
{ {
proc_from_chunks_result ProcResult = S_ProcFromChunks(Arena, Chunk); proc_from_chunks_result ProcResult = S_ProcFromChunks(Arena, Chunk);
s64 Hash = HashString(Chunk->Name); s64 Hash = HashString(Chunk->Name);
@ -725,12 +732,22 @@ static compiled_scene S_ScriptFromText(memory_arena *Arena, string Text)
return(Result); return(Result);
} }
static compiled_scene S_CopyCompiledScene(memory_arena *Arena, compiled_scene *Compiled) static compiled_scene S_CopyCompiledScene(arena *Arena, compiled_scene *Compiled)
{ {
compiled_scene Result = {}; compiled_scene Result = {};
Assert(Compiled->Errors.Count == 0); Assert(Compiled->Errors.Count == 0);
//- sixten: copy the global scope
if(Compiled->GlobalScope)
{
Result.GlobalScope = PushStruct(Arena, scene_proc);
Result.GlobalScope->Name = PushString(Arena, Compiled->GlobalScope->Name);
Result.GlobalScope->Data = PushArray(Arena, u8, Compiled->GlobalScope->Count);
Copy(Result.GlobalScope->Data, Compiled->GlobalScope->Data, Compiled->GlobalScope->Count);
Result.GlobalScope->Count = Compiled->GlobalScope->Count;
}
//- sixten: copy the procs //- sixten: copy the procs
for(s64 BucketIndex = 0; BucketIndex < ArrayCount(Compiled->Buckets); BucketIndex += 1) for(s64 BucketIndex = 0; BucketIndex < ArrayCount(Compiled->Buckets); BucketIndex += 1)
{ {
@ -766,7 +783,8 @@ static void S_RuntimeError(scene_runtime *Runtime, string Message)
{ {
scene_runtime_error *Error = PushStruct(Runtime->ErrorArena, scene_runtime_error); scene_runtime_error *Error = PushStruct(Runtime->ErrorArena, scene_runtime_error);
Error->Message = PushString(Runtime->ErrorArena, Message); Error->Message = PushString(Runtime->ErrorArena, Message);
DLLInsertLast(Runtime->FirstError, Runtime->LastError, Error); DLLInsertLast(Runtime->Errors.First, Runtime->Errors.Last, Error);
Runtime->Errors.Count += 1;
} }
static void S_RuntimeErrorF(scene_runtime *Runtime, char *Format, ...) static void S_RuntimeErrorF(scene_runtime *Runtime, char *Format, ...)
@ -776,11 +794,53 @@ static void S_RuntimeErrorF(scene_runtime *Runtime, char *Format, ...)
scene_runtime_error *Error = PushStruct(Runtime->ErrorArena, scene_runtime_error); scene_runtime_error *Error = PushStruct(Runtime->ErrorArena, scene_runtime_error);
Error->Message = PushFormatVariadic(Runtime->ErrorArena, Format, Arguments); Error->Message = PushFormatVariadic(Runtime->ErrorArena, Format, Arguments);
DLLInsertLast(Runtime->FirstError, Runtime->LastError, Error); DLLInsertLast(Runtime->Errors.First, Runtime->Errors.Last, Error);
Runtime->Errors.Count += 1;
va_end(Arguments); va_end(Arguments);
} }
static scene_named_value *S_FindGlobalVariableByName(scene_runtime *Runtime, string Name, b32 AlwaysCreate)
{
scene_named_value *Result = 0;
u64 Hash = HashString(Name);
scene_named_value_bucket *Bucket = &Runtime->GlobalVariableBuckets[Hash%ArrayCount(Runtime->GlobalVariableBuckets)];
//- sixten: search for the value in the bucket
for(scene_named_value_node *Node = Bucket->First; Node != 0; Node = Node->Next)
{
scene_named_value *Value = &Node->NamedValue;
if(AreEqual(Name, Value->Name))
{
Result = Value;
break;
}
}
//- sixten: create it if it doesn't exist
if(Result == 0)
{
//- sixten: check the free list first
scene_named_value_bucket *FreeList = &Runtime->GlobalVariableFreeList;
scene_named_value_node *Node = FreeList->First;
if(Node)
{
DLLRemove(FreeList->First, FreeList->Last, Node);
}
else
{
Node = PushStruct(Runtime->RuntimeArena, scene_named_value_node);
}
DLLInsertLast(Bucket->First, Bucket->Last, Node);
Result = &Node->NamedValue;
Result->Name = Name;
}
return(Result);
}
static scene_proc *S_FindProcByName(compiled_scene *Compiled, string Name) static scene_proc *S_FindProcByName(compiled_scene *Compiled, string Name)
{ {
scene_proc *Result = 0; scene_proc *Result = 0;
@ -843,6 +903,10 @@ static void S_ResetRuntime(scene_runtime *Runtime)
Runtime->IP = 0; Runtime->IP = 0;
Runtime->CurrentProc = 0; Runtime->CurrentProc = 0;
Runtime->BranchCount = 0; Runtime->BranchCount = 0;
Fill(Runtime->GlobalVariableBuckets, 0, sizeof(Runtime->GlobalVariableBuckets));
ZeroStruct(&Runtime->GlobalVariableFreeList);
ZeroStruct(&Runtime->Errors);
if(Runtime->RuntimeArena) if(Runtime->RuntimeArena)
{ {
@ -850,11 +914,11 @@ static void S_ResetRuntime(scene_runtime *Runtime)
} }
else else
{ {
Runtime->RuntimeArena = ArenaAllocate(Megabytes(32)); Runtime->RuntimeArena = ArenaAlloc(Kilobytes(16));
} }
} }
static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameArena, b32 AdvanceOnAwait) static scene_runtime_result S_Run(scene_runtime *Runtime, arena *FrameArena, b32 AdvanceOnAwait)
{ {
scene_runtime_result Result = {}; scene_runtime_result Result = {};
compiled_scene *Compiled = &Runtime->Compiled; compiled_scene *Compiled = &Runtime->Compiled;
@ -862,12 +926,6 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
Assert(Runtime != 0); Assert(Runtime != 0);
Assert(Compiled->IsValid); Assert(Compiled->IsValid);
//- sixten: default to the main proc
if(Runtime->CurrentProc == 0)
{
Runtime->CurrentProc = S_FindProcByName(Compiled, StrLit("main"));
}
// sixten(NOTE): This will only work on little endian architectures. // sixten(NOTE): This will only work on little endian architectures.
#define S_ReadU32() (Runtime->IP += 4, *(u32 *)(Data+Runtime->IP-4)) #define S_ReadU32() (Runtime->IP += 4, *(u32 *)(Data+Runtime->IP-4))
#define S_ReadValue() Compiled->Values[S_ReadU32()] #define S_ReadValue() Compiled->Values[S_ReadU32()]
@ -951,6 +1009,32 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
S_RuntimeError(Runtime, StrLit("This operation is not supported.")); S_RuntimeError(Runtime, StrLit("This operation is not supported."));
} break; } break;
case S_Op_DefineGlobal:
{
Runtime->IP += 1;
scene_value Value = Runtime->Compiled.Values[S_ReadU32()];
if(Value.Kind == S_ValueKind_SourceRef)
{
string Name = Substring(Runtime->Compiled.Source, Value.SourceRef);
scene_named_value *NamedValue = S_FindGlobalVariableByName(Runtime, Name);
if(!NamedValue->Initialized)
{
NamedValue->Initialized = true;
scene_value TargetValue = S_PopStackAndImplicitConvert(Runtime);
NamedValue->Value = TargetValue;
}
else
{
S_RuntimeErrorF(Runtime, "Global %S is already defined.", Name);
}
}
else
{
S_RuntimeError(Runtime, StrLit("Incorrect value kind when retrieving global name."));
}
} break;
case S_Op_Jump: case S_Op_Jump:
{ {
Runtime->IP += 1; Runtime->IP += 1;
@ -999,7 +1083,7 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
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, Pad(BranchName.SourceRef, -1)); Branch->Name = Substring(Compiled->Source, BranchName.SourceRef);
Branch->Offset = Offset.Offset; Branch->Offset = Offset.Offset;
Runtime->BranchCount += 1; Runtime->BranchCount += 1;
} }
@ -1027,8 +1111,8 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
case S_Op_ClearDialog: case S_Op_ClearDialog:
{ {
textbox_action *Action = PushStructNoClear(FrameArena, textbox_action); scene_textbox_action *Action = PushStructNoClear(FrameArena, scene_textbox_action);
Action->Kind = TextboxActionKind_Set; Action->Kind = S_TextboxActionKind_Set;
Action->String = StrLit(""); Action->String = StrLit("");
QueuePush(Runtime->FirstTextboxAction, Runtime->LastTextboxAction, Action); QueuePush(Runtime->FirstTextboxAction, Runtime->LastTextboxAction, Action);
@ -1069,15 +1153,15 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
case S_Op_LineEntry: case S_Op_LineEntry:
{ {
textbox_action *Action = PushStructNoClear(FrameArena, textbox_action); scene_textbox_action *Action = PushStructNoClear(FrameArena, scene_textbox_action);
Action->Kind = TextboxActionKind_Append; Action->Kind = S_TextboxActionKind_Append;
Runtime->IP += 1; Runtime->IP += 1;
scene_value Value = S_PopStack(Runtime); scene_value Value = S_PopStack(Runtime);
if(Value.Kind == S_ValueKind_SourceRef) if(Value.Kind == S_ValueKind_SourceRef)
{ {
Action->String = Substring(Compiled->Source, Pad(Value.SourceRef, -1)); Action->String = Substring(Compiled->Source, Value.SourceRef);
QueuePush(Runtime->FirstTextboxAction, Runtime->LastTextboxAction, Action); QueuePush(Runtime->FirstTextboxAction, Runtime->LastTextboxAction, Action);
} }
else else
@ -1095,7 +1179,8 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
} }
else else
{ {
S_RuntimeErrorF(Runtime, "Reached end of proc."); Result.ReachedAwait = true;
Runtime->CurrentProc = 0;
} }
} }
else else
@ -1103,7 +1188,7 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
S_RuntimeErrorF(Runtime, "No main entry was found"); S_RuntimeErrorF(Runtime, "No main entry was found");
} }
Result.HadError = !DLLIsEmpty(Runtime->FirstError); Result.HadError = !DLLIsEmpty(Runtime->Errors.First);
Runtime->LastResult = Result; Runtime->LastResult = Result;
return(Result); return(Result);

View File

@ -67,22 +67,15 @@ enum scene_opcode
struct scene_bytecode_chunk struct scene_bytecode_chunk
{ {
scene_bytecode_chunk *Next; scene_bytecode_chunk *Next;
s64 Count;
u8 Data[4096];
};
struct scene_annotated_bytecode_chunk
{
scene_annotated_bytecode_chunk *Next;
string Name; string Name;
s64 Count; s64 Count;
u8 Data[4096]; u8 Data[4096];
}; };
struct scene_annotated_bytecode_bucket struct scene_bytecode_bucket
{ {
scene_annotated_bytecode_chunk *First; scene_bytecode_chunk *First;
scene_annotated_bytecode_chunk *Last; scene_bytecode_chunk *Last;
s64 Count; s64 Count;
}; };
@ -150,8 +143,8 @@ enum scene_emission_target_type
struct scene_emission_target struct scene_emission_target
{ {
memory_arena *Arena; arena *Arena;
scene_annotated_bytecode_bucket *Bucket; scene_bytecode_bucket *Bucket;
scene_emission_target_type Type; scene_emission_target_type Type;
string Name; string Name;
}; };
@ -160,7 +153,7 @@ struct scene_branch_case
{ {
scene_branch_case *Next; scene_branch_case *Next;
token Name; token Name;
scene_annotated_bytecode_bucket Bucket; scene_bytecode_bucket Bucket;
scene_value *OffsetValue; scene_value *OffsetValue;
scene_value *EndOffsetValue; scene_value *EndOffsetValue;
}; };
@ -176,7 +169,7 @@ struct scene_character_action
struct scene_compiler struct scene_compiler
{ {
memory_arena *Arena; arena *Arena;
b32 InPanicMode; b32 InPanicMode;
b32 EncounteredError; b32 EncounteredError;
@ -187,8 +180,8 @@ struct scene_compiler
token *TokensEnd; token *TokensEnd;
token *At; token *At;
scene_annotated_bytecode_bucket GlobalScope; scene_bytecode_bucket GlobalScope;
scene_annotated_bytecode_bucket ProcBuckets[32]; scene_bytecode_bucket ProcBuckets[32];
scene_emission_target TargetStack[16]; scene_emission_target TargetStack[16];
s32 TargetStackIndex; s32 TargetStackIndex;
@ -219,6 +212,7 @@ struct scene_proc_bucket
struct compiled_scene struct compiled_scene
{ {
scene_proc *GlobalScope;
scene_proc_bucket Buckets[16]; scene_proc_bucket Buckets[16];
scene_value *Values; scene_value *Values;
s64 ValueCount; s64 ValueCount;
@ -236,22 +230,50 @@ struct scene_runtime_error
string Message; string Message;
}; };
struct scene_runtime_error_list
{
scene_runtime_error *First;
scene_runtime_error *Last;
s64 Count;
};
struct scene_named_value
{
b32 Initialized;
string Name;
scene_value Value;
};
struct scene_named_value_node
{
scene_named_value_node *Next;
scene_named_value_node *Prev;
scene_named_value NamedValue;
};
struct scene_named_value_bucket
{
s64 Count;
scene_named_value_node *First;
scene_named_value_node *Last;
};
struct scene_runtime_result struct scene_runtime_result
{ {
b32 HadError; b32 HadError;
b32 ReachedAwait; b32 ReachedAwait;
}; };
enum textbox_action_kind enum scene_textbox_action_kind
{ {
TextboxActionKind_Set, S_TextboxActionKind_Set,
TextboxActionKind_Append, S_TextboxActionKind_Append,
}; };
struct textbox_action struct scene_textbox_action
{ {
textbox_action *Next; scene_textbox_action *Next;
textbox_action_kind Kind; scene_textbox_action_kind Kind;
string String; string String;
}; };
@ -272,27 +294,27 @@ struct scene_runtime
compiled_scene Compiled; compiled_scene Compiled;
// sixten: runtime state // sixten: runtime state
memory_arena *RuntimeArena; arena *RuntimeArena;
scene_proc *CurrentProc; scene_proc *CurrentProc;
s64 IP; s64 IP;
scene_runtime_stack Stack; scene_runtime_stack Stack;
scene_named_value_bucket GlobalVariableBuckets[16];
scene_named_value_bucket GlobalVariableFreeList;
// sixten: errors // sixten: errors
memory_arena *ErrorArena; arena *ErrorArena;
scene_runtime_error *FirstError; scene_runtime_error_list Errors;
scene_runtime_error *LastError;
// sixten: branches // sixten: branches
branch_case Branches[16]; branch_case Branches[16];
s64 BranchCount; s64 BranchCount;
// sixten: result // sixten: result
textbox_action *FirstTextboxAction; scene_runtime_result LastResult;
textbox_action *LastTextboxAction; scene_textbox_action *FirstTextboxAction;
scene_textbox_action *LastTextboxAction;
scene_character_action *FirstCharacterAction; scene_character_action *FirstCharacterAction;
scene_character_action *LastCharacterAction; scene_character_action *LastCharacterAction;
branch_case *FirstBranchCase;
scene_runtime_result LastResult;
}; };
//////////////////////////////// ////////////////////////////////
@ -338,6 +360,14 @@ inline scene_value S_MakeSourceRef(token Token)
return(Result); return(Result);
} }
inline scene_value S_MakeSourceRef(range1_s64 Range)
{
scene_value Result;
Result.Kind = S_ValueKind_SourceRef;
Result.SourceRef = Range;
return(Result);
}
inline scene_value S_MakeOffset(s64 Offset) inline scene_value S_MakeOffset(s64 Offset)
{ {
scene_value Result; scene_value Result;
@ -352,15 +382,15 @@ static void S_ParseError(scene_compiler *Compiler, char *Message, s64 TokenOffse
//- sixten: bytecode helpers //- sixten: bytecode helpers
static void S_EmitByte(scene_compiler *Compiler, u8 Byte); static void S_EmitByte(scene_compiler *Compiler, u8 Byte);
static void S_EmitU32(scene_compiler *Compiler, u32 Value); static void S_EmitU32(scene_compiler *Compiler, u32 Value);
static void S_EmitBucket(scene_compiler *Compiler, scene_annotated_bytecode_bucket *Bucket); static void S_EmitBucket(scene_compiler *Compiler, scene_bytecode_bucket *Bucket);
static u64 S_MakeConstant(scene_compiler *Compiler, scene_value Value); static u64 S_MakeConstant(scene_compiler *Compiler, scene_value Value);
static void S_EmitConstant(scene_compiler *Compiler, scene_value Value); static void S_EmitConstant(scene_compiler *Compiler, scene_value Value);
static void S_SetEmissionTarget(scene_compiler *Compiler, scene_emission_target Target); static void S_SetEmissionTarget(scene_compiler *Compiler, scene_emission_target Target);
static void S_PushEmissionTarget(scene_compiler *Compiler, scene_emission_target Target); static void S_PushEmissionTarget(scene_compiler *Compiler, scene_emission_target Target);
static void S_PopEmissionTarget(scene_compiler *Compiler); static void S_PopEmissionTarget(scene_compiler *Compiler);
static scene_annotated_bytecode_chunk *S_FindBytecodeChunkByName(scene_compiler *Compiler, string Name); static scene_bytecode_chunk *S_FindBytecodeChunkByName(scene_compiler *Compiler, string Name);
inline scene_emission_target S_RawEmissionTarget(memory_arena *Arena, scene_annotated_bytecode_bucket *Bucket) inline scene_emission_target S_RawEmissionTarget(arena *Arena, scene_bytecode_bucket *Bucket)
{ {
scene_emission_target Target = {}; scene_emission_target Target = {};
Target.Arena = Arena; Target.Arena = Arena;
@ -369,7 +399,7 @@ inline scene_emission_target S_RawEmissionTarget(memory_arena *Arena, scene_anno
return(Target); return(Target);
} }
inline scene_emission_target S_NamedEmissionTarget(memory_arena *Arena, scene_annotated_bytecode_bucket *Bucket, string Name) inline scene_emission_target S_NamedEmissionTarget(arena *Arena, scene_bytecode_bucket *Bucket, string Name)
{ {
scene_emission_target Target = {}; scene_emission_target Target = {};
Target.Arena = Arena; Target.Arena = Arena;
@ -395,7 +425,7 @@ static void S_ParseNamedVariable(scene_compiler *Compiler, token Token, b32 CanA
static void S_ParseLineEntry(scene_compiler *Compiler); static void S_ParseLineEntry(scene_compiler *Compiler);
static void S_ParseJumpStatement(scene_compiler *Compiler); static void S_ParseJumpStatement(scene_compiler *Compiler);
static void S_ParseBranchStatement(scene_compiler *Compiler); static void S_ParseBranchStatement(scene_compiler *Compiler);
static scene_branch_case *S_ParseBranchCase(scene_compiler *Compiler, memory_arena *Arena); static scene_branch_case *S_ParseBranchCase(scene_compiler *Compiler, arena *Arena);
static void S_ParseStatement(scene_compiler *Compiler); static void S_ParseStatement(scene_compiler *Compiler);
static void S_ParseExpression(scene_compiler *Compiler); static void S_ParseExpression(scene_compiler *Compiler);
static void S_ParseLiteral(scene_compiler *Compiler, b32 CanAssign); static void S_ParseLiteral(scene_compiler *Compiler, b32 CanAssign);
@ -407,16 +437,17 @@ static void S_ParseBinary(scene_compiler *Compiler, b32 CanAssign);
static void S_ParsePrecedence(scene_compiler *Compiler, scene_precedence Precedence); static void S_ParsePrecedence(scene_compiler *Compiler, scene_precedence Precedence);
//- sixten: debugging //- sixten: debugging
static string S_DisassembleBytecode(scene_compiler *Compiler, scene_annotated_bytecode_chunk *Chunk, memory_arena *Arena); static string S_DisassembleBytecode(scene_compiler *Compiler, scene_bytecode_chunk *Chunk, arena *Arena);
//- sixten: compilation //- sixten: compilation
static compiled_scene S_ScriptFromText(memory_arena *Arena, string Text); static compiled_scene S_ScriptFromText(arena *Arena, string Text);
static compiled_scene S_CopyCompiledScene(memory_arena *Arena, compiled_scene *Compiled); static compiled_scene S_CopyCompiledScene(arena *Arena, compiled_scene *Compiled);
//////////////////////////////// ////////////////////////////////
//~ sixten: Scene Runtime Functions //~ sixten: Scene Runtime Functions
static scene_proc *S_FindProcByName(compiled_scene *Compiled, string Name); static scene_proc *S_FindProcByName(compiled_scene *Compiled, string Name);
static scene_named_value *S_FindGlobalVariableByName(scene_runtime *Runtime, string Name, b32 AlwaysCreate = true);
static void S_ResetRuntime(scene_runtime *Runtime); static void S_ResetRuntime(scene_runtime *Runtime);
static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameArena, b32 AdvanceOnAwait); static scene_runtime_result S_Run(scene_runtime *Runtime, arena *FrameArena, b32 AdvanceOnAwait);
#endif //VN_SCENE_H #endif //VN_SCENE_H

View File

@ -1,4 +1,4 @@
thread_local scene_view *ThreadLocal_SceneView = 0; per_thread scene_view *ThreadLocal_SceneView = 0;
static void SV_SetState(scene_view *View) static void SV_SetState(scene_view *View)
{ {
@ -17,29 +17,73 @@ static void SV_NewFrame(scene_view *View, platform_event_list *EventList, r32 dt
View->dtForFrame = dtForFrame; View->dtForFrame = dtForFrame;
} }
static void SV_SetCurrentSource(compiled_scene *Compiled) static void SV_Reset(void)
{ {
scene_view *SceneView = SV_GetState(); scene_view *SceneView = SV_GetState();
// sixten(TODO): extract runtime information required to seamlessly transition between compilations ArenaClear(SceneView->Runtime.ErrorArena);
ArenaClear(SceneView->SceneArena);
SceneView->Runtime.Compiled = S_CopyCompiledScene(SceneView->SceneArena, Compiled);
S_ResetRuntime(&SceneView->Runtime); S_ResetRuntime(&SceneView->Runtime);
// sixten: reset textbox
SceneView->Textbox.String.Count = 0;
// sixten: reset last talking character
SceneView->LastTalkingCharacter.Count = 0;
SceneView->CharacterIsTalking = false;
SceneView->OnscreenCharacterCount = 0;
} }
static void SV_Init(scene_view *SceneView, memory_arena *TextboxArena) static void SV_SetCurrentSource(compiled_scene *Compiled)
{
scene_view *SceneView = SV_GetState();
scene_runtime *Runtime = &SceneView->Runtime;
// sixten(TODO): extract runtime information required to seamlessly transition between compilations
SV_Reset();
ArenaClear(SceneView->SceneArena);
Runtime->Compiled = S_CopyCompiledScene(SceneView->SceneArena, Compiled);
//- sixten: run top level
Runtime->CurrentProc = Runtime->Compiled.GlobalScope;
if(Runtime->CurrentProc)
{
temporary_memory Scratch = GetScratch(0, 0);
for(;;)
{
scene_runtime_result RunResult = S_Run(Runtime, Scratch.Arena, false);
if(RunResult.ReachedAwait || RunResult.HadError)
{
break;
}
}
ReleaseScratch(Scratch);
}
//- sixten: find main proc
Runtime->CurrentProc = S_FindProcByName(&Runtime->Compiled, StrLit("main"));
Runtime->IP = 0;
}
static void SV_Init(scene_view *SceneView, arena *TextboxArena)
{ {
SV_SetState(SceneView); SV_SetState(SceneView);
SceneView->SceneArena = ArenaAllocate(Gigabytes(1)); SceneView->SceneArena = ArenaAlloc(Kilobytes(16), true);
SceneView->Runtime.ErrorArena = ArenaAllocate(Megabytes(1)); SceneView->Runtime.ErrorArena = ArenaAlloc(Kilobytes(4), true);
S_ResetRuntime(&SceneView->Runtime);
SceneView->Textbox.Capacity = 4096; SceneView->Textbox.Capacity = 4096;
SceneView->Textbox.String.Data = PushArray(TextboxArena, u8, SceneView->Textbox.Capacity); SceneView->Textbox.String.Data = PushArray(TextboxArena, u8, SceneView->Textbox.Capacity);
SceneView->Textbox.String.Count = 0;
SV_Reset();
}
static b32 SV_CurrentlyInProc(void)
{
scene_view *SceneView = SV_GetState();
b32 Result = (SceneView->Runtime.CurrentProc != 0);
return(Result);
} }
struct text_properties struct text_properties
@ -52,6 +96,7 @@ struct text_properties
static void RenderAnimatedText(render_group *Group, glyph_atlas *Atlas, text_properties Properties, string Text, r32 CharsToRender, v2_r32 P, r32 WrapWidth) static void RenderAnimatedText(render_group *Group, glyph_atlas *Atlas, text_properties Properties, string Text, r32 CharsToRender, v2_r32 P, r32 WrapWidth)
{ {
v2_r32 Offset = V2R32(0, 0); v2_r32 Offset = V2R32(0, 0);
v2_r32 ShadowOffset = V2R32(Properties.FontSize*0.1, Properties.FontSize*0.1);
u8 *TextBegin = Text.Data; u8 *TextBegin = Text.Data;
u8 *TextEnd = TextBegin+Text.Count; u8 *TextEnd = TextBegin+Text.Count;
@ -84,6 +129,7 @@ static void RenderAnimatedText(render_group *Group, glyph_atlas *Atlas, text_pro
Offset.y += Properties.LineHeight; Offset.y += Properties.LineHeight;
} }
PushText(Group, Atlas, Properties.Font, P+Offset+ShadowOffset, Properties.FontSize, Color_Black, Word);
Offset.x += PushText(Group, Atlas, Properties.Font, P+Offset, Properties.FontSize, Color_White, Word); Offset.x += PushText(Group, Atlas, Properties.Font, P+Offset, Properties.FontSize, Color_White, Word);
if(WordEnd != TrueWordEnd) if(WordEnd != TrueWordEnd)
@ -129,6 +175,8 @@ struct scene_textbox_data
{ {
textbox *Textbox; textbox *Textbox;
ui_box *SceneViewBox; ui_box *SceneViewBox;
string Name;
r32 NameT;
}; };
UI_CUSTOM_DRAW_CALLBACK(BuildSceneTextboxDrawCallback) UI_CUSTOM_DRAW_CALLBACK(BuildSceneTextboxDrawCallback)
@ -136,23 +184,38 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneTextboxDrawCallback)
scene_textbox_data *TextboxData = (scene_textbox_data *)Data; scene_textbox_data *TextboxData = (scene_textbox_data *)Data;
textbox *Textbox = TextboxData->Textbox; textbox *Textbox = TextboxData->Textbox;
r32 GlobalScale = CalculateGlobalScaleFromRootBox(TextboxData->SceneViewBox);
//- sixten: render textbox //- sixten: render textbox
v4 TopColor = V4(0, 0, 0, 0.8f); {
v4 BottomColor = V4(0, 0, 0, 0.5f); v4 TopColor = V4(0, 0, 0, 0.8f);
range2_r32 Dest = Range2R32(Box->Rect.Min, Box->Rect.Max); v4 BottomColor = V4(0, 0, 0, 0.5f);
PushQuad(Group, Dest, TopColor, TopColor, BottomColor, BottomColor, 0, 0, 0); range2_r32 Dest = Pad(Range2R32(Box->Rect.Min, Box->Rect.Max), V2(GlobalScale, GlobalScale)*2.0f);
PushQuad(Group, Dest, TopColor, TopColor, BottomColor, BottomColor, 0, GlobalScale, 0);
}
//- sixten: render text //- sixten: render text
string Text = Textbox->String; {
r32 CharsRevealed = Textbox->CharsRevealed; string Text = Textbox->String;
r32 GlobalScale = CalculateGlobalScaleFromRootBox(TextboxData->SceneViewBox); r32 CharsRevealedT = Textbox->CharsRevealedT;
text_properties Properties = {}; text_properties Properties = {};
Properties.Font = Font_Fancy; Properties.Font = Font_Fancy;
Properties.FontSize = GlobalScale; Properties.FontSize = GlobalScale;
Properties.LineHeight = GlobalScale*1.5f; Properties.LineHeight = GlobalScale*1.5f;
r32 Padding = 1.5f*GlobalScale; r32 Padding = 1.5f*GlobalScale;
v2 Offset = V2R32(Padding, Padding); v2 Offset = V2R32(Padding, Padding);
RenderAnimatedText(Group, Atlas, Properties, Text, CharsRevealed, Box->Rect.Min+Offset, DimOfRange(Box->Rect).x-2*Padding); RenderAnimatedText(Group, Atlas, Properties, Text, CharsRevealedT, Box->Rect.Min+Offset, DimOfRange(Box->Rect).x-2*Padding);
}
//- sixten: render character name
{
string Name = TextboxData->Name;
r32 T = TextboxData->NameT;
v2 TextP = Box->Rect.Min + V2(1.5f*GlobalScale, -GlobalScale*T);
PushText(Group, Atlas, Font_Fancy, TextP+V2(GlobalScale*0.1, GlobalScale*0.1), GlobalScale, SetAlpha(Color_Black, T), Name);
PushText(Group, Atlas, Font_Fancy, TextP, GlobalScale, SetAlpha(Color_White, T), Name);
}
} }
UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback) UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback)
@ -165,22 +228,32 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback)
//- 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
// on the render group. // on the render group.
#if 0
persist r32 Time = 0;
Time += 1 / 1200.0f;
r32 r = 30;
v2_r32 Offset = V2(Sin(Time)+0.5*Sin(43+2.43*Time)+Sin(424+Time*16)*0.1, Sin(8+Time)+0.5*Sin(43+2.43*Time)+Sin(4242+Time*16)*0.1)*(1.0f/1.6f)*r;
range2_r32 BackgroundDest = Range2R32(Box->Rect.Min-V2(r, r)+Offset, RenderDim+Box->Rect.Min+V2(r, r)+Offset);
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(SceneView->BackgroundTexture)));
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, SceneView->BackgroundTexture);
#else
range2_r32 BackgroundDest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min); range2_r32 BackgroundDest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min);
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(SceneView->BackgroundTexture))); range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(SceneView->BackgroundTexture)));
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
//- sixten: render characters //- sixten: render characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1) for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1)
{ {
scene_view_character_data *Character = SceneView->OnscreenCharacters + CharacterIndex; scene_view_character_data *Character = SceneView->OnscreenCharacters + CharacterIndex;
v4_r32 BlendColor = LinearBlend(Color_White, Color_Black, 0.5-Character->TalkingT*0.5); v4_r32 BlendColor = LinearBlend(Color_White, Color_Black, 0.5-Character->TalkingT*0.5);
BlendColor.a = Character->ActiveT; BlendColor.a = Character->ActiveT;
r32 Scale = (Character->TextureScale + Character->TalkingT*0.001)*(0.95+Character->ActiveT*0.05)*GlobalScale; r32 Scale = (Character->Info.Scale + Character->TalkingT*0.001)*(0.95+Character->ActiveT*0.05)*GlobalScale;
render_handle CharacterHandle = Character->Texture; render_handle CharacterHandle = Character->Info.Texture;
v2_r32 CharacterDim = ConvertV2ToR32(DimFromTexture(CharacterHandle)); v2_r32 CharacterDim = ConvertV2ToR32(DimFromTexture(CharacterHandle));
v2_r32 CharacterOriginP = V2R32(RenderDim.x*Character->PctP, RenderDim.y); v2_r32 CharacterOriginP = V2R32(RenderDim.x*Character->PctP, RenderDim.y);
v2_r32 CharacterMidP = V2R32(CharacterOriginP.x, CharacterOriginP.y - CharacterDim.y*Scale/2); v2_r32 CharacterMidP = Box->Rect.Min+V2R32(CharacterOriginP.x, CharacterOriginP.y - CharacterDim.y*Scale/2);
range2_r32 CharacterDest = Range2R32(CharacterMidP-CharacterDim*0.5f*Scale, CharacterMidP+CharacterDim*0.5f*Scale); range2_r32 CharacterDest = Range2R32(CharacterMidP-CharacterDim*0.5f*Scale, CharacterMidP+CharacterDim*0.5f*Scale);
range2_r32 CharacterSource = Range2R32(V2R32(0, 0), CharacterDim); range2_r32 CharacterSource = Range2R32(V2R32(0, 0), CharacterDim);
PushTexturedQuad(Group, CharacterDest, CharacterSource, BlendColor, BlendColor, BlendColor, BlendColor, 0, 0, 0, CharacterHandle); PushTexturedQuad(Group, CharacterDest, CharacterSource, BlendColor, BlendColor, BlendColor, BlendColor, 0, 0, 0, CharacterHandle);
@ -197,35 +270,48 @@ static void BuildScene(scene_view *View)
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);
UI_Parent(Box) if(SV_CurrentlyInProc())
{ {
UI_WidthFill UI_Height(UI_Percent(1, 0)) UI_Row() UI_FillPadding UI_Column() UI_FillPadding UI_Parent(Box)
{ {
b32 FoundOffset = false; //- sixten: build branches
s64 Offset = 0; UI_WidthFill UI_Height(UI_Percent(1, 0)) UI_Row() UI_FillPadding UI_Column() UI_FillPadding
for(s32 BranchIndex = 0; BranchIndex < Runtime->BranchCount; BranchIndex += 1)
{ {
branch_case *Branch = &Runtime->Branches[BranchIndex]; b32 FoundOffset = false;
if(UI_ButtonF("%S#%i", Branch->Name, BranchIndex).Clicked) s64 Offset = 0;
for(s32 BranchIndex = 0; BranchIndex < Runtime->BranchCount; BranchIndex += 1)
{ {
Offset = Branch->Offset; branch_case *Branch = &Runtime->Branches[BranchIndex];
FoundOffset = true; if(UI_ButtonF("%S#%i", Branch->Name, BranchIndex).Clicked)
{
Offset = Branch->Offset;
FoundOffset = true;
}
}
if(FoundOffset)
{
Runtime->IP += 1+Offset;
Runtime->BranchCount = 0;
} }
} }
if(FoundOffset)
//- sixten: build textbox
UI_Size(UI_Percent(1, 1), UI_Percent(0.3, 1))
{ {
Runtime->IP += 1+Offset; ui_box *TextBox = UI_MakeBox(0, StrLit("Scene Textbox"));
Runtime->BranchCount = 0;
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);
} }
} }
}
UI_SetNextWidth(UI_Percent(1, 1)); else
UI_SetNextHeight(UI_Percent(0.3, 1)); {
ui_box *TextBox = UI_MakeBox(0, StrLit("Scene Textbox")); //- sixten: render environmental objects
scene_textbox_data *TextboxData = PushStruct(UI_FrameArena(), scene_textbox_data);
TextboxData->Textbox = Textbox;
TextboxData->SceneViewBox = Box;
UI_EquipBoxCustomDrawCallback(TextBox, BuildSceneTextboxDrawCallback, TextboxData);
} }
} }
@ -238,7 +324,7 @@ static void BuildErrorScreen(scene_runtime *Runtime, vn_input *Input)
{ {
UI_Font(Font_Bold) UI_Size(UI_TextContent(0, 1), UI_TextContent(0, 1)) UI_FontSize(32) UI_LabelF("A runtime error has occurred"); UI_Font(Font_Bold) UI_Size(UI_TextContent(0, 1), UI_TextContent(0, 1)) UI_FontSize(32) UI_LabelF("A runtime error has occurred");
s64 ErrorIndex = 0; s64 ErrorIndex = 0;
for(scene_runtime_error *Error = Runtime->FirstError; Error != 0; Error = Error->Next, ErrorIndex += 1) for(scene_runtime_error *Error = Runtime->Errors.First; Error != 0; Error = Error->Next, ErrorIndex += 1)
{ {
UI_Spacer(UI_Em(3, 1)); UI_Spacer(UI_Em(3, 1));
UI_SetNextCornerRadius(3); UI_SetNextCornerRadius(3);
@ -259,7 +345,7 @@ static void BuildErrorScreen(scene_runtime *Runtime, vn_input *Input)
} }
if(IgnoreSignal.Clicked) if(IgnoreSignal.Clicked)
{ {
Runtime->FirstError = Runtime->LastError = 0; ZeroStruct(&Runtime->Errors);
ArenaClear(Runtime->ErrorArena); ArenaClear(Runtime->ErrorArena);
} }
@ -272,10 +358,7 @@ static void BuildErrorScreen(scene_runtime *Runtime, vn_input *Input)
} }
if(RestartSignal.Clicked) if(RestartSignal.Clicked)
{ {
Runtime->FirstError = Runtime->LastError = 0; SV_Reset();
Runtime->IP = 0;
Runtime->CurrentProc = 0;
ArenaClear(Runtime->ErrorArena);
} }
UI_Spacer(UI_Em(1, 1)); UI_Spacer(UI_Em(1, 1));
@ -294,7 +377,7 @@ static scene_view_character_data *SV_CharacterDataFromName(string Name)
scene_view *View = SV_GetState(); scene_view *View = SV_GetState();
for(s32 CharacterIndex = 0; CharacterIndex < View->CharacterCount; CharacterIndex += 1) for(s32 CharacterIndex = 0; CharacterIndex < View->OnscreenCharacterCount; CharacterIndex += 1)
{ {
scene_view_character_data *Character = View->OnscreenCharacters + CharacterIndex; scene_view_character_data *Character = View->OnscreenCharacters + CharacterIndex;
if(AreEqual(Character->Name, Name)) if(AreEqual(Character->Name, Name))
@ -305,24 +388,26 @@ static scene_view_character_data *SV_CharacterDataFromName(string Name)
} }
//- sixten: create character if not initialized //- sixten: create character if not initialized
if(!Result && View->CharacterCount < ArrayCount(View->OnscreenCharacters)) if(!Result && View->OnscreenCharacterCount < ArrayCount(View->OnscreenCharacters))
{ {
s32 CharacterIndex = View->CharacterCount; s32 CharacterIndex = View->OnscreenCharacterCount;
View->CharacterCount += 1; View->OnscreenCharacterCount += 1;
Result = View->OnscreenCharacters + CharacterIndex; Result = View->OnscreenCharacters + CharacterIndex;
*Result = {}; *Result = {};
Result->Name = Name; Result->Name = Name;
Result->Active = true; Result->Active = true;
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharacterCount + 1); Result->PctP = (r32)(CharacterIndex + 1) / (View->OnscreenCharacterCount + 1);
} }
return(Result); return(Result);
} }
static render_handle SV_CharacterTextureFromAction(scene_character_action *Action) static scene_view_character_texture_info SV_CharacterTextureFromAction(scene_character_action *Action)
{ {
render_handle Result = EmptyRenderHandle(); scene_view_character_texture_info Result = {};
Result.Texture = EmptyRenderHandle();
Result.Scale = 1.0f;
scene_view *View = SV_GetState(); scene_view *View = SV_GetState();
@ -330,16 +415,47 @@ static render_handle SV_CharacterTextureFromAction(scene_character_action *Actio
{ {
switch(Action->State) switch(Action->State)
{ {
case CR_State_Normal: { Result = View->TestNormal; } break; case CR_State_Normal: { Result.Texture = View->TestNormal; } break;
case CR_State_Happy: { Result = View->TestHappy; } break; case CR_State_Happy: { Result.Texture = View->TestHappy; } break;
default: break; default: break;
} }
}
Result.Scale = 0.017f;
}
else if(AreEqual(StrLit("monika"), Action->Target))
{
switch(Action->State)
{
case CR_State_Leaning: { Result.Texture = View->MonikaLeaning; } break;
default: break;
}
Result.Scale = 0.033f;
}
return(Result); return(Result);
} }
static void SV_Update(memory_arena *FrameArena) static r32 SV_CalculateTargetPctP(s32 TrueCharacterIndex)
{
scene_view *View = SV_GetState();
s32 CharacterCount = 0;
s32 AssumedCharacterIndex = 0;
for(s32 CharacterIndex = 0; CharacterIndex < View->OnscreenCharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = View->OnscreenCharacters + CharacterIndex;
if(Data->Active)
{
CharacterCount += 1;
if(CharacterIndex < TrueCharacterIndex)
{
AssumedCharacterIndex += 1;
}
}
}
r32 Result = (r32)(AssumedCharacterIndex + 1) / (Max(CharacterCount, 1) + 1);
return(Result);
}
static void SV_UpdateInDialog(arena *FrameArena)
{ {
scene_view *SceneView = SV_GetState(); scene_view *SceneView = SV_GetState();
textbox *Textbox = &SceneView->Textbox; textbox *Textbox = &SceneView->Textbox;
@ -348,35 +464,11 @@ static void SV_Update(memory_arena *FrameArena)
r32 dtForFrame = SceneView->dtForFrame; r32 dtForFrame = SceneView->dtForFrame;
compiled_scene *Compiled = &Runtime->Compiled; compiled_scene *Compiled = &Runtime->Compiled;
//- sixten: update the characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
AC_AnimateValueDirect(Data->Active, 0.3f, &Data->ActiveT);
AC_AnimateValueDirect(Data->Talking, 0.3f, &Data->TalkingT);
r32 TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharacterCount+1);
AC_AnimateValueDirect(TargetPctP, 0.3f, &Data->PctP);
}
//- sixten: prune any unactive characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
if(!Data->Active && Data->ActiveT < 0.01)
{
Move(Data, Data+1, SceneView->CharacterCount-CharacterIndex-1);
SceneView->CharacterCount -= 1;
CharacterIndex -= 1;
}
}
if(Compiled && Compiled->IsValid) if(Compiled && Compiled->IsValid)
{ {
b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||Platform_KeyPress(EventList, Key_MouseLeft)); b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||Platform_KeyPress(EventList, Key_MouseLeft));
if(DLLIsEmpty(Runtime->FirstError)) if(!Runtime->LastResult.HadError)
{ {
b32 AdvanceOnAwait = (Textbox->CharsRevealed >= Textbox->String.Count) && PlayerAction; b32 AdvanceOnAwait = (Textbox->CharsRevealed >= Textbox->String.Count) && PlayerAction;
@ -389,7 +481,7 @@ static void SV_Update(memory_arena *FrameArena)
} }
} }
} }
r32 CharsPerSecond = 35.0f;//10.0f; r32 CharsPerSecond = 25.0f;
Textbox->CharsRevealed += dtForFrame*CharsPerSecond; Textbox->CharsRevealed += dtForFrame*CharsPerSecond;
Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count); Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count);
@ -398,20 +490,23 @@ static void SV_Update(memory_arena *FrameArena)
Textbox->CharsRevealed = Textbox->String.Count; Textbox->CharsRevealed = Textbox->String.Count;
} }
AC_AnimateValueDirect(Textbox->CharsRevealed, 0.05f, &Textbox->CharsRevealedT);
//- sixten: apply the textbox actions //- sixten: apply the textbox actions
for(textbox_action *Action = Runtime->FirstTextboxAction; Action != 0; Action = Action->Next) for(scene_textbox_action *Action = Runtime->FirstTextboxAction; Action != 0; Action = Action->Next)
{ {
if(Action->Kind == TextboxActionKind_Set) if(Action->Kind == S_TextboxActionKind_Set)
{ {
string ReplaceString = Action->String; string ReplaceString = Action->String;
Textbox->String.Count = Min(ReplaceString.Count, Textbox->Capacity); Textbox->String.Count = Min(ReplaceString.Count, Textbox->Capacity);
Copy(Textbox->String.Data, ReplaceString.Data, Textbox->String.Count); Copy(Textbox->String.Data, ReplaceString.Data, Textbox->String.Count);
Textbox->CharsRevealedT = 0;
Textbox->CharsRevealed = 0; Textbox->CharsRevealed = 0;
} }
else if(Action->Kind == TextboxActionKind_Append) else if(Action->Kind == S_TextboxActionKind_Append)
{ {
string Addend = Action->String; string Addend = Action->String;
Textbox->CharsRevealed = Textbox->String.Count; Textbox->CharsRevealedT = Textbox->String.Count;
s64 NewCount = Min(Textbox->String.Count+Addend.Count, Textbox->Capacity-1); s64 NewCount = Min(Textbox->String.Count+Addend.Count, Textbox->Capacity-1);
Copy(Textbox->String.Data+Textbox->String.Count, Action->String.Data, NewCount-Textbox->String.Count); Copy(Textbox->String.Data+Textbox->String.Count, Action->String.Data, NewCount-Textbox->String.Count);
Textbox->String.Count = NewCount; Textbox->String.Count = NewCount;
@ -423,6 +518,18 @@ static void SV_Update(memory_arena *FrameArena)
} }
Runtime->FirstTextboxAction = Runtime->LastTextboxAction = 0; Runtime->FirstTextboxAction = Runtime->LastTextboxAction = 0;
//- sixten: make all characters non-talking
if(Runtime->FirstCharacterAction != 0)
{
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
Data->Talking = false;
}
SceneView->CharacterIsTalking = false;
}
//- sixten: apply character actions //- sixten: apply character actions
for(scene_character_action *Action = Runtime->FirstCharacterAction; Action != 0; Action = Action->Next) for(scene_character_action *Action = Runtime->FirstCharacterAction; Action != 0; Action = Action->Next)
{ {
@ -435,9 +542,20 @@ static void SV_Update(memory_arena *FrameArena)
} }
else else
{ {
Data->Texture = SV_CharacterTextureFromAction(Action); Data->Info = SV_CharacterTextureFromAction(Action);
Data->TextureScale = 0.017f;
Data->Talking = true; Data->Talking = true;
SceneView->CharacterIsTalking = true;
string CharacterName = Action->Target;
scene_named_value *CharacterNameValue = S_FindGlobalVariableByName(Runtime, CharacterName, false);
if(CharacterNameValue && CharacterNameValue->Value.Kind == S_ValueKind_String)
{
CharacterName = CharacterNameValue->Value.String;
}
SceneView->LastTalkingCharacter = MakeString(SceneView->LastTalkingCharacterBuffer, CharacterName.Count);
Copy(SceneView->LastTalkingCharacterBuffer, CharacterName.Data, CharacterName.Count);
} }
} }
@ -445,6 +563,57 @@ static void SV_Update(memory_arena *FrameArena)
} }
} }
static void SV_Update(arena *FrameArena)
{
scene_view *SceneView = SV_GetState();
//- sixten: update the characters
{
AC_AnimateValueDirect(SceneView->CharacterIsTalking, 0.3f, &SceneView->CharacterIsTalkingT);
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
AC_AnimateValueDirect(Data->Active, 0.5f, &Data->ActiveT);
AC_AnimateValueDirect(Data->Talking, 0.4f, &Data->TalkingT);
r32 TargetPctP;
if(Data->Active)
{
TargetPctP = SV_CalculateTargetPctP(CharacterIndex);
}
else
{
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->OnscreenCharacterCount+1);
}
AC_AnimateValueDirect(TargetPctP, 0.4f, &Data->PctP);
}
}
//- sixten: prune any unactive characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
if(!Data->Active && Data->ActiveT < 0.01)
{
Move(Data, Data+1, (SceneView->OnscreenCharacterCount-CharacterIndex-1)*sizeof(scene_view_character_data));
SceneView->OnscreenCharacterCount -= 1;
CharacterIndex -= 1;
}
}
//- sixten: update scene
if(SV_CurrentlyInProc())
{
SV_UpdateInDialog(FrameArena);
}
else
{
}
}
static void SV_BuildSceneView(vn_input *Input) static void SV_BuildSceneView(vn_input *Input)
{ {
scene_view *SceneView = SV_GetState(); scene_view *SceneView = SV_GetState();
@ -456,23 +625,6 @@ static void SV_BuildSceneView(vn_input *Input)
else if(SceneView->Runtime.Compiled.IsValid) else if(SceneView->Runtime.Compiled.IsValid)
{ {
BuildScene(SceneView); BuildScene(SceneView);
#if 0
UI_Tooltip
{
UI_SetNextFixedP(V2R32(0, 0));
UI_SetNextSize(UI_ChildrenSum(1, 1), UI_ChildrenSum(1, 1));
UI_Column() UI_Size(UI_TextContent(15, 1), UI_TextContent(15, 1))
{
UI_Row()
{
UI_LabelF("Character Count: %i", SceneView->CharacterCount);
if(UI_ButtonF("+").Clicked) ++SceneView->CharacterCount;
if(UI_ButtonF("-").Clicked) --SceneView->CharacterCount;
}
}
}
#endif
} }
else else
{ {

View File

@ -7,50 +7,71 @@ struct textbox
{ {
string String; string String;
s64 Capacity; s64 Capacity;
r32 CharsRevealedT;
r32 CharsRevealed; r32 CharsRevealed;
}; };
struct scene_view_character_texture_info
{
render_handle Texture;
r32 Scale;
};
struct scene_view_character_data struct scene_view_character_data
{ {
string Name; string Name;
scene_view_character_texture_info Info;
b32 Active; b32 Active;
b32 Talking;
render_handle Texture;
r32 TextureScale;
r32 ActiveT; r32 ActiveT;
b32 Talking;
r32 TalkingT; r32 TalkingT;
r32 PctP; r32 PctP;
}; };
struct scene_view struct scene_view
{ {
memory_arena *SceneArena; arena *SceneArena;
// sixten: input //- sixten: state
scene_runtime Runtime;
textbox Textbox;
u8 LastTalkingCharacterBuffer[32];
string LastTalkingCharacter;
b32 CharacterIsTalking;
r32 CharacterIsTalkingT;
s32 OnscreenCharacterCount;
scene_view_character_data OnscreenCharacters[16];
//- sixten: input per frame
platform_event_list *EventList; platform_event_list *EventList;
r32 dtForFrame; r32 dtForFrame;
scene_runtime Runtime; //- sixten: temporary texture hub
textbox Textbox;
render_handle BackgroundTexture; render_handle BackgroundTexture;
s32 TargetCharacter;
render_handle TestHappy; render_handle TestHappy;
render_handle TestNormal; render_handle TestNormal;
render_handle MonikaLeaning;
s32 CharacterCount;
scene_view_character_data OnscreenCharacters[16];
}; };
static void SV_SetState(scene_view *View); static void SV_SetState(scene_view *View);
static scene_view *SV_GetState(); static scene_view *SV_GetState();
static void SV_NewFrame(scene_view *View, platform_event_list *EventList, r32 dtForFrame); static void SV_NewFrame(scene_view *View, platform_event_list *EventList, r32 dtForFrame);
static void SV_Reset(void);
static void SV_SetCurrentSource(compiled_scene *Compiled); static void SV_SetCurrentSource(compiled_scene *Compiled);
static void SV_Init(scene_view *View, memory_arena *TextboxArena); static void SV_Init(scene_view *View, arena *TextboxArena);
static b32 SV_CurrentlyInProc(void);
static void SV_BuildSceneView(vn_input *Input); static void SV_BuildSceneView(vn_input *Input);
static void SV_Update(memory_arena *FrameArena); static void SV_Update(arena *FrameArena);
#endif //VN_SCENE_VIEW_H #endif //VN_SCENE_VIEW_H

View File

@ -359,7 +359,7 @@ static b32 StringIsWhitespace(string String)
return(Result); return(Result);
} }
static text_op TextOpFromAction(memory_arena *Arena, string String, static text_op TextOpFromAction(arena *Arena, string String,
text_edit_state *State, text_action *Action, text_edit_state *State, text_action *Action,
range1_s64_array *Lines = 0, s64 LastColumnIndex = 0) range1_s64_array *Lines = 0, s64 LastColumnIndex = 0)
{ {
@ -413,42 +413,6 @@ static text_op TextOpFromAction(memory_arena *Arena, string String,
{ {
IgnoreFirstWhitespace = false; IgnoreFirstWhitespace = false;
} }
#if 0
u8 *LineBegin = Line.Data;
u8 *LineEnd = LineBegin+Line.Count;
u8 *Char = (Action->Delta > 0)?LineBegin:LineEnd;
if(Action->Delta > 0)
{
for(;Char <= LineEnd; Char += 1)
{
if(Char == LineEnd)
{
goto FoundLine;
}
if(!IsWhitespace(*Char))
{
break;
}
}
}
else if(Action->Delta < 0)
{
for(;LineBegin <= Char; Char -= 1)
{
if(!IsWhitespace(*Char))
{
break;
}
if(Char == LineBegin)
{
goto FoundLine;
}
}
}
#endif
} }
} }

View File

@ -7,7 +7,7 @@ static string T_StringFromToken(string Text, token Token)
return(Result); return(Result);
} }
static void T_TokenChunkListPush(memory_arena *Arena, token_chunk_list *List, token Token, s64 MaxTokenCountPerNode) static void T_TokenChunkListPush(arena *Arena, token_chunk_list *List, token Token, s64 MaxTokenCountPerNode)
{ {
token_chunk_node *Node = List->Last; token_chunk_node *Node = List->Last;
if(!Node || Node->Count >= Node->MaxCount) if(!Node || Node->Count >= Node->MaxCount)
@ -23,7 +23,7 @@ static void T_TokenChunkListPush(memory_arena *Arena, token_chunk_list *List, to
List->Count += 1; List->Count += 1;
} }
static token_array T_TokenArrayFromList(memory_arena *Arena, token_chunk_list *List) static token_array T_TokenArrayFromList(arena *Arena, token_chunk_list *List)
{ {
token_array Result = {}; token_array Result = {};
Result.Tokens = PushArrayNoClear(Arena, token, List->Count); Result.Tokens = PushArrayNoClear(Arena, token, List->Count);
@ -40,7 +40,7 @@ static token_array T_TokenArrayFromList(memory_arena *Arena, token_chunk_list *L
//////////////////////////////// ////////////////////////////////
//~ sixten: Tokenizer Message Functions //~ sixten: Tokenizer Message Functions
static void T_MessageListPush(memory_arena *Arena, tokenizer_message_list *List, tokenizer_message_kind Kind, s64 Offset, string String) static void T_MessageListPush(arena *Arena, tokenizer_message_list *List, tokenizer_message_kind Kind, s64 Offset, string String)
{ {
tokenizer_message *Message = PushStructNoClear(Arena, tokenizer_message); tokenizer_message *Message = PushStructNoClear(Arena, tokenizer_message);
Message->Kind = Kind; Message->Kind = Kind;
@ -52,7 +52,7 @@ static void T_MessageListPush(memory_arena *Arena, tokenizer_message_list *List,
//////////////////////////////// ////////////////////////////////
//~ sixten: Text -> Token Functions //~ sixten: Text -> Token Functions
static tokenize_result T_TokenizeFromText(memory_arena *Arena, string Text, tokenizer_filter_function *ExcludeFilter) static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_filter_function *ExcludeFilter)
{ {
temporary_memory Scratch = GetScratch(&Arena, 1); temporary_memory Scratch = GetScratch(&Arena, 1);
token_chunk_list Tokens = {}; token_chunk_list Tokens = {};

View File

@ -148,15 +148,15 @@ inline b32 T_IsInvalid(token_kind Kind) { return(Kind == TokenKind_None ||
//////////////////////////////// ////////////////////////////////
//~ sixten: Token Type Functions //~ sixten: Token Type Functions
static string T_StringFromToken(string Text, token Token); static string T_StringFromToken(string Text, token Token);
static void T_TokenChunkListPush(memory_arena *Arena, token_chunk_list *List, token Token, s64 MaxTokenCountPerNode); static void T_TokenChunkListPush(arena *Arena, token_chunk_list *List, token Token, s64 MaxTokenCountPerNode);
static token_array T_TokenArrayFromChunkList(memory_arena *Arena, token_chunk_list *List); static token_array T_TokenArrayFromChunkList(arena *Arena, token_chunk_list *List);
//////////////////////////////// ////////////////////////////////
//~ sixten: Tokenizer Message Functions //~ sixten: Tokenizer Message Functions
static void T_MessageListPush(memory_arena *Arena, tokenizer_message_list *List, tokenizer_message_kind Kind, s64 Offset, string String); static void T_MessageListPush(arena *Arena, tokenizer_message_list *List, tokenizer_message_kind Kind, s64 Offset, string String);
//////////////////////////////// ////////////////////////////////
//~ sixten: Text -> Token Functions //~ sixten: Text -> Token Functions
static tokenize_result T_TokenizeFromText(memory_arena *Arena, string Text, tokenizer_filter_function *ExcludeFilter = 0); static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_filter_function *ExcludeFilter = 0);
#endif //VN_TOKENIZER_H #endif //VN_TOKENIZER_H

View File

@ -36,7 +36,7 @@ inline platform_event_list *UI_EventList(void)
return(UI_GetState()->EventList); return(UI_GetState()->EventList);
} }
inline memory_arena *UI_FrameArena(void) inline arena *UI_FrameArena(void)
{ {
return(UI_GetState()->FrameArena); return(UI_GetState()->FrameArena);
} }
@ -795,8 +795,8 @@ static void UI_LayoutBox(ui_box *Box)
static void UI_Init(ui *UI) static void UI_Init(ui *UI)
{ {
UI->Arena = ArenaAllocate(Gigabytes(1)); UI->Arena = ArenaAlloc(Kilobytes(4), true);
UI->FrameArena = ArenaAllocate(Gigabytes(1)); UI->FrameArena = ArenaAlloc(Kilobytes(16), true);
} }
static void UI_BeginBuild(v2 ScreenDim) static void UI_BeginBuild(v2 ScreenDim)

View File

@ -130,8 +130,8 @@ struct ui_signal
struct ui struct ui
{ {
memory_arena *Arena; arena *Arena;
memory_arena *FrameArena; arena *FrameArena;
ui_box *FirstFreeBox; ui_box *FirstFreeBox;
ui_box *LastFreeBox; ui_box *LastFreeBox;
@ -165,7 +165,7 @@ inline ui *UI_GetState(void);
inline ui_key UI_HotKey(void); inline ui_key UI_HotKey(void);
inline ui_key UI_ActiveKey(void); inline ui_key UI_ActiveKey(void);
inline platform_event_list *UI_EventList(void); inline platform_event_list *UI_EventList(void);
inline memory_arena *UI_FrameArena(void); inline arena *UI_FrameArena(void);
inline v2 UI_MouseP(void); inline v2 UI_MouseP(void);
inline glyph_atlas *UI_GlyphAtlas(void); inline glyph_atlas *UI_GlyphAtlas(void);

View File

@ -1,8 +1,6 @@
#include "vn_workspace_view.cpp"
#include "vn_workspace_editor.cpp"
#include "vn_workspace_text_editor.cpp"
#include "vn_workspace_character_editor.cpp"
#include "vn_workspace_commands.cpp" #include "vn_workspace_commands.cpp"
#include "vn_workspace_view.cpp"
#include "vn_workspace_text_editor.cpp"
//- sixten: State management //- sixten: State management
per_thread workspace *ThreadLocal_Workspace; per_thread workspace *ThreadLocal_Workspace;
@ -13,7 +11,6 @@ static workspace_keybind Workspace_Keybinds[] =
{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_View_TextEditor},
{Key_T, PlatformModifier_Ctrl, W_Command_Test},
#if VN_INTERNAL #if VN_INTERNAL
{Key_U, PlatformModifier_Ctrl|PlatformModifier_Shift, W_Command_ToggleRenderUIDebugRects}, {Key_U, PlatformModifier_Ctrl|PlatformModifier_Shift, W_Command_ToggleRenderUIDebugRects},
@ -30,7 +27,7 @@ static workspace *W_GetState(void)
return(ThreadLocal_Workspace); return(ThreadLocal_Workspace);
} }
static memory_arena *W_FrameArena(void) static arena *W_FrameArena(void)
{ {
return(ThreadLocal_Workspace->FrameArena); return(ThreadLocal_Workspace->FrameArena);
} }
@ -104,7 +101,7 @@ static void W_ProcessKeyBinds()
//- sixten: Builder code //- sixten: Builder code
static ui_signal W_BuildToolbarButton(char *Text, toolbar_menu Menu) static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu)
{ {
workspace *Workspace = W_GetState(); workspace *Workspace = W_GetState();
@ -123,7 +120,7 @@ static ui_signal W_BuildToolbarButton(char *Text, toolbar_menu Menu)
ui_signal Signal = UI_SignalFromBox(Box); ui_signal Signal = UI_SignalFromBox(Box);
if(Workspace->Menu == ToolbarMenu_None) if(Workspace->Menu == W_ToolbarMenu_None)
{ {
if(Signal.Clicked) if(Signal.Clicked)
{ {
@ -178,7 +175,7 @@ static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut)
return(Signal); return(Signal);
} }
static void W_BuildToolbar() static void W_BuildToolbar(void)
{ {
workspace *Workspace = W_GetState(); workspace *Workspace = W_GetState();
@ -191,12 +188,12 @@ static void W_BuildToolbar()
UI_Parent(ToolbarBox) UI_Parent(ToolbarBox)
{ {
W_BuildToolbarButton("Panel", ToolbarMenu_Panel); W_BuildToolbarButton("Panel", W_ToolbarMenu_Panel);
W_BuildToolbarButton("View", ToolbarMenu_View); W_BuildToolbarButton("View", W_ToolbarMenu_View);
W_BuildToolbarButton("Window", ToolbarMenu_Window); W_BuildToolbarButton("Window", W_ToolbarMenu_Window);
} }
if(Workspace->Menu != ToolbarMenu_None) if(Workspace->Menu != W_ToolbarMenu_None)
{ {
r32 MenuTransition = Workspace->MenuTransition; r32 MenuTransition = Workspace->MenuTransition;
@ -219,20 +216,20 @@ static void W_BuildToolbar()
UI_CornerRadius(2) UI_CornerRadius(2)
UI_Size(UI_Percent(1, 1), UI_Pixels(25, 1)) UI_Size(UI_Percent(1, 1), UI_Pixels(25, 1))
{ {
if(Workspace->Menu == ToolbarMenu_Panel) if(Workspace->Menu == W_ToolbarMenu_Panel)
{ {
if(W_BuildMenuItem(FontIcon_ResizeHorizontal, "Split Horizontal", "Ctrl + P").Clicked) if(W_BuildMenuItem(FontIcon_ResizeHorizontal, "Split Horizontal", "Ctrl + P").Clicked)
{ {
W_IssueCommand(W_Command_SplitPanelHorizontal); W_IssueCommand(W_Command_SplitPanelHorizontal);
Workspace->Menu = ToolbarMenu_None; Workspace->Menu = W_ToolbarMenu_None;
} }
if(W_BuildMenuItem(FontIcon_ResizeVertical, "Split Vertical", "Ctrl + L").Clicked) if(W_BuildMenuItem(FontIcon_ResizeVertical, "Split Vertical", "Ctrl + L").Clicked)
{ {
W_IssueCommand(W_Command_SplitPanelVertical); W_IssueCommand(W_Command_SplitPanelVertical);
Workspace->Menu = ToolbarMenu_None; Workspace->Menu = W_ToolbarMenu_None;
} }
} }
else if(Workspace->Menu == ToolbarMenu_View) else if(Workspace->Menu == W_ToolbarMenu_View)
{ {
workspace_panel *CurrentPanel = Workspace->CurrentPanel; workspace_panel *CurrentPanel = Workspace->CurrentPanel;
@ -243,49 +240,45 @@ static void W_BuildToolbar()
if(W_BuildMenuItem(FontIcon_None, "Welcome", "").Clicked) if(W_BuildMenuItem(FontIcon_None, "Welcome", "").Clicked)
{ {
W_CreateNewView(W_View_Startup, CurrentPanel); W_CreateNewView(W_View_Startup, CurrentPanel);
Workspace->Menu = ToolbarMenu_None; Workspace->Menu = W_ToolbarMenu_None;
} }
if(W_BuildMenuItem(FontIcon_Pencil, "Script Editor", "Ctrl + O").Clicked) if(W_BuildMenuItem(FontIcon_Pencil, "Script Editor", "Ctrl + O").Clicked)
{ {
W_CreateNewView(W_View_TextEditor, CurrentPanel); W_CreateNewView(W_View_TextEditor, CurrentPanel);
Workspace->Menu = ToolbarMenu_None; Workspace->Menu = W_ToolbarMenu_None;
} }
if(W_BuildMenuItem(FontIcon_Terminal, "Scene View", "").Clicked) if(W_BuildMenuItem(FontIcon_Terminal, "Scene View", "").Clicked)
{ {
W_CreateNewView(W_View_SceneView, CurrentPanel); W_CreateNewView(W_View_SceneView, CurrentPanel);
Workspace->Menu = ToolbarMenu_None; Workspace->Menu = W_ToolbarMenu_None;
}
if(W_BuildMenuItem(FontIcon_User, "Character Editor", "").Clicked)
{
W_CreateNewView(W_View_CharacterEditor, CurrentPanel);
Workspace->Menu = ToolbarMenu_None;
} }
if(W_BuildMenuItem(FontIcon_Wrench, "Settings", "").Clicked) if(W_BuildMenuItem(FontIcon_Wrench, "Settings", "").Clicked)
{ {
W_CreateNewView(W_View_Settings, CurrentPanel); W_CreateNewView(W_View_Settings, CurrentPanel);
Workspace->Menu = ToolbarMenu_None; Workspace->Menu = W_ToolbarMenu_None;
}
}
else if(Workspace->Menu == ToolbarMenu_Window)
{
if(W_BuildMenuItem(FontIcon_WindowMaximize, "ToggleFullscreen", "Alt + Enter").Clicked)
{
Platform.ToggleFullscreen();
Workspace->Menu = ToolbarMenu_None;
} }
} }
else if(Workspace->Menu == W_ToolbarMenu_Window)
AC_AnimateValueDirect(1, 0.1, &Workspace->MenuTransition); if(W_BuildMenuItem(FontIcon_WindowMaximize, "ToggleFullscreen", "Alt + Enter").Clicked)
{
Platform.ToggleFullscreen();
Workspace->Menu = W_ToolbarMenu_None;
}
} }
AC_AnimateValueDirect(1, 0.1, &Workspace->MenuTransition);
// 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))
{ {
Workspace->Menu = ToolbarMenu_None; Workspace->Menu = W_ToolbarMenu_None;
} }
} }
} }
//- sixten: Panels //- sixten: Panels
static workspace_panel *W_CreateNewPanel(workspace_panel *Parent) static workspace_panel *W_CreateNewPanel(workspace_panel *Parent)
{ {
@ -762,9 +755,9 @@ static void W_Init(workspace *Workspace)
{ {
W_SetState(Workspace); W_SetState(Workspace);
Workspace->FrameArena = ArenaAllocate(Gigabytes(1)); Workspace->FrameArena = ArenaAlloc(Kilobytes(32), true);
Workspace->CommandArena = ArenaAllocate(Gigabytes(1)); Workspace->CommandArena = ArenaAlloc(Kilobytes(4), true);
Workspace->PanelArena = ArenaAllocate(Gigabytes(1)); Workspace->PanelArena = ArenaAlloc(Kilobytes(4), true);
Workspace->RootPanel = Workspace->CurrentPanel = W_CreateNewPanel(0); Workspace->RootPanel = Workspace->CurrentPanel = W_CreateNewPanel(0);
@ -774,16 +767,13 @@ static void W_Init(workspace *Workspace)
} }
// sixten: build text editor / scene view layout // sixten: build text editor / scene view layout
if(1) if(0)
{ {
W_CreateNewView(W_View_TextEditor, Workspace->RootPanel); W_CreateNewView(W_View_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_View_SceneView, Workspace->RootPanel->Last);
} }
else // sixten: build character editor
{
W_CreateNewView(W_View_CharacterEditor, Workspace->RootPanel);
}
} }
static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands, static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands,

View File

@ -7,12 +7,12 @@
//~ sixten: Workspace Types //~ sixten: Workspace Types
// sixten(TODO): Remove this type entirely. // sixten(TODO): Remove this type entirely.
enum toolbar_menu enum workspace_toolbar_menu
{ {
ToolbarMenu_None = 0, W_ToolbarMenu_None = 0,
ToolbarMenu_Panel, W_ToolbarMenu_Panel,
ToolbarMenu_View, W_ToolbarMenu_View,
ToolbarMenu_Window, W_ToolbarMenu_Window,
}; };
struct workspace_panel struct workspace_panel
@ -71,10 +71,10 @@ struct workspace
platform_event_list *EventList; platform_event_list *EventList;
// sixten: General Purpose Allocation // sixten: General Purpose Allocation
memory_arena *FrameArena; arena *FrameArena;
// sixten: Command Allocation // sixten: Command Allocation
memory_arena *CommandArena; arena *CommandArena;
workspace_command *FirstFreeCommand; workspace_command *FirstFreeCommand;
workspace_command *LastFreeCommand; workspace_command *LastFreeCommand;
@ -83,14 +83,14 @@ struct workspace
workspace_command *LastCommand; workspace_command *LastCommand;
// sixten: Panels // sixten: Panels
memory_arena *PanelArena; arena *PanelArena;
workspace_panel *FirstFreePanel; workspace_panel *FirstFreePanel;
workspace_panel *LastFreePanel; workspace_panel *LastFreePanel;
workspace_drag_payload_state DragPayloadState; workspace_drag_payload_state DragPayloadState;
workspace_drag_payload DragPayload; workspace_drag_payload DragPayload;
toolbar_menu Menu; workspace_toolbar_menu Menu;
v2 MenuP; v2 MenuP;
r32 MenuTransition; r32 MenuTransition;
@ -98,9 +98,7 @@ struct workspace
workspace_panel *CurrentPanel; workspace_panel *CurrentPanel;
}; };
#include "vn_workspace_editor.h"
#include "vn_workspace_text_editor.h" #include "vn_workspace_text_editor.h"
#include "vn_workspace_character_editor.h"
#include "vn_workspace_view.h" #include "vn_workspace_view.h"
//////////////////////////////// ////////////////////////////////
@ -109,7 +107,7 @@ 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 memory_arena *W_FrameArena(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);
@ -121,9 +119,9 @@ 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: Builder code //- sixten: Builder code
static ui_signal W_BuildToolbarButton(char *Text, 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);
static void W_BuildToolbar(r32 dtForFrame); static void W_BuildToolbar(void);
//- sixten: Workspace //- sixten: Workspace
static void W_Init(workspace *Workspace); static void W_Init(workspace *Workspace);

View File

@ -1,100 +0,0 @@
////////////////////////////////
//~ sixten: Workspace Character Editor Functions
static character_editor_entry_data *W_AllocateCharacterEntryData(workspace_view_character_editor *Editor, memory_arena *Arena)
{
character_editor_entry_data *Result = Editor->FreeList.First;
if(!Result)
{
Result = PushStructNoClear(Arena, character_editor_entry_data);
}
*Result = {};
return(Result);
}
static void W_BuildCharacterEditorView(workspace_view *View)
{
workspace_view_character_editor *Editor = (workspace_view_character_editor *)View->Data;
//- sixten: check that the entry list is filled out
if(DLLIsEmpty(Editor->List.First))
{
character_list Characters = CR_GetCharacters();
for(character_entry *Character = Characters.First; Character != 0; Character = Character->Next)
{
character_editor_entry_data *Data = W_AllocateCharacterEntryData(Editor, View->Arena);
Data->Entry = Character;
DLLInsertLast(Editor->List.First, Editor->List.Last, Data);
}
}
UI_WidthFill UI_HeightFill UI_Row() UI_Padding(UI_Em(5, 1)) UI_Column()
{
UI_Spacer(UI_Em(2, 1));
// sixten: build character lister
{
UI_SetNextWidth(UI_Percent(1, 1));
UI_SetNextHeight(UI_Percent(1, 0));
UI_Scroll(0, &Editor->ScrollT)
{
UI_Height(UI_Em(2.0f, 1)) UI_CornerRadius(4.0f)
for(character_editor_entry_data *Data = Editor->List.First; Data != 0; Data = Data->Next)
{
character_entry *Entry = Data->Entry;
if(UI_ButtonF("%S", Entry->Name).Clicked)
{
Data->IsOpen = !Data->IsOpen;
}
AC_AnimateValueDirect(Data->IsOpen, 0.3f, &Data->OpenTransition);
if(Data->OpenTransition > 0.1f)
{
UI_SetNextHeight(UI_ChildrenSum(Data->OpenTransition, 1));
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBorder |
UI_BoxFlag_DrawDropShadow |
UI_BoxFlag_Clip,
StrLit("")))
{
UI_LabelF("hello");
UI_LabelF("line");
UI_LabelF("paint");
UI_LabelF("color");
UI_LabelF("design");
UI_LabelF("address");
UI_LabelF("brightness");
}
}
}
}
}
// sixten: build bottom controls
UI_Spacer(UI_Em(1.5, 1));
UI_Height(UI_Em(2, 1)) UI_Row()
{
UI_Width(UI_TextContent(15, 1)) UI_CornerRadius(4)
{
UI_SetNextFont(Font_Icons);
ui_signal AddSignal = UI_ButtonF("%U", FontIcon_UserPlus);
if(AddSignal.Hovering)
{
UI_TooltipLabel(StrLit("Add new character"), UI_MouseP());
}
UI_Spacer(UI_Em(0.5, 1));
UI_SetNextFont(Font_Icons);
ui_signal RemoveSignal = UI_ButtonF("%U", FontIcon_UserTimes);
if(RemoveSignal.Hovering)
{
UI_TooltipLabel(StrLit("Delete selected character"), UI_MouseP());
}
}
}
UI_Spacer(UI_Em(1.5, 1));
}
}

View File

@ -1,40 +0,0 @@
/* date = August 27th 2023 3:38 pm */
#ifndef VN_WORKSPACE_CHARACTER_EDITOR_H
#define VN_WORKSPACE_CHARACTER_EDITOR_H
////////////////////////////////
//~ sixten: Workspace Character Editor Types
struct character_editor_entry_data
{
//- sixten: node links
character_editor_entry_data *Next;
character_editor_entry_data *Prev;
//- sixten: contents
struct character_entry *Entry;
b32 IsOpen;
r32 OpenTransition;
};
struct character_editor_processed_entry_list
{
character_editor_entry_data *First;
character_editor_entry_data *Last;
};
struct workspace_view_character_editor
{
character_editor_processed_entry_list List;
character_editor_processed_entry_list FreeList;
r32 ScrollT;
};
////////////////////////////////
//~ sixten: Workspace Character Editor Functions
static void W_BuildCharacterEditorView(workspace_view *View);
#endif //VN_WORKSPACE_CHARACTER_EDITOR_H

View File

@ -1,377 +0,0 @@
//- sixten: Managing nodes
static workspace_editor_node *Workspace_GetNewEditorNode(workspace_view *View)
{
Assert(View->Type == W_View_Editor);
workspace_view_editor *Editor = (workspace_view_editor *)View->Data;
workspace_editor_node *Result = 0;
if(DLLIsEmpty(Editor->FirstFreeNode))
{
Result = PushStruct(View->Arena, workspace_editor_node);
}
else
{
Result = Editor->FirstFreeNode;
DLLRemove(Editor->FirstFreeNode, Editor->LastFreeNode, Result);
}
if(Result)
{
*Result = {};
DLLInsertLast(Editor->FirstNode, Editor->LastNode, Result);
}
return(Result);
}
//- sixten: Transformations
inline r32 Workspace_ViewToWorld(r32 Offset, r32 Scale, r32 Dim, r32 P)
{
r32 Result = (P - Dim*0.5)*(1.0/Scale) - Offset;
return(Result);
}
inline r32 Workspace_WorldToView(r32 Offset, r32 Scale, r32 Dim, r32 P)
{
r32 Result = (P + Offset)*Scale + Dim*0.5;
return(Result);
}
inline v2 Workspace_ViewToWorld(v2 Offset, r32 Scale, v2 Dim, v2 P)
{
v2 Result = (P - Dim*0.5)*(1.0/Scale) - Offset;
return(Result);
}
inline v2 Workspace_WorldToView(v2 Offset, r32 Scale, v2 Dim, v2 P)
{
v2 Result = (P + Offset)*Scale + Dim*0.5;
return(Result);
}
inline r32 Workspace_CalculateScaleFromZoomLevel(r32 ZoomLevel)
{
r32 PixelsPerUnit = 100.0;
r32 Scale = PixelsPerUnit*Pow(1.25, ZoomLevel);
return(Scale);
}
//- sixten: Commands
//- sixten: Builder code
static void Workspace_BuildEditorListerDropdown(workspace_editor_lister_dropdown *ListerDropdown)
{
b32 ActiveInDropdown = false;
UI_PushBackgroundColor(SetAlpha(Color_Black, 0.3));
UI_PushBorderColor(SetAlpha(Color_Black, 0.7));
r32 HeightTransition = AC_AnimateValueF(1, 0, 0.3, "Editor Lister Dropdown %p", ListerDropdown);
UI_SetNextSize(UI_Em(15, 1), UI_Em(25*HeightTransition, 1));
UI_SetNextCornerRadius(4.0);
UI_SetNextFixedP(ListerDropdown->P);
UI_SetNextLayoutAxis(Axis2_Y);
ui_box *Box = UI_MakeBox(UI_BoxFlag_DrawBackground |
UI_BoxFlag_FloatingX |
UI_BoxFlag_FloatingY |
UI_BoxFlag_Clickable |
UI_BoxFlag_Clip,
StrLit("Editor Lister Dropdown"));
UI_Parent(Box)
{
UI_BorderColor(SetAlpha(Color_Grey, 0.7))
UI_Row() UI_Column()
{
UI_Size(UI_TextContent(15, 1), UI_TextContent(12, 1)) UI_LabelF("Create new node");
// sixten: Build search bar
UI_SetNextWidth(UI_Percent(1, 1));
UI_SetNextHeight(UI_Em(2, 1));
UI_SetNextCornerRadius(4.0);
UI_SetNextLayoutAxis(Axis2_X);
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, StrLit("Editor Lister Field")))
{
UI_Spacer(UI_Em(0.8, 1));
UI_Width(UI_TextContent(1, 1)) UI_Font(Font_Icons) UI_LabelF("%U", FontIcon_Filter);
UI_Width(UI_Percent(1, 0))
{
UI_MakeBox(0, StrLit(""));
}
}
struct lister_option
{
char *Text;
u32 Icons;
};
lister_option Options[] =
{
{"Text", FontIcon_Pencil},
{"Branch", FontIcon_Menu},
};
for(s32 OptionIndex = 0;
OptionIndex < ArrayCount(Options);
++OptionIndex)
{
lister_option *Option = Options + OptionIndex;
UI_SetNextSize(UI_Percent(1, 1), UI_Em(2, 1));
UI_SetNextLayoutAxis(Axis2_X);
ui_box *ClickableBox = UI_MakeBoxF(UI_BoxFlag_Clickable, "Editor Lister %s", Option->Text);
ui_signal Signal = UI_SignalFromBox(ClickableBox);
if(AreEqual(UI_ActiveKey(), ClickableBox->Key))
{
ActiveInDropdown = true;
}
UI_Parent(ClickableBox)
UI_Height(UI_Percent(1, 1))
{
b32 IsHot = AreEqual(UI_HotKey(), ClickableBox->Key);
r32 TargetHot = IsHot*0.8;
UI_SetNextCornerRadius(3.0);
UI_SetNextSize(UI_Percent(1, 1), UI_Percent(1, 1));
UI_SetNextBackgroundColor(SetAlpha(Theme_HighlightBorderColor,
AC_AnimateValueF(TargetHot, TargetHot, 0.1, "Editor Lister %s%p",
Option->Text, ListerDropdown)));
UI_SetNextLayoutAxis(Axis2_X);
ui_box *HighlightBox = UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit(""));
UI_Parent(HighlightBox)
UI_Padding(UI_Em(0.8, 1))
{
UI_Width(UI_TextContent(0, 1))
UI_Font(Font_Icons) UI_MakeBoxF(UI_BoxFlag_DrawText, "%U", Option->Icons);
UI_Spacer(UI_Em(0.6, 1));
UI_Width(UI_TextContent(0, 1)) UI_MakeBoxF(UI_BoxFlag_DrawText, "%s", Option->Text);
if(Signal.Clicked)
{
// sixten(TODO): Issue the requested command.
ListerDropdown->Open = false;
}
}
}
}
}
ui_signal Signal = UI_SignalFromBox(Box);
if(AreEqual(UI_ActiveKey(), Box->Key))
{
ActiveInDropdown = true;
}
}
UI_PopBackgroundColor();
UI_PopBorderColor();
if(!ActiveInDropdown && !AreEqual(UI_ActiveKey(), UI_EmptyKey()))
{
ListerDropdown->Open = false;
}
}
static void Workspace_EditorDrawCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data)
{
workspace_view_editor *Editor = (workspace_view_editor *)Data;
r32 Scale = Editor->Scale;
v4 LineColor = Theme_BorderColor;
v2 Dim = DimOfRange(Box->Rect);
s32 VerticalLineCount = Dim.x / Scale + 4;
for(s32 LineIndex = -VerticalLineCount/2;
LineIndex < VerticalLineCount/2;
++LineIndex)
{
r32 OffsetX = Workspace_WorldToView(Editor->Offset.x, Scale, Dim.x, LineIndex - (s32)Editor->Offset.x);
v2 Min = Box->Rect.Min + V2(OffsetX, 0);
v2 Max = Min + V2(1.5, Dim.y);
PushQuad(Group, Range2R32(Min, Max), LineColor, 0, 1.2, 0);
}
s32 HorizontalLineCount = Dim.y / Scale + 4;
for(s32 LineIndex = -HorizontalLineCount/2;
LineIndex < HorizontalLineCount/2;
++LineIndex)
{
r32 OffsetY = Workspace_WorldToView(Editor->Offset.y, Scale, Dim.y, LineIndex - (s32)Editor->Offset.y);
v2 Min = Box->Rect.Min + V2(0, OffsetY);
v2 Max = Min + V2(Dim.x, 1.5);
PushQuad(Group, Range2R32(Min, Max), LineColor, 0, 1.2, 0);
}
}
static void Workspace_BuildEditor(workspace_view *View)
{
workspace *Workspace = W_GetState();
workspace_view_editor *Editor = (workspace_view_editor *)View->Data;
UI_SetNextWidth(UI_Percent(1, 1));
UI_SetNextHeight(UI_Percent(1, 1));
ui_box *EditorBox = UI_MakeBoxF(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "Workspace Editor %p", View);
UI_EquipBoxCustomDrawCallback(EditorBox, Workspace_EditorDrawCallback, Editor);
r32 AnimatedZoomLevel = AC_AnimateValueF(Editor->ZoomLevel, 0, 0.25, "Workspace Editor Zoom");
Editor->Scale = Workspace_CalculateScaleFromZoomLevel(AnimatedZoomLevel);
v2 EditorDim = DimOfRange(EditorBox->Rect);
UI_Parent(EditorBox)
{
// sixten: Build the node boxes.
for(workspace_editor_node *Node = Editor->FirstNode;
Node != 0;
Node = Node->Next)
{
v2 ViewDim = V2(2, 1.5)*Editor->Scale;
v2 ViewP = Workspace_WorldToView(Editor->Offset, Editor->Scale, EditorDim, Node->P) - ViewDim*0.5;
UI_SetNextSize(UI_Pixels(ViewDim.x, 1), UI_Pixels(ViewDim.y, 1));
UI_SetNextFixedP(ViewP);
UI_SetNextLayoutAxis(Axis2_Y);
Node->Box = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
UI_BoxFlag_DrawBorder |
UI_BoxFlag_FloatingX |
UI_BoxFlag_FloatingY |
UI_BoxFlag_DrawDropShadow,
"Workspace Editor Node %p", Node);
UI_Parent(Node->Box)
{
UI_SetNextBackgroundColor(LinearBlend(Theme_BackgroundColor, Color_Black, 0.3));
UI_SetNextLayoutAxis(Axis2_X);
UI_SetNextSize(UI_Percent(1, 1), UI_Em(1.8, 1));
Node->TitleBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
UI_BoxFlag_DrawBorder |
UI_BoxFlag_Clickable,
"Workspace Editor Node Title");
UI_Parent(Node->TitleBox)
{
UI_Spacer(UI_Em(0.5, 1));
UI_Width(UI_TextContent(0, 1)) UI_Font(Font_Bold) UI_LabelF("Node");
UI_Spacer(UI_Percent(1, 0));
UI_SetNextSize(UI_Em(1.8, 1), UI_Percent(1, 1));
UI_SetNextFont(Font_Icons);
Node->CloseBox = UI_MakeBoxF(UI_BoxFlag_DrawText, "%U", FontIcon_Cancel);
}
}
}
if(Editor->ListerDropdown.Open)
{
Workspace_BuildEditorListerDropdown(&Editor->ListerDropdown);
}
}
// sixten: Get input from boxes.
{
workspace_editor_node *Next = 0;
for(workspace_editor_node *Node = Editor->FirstNode;
Node != 0;
Node = Next)
{
Next = Node->Next;
ui_signal Signal = UI_SignalFromBox(Node->TitleBox);
if(Signal.Dragging)
{
if(Signal.Pressed)
{
UI_StoreDragV2(Node->P);
}
v2 StartP = UI_GetDragV2();
v2 EndP = StartP + Signal.DragDelta*(1.0 / Editor->Scale);
Node->P = EndP;
}
if(Signal.Dragging || Signal.Hovering)
{
Platform.SetCursor(PlatformCursor_ArrowAll);
}
}
}
// sixten: Process panning and zooming of the editor.
ui_signal Signal = UI_SignalFromBox(EditorBox);
{
if(Signal.Dragging)
{
if(Signal.Pressed)
{
UI_StoreDragV2(Editor->Offset);
}
v2 StartOffset = UI_GetDragV2();
v2 EndOffset = StartOffset + Signal.DragDelta*(1.0 / Editor->Scale);
Editor->Offset = EndOffset;
// sixten: Update node positions, as to not get a one frame delay.
for(workspace_editor_node *Node = 0;
Node != 0;
Node = Node->Next)
{
v2 ViewDim = V2(2, 1.5)*Editor->Scale;
v2 ViewP = Workspace_WorldToView(Editor->Offset, Editor->Scale, EditorDim, Node->P) - ViewDim*0.5;
Node->Box->FixedP = ViewP;
}
}
}
for(platform_event *Event = Workspace->EventList->First;
Event != 0;
Event = Event->Next)
{
if(Event->Type == PlatformEvent_MouseScroll)
{
if(Signal.Dragging)
{
UI_StoreDragV2(Editor->Offset);
UI_UpdateDragStartP();
}
Editor->ZoomLevel = Clamp(Editor->ZoomLevel + Event->Scroll.y, -4, 5);
}
}
// sixten: Process shortcuts.
if(Platform_KeyPress(Workspace->EventList, Key_Space, PlatformModifier_Ctrl))
{
workspace_editor_lister_dropdown *ListerDropdown = &Editor->ListerDropdown;
if(ListerDropdown->Open)
{
ListerDropdown->Open = false;
}
else if(InRange(EditorBox->Rect, UI_GetState()->MouseP))
{
ListerDropdown->Open = true;
ListerDropdown->P = UI_GetState()->MouseP - EditorBox->Rect.Min;
}
}
}

View File

@ -1,63 +0,0 @@
/* date = May 13th 2023 6:20 pm */
#ifndef VN_WORKSPACE_EDITOR_H
#define VN_WORKSPACE_EDITOR_H
/* sixten(NOTE): Node types
*
* Text(String, opt. Character) -> Node
* Branch(Strings[0..n]) -> Nodes[0..n]
*
*/
enum workspace_editor_node_type
{
Workspace_EditorNode_None,
Workspace_EditorNode_Start,
Workspace_EditorNode_Text,
Workspace_EditorNode_Branch,
};
struct workspace_editor_node
{
workspace_editor_node_type Type;
workspace_editor_node *Next;
workspace_editor_node *Prev;
ui_box *Box;
ui_box *TitleBox;
ui_box *CloseBox;
v2 P;
};
struct workspace_editor_lister_dropdown
{
// sixten: Input field
char InputField[128];
s32 InputFieldUsed;
b32 InputFieldSelected;
// sixten: Properties
b32 Open;
v2 P;
};
//- sixten: Managing nodes
static workspace_editor_node *Workspace_GetNewEditorNode(struct workspace_view *View);
//- sixten: Transformations
inline v2 Workspace_ViewToWorld(v2 Offset, r32 Scale, v2 Dim, v2 P);
inline v2 Workspace_WorldToView(v2 Offset, r32 Scale, v2 Dim, v2 P);
inline r32 Workspace_CalculateScaleFromZoomLevel(r32 ZoomLevel);
//- sixten: Lister dropdown
static void Workspace_OpenListerDropdown(v2 MouseP);
//- sixten: Builder code
static void Workspace_BuildEditorListerDropdown(workspace_editor_lister_dropdown *ListerDropdown);
static void Workspace_EditorDrawCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data);
static void Workspace_BuildEditor(struct workspace_view *View);
#endif //VN_WORKSPACE_EDITOR_H

View File

@ -4,7 +4,7 @@
static mutable_string MutableStringAllocate(u64 Size) static mutable_string MutableStringAllocate(u64 Size)
{ {
mutable_string Result = {}; mutable_string Result = {};
Result.Arena = ArenaAllocate(Size); Result.Arena = ArenaAlloc(Size);
ArenaSetAlign(Result.Arena, 1); ArenaSetAlign(Result.Arena, 1);
Result.String = MakeString(PushArray(Result.Arena, u8, 1), 0LL); Result.String = MakeString(PushArray(Result.Arena, u8, 1), 0LL);
return(Result); return(Result);
@ -27,7 +27,7 @@ static void MutableStringReplaceRange(mutable_string *MutString, string ReplaceS
} }
else if(NewCount < MutString->String.Count) else if(NewCount < MutString->String.Count)
{ {
ArenaPopTo(MutString->Arena, sizeof(memory_arena)+NewCount+1); ArenaPopTo(MutString->Arena, sizeof(arena)+NewCount+1);
} }
Move(MutString->String.Data+Range.Min+ReplaceString.Count, MutString->String.Data+Range.Max, MutString->String.Count-Range.Min-DimOfRange(Range)); Move(MutString->String.Data+Range.Min+ReplaceString.Count, MutString->String.Data+Range.Max, MutString->String.Count-Range.Min-DimOfRange(Range));
@ -40,7 +40,7 @@ static void MutableStringReplaceRange(mutable_string *MutString, string ReplaceS
//////////////////////////////// ////////////////////////////////
//~ sixten: History & Undo Functions //~ sixten: History & Undo Functions
static history_entry HistoryEntry(memory_arena *Arena, string ReplaceString, range1_s64 Range) static history_entry HistoryEntry(arena *Arena, string ReplaceString, range1_s64 Range)
{ {
// sixten(TODO): proper memory management, right now we just keep appending to the arena, which works but never frees any memory // sixten(TODO): proper memory management, right now we just keep appending to the arena, which works but never frees any memory
history_entry Entry = {}; history_entry Entry = {};
@ -49,7 +49,7 @@ static history_entry HistoryEntry(memory_arena *Arena, string ReplaceString, ran
return(Entry); return(Entry);
} }
static void AppendToHistory(memory_arena *Arena, history_list *List, history_entry Forward, history_entry Backward) static void AppendToHistory(arena *Arena, history_list *List, history_entry Forward, history_entry Backward)
{ {
// sixten(TODO): proper memory management, right now we just keep appending to the arena, which works but never frees any memory // sixten(TODO): proper memory management, right now we just keep appending to the arena, which works but never frees any memory
history_node *Node = PushStructNoClear(Arena, history_node); history_node *Node = PushStructNoClear(Arena, history_node);
@ -62,7 +62,7 @@ static void AppendToHistory(memory_arena *Arena, history_list *List, history_ent
//////////////////////////////// ////////////////////////////////
//~ sixten: Workspace Text Editing Functions //~ sixten: Workspace Text Editing Functions
static workspace_text_data W_TextDataFromString(memory_arena *Arena, string Text) static workspace_text_data W_TextDataFromString(arena *Arena, string Text)
{ {
temporary_memory Scratch = GetScratch(&Arena, 1); temporary_memory Scratch = GetScratch(&Arena, 1);
@ -426,11 +426,14 @@ UI_CUSTOM_DRAW_CALLBACK(W_TextEditorListerInputCallback)
} }
} }
static b32 W_BuildTextEditorListerItem(string Text, u32 Icon) static b32 W_BuildTextEditorListerItem(string Text, u32 Icon, b32 Selected, b32 EnterPressed)
{ {
b32 Result = false; b32 Result = false;
UI_SetNextLayoutAxis(Axis2_X); UI_SetNextLayoutAxis(Axis2_X);
UI_SetNextHoverCursor(PlatformCursor_Hand); 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_box *Container = UI_MakeBoxF(UI_BoxFlag_DrawBorder |
UI_BoxFlag_DrawBackground | UI_BoxFlag_DrawBackground |
UI_BoxFlag_Clickable | UI_BoxFlag_Clickable |
@ -445,7 +448,7 @@ static b32 W_BuildTextEditorListerItem(string Text, u32 Icon)
} }
ui_signal Signal = UI_SignalFromBox(Container); ui_signal Signal = UI_SignalFromBox(Container);
if(Signal.Clicked) if(Signal.Clicked || Selected&&EnterPressed)
{ {
Result = true; Result = true;
} }
@ -460,6 +463,9 @@ static workspace_text_editor_lister_action W_BuildTextEditorLister(workspace_vie
{ {
UI_Height(UI_Em(2, 1)) UI_Height(UI_Em(2, 1))
{ {
b32 EnterPressed = Platform_KeyPress(UI_EventList(), Key_Return);
s32 SelectedItemDelta = 0;
//- sixten: filename input field //- sixten: filename input field
if(W_ViewIsCurrent(View)) if(W_ViewIsCurrent(View))
{ {
@ -471,23 +477,30 @@ static workspace_text_editor_lister_action W_BuildTextEditorLister(workspace_vie
if(IsValid(&Action)) if(IsValid(&Action))
{ {
text_op Op = TextOpFromAction(Scratch.Arena, MakeString(Editor->ListerInput, Editor->ListerInputUsed), &Editor->ListerInputEditState, &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);
string Left = MakeString(Editor->ListerInput, Op.Range.Min); u64 NewStringSize = Left.Count + Right.Count + Op.ReplaceString.Count;
string Right = MakeString(Editor->ListerInput + Op.Range.Max, Editor->ListerInputUsed - Op.Range.Max); 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);
u64 NewStringSize = Left.Count + Right.Count + Op.ReplaceString.Count; Editor->ListerInputEditState.Cursor = Minimum(Op.NewCursor, Editor->ListerInputUsed);
char *NewString = PushArray(Scratch.Arena, char, NewStringSize); Editor->ListerInputEditState.Mark = Minimum(Op.NewMark, Editor->ListerInputUsed);
Copy(NewString, Left.Data, Left.Count); Platform_ConsumeEvent(UI_EventList(), Event);
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);
} }
} }
if(Event->Type == PlatformEvent_Press && (Event->Key == Key_Up || Event->Key == Key_Down))
{
SelectedItemDelta = Event->Key == Key_Up ? -1 : 1;
}
} }
} }
@ -506,7 +519,7 @@ static workspace_text_editor_lister_action W_BuildTextEditorLister(workspace_vie
UI_Padding(UI_Percent(1, 0)); UI_Padding(UI_Percent(1, 0));
UI_SetNextWidth(UI_TextContent(20, 1)); UI_SetNextWidth(UI_TextContent(20, 1));
if(UI_ButtonF("Open/Create").Clicked || Platform_KeyPress(UI_EventList(), Key_Return)) if(UI_ButtonF("Open/Create").Clicked || EnterPressed)
{ {
ListerAction.HasRequestedFile = true; ListerAction.HasRequestedFile = true;
ListerAction.Name = MakeString(Editor->ListerInput, Editor->ListerInputUsed); ListerAction.Name = MakeString(Editor->ListerInput, Editor->ListerInputUsed);
@ -514,15 +527,21 @@ static workspace_text_editor_lister_action W_BuildTextEditorLister(workspace_vie
} }
} }
s32 ListerCount = 0;
//- sixten: display "parent directory button" //- sixten: display "parent directory button"
s64 LastSlash = LastIndexOf(Editor->Path, '/'); s64 LastSlash = LastIndexOf(Editor->Path, '/');
if(LastSlash != -1) if(LastSlash != -1)
{ {
if(W_BuildTextEditorListerItem(StrLit("Parent Directory"), FontIcon_Reply)) 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->Path = Prefix(Editor->Path, LastSlash);
Editor->ListerInputUsed = 0; Editor->ListerInputUsed = 0;
Editor->SelectedItem = -1;
} }
ListerCount += 1;
} }
platform_file_info FileInfo; platform_file_info FileInfo;
platform_file_iter *FileIter; platform_file_iter *FileIter;
@ -537,11 +556,14 @@ static workspace_text_editor_lister_action W_BuildTextEditorLister(workspace_vie
{ {
if(FileInfo.IsDirectory) if(FileInfo.IsDirectory)
{ {
if(W_BuildTextEditorListerItem(FileInfo.Name, FontIcon_Folder)) if(W_BuildTextEditorListerItem(FileInfo.Name, FontIcon_Folder, Editor->SelectedItem == ListerCount, EnterPressed))
{ {
Editor->Path = PushFormat(View->Arena, "%S/%S", Editor->Path, FileInfo.Name); Editor->Path = PushFormat(View->Arena, "%S/%S", Editor->Path, FileInfo.Name);
Editor->ListerInputUsed = 0; 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;
} }
} }
} }
@ -554,15 +576,32 @@ static workspace_text_editor_lister_action W_BuildTextEditorLister(workspace_vie
{ {
if(!FileInfo.IsDirectory) if(!FileInfo.IsDirectory)
{ {
if(W_BuildTextEditorListerItem(FileInfo.Name, FontIcon_Document)) if(W_BuildTextEditorListerItem(FileInfo.Name, FontIcon_Document, Editor->SelectedItem == ListerCount, EnterPressed))
{ {
ListerAction.HasRequestedFile = true; ListerAction.HasRequestedFile = true;
Editor->SelectedItem = -1;
ListerAction.Name = PushString(View->Arena, FileInfo.Name); ListerAction.Name = PushString(View->Arena, FileInfo.Name);
ListerAction.Path = Editor->Path; 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); Platform.EndFileIter(FileIter);
} }
} }
@ -646,10 +685,15 @@ 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("")); b32 InFileListMode = AreEqual(Editor->FileName, StrLit(""));
if(InFileListMode) 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 //- sixten: build & handle file lister
workspace_text_editor_lister_action Action = W_BuildTextEditorLister(View, Editor); workspace_text_editor_lister_action Action = W_BuildTextEditorLister(View, Editor);
if(Action.HasRequestedFile) if(Action.HasRequestedFile)
@ -677,6 +721,8 @@ static void W_BuildTextEditor(workspace_view *View)
{ {
Editor->FileName = Action.Name; Editor->FileName = Action.Name;
Editor->FilePath = Action.Path; Editor->FilePath = Action.Path;
Editor->SelectedItem = -1;
} }
} }
} }

View File

@ -8,7 +8,7 @@
struct mutable_string struct mutable_string
{ {
memory_arena *Arena; arena *Arena;
string String; string String;
}; };
@ -54,7 +54,7 @@ struct workspace_text_editor_lister_action
struct workspace_view_text_editor struct workspace_view_text_editor
{ {
// sixten: processed text // sixten: processed text
memory_arena *ProcessingArena; arena *ProcessingArena;
token_array Tokens; token_array Tokens;
range1_s64_array Lines; range1_s64_array Lines;
compiled_scene Compiled; compiled_scene Compiled;
@ -72,7 +72,7 @@ struct workspace_view_text_editor
r32 FontSize; r32 FontSize;
// sixten: history // sixten: history
memory_arena *HistoryArena; arena *HistoryArena;
history_list History; history_list History;
history_node *SavePoint; history_node *SavePoint;
@ -90,6 +90,7 @@ struct workspace_view_text_editor
u8 ListerInput[256]; u8 ListerInput[256];
s32 ListerInputUsed; s32 ListerInputUsed;
text_edit_state ListerInputEditState; text_edit_state ListerInputEditState;
s32 SelectedItem;
}; };
//////////////////////////////// ////////////////////////////////
@ -102,13 +103,13 @@ static void MutableStringReplaceRange(mutable_string *String, string ReplaceStri
//////////////////////////////// ////////////////////////////////
//~ sixten: History & Undo Functions //~ sixten: History & Undo Functions
static history_entry HistoryEntry(memory_arena *Arena, string ReplaceString, range1_s64 Range); static history_entry HistoryEntry(arena *Arena, string ReplaceString, range1_s64 Range);
static void AppendToHistory(memory_arena *Arena, history_list *List, history_entry Forward, history_entry Backward); static void AppendToHistory(arena *Arena, history_list *List, history_entry Forward, history_entry Backward);
//////////////////////////////// ////////////////////////////////
//~ sixten: Workspace Text Editing Functions //~ sixten: Workspace Text Editing Functions
static workspace_text_data W_TextDataFromString(memory_arena *Arena, string Text); static workspace_text_data W_TextDataFromString(arena *Arena, string Text);
static void W_TextEditorApplyChanges(workspace_view_text_editor *Editor); static void W_TextEditorApplyChanges(workspace_view_text_editor *Editor);
static void W_SaveTextEditorToFile(workspace_view_text_editor *Editor); static void W_SaveTextEditorToFile(workspace_view_text_editor *Editor);
@ -116,7 +117,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); 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 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);

View File

@ -1,7 +1,7 @@
//- sixten: Views //- sixten: Views
inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel *Parent) inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel *Parent)
{ {
memory_arena *Arena = ArenaAllocate(Gigabytes(1)); 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->Type = Type;
@ -9,16 +9,6 @@ inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel
switch(View->Type) switch(View->Type)
{ {
case W_View_Editor:
{
View->Data = PushStruct(View->Arena, workspace_view_editor);
} break;
case W_View_CommandPalette:
{
View->Data = PushStruct(View->Arena, workspace_view_command_palette);
} break;
case W_View_Settings: case W_View_Settings:
{ {
View->Data = PushStruct(View->Arena, workspace_view_settings); View->Data = PushStruct(View->Arena, workspace_view_settings);
@ -29,24 +19,21 @@ inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel
View->Data = PushStruct(View->Arena, workspace_view_text_editor); View->Data = PushStruct(View->Arena, workspace_view_text_editor);
workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data; workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data;
Editor->ProcessingArena = ArenaAllocate(Gigabytes(1)); Editor->ProcessingArena = ArenaAlloc(Gigabytes(1));
Editor->Text = MutableStringAllocate(Gigabytes(1)); Editor->Text = MutableStringAllocate(Gigabytes(1));
Editor->HistoryArena = ArenaAllocate(Gigabytes(1)); Editor->HistoryArena = ArenaAlloc(Gigabytes(1));
SenDLLInit(&Editor->History.Sentinel); SenDLLInit(&Editor->History.Sentinel);
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_View_CharacterEditor:
{
View->Data = PushStruct(View->Arena, workspace_view_character_editor);
} break;
default: break; default: break;
} }
@ -93,7 +80,6 @@ inline string W_GetViewName(workspace_view *View)
switch(View->Type) switch(View->Type)
{ {
case W_View_Startup: { Result = StrLit("Welcome"); } break; case W_View_Startup: { Result = StrLit("Welcome"); } break;
case W_View_Editor: { Result = StrLit("Editor"); } break;
case W_View_Settings: { Result = StrLit("Settings"); } break; case W_View_Settings: { Result = StrLit("Settings"); } break;
case W_View_TextEditor: case W_View_TextEditor:
{ {
@ -116,184 +102,12 @@ inline string W_GetViewName(workspace_view *View)
} }
} break; } break;
case W_View_SceneView: { Result = StrLit("Scene View"); } break; case W_View_SceneView: { Result = StrLit("Scene View"); } break;
case W_View_CommandPalette: { Result = StrLit("Command Palette"); } break;
case W_View_CharacterEditor: { Result = StrLit("Character Editor"); } break;
} }
return(Result); return(Result);
} }
//- sixten: Builder code //- sixten: Builder code
static void W_ViewListerInputCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data)
{
workspace_view_command_palette *CommandPalette = (workspace_view_command_palette *)Data;
string ToCursor = MakeString(Box->String.Data, CommandPalette->ListerInputEditState.Cursor);
string ToMark = MakeString(Box->String.Data, CommandPalette->ListerInputEditState.Mark);
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
if(CommandPalette->ListerFieldSelected)
{
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 void W_BuildViewTypeLister(workspace_view *View)
{
workspace_view_command_palette *CommandPalette = (workspace_view_command_palette *)View->Data;
workspace *Workspace = W_GetState();
temporary_memory Scratch = GetScratch(0, 0);
UI_Size(UI_Percent(1, 1), UI_Percent(1, 1))
UI_Parent(UI_MakeBox(0, StrLit("")))
{
UI_Spacer(UI_Pixels(1.25, 1));
UI_CornerRadius(4)
UI_BackgroundColor(V4(0.5, 0.2, 0.3, 1.0))
UI_LayoutAxis(Axis2_X)
UI_Height(UI_Pixels(30, 1))
UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawDropShadow, "Workspace View Lister Header"))
{
UI_Spacer(UI_Pixels(5, 1));
UI_Width(UI_TextContent(10, 1)) UI_LabelF("Open View:");
UI_Spacer(UI_Pixels(15, 1));
// sixten: Input Field.
{
r32 SelectedTransition = AC_AnimateValueF(CommandPalette->ListerFieldSelected ? 1.0 : 0.0,
0, 0.125, "View Input Field %p", View);
v4 BorderColor = UI_TopBackgroundColor()*2;
BorderColor.w = SelectedTransition;
UI_SetNextBorderColor(BorderColor);
UI_SetNextBackgroundColor(LinearBlend(V4(0, 0, 0, 1), UI_TopBackgroundColor(), 0.5));
UI_SetNextWidth(UI_Percent(1, 0));
ui_box *InputBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
UI_BoxFlag_Clickable |
UI_BoxFlag_DrawBorder,
"View Type Lister Input");
UI_Parent(InputBox)
{
UI_SetNextWidth(UI_TextContent(15, 1));
ui_box *InputTextBox = UI_MakeBox(UI_BoxFlag_DrawText, StrLit("Workspace View Lister"));
InputTextBox->String = MakeString(CommandPalette->ListerInput, CommandPalette->ListerInputUsed);
UI_EquipBoxCustomDrawCallback(InputTextBox, W_ViewListerInputCallback, CommandPalette);
}
UI_Spacer(UI_Pixels(4, 1));
if(CommandPalette->ListerFieldSelected)
{
for(platform_event *Event = Workspace->EventList->First;
Event != 0;
Event = Event->Next)
{
if(Event->Type == PlatformEvent_Press || Event->Type == PlatformEvent_Text)
{
text_action Action = SingleLineTextActionFromEvent(Event);
if(IsValid(&Action))
{
text_op Op = TextOpFromAction(Scratch.Arena, MakeString(CommandPalette->ListerInput, CommandPalette->ListerInputUsed),
&CommandPalette->ListerInputEditState, &Action);
string Left = MakeString(CommandPalette->ListerInput, Op.Range.Min);
string Right = MakeString(CommandPalette->ListerInput + Op.Range.Max, CommandPalette->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);
CommandPalette->ListerInputUsed = Minimum(ArrayCount(CommandPalette->ListerInput), NewStringSize);
Copy(CommandPalette->ListerInput, NewString, CommandPalette->ListerInputUsed);
CommandPalette->ListerInputEditState.Cursor = Minimum(Op.NewCursor, CommandPalette->ListerInputUsed);
CommandPalette->ListerInputEditState.Mark = Minimum(Op.NewMark, CommandPalette->ListerInputUsed);
}
}
}
}
if(UI_SignalFromBox(InputBox).Pressed)
{
CommandPalette->ListerFieldSelected = true;
}
ui *UI = UI_GetState();
if(!(AreEqual(UI->Active, UI_EmptyKey()) || AreEqual(UI->Active, InputBox->Key)))
{
CommandPalette->ListerFieldSelected = false;
}
}
}
UI_Spacer(UI_Pixels(15, 1));
{
UI_SetNextCornerRadius(10);
UI_SetNextBackgroundColor(V4(0.15, 0.15, 0.15, 1.0));
UI_SetNextBorderColor(V4(0.35, 0.35, 0.35, 1.0));
UI_SetNextSize(UI_Percent(1, 1), UI_Pixels(100, 1));
UI_SetNextLayoutAxis(Axis2_Y);
ui_box *ButtonBox = UI_MakeBox(UI_BoxFlag_DrawBackground |
UI_BoxFlag_DrawBorder |
UI_BoxFlag_HotAnimation |
UI_BoxFlag_ActiveAnimation |
UI_BoxFlag_Clickable,
StrLit("Type Lister Box"));
UI_SignalFromBox(ButtonBox);
}
}
ReleaseScratch(Scratch);
}
static void W_BuildSettingsTabButton(workspace_view_settings *Settings, char *Name, workspace_settings_category Category) static void W_BuildSettingsTabButton(workspace_view_settings *Settings, char *Name, workspace_settings_category Category)
{ {
@ -442,8 +256,6 @@ static void W_BuildSettings(workspace_view *View)
UI_Spacer(UI_Pixels(30, 1)); UI_Spacer(UI_Pixels(30, 1));
W_BuildSettingsTabButton(Settings, "General", W_Settings_General); W_BuildSettingsTabButton(Settings, "General", W_Settings_General);
UI_Spacer(UI_Pixels(30, 1)); UI_Spacer(UI_Pixels(30, 1));
W_BuildSettingsTabButton(Settings, "Theme", W_Settings_Theme);
UI_Spacer(UI_Pixels(30, 1));
W_BuildSettingsTabButton(Settings, "Developer", W_Settings_Developer); W_BuildSettingsTabButton(Settings, "Developer", W_Settings_Developer);
UI_Spacer(UI_Pixels(150, 1)); UI_Spacer(UI_Pixels(150, 1));
@ -485,34 +297,6 @@ static void W_BuildSettings(workspace_view *View)
UI_Spacer(UI_Pixels(50, 1)); UI_Spacer(UI_Pixels(50, 1));
} }
if(!Category || (Category == W_Settings_Theme))
{
UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("Theme");
UI_SetNextSize(UI_Percent(1, 1), UI_Em(13, 1));
UI_Scroll(0, &Settings->ThemeScroll)
{
UI_Size(UI_Percent(1, 1), UI_Em(2, 1))
{
for(s32 Index = 0;
Index < 2;
++Index)
{
UI_ButtonF("Hello#%i", Index);
UI_ButtonF("Line#%i", Index);
UI_ButtonF("Paint#%i", Index);
UI_ButtonF("Color#%i", Index);
UI_ButtonF("Design#%i", Index);
UI_ButtonF("Address#%i", Index);
UI_ButtonF("Brightness#%i", Index);
}
}
}
UI_Spacer(UI_Pixels(50, 1));
}
if(!Category || (Category == W_Settings_Developer)) if(!Category || (Category == W_Settings_Developer))
{ {
UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("Developer"); UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("Developer");
@ -568,16 +352,6 @@ static void W_BuildView(workspace_view *View)
} }
} break; } break;
case W_View_CommandPalette:
{
W_BuildViewTypeLister(View);
} break;
case W_View_Editor:
{
Workspace_BuildEditor(View);
} break;
case W_View_Settings: case W_View_Settings:
{ {
W_BuildSettings(View); W_BuildSettings(View);
@ -592,11 +366,6 @@ static void W_BuildView(workspace_view *View)
{ {
W_BuildSceneView(View); W_BuildSceneView(View);
} break; } break;
case W_View_CharacterEditor:
{
W_BuildCharacterEditorView(View);
} break;
} }
} }

View File

@ -8,7 +8,7 @@
struct workspace_view struct workspace_view
{ {
memory_arena *Arena; arena *Arena;
enum workspace_view_type Type; enum workspace_view_type Type;
workspace_panel *Parent; workspace_panel *Parent;
@ -21,40 +21,15 @@ struct workspace_view
enum workspace_view_type enum workspace_view_type
{ {
W_View_Startup, W_View_Startup,
W_View_Editor,
W_View_CommandPalette,
W_View_Settings, W_View_Settings,
W_View_TextEditor, W_View_TextEditor,
W_View_SceneView, W_View_SceneView,
W_View_CharacterEditor,
};
struct workspace_view_editor
{
v2 Offset;
r32 ZoomLevel;
r32 Scale; // sixten(NOTE): Read-only, based on the zoom level
workspace_editor_node *FirstNode;
workspace_editor_node *LastNode;
workspace_editor_node *FirstFreeNode;
workspace_editor_node *LastFreeNode;
workspace_editor_lister_dropdown ListerDropdown;
};
struct workspace_view_command_palette
{
b32 ListerFieldSelected;
u8 ListerInput[128];
s32 ListerInputUsed;
text_edit_state ListerInputEditState;
}; };
enum workspace_settings_category enum workspace_settings_category
{ {
W_Settings_All, W_Settings_All,
W_Settings_General, W_Settings_General,
W_Settings_Theme,
W_Settings_Developer, W_Settings_Developer,
}; };
@ -65,9 +40,6 @@ struct workspace_view_settings
// sixten: General // sixten: General
b32 GeneralDropdownOpen; b32 GeneralDropdownOpen;
// sixten: Theme
r32 ThemeScroll;
}; };
//////////////////////////////// ////////////////////////////////

View File

@ -5,6 +5,10 @@
#include "vn_platform.h" #include "vn_platform.h"
#if W32_LINK_SINGLE
#include "vn.cpp"
#endif
#include "win32_main.h" #include "win32_main.h"
#include "win32_opengl.cpp" #include "win32_opengl.cpp"
@ -77,6 +81,17 @@ static PLATFORM_DECOMMIT(Win32_Decommit)
VirtualFree(Pointer, Size, MEM_DECOMMIT); VirtualFree(Pointer, Size, MEM_DECOMMIT);
} }
static PLATFORM_ALLOCATE(Win32_Allocate)
{
void *Result = VirtualAlloc(0, Size, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
return(Result);
}
static PLATFORM_DEALLOCATE(Win32_Deallocate)
{
VirtualFree(Pointer, 0, MEM_DECOMMIT|MEM_RELEASE);
}
static PLATFORM_OPEN_FILE(Win32_OpenFile) static PLATFORM_OPEN_FILE(Win32_OpenFile)
{ {
DWORD DesiredAccess = 0; DWORD DesiredAccess = 0;
@ -269,6 +284,7 @@ inline FILETIME Win32_GetLastWriteTime(char *Path)
return(Result); return(Result);
} }
#if !W32_LINK_SINGLE
static win32_loaded_code Win32_LoadCode(void) static win32_loaded_code Win32_LoadCode(void)
{ {
win32_loaded_code Code = {}; win32_loaded_code Code = {};
@ -317,6 +333,7 @@ static void Win32_UpdateCode(win32_loaded_code *Code)
Sleep(500); Sleep(500);
} }
} }
#endif
static PLATFORM_TOGGLE_FULLSCREEN(Win32_ToggleFullscreen) static PLATFORM_TOGGLE_FULLSCREEN(Win32_ToggleFullscreen)
{ {
@ -558,6 +575,7 @@ static LRESULT Win32_WindowCallback(HWND Window, UINT Message, WPARAM WParam, LP
else if(VKCode == VK_END) { Key = Key_End; } else if(VKCode == VK_END) { Key = Key_End; }
else if(VKCode == VK_BACK) { Key = Key_Backspace; } else if(VKCode == VK_BACK) { Key = Key_Backspace; }
else if(VKCode == VK_DELETE) { Key = Key_Delete; } else if(VKCode == VK_DELETE) { Key = Key_Delete; }
else if(VKCode == VK_ESCAPE) { Key = Key_Escape; }
if(Key != Key_Invalid) if(Key != Key_Invalid)
{ {
@ -744,7 +762,7 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
QueryPerformanceFrequency(&FrequencyQuery); QueryPerformanceFrequency(&FrequencyQuery);
State->PerformanceFrequency = FrequencyQuery.QuadPart; State->PerformanceFrequency = FrequencyQuery.QuadPart;
State->EventArena = ArenaAllocate(Gigabytes(1)); State->EventArena = ArenaAlloc(Gigabytes(1));
State->SleepIsGranular = (timeBeginPeriod(1) == TIMERR_NOERROR); State->SleepIsGranular = (timeBeginPeriod(1) == TIMERR_NOERROR);
} }
@ -759,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 - August 2023 Build", "vn - October 2023 Build",
WS_OVERLAPPEDWINDOW, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
@ -779,7 +797,9 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
vn_memory Memory = {}; vn_memory Memory = {};
Memory.PlatformAPI = Platform; Memory.PlatformAPI = Platform;
#if !W32_LINK_SINGLE
win32_loaded_code LoadedCode = Win32_LoadCode(); win32_loaded_code LoadedCode = Win32_LoadCode();
#endif
ShowWindow(Window, SW_SHOWNORMAL); ShowWindow(Window, SW_SHOWNORMAL);
@ -797,14 +817,18 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
// sixten: Update and render frame. // sixten: Update and render frame.
{ {
v2_r32 RenderDim = Win32_GetWindowDim(Window);
OpenGL_BeginFrame(&RenderCommands, RenderDim);
#if W32_LINK_SINGLE
VN_UpdateAndRender(&ThreadContext, &Memory, &Input, &RenderCommands);
#else
Win32_UpdateCode(&LoadedCode); Win32_UpdateCode(&LoadedCode);
OpenGL_BeginFrame(&RenderCommands, Win32_GetWindowDim(Window));
if(LoadedCode.IsValid) if(LoadedCode.IsValid)
{ {
LoadedCode.UpdateAndRender(&ThreadContext, &Memory, &Input, &RenderCommands); LoadedCode.UpdateAndRender(&ThreadContext, &Memory, &Input, &RenderCommands);
} }
#endif
b32 UseVSync = (Input.RefreshRate == 0); b32 UseVSync = (Input.RefreshRate == 0);
wglSwapIntervalEXT(UseVSync); wglSwapIntervalEXT(UseVSync);
@ -832,3 +856,10 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
return(0); return(0);
} }
#if VN_ASAN_ENABLED
int main(int ArgumentCount, char **Arguments)
{
return WinMain(GetModuleHandle(0), 0, 0, 0);
}
#endif

View File

@ -10,7 +10,7 @@ struct win32_state
HWND Window; HWND Window;
memory_arena *EventArena; arena *EventArena;
platform_event_list EventList; platform_event_list EventList;
char EXEPath[512]; char EXEPath[512];

View File

@ -1,6 +1,6 @@
Platform Platform
{ {
RefreshRate = 60; RefreshRate = 144;
} }
Dev Dev

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

View File

@ -6,4 +6,6 @@ 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;
} }

30
data/ddlc2.vns 100644
View File

@ -0,0 +1,30 @@
var monika = "Monika";
var arthur = "Arthur";
proc main
{
"hello, line, paint, color, design, address, brightness";
@monika(leaning) "Hi";
@arthur(normal) "Wasssap!";
@monika(leaning) "This is completely normal";
@monika(none);
@arthur(normal) "Wow, what a rude person";
@arthur(happy) "But hey! They left atleast!";
@arthur(none);
"Something inbetween!";
@monika(leaning) @arthur(happy) "BOOOO!";
"Gotcha'!";
@arthur(none) @monika(none);
jump main;
}

23
data/scene.vns 100644
View File

@ -0,0 +1,23 @@
var arthur = "Arthur";
var monika = "Monika";
proc main
{
@arthur(normal) "Welcome to the Scene Test!";
@arthur(happy) "Feel free to move around.";
branch
{
"No! Sooth me with your voice one more time."
{
@monika(leaning) "Really? Him?!?!";
@monika(leaning) "If you say so...";
@monika(none);
jump main;
}
"Okay!"
{
@arthur(none);
}
}
}

View File

@ -32,14 +32,14 @@ load_paths =
command_list = command_list =
{ {
{ {
.name = "build", .name = "build-win32",
.out = "*compilation*", .out = "*compilation*",
.footer_panel = true, .footer_panel = true,
.save_dirty_files = true, .save_dirty_files = true,
.cursor_at_end = false, .cursor_at_end = false,
.cmd = .cmd =
{ {
{ "build.bat", .os = "win" }, { "code\\build.bat", .os = "win" },
}, },
}, },
@ -67,7 +67,21 @@ command_list =
}, },
}, },
{
.name = "build-wasm",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
.cmd =
{
{ "code\\build_emscripten.bat", .os = "win" },
},
},
}; };
fkey_command[1] = "build-win32";
fkey_command[2] = "run"; fkey_command[2] = "run";
fkey_command[3] = "cloc"; fkey_command[3] = "cloc";
fkey_command[4] = "build-wasm";

View File

@ -1,6 +1,18 @@
[0] - Characters [0] - Characters
- Get characters names displaying while they talk V
////////////////////////////////
[1] - Environments & Time [1] - Environments & Time
[2] - Map & Notebook [2] - Map & Notebook
[3] - UI [3] - UI
- Keyboard Navigation
- Blinking Caret
[4] - Minigames [4] - Minigames
[5] - Rendering [5] - Rendering
- Check up on texture mappings, something seems to be weird
[6] - Data Submission