Rewrote the scripting language.

main
sixtenhugosson 2024-01-20 12:18:57 +01:00
parent 46c3075258
commit 8b2d19f096
64 changed files with 3361 additions and 3170 deletions

View File

@ -177,9 +177,8 @@ do { (Sentinel)->Next = (Sentinel); (Sentinel)->Prev = (Sentinel); } while(0)
(Element)->Prev->Next = (Element);
#define SenDLLRemove(Element)\
auto __Temp = (Element)->Next->Prev;\
(Element)->Next->Prev = (Element)->Prev->Next;\
(Element)->Prev->Next = __Temp;
(Element)->Next->Prev = (Element)->Prev;\
(Element)->Prev->Next = (Element)->Next;
#define SenDLLIsEmpty(Sentinel)\
((Sentinel)->Next==(Sentinel))

View File

@ -4,6 +4,7 @@
#define CORE_MATH_H
#include <math.h>
#include <float.h>
//- sixten: Constants
@ -374,14 +375,4 @@ inline v2_s64 DimOfRange(range2_s64 Range);
inline range2_s64 Intersection(range2_s64 A, range2_s64 B);
inline v2_s64 CornerFromRange(range2_s64 Range, corner Corner);
//- sixten: Shorthand base types
typedef v2_r32 v2;
typedef v3_r32 v3;
typedef v4_r32 v4;
#define V2(...) V2R32(__VA_ARGS__)
#define V3(...) V3R32(__VA_ARGS__)
#define V4(...) V4R32(__VA_ARGS__)
#endif //CORE_MATH_H

View File

@ -49,7 +49,7 @@ static void Fill(void *Dest, u8 Value, umm Count)
////////////////////////////////
//- sixten: Memory Arena Functions
static arena *ArenaAlloc(u64 Size, b32 Chaining)
static arena *ArenaAlloc(u64 Size, b32 Chaining, char *Format, ...)
{
arena *Arena = 0;
if(Chaining)
@ -113,7 +113,7 @@ static void *ArenaPushNoClear(arena *Arena, u64 Size)
arena *Target = Arena->Prev; // sixten: We always append to the end of the list.
if(Target->Position + Size + Arena->Align > Target->Size)
{
arena *New = ArenaAlloc(Arena->Size, true);
arena *New = ArenaAlloc(Arena->Size, true, "Chain");
New->NotFirst = true;
SenDLLInsertLast(Arena, New);
Target = New;

View File

@ -40,7 +40,7 @@ struct arena
u64 Align;
b32 Chaining;
b32 NotFirst;
arena *Next;
arena *Next;
arena *Prev;
};
@ -58,7 +58,7 @@ struct temp
////////////////////////////////
//- sixten: Memory Arena Functions
static arena *ArenaAlloc(u64 Size, b32 Chaining = false);
static arena *ArenaAlloc(u64 Size, b32 Chaining, char *Format, ...);
static void ArenaRelease(arena *Arena);
static void *ArenaPushNoClear(arena *Arena, u64 Size);
static void *ArenaPush(arena *Arena, u64 Size);

View File

@ -212,12 +212,15 @@ static string PushFormatVariadic(arena *Arena, char *Format, va_list Arguments)
string Result;
Result.Count = stbsp_vsnprintf(0, 0, Format, ArgumentsCopy);
va_end(ArgumentsCopy);
Result.Data = PushArrayNoClear(Arena, u8, Result.Count + 1);
Result.Data[Result.Count] = 0;
stbsp_vsnprintf((char *)Result.Data, (s32)Result.Count + 1, Format, Arguments);
stbsp_vsnprintf((char *)Result.Data, (s32)Result.Count + 1, Format, Arguments);
return(Result);
return(Result);
}
static string PushFormat(arena *Arena, char *Format, ...)

View File

@ -53,6 +53,7 @@ inline string MakeString(u8 *Data, s64 Count);
inline string MakeString(u8 *Start, u8 *End);
inline string MakeString(char *CString);
#define StrLit(String) MakeString((u8 *)String, (s64)(ArrayCount(String) - 1))
#define StrComp(String) {(s64)(ArrayCount(String) - 1), (u8 *)String}
inline string16 MakeString16(u16 *Data, s64 Count);

View File

@ -5,7 +5,7 @@ static thread_context AllocateThreadContext(void)
thread_context Context = {};
for(s64 ArenaIndex = 0; ArenaIndex < ArrayCount(Context.Arenas); ArenaIndex += 1)
{
Context.Arenas[ArenaIndex] = ArenaAlloc(Megabytes(2), true);
Context.Arenas[ArenaIndex] = ArenaAlloc(Megabytes(2), true, "Scratch Arena %i", ArenaIndex);
}
return(Context);
}
@ -26,13 +26,13 @@ static temp GetScratch(arena **Conflicts, u64 ConflictCount)
thread_context *Context = GetThreadContext();
for(u64 ArenaIndex = 0;
ArenaIndex < ArrayCount(Context->Arenas);
++ArenaIndex)
ArenaIndex < ArrayCount(Context->Arenas);
++ArenaIndex)
{
b32 FoundConflict = false;
for(u64 ConflictIndex = 0;
ConflictIndex < ConflictCount;
++ConflictIndex)
ConflictIndex < ConflictCount;
++ConflictIndex)
{
arena *Conflict = Conflicts[ConflictIndex];
if(Conflict == Context->Arenas[ArenaIndex])

View File

@ -31,3 +31,14 @@ char * AssetNameLUT[7] =
"MonikaLeaning",
};
r32 AssetScaleLUT[7] =
{
0,
0,
1,
1,
0.017,
0.017,
0.033,
};

View File

@ -4,6 +4,8 @@ extern bool AssetIsPermanentLUT[7];
extern char * AssetNameLUT[7];
extern r32 AssetScaleLUT[7];
typedef s32 asset_id;
enum
{

View File

@ -1,37 +0,0 @@
enum scene_operator
{
S_Operator_Invalid,
S_Operator_Not,
S_Operator_Equal,
S_Operator_Equals,
S_Operator_NotEquals,
S_Operator_GreaterThanOrEquals,
S_Operator_LessThanOrEquals,
S_Operator_Greater,
S_Operator_Less,
S_Operator_Add,
S_Operator_Minus,
S_Operator_Multiply,
S_Operator_Divide,
};
inline scene_operator S_OperatorFromString(string String)
{
scene_operator Result = S_Operator_Invalid;
if(0) {}
else if(AreEqual(String, StrLit("###"))) { Result = S_Operator_Invalid; }
else if(AreEqual(String, StrLit("!"))) { Result = S_Operator_Not; }
else if(AreEqual(String, StrLit("="))) { Result = S_Operator_Equal; }
else if(AreEqual(String, StrLit("=="))) { Result = S_Operator_Equals; }
else if(AreEqual(String, StrLit("!="))) { Result = S_Operator_NotEquals; }
else if(AreEqual(String, StrLit(">="))) { Result = S_Operator_GreaterThanOrEquals; }
else if(AreEqual(String, StrLit("<="))) { Result = S_Operator_LessThanOrEquals; }
else if(AreEqual(String, StrLit(">"))) { Result = S_Operator_Greater; }
else if(AreEqual(String, StrLit("<"))) { Result = S_Operator_Less; }
else if(AreEqual(String, StrLit("+"))) { Result = S_Operator_Add; }
else if(AreEqual(String, StrLit("-"))) { Result = S_Operator_Minus; }
else if(AreEqual(String, StrLit("*"))) { Result = S_Operator_Multiply; }
else if(AreEqual(String, StrLit("/"))) { Result = S_Operator_Divide; }
return(Result);
}

View File

@ -0,0 +1,164 @@
enum scene2_opcode
{
S2_Op_None, // does nothing (effectivly a nop)
S2_Op_Call, // stages runtime hook
S2_Op_Wait, // executes staged actions and waits for user input
S2_Op_Pop, // pops object from stack
S2_Op_PushBool, // pushes a boolean onto the stack
S2_Op_PushNumber, // pushes a number onto the stack
S2_Op_PushString, // pushes a string onto the stack
S2_Op_PushNil, // pushes `nil` onto the stack
S2_Op_PushVariable, // pushes a variable onto the stack
S2_Op_DuplicateStack, // duplicates the top N-most elements of the stack (specified in Arg as u64)
S2_Op_SetVariable, // pops the stack and stores the value in a variable
S2_Op_SetLocal, // defines a locally scoped variable
S2_Op_BeginBlock, // increases the variable stack depth
S2_Op_EndBlock, // decreases the variable stack depth
S2_Op_Jump, // performs a relative jump (specified in Arg as s64)
S2_Op_CondJump, // performs a relative jump (specified in Arg as s64) if the topmost element on the stack is non-zero
S2_Op_Add, // adds the two topmost elements of the stack
S2_Op_Subtract, // subtracts the topmost element of the stack by the second topmost element
S2_Op_Multiply, // multiplies the two topmost elements of the stack
S2_Op_Divide, // divides the topmost element of the stack by the second topmost element
S2_Op_Equals, //
S2_Op_Greater, //
S2_Op_Less, //
S2_Op_Not, // performs a not operation on the topmost element of the stack
S2_Op_Negate, // negates the topmost element of the stack
S2_Op_COUNT,
};
global read_only string S2_InstructionInfoLookup[] =
{
StrComp("None"),
StrComp("Call"),
StrComp("Wait"),
StrComp("Pop"),
StrComp("PushBool"),
StrComp("PushNumber"),
StrComp("PushString"),
StrComp("PushNil"),
StrComp("PushVariable"),
StrComp("DuplicateStack"),
StrComp("SetVariable"),
StrComp("SetLocal"),
StrComp("BeginBlock"),
StrComp("EndBlock"),
StrComp("Jump"),
StrComp("CondJump"),
StrComp("Add"),
StrComp("Subtract"),
StrComp("Multiply"),
StrComp("Divide"),
StrComp("Equals"),
StrComp("Greater"),
StrComp("Less"),
StrComp("Not"),
StrComp("Negate"),
};
global read_only string S2_InstructionNameLookup[] =
{
StrComp("does nothing (effectivly a nop)"),
StrComp("stages runtime hook"),
StrComp("executes staged actions and waits for user input"),
StrComp("pops object from stack"),
StrComp("pushes a boolean onto the stack"),
StrComp("pushes a number onto the stack"),
StrComp("pushes a string onto the stack"),
StrComp("pushes `nil` onto the stack"),
StrComp("pushes a variable onto the stack"),
StrComp("duplicates the top N-most elements of the stack (specified in Arg as u64)"),
StrComp("pops the stack and stores the value in a variable"),
StrComp("defines a locally scoped variable"),
StrComp("increases the variable stack depth"),
StrComp("decreases the variable stack depth"),
StrComp("performs a relative jump (specified in Arg as s64)"),
StrComp("performs a relative jump (specified in Arg as s64) if the topmost element on the stack is non-zero"),
StrComp("adds the two topmost elements of the stack"),
StrComp("subtracts the topmost element of the stack by the second topmost element"),
StrComp("multiplies the two topmost elements of the stack"),
StrComp("divides the topmost element of the stack by the second topmost element"),
StrComp(""),
StrComp(""),
StrComp(""),
StrComp("performs a not operation on the topmost element of the stack"),
StrComp("negates the topmost element of the stack"),
};
enum scene2_operator
{
S2_Operator_Invalid,
S2_Operator_Not,
S2_Operator_Equal,
S2_Operator_Equals,
S2_Operator_NotEquals,
S2_Operator_GreaterThanOrEquals,
S2_Operator_LessThanOrEquals,
S2_Operator_Greater,
S2_Operator_Less,
S2_Operator_Add,
S2_Operator_Minus,
S2_Operator_Multiply,
S2_Operator_Divide,
};
inline scene2_operator S2_OperatorFromString(string String)
{
scene2_operator Result = S2_Operator_Invalid;
if(0) {}
else if(AreEqual(String, StrLit("###"))) { Result = S2_Operator_Invalid; }
else if(AreEqual(String, StrLit("!"))) { Result = S2_Operator_Not; }
else if(AreEqual(String, StrLit("="))) { Result = S2_Operator_Equal; }
else if(AreEqual(String, StrLit("=="))) { Result = S2_Operator_Equals; }
else if(AreEqual(String, StrLit("!="))) { Result = S2_Operator_NotEquals; }
else if(AreEqual(String, StrLit(">="))) { Result = S2_Operator_GreaterThanOrEquals; }
else if(AreEqual(String, StrLit("<="))) { Result = S2_Operator_LessThanOrEquals; }
else if(AreEqual(String, StrLit(">"))) { Result = S2_Operator_Greater; }
else if(AreEqual(String, StrLit("<"))) { Result = S2_Operator_Less; }
else if(AreEqual(String, StrLit("+"))) { Result = S2_Operator_Add; }
else if(AreEqual(String, StrLit("-"))) { Result = S2_Operator_Minus; }
else if(AreEqual(String, StrLit("*"))) { Result = S2_Operator_Multiply; }
else if(AreEqual(String, StrLit("/"))) { Result = S2_Operator_Divide; }
return(Result);
}
static S2_CALL_FUNCTION(S2_Call_Stub); // does nothing
static S2_CALL_FUNCTION(S2_Call_StackSanity); // does checks that the stack is at a certain depth
static S2_CALL_FUNCTION(S2_Call_TextAppend); // pops a value and appends it to the textbox
static S2_CALL_FUNCTION(S2_Call_NewLine); // appends a newline to the textbox
static S2_CALL_FUNCTION(S2_Call_TextClear); // clears the textbox
static S2_CALL_FUNCTION(S2_Call_ProcSet); // sets the current proc
static S2_CALL_FUNCTION(S2_Call_CharacterSet); // sets the state of a character
static S2_CALL_FUNCTION(S2_Call_CharacterRemove); // removes a character
static S2_CALL_FUNCTION(S2_Call_CharacterSetTalking); // makes a character talking
static S2_CALL_FUNCTION(S2_Call_CharacterUnsetAllTalking); // makes no characters talking
global read_only scene2_call_function *S2_CallBindingLookup[] =
{
S2_Call_Stub,
S2_Call_StackSanity,
S2_Call_TextAppend,
S2_Call_NewLine,
S2_Call_TextClear,
S2_Call_ProcSet,
S2_Call_CharacterSet,
S2_Call_CharacterRemove,
S2_Call_CharacterSetTalking,
S2_Call_CharacterUnsetAllTalking,
};
global read_only string S2_CallNameLookup[] =
{
StrComp("none"),
StrComp("stack_sanity"),
StrComp("text_append"),
StrComp("text_newline"),
StrComp("text_clear"),
StrComp("proc_set"),
StrComp("ctr_set"),
StrComp("ctr_remove"),
StrComp("ctr_set_talking"),
StrComp("ctr_unset_all_talking"),
};

View File

@ -3,12 +3,12 @@ inline void UI_PushWidth(ui_size Element) { ui *UI = UI_GetState(); Ass
inline void UI_PushHeight(ui_size Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.HeightStackUsed + 1 < ArrayCount(UI->Stacks.HeightStack)); UI->Stacks.HeightStack[UI->Stacks.HeightStackUsed++] = Element; }
inline void UI_PushFixedX(r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.FixedXStackUsed + 1 < ArrayCount(UI->Stacks.FixedXStack)); UI->Stacks.FixedXStack[UI->Stacks.FixedXStackUsed++] = Element; }
inline void UI_PushFixedY(r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.FixedYStackUsed + 1 < ArrayCount(UI->Stacks.FixedYStack)); UI->Stacks.FixedYStack[UI->Stacks.FixedYStackUsed++] = Element; }
inline void UI_PushTextColor(v4 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.TextColorStackUsed + 1 < ArrayCount(UI->Stacks.TextColorStack)); UI->Stacks.TextColorStack[UI->Stacks.TextColorStackUsed++] = Element; }
inline void UI_PushBackgroundColor(v4 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.BackgroundColorStackUsed + 1 < ArrayCount(UI->Stacks.BackgroundColorStack)); UI->Stacks.BackgroundColorStack[UI->Stacks.BackgroundColorStackUsed++] = Element; }
inline void UI_PushBorderColor(v4 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.BorderColorStackUsed + 1 < ArrayCount(UI->Stacks.BorderColorStack)); UI->Stacks.BorderColorStack[UI->Stacks.BorderColorStackUsed++] = Element; }
inline void UI_PushTextColor(v4_r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.TextColorStackUsed + 1 < ArrayCount(UI->Stacks.TextColorStack)); UI->Stacks.TextColorStack[UI->Stacks.TextColorStackUsed++] = Element; }
inline void UI_PushBackgroundColor(v4_r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.BackgroundColorStackUsed + 1 < ArrayCount(UI->Stacks.BackgroundColorStack)); UI->Stacks.BackgroundColorStack[UI->Stacks.BackgroundColorStackUsed++] = Element; }
inline void UI_PushBorderColor(v4_r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.BorderColorStackUsed + 1 < ArrayCount(UI->Stacks.BorderColorStack)); UI->Stacks.BorderColorStack[UI->Stacks.BorderColorStackUsed++] = Element; }
inline void UI_PushBorderThickness(r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.BorderThicknessStackUsed + 1 < ArrayCount(UI->Stacks.BorderThicknessStack)); UI->Stacks.BorderThicknessStack[UI->Stacks.BorderThicknessStackUsed++] = Element; }
inline void UI_PushLayoutAxis(axis2 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.LayoutAxisStackUsed + 1 < ArrayCount(UI->Stacks.LayoutAxisStack)); UI->Stacks.LayoutAxisStack[UI->Stacks.LayoutAxisStackUsed++] = Element; }
inline void UI_PushCornerRadius(r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.CornerRadiusStackUsed + 1 < ArrayCount(UI->Stacks.CornerRadiusStack)); UI->Stacks.CornerRadiusStack[UI->Stacks.CornerRadiusStackUsed++] = Element; }
inline void UI_PushCornerRadii(v4_r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.CornerRadiiStackUsed + 1 < ArrayCount(UI->Stacks.CornerRadiiStack)); UI->Stacks.CornerRadiiStack[UI->Stacks.CornerRadiiStackUsed++] = Element; }
inline void UI_PushFont(font_id Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.FontStackUsed + 1 < ArrayCount(UI->Stacks.FontStack)); UI->Stacks.FontStack[UI->Stacks.FontStackUsed++] = Element; }
inline void UI_PushFontSize(r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.FontSizeStackUsed + 1 < ArrayCount(UI->Stacks.FontSizeStack)); UI->Stacks.FontSizeStack[UI->Stacks.FontSizeStackUsed++] = Element; }
inline void UI_PushOffsetX(r32 Element) { ui *UI = UI_GetState(); Assert(UI->Stacks.OffsetXStackUsed + 1 < ArrayCount(UI->Stacks.OffsetXStack)); UI->Stacks.OffsetXStack[UI->Stacks.OffsetXStackUsed++] = Element; }
@ -24,7 +24,7 @@ inline void UI_PopBackgroundColor(void) { ui *UI = UI_GetState(); Ass
inline void UI_PopBorderColor(void) { ui *UI = UI_GetState(); Assert(UI->Stacks.BorderColorStackUsed > 0); --UI->Stacks.BorderColorStackUsed; }
inline void UI_PopBorderThickness(void) { ui *UI = UI_GetState(); Assert(UI->Stacks.BorderThicknessStackUsed > 0); --UI->Stacks.BorderThicknessStackUsed; }
inline void UI_PopLayoutAxis(void) { ui *UI = UI_GetState(); Assert(UI->Stacks.LayoutAxisStackUsed > 0); --UI->Stacks.LayoutAxisStackUsed; }
inline void UI_PopCornerRadius(void) { ui *UI = UI_GetState(); Assert(UI->Stacks.CornerRadiusStackUsed > 0); --UI->Stacks.CornerRadiusStackUsed; }
inline void UI_PopCornerRadii(void) { ui *UI = UI_GetState(); Assert(UI->Stacks.CornerRadiiStackUsed > 0); --UI->Stacks.CornerRadiiStackUsed; }
inline void UI_PopFont(void) { ui *UI = UI_GetState(); Assert(UI->Stacks.FontStackUsed > 0); --UI->Stacks.FontStackUsed; }
inline void UI_PopFontSize(void) { ui *UI = UI_GetState(); Assert(UI->Stacks.FontSizeStackUsed > 0); --UI->Stacks.FontSizeStackUsed; }
inline void UI_PopOffsetX(void) { ui *UI = UI_GetState(); Assert(UI->Stacks.OffsetXStackUsed > 0); --UI->Stacks.OffsetXStackUsed; }
@ -35,12 +35,12 @@ inline void UI_SetNextWidth(ui_size Element) { ui *UI = UI_GetState(); UI_PushWi
inline void UI_SetNextHeight(ui_size Element) { ui *UI = UI_GetState(); UI_PushHeight(Element); UI->Stacks.AutoPopHeight = true; }
inline void UI_SetNextFixedX(r32 Element) { ui *UI = UI_GetState(); UI_PushFixedX(Element); UI->Stacks.AutoPopFixedX = true; }
inline void UI_SetNextFixedY(r32 Element) { ui *UI = UI_GetState(); UI_PushFixedY(Element); UI->Stacks.AutoPopFixedY = true; }
inline void UI_SetNextTextColor(v4 Element) { ui *UI = UI_GetState(); UI_PushTextColor(Element); UI->Stacks.AutoPopTextColor = true; }
inline void UI_SetNextBackgroundColor(v4 Element) { ui *UI = UI_GetState(); UI_PushBackgroundColor(Element); UI->Stacks.AutoPopBackgroundColor = true; }
inline void UI_SetNextBorderColor(v4 Element) { ui *UI = UI_GetState(); UI_PushBorderColor(Element); UI->Stacks.AutoPopBorderColor = true; }
inline void UI_SetNextTextColor(v4_r32 Element) { ui *UI = UI_GetState(); UI_PushTextColor(Element); UI->Stacks.AutoPopTextColor = true; }
inline void UI_SetNextBackgroundColor(v4_r32 Element) { ui *UI = UI_GetState(); UI_PushBackgroundColor(Element); UI->Stacks.AutoPopBackgroundColor = true; }
inline void UI_SetNextBorderColor(v4_r32 Element) { ui *UI = UI_GetState(); UI_PushBorderColor(Element); UI->Stacks.AutoPopBorderColor = true; }
inline void UI_SetNextBorderThickness(r32 Element) { ui *UI = UI_GetState(); UI_PushBorderThickness(Element); UI->Stacks.AutoPopBorderThickness = true; }
inline void UI_SetNextLayoutAxis(axis2 Element) { ui *UI = UI_GetState(); UI_PushLayoutAxis(Element); UI->Stacks.AutoPopLayoutAxis = true; }
inline void UI_SetNextCornerRadius(r32 Element) { ui *UI = UI_GetState(); UI_PushCornerRadius(Element); UI->Stacks.AutoPopCornerRadius = true; }
inline void UI_SetNextCornerRadii(v4_r32 Element) { ui *UI = UI_GetState(); UI_PushCornerRadii(Element); UI->Stacks.AutoPopCornerRadii = true; }
inline void UI_SetNextFont(font_id Element) { ui *UI = UI_GetState(); UI_PushFont(Element); UI->Stacks.AutoPopFont = true; }
inline void UI_SetNextFontSize(r32 Element) { ui *UI = UI_GetState(); UI_PushFontSize(Element); UI->Stacks.AutoPopFontSize = true; }
inline void UI_SetNextOffsetX(r32 Element) { ui *UI = UI_GetState(); UI_PushOffsetX(Element); UI->Stacks.AutoPopOffsetX = true; }
@ -51,12 +51,12 @@ inline ui_size UI_FirstWidth(void) { ui *UI = UI_GetState(); return(UI->Stacks.W
inline ui_size UI_FirstHeight(void) { ui *UI = UI_GetState(); return(UI->Stacks.HeightStack[0]); }
inline r32 UI_FirstFixedX(void) { ui *UI = UI_GetState(); return(UI->Stacks.FixedXStack[0]); }
inline r32 UI_FirstFixedY(void) { ui *UI = UI_GetState(); return(UI->Stacks.FixedYStack[0]); }
inline v4 UI_FirstTextColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.TextColorStack[0]); }
inline v4 UI_FirstBackgroundColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.BackgroundColorStack[0]); }
inline v4 UI_FirstBorderColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.BorderColorStack[0]); }
inline v4_r32 UI_FirstTextColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.TextColorStack[0]); }
inline v4_r32 UI_FirstBackgroundColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.BackgroundColorStack[0]); }
inline v4_r32 UI_FirstBorderColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.BorderColorStack[0]); }
inline r32 UI_FirstBorderThickness(void) { ui *UI = UI_GetState(); return(UI->Stacks.BorderThicknessStack[0]); }
inline axis2 UI_FirstLayoutAxis(void) { ui *UI = UI_GetState(); return(UI->Stacks.LayoutAxisStack[0]); }
inline r32 UI_FirstCornerRadius(void) { ui *UI = UI_GetState(); return(UI->Stacks.CornerRadiusStack[0]); }
inline v4_r32 UI_FirstCornerRadii(void) { ui *UI = UI_GetState(); return(UI->Stacks.CornerRadiiStack[0]); }
inline font_id UI_FirstFont(void) { ui *UI = UI_GetState(); return(UI->Stacks.FontStack[0]); }
inline r32 UI_FirstFontSize(void) { ui *UI = UI_GetState(); return(UI->Stacks.FontSizeStack[0]); }
inline r32 UI_FirstOffsetX(void) { ui *UI = UI_GetState(); return(UI->Stacks.OffsetXStack[0]); }
@ -67,12 +67,12 @@ inline ui_size UI_TopWidth(void) { ui *UI = UI_GetState(); return(UI->Stacks.Wid
inline ui_size UI_TopHeight(void) { ui *UI = UI_GetState(); return(UI->Stacks.HeightStack[UI->Stacks.HeightStackUsed - 1]); }
inline r32 UI_TopFixedX(void) { ui *UI = UI_GetState(); return(UI->Stacks.FixedXStack[UI->Stacks.FixedXStackUsed - 1]); }
inline r32 UI_TopFixedY(void) { ui *UI = UI_GetState(); return(UI->Stacks.FixedYStack[UI->Stacks.FixedYStackUsed - 1]); }
inline v4 UI_TopTextColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.TextColorStack[UI->Stacks.TextColorStackUsed - 1]); }
inline v4 UI_TopBackgroundColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.BackgroundColorStack[UI->Stacks.BackgroundColorStackUsed - 1]); }
inline v4 UI_TopBorderColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.BorderColorStack[UI->Stacks.BorderColorStackUsed - 1]); }
inline v4_r32 UI_TopTextColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.TextColorStack[UI->Stacks.TextColorStackUsed - 1]); }
inline v4_r32 UI_TopBackgroundColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.BackgroundColorStack[UI->Stacks.BackgroundColorStackUsed - 1]); }
inline v4_r32 UI_TopBorderColor(void) { ui *UI = UI_GetState(); return(UI->Stacks.BorderColorStack[UI->Stacks.BorderColorStackUsed - 1]); }
inline r32 UI_TopBorderThickness(void) { ui *UI = UI_GetState(); return(UI->Stacks.BorderThicknessStack[UI->Stacks.BorderThicknessStackUsed - 1]); }
inline axis2 UI_TopLayoutAxis(void) { ui *UI = UI_GetState(); return(UI->Stacks.LayoutAxisStack[UI->Stacks.LayoutAxisStackUsed - 1]); }
inline r32 UI_TopCornerRadius(void) { ui *UI = UI_GetState(); return(UI->Stacks.CornerRadiusStack[UI->Stacks.CornerRadiusStackUsed - 1]); }
inline v4_r32 UI_TopCornerRadii(void) { ui *UI = UI_GetState(); return(UI->Stacks.CornerRadiiStack[UI->Stacks.CornerRadiiStackUsed - 1]); }
inline font_id UI_TopFont(void) { ui *UI = UI_GetState(); return(UI->Stacks.FontStack[UI->Stacks.FontStackUsed - 1]); }
inline r32 UI_TopFontSize(void) { ui *UI = UI_GetState(); return(UI->Stacks.FontSizeStack[UI->Stacks.FontSizeStackUsed - 1]); }
inline r32 UI_TopOffsetX(void) { ui *UI = UI_GetState(); return(UI->Stacks.OffsetXStack[UI->Stacks.OffsetXStackUsed - 1]); }
@ -88,7 +88,7 @@ inline platform_cursor UI_TopHoverCursor(void) { ui *UI = UI_GetState(); return(
#define UI_BorderColor(Element) DeferLoop(UI_PushBorderColor(Element), UI_PopBorderColor())
#define UI_BorderThickness(Element) DeferLoop(UI_PushBorderThickness(Element), UI_PopBorderThickness())
#define UI_LayoutAxis(Element) DeferLoop(UI_PushLayoutAxis(Element), UI_PopLayoutAxis())
#define UI_CornerRadius(Element) DeferLoop(UI_PushCornerRadius(Element), UI_PopCornerRadius())
#define UI_CornerRadii(Element) DeferLoop(UI_PushCornerRadii(Element), UI_PopCornerRadii())
#define UI_Font(Element) DeferLoop(UI_PushFont(Element), UI_PopFont())
#define UI_FontSize(Element) DeferLoop(UI_PushFontSize(Element), UI_PopFontSize())
#define UI_OffsetX(Element) DeferLoop(UI_PushOffsetX(Element), UI_PopOffsetX())
@ -108,7 +108,7 @@ Assert(UI->Stacks.BackgroundColorStackUsed > 0); Box->BackgroundColor = UI
Assert(UI->Stacks.BorderColorStackUsed > 0); Box->BorderColor = UI->Stacks.BorderColorStack[UI->Stacks.BorderColorStackUsed - 1]; if(UI->Stacks.AutoPopBorderColor) { UI_PopBorderColor(); UI->Stacks.AutoPopBorderColor = false; }
Assert(UI->Stacks.BorderThicknessStackUsed > 0); Box->BorderThickness = UI->Stacks.BorderThicknessStack[UI->Stacks.BorderThicknessStackUsed - 1]; if(UI->Stacks.AutoPopBorderThickness) { UI_PopBorderThickness(); UI->Stacks.AutoPopBorderThickness = false; }
Assert(UI->Stacks.LayoutAxisStackUsed > 0); Box->LayoutAxis = UI->Stacks.LayoutAxisStack[UI->Stacks.LayoutAxisStackUsed - 1]; if(UI->Stacks.AutoPopLayoutAxis) { UI_PopLayoutAxis(); UI->Stacks.AutoPopLayoutAxis = false; }
Assert(UI->Stacks.CornerRadiusStackUsed > 0); Box->CornerRadius = UI->Stacks.CornerRadiusStack[UI->Stacks.CornerRadiusStackUsed - 1]; if(UI->Stacks.AutoPopCornerRadius) { UI_PopCornerRadius(); UI->Stacks.AutoPopCornerRadius = false; }
Assert(UI->Stacks.CornerRadiiStackUsed > 0); Box->CornerRadii = UI->Stacks.CornerRadiiStack[UI->Stacks.CornerRadiiStackUsed - 1]; if(UI->Stacks.AutoPopCornerRadii) { UI_PopCornerRadii(); UI->Stacks.AutoPopCornerRadii = false; }
Assert(UI->Stacks.FontStackUsed > 0); Box->Font = UI->Stacks.FontStack[UI->Stacks.FontStackUsed - 1]; if(UI->Stacks.AutoPopFont) { UI_PopFont(); UI->Stacks.AutoPopFont = false; }
Assert(UI->Stacks.FontSizeStackUsed > 0); Box->FontSize = UI->Stacks.FontSizeStack[UI->Stacks.FontSizeStackUsed - 1]; if(UI->Stacks.AutoPopFontSize) { UI_PopFontSize(); UI->Stacks.AutoPopFontSize = false; }
Assert(UI->Stacks.OffsetXStackUsed > 0); Box->Offset.x = UI->Stacks.OffsetXStack[UI->Stacks.OffsetXStackUsed - 1]; if(UI->Stacks.AutoPopOffsetX) { UI_PopOffsetX(); UI->Stacks.AutoPopOffsetX = false; }

View File

@ -5,12 +5,12 @@ ui_size WidthStack[64]; s32 WidthStackUsed; b32 AutoPopWidth;
ui_size HeightStack[64]; s32 HeightStackUsed; b32 AutoPopHeight;
r32 FixedXStack[64]; s32 FixedXStackUsed; b32 AutoPopFixedX;
r32 FixedYStack[64]; s32 FixedYStackUsed; b32 AutoPopFixedY;
v4 TextColorStack[64]; s32 TextColorStackUsed; b32 AutoPopTextColor;
v4 BackgroundColorStack[64]; s32 BackgroundColorStackUsed; b32 AutoPopBackgroundColor;
v4 BorderColorStack[64]; s32 BorderColorStackUsed; b32 AutoPopBorderColor;
v4_r32 TextColorStack[64]; s32 TextColorStackUsed; b32 AutoPopTextColor;
v4_r32 BackgroundColorStack[64]; s32 BackgroundColorStackUsed; b32 AutoPopBackgroundColor;
v4_r32 BorderColorStack[64]; s32 BorderColorStackUsed; b32 AutoPopBorderColor;
r32 BorderThicknessStack[64]; s32 BorderThicknessStackUsed; b32 AutoPopBorderThickness;
axis2 LayoutAxisStack[64]; s32 LayoutAxisStackUsed; b32 AutoPopLayoutAxis;
r32 CornerRadiusStack[64]; s32 CornerRadiusStackUsed; b32 AutoPopCornerRadius;
v4_r32 CornerRadiiStack[64]; s32 CornerRadiiStackUsed; b32 AutoPopCornerRadii;
font_id FontStack[64]; s32 FontStackUsed; b32 AutoPopFont;
r32 FontSizeStack[64]; s32 FontSizeStackUsed; b32 AutoPopFontSize;
r32 OffsetXStack[64]; s32 OffsetXStackUsed; b32 AutoPopOffsetX;

View File

@ -131,9 +131,9 @@ static RENDER_FILL_REGION(OpenGL_FillRegion)
glBindTexture(GL_TEXTURE_2D, Texture.ID);
glTexSubImage2D(GL_TEXTURE_2D, 0,
DestP.x, DestP.y, DestDim.x, DestDim.y,
OpenGL_InternalFormatFromTextureFormat(Texture.Format),
GL_UNSIGNED_BYTE, Data);
DestP.x, DestP.y, DestDim.x, DestDim.y,
OpenGL_InternalFormatFromTextureFormat(Texture.Format),
GL_UNSIGNED_BYTE, Data);
glBindTexture(GL_TEXTURE_2D, 0);
}
@ -358,8 +358,8 @@ Out_Color = Color*TextureFactor*BorderFactor*SDFFactor;
temp Scratch = GetScratch(0, 0);
for(s32 TextureIndex = 0;
TextureIndex < MAX_BOUND_TEXTURES;
++TextureIndex)
TextureIndex < MAX_BOUND_TEXTURES;
++TextureIndex)
{
string Name = PushFormat(Scratch.Arena, "TextureSamplers[%i]", TextureIndex);
s32 Location = glGetUniformLocation(Program.ID, (char *)Name.Data);
@ -381,7 +381,7 @@ static instanced_quad_program OpenGL_CompileInstacedQuadProgram(void)
in v4 In_Source;
in s32 In_TextureIndex;
in u32 In_Color[4];
in r32 In_CornerRadius;
in r32 In_CornerRadius[4];
in r32 In_EdgeSoftness;
in r32 In_BorderThickness;
)GLSL"
@ -421,7 +421,7 @@ Color.r = r32((ColorData >> 24) & 255u)/255.0;
Color.b = r32((ColorData >> 8) & 255u)/255.0;
Color.a = r32((ColorData >> 0) & 255u)/255.0;
CornerRadius = In_CornerRadius;
CornerRadius = In_CornerRadius[gl_VertexID];
EdgeSoftness = In_EdgeSoftness;
BorderThickness = In_BorderThickness;
@ -457,10 +457,14 @@ return(Result);
void main()
{
r32 SDFFactor = 1;
r32 SoftnessPadding = Max(0, EdgeSoftness*2-1);
if(EdgeSoftness != 0 || CornerRadius != 0)
{
r32 Dist = RoundedRect(DestP, DestCenter, DestHalfSize - SoftnessPadding, CornerRadius);
r32 SDFFactor = 1 - smoothstep(0, 2*EdgeSoftness, Dist);
SDFFactor = 1 - smoothstep(0, 2*EdgeSoftness, Dist);
}
r32 BorderFactor = 1;
if(BorderThickness != 0)
@ -476,7 +480,7 @@ BorderFactor = smoothstep(0, 2*EdgeSoftness, InsideDist);
}
v4 TextureFactor = texture(TextureSamplers[TextureIndex], SourceP);
Out_Color = Color*SDFFactor*BorderFactor*TextureFactor;
Out_Color = Color*TextureFactor*SDFFactor*BorderFactor;
}
)GLSL";
@ -491,7 +495,10 @@ Out_Color = Color*SDFFactor*BorderFactor*TextureFactor;
Program.ColorID[1] = glGetAttribLocation(Program.ID, "In_Color[1]");
Program.ColorID[2] = glGetAttribLocation(Program.ID, "In_Color[2]");
Program.ColorID[3] = glGetAttribLocation(Program.ID, "In_Color[3]");
Program.CornerRadiusID = glGetAttribLocation(Program.ID, "In_CornerRadius");
Program.CornerRadiusID[0] = glGetAttribLocation(Program.ID, "In_CornerRadius[0]");
Program.CornerRadiusID[1] = glGetAttribLocation(Program.ID, "In_CornerRadius[1]");
Program.CornerRadiusID[2] = glGetAttribLocation(Program.ID, "In_CornerRadius[2]");
Program.CornerRadiusID[3] = glGetAttribLocation(Program.ID, "In_CornerRadius[3]");
Program.EdgeSoftnessID = glGetAttribLocation(Program.ID, "In_EdgeSoftness");
Program.BorderThicknessID = glGetAttribLocation(Program.ID, "In_BorderThickness");
@ -500,8 +507,8 @@ Out_Color = Color*SDFFactor*BorderFactor*TextureFactor;
temp Scratch = GetScratch(0, 0);
for(s32 TextureIndex = 0;
TextureIndex < MAX_BOUND_TEXTURES;
++TextureIndex)
TextureIndex < MAX_BOUND_TEXTURES;
++TextureIndex)
{
string Name = PushFormat(Scratch.Arena, "TextureSamplers[%i]", TextureIndex);
s32 Location = glGetUniformLocation(Program.ID, (char *)Name.Data);
@ -583,7 +590,10 @@ static void OpenGL_BeginProgram(instanced_quad_program *Program)
OpenGL_EnableIntegerVertexAttribute(Program->ColorID[1], 1, GL_UNSIGNED_INT, instanced_quad, Color[1]);
OpenGL_EnableIntegerVertexAttribute(Program->ColorID[2], 1, GL_UNSIGNED_INT, instanced_quad, Color[2]);
OpenGL_EnableIntegerVertexAttribute(Program->ColorID[3], 1, GL_UNSIGNED_INT, instanced_quad, Color[3]);
OpenGL_EnableFloatVertexAttribute(Program->CornerRadiusID, 1, GL_FLOAT, instanced_quad, CornerRadius);
OpenGL_EnableFloatVertexAttribute(Program->CornerRadiusID[0], 1, GL_FLOAT, instanced_quad, CornerRadius[0]);
OpenGL_EnableFloatVertexAttribute(Program->CornerRadiusID[1], 1, GL_FLOAT, instanced_quad, CornerRadius[1]);
OpenGL_EnableFloatVertexAttribute(Program->CornerRadiusID[2], 1, GL_FLOAT, instanced_quad, CornerRadius[2]);
OpenGL_EnableFloatVertexAttribute(Program->CornerRadiusID[3], 1, GL_FLOAT, instanced_quad, CornerRadius[3]);
OpenGL_EnableFloatVertexAttribute(Program->EdgeSoftnessID, 1, GL_FLOAT, instanced_quad, EdgeSoftness);
OpenGL_EnableFloatVertexAttribute(Program->BorderThicknessID, 1, GL_FLOAT, instanced_quad, BorderThickness);
}
@ -597,7 +607,10 @@ static void OpenGL_EndProgram(instanced_quad_program *Program)
OpenGL_DisableVertexAttribute(Program->ColorID[1]);
OpenGL_DisableVertexAttribute(Program->ColorID[2]);
OpenGL_DisableVertexAttribute(Program->ColorID[3]);
OpenGL_DisableVertexAttribute(Program->CornerRadiusID);
OpenGL_DisableVertexAttribute(Program->CornerRadiusID[0]);
OpenGL_DisableVertexAttribute(Program->CornerRadiusID[1]);
OpenGL_DisableVertexAttribute(Program->CornerRadiusID[2]);
OpenGL_DisableVertexAttribute(Program->CornerRadiusID[3]);
OpenGL_DisableVertexAttribute(Program->EdgeSoftnessID);
OpenGL_DisableVertexAttribute(Program->BorderThicknessID);
@ -669,7 +682,7 @@ static opengl_context OpenGL_SetupContext(vn_render_commands *RenderCommands, um
return(Context);
}
static void OpenGL_BeginFrame(vn_render_commands *RenderCommands, v2 RenderDim)
static void OpenGL_BeginFrame(vn_render_commands *RenderCommands, v2_r32 RenderDim)
{
RenderCommands->PushBufferAt = RenderCommands->PushBufferBase;
#if VN_USE_INSTANCING
@ -705,8 +718,13 @@ static void OpenGL_EndFrame(opengl_context *Context, vn_render_commands *RenderC
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, IndexSize, IndexData);
#endif
glBindBuffer(GL_ARRAY_BUFFER, Context->InstancedQuadBuffer);
OpenGL_BeginProgram(&Context->InstancedQuadProgram);
glUniform2f(Context->InstancedQuadProgram.UniformResolutionLocation,
RenderCommands->RenderDim.x, RenderCommands->RenderDim.y);
for(u8 *PushBufferAt = RenderCommands->PushBufferBase;
PushBufferAt < RenderCommands->PushBufferAt;)
PushBufferAt < RenderCommands->PushBufferAt;)
{
render_command_header *Header = (render_command_header *)PushBufferAt;
PushBufferAt += sizeof(*Header);
@ -731,27 +749,20 @@ static void OpenGL_EndFrame(opengl_context *Context, vn_render_commands *RenderC
render_texture_mapping *Mapping = &Command->Mapping;
for(s32 TextureIndex = 0;
TextureIndex < Mapping->TexturesUsed;
++TextureIndex)
TextureIndex < Mapping->TexturesUsed;
++TextureIndex)
{
opengl_texture Texture = OpenGL_TextureFromHandle(Mapping->Textures[TextureIndex]);
glActiveTexture(GL_TEXTURE0 + TextureIndex);
glBindTexture(GL_TEXTURE_2D, Texture.ID);
}
glBindBuffer(GL_ARRAY_BUFFER, Context->InstancedQuadBuffer);
void *VertexData = RenderCommands->InstancedQuadBase+Command->QuadBufferIndex;
umm VertexSize = Command->QuadCount*sizeof(instanced_quad);
glBufferSubData(GL_ARRAY_BUFFER, 0, VertexSize, VertexData);
OpenGL_BeginProgram(&Context->InstancedQuadProgram);
glUniform2f(Context->InstancedQuadProgram.UniformResolutionLocation,
RenderCommands->RenderDim.x, RenderCommands->RenderDim.y);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, Command->QuadCount);
OpenGL_EndProgram(&Context->InstancedQuadProgram);
glBindTexture(GL_TEXTURE_2D, 0);
} break;
@ -782,13 +793,13 @@ static void OpenGL_EndFrame(opengl_context *Context, vn_render_commands *RenderC
OpenGL_BeginProgram(&Context->QuadProgram);
glUniform2f(Context->QuadProgram.UniformResolutionLocation,
RenderCommands->RenderDim.x, RenderCommands->RenderDim.y);
RenderCommands->RenderDim.x, RenderCommands->RenderDim.y);
render_texture_mapping *Mapping = &Command->Mapping;
for(s32 TextureIndex = 0;
TextureIndex < Mapping->TexturesUsed;
++TextureIndex)
TextureIndex < Mapping->TexturesUsed;
++TextureIndex)
{
opengl_texture Texture = OpenGL_TextureFromHandle(Mapping->Textures[TextureIndex]);
glActiveTexture(GL_TEXTURE0 + TextureIndex);
@ -807,5 +818,7 @@ static void OpenGL_EndFrame(opengl_context *Context, vn_render_commands *RenderC
}
}
OpenGL_EndProgram(&Context->InstancedQuadProgram);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}

View File

@ -38,7 +38,7 @@ struct instanced_quad_program
u32 SourceID;
u32 TextureIndexID;
u32 ColorID[4];
u32 CornerRadiusID;
u32 CornerRadiusID[4];
u32 EdgeSoftnessID;
u32 BorderThicknessID;

View File

@ -25,7 +25,7 @@ global debug_settings *DEBUG_DebugSettings = 0;
#include "vn_text_op.h"
#include "vn_ui.h"
#include "vn_ui_utils.h"
#include "vn_scene.h"
#include "vn_scene2.h"
#include "vn_scene_view.h"
#include "vn_animation_curve.h"
#include "vn_theme_dark.h"
@ -47,7 +47,7 @@ global vn_render_commands *GlobalRenderCommands = 0;
#include "vn_ui.cpp"
#include "vn_ui_utils.cpp"
#include "vn_animation_curve.cpp"
#include "vn_scene.cpp"
#include "vn_scene2.cpp"
#include "vn_scene_view.cpp"
#if VN_INTERNAL
@ -70,8 +70,6 @@ struct vn_state
animation_curve_state AnimationCurveState;
b32 EditorMode;
render_handle BackgroundTexture;
scene_view SceneView;
#if VN_INTERNAL
@ -95,20 +93,18 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
//- sixten: initialize application state
if(!Memory->State)
{
arena *Arena = ArenaAlloc(Kilobytes(24), true);
arena *Arena = ArenaAlloc(Kilobytes(24), true, "VN State Arena");
State = Memory->State = PushStruct(Arena, vn_state);
State->Arena = Arena;
State->FrameArena = ArenaAlloc(Kilobytes(1), true);
State->FrameArena = ArenaAlloc(Kilobytes(1), true, "VN Frame Arena");
State->GlyphAtlas = CreateGlyphAtlas(RenderCommands);
State->GlyphAtlas = F_CreateGlyphAtlas(RenderCommands, 2048, 128);
State->Config = CreateConfig();
//- sixten: load assets
State->Assets.AllocateTexture = RenderCommands->AllocateTexture;
LoadPermanentAssets(&State->Assets);
State->BackgroundTexture = TextureFromAssetID(AssetID_DemoBackground);
//- sixten: setup config binds and load current config
{
Config_BindS32(State->Config, StrLit("Platform/RefreshRate"), &Input->RefreshRate, 60);
@ -125,28 +121,21 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
Config_ReadFile(State->Config, StrLit("config.vn"));
}
scene_view *SceneView = &State->SceneView;
SV_Init(SceneView, State->Arena);
//- sixten: load startup scene
temp Scratch = GetScratch();
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, StrLit("data/scene.vns"));
compiled_scene Scene = S_ScriptFromText(Scratch.Arena, SceneInput);
SV_SetCurrentSource(&Scene);
ReleaseScratch(Scratch);
SceneView->TestHappy = TextureFromAssetID(AssetID_ArthurHappy);
SceneView->TestNormal = TextureFromAssetID(AssetID_ArthurNormal);
SceneView->MonikaLeaning = TextureFromAssetID(AssetID_MonikaLeaning);
SceneView->BackgroundTexture = State->BackgroundTexture;
SV_Init(&State->SceneView);
UI_Init(&State->UI);
AC_Init(&State->AnimationCurveState);
#if VN_INTERNAL
W_Init(&State->Workspace);
#endif
//- sixten: load startup scene
temp Scratch = GetScratch();
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, Platform_ReadEntireFile(Scratch.Arena, StrLit("data/while_test.vns")));
SV_SetCurrentSource(&Scene);
ReleaseScratch(Scratch);
return;
}
@ -208,7 +197,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
//- sixten: render the frame
{
render_group Group = BeginRenderGroup(RenderCommands);
PushClear(&Group, V3(0.1, 0.1, 0.1));
PushClear(&Group, V3R32(0.1, 0.1, 0.1));
UI_RenderFrame(&Group, State->GlyphAtlas);
@ -216,17 +205,17 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
r32 DEBUGDisplayOffsetY = 20;
if(DEBUG_DebugSettings->ListHotAndActive)
{
PushText(&Group, State->GlyphAtlas, Font_Regular, V2(5, RenderCommands->RenderDim.y - DEBUGDisplayOffsetY), 15, Color_Grey,
PushText(&Group, State->GlyphAtlas, Font_Regular, V2R32(5, RenderCommands->RenderDim.y - DEBUGDisplayOffsetY), 15, Color_Grey,
PushFormat(State->UI.FrameArena, "Hot: %S:%llu", UI_BoxStringFromKey(UI_HotKey()), UI_HotKey()));
DEBUGDisplayOffsetY += 20;
PushText(&Group, State->GlyphAtlas, Font_Regular, V2(5, RenderCommands->RenderDim.y - DEBUGDisplayOffsetY), 15, Color_Grey,
PushText(&Group, State->GlyphAtlas, Font_Regular, V2R32(5, RenderCommands->RenderDim.y - DEBUGDisplayOffsetY), 15, Color_Grey,
PushFormat(State->UI.FrameArena, "Active: %S:%llu", UI_BoxStringFromKey(UI_ActiveKey()), UI_ActiveKey()));
DEBUGDisplayOffsetY += 20;
}
if(DEBUG_DebugSettings->RenderFPSCounter)
{
PushText(&Group, State->GlyphAtlas, Font_Regular, V2(5, RenderCommands->RenderDim.y - DEBUGDisplayOffsetY), 15, Color_Grey,
PushText(&Group, State->GlyphAtlas, Font_Regular, V2R32(5, RenderCommands->RenderDim.y - DEBUGDisplayOffsetY), 15, Color_Grey,
PushFormat(State->UI.FrameArena, "FPS: %.2f", 1.0f/Input->dtForFrame));
DEBUGDisplayOffsetY += 20;

View File

@ -15,7 +15,7 @@ inline void AC_SetState(animation_curve_state *State)
static void AC_Init(animation_curve_state *State)
{
State->Arena = ArenaAlloc(Kilobytes(32), true);
State->Arena = ArenaAlloc(Kilobytes(32), true, "Animation Curve State Arena");
}
inline animation_curve_key AC_GenerateKeyFromString(string String)
@ -37,8 +37,8 @@ static animation_curve_entry *AC_GetEntryByKey(animation_curve_key Key, r32 Init
animation_curve_entry *Result = 0;
for(animation_curve_entry *Entry = Bucket->First;
Entry != 0;
Entry = Entry->Next)
Entry != 0;
Entry = Entry->Next)
{
if(AreEqual(Entry->Key, Key))
{
@ -91,6 +91,9 @@ inline r32 AC_AnimateValueDirect(r32 Target, r32 Duration, r32 *Value)
{
animation_curve_state *State = AC_GetState();
//- sixten: make sure the value is valid
if(*Value != *Value) *Value = 0;
r32 Result = *Value;
r32 Rate = 1.0 - Pow(2, -(10.0 / Duration * State->dtForFrame));
@ -131,8 +134,8 @@ static void AC_NewFrame(animation_curve_state *State, r32 dtForFrame)
// sixten: Prune untouched entries.
for(s32 BucketIndex = 0;
BucketIndex < ArrayCount(State->Buckets);
++BucketIndex)
BucketIndex < ArrayCount(State->Buckets);
++BucketIndex)
{
animation_curve_bucket *Bucket = State->Buckets + BucketIndex;

View File

@ -69,10 +69,30 @@ static void LoadPermanentAssets(assets *Assets)
}
}
static render_handle TextureFromAssetID(asset_id ID)
static render_handle A_TextureFromAssetID(asset_id ID)
{
Assert(ID >= AssetID_None && ID < AssetID_COUNT);
asset *Asset = GetAssets()->Assets + ID;
return(Asset->Handle);
}
static r32 A_ScaleFromAssetID(asset_id ID)
{
Assert(ID >= AssetID_None && ID < AssetID_COUNT);
r32 Result = AssetScaleLUT[ID];
return(Result);
}
static asset_id A_AssetIDFromString(string String)
{
asset_id Result = AssetID_None;
for(u64 AssetIndex = 0; AssetIndex < AssetID_COUNT; AssetIndex += 1)
{
if(AreEqual(String, MakeString(AssetNameLUT[AssetIndex])))
{
Result = AssetIndex;
break;
}
}
return(Result);
}

View File

@ -18,6 +18,8 @@ struct assets
static assets *GetAssets();
static void SetAssets(assets *Assets);
static void LoadAsset(asset_id ID);
static void LoadPermanentAssets(assets *Assets);
static render_handle TextureFromAssetID(asset_id ID);
static void A_LoadAsset(asset_id ID);
static void A_LoadPermanentAssets(assets *Assets);
static render_handle A_TextureFromAssetID(asset_id ID);
static r32 A_ScaleFromAssetID(asset_id ID);
static asset_id A_AssetIDFromString(string String);

View File

@ -1,22 +1,22 @@
@table(Name, Path, IsPermanent) assets_desc:
@table(Name, Path, IsPermanent, Scale) assets_desc:
{
{ None, "", true }
{ Error, "backgrounds/unknown.png", true }
{ None, "", true, 0 }
{ Error, "backgrounds/unknown.png", true, 0 }
////////////////////////////////
//~ sixten: backgrounds
{ DemoBackground, "backgrounds/test.jpg", false }
{ DDLCBackground, "backgrounds/ddlc.png", false }
{ DemoBackground, "backgrounds/test.jpg", false, 1 }
{ DDLCBackground, "backgrounds/ddlc.png", false, 1 }
////////////////////////////////
//~ sixten: characters
//- sixten: arthur
{ ArthurNormal, "characters/test_normal.png", false }
{ ArthurHappy, "characters/test_happy.png", false }
{ ArthurNormal, "characters/test_normal.png", false, 0.017 }
{ ArthurHappy, "characters/test_happy.png", false, 0.017 }
//- sixten: monika
{ MonikaLeaning, "characters/monika_leaning.png", false }
{ MonikaLeaning, "characters/monika_leaning.png", false, 0.033 }
}
@ -48,3 +48,8 @@
@expand(assets_desc s)
`"$(s.Name)",`;
}
@table_gen_data(`r32`) AssetScaleLUT:
{
@expand(assets_desc s)
`$(s.Scale),`;
}

View File

@ -1,6 +1,6 @@
static config *CreateConfig(void)
{
arena *Arena = ArenaAlloc(Kilobytes(4), true);
arena *Arena = ArenaAlloc(Kilobytes(4), true, "Config Arena");
config *Config = PushStruct(Arena, config);
Config->Arena = Arena;
return(Config);
@ -14,8 +14,8 @@ static config_entry *Config_FindEntryByName(config *Config, string Name)
config_entry_bucket *Bucket = Config->EntryBuckets + BucketSlot;
for(config_entry *Entry = Bucket->First;
Entry != 0;
Entry = Entry->Next)
Entry != 0;
Entry = Entry->Next)
{
if(AreEqual(Entry->Name, Name))
{
@ -254,8 +254,8 @@ static void Config_WriteFile(config *Config, string Path)
string LastDir = MakeString(0, 0LL);
for(config_entry *Entry = Config->FirstInternal;
Entry != 0;
Entry = Entry->NextInternal)
Entry != 0;
Entry = Entry->NextInternal)
{
s64 LastSlash = LastIndexOf(Entry->Name, '/');
Assert(LastSlash != -1);

View File

@ -6,7 +6,7 @@ per_thread debug_info *ThreadLocal_DebugInfo = 0;
//- sixten: manage state
static debug_info *DI_DebugInfoAlloc(void)
{
arena *Arena = ArenaAlloc(Kilobytes(1), true);
arena *Arena = ArenaAlloc(Kilobytes(1), true, "Debug Info Arena");
debug_info *Result = PushStruct(Arena, debug_info);
Result->Arena = Arena;
return(Result);
@ -57,8 +57,8 @@ static void DI_BuildInfo(void)
UI_SetNextCornerRadius(4.0f);
UI_SetNextHoverCursor(PlatformCursor_ArrowAll);
ui_box *Box = UI_MakeBox(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder|UI_BoxFlag_Clickable|
UI_BoxFlag_HotAnimation|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY|UI_BoxFlag_Clip,
StrLit("DI Container"));
UI_BoxFlag_HotAnimation|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY|UI_BoxFlag_Clip,
StrLit("DI Container"));
UI_Parent(Box)
{
UI_Size(UI_Percent(1, 1), UI_ChildrenSum(1, 1)) UI_Row() UI_Width(UI_TextContent(15, 1)) UI_Height(UI_TextContent(15, 1))
@ -95,8 +95,8 @@ static void DI_BuildInfo(void)
UI_StoreDragV2(DebugInfo->RelativeP);
}
v2 StartP = UI_GetDragV2();
v2 EndP = StartP + Signal.DragDelta;
v2_r32 StartP = UI_GetDragV2();
v2_r32 EndP = StartP + Signal.DragDelta;
DebugInfo->RelativeP = EndP;
}
Box->FixedP = DebugInfo->RelativeP;

View File

@ -2,13 +2,13 @@
global read_only s32 Font_Oversample = 2;
inline s32 GetSubpixelSegmentAtP(r32 Value)
inline s32 F_SubpixelSegmentFromP(r32 Value)
{
s32 Result = (s32)(Value - Floor(Value))*GLYPH_SUBPIXEL_SEGMENTS;
return(Result);
}
static void RasterizeGlyph(glyph_atlas *Atlas, font_id Font, glyph *Glyph, u32 Codepoint, r32 Size, s32 Subpixel)
static void F_RasterizeGlyph(glyph_atlas *Atlas, font_id Font, glyph *Glyph, u32 Codepoint, r32 Size, s32 Subpixel)
{
Glyph->Font = Font;
Glyph->Codepoint = Codepoint;
@ -58,7 +58,7 @@ static void RasterizeGlyph(glyph_atlas *Atlas, font_id Font, glyph *Glyph, u32 C
Atlas->BitmapBuffer);
}
static glyph *GetGlyph(glyph_atlas *Atlas, font_id Font, u32 Codepoint, r32 Size, s32 Subpixel)
static glyph *F_GlyphFromAtlas(glyph_atlas *Atlas, font_id Font, u32 Codepoint, r32 Size, s32 Subpixel)
{
glyph *Glyph = 0;
@ -92,7 +92,7 @@ static glyph *GetGlyph(glyph_atlas *Atlas, font_id Font, u32 Codepoint, r32 Size
DLLRemove_NP(Atlas->LRUFirst, Atlas->LRULast, Glyph, LRUNext, LRUPrev);
}
RasterizeGlyph(Atlas, Font, Glyph, Codepoint, Size, Subpixel);
F_RasterizeGlyph(Atlas, Font, Glyph, Codepoint, Size, Subpixel);
}
DLLInsertLast_NP(Atlas->LRUFirst, Atlas->LRULast, Glyph, LRUNext, LRUPrev);
@ -100,134 +100,140 @@ static glyph *GetGlyph(glyph_atlas *Atlas, font_id Font, u32 Codepoint, r32 Size
return(Glyph);
}
static glyph_atlas *CreateGlyphAtlas(vn_render_commands *RenderCommands,
s32 BitmapSize = DEFAULT_GLYPH_ATLAS_DIM,
s32 GlyphSize = MAX_GLYPH_SIZE)
static loaded_font F_CreateFontFromFile(arena *Arena, string Filepath)
{
arena *Arena = ArenaAlloc(Megabytes(1), true);
glyph_atlas *Atlas = PushStruct(Arena, glyph_atlas);
Atlas->Arena = Arena;
loaded_font Result = {};
Result.Data = Platform_ReadEntireFile(Arena, Filepath);
if(!Result.Data.Count)
{
Result.Data = Platform_ReadEntireFile(Arena, StrLit("data/fonts/fallback.ttf"));
if(!Result.Data.Count)
{
temp Scratch = GetScratch(&Arena, 1);
Platform.ShowMessage(PushFormat(Scratch.Arena, "Unable to fallback font.", Filepath), Platform_Message_Fatal);
ReleaseScratch(Scratch);
}
}
stbtt_InitFont(&Result.Info, Result.Data.Data, stbtt_GetFontOffsetForIndex(Result.Data.Data, 0));
stbtt_GetFontVMetrics(&Result.Info, &Result.Ascent, &Result.Descent, &Result.LineGap);
Atlas->BitmapSize = BitmapSize;
Atlas->GlyphSize = GlyphSize;
return(Result);
}
Atlas->MaxGlyphCount = (DEFAULT_GLYPH_ATLAS_DIM / MAX_GLYPH_SIZE)*(DEFAULT_GLYPH_ATLAS_DIM / MAX_GLYPH_SIZE);
Atlas->Glyphs = PushArray(Atlas->Arena, glyph, Atlas->MaxGlyphCount);
static glyph_atlas *F_CreateGlyphAtlas(vn_render_commands *RenderCommands, s32 BitmapSize, s32 GlyphSize)
{
arena *Arena = ArenaAlloc(Megabytes(1), true, "Glyph Atlas Arena");
glyph_atlas *Atlas = PushStruct(Arena, glyph_atlas);
Atlas->Arena = Arena;
Atlas->RenderCommands = RenderCommands;
Atlas->Texture = RenderCommands->AllocateTexture(V2S32(BitmapSize, BitmapSize), Render_TextureFormat_R8, false, 0);
Atlas->BitmapSize = BitmapSize;
Atlas->GlyphSize = GlyphSize;
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("data/fonts/Roboto-Bold.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("data/fonts/DejaVuSansMono-Oblique.ttf"));
Atlas->Fonts[Font_Fancy].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("data/fonts/Merriweather-Regular.ttf"));
Atlas->Fonts[Font_Icons].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("data/fonts/icons.ttf"));
Atlas->MaxGlyphCount = (BitmapSize / GlyphSize)*(BitmapSize / GlyphSize);
Atlas->Glyphs = PushArray(Atlas->Arena, glyph, Atlas->MaxGlyphCount);
for(s32 FontIndex = 0;
FontIndex < Font_Count;
++FontIndex)
{
loaded_font *Font = Atlas->Fonts + FontIndex;
stbtt_InitFont(&Font->Info,
Font->Data.Data,
stbtt_GetFontOffsetForIndex(Font->Data.Data, 0));
Atlas->RenderCommands = RenderCommands;
Atlas->Texture = RenderCommands->AllocateTexture(V2S32(BitmapSize, BitmapSize), Render_TextureFormat_R8, false, 0);
stbtt_GetFontVMetrics(&Font->Info, &Font->Ascent, &Font->Descent, &Font->LineGap);
}
Atlas->Fonts[Font_Regular] = F_CreateFontFromFile(Atlas->Arena, StrLit("data/fonts/Roboto-Regular.ttf"));
Atlas->Fonts[Font_Bold] = F_CreateFontFromFile(Atlas->Arena, StrLit("data/fonts/Roboto-Bold.ttf"));
Atlas->Fonts[Font_Monospace] = F_CreateFontFromFile(Atlas->Arena, StrLit("data/fonts/DejaVuSansMono.ttf"));
Atlas->Fonts[Font_MonospaceOblique] = F_CreateFontFromFile(Atlas->Arena, StrLit("data/fonts/DejaVuSansMono-Oblique.ttf"));
Atlas->Fonts[Font_Fancy] = F_CreateFontFromFile(Atlas->Arena, StrLit("data/fonts/Merriweather-Regular.ttf"));
Atlas->Fonts[Font_Icons] = F_CreateFontFromFile(Atlas->Arena, StrLit("data/fonts/icons.ttf"));
Atlas->BitmapBuffer = PushArray(Atlas->Arena, u8, GlyphSize*GlyphSize);
Atlas->BitmapBuffer = PushArray(Atlas->Arena, u8, GlyphSize*GlyphSize);
return(Atlas);
return(Atlas);
}
static r32 PushText(render_group *Group, glyph_atlas *Atlas, font_id Font,
v2 P, r32 Size, v4 Color,
v2_r32 P, r32 Size, v4_r32 Color,
string Text)
{
r32 OffsetX = 0;
u8 *TextBegin = Text.Data;
u8 *TextEnd = TextBegin+Text.Count;
for(u8 *Byte = TextBegin; Byte < TextEnd;)
{
string_decode Decode = DecodeUTF8Codepoint(Byte, TextEnd-Byte);
Byte += Decode.Size;
u32 Codepoint = Decode.Codepoint;
r32 OffsetX = 0;
u8 *TextBegin = Text.Data;
u8 *TextEnd = TextBegin+Text.Count;
for(u8 *Byte = TextBegin; Byte < TextEnd;)
{
string_decode Decode = DecodeUTF8Codepoint(Byte, TextEnd-Byte);
Byte += Decode.Size;
u32 Codepoint = Decode.Codepoint;
glyph *Glyph = GetGlyph(Atlas, Font, Codepoint, Size*Font_Oversample, GetSubpixelSegmentAtP(P.x*Font_Oversample));
Assert(Glyph);
glyph *Glyph = F_GlyphFromAtlas(Atlas, Font, Codepoint, Size*Font_Oversample, F_SubpixelSegmentFromP(P.x*Font_Oversample));
Assert(Glyph);
v2 GlyphP = P + Glyph->Offset*(1.0 / Font_Oversample) + V2(OffsetX, 1);
v2_r32 GlyphP = P + Glyph->Offset*(1.0 / Font_Oversample) + V2R32(OffsetX, 1);
v2 RenderDim = ConvertV2ToR32(Glyph->P1 - Glyph->P0);
v2 Dim = RenderDim*(1.0 / Font_Oversample);
v2_r32 RenderDim = ConvertV2ToR32(Glyph->P1 - Glyph->P0);
v2_r32 Dim = RenderDim*(1.0 / Font_Oversample);
PushTexturedQuad(Group,
PushTexturedQuad(Group,
Range2R32(GlyphP, GlyphP+Dim),
Range2R32(ConvertV2ToR32(Glyph->P0), ConvertV2ToR32(Glyph->P1)),
Color, Color, Color, Color, 0, 0, 0, Atlas->Texture);
Color, Color, Color, Color, 0, 0, 0, 0, 0, 0, Atlas->Texture);
OffsetX += Glyph->Advance/Font_Oversample;
}
return(OffsetX);
OffsetX += Glyph->Advance/Font_Oversample;
}
return(OffsetX);
}
static void PushTextF(render_group *Group, glyph_atlas *Atlas, font_id Font,
v2 P, r32 Size, v4 Color,
v2_r32 P, r32 Size, v4_r32 Color,
char *Format, ...)
{
temp Scratch = GetScratch(0, 0);
temp Scratch = GetScratch(0, 0);
va_list Arguments;
va_start(Arguments, Format);
string String = PushFormatVariadic(Scratch.Arena, Format, Arguments);
va_end(Arguments);
va_list Arguments;
va_start(Arguments, Format);
string String = PushFormatVariadic(Scratch.Arena, Format, Arguments);
va_end(Arguments);
PushText(Group, Atlas, Font, P, Size, Color, String);
PushText(Group, Atlas, Font, P, Size, Color, String);
ReleaseScratch(Scratch);
ReleaseScratch(Scratch);
}
inline r32 CalculateRasterizedTextWidth(glyph_atlas *Atlas, font_id Font, r32 Size, string Text)
{
r32 X = 0;
r32 X = 0;
u8 *TextBegin = Text.Data;
u8 *TextEnd = TextBegin+Text.Count;
for(u8 *Byte = TextBegin; Byte < TextEnd;)
{
string_decode Decode = DecodeUTF8Codepoint(Byte, TextEnd-Byte);
Byte += Decode.Size;
u32 Codepoint = Decode.Codepoint;
u8 *TextBegin = Text.Data;
u8 *TextEnd = TextBegin+Text.Count;
for(u8 *Byte = TextBegin; Byte < TextEnd;)
{
string_decode Decode = DecodeUTF8Codepoint(Byte, TextEnd-Byte);
Byte += Decode.Size;
u32 Codepoint = Decode.Codepoint;
glyph *Glyph = GetGlyph(Atlas, Font, Codepoint, Size*Font_Oversample, GetSubpixelSegmentAtP(X*Font_Oversample));
Assert(Glyph);
glyph *Glyph = F_GlyphFromAtlas(Atlas, Font, Codepoint, Size*Font_Oversample, F_SubpixelSegmentFromP(X*Font_Oversample));
Assert(Glyph);
X += Glyph->Advance/Font_Oversample;
}
X += Glyph->Advance/Font_Oversample;
}
return(X);
return(X);
}
inline r32 CalculateRasterizedTextHeight(glyph_atlas *Atlas, font_id Font, r32 Size, string Text)
{
r32 Scale = stbtt_ScaleForMappingEmToPixels(&Atlas->Fonts[Font].Info, Size)/
stbtt_ScaleForPixelHeight(&Atlas->Fonts[Font].Info, Size);
r32 Scale = stbtt_ScaleForMappingEmToPixels(&Atlas->Fonts[Font].Info, Size)/
stbtt_ScaleForPixelHeight(&Atlas->Fonts[Font].Info, Size);
r32 Y = Size*Scale;
r32 Y = Size*Scale;
u8 *TextBegin = Text.Data;
u8 *TextEnd = TextBegin+Text.Count;
for(u8 *Byte = TextBegin; Byte < TextEnd;)
{
string_decode Decode = DecodeUTF8Codepoint(Byte, TextEnd-Byte);
Byte += Decode.Size;
u32 Codepoint = Decode.Codepoint;
u8 *TextBegin = Text.Data;
u8 *TextEnd = TextBegin+Text.Count;
for(u8 *Byte = TextBegin; Byte < TextEnd;)
{
string_decode Decode = DecodeUTF8Codepoint(Byte, TextEnd-Byte);
Byte += Decode.Size;
u32 Codepoint = Decode.Codepoint;
if(Codepoint == '\n')
{
Y += Size*Scale;
}
}
return(Y);
if(Codepoint == '\n')
{
Y += Size*Scale;
}
}
return(Y);
}

View File

@ -86,13 +86,10 @@ struct glyph
v2_s32 P0;
v2_s32 P1;
v2 Offset;
v2_r32 Offset;
r32 Advance;
};
#define DEFAULT_GLYPH_ATLAS_DIM 1024*2
#define MAX_GLYPH_SIZE 128
#define STB_TRUETYPE_IMPLEMENTATION
#include "third_party/stb_truetype.h"
@ -127,4 +124,15 @@ struct glyph_atlas
loaded_font Fonts[Font_Count];
};
////////////////////////////////
//~ sixten: Font Atlas Functions
inline s32 F_SubpixelSegmentFromP(r32 Value);
static void F_RasterizeGlyph(glyph_atlas *Atlas, font_id Font, glyph *Glyph, u32 Codepoint, r32 Size, s32 Subpixel);
static glyph *F_GlyphFromAtlas(glyph_atlas *Atlas, font_id Font, u32 Codepoint, r32 Size, s32 Subpixel);
static loaded_font F_CreateFontFromFile(arena *Arena, string Filepath);
static glyph_atlas *F_CreateGlyphAtlas(vn_render_commands *RenderCommands, s32 BitmapSize, s32 GlyphSize);
#endif //VN_FONT_H

View File

@ -13,8 +13,9 @@
enum
{
PlatformAccess_Read = 0x1,
PlatformAccess_Write = 0x2,
PlatformAccess_Read = 0x1,
PlatformAccess_Write = 0x2,
PlatformAccess_OpenAlways = 0x4,
};
typedef u32 platform_access_flags;
@ -120,8 +121,8 @@ struct platform_event
platform_modifiers Modifiers;
platform_key Key;
u32 Codepoint;
v2 P;
v2 Scroll;
v2_r32 P;
v2_r32 Scroll;
};
struct platform_event_list
@ -173,7 +174,7 @@ struct vn_render_commands
s32 QuadIndexCount;
#endif
v2 RenderDim;
v2_r32 RenderDim;
};
// sixten: Services the application provides to the platform
@ -183,8 +184,8 @@ struct vn_input
// sixten: Platform to application
platform_event_list *EventList;
v2 MouseP;
v2 dMouseP;
v2_r32 MouseP;
v2_r32 dMouseP;
r32 dtForFrame;

View File

@ -60,7 +60,7 @@ inline render_group BeginRenderGroup(vn_render_commands *Commands)
return(Group);
}
inline void PushClear(render_group *Group, v3 Color)
inline void PushClear(render_group *Group, v3_r32 Color)
{
render_command_clear *Command = PushCommand(Group, render_command_clear);
Command->Color = Color;
@ -92,7 +92,7 @@ inline s32 GetTextureIndexForCommand(render_texture_mapping *Mapping, render_han
return(Result);
}
inline u32 PackV4ToU32(v4 V)
inline u32 PackV4ToU32(v4_r32 V)
{
u32 Result =
((u8)(Clamp01(V.x)*255.0)<<24) |
@ -106,8 +106,9 @@ inline u32 PackV4ToU32(v4 V)
static void PushTexturedQuad(render_group *Group,
range2_r32 Dest,
range2_r32 Source,
v4 Color00, v4 Color10, v4 Color01, v4 Color11,
r32 CornerRadius, r32 EdgeSoftness, r32 BorderThickness,
v4_r32 Color00, v4_r32 Color10, v4_r32 Color01, v4_r32 Color11,
r32 CornerRadius00, r32 CornerRadius10, r32 CornerRadius01, r32 CornerRadius11,
r32 EdgeSoftness, r32 BorderThickness,
render_handle Texture)
{
vn_render_commands *Commands = Group->Commands;
@ -145,7 +146,10 @@ static void PushTexturedQuad(render_group *Group,
Quad->Color[1] = PackV4ToU32(Color01);
Quad->Color[2] = PackV4ToU32(Color10);
Quad->Color[3] = PackV4ToU32(Color11);
Quad->CornerRadius = CornerRadius;
Quad->CornerRadius[0] = CornerRadius00;
Quad->CornerRadius[1] = CornerRadius01;
Quad->CornerRadius[2] = CornerRadius10;
Quad->CornerRadius[3] = CornerRadius11;
Quad->EdgeSoftness = EdgeSoftness;
Quad->BorderThickness = BorderThickness;
@ -261,19 +265,45 @@ static void PushTexturedQuad(render_group *Group,
#endif
inline void PushQuad(render_group *Group, range2_r32 Dest,
v4 Color00, v4 Color01, v4 Color10, v4 Color11,
r32 CornerRadius, r32 EdgeSoftness, r32 BorderThickness)
v4_r32 Color00, v4_r32 Color01, v4_r32 Color10, v4_r32 Color11,
r32 CornerRadius00, r32 CornerRadius01, r32 CornerRadius10, r32 CornerRadius11,
r32 EdgeSoftness, r32 BorderThickness)
{
PushTexturedQuad(Group, Dest, Range2R32(V2(0, 0), V2(0, 0)), Color00, Color01, Color10, Color11,
CornerRadius, EdgeSoftness, BorderThickness, Group->Commands->WhiteTexture);
PushTexturedQuad(Group, Dest, Range2R32(V2R32(0, 0), V2R32(0, 0)),
Color00, Color01, Color10, Color11,
CornerRadius00, CornerRadius01, CornerRadius10, CornerRadius11,
EdgeSoftness, BorderThickness, Group->Commands->WhiteTexture);
}
inline void PushQuad(render_group *Group, range2_r32 Dest,
v4 Color,
v4_r32 Color,
r32 CornerRadius00, r32 CornerRadius01, r32 CornerRadius10, r32 CornerRadius11,
r32 EdgeSoftness, r32 BorderThickness)
{
PushTexturedQuad(Group, Dest, Range2R32(V2R32(0, 0), V2R32(0, 0)),
Color, Color, Color, Color,
CornerRadius00, CornerRadius01, CornerRadius10, CornerRadius11,
EdgeSoftness, BorderThickness, Group->Commands->WhiteTexture);
}
inline void PushQuad(render_group *Group, range2_r32 Dest,
v4_r32 Color00, v4_r32 Color01, v4_r32 Color10, v4_r32 Color11,
r32 CornerRadius, r32 EdgeSoftness, r32 BorderThickness)
{
PushTexturedQuad(Group, Dest, Range2R32(V2(0, 0), V2(0, 0)), Color, Color, Color, Color,
CornerRadius, EdgeSoftness, BorderThickness, Group->Commands->WhiteTexture);
PushTexturedQuad(Group, Dest, Range2R32(V2R32(0, 0), V2R32(0, 0)),
Color00, Color01, Color10, Color11,
CornerRadius, CornerRadius, CornerRadius, CornerRadius,
EdgeSoftness, BorderThickness, Group->Commands->WhiteTexture);
}
inline void PushQuad(render_group *Group, range2_r32 Dest,
v4_r32 Color,
r32 CornerRadius, r32 EdgeSoftness, r32 BorderThickness)
{
PushTexturedQuad(Group, Dest, Range2R32(V2R32(0, 0), V2R32(0, 0)),
Color, Color, Color, Color,
CornerRadius, CornerRadius, CornerRadius, CornerRadius,
EdgeSoftness, BorderThickness, Group->Commands->WhiteTexture);
}
inline void PushClip(render_group *Group, range2_r32 Clip)

View File

@ -6,22 +6,22 @@
#define MAX_BOUND_TEXTURES 16
#define MAX_QUAD_COUNT 128*1024
#define ColorFromHex(Value) V4((((Value) >> 24) & 0xFF) / 255.0, (((Value) >> 16) & 0xFF) / 255.0, (((Value) >> 8) & 0xFF) / 255.0, (((Value) >> 0) & 0xFF) / 255.0)
#define ColorFromHex(Value) V4R32((((Value) >> 24) & 0xFF) / 255.0, (((Value) >> 16) & 0xFF) / 255.0, (((Value) >> 8) & 0xFF) / 255.0, (((Value) >> 0) & 0xFF) / 255.0)
#define Brighten(Color, Amount) (Color*(Amount))
#define Darken(Color, Amount) (Color*(1.0/(Amount)))
read_only v4 Color_Black = V4(0, 0, 0, 1);
read_only v4 Color_White = V4(1, 1, 1, 1);
read_only v4 Color_Grey = V4(0.5, 0.5, 0.5, 1);
read_only v4 Color_Red = V4(1, 0, 0, 1);
read_only v4 Color_Green = V4(0, 1, 0, 1);
read_only v4 Color_Blue = V4(0, 0, 1, 1);
read_only v4 Color_Yellow = V4(1, 1, 0, 1);
read_only v4 Color_Magenta = V4(1, 0, 1, 1);
read_only v4 Color_Cyan = V4(0, 1, 1, 1);
read_only v4_r32 Color_Black = V4R32(0, 0, 0, 1);
read_only v4_r32 Color_White = V4R32(1, 1, 1, 1);
read_only v4_r32 Color_Grey = V4R32(0.5, 0.5, 0.5, 1);
read_only v4_r32 Color_Red = V4R32(1, 0, 0, 1);
read_only v4_r32 Color_Green = V4R32(0, 1, 0, 1);
read_only v4_r32 Color_Blue = V4R32(0, 0, 1, 1);
read_only v4_r32 Color_Yellow = V4R32(1, 1, 0, 1);
read_only v4_r32 Color_Magenta = V4R32(1, 0, 1, 1);
read_only v4_r32 Color_Cyan = V4R32(0, 1, 1, 1);
#define SetAlpha(Color, Value) V4(Color.x, Color.y, Color.z, Value)
#define SetAlpha(Color, Value) V4R32(Color.x, Color.y, Color.z, Value)
enum render_texture_format
{
@ -50,7 +50,7 @@ enum render_command_type
struct render_command_clear
{
v3 Color;
v3_r32 Color;
};
struct render_texture_mapping
@ -99,19 +99,19 @@ struct instanced_quad
range2_r32 Source;
u32 TextureIndex;
u32 Color[4];
r32 CornerRadius;
r32 CornerRadius[4];
r32 EdgeSoftness;
r32 BorderThickness;
};
struct quad_vertex
{
v2 P;
v2 SourceP;
v2_r32 P;
v2_r32 SourceP;
u32 TextureIndex;
u32 Color;
v2 ToCenter; // sixten: ToCenter = Center - P
v2 HalfSize;
v2_r32 ToCenter; // sixten: ToCenter = Center - P
v2_r32 HalfSize;
r32 CornerRadius;
r32 EdgeSoftness;
r32 BorderThickness;

File diff suppressed because it is too large Load Diff

View File

@ -1,458 +0,0 @@
/* date = July 30th 2023 7:45 pm */
#ifndef VN_SCENE_H
#define VN_SCENE_H
// sixten(IMPORTANT): The arena that the scene is compiled on
// is assumed to be the same it runs on, i.e. the interpreter relies
// on the memory addresses being the same during compilation and
// runtime.
// We also assume that the original text and tokenization remains in
// memory, for the duration of the scene.
////////////////////////////////
//~ sixten: Scene Compilation Types
struct scene_compile_error
{
scene_compile_error *Next;
string Message;
token Token;
};
struct scene_compile_error_list
{
scene_compile_error *First;
scene_compile_error *Last;
s64 Count;
};
enum scene_opcode
{
S_Op_Invalid = 0,
S_Op_Constant,
S_Op_Pop,
S_Op_Nil,
S_Op_True,
S_Op_False,
S_Op_Add,
S_Op_Subtract,
S_Op_Multiply,
S_Op_Divide,
S_Op_Equal,
S_Op_Greater,
S_Op_Less,
S_Op_Negate,
S_Op_Not,
S_Op_DefineGlobal,
S_Op_GetGlobal,
S_Op_SetGlobal,
S_Op_Jump,
S_Op_JumpClose,
S_Op_AddBranch,
S_Op_Halt,
S_Op_AwaitInput,
S_Op_ClearDialog,
S_Op_LineEntry,
S_Op_ShowCharacter,
};
struct scene_bytecode_chunk
{
scene_bytecode_chunk *Next;
string Name;
s64 Count;
u8 Data[4096];
};
struct scene_bytecode_bucket
{
scene_bytecode_chunk *First;
scene_bytecode_chunk *Last;
s64 Count;
};
enum scene_value_kind
{
S_ValueKind_Nil = 0,
S_ValueKind_Number,
S_ValueKind_Boolean,
S_ValueKind_Pointer,
S_ValueKind_SourceRef,
S_ValueKind_String,
S_ValueKind_Offset,
};
struct scene_value
{
scene_value_kind Kind;
union
{
r64 Number;
b32 Boolean;
u64 Pointer;
range1_s64 SourceRef;
string String;
s64 Offset;
};
};
struct scene_value_chunk
{
scene_value_chunk *Next;
s64 Count;
scene_value Values[512];
};
enum scene_precedence
{
S_Precedence_None,
S_Precedence_Assignment,
S_Precedence_Or,
S_Precedence_And,
S_Precedence_Equality,
S_Precedence_Comparison,
S_Precedence_Term,
S_Precedence_Factor,
S_Precedence_Unary,
S_Precedence_Call,
S_Precedence_Primary,
};
typedef void scene_parse_function(struct scene_compiler *Compiler, b32 CanAssign);
struct scene_parse_rule
{
scene_parse_function *PrefixRule;
scene_parse_function *InfixRule;
scene_precedence Precedence;
};
enum scene_emission_target_type
{
S_EmissionTarget_Raw,
S_EmissionTarget_Named,
};
struct scene_emission_target
{
arena *Arena;
scene_bytecode_bucket *Bucket;
scene_emission_target_type Type;
string Name;
};
struct scene_branch_case
{
scene_branch_case *Next;
token Name;
scene_bytecode_bucket Bucket;
scene_value *OffsetValue;
scene_value *EndOffsetValue;
};
struct scene_character_action
{
scene_character_action *Next;
scene_character_action *Prev;
string Target;
character_state State;
};
struct scene_compiler
{
arena *Arena;
b32 InPanicMode;
b32 EncounteredError;
scene_compile_error_list Errors;
string Text;
token *TokensBegin;
token *TokensEnd;
token *At;
scene_bytecode_bucket GlobalScope;
scene_bytecode_bucket ProcBuckets[32];
scene_emission_target TargetStack[16];
s32 TargetStackIndex;
scene_value_chunk *FirstValueChunk;
scene_value_chunk *LastValueChunk;
s64 ValueCount;
string NavFileName;
asset_id BackgroundTexture;
};
////////////////////////////////
//~ sixten: Compiled Scene Types
struct scene_proc
{
// sixten: scene data
string Name;
u8 *Data;
s64 Count;
// sixten: hash link
scene_proc *Next;
};
struct scene_proc_bucket
{
scene_proc *First;
scene_proc *Last;
};
struct compiled_scene
{
scene_proc *GlobalScope;
scene_proc_bucket Buckets[16];
scene_value *Values;
s64 ValueCount;
string Source;
string NavFileName;
asset_id BackgroundTexture;
scene_compile_error_list Errors;
b32 IsValid;
};
////////////////////////////////
//~ sixten: Scene Runtime Types
struct scene_runtime_error
{
scene_runtime_error *Next;
scene_runtime_error *Prev;
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
{
b32 HadError;
b32 ReachedAwait;
};
enum scene_textbox_action_kind
{
S_TextboxActionKind_Set,
S_TextboxActionKind_Append,
};
struct scene_textbox_action
{
scene_textbox_action *Next;
scene_textbox_action_kind Kind;
string String;
};
struct branch_case
{
string Name;
s64 Offset;
};
struct scene_runtime_stack
{
scene_value Stack[128];
s32 Count;
};
struct scene_runtime
{
compiled_scene Compiled;
// sixten: runtime state
arena *RuntimeArena;
scene_proc *CurrentProc;
s64 IP;
scene_runtime_stack Stack;
scene_named_value_bucket GlobalVariableBuckets[16];
scene_named_value_bucket GlobalVariableFreeList;
// sixten: errors
arena *ErrorArena;
scene_runtime_error_list Errors;
// sixten: branches
branch_case Branches[16];
s64 BranchCount;
// sixten: result
scene_runtime_result LastResult;
scene_textbox_action *FirstTextboxAction;
scene_textbox_action *LastTextboxAction;
scene_character_action *FirstCharacterAction;
scene_character_action *LastCharacterAction;
};
////////////////////////////////
//~ sixten: Scene Compiler Functions
//- sixten: value helpers
inline scene_value S_MakeNil(void)
{
scene_value Result;
Result.Kind = S_ValueKind_Nil;
return(Result);
}
inline scene_value S_MakeNumber(r64 Value)
{
scene_value Result;
Result.Kind = S_ValueKind_Number;
Result.Number = Value;
return(Result);
}
inline scene_value S_MakeBoolean(b32 Value)
{
scene_value Result;
Result.Kind = S_ValueKind_Boolean;
Result.Boolean = Value;
return(Result);
}
inline scene_value S_MakePointer(void *Value)
{
scene_value Result;
Result.Kind = S_ValueKind_Pointer;
Result.Pointer = PointerToU64(Value);
return(Result);
}
inline scene_value S_MakeSourceRef(token Token)
{
scene_value Result;
Result.Kind = S_ValueKind_SourceRef;
Result.SourceRef = Token.Range;
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)
{
scene_value Result;
Result.Kind = S_ValueKind_Offset;
Result.Offset = Offset;
return(Result);
}
//- sixten: error messaging
static void S_ParseError(scene_compiler *Compiler, char *Message, s64 TokenOffset = -1);
//- sixten: bytecode helpers
static void S_EmitByte(scene_compiler *Compiler, u8 Byte);
static void S_EmitU32(scene_compiler *Compiler, u32 Value);
static void S_EmitBucket(scene_compiler *Compiler, scene_bytecode_bucket *Bucket);
static u64 S_MakeConstant(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_PushEmissionTarget(scene_compiler *Compiler, scene_emission_target Target);
static void S_PopEmissionTarget(scene_compiler *Compiler);
inline scene_emission_target S_RawEmissionTarget(arena *Arena, scene_bytecode_bucket *Bucket)
{
scene_emission_target Target = {};
Target.Arena = Arena;
Target.Bucket = Bucket;
Target.Type = S_EmissionTarget_Raw;
return(Target);
}
inline scene_emission_target S_NamedEmissionTarget(arena *Arena, scene_bytecode_bucket *Bucket, string Name)
{
scene_emission_target Target = {};
Target.Arena = Arena;
Target.Bucket = Bucket;
Target.Type = S_EmissionTarget_Named;
Target.Name = Name;
return(Target);
}
//- sixten: parsing helpers
static void S_AdvanceCompiler(scene_compiler *Compiler);
static scene_parse_rule S_ParseRuleFromToken(scene_compiler *Compiler, token Token);
static token S_ConsumeToken(scene_compiler *Compiler, token_kind Kind, char *Message);
//- sixten: parsing
static void S_ParseTopLevelDeclaration(scene_compiler *Compiler);
static void S_ParseProcedure(scene_compiler *Compiler);
static void S_ParseDeclaration(scene_compiler *Compiler);
static void S_ParseVariableDeclaration(scene_compiler *Compiler);
static void S_ParseVariable(scene_compiler *Compiler, b32 CanAssign);
static void S_ParseNamedVariable(scene_compiler *Compiler, token Token, b32 CanAssign);
static void S_ParseNavFilePath(scene_compiler *Compiler);
static void S_ParseBackgroundAsset(scene_compiler *Compiler);
static void S_ParseLineEntry(scene_compiler *Compiler);
static void S_ParseJumpStatement(scene_compiler *Compiler);
static void S_ParseBranchStatement(scene_compiler *Compiler);
static scene_branch_case *S_ParseBranchCase(scene_compiler *Compiler, arena *Arena);
static void S_ParseStatement(scene_compiler *Compiler);
static void S_ParseExpression(scene_compiler *Compiler);
static void S_ParseLiteral(scene_compiler *Compiler, b32 CanAssign);
static void S_ParseNumber(scene_compiler *Compiler, b32 CanAssign);
static void S_ParseString(scene_compiler *Compiler, b32 CanAssign);
static void S_ParseGrouping(scene_compiler *Compiler, b32 CanAssign);
static void S_ParseUnary(scene_compiler *Compiler, b32 CanAssign);
static void S_ParseBinary(scene_compiler *Compiler, b32 CanAssign);
static void S_ParsePrecedence(scene_compiler *Compiler, scene_precedence Precedence);
//- sixten: debugging
static string S_DisassembleBytecode(scene_compiler *Compiler, scene_bytecode_chunk *Chunk, arena *Arena);
//- sixten: compilation
static compiled_scene S_ScriptFromText(arena *Arena, string Text);
static compiled_scene S_CopyCompiledScene(arena *Arena, compiled_scene *Compiled);
////////////////////////////////
//~ sixten: Scene Runtime Functions
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 scene_runtime_result S_Run(scene_runtime *Runtime, arena *Arena, b32 AdvanceOnAwait);
#endif //VN_SCENE_H

View File

@ -1,35 +0,0 @@
@table(Name, Operator) scene_operator_table:
{
{ Invalid, "###" }
{ Not, "!" }
{ Equal, "=" }
{ Equals, "==" }
{ NotEquals, "!=" }
{ GreaterThanOrEquals, ">=" }
{ LessThanOrEquals, "<=" }
{ Greater, ">" }
{ Less, "<" }
{ Add, "+" }
{ Minus, "-" }
{ Multiply "*" }
{ Divide, "/" }
}
@table_gen
{
`enum scene_operator`;
`{`;
@expand(scene_operator_table s) `S_Operator_$(s.Name),`;
`};`;
}
@table_gen
{
`inline scene_operator S_OperatorFromString(string String)`;
`{`;
`scene_operator Result = S_Operator_Invalid;`;
`if(0) {}`;
@expand(scene_operator_table s) `else if(AreEqual(String, StrLit("$(s.Operator)")))$(=>40) { Result = S_Operator_$(s.Name); }`;
`return(Result);`;;
`}`;
}

1025
code/vn_scene2.cpp 100644

File diff suppressed because it is too large Load Diff

292
code/vn_scene2.h 100644
View File

@ -0,0 +1,292 @@
/* date = December 30th 2023 8:26 pm */
#ifndef VN_SCENE2_H
#define VN_SCENE2_H
struct scene2_runtime;
struct compiled_scene2;
#define S2_CALL_FUNCTION(name) void name(scene2_runtime *Runtime, compiled_scene2 *Compiled)
typedef S2_CALL_FUNCTION(scene2_call_function);
static S2_CALL_FUNCTION(S2_Call_Stub) {}
static u64 S2_CallFunctionIndexFromString(string String);
static scene2_call_function *S2_CallFunctionFromString(string String);
#include "generated/vn_scene2.meta.h"
////////////////////////////////
//~ sixten: Scene Message Types
struct scene2_message
{
scene2_message *Next;
string Message;
token Token;
};
struct scene2_message_list
{
scene2_message *First;
scene2_message *Last;
u64 Count;
};
////////////////////////////////
//~ sixten: Scene Parsing Types
enum scene2_precedence
{
S2_Precedence_None,
S2_Precedence_Assignment,
S2_Precedence_Or,
S2_Precedence_And,
S2_Precedence_Equality,
S2_Precedence_Comparison,
S2_Precedence_Term,
S2_Precedence_Factor,
S2_Precedence_Unary,
S2_Precedence_Call,
S2_Precedence_Primary,
};
typedef void scene2_parse_function(struct scene2_compiler *Compiler, b32 CanAssign);
struct scene2_parse_rule
{
scene2_parse_function *PrefixRule;
scene2_parse_function *InfixRule;
scene2_precedence Precedence;
};
struct scene2_instruction
{
scene2_opcode Opcode;
union
{
struct
{
u32 Arg1;
u32 Arg2;
};
struct
{
u32 Min;
u32 Max;
};
u64 Arg;
r64 Number;
};
};
struct scene2_instruction_chunk
{
scene2_instruction_chunk *Next;
u64 InstructionsUsed;
scene2_instruction Instructions[1];
};
struct scene2_proc_info
{
string Name;
u64 InstructionBegin;
u64 InstructionEnd;
};
struct scene2_proc_node
{
scene2_proc_node *Next;
scene2_proc_info Info;
};
struct scene2_proc_list
{
scene2_proc_node *First;
scene2_proc_node *Last;
u64 Count;
};
struct scene2_compiler
{
arena *Arena;
scene2_message_list Messages;
b32 InPanicMode;
scene2_instruction_chunk *FirstChunk;
scene2_instruction_chunk *LastChunk;
u64 InstructionPointer;
scene2_proc_list ProcList;
string Source;
token_array Tokens;
s64 At;
};
struct compiled_scene2
{
string Source;
scene2_message_list Messages;
u64 InstructionCount;
scene2_instruction *Instructions;
scene2_proc_list ProcList;
};
////////////////////////////////
//~ sixten: Scene Message Functions
static void S2_PushMessage(arena *Arena, scene2_message_list *List, token Token, string Message);
static void S2_PushMessageFV(arena *Arena, scene2_message_list *List, token Token, char *Format, va_list Arguments);
static void S2_PushMessageF(arena *Arena, scene2_message_list *List, token Token, char *Format, ...);
static scene2_message_list S2_CopyMessageList(arena *Arena, scene2_message_list *Source);
static void S2_ConcatMessageList(arena *Arena, scene2_message_list *Dest, scene2_message_list *Source);
////////////////////////////////
//~ sixten: Scene Action Types
enum scene2_action_kind
{
S2_ActionKind_None = 0,
};
struct scene2_action
{
scene2_action *Next;
scene2_action_kind Kind;
};
struct scene2_action_list
{
scene2_action *First;
scene2_action *Last;
u64 Count;
};
////////////////////////////////
//~ sixten: Scene Action Functions
static void S2_SceneActionPush(scene2_action_list *List, scene2_action Action);
////////////////////////////////
//~ sixten: Scene Runtime Types
enum scene2_object_kind
{
S2_ObjectKind_Nil,
S2_ObjectKind_Bool,
S2_ObjectKind_Number,
S2_ObjectKind_String,
};
global read_only string S2_ObjectKindNameLookup[] =
{
StrComp("nil"),
StrComp("bool"),
StrComp("number"),
StrComp("string"),
};
struct scene2_object
{
scene2_object_kind Kind;
union
{
b32 Bool;
r64 Number;
string String;
} As;
};
struct scene2_variable
{
scene2_variable *Next;
scene2_variable *Prev;
string Name;
scene2_object Value;
};
struct scene2_runtime
{
scene2_proc_info CurrentProc;
u64 InstructionPointer;
//- siten: variables
arena *VariableArena;
scene2_variable *FirstGlobalVariable;
scene2_variable *LastGlobalVariable;
scene2_variable *FirstFreeVariable;
scene2_variable *LastFreeVariable;
//- sixten: runtime stack
u64 StackPointer;
scene2_object Stack[128];
//- sixten: custom callback data
void *Data;
};
struct scene2_run_result
{
scene2_message_list Messages;
scene2_action_list Actions;
};
////////////////////////////////
//~ sixten: Scene Parsing Helpers
static token S2_Token(scene2_compiler *Compiler);
static token S2_Consume(scene2_compiler *Compiler, token_kind Expected, string Message);
static void S2_Advance(scene2_compiler *Compiler);
static scene2_parse_rule S2_ParseRuleFromToken(scene2_compiler *Compiler, token Token);
static scene2_instruction S2_Instruction(scene2_opcode Opcode);
static scene2_instruction S2_Instruction(scene2_opcode Opcode, u64 Arg);
static scene2_instruction S2_Instruction(scene2_opcode Opcode, r64 Number);
static scene2_instruction S2_Instruction(scene2_opcode Opcode, u32 Arg1, u32 Arg2);
static scene2_instruction S2_Instruction(scene2_opcode Opcode, range1_s64 Range);
static scene2_instruction *S2_Emit(scene2_compiler *Compiler, scene2_instruction Instruction);
////////////////////////////////
//~ sixten: Scene Parsing Functions
static void S2_ParseTopLevel(scene2_compiler *Compiler);
static void S2_ParseProc(scene2_compiler *Compiler);
static void S2_ParseBlock(scene2_compiler *Compiler);
static void S2_ParseStatement(scene2_compiler *Compiler);
static void S2_ParseWaitStatement(scene2_compiler *Compiler);
static void S2_ParseIfStatement(scene2_compiler *Compiler);
static void S2_ParseWhileStatement(scene2_compiler *Compiler);
static void S2_ParseLetStatement(scene2_compiler *Compiler);
static void S2_ParseShorthand(scene2_compiler *Compiler);
static void S2_ParseExpression(scene2_compiler *Compiler);
static void S2_ParsePrecedence(scene2_compiler *Compiler, scene2_precedence Precedence);
static void S2_ParseStatement(scene2_compiler *Compiler);
static void S2_ParseGrouping(scene2_compiler *Compiler, b32 CanAssign);
static void S2_ParseUnary(scene2_compiler *Compiler, b32 CanAssign);
static void S2_ParseBinary(scene2_compiler *Compiler, b32 CanAssign);
static void S2_ParseLiteral(scene2_compiler *Compiler, b32 CanAssign);
static void S2_ParseNumber(scene2_compiler *Compiler, b32 CanAssign);
static void S2_ParseString(scene2_compiler *Compiler, b32 CanAssign);
static void S2_ParseVariable(scene2_compiler *Compiler, b32 CanAssign);
static void S2_ParseCall(scene2_compiler *Compiler, b32 CanAssign);
////////////////////////////////
//~ sixten: Scene Runtime Helper Functions
static string S2_StringFromObject(arena *Arena, scene2_object Object);
static void S2_StackPush(scene2_runtime *Runtime, scene2_object Object);
static scene2_object S2_StackPop(scene2_runtime *Runtime);
static scene2_object S2_MakeNil(void);
static scene2_object S2_MakeNumber(r64 Number);
static scene2_object S2_MakeString(string String);
static b32 S2_ObjectIsTrue(scene2_object Object);
////////////////////////////////
//~ sixten: Scene Interface Functions
static compiled_scene2 S2_CompiledFromString(arena *Arena, string String);
static compiled_scene2 S2_CopyCompiledScene(arena *Arena, compiled_scene2 *Source);
static void S2_SetCurrentProc(scene2_runtime *Runtime, scene2_proc_info *Info);
static scene2_proc_info S2_ProcFromName(compiled_scene2 *Compiled, string Name);
#endif //VN_SCENE2_H

145
code/vn_scene2.md 100644
View File

@ -0,0 +1,145 @@
@table(Op, Desc) scene2_opcode_table:
{
{ None, "does nothing (effectivly a nop)" },
// sixten: interfacing with user
{ Call, "stages runtime hook" },
{ Wait, "executes staged actions and waits for user input" },
// sixten: stack manipulation
{ Pop, "pops object from stack" },
{ PushBool, "pushes a boolean onto the stack" },
{ PushNumber, "pushes a number onto the stack" },
{ PushString, "pushes a string onto the stack" },
{ PushNil, "pushes `nil` onto the stack" },
{ PushVariable, "pushes a variable onto the stack" },
{ DuplicateStack, "duplicates the top N-most elements of the stack (specified in Arg as u64)" },
// sixten: variables
{ SetVariable, "pops the stack and stores the value in a variable" },
{ SetLocal, "defines a locally scoped variable" },
// sixten: blocks
{ BeginBlock, "increases the variable stack depth" },
{ EndBlock, "decreases the variable stack depth" },
// sixten: jumps
{ Jump, "performs a relative jump (specified in Arg as s64)" },
{ CondJump, "performs a relative jump (specified in Arg as s64) if the topmost element on the stack is non-zero" },
// sixten: operations
{ Add, "adds the two topmost elements of the stack" },
{ Subtract, "subtracts the topmost element of the stack by the second topmost element" },
{ Multiply, "multiplies the two topmost elements of the stack" },
{ Divide, "divides the topmost element of the stack by the second topmost element" },
{ Equals, "" },
{ Greater, "" },
{ Less, "" },
{ Not, "performs a not operation on the topmost element of the stack" },
{ Negate, "negates the topmost element of the stack" },
}
@table(Name, Operator) scene2_operator_table:
{
{ Invalid, "###" }
{ Not, "!" }
{ Equal, "=" }
{ Equals, "==" }
{ NotEquals, "!=" }
{ GreaterThanOrEquals, ">=" }
{ LessThanOrEquals, "<=" }
{ Greater, ">" }
{ Less, "<" }
{ Add, "+" }
{ Minus, "-" }
{ Multiply "*" }
{ Divide, "/" }
}
@table(Name, Binding, Desc) scene2_call_table:
{
{ none, S2_Call_Stub, "does nothing" },
// sixten: debugging
{ stack_sanity, S2_Call_StackSanity, "does checks that the stack is at a certain depth" },
// sixten: textbox management calls
{ text_append, S2_Call_TextAppend, "pops a value and appends it to the textbox" },
{ text_newline, S2_Call_NewLine, "appends a newline to the textbox" },
{ text_clear, S2_Call_TextClear, "clears the textbox" },
// sixten: proc management calls
{ proc_set, S2_Call_ProcSet, "sets the current proc" },
// sixten: character management calls
{ ctr_set, S2_Call_CharacterSet, "sets the state of a character" },
{ ctr_remove, S2_Call_CharacterRemove, "removes a character" },
{ ctr_set_talking, S2_Call_CharacterSetTalking, "makes a character talking" },
{ ctr_unset_all_talking, S2_Call_CharacterUnsetAllTalking, "makes no characters talking" },
}
@table_gen
{
`enum scene2_opcode`;
`{`;
@expand(scene2_opcode_table s) `S2_Op_$(s.Op), $(=>50) // $(s.Desc)`;
`S2_Op_COUNT,`
`};`;
}
@table_gen
{
`global read_only string S2_InstructionInfoLookup[] =`;
`{`;
@expand(scene2_opcode_table s) `StrComp("$(s.Op)"),`;
`};`;
}
@table_gen
{
`global read_only string S2_InstructionNameLookup[] =`;
`{`;
@expand(scene2_opcode_table s) `StrComp("$(s.Desc)"),`;
`};`;
}
@table_gen
{
`enum scene2_operator`;
`{`;
@expand(scene2_operator_table s) `S2_Operator_$(s.Name),`;
`};`;
}
@table_gen
{
`inline scene2_operator S2_OperatorFromString(string String)`;
`{`;
`scene2_operator Result = S2_Operator_Invalid;`;
`if(0) {}`;
@expand(scene2_operator_table s) `else if(AreEqual(String, StrLit("$(s.Operator)")))$(=>40) { Result = S2_Operator_$(s.Name); }`;
`return(Result);`;
`}`;
}
@table_gen
{
@expand(scene2_call_table s) `static S2_CALL_FUNCTION($(s.Binding)); $(=>50) // $(s.Desc)`;
}
@table_gen
{
`global read_only scene2_call_function *S2_CallBindingLookup[] =`;
`{`;
@expand(scene2_call_table s) `$(s.Binding), `;
`};`;
}
@table_gen
{
`global read_only string S2_CallNameLookup[] =`;
`{`;
@expand(scene2_call_table s) `StrComp("$(s.Name)"), `;
`};`;
}

View File

@ -0,0 +1,202 @@
static u64 S2_CallFunctionIndexFromString(string String)
{
u64 Result = 0;
for(u64 Index = 0; Index < ArrayCount(S2_CallNameLookup); Index += 1)
{
if(AreEqual(String, S2_CallNameLookup[Index]))
{
Result = Index;
break;
}
}
return(Result);
}
static scene2_call_function *S2_CallFunctionFromString(string String)
{
scene2_call_function *Result = S2_Call_Stub;
for(u64 Index = 0; Index < ArrayCount(S2_CallNameLookup); Index += 1)
{
if(AreEqual(String, S2_CallNameLookup[Index]))
{
Result = S2_CallBindingLookup[Index];
break;
}
}
return(Result);
}
static S2_CALL_FUNCTION(S2_Call_StackSanity)
{
scene2_object Value = S2_StackPop(Runtime);
Assert(Value.Kind == S2_ObjectKind_Number && Runtime->StackPointer == (u64)Value.As.Number);
}
static S2_CALL_FUNCTION(S2_Call_TextClear)
{
scene_view *SceneView = (scene_view *)Runtime->Data;
SceneView->TextboxUsed = 0;
SceneView->TextboxRevealed = 0;
}
static S2_CALL_FUNCTION(S2_Call_NewLine)
{
scene_view *SceneView = (scene_view *)Runtime->Data;
if(SceneView->TextboxUsed < ArrayCount(SceneView->TextboxData))
{
SceneView->TextboxData[SceneView->TextboxUsed++] = '\n';
}
}
static S2_CALL_FUNCTION(S2_Call_TextAppend)
{
scene_view *SceneView = (scene_view *)Runtime->Data;
temp Scratch = GetScratch();
string Addend = S2_StringFromObject(Scratch.Arena, S2_StackPop(Runtime));
Addend.Count = Min(Addend.Count, ArrayCount(SceneView->TextboxData)-SceneView->TextboxUsed);
Copy(SceneView->TextboxData+SceneView->TextboxUsed, Addend.Data, Addend.Count);
SceneView->TextboxUsed += Addend.Count;
ReleaseScratch(Scratch);
}
static S2_CALL_FUNCTION(S2_Call_ProcSet)
{
temp Scratch = GetScratch();
S2_SetCurrentProc(Runtime, S2_ProcFromName(Compiled, S2_StringFromObject(Scratch.Arena, S2_StackPop(Runtime))));
ReleaseScratch(Scratch);
}
static S2_CALL_FUNCTION(S2_Call_CharacterSet)
{
scene_view *SceneView = (scene_view *)Runtime->Data;
scene2_object IDObject = S2_StackPop(Runtime);
scene2_object TargetObject = S2_StackPop(Runtime);
// sixten(TODO): this should fail gracefully
Assert(IDObject.Kind == S2_ObjectKind_Number || IDObject.Kind == S2_ObjectKind_Nil);
Assert(TargetObject.Kind == S2_ObjectKind_String);
string Target = TargetObject.As.String;
asset_id ID = IDObject.Kind == S2_ObjectKind_Number ? (asset_id)IDObject.As.Number : AssetID_None;
scene_view_character_data *CharacterBegin = SceneView->Characters;
scene_view_character_data *CharacterUsedEnd = SceneView->Characters+SceneView->CharactersUsed;
scene_view_character_data *CharacterEnd = SceneView->Characters+ArrayCount(SceneView->Characters);
scene_view_character_data *Character = CharacterBegin;
for(;Character < CharacterEnd; Character += 1)
{
// sixten: check if the character doesn't exist
if(Character == CharacterUsedEnd)
{
// sixten: "create" new character
ZeroStruct(Character);
Character->Name = PushString(SceneView->SceneArena, Target);
SceneView->CharactersUsed += 1;
Character->PctP = ((r32)SceneView->CharactersUsed / (r32)(SceneView->CharactersUsed+1));
break;
}
// sixten: check if character exists
if(AreEqual(Character->Name, Target))
{
break;
}
}
if(Character != CharacterEnd)
{
Character->Active = true;
if(ID != AssetID_None)
{
Character->Info.Texture = A_TextureFromAssetID(ID);
Character->Info.Scale = A_ScaleFromAssetID(ID);
}
}
else
{
// sixten: we've run out of characters
}
}
static S2_CALL_FUNCTION(S2_Call_CharacterRemove)
{
scene_view *SceneView = (scene_view *)Runtime->Data;
scene2_object TargetObject = S2_StackPop(Runtime);
// sixten(TODO): this should fail gracefully
Assert(TargetObject.Kind == S2_ObjectKind_String);
string Target = TargetObject.As.String;
scene_view_character_data *CharacterBegin = SceneView->Characters;
scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed;
scene_view_character_data *Character = CharacterBegin;
// sixten: check if the character exists
for(;Character < CharacterEnd; Character += 1)
{
if(AreEqual(Character->Name, Target))
{
break;
}
}
// sixten: if the character exists, request its deletion
if(Character != CharacterEnd)
{
Character->Active = false;
Character->Talking = false;
}
}
static S2_CALL_FUNCTION(S2_Call_CharacterSetTalking)
{
scene_view *SceneView = (scene_view *)Runtime->Data;
scene2_object TargetObject = S2_StackPop(Runtime);
// sixten(TODO): this should fail gracefully
Assert(TargetObject.Kind == S2_ObjectKind_String);
string Target = TargetObject.As.String;
scene_view_character_data *CharacterBegin = SceneView->Characters;
scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed;
scene_view_character_data *Character = CharacterBegin;
// sixten: check if the character exists
for(;Character < CharacterEnd; Character += 1)
{
if(AreEqual(Character->Name, Target))
{
break;
}
}
// sixten: if the character exists, request its deletion
if(Character != CharacterEnd)
{
Character->Talking = true;
}
}
static S2_CALL_FUNCTION(S2_Call_CharacterUnsetAllTalking)
{
scene_view *SceneView = (scene_view *)Runtime->Data;
scene_view_character_data *CharacterBegin = SceneView->Characters;
scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed;
scene_view_character_data *Character = CharacterBegin;
for(;Character < CharacterEnd; Character += 1)
{
Character->Talking = false;
}
}

View File

@ -1,3 +1,5 @@
#include "vn_scene_commands.cpp"
per_thread scene_view *ThreadLocal_SceneView = 0;
static void SV_SetState(scene_view *View)
@ -21,18 +23,13 @@ static void SV_Reset(void)
{
scene_view *SceneView = SV_GetState();
ArenaClear(SceneView->Runtime.ErrorArena);
S_ResetRuntime(&SceneView->Runtime);
// sixten: reset textbox
SceneView->Textbox.String.Count = 0;
// sixten: reset onscreen characters
SceneView->CharacterCount = 0;
SceneView->CharactersUsed = 0;
}
static void SV_LoadNavItems(void)
{
#if 0
scene_view *SceneView = SV_GetState();
temp Scratch = GetScratch();
string NavData = Platform_ReadEntireFile(Scratch.Arena, SceneView->Runtime.Compiled.NavFileName);
@ -117,60 +114,45 @@ static void SV_LoadNavItems(void)
}
}
ReleaseScratch(Scratch);
#endif
}
static void SV_SetCurrentSource(compiled_scene *Compiled)
static void SV_SetCurrentSource(compiled_scene2 *Compiled)
{
scene_view *SceneView = SV_GetState();
scene_runtime *Runtime = &SceneView->Runtime;
scene2_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);
ArenaClear(SceneView->SceneArena);
SceneView->Compiled = S2_CopyCompiledScene(SceneView->SceneArena, Compiled);
SV_LoadNavItems();
//- sixten: run top level
Runtime->CurrentProc = Runtime->Compiled.GlobalScope;
if(Runtime->CurrentProc)
{
temp 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;
S2_SetCurrentProc(Runtime, S2_ProcFromName(Compiled, StrLit("main")));
}
static void SV_Init(scene_view *SceneView, arena *TextboxArena)
static void SV_Init(scene_view *SceneView)
{
SV_SetState(SceneView);
SceneView->SceneArena = ArenaAlloc(Kilobytes(16), true);
SceneView->Runtime.ErrorArena = ArenaAlloc(Kilobytes(4), true);
SceneView->SceneArena = ArenaAlloc(Kilobytes(16), true, "Scene View Scene Arena");
SceneView->MessageArena = ArenaAlloc(Kilobytes(16), true, "Scene View Message Arena");
SceneView->Textbox.Capacity = 4096;
SceneView->Textbox.String.Data = PushArray(TextboxArena, u8, SceneView->Textbox.Capacity);
S2_Init(&SceneView->Runtime);
SV_Reset();
SceneView->Runtime.Data = SceneView;
SV_Reset();
}
static b32 SV_CurrentlyInProc(void)
{
scene_view *SceneView = SV_GetState();
b32 Result = (SceneView->Runtime.CurrentProc != 0);
b32 Result = (SceneView->Runtime.CurrentProc.Name.Count != 0);
return(Result);
}
@ -178,7 +160,7 @@ static scene_view_character_data *SV_FindTalkingCharacter(void)
{
scene_view *SceneView = SV_GetState();
scene_view_character_data *Result = 0;
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Character = SceneView->Characters+CharacterIndex;
if(Character->Talking)
@ -190,23 +172,6 @@ static scene_view_character_data *SV_FindTalkingCharacter(void)
return(Result);
}
static string SV_DisplayNameFromCharacter(scene_view_character_data *Character)
{
scene_view *SceneView = SV_GetState();
string Result = StrLit("invalid character");
if(Character)
{
Result = StrLit("undefined name");
scene_named_value *CharacterNameValue = S_FindGlobalVariableByName(&SceneView->Runtime, Character->Name, false);
if(CharacterNameValue && CharacterNameValue->Value.Kind == S_ValueKind_String)
{
Result = CharacterNameValue->Value.String;
}
}
return(Result);
}
struct text_properties
{
font_id Font;
@ -287,15 +252,17 @@ static r32 CalculateGlobalScaleFromDim(v2_r32 Dim)
}
static r32 CalculateGlobalScaleFromRootBox(ui_box *Box)
{
v2 RenderDim = UI_CalculateBoxDim(Box);
v2_r32 RenderDim = UI_CalculateBoxDim(Box);
r32 GlobalScale = SquareRoot(RenderDim.x*RenderDim.y)/45;
return(GlobalScale);
}
struct scene_textbox_data
{
textbox *Textbox;
ui_box *SceneViewBox;
char *TextboxData;
u64 TextboxUsed;
r32 TextboxRevealed;
ui_box *SceneViewBox;
string Name;
r32 NameT;
};
@ -303,37 +270,36 @@ struct scene_textbox_data
UI_CUSTOM_DRAW_CALLBACK(BuildSceneTextboxDrawCallback)
{
scene_textbox_data *TextboxData = (scene_textbox_data *)Data;
textbox *Textbox = TextboxData->Textbox;
r32 GlobalScale = CalculateGlobalScaleFromRootBox(TextboxData->SceneViewBox);
//- sixten: render textbox
{
v4 TopColor = V4(0, 0, 0, 0.8f);
v4 BottomColor = V4(0, 0, 0, 0.5f);
range2_r32 Dest = Pad(Range2R32(Box->Rect.Min, Box->Rect.Max), V2(GlobalScale, GlobalScale)*2.0f);
v4_r32 TopColor = V4R32(0, 0, 0, 0.8f);
v4_r32 BottomColor = V4R32(0, 0, 0, 0.5f);
range2_r32 Dest = Pad(Range2R32(Box->Rect.Min, Box->Rect.Max), V2R32(GlobalScale, GlobalScale)*2.0f);
PushQuad(Group, Dest, TopColor, TopColor, BottomColor, BottomColor, 0, GlobalScale, 0);
}
//- sixten: render text
{
string Text = Textbox->String;
r32 CharsRevealedT = Textbox->CharsRevealedT;
string Text = MakeString((u8 *)TextboxData->TextboxData, TextboxData->TextboxUsed);
r32 RevealedT = TextboxData->TextboxRevealed;
text_properties Properties = {};
Properties.Font = Font_Fancy;
Properties.FontSize = GlobalScale;
Properties.LineHeight = GlobalScale*1.5f;
r32 Padding = 1.5f*GlobalScale;
v2 Offset = V2R32(Padding, Padding);
RenderAnimatedText(Group, Atlas, Properties, Text, CharsRevealedT, Box->Rect.Min+Offset, DimOfRange(Box->Rect).x-2*Padding);
v2_r32 Offset = V2R32(Padding, Padding);
RenderAnimatedText(Group, Atlas, Properties, Text, RevealedT, 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);
v2_r32 TextP = Box->Rect.Min + V2R32(1.5f*GlobalScale, -GlobalScale*T);
PushText(Group, Atlas, Font_Fancy, TextP+V2R32(GlobalScale*0.1, GlobalScale*0.1), GlobalScale, SetAlpha(Color_Black, T), Name);
PushText(Group, Atlas, Font_Fancy, TextP, GlobalScale, SetAlpha(Color_White, T), Name);
}
@ -341,25 +307,24 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneTextboxDrawCallback)
static void SV_DrawBackground(scene_view *SceneView, ui_box *Box, render_group *Group)
{
v2 RenderDim = DimOfRange(Box->Rect);
v2_r32 RenderDim = DimOfRange(Box->Rect);
render_handle Texture = TextureFromAssetID(SceneView->Runtime.Compiled.BackgroundTexture);
render_handle Texture = A_TextureFromAssetID(AssetID_DemoBackground);;//A_TextureFromAssetID(SceneView->Runtime.Compiled.BackgroundTexture);
//- sixten: render background
#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)));
v2_r32 Offset = V2R32(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-V2R32(r, r)+Offset, RenderDim+Box->Rect.Min+V2R32(r, r)+Offset);
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(Texture)));
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, Texture);
#else
range2_r32 BackgroundDest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min);
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, Texture);
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(Texture)));
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, 0, 0, 0, Texture);
#endif
}
UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback)
@ -367,11 +332,11 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback)
scene_view *SceneView = (scene_view *)Data;
SV_DrawBackground(SceneView, Box, Group);
v2 RenderDim = DimOfRange(Box->Rect);
v2_r32 RenderDim = DimOfRange(Box->Rect);
r32 GlobalScale = CalculateGlobalScaleFromDim(RenderDim);
//- sixten: render characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Character = SceneView->Characters + CharacterIndex;
@ -384,7 +349,7 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback)
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 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, 0, 0, 0, CharacterHandle);
}
}
@ -405,12 +370,13 @@ static void BuildProcView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
r32 ActiveScale = GlobalScale * 0.75f;
scene_runtime *Runtime = &View->Runtime;
textbox *Textbox = &View->Textbox;
//scene2_runtime *Runtime = &View->Runtime;
//textbox *Textbox = &View->Textbox;
//- sixten: build branches
UI_FillPadding UI_WidthFill UI_Height(UI_Pixels(2*ActiveScale, 1)) UI_Row() UI_FillPadding UI_Column() UI_FillPadding
{
#if 0
b32 FoundOffset = false;
s64 Offset = 0;
for(s32 BranchIndex = 0; BranchIndex < Runtime->BranchCount; BranchIndex += 1)
@ -432,6 +398,7 @@ static void BuildProcView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
Runtime->IP += 1+Offset;
Runtime->BranchCount = 0;
}
#endif
}
//- sixten: build textbox
@ -440,11 +407,13 @@ static void BuildProcView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
ui_box *TextBox = UI_MakeBox(0, StrLit("Scene Textbox"));
scene_textbox_data *TextboxData = PushStruct(UI_FrameArena(), scene_textbox_data);
TextboxData->Textbox = Textbox;
TextboxData->TextboxData = View->TextboxData;
TextboxData->TextboxUsed = View->TextboxUsed;
TextboxData->TextboxRevealed = View->TextboxRevealed;
TextboxData->SceneViewBox = Box;
scene_view_character_data *TalkingCharacter = SV_FindTalkingCharacter();
TextboxData->Name = SV_DisplayNameFromCharacter(TalkingCharacter);
TextboxData->Name = TalkingCharacter ? TalkingCharacter->Name : StrLit("");
TextboxData->NameT = AC_AnimateValueF(TalkingCharacter != 0, 0, 0.3f, "Scene View Talking Character %p", View);
UI_EquipBoxCustomDrawCallback(TextBox, BuildSceneTextboxDrawCallback, TextboxData);
@ -462,7 +431,7 @@ struct scene_nav_item_info
UI_CUSTOM_DRAW_CALLBACK(BuildNavItemDrawCallback)
{
scene_nav_item_info *Info = (scene_nav_item_info *)Data;
render_handle Texture = TextureFromAssetID(Info->Item->TextureID);
render_handle Texture = A_TextureFromAssetID(Info->Item->TextureID);
v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture));
range2_r32 DestRect = Range2R32(Box->Rect.Min, Box->Rect.Max);
@ -470,7 +439,7 @@ UI_CUSTOM_DRAW_CALLBACK(BuildNavItemDrawCallback)
v4_r32 Color = LinearBlend(Color_Grey, Color_White, Info->Signal.Hovering);
PushTexturedQuad(Group, DestRect, SourceRect, Color, Color, Color, Color, 0, 0, 0, Texture);
PushTexturedQuad(Group, DestRect, SourceRect, Color, Color, Color, Color, 0, 0, 0, 0, 0, 0, Texture);
}
inline u32 U32FromRawR32(r32 Value)
@ -486,7 +455,7 @@ static ui_signal SV_BuildNavItem(scene_nav_item *Item, r32 GlobalScale, v2_r32 G
scene_nav_item_info *Data = PushStruct(UI_FrameArena(), scene_nav_item_info);
Data->Item = Item;
render_handle Texture = TextureFromAssetID(Item->TextureID);
render_handle Texture = A_TextureFromAssetID(Item->TextureID);
v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture));
v2_r32 TextureOrigin = Hadamard(TextureDim, Item->Origin);
@ -537,7 +506,7 @@ static void BuildNavView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
// sixten: apply the action
if(Item->Action.Kind == S_NavAction_Proc)
{
S_SetCurrentProc(&View->Runtime, S_FindProcByName(&View->Runtime.Compiled, Item->Action.Content));
S2_SetCurrentProc(&View->Runtime, S2_ProcFromName(&View->Compiled, Item->Action.Content));
}
else if(Item->Action.Kind == S_NavAction_Scene)
{
@ -545,7 +514,7 @@ static void BuildNavView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
string Filepath = PushFormat(Scratch.Arena, "data/%S.vns", Item->Action.Content);;
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, Filepath);
compiled_scene Scene = S_ScriptFromText(Scratch.Arena, SceneInput);
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, SceneInput);
SV_SetCurrentSource(&Scene);
ReleaseScratch(Scratch);
@ -592,7 +561,7 @@ static void BuildScene(scene_view *View)
}
}
static void BuildErrorScreen(scene_runtime *Runtime, vn_input *Input)
static void BuildErrorScreen(scene_view *SceneView, vn_input *Input)
{
UI_SetNextLayoutAxis(Axis2_X);
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("Container")))
@ -601,14 +570,14 @@ 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");
s64 ErrorIndex = 0;
for(scene_runtime_error *Error = Runtime->Errors.First; Error != 0; Error = Error->Next, ErrorIndex += 1)
for(scene2_message *Message = SceneView->Messages.First; Message != 0; Message = Message->Next, ErrorIndex += 1)
{
UI_Spacer(UI_Em(3, 1));
UI_SetNextCornerRadius(3);
UI_Size(UI_Percent(1, 1), UI_Percent(1, 0)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawDropShadow|UI_BoxFlag_DrawBorder, "%i", ErrorIndex))
UI_Size(UI_TextContent(30, 1), UI_TextContent(30, 1))
{
UI_LabelF("Message: %S", Error->Message);
UI_Label(Message->Message);
}
}
UI_Spacer(UI_Em(3, 1));
@ -622,8 +591,8 @@ static void BuildErrorScreen(scene_runtime *Runtime, vn_input *Input)
}
if(IgnoreSignal.Clicked)
{
ZeroStruct(&Runtime->Errors);
ArenaClear(Runtime->ErrorArena);
ZeroStruct(&SceneView->Messages);
ArenaClear(SceneView->MessageArena);
}
UI_Spacer(UI_Em(1, 1));
@ -654,7 +623,7 @@ static scene_view_character_data *SV_CharacterDataFromName(string Name)
scene_view *View = SV_GetState();
for(s32 CharacterIndex = 0; CharacterIndex < View->CharacterCount; CharacterIndex += 1)
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Character = View->Characters + CharacterIndex;
if(AreEqual(Character->Name, Name))
@ -665,32 +634,38 @@ static scene_view_character_data *SV_CharacterDataFromName(string Name)
}
//- sixten: create character if not initialized
if(!Result && View->CharacterCount < ArrayCount(View->Characters))
if(!Result && View->CharactersUsed < ArrayCount(View->Characters))
{
s32 CharacterIndex = View->CharacterCount;
View->CharacterCount += 1;
s32 CharacterIndex = View->CharactersUsed;
View->CharactersUsed += 1;
Result = View->Characters + CharacterIndex;
*Result = {};
Result->Name = Name;
Result->Active = true;
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharacterCount + 1);
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharactersUsed + 1);
}
return(Result);
}
#if 0
static scene_view_character_texture_info SV_CharacterTextureFromAction(scene_character_action *Action)
{
scene_view_character_texture_info Result = {};
Result.Texture = EmptyRenderHandle();
Result.Scale = 1.0f;
scene_view *View = SV_GetState();
asset_id AssetID = Action->State;
Result.Texture = A_TextureFromAssetID(AssetID);
Result.Scale = A_ScaleFromAssetID(AssetID);
if(AreEqual(StrLit("arthur"), Action->Target))
#if 0
if(AreEqual(StrLit("arthur"), Action->Target))
{
switch(Action->State)
switch(Action->State)
{
case CR_State_Normal: { Result.Texture = View->TestNormal; } break;
case CR_State_Happy: { Result.Texture = View->TestHappy; } break;
@ -708,15 +683,17 @@ static scene_view_character_texture_info SV_CharacterTextureFromAction(scene_cha
}
Result.Scale = 0.033f;
}
#endif
return(Result);
}
#endif
static r32 SV_CalculateTargetPctP(s32 TrueCharacterIndex)
{
scene_view *View = SV_GetState();
s32 CharacterCount = 0;
s32 AssumedCharacterIndex = 0;
for(s32 CharacterIndex = 0; CharacterIndex < View->CharacterCount; CharacterIndex += 1)
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Data = View->Characters + CharacterIndex;
if(Data->Active)
@ -734,122 +711,161 @@ static r32 SV_CalculateTargetPctP(s32 TrueCharacterIndex)
static void SV_UpdateInDialog(arena *FrameArena)
{
scene_view *SceneView = SV_GetState();
textbox *Textbox = &SceneView->Textbox;
scene_runtime *Runtime = &SceneView->Runtime;
platform_event_list *EventList = SceneView->EventList;
r32 dtForFrame = SceneView->dtForFrame;
compiled_scene *Compiled = &Runtime->Compiled;
scene_view *SceneView = SV_GetState();
if(Compiled && Compiled->IsValid)
{
//- sixten: gather user input
b32 MousePressed = false;
for(platform_event *Event = EventList->First; Event != 0; Event = Event->Next)
{
if(Event->Type == PlatformEvent_Press && Event->Key == Key_MouseLeft)
{
MousePressed = true;
}
}
//- sixten: gather user input
b32 MousePressed = false;
for(platform_event *Event = SceneView->EventList->First; Event != 0; Event = Event->Next)
{
if(Event->Type == PlatformEvent_Press && Event->Key == Key_MouseLeft)
{
MousePressed = true;
}
}
b32 PlayerAction = (Platform_KeyPress(SceneView->EventList, Key_Space)||MousePressed);
b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||MousePressed);
//- sixten: check if we can skip the current textbox
if(PlayerAction && SceneView->TextboxRevealed < SceneView->TextboxUsed)
{
PlayerAction = false;
SceneView->TextboxRevealed = SceneView->TextboxUsed;
}
//- sixten: run the scene
if(!Runtime->LastResult.HadError)
{
b32 AdvanceOnAwait = (Textbox->CharsRevealed >= Textbox->String.Count) && PlayerAction;
//- sixten: update the textbox
r32 CharsPerSecond = 25.0f;
SceneView->TextboxRevealed = Min((r32)SceneView->TextboxUsed, SceneView->TextboxRevealed+CharsPerSecond*SceneView->dtForFrame);
for(;;)
{
scene_runtime_result RunResult = S_Run(Runtime, FrameArena, AdvanceOnAwait);
if(RunResult.ReachedAwait || RunResult.HadError)
{
break;
}
}
}
//- sixten: advance textbox
{
r32 CharsPerSecond = 25.0f;
Textbox->CharsRevealed += dtForFrame*CharsPerSecond;
Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count);
//- sixten: run the runtime
scene2_run_result RunResult = S2_Run(FrameArena, &SceneView->Runtime, &SceneView->Compiled, PlayerAction);
if(Textbox->CharsRevealed < Textbox->String.Count && PlayerAction)
{
Textbox->CharsRevealed = Textbox->String.Count;
}
//- sixten: append messages
S2_ConcatMessageList(SceneView->MessageArena, &SceneView->Messages, &RunResult.Messages);
AC_AnimateValueDirect(Textbox->CharsRevealed, 0.05f, &Textbox->CharsRevealedT);
}
for(scene2_action *Action = RunResult.Actions.First; Action != 0; Action = Action->Next)
{
switch(Action->Kind)
{
case S2_ActionKind_None: { InvalidCodepath; } break;
InvalidDefaultCase;
}
}
//- sixten: apply the textbox actions
for(scene_textbox_action *Action = Runtime->FirstTextboxAction; Action != 0; Action = Action->Next)
{
if(Action->Kind == S_TextboxActionKind_Set)
{
string ReplaceString = Action->String;
Textbox->String.Count = Min(ReplaceString.Count, Textbox->Capacity);
Copy(Textbox->String.Data, ReplaceString.Data, Textbox->String.Count);
Textbox->CharsRevealedT = 0;
Textbox->CharsRevealed = 0;
}
else if(Action->Kind == S_TextboxActionKind_Append)
{
string Addend = Action->String;
Textbox->CharsRevealedT = Textbox->String.Count;
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);
Textbox->String.Count = NewCount;
}
else
{
InvalidCodepath;
}
}
Runtime->FirstTextboxAction = Runtime->LastTextboxAction = 0;
#if 0
scene_view *SceneView = SV_GetState();
textbox *Textbox = &SceneView->Textbox;
scene2_runtime *Runtime = &SceneView->Runtime;
platform_event_list *EventList = SceneView->EventList;
r32 dtForFrame = SceneView->dtForFrame;
compiled_scene2 *Compiled = &Runtime->Compiled;
// sixten: update character state only if there has been a change
if(Runtime->FirstCharacterAction != 0)
{
//- sixten: make all characters non-talking
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
Data->Talking = false;
}
if(Compiled && Compiled->IsValid)
{
//- sixten: gather user input
b32 MousePressed = false;
for(platform_event *Event = EventList->First; Event != 0; Event = Event->Next)
{
if(Event->Type == PlatformEvent_Press && Event->Key == Key_MouseLeft)
{
MousePressed = true;
}
}
//- sixten: apply character actions
for(scene_character_action *Action = Runtime->FirstCharacterAction; Action != 0; Action = Action->Next)
{
// sixten: find character
scene_view_character_data *Data = SV_CharacterDataFromName(Action->Target);
b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||MousePressed);
if(Action->State == CR_State_None)
{
Data->Active = false;
}
else
{
if(Action->State != CR_State_Invalid)
{
Data->Info = SV_CharacterTextureFromAction(Action);
}
Data->Talking = true;
//- sixten: run the scene
if(!Runtime->LastResult.HadError)
{
b32 AdvanceOnAwait = (Textbox->CharsRevealed >= Textbox->String.Count) && PlayerAction;
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;
}
}
}
}
for(;;)
{
scene_runtime_result RunResult = S_Run(Runtime, FrameArena, AdvanceOnAwait);
if(RunResult.ReachedAwait || RunResult.HadError)
{
break;
}
}
}
Runtime->FirstCharacterAction = Runtime->LastCharacterAction = 0;
}
//- sixten: advance textbox
{
r32 CharsPerSecond = 25.0f;
Textbox->CharsRevealed += dtForFrame*CharsPerSecond;
Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count);
if(Textbox->CharsRevealed < Textbox->String.Count && PlayerAction)
{
Textbox->CharsRevealed = Textbox->String.Count;
}
AC_AnimateValueDirect(Textbox->CharsRevealed, 0.05f, &Textbox->CharsRevealedT);
}
//- sixten: apply the textbox actions
for(scene_textbox_action *Action = Runtime->FirstTextboxAction; Action != 0; Action = Action->Next)
{
if(Action->Kind == S_TextboxActionKind_Set)
{
string ReplaceString = Action->String;
Textbox->String.Count = Min(ReplaceString.Count, Textbox->Capacity);
Copy(Textbox->String.Data, ReplaceString.Data, Textbox->String.Count);
Textbox->CharsRevealedT = 0;
Textbox->CharsRevealed = 0;
}
else if(Action->Kind == S_TextboxActionKind_Append)
{
string Addend = Action->String;
Textbox->CharsRevealedT = Textbox->String.Count;
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);
Textbox->String.Count = NewCount;
}
else
{
InvalidCodepath;
}
}
Runtime->FirstTextboxAction = Runtime->LastTextboxAction = 0;
// sixten: update character state only if there has been a change
if(Runtime->FirstCharacterAction != 0)
{
//- sixten: make all characters non-talking
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
Data->Talking = false;
}
//- sixten: apply character actions
for(scene_character_action *Action = Runtime->FirstCharacterAction; Action != 0; Action = Action->Next)
{
// sixten: find character
scene_view_character_data *Data = SV_CharacterDataFromName(Action->Target);
if(Action->StateModified)
{
if(Action->State == AssetID_None)
{
Data->Active = false;
}
else
{
Data->Info = SV_CharacterTextureFromAction(Action);
Data->Talking = true;
}
}
else
{
Data->Talking = true;
}
}
}
Runtime->FirstCharacterAction = Runtime->LastCharacterAction = 0;
}
#endif
}
static void SV_Update(arena *FrameArena)
@ -858,7 +874,7 @@ static void SV_Update(arena *FrameArena)
//- sixten: update the characters
{
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
@ -878,22 +894,22 @@ static void SV_Update(arena *FrameArena)
}
else
{
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharacterCount+1);
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharactersUsed+1);
}
AC_AnimateValueDirect(TargetPctP, 0.4f, &Data->PctP);
}
}
//- sixten: prune any unactive characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
if(!Data->Active && Data->ActiveT < 0.01)
{
Move(Data, Data+1, (SceneView->CharacterCount-CharacterIndex-1)*sizeof(scene_view_character_data));
SceneView->CharacterCount -= 1;
CharacterIndex -= 1;
}
// sixten: prune any unactive characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
if(!Data->Active && Data->ActiveT < 0.01)
{
Move(Data, Data+1, (SceneView->CharactersUsed-CharacterIndex-1)*sizeof(scene_view_character_data));
SceneView->CharactersUsed -= 1;
CharacterIndex -= 1;
}
}
}
//- sixten: update scene
@ -901,26 +917,31 @@ static void SV_Update(arena *FrameArena)
{
SV_UpdateInDialog(FrameArena);
}
else
{
}
}
static void SV_BuildSceneView(vn_input *Input)
{
scene_view *SceneView = SV_GetState();
scene_runtime_result LastRun = SceneView->Runtime.LastResult;
if(LastRun.HadError)
{
BuildErrorScreen(&SceneView->Runtime, Input);
}
else if(SceneView->Runtime.Compiled.IsValid)
{
BuildScene(SceneView);
}
else
{
UI_LabelF("Invalid source");
}
scene_view *SceneView = SV_GetState();
if(SceneView->Messages.Count != 0)
{
BuildErrorScreen(SceneView, Input);
}
else
{
BuildScene(SceneView);
}
}
#if 0
scene_user_input Input = SV_GatherInputs(); // note that we here could consume a player interaction for skipping the text
scene_runtime_result Result = S_Run(&Runtime, &Inputs);
for(scene_action *Action = Result.FirstAction; Action != 0; Action = Action->Next)
{
switch(Action->Kind)
{
...
}
}
#endif

View File

@ -3,14 +3,6 @@
#ifndef VN_SCENE_VIEW_H
#define VN_SCENE_VIEW_H
struct textbox
{
string String;
s64 Capacity;
r32 CharsRevealedT;
r32 CharsRevealed;
};
struct scene_view_character_texture_info
{
render_handle Texture;
@ -79,12 +71,21 @@ struct scene_view
arena *SceneArena;
//- sixten: state
scene_runtime Runtime;
textbox Textbox;
scene2_runtime Runtime;
compiled_scene2 Compiled;
//- sixten: characters
s32 CharacterCount;
//- sixten: messages
arena *MessageArena;
scene2_message_list Messages;
//- sixten: textbox
char TextboxData[1024];
u64 TextboxUsed;
r32 TextboxRevealed;
//- sixten: characters
scene_view_character_data Characters[16];
u64 CharactersUsed;
//- sixten: nav items
scene_nav_item *NavItems;
@ -93,13 +94,6 @@ struct scene_view
//- sixten: input per frame
platform_event_list *EventList;
r32 dtForFrame;
//- sixten: temporary texture hub
render_handle BackgroundTexture;
render_handle TestHappy;
render_handle TestNormal;
render_handle MonikaLeaning;
};
static void SV_SetState(scene_view *View);
@ -107,8 +101,8 @@ static scene_view *SV_GetState();
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_Init(scene_view *View, arena *TextboxArena);
static void SV_SetCurrentSource(compiled_scene2 *Compiled);
static void SV_Init(scene_view *View);
static b32 SV_CurrentlyInProc(void);

View File

@ -3,9 +3,9 @@
#ifndef VN_THEME_DARK_H
#define VN_THEME_DARK_H
read_only v4 Theme_TextColor = V4(0.8, 0.8, 0.8, 1.0);
read_only v4 Theme_BackgroundColor = V4(0.1, 0.1, 0.1, 1.0);
read_only v4 Theme_BorderColor = V4(0.3, 0.3, 0.3, 1.0);
read_only v4 Theme_HighlightBorderColor = V4(0.6, 0.3, 0.1, 1.0);
read_only v4_r32 Theme_TextColor = V4R32(0.8, 0.8, 0.8, 1.0);
read_only v4_r32 Theme_BackgroundColor = V4R32(0.1, 0.1, 0.1, 1.0);
read_only v4_r32 Theme_BorderColor = V4R32(0.3, 0.3, 0.3, 1.0);
read_only v4_r32 Theme_HighlightBorderColor = V4R32(0.6, 0.3, 0.1, 1.0);
#endif //VN_THEME_DARK_H

View File

@ -1,61 +0,0 @@
/* date = April 30th 2023 11:35 am */
#ifndef VN_THREAD_CONTEXT_H
#define VN_THREAD_CONTEXT_H
#define per_thread __declspec(thread)
struct thread_context
{
memory_arena Arenas[2];
};
per_thread thread_context *ThreadLocal_ThreadContext = 0;
inline void SetThreadContext(thread_context *Context)
{
ThreadLocal_ThreadContext = Context;
}
inline thread_context *GetThreadContext(void)
{
return(ThreadLocal_ThreadContext);
}
static temporary_memory GetScratch(memory_arena **Conflicts = 0, u64 ConflictCount = 0)
{
temporary_memory Scratch = {};
thread_context *Context = GetThreadContext();
for(u64 ArenaIndex = 0;
ArenaIndex < ArrayCount(Context->Arenas);
++ArenaIndex)
{
b32 FoundConflict = false;
for(u64 ConflictIndex = 0;
ConflictIndex < ConflictCount;
++ConflictIndex)
{
memory_arena *Conflict = Conflicts[ConflictIndex];
if(Conflict == Context->Arenas + ArenaIndex)
{
FoundConflict = true;
break;
}
}
if(!FoundConflict)
{
Scratch = BeginTemporaryMemory(Context->Arenas + ArenaIndex);
break;
}
}
Assert(Scratch.Arena);
return(Scratch);
}
#define ReleaseScratch(Scratch) EndTemp(Scratch)
#endif //VN_THREAD_CONTEXT_H

View File

@ -140,9 +140,9 @@ static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_f
//- sixten: identifiers
if(TokenKind == TokenKind_None && (('A' <= *Byte && *Byte <= 'Z') ||
('a' <= *Byte && *Byte <= 'z') ||
(UTF8Lengths[*Byte>>3] > 1) ||
*Byte == '_'))
('a' <= *Byte && *Byte <= 'z') ||
(UTF8Lengths[*Byte>>3] > 1) ||
*Byte == '_'))
{
TokenKind = TokenKind_Identifier;
TokenStart = Byte;
@ -151,10 +151,10 @@ static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_f
for(;Byte <= TextEnd; Byte += UTF8Lengths[*Byte>>3])
{
if(Byte == TextEnd || !(('A' <= *Byte && *Byte <= 'Z') ||
('a' <= *Byte && *Byte <= 'z') ||
('0' <= *Byte && *Byte <= '9') ||
(UTF8Lengths[*Byte>>3] > 1) ||
*Byte == '_'))
('a' <= *Byte && *Byte <= 'z') ||
('0' <= *Byte && *Byte <= '9') ||
(UTF8Lengths[*Byte>>3] > 1) ||
*Byte == '_'))
{
TokenEnd = Byte;
break;
@ -163,25 +163,24 @@ static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_f
string String = MakeString(TokenStart, TokenEnd-TokenStart);
if(0) {}
else if(AreEqual(String, StrLit("and"))) { TokenKind = TokenKind_And; }
else if(AreEqual(String, StrLit("branch"))) { TokenKind = TokenKind_Branch; }
else if(AreEqual(String, StrLit("else"))) { TokenKind = TokenKind_Else; }
else if(AreEqual(String, StrLit("false"))) { TokenKind = TokenKind_False; }
else if(AreEqual(String, StrLit("for"))) { TokenKind = TokenKind_For; }
else if(AreEqual(String, StrLit("if"))) { TokenKind = TokenKind_If; }
else if(AreEqual(String, StrLit("then"))) { TokenKind = TokenKind_Then; }
else if(AreEqual(String, StrLit("jump"))) { TokenKind = TokenKind_Jump; }
else if(AreEqual(String, StrLit("or"))) { TokenKind = TokenKind_Or; }
else if(AreEqual(String, StrLit("proc"))) { TokenKind = TokenKind_Proc; }
else if(AreEqual(String, StrLit("true"))) { TokenKind = TokenKind_True; }
else if(AreEqual(String, StrLit("var"))) { TokenKind = TokenKind_Var; }
else if(AreEqual(String, StrLit("let"))) { TokenKind = TokenKind_Let; }
else if(AreEqual(String, StrLit("while"))) { TokenKind = TokenKind_While; }
else if(AreEqual(String, StrLit("nav"))) { TokenKind = TokenKind_Nav; }
else if(AreEqual(String, StrLit("background"))) { TokenKind = TokenKind_Background; }
else if(AreEqual(String, StrLit("call"))) { TokenKind = TokenKind_Call; }
else if(AreEqual(String, StrLit("wait"))) { TokenKind = TokenKind_Wait; }
else if(AreEqual(String, StrLit("end"))) { TokenKind = TokenKind_End; }
}
//- sixten: numerics
if(TokenKind == TokenKind_None && (('0' <= *Byte && *Byte <= '9') ||
(*Byte == '-' && Byte + 1 < TextEnd && '0' <= Byte[1] && Byte[1] <= '9')))
(*Byte == '-' && Byte + 1 < TextEnd && '0' <= Byte[1] && Byte[1] <= '9')))
{
TokenKind = TokenKind_Numeric;
TokenStart = Byte;
@ -191,8 +190,8 @@ static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_f
{
TokenEnd += 1;
if(Byte == TextEnd ||
!(('0' <= *Byte && *Byte <= '9') ||
*Byte == '_' || *Byte == '.'))
!(('0' <= *Byte && *Byte <= '9') ||
*Byte == '_' || *Byte == '.'))
{
break;
}
@ -225,9 +224,8 @@ static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_f
//- sixten: symbols
if(TokenKind == TokenKind_None && (*Byte == '{' || *Byte == '}' || *Byte == '(' || *Byte == ')' ||
*Byte == ',' || *Byte == '.' || *Byte == '@' || *Byte == '#' ||
*Byte == ';' || *Byte == '+' || *Byte == '-' || *Byte == '*' ||
*Byte == '/'))
*Byte == ',' || *Byte == '.' || *Byte == '$' || *Byte == ';' ||
*Byte == '+' || *Byte == '-' || *Byte == '*' || *Byte == '/'))
{
TokenStart = Byte;
TokenEnd = Byte+1;
@ -240,8 +238,7 @@ static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_f
case ')': { TokenKind = TokenKind_ParenthesisClose; } break;
case ',': { TokenKind = TokenKind_Comma; } break;
case '.': { TokenKind = TokenKind_Dot; } break;
case '@': { TokenKind = TokenKind_At; } break;
case '#': { TokenKind = TokenKind_PoundSign; } break;
case '$': { TokenKind = TokenKind_DollarSign; } break;
case ';': { TokenKind = TokenKind_Semicolon; } break;
case '+': { TokenKind = TokenKind_Plus; } break;
case '-': { TokenKind = TokenKind_Minus; } break;

View File

@ -23,8 +23,7 @@ enum token_kind
TokenKind_ParenthesisClose,
TokenKind_Comma,
TokenKind_Dot,
TokenKind_At,
TokenKind_PoundSign,
TokenKind_DollarSign,
TokenKind_Semicolon,
TokenKind_Plus,
TokenKind_Minus,
@ -43,20 +42,19 @@ enum token_kind
// sixten: keywords
TokenKind_KeywordsBegin,
TokenKind_And,
TokenKind_Branch,
TokenKind_Else,
TokenKind_False,
TokenKind_For,
TokenKind_If,
TokenKind_Then,
TokenKind_While,
TokenKind_Jump,
TokenKind_Or,
TokenKind_Proc,
TokenKind_True,
TokenKind_Var,
TokenKind_While,
TokenKind_Nav,
TokenKind_Background,
TokenKind_Let,
TokenKind_Call,
TokenKind_Wait,
TokenKind_End,
TokenKind_KeywordsEnd,
// sixten: whitespace
@ -79,6 +77,8 @@ struct token
s64 Line;
};
global read_only token T_EmptyToken = {};
struct token_chunk_node
{
token *Tokens;

View File

@ -51,7 +51,7 @@ inline glyph_atlas *UI_GlyphAtlas(void)
return(UI_GetState()->GlyphAtlas);
}
inline void UI_SetDragStartP(v2 P)
inline void UI_SetDragStartP(v2_r32 P)
{
ui *UI = UI_GetState();
UI->DragStartP = P;
@ -63,22 +63,22 @@ inline void UI_UpdateDragStartP(void)
UI->DragStartP = UI->MouseP;
}
inline v2 UI_GetDragStartP(void)
inline v2_r32 UI_GetDragStartP(void)
{
ui *UI = UI_GetState();
return(UI->DragStartP);
}
inline void UI_StoreDragV2(v2 DragData)
inline void UI_StoreDragV2(v2_r32 DragData)
{
ui *UI = UI_GetState();
*(v2 *)&UI->DragData = DragData;
*(v2_r32 *)&UI->DragData = DragData;
}
inline v2 UI_GetDragV2(void)
inline v2_r32 UI_GetDragV2(void)
{
ui *UI = UI_GetState();
v2 Result = *(v2 *)UI->DragData;
v2_r32 Result = *(v2_r32 *)UI->DragData;
return(Result);
}
@ -127,7 +127,7 @@ static r64 UI_Time(void)
static r64 UI_Blink(void)
{
return(Cos(UI_GetState()->BlinkTime*10.0f)*0.5f+0.5f);
return(Cos(UI_GetState()->BlinkTime*6.0f)*0.5f+0.5f);
}
static void UI_ResetBlink(void)
@ -170,13 +170,13 @@ static string UI_BoxStringFromKey(ui_key Key)
if(!AreEqual(Key, UI_EmptyKey()))
{
for(s32 BucketIndex = 0;
BucketIndex < ArrayCount(UI->BoxBuckets);
++BucketIndex)
BucketIndex < ArrayCount(UI->BoxBuckets);
++BucketIndex)
{
ui_box_bucket *Bucket = UI->BoxBuckets + BucketIndex;
for(ui_box *Box = Bucket->First;
Box != 0;
Box = Box->HashNext)
Box != 0;
Box = Box->HashNext)
{
if(AreEqual(Key, Box->Key))
{
@ -202,8 +202,8 @@ inline ui_box *UI_BoxFromKey(ui *UI, ui_key Key)
if(!AreEqual(Key, UI_EmptyKey()))
{
for(ui_box *Box = Bucket->First;
Box != 0;
Box = Box->HashNext)
Box != 0;
Box = Box->HashNext)
{
if(AreEqual(Box->Key, Key))
{
@ -259,8 +259,8 @@ inline ui_box *UI_MakeBox(ui_box_flags Flags, string String)
if(Parent && !AreEqual(Key, UI_EmptyKey()))
{
for(ui_box *Child = Parent->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
Assert(!AreEqual(Child->Key, Key));
}
@ -272,8 +272,8 @@ inline ui_box *UI_MakeBox(ui_box_flags Flags, string String)
Box->First = Box->Last = Box->Next = Box->Prev = Box->Parent = 0;
Box->ComputedRelativeP = V2(0, 0);
Box->ComputedDim = V2(0, 0);
Box->ComputedRelativeP = V2R32(0, 0);
Box->ComputedDim = V2R32(0, 0);
Box->LastFrameTouched = UI->CurrentFrame;
@ -341,13 +341,13 @@ static void UI_EquipBoxCustomDrawCallback(ui_box *Box, ui_custom_draw_callback *
}
// sixten(NOTE): ClippingRect = Intersection(TrueClippingRect, Parent->Rect);
static b32 UI_ChildrenContainsP(ui_box *Parent, v2 P, range2_r32 Clip)
static b32 UI_ChildrenContainsP(ui_box *Parent, v2_r32 P, range2_r32 Clip)
{
b32 Result = false;
for(ui_box *Child = Parent->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
range2_r32 IntersectionRect = Intersection(Clip, Child->Rect);
@ -391,8 +391,8 @@ static ui_signal UI_SignalFromBox(ui_box *Box)
// sixten: Gather the clipping rects of all the parents.
range2_r32 ClippedRect = Box->Rect;
for(ui_box *Parent = Box->Parent;
Parent != 0;
Parent = Parent->Parent)
Parent != 0;
Parent = Parent->Parent)
{
if(Parent->Flags & UI_BoxFlag_Clip)
{
@ -421,8 +421,8 @@ static ui_signal UI_SignalFromBox(ui_box *Box)
// sixten: Are we the tooltip?
b32 FoundTooltip = false;
for(ui_box *Parent = Box->Parent;
Parent != 0;
Parent = Parent->Parent)
Parent != 0;
Parent = Parent->Parent)
{
if(Parent == UI->TooltipNode)
{
@ -434,7 +434,7 @@ static ui_signal UI_SignalFromBox(ui_box *Box)
if(!FoundTooltip)
{
Signal.Hovering &= ~UI_ChildrenContainsP(UI->TooltipNode, UI->MouseP,
Range2R32(V2(0, 0), V2(InfinityR32, InfinityR32)));
Range2R32(V2R32(0, 0), V2R32(InfinityR32, InfinityR32)));
}
}
@ -512,8 +512,8 @@ static void UI_SolveSizeViolations(ui_box *Box, axis2 Axis)
if(!(Box->Flags & (UI_BoxFlag_OverflowX<<Axis)))
{
for(ui_box *Child = Box->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
if(!(Child->Flags & (UI_BoxFlag_FloatingX<<Axis)))
{
@ -533,8 +533,8 @@ static void UI_SolveSizeViolations(ui_box *Box, axis2 Axis)
if(Violation > 0 && FixupBudget > 0)
{
for(ui_box *Child = Box->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
if(!(Child->Flags & (UI_BoxFlag_FloatingX<<Axis)))
{
@ -560,8 +560,8 @@ static void UI_SolveSizeViolations(ui_box *Box, axis2 Axis)
{
r32 Position = 0;
for(ui_box *Child = Box->First;
Child;
Child = Child->Next)
Child;
Child = Child->Next)
{
if((Child->Flags & (UI_BoxFlag_FloatingX<<Axis)))
{
@ -577,8 +577,8 @@ static void UI_SolveSizeViolations(ui_box *Box, axis2 Axis)
else
{
for(ui_box *Child = Box->First;
Child;
Child = Child->Next)
Child;
Child = Child->Next)
{
if((Child->Flags & (UI_BoxFlag_FloatingX<<Axis)))
{
@ -619,31 +619,36 @@ static void UI_DrawBox(ui_box *Box, render_group *Group, glyph_atlas *GlyphAtlas
if(Box->Flags & UI_BoxFlag_DrawBackground)
{
PushQuad(Group, Box->Rect, Box->BackgroundColor, Box->CornerRadius, 0, 0);
PushQuad(Group, Box->Rect, Box->BackgroundColor,
Box->CornerRadii.x, Box->CornerRadii.y, Box->CornerRadii.z, Box->CornerRadii.w,
0, 0);
}
if(Box->Flags & UI_BoxFlag_HotAnimation)
{
v4 Top = V4(1, 1, 1, 0.08F*Box->HotTransition);
v4 Bottom = V4(1, 1, 1, 0.0);
v4_r32 Top = V4R32(1, 1, 1, 0.08F*Box->HotTransition);
v4_r32 Bottom = V4R32(1, 1, 1, 0.0);
PushQuad(Group, Box->Rect, Top, Top, Bottom, Bottom, Box->CornerRadius, 0, 0);
PushQuad(Group, Box->Rect, Top, Top, Bottom, Bottom,
Box->CornerRadii.x, Box->CornerRadii.y, Box->CornerRadii.z, Box->CornerRadii.w, 0, 0);
}
if(Box->Flags & UI_BoxFlag_ActiveAnimation)
{
v4 Top = V4(0, 0, 0, 0.7F*Box->ActiveTransition);
v4 Bottom = V4(0, 0, 0, 0.1F*Box->ActiveTransition);
v4_r32 Top = V4R32(0, 0, 0, 0.7F*Box->ActiveTransition);
v4_r32 Bottom = V4R32(0, 0, 0, 0.1F*Box->ActiveTransition);
PushQuad(Group, Box->Rect, Top, Top, Bottom, Bottom, Box->CornerRadius, 0, 0);
PushQuad(Group, Box->Rect, Top, Top, Bottom, Bottom,
Box->CornerRadii.x, Box->CornerRadii.y, Box->CornerRadii.z, Box->CornerRadii.w, 0, 0);
}
if(Box->Flags & UI_BoxFlag_DrawText)
{
v2 TextDim = V2(CalculateRasterizedTextWidth(GlyphAtlas, Box->Font, Box->FontSize, Box->String),
CalculateRasterizedTextHeight(GlyphAtlas, Box->Font, Box->FontSize, Box->String));
v2_r32 TextDim = V2R32(CalculateRasterizedTextWidth(GlyphAtlas, Box->Font, Box->FontSize, Box->String),
CalculateRasterizedTextHeight(GlyphAtlas, Box->Font, Box->FontSize, Box->String));
v2 P = Box->Rect.Min + (Box->ComputedDim - TextDim)*0.5;
v2_r32 P = Box->Rect.Min + (Box->ComputedDim - TextDim)*0.5;
PushText(Group, GlyphAtlas, Box->Font, P, Box->FontSize, Box->TextColor, Box->String);
}
@ -660,23 +665,23 @@ static void UI_DrawBox(ui_box *Box, render_group *Group, glyph_atlas *GlyphAtlas
r32 R = (((Box->Key.Value >> 0) & ((1 << 22) - 1)) / (r32)((1 << 22) - 1));
r32 G = (((Box->Key.Value >> 21) & ((1 << 22) - 1)) / (r32)((1 << 22) - 1));
r32 B = (((Box->Key.Value >> 42) & ((1 << 22) - 1)) / (r32)((1 << 22) - 1));
v4 Red = V4R32(R, G, B, 1);
v4_r32 Red = V4R32(R, G, B, 1);
PushQuad(Group, Box->Rect, Red, Red, Red, Red, 0, 1.8, 1.8);
}
#endif
for(ui_box *Child = Box->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
if(Child->Flags & UI_BoxFlag_DrawDropShadow)
{
r32 ShadowRadius = 10;
range2_r32 Rect = Range2R32(Child->Rect.Min - V2R32(ShadowRadius, ShadowRadius),
Child->Rect.Max + V2R32(ShadowRadius, ShadowRadius));
Child->Rect.Max + V2R32(ShadowRadius, ShadowRadius));
v4 ShadowColor = V4(0, 0, 0, 0.3);
v4_r32 ShadowColor = V4R32(0, 0, 0, 0.3);
PushQuad(Group, Rect, ShadowColor, 0, ShadowRadius, 0);
}
@ -689,8 +694,8 @@ static void UI_DrawBox(ui_box *Box, render_group *Group, glyph_atlas *GlyphAtlas
}
for(ui_box *Child = Box->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
UI_DrawBox(Child, Group, GlyphAtlas);
}
@ -702,7 +707,8 @@ static void UI_DrawBox(ui_box *Box, render_group *Group, glyph_atlas *GlyphAtlas
if(Box->Flags & UI_BoxFlag_DrawBorder)
{
PushQuad(Group, Box->Rect, Box->BorderColor, Box->CornerRadius, 0.8, Box->BorderThickness);
v4_r32 BorderColor = Brighten(Box->BorderColor, Box->HotTransition*0.5f+1.0f);
PushQuad(Group, Box->Rect, BorderColor, Box->CornerRadii.x, Box->CornerRadii.y, Box->CornerRadii.z, Box->CornerRadii.w, 0.8, Box->BorderThickness);
}
}
@ -728,8 +734,8 @@ static r32 UI_CalculateBoxSize(ui_box *Box, axis2 Axis, b32 ForceCalculate = fal
glyph_atlas *Atlas = UI->GlyphAtlas;
Result = ((Axis == Axis2_X) ?
CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, Box->String) :
CalculateRasterizedTextHeight(Atlas, Box->Font, Box->FontSize, Box->String)) +
CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, Box->String) :
CalculateRasterizedTextHeight(Atlas, Box->Font, Box->FontSize, Box->String)) +
Box->SemanticSize[Axis].Value;
} break;
@ -784,8 +790,8 @@ static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis, b32 ForceCalculate =
if(Box->LayoutAxis == Axis)
{
for(ui_box *Child = Box->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
Result += UI_CalculateBoxSize(Child, Axis, ForceCalculate);
}
@ -793,8 +799,8 @@ static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis, b32 ForceCalculate =
else
{
for(ui_box *Child = Box->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
Result = Max(Result, UI_CalculateBoxSize(Child, Axis, ForceCalculate));
}
@ -805,8 +811,8 @@ static r32 UI_CalculateChildrenSum(ui_box *Box, axis2 Axis, b32 ForceCalculate =
static void UI_LayoutBox(ui_box *Box)
{
for(ui_box *Child = Box->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
Child->ComputedDim.E[Axis2_X] = UI_CalculateBoxSize(Child, Axis2_X);
Child->ComputedDim.E[Axis2_Y] = UI_CalculateBoxSize(Child, Axis2_Y);
@ -816,8 +822,8 @@ static void UI_LayoutBox(ui_box *Box)
UI_SolveSizeViolations(Box, Axis2_Y);
for(ui_box *Child = Box->First;
Child != 0;
Child = Child->Next)
Child != 0;
Child = Child->Next)
{
Child->Rect.Min = Box->Rect.Min + Child->ComputedRelativeP + Box->Offset;
Child->Rect.Max = Child->Rect.Min + Child->ComputedDim;
@ -827,11 +833,11 @@ static void UI_LayoutBox(ui_box *Box)
static void UI_Init(ui *UI)
{
UI->Arena = ArenaAlloc(Kilobytes(4), true);
UI->FrameArena = ArenaAlloc(Kilobytes(16), true);
UI->Arena = ArenaAlloc(Kilobytes(4), true, "UI State Arena");
UI->FrameArena = ArenaAlloc(Kilobytes(16), true, "UI Frame Arena");
}
static void UI_BeginBuild(v2 ScreenDim)
static void UI_BeginBuild(v2_r32 ScreenDim)
{
ui *UI = UI_GetState();
@ -923,7 +929,7 @@ inline void UI_ScanForHotAndActive(ui_box *Box, b32 *FoundHot, b32 *FoundActive)
}
}
static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, r32 dtForFrame, glyph_atlas *GlyphAtlas)
static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2_r32 MouseP, r32 dtForFrame, glyph_atlas *GlyphAtlas)
{
UI_SetState(UI);
@ -977,8 +983,8 @@ static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, r32 d
// sixten: Prune any unused boxes.
for(s32 BucketIndex = 0;
BucketIndex < ArrayCount(UI->BoxBuckets);
++BucketIndex)
BucketIndex < ArrayCount(UI->BoxBuckets);
++BucketIndex)
{
ui_box_bucket *Bucket = UI->BoxBuckets + BucketIndex;
for(ui_box *Box = Bucket->First; Box != 0;)

View File

@ -81,28 +81,28 @@ struct ui_box
ui_box_flags Flags;
string String;
ui_size SemanticSize[Axis2_Count];
v2 FixedP;
v4 TextColor;
v4 BackgroundColor;
v4 BorderColor;
v2_r32 FixedP;
v4_r32 TextColor;
v4_r32 BackgroundColor;
v4_r32 BorderColor;
r32 BorderThickness;
axis2 LayoutAxis;
r32 CornerRadius;
v4_r32 CornerRadii;
font_id Font;
r32 FontSize;
v2 Offset;
v2_r32 Offset;
platform_cursor HoverCursor;
ui_custom_draw_callback *DrawCallback;
void *DrawCallbackData;
v2 ComputedRelativeP;
v2 ComputedDim;
v2_r32 ComputedRelativeP;
v2_r32 ComputedDim;
// sixten: retained data
range2_r32 Rect;
r32 HotTransition;
r32 ActiveTransition;
v2 ApproachingRelativeP;
v2_r32 ApproachingRelativeP;
};
struct ui_box_bucket
@ -114,10 +114,10 @@ struct ui_box_bucket
struct ui_signal
{
ui_box *Box;
v2 MouseP;
v2 dMouseP;
v2 DragDelta;
v2 Scroll;
v2_r32 MouseP;
v2_r32 dMouseP;
v2_r32 DragDelta;
v2_r32 Scroll;
b8 Clicked;
b8 Pressed;
b8 PressedRight;
@ -153,13 +153,13 @@ struct ui
b32 NextHotSet;
u64 DragData[8];
v2 DragStartP;
v2_r32 DragStartP;
ui_style_stacks Stacks;
platform_event_list *EventList;
v2 dMouseP;
v2 MouseP;
v2_r32 dMouseP;
v2_r32 MouseP;
glyph_atlas *GlyphAtlas;
};
@ -171,15 +171,15 @@ inline ui_key UI_HotKey(void);
inline ui_key UI_ActiveKey(void);
inline platform_event_list *UI_EventList(void);
inline arena *UI_FrameArena(void);
inline v2 UI_MouseP(void);
inline v2_r32 UI_MouseP(void);
inline glyph_atlas *UI_GlyphAtlas(void);
//- sixten: Drag helpers
inline void UI_SetDragStartP(v2 P);
inline void UI_SetDragStartP(v2_r32 P);
inline void UI_UpdateDragStartP(void);
inline v2 UI_GetDragStartP(void);
inline void UI_StoreDragV2(v2 DragData);
inline v2 UI_GetDragV2(void);
inline v2_r32 UI_GetDragStartP(void);
inline void UI_StoreDragV2(v2_r32 DragData);
inline v2_r32 UI_GetDragV2(void);
inline void UI_StoreDragR32(r32 DragData);
inline r32 UI_GetDragR32(void);
inline void UI_StoreDragPayload(void *Data); // sixten(NOTE): Payload MUST be 64-bytes.
@ -210,9 +210,9 @@ static ui_signal UI_SignalFromBox(ui_box *Box);
//- sixten: Building and rendering
static void UI_Init(ui *UI);
static void UI_BeginBuild(ui *UI, v2 ScreenDim);
static void UI_BeginBuild(ui *UI, v2_r32 ScreenDim);
static void UI_EndBuild(void);
static void UI_RenderFrame(render_group *RenderGroup);
static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, r32 dtForFrame, glyph_atlas *GlyphAtlas);
static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2_r32 MouseP, r32 dtForFrame, glyph_atlas *GlyphAtlas);
#endif //VN_UI_H

View File

@ -6,12 +6,12 @@ UIStyleStacks:
{ Height `ui_size` `SemanticSize[Axis2_Y]` }
{ FixedX `r32` `FixedP.E[Axis2_X]` }
{ FixedY `r32` `FixedP.E[Axis2_Y]` }
{ TextColor `v4` `TextColor` }
{ BackgroundColor `v4` `BackgroundColor` }
{ BorderColor `v4` `BorderColor` }
{ TextColor `v4_r32` `TextColor` }
{ BackgroundColor `v4_r32` `BackgroundColor` }
{ BorderColor `v4_r32` `BorderColor` }
{ BorderThickness `r32` `BorderThickness` }
{ LayoutAxis `axis2` `LayoutAxis` }
{ CornerRadius `r32` `CornerRadius` }
{ CornerRadii `v4_r32` `CornerRadii` }
{ Font `font_id` `Font` }
{ FontSize `r32` `FontSize` }
{ OffsetX `r32` `Offset.x` }

View File

@ -166,7 +166,7 @@ static ui_signal UI_Checkbox(b32 *Checked, string String)
{
r32 OpacityTransition = AC_AnimateValueF(*Checked, *Checked, 0.15, "UI Checkbox Transition %p", Checked);
v4 TextColor = UI_TopTextColor();
v4_r32 TextColor = UI_TopTextColor();
TextColor.a = OpacityTransition;
UI_CornerRadius(2) UI_Size(UI_Em(1, 1), UI_Em(1, 1)) UI_Font(Font_Icons) UI_TextColor(TextColor)
@ -420,7 +420,7 @@ static r32 UI_Slider(r32 Value, range1_r32 Range)
return(Result);
}
static void UI_TooltipLabel(string Label, v2 P)
static void UI_TooltipLabel(string Label, v2_r32 P)
{
UI_Tooltip
{
@ -457,12 +457,12 @@ UI_CUSTOM_DRAW_CALLBACK(UI_LineEditCallback)
r32 CursorX = AC_AnimateValueF(TargetCursorX, 0, 0.175, "UI Input Cursor %p", Box);
r32 MarkerX = AC_AnimateValueF(TargetMarkerX, 0, 0.175, "UI Input Mark %p", Box);
v2 BoxDim = DimOfRange(Box->Rect);
v2_r32 BoxDim = DimOfRange(Box->Rect);
// sixten: Draw selection
{
v2 Offset = V2(7.5, (BoxDim.y - Box->FontSize) / 2);
v2 Dim = V2(0, Box->FontSize);
v2_r32 Offset = V2R32(7.5, (BoxDim.y - Box->FontSize) / 2);
v2_r32 Dim = V2R32(0, Box->FontSize);
if(CursorX > MarkerX)
{
Offset.x += MarkerX;
@ -474,8 +474,8 @@ UI_CUSTOM_DRAW_CALLBACK(UI_LineEditCallback)
Dim.x = MarkerX - CursorX;
}
v2 P = Box->Rect.Min + Offset;
v4 Color = V4(0.4, 0.7, 0.8, 0.3);
v2_r32 P = Box->Rect.Min + Offset;
v4_r32 Color = V4R32(0.4, 0.7, 0.8, 0.3);
PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
}
@ -483,12 +483,12 @@ UI_CUSTOM_DRAW_CALLBACK(UI_LineEditCallback)
{
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_r32 Offset = V2R32(7.5F + CursorSpan.Min, (BoxDim.y - Height) / 2);
v2_r32 Dim = V2R32(1.25F + CursorSpan.Max - CursorSpan.Min, Height);
r32 FocusT = AC_AnimateValueF(EditData->Focus, 0, 0.175, "UI Input Focus %p", Box);
v2 P = Box->Rect.Min + Offset;
v4 Color = SetAlpha(V4(0.3, 1, 0.3, 0.7), UI_Blink()*FocusT);
v2_r32 P = Box->Rect.Min + Offset;
v4_r32 Color = SetAlpha(V4R32(0.3, 1, 0.3, 0.7), UI_Blink()*FocusT);
PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
}
}
@ -513,7 +513,7 @@ static s64 UI_TextIndexFromP(ui_box *Box, v2_r32 P)
Byte += Decode.Size;
u32 Codepoint = Decode.Codepoint;
glyph *Glyph = GetGlyph(Atlas, Box->Font, Codepoint, Box->FontSize*Font_Oversample, GetSubpixelSegmentAtP(Advance*Font_Oversample));
glyph *Glyph = F_GlyphFromAtlas(Atlas, Box->Font, Codepoint, Box->FontSize*Font_Oversample, F_SubpixelSegmentFromP(Advance*Font_Oversample));
Assert(Glyph);
Advance += Glyph->Advance/Font_Oversample;

View File

@ -32,6 +32,11 @@ inline void UI_SetNextAxisSize(axis2 Axis, ui_size Size);
#define UI_PopOffset() UI_PopOffsetX(); UI_PopOffsetY()
#define UI_SetNextOffset(x, y) UI_SetNextOffsetX(x); UI_SetNextOffsetY(y)
#define UI_PushCornerRadius(x) UI_PushCornerRadii(V4R32(x, x, x, x))
#define UI_PopCornerRadius() UI_PopCornerRadii()
#define UI_SetNextCornerRadius(x) UI_SetNextCornerRadii(V4R32(x, x, x, x))
#define UI_CornerRadius(x) UI_CornerRadii(V4R32(x, x, x, x))
#define UI_FixedP(Value) UI_FixedX(Value.x) UI_FixedY(Value.y)
#define UI_SetNextFixedP(Value) UI_SetNextFixedX((Value).x); UI_SetNextFixedY((Value).y)
@ -56,7 +61,7 @@ static ui_signal UI_Button(string String);
static ui_signal UI_ButtonF(char *Format, ...);
static ui_signal UI_Checkbox(b32 *Checked, string String);
static r32 UI_Slider(r32 Value, range1_r32 Range);
static void UI_TooltipLabel(string Label, v2 P);
static void UI_TooltipLabel(string Label, v2_r32 P);
static b32 UI_LineEdit(text_edit_state *State, u64 BufferSize, u8 *Buffer, u64 *BufferUsed, string String, b32 Focused);
#endif //VN_UI_UTILS_H

View File

@ -38,20 +38,9 @@ static workspace *W_GetState(void)
//- sixten: Commands
static void W_IssueCommand(workspace_command_sig *Sig, u64 Argument)
{
workspace_command *Result = 0;
workspace *Workspace = W_GetState();
if(Workspace->FirstFreeCommand)
{
Result = Workspace->FirstFreeCommand;
DLLRemove(Workspace->FirstFreeCommand, Workspace->LastFreeCommand, Result);
}
if(!Result)
{
Result = PushStruct(Workspace->CommandArena, workspace_command);
}
workspace_command *Result = PushStruct(Workspace->CommandArena, workspace_command);
Result->Command = Sig;
Result->Argument = Argument;
@ -62,20 +51,14 @@ static void W_ProcessCommands(void)
{
workspace *Workspace = W_GetState();
workspace_command *Command = Workspace->FirstCommand;
while(Command != 0)
{
Command->Command(Command->Argument);
for(workspace_command *Command = Workspace->FirstCommand; Command != 0; Command = Command->Next)
{
workspace_command_sig *CommandSig = Command->Command;
CommandSig(Command->Argument);
}
workspace_command *ToRemove = Command;
Command = Command->Next;
DLLRemove(Workspace->FirstCommand, Workspace->LastCommand, ToRemove);
Fill(ToRemove, 0, sizeof(workspace_command));
DLLInsertLast(Workspace->FirstFreeCommand, Workspace->LastFreeCommand, ToRemove);
}
ArenaClear(Workspace->CommandDataArena);
ArenaClear(Workspace->CommandArena);
Workspace->FirstCommand = Workspace->LastCommand = 0;
}
static void W_ProcessKeyBinds()
@ -143,7 +126,7 @@ static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu)
}
Workspace->Menu = Menu;
Workspace->MenuP = V2(Box->Rect.Min.x, Box->Rect.Max.y);
Workspace->MenuP = V2R32(Box->Rect.Min.x, Box->Rect.Max.y);
}
}
@ -170,7 +153,7 @@ static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut)
UI_Width(UI_TextContent(5, 1)) UI_MakeBoxF(UI_BoxFlag_DrawText, Text);
UI_Spacer(UI_Percent(1, 0));
UI_TextColor(V4(0.5, 0.5, 0.5, 1.0)) UI_Width(UI_TextContent(15, 1))
UI_TextColor(V4R32(0.5, 0.5, 0.5, 1.0)) UI_Width(UI_TextContent(15, 1))
UI_MakeBoxF(UI_BoxFlag_DrawText, Shortcut);
}
@ -216,8 +199,8 @@ static void W_BuildToolbar(void)
"Workspace Dropdown");
UI_Parent(Dropdown)
UI_BackgroundColor(V4(0.25, 0.25, 0.25, 1))
UI_BorderColor(V4(0.45, 0.45, 0.45, 1))
UI_BackgroundColor(V4R32(0.25, 0.25, 0.25, 1))
UI_BorderColor(V4R32(0.45, 0.45, 0.45, 1))
UI_CornerRadius(2)
UI_Size(UI_Percent(1, 1), UI_Pixels(25, 1))
{
@ -240,6 +223,7 @@ static void W_BuildToolbar(void)
if(W_BuildMenuItem(FontIcon_None, "Welcome", "").Clicked) {ViewKind = W_ViewKind_Startup;}
if(W_BuildMenuItem(FontIcon_FolderOpen, "File Lister", "Ctrl + O").Clicked) {ViewKind = W_ViewKind_FileLister;}
if(W_BuildMenuItem(FontIcon_Terminal, "Scene View", "").Clicked) {ViewKind = W_ViewKind_SceneView;}
if(W_BuildMenuItem(FontIcon_Wrench, "Bytecode Viewer", "").Clicked) {ViewKind = W_ViewKind_BytecodeViewer;}
if(W_BuildMenuItem(FontIcon_Wrench, "Settings", "Ctrl + Shift + P").Clicked) {ViewKind = W_ViewKind_Settings;}
if(ViewKind != W_ViewKind_None)
@ -267,125 +251,6 @@ static void W_BuildToolbar(void)
}
}
//- sixten: Panels
static workspace_panel *W_CreateNewPanel(workspace_panel *Parent)
{
workspace_panel *Result = 0;
workspace *Workspace = W_GetState();
if(DLLIsEmpty(Workspace->FirstFreePanel))
{
Result = PushStruct(Workspace->PanelArena, workspace_panel);
}
else
{
Result = Workspace->FirstFreePanel;
DLLRemove(Workspace->FirstFreePanel, Workspace->LastFreePanel, Result);
*Result = {};
}
Result->Parent = Parent;
return(Result);
}
static void W_DeletePanel(workspace_panel *Panel)
{
workspace *Workspace = W_GetState();
if(Workspace->CurrentPanel == Panel)
{
Workspace->CurrentPanel = 0;
}
*Panel = {};
DLLInsertLast(Workspace->FirstFreePanel, Workspace->LastFreePanel, Panel);
}
static void W_SplitPanel(workspace_panel *Panel, axis2 Axis)
{
workspace *Workspace = W_GetState();
if(Panel)
{
workspace_panel *Parent = Panel->Parent;
if(Parent && (Parent->SplitAxis == Axis))
{
workspace_panel *NewPanel = W_CreateNewPanel(Parent);
NewPanel->PercentOfParent = Panel->PercentOfParent = Panel->PercentOfParent * 0.5;
DLLInsert_NP(Parent->First, Parent->Last, Panel, NewPanel, Next, Prev);
}
else
{
workspace_panel *NewPanel = W_CreateNewPanel(Panel);
NewPanel->FirstView = Panel->FirstView;
NewPanel->LastView = Panel->LastView;
// sixten: Update the parents of the children.
for(workspace_view *Child = NewPanel->FirstView;
Child != 0;
Child = Child->Next)
{
Child->Parent = NewPanel;
}
NewPanel->CurrentView = Panel->CurrentView;
NewPanel->PercentOfParent = 0.5;
DLLInsertLast(Panel->First, Panel->Last, NewPanel);
NewPanel = W_CreateNewPanel(Panel);
NewPanel->PercentOfParent = 0.5;
DLLInsertLast(Panel->First, Panel->Last, NewPanel);
Panel->FirstView = 0;
Panel->LastView = 0;
Panel->CurrentView = 0;
Panel->SplitAxis = Axis;
if(Workspace->CurrentPanel == Panel)
{
Workspace->CurrentPanel = Panel->First;
}
}
}
}
static b32 W_ViewIsDragged(workspace_view *View)
{
workspace *Workspace = W_GetState();
b32 Result = (Workspace->DragPayloadState != W_DragPayload_Inactive && Workspace->DragPayload.View == View) &&
UI_GetState()->DragStartP != UI_MouseP();
return(Result);
}
inline void W_BeginDrag(workspace_drag_payload *Payload)
{
workspace *Workspace = W_GetState();
// sixten(no longer a todo): Right now, if you spam-click a draggable item, you can trigger this
// assertion. I don't know what I want to do about this at the moment, but I'm sure
// future me will have a soulution at hand. ^.^
// Assert(Workspace->DragPayloadState == W_DragPayload_Inactive);
// sixten(from the future): I have concluded that this should never be an issue.
Workspace->DragPayload = *Payload;
Workspace->DragPayloadState = W_DragPayload_Active;
}
inline b32 W_GetDragPayload(workspace_drag_payload *Dest)
{
workspace *Workspace = W_GetState();
b32 Result = (Workspace->DragPayloadState != W_DragPayload_Inactive);
*Dest = Workspace->DragPayload;
return(Result);
}
static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View)
{
workspace *Workspace = W_GetState();
@ -403,16 +268,17 @@ static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View)
{
UI_Spacer(UI_Percent(1-OpenT, 1));
v4 BackgroundColor = ViewIsCurrent ? (PanelIsCurrent ? Theme_HighlightBorderColor : Theme_BorderColor) : ColorFromHex(0x353738FF);
v4_r32 BackgroundColor = ViewIsCurrent ? (PanelIsCurrent ? Theme_HighlightBorderColor : Theme_BorderColor) : ColorFromHex(0x353738FF);
UI_SetNextWidth(UI_ChildrenSum(1, 1));
UI_SetNextHeight(UI_Percent(1, 1));
UI_SetNextBackgroundColor(BackgroundColor);
UI_SetNextBackgroundColor(Brighten(BackgroundColor, 1.2f));
UI_SetNextBorderColor(LinearBlend(UI_TopBackgroundColor(), Color_Grey, 0.5));
UI_SetNextLayoutAxis(Axis2_X);
UI_SetNextCornerRadius(0.0);
UI_SetNextLayoutAxis(Axis2_X);
UI_SetNextCornerRadii(V4R32(3.0, 3.0, 0, 0));
ui_box *TabBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
ui_box *TabBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
//UI_BoxFlag_DrawBorder |
UI_BoxFlag_DrawDropShadow |
UI_BoxFlag_HotAnimation |
UI_BoxFlag_ActiveAnimation |
@ -420,48 +286,48 @@ static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View)
UI_BoxFlag_Clickable,
"Workspace Panel Tab Item %S#%p", Name, View);
UI_Parent(TabBox) UI_Padding(UI_Pixels(5, 1))
{
UI_Size(UI_TextContent(1, 1), UI_Percent(1, 1)) UI_Label(Name);
UI_Spacer(UI_Pixels(5, 1));
UI_Parent(TabBox) UI_Padding(UI_Pixels(5, 1))
{
UI_Size(UI_TextContent(1, 1), UI_Percent(1, 1)) UI_Label(Name);
UI_Spacer(UI_Pixels(5, 1));
// sixten: Build close button
{
UI_SetNextFont(Font_Icons);
UI_SetNextSize(UI_TextContent(1, 1), UI_Percent(1, 1));
UI_SetNextHoverCursor(PlatformCursor_Hand);
// sixten: Build close button
{
UI_SetNextFont(Font_Icons);
UI_SetNextSize(UI_TextContent(1, 1), UI_Percent(1, 1));
UI_SetNextHoverCursor(PlatformCursor_Hand);
ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "%U", FontIcon_Cancel);
ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "%U", FontIcon_Cancel);
CloseBox->TextColor = LinearBlend(TabBox->BackgroundColor, Color_Black, 0.3 - CloseBox->HotTransition*0.8);
CloseBox->TextColor = LinearBlend(TabBox->BackgroundColor, Color_Black, 0.3 - CloseBox->HotTransition*0.8);
ui_signal Signal = UI_SignalFromBox(CloseBox);
if(Signal.Clicked)
{
W_IssueCommand(W_Command_CloseView, PointerToU64(View));
}
}
}
ui_signal Signal = UI_SignalFromBox(CloseBox);
if(Signal.Clicked)
{
W_IssueCommand(W_Command_CloseView, PointerToU64(View));
}
}
}
ui_signal Signal = UI_SignalFromBox(TabBox);
if(Signal.Clicked)
{
Workspace->CurrentPanel = Panel;
Panel->CurrentView = View;
}
ui_signal Signal = UI_SignalFromBox(TabBox);
if(Signal.Clicked)
{
Workspace->CurrentPanel = Panel;
Panel->CurrentView = View;
}
// sixten: Handle dragging the view.
if(Signal.Dragging)
{
if(Signal.Pressed)
{
workspace_drag_payload Payload = {};
Payload.View = View;
Payload.Key = TabBox->Key;
// sixten: Handle dragging the view.
if(Signal.Dragging)
{
if(Signal.Pressed)
{
workspace_drag_payload Payload = {};
Payload.View = View;
Payload.Key = TabBox->Key;
W_BeginDrag(&Payload);
}
}
W_BeginDrag(&Payload);
}
}
}
}
@ -590,7 +456,7 @@ static void W_BuildPanel(workspace_panel *Panel)
// sixten: Draw dragged view overlay.
{
workspace_drag_payload Payload;
b32 DragActive = W_GetDragPayload(&Payload);
b32 DragActive = W_DragPayload(&Payload);
b32 OverlayActive = (DragActive && (Payload.View->Parent != Panel) &&
InRange(BodyBox->Rect, UI_GetState()->MouseP));
@ -637,7 +503,7 @@ static void W_BuildPanel(workspace_panel *Panel)
r32 OverlayTransition = AC_AnimateValueF(OverlayActive, 0, 0.25, "Panel Drag Overlay %p", Panel);
v4 OverlayColor = LinearBlend(Color_Grey, Theme_HighlightBorderColor, 0.75);
v4_r32 OverlayColor = LinearBlend(Color_Grey, Theme_HighlightBorderColor, 0.75);
OverlayColor.a = 0.5*OverlayTransition;
UI_SetNextBackgroundColor(OverlayColor);
@ -674,7 +540,7 @@ static void W_BuildPanel(workspace_panel *Panel)
++ChildCount;
}
v2 PanelDim = DimOfRange(PanelBox->Rect);
v2_r32 PanelDim = DimOfRange(PanelBox->Rect);
r32 PaddingSize = 5;
r32 PaddedSpace = (ChildCount - 1)*PaddingSize;
@ -725,12 +591,12 @@ static void W_BuildPanel(workspace_panel *Panel)
}
}
static void W_BuildDragPayload()
static void W_BuildDragPayload(void)
{
workspace *Workspace = W_GetState();
workspace_drag_payload Payload;
if(W_GetDragPayload(&Payload) && W_ViewIsDragged(Payload.View))
if(W_DragPayload(&Payload) && W_ViewIsDragged(Payload.View))
{
if(Workspace->DragPayloadState == W_DragPayload_Released)
{
@ -753,14 +619,133 @@ static void W_BuildDragPayload()
}
}
//- sixten: Panels
static workspace_panel *W_CreateNewPanel(workspace_panel *Parent)
{
workspace_panel *Result = 0;
workspace *Workspace = W_GetState();
if(DLLIsEmpty(Workspace->FirstFreePanel))
{
Result = PushStruct(Workspace->PanelArena, workspace_panel);
}
else
{
Result = Workspace->FirstFreePanel;
DLLRemove(Workspace->FirstFreePanel, Workspace->LastFreePanel, Result);
*Result = {};
}
Result->Parent = Parent;
return(Result);
}
static void W_DeletePanel(workspace_panel *Panel)
{
workspace *Workspace = W_GetState();
if(Workspace->CurrentPanel == Panel)
{
Workspace->CurrentPanel = 0;
}
DLLInsertLast(Workspace->FirstFreePanel, Workspace->LastFreePanel, Panel);
}
static void W_SplitPanel(workspace_panel *Panel, axis2 Axis)
{
workspace *Workspace = W_GetState();
if(Panel)
{
workspace_panel *Parent = Panel->Parent;
if(Parent && (Parent->SplitAxis == Axis))
{
workspace_panel *NewPanel = W_CreateNewPanel(Parent);
NewPanel->PercentOfParent = Panel->PercentOfParent = Panel->PercentOfParent * 0.5;
DLLInsert_NP(Parent->First, Parent->Last, Panel, NewPanel, Next, Prev);
}
else
{
workspace_panel *NewPanel = W_CreateNewPanel(Panel);
NewPanel->FirstView = Panel->FirstView;
NewPanel->LastView = Panel->LastView;
// sixten: Update the parents of the children.
for(workspace_view *Child = NewPanel->FirstView;
Child != 0;
Child = Child->Next)
{
Child->Parent = NewPanel;
}
NewPanel->CurrentView = Panel->CurrentView;
NewPanel->PercentOfParent = 0.5;
DLLInsertLast(Panel->First, Panel->Last, NewPanel);
NewPanel = W_CreateNewPanel(Panel);
NewPanel->PercentOfParent = 0.5;
DLLInsertLast(Panel->First, Panel->Last, NewPanel);
Panel->FirstView = 0;
Panel->LastView = 0;
Panel->CurrentView = 0;
Panel->SplitAxis = Axis;
if(Workspace->CurrentPanel == Panel)
{
Workspace->CurrentPanel = Panel->First;
}
}
}
}
static b32 W_ViewIsDragged(workspace_view *View)
{
workspace *Workspace = W_GetState();
b32 Result = (Workspace->DragPayloadState != W_DragPayload_Inactive && Workspace->DragPayload.View == View) &&
UI_GetState()->DragStartP != UI_MouseP();
return(Result);
}
//- sixten: Dragging
inline void W_BeginDrag(workspace_drag_payload *Payload)
{
workspace *Workspace = W_GetState();
// sixten(no longer a todo): Right now, if you spam-click a draggable item, you can trigger this
// assertion. I don't know what I want to do about this at the moment, but I'm sure
// future me will have a soulution at hand. ^.^
// Assert(Workspace->DragPayloadState == W_DragPayload_Inactive);
// sixten(from the future): I have concluded that this should never be an issue.
Workspace->DragPayload = *Payload;
Workspace->DragPayloadState = W_DragPayload_Active;
}
inline b32 W_DragPayload(workspace_drag_payload *Dest)
{
workspace *Workspace = W_GetState();
b32 Result = (Workspace->DragPayloadState != W_DragPayload_Inactive);
*Dest = Workspace->DragPayload;
return(Result);
}
//- sixten: Workspace
static void W_Init(workspace *Workspace)
{
W_SetState(Workspace);
Workspace->CommandArena = ArenaAlloc(Kilobytes(4), true);
Workspace->CommandDataArena = ArenaAlloc(Kilobytes(4), true);
Workspace->PanelArena = ArenaAlloc(Kilobytes(4), true);
Workspace->CommandArena = ArenaAlloc(Kilobytes(4), true, "Workspace Command Arena");
Workspace->PanelArena = ArenaAlloc(Kilobytes(4), true, "Workspace Panel Arena");
Workspace->RootPanel = Workspace->CurrentPanel = W_CreateNewPanel(0);

View File

@ -87,9 +87,6 @@ struct workspace
// sixten: Command Allocation
arena *CommandArena;
arena *CommandDataArena;
workspace_command *FirstFreeCommand;
workspace_command *LastFreeCommand;
// sixten: Command List
workspace_command *FirstCommand;
@ -99,16 +96,17 @@ struct workspace
arena *PanelArena;
workspace_panel *FirstFreePanel;
workspace_panel *LastFreePanel;
workspace_panel *RootPanel;
workspace_panel *CurrentPanel;
// sixten: Drag Data
workspace_drag_payload_state DragPayloadState;
workspace_drag_payload DragPayload;
// sixten: Dropdown Menu
workspace_toolbar_menu Menu;
v2 MenuP;
v2_r32 MenuP;
r32 MenuT;
workspace_panel *RootPanel;
workspace_panel *CurrentPanel;
};
#include "vn_workspace_file_lister.h"
@ -126,6 +124,16 @@ static workspace *W_GetState(void);
//- sixten: Commands
static void W_IssueCommand(workspace_command_sig *Sig, u64 Argument = 0);
static void W_ProcessCommands(void);
static void W_ProcessKeyBinds();
//- sixten: Builder code
static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu);
static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut);
static void W_BuildToolbar(void);
static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View);
static void W_BuildPanel(workspace_panel *Panel);
static void W_BuildDragPayload(void);
//- sixten: Panels
static workspace_panel *W_CreateNewPanel(workspace_panel *Parent);
@ -135,10 +143,9 @@ static void W_SplitPanel(workspace_panel *Panel, axis2 Axis);
//- sixten: Views
static b32 W_ViewIsDragged(workspace_view *View);
//- sixten: Builder code
static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu);
static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut);
static void W_BuildToolbar(void);
//- sixten: Dragging
inline void W_BeginDrag(workspace_drag_payload *Payload);
inline b32 W_DragPayload(workspace_drag_payload *Dest);
//- sixten: Workspace
static void W_Init(workspace *Workspace);

View File

@ -131,7 +131,7 @@ WORKSPACE_COMMAND(W_Command_OpenFile)
string Filepath = PushFormat(Scratch.Arena, "%S/%S", Action->Path, Action->Name);
platform_file_handle File = Platform.OpenFile(Filepath, PlatformAccess_Read);
platform_file_handle File = Platform.OpenFile(Filepath, PlatformAccess_Read|PlatformAccess_OpenAlways);
if(File.IsValid)
{
// sixten: retrieve file extension

View File

@ -21,12 +21,12 @@ UI_CUSTOM_DRAW_CALLBACK(W_FileListerInputCallback)
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);
v2_r32 BoxDim = DimOfRange(Box->Rect);
// sixten: Draw selection
{
v2 Offset = V2(7.5, (BoxDim.y - Box->FontSize) / 2);
v2 Dim = V2(0, Box->FontSize);
v2_r32 Offset = V2R32(7.5, (BoxDim.y - Box->FontSize) / 2);
v2_r32 Dim = V2R32(0, Box->FontSize);
if(CursorX > MarkerX)
{
Offset.x += MarkerX;
@ -38,8 +38,8 @@ UI_CUSTOM_DRAW_CALLBACK(W_FileListerInputCallback)
Dim.x = MarkerX - CursorX;
}
v2 P = Box->Rect.Min + Offset;
v4 Color = V4(0.4, 0.7, 0.8, 0.3);
v2_r32 P = Box->Rect.Min + Offset;
v4_r32 Color = V4R32(0.4, 0.7, 0.8, 0.3);
PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
}
@ -47,11 +47,11 @@ UI_CUSTOM_DRAW_CALLBACK(W_FileListerInputCallback)
{
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_r32 Offset = V2R32(7.5F + CursorSpan.Min, (BoxDim.y - Height) / 2);
v2_r32 Dim = V2R32(1.25F + CursorSpan.Max - CursorSpan.Min, Height);
v2 P = Box->Rect.Min + Offset;
v4 Color = V4(0.3, 1, 0.3, 0.7);
v2_r32 P = Box->Rect.Min + Offset;
v4_r32 Color = V4R32(0.3, 1, 0.3, 0.7);
PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
}
}
@ -65,12 +65,12 @@ static b32 W_BuildFileListerItem(string Text, u32 Icon, b32 Selected, b32 EnterP
UI_SetNextBackgroundColor(LinearBlend(Theme_BackgroundColor, Theme_HighlightBorderColor, SelectedT*0.5));
UI_SetNextBorderColor(LinearBlend(Theme_BorderColor, Theme_HighlightBorderColor, SelectedT));
ui_box *Container = UI_MakeBoxF(UI_BoxFlag_DrawBorder |
UI_BoxFlag_DrawBackground |
UI_BoxFlag_Clickable |
UI_BoxFlag_HotAnimation |
UI_BoxFlag_ActiveAnimation|
UI_BoxFlag_DrawDropShadow,
"File Lister %S", Text);
UI_BoxFlag_DrawBackground |
UI_BoxFlag_Clickable |
UI_BoxFlag_HotAnimation |
UI_BoxFlag_ActiveAnimation|
UI_BoxFlag_DrawDropShadow,
"File Lister %S", Text);
UI_Parent(Container)
{
UI_Width(UI_Em(2, 1)) UI_Font(Font_Icons) UI_LabelF("%U", Icon);

View File

@ -215,8 +215,8 @@ static void W_BuildNavEditor(workspace_view *View)
workspace_view_nav_editor *Editor = (workspace_view_nav_editor *)View->Data;
scene_view *SceneView = SV_GetState();
UI_BackgroundColor(V4(0.25, 0.25, 0.25, 1))
UI_BorderColor(V4(0.45, 0.45, 0.45, 1))
UI_BackgroundColor(V4R32(0.25, 0.25, 0.25, 1))
UI_BorderColor(V4R32(0.45, 0.45, 0.45, 1))
UI_WidthFill UI_Height(UI_Em(2.0f, 1.0f))
UI_LayoutAxis(Axis2_X)
UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, "Workspace Nav Editor Toolbar"))
@ -383,7 +383,7 @@ static void W_BuildNavEditor(workspace_view *View)
//- sixten: calculate item position
r32 AppliedScale = GlobalScale*Item->Scale;
render_handle Texture = TextureFromAssetID(Item->TextureID);
render_handle Texture = A_TextureFromAssetID(Item->TextureID);
v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture));
v2_r32 TextureOrigin = Hadamard(TextureDim, Item->Origin);
v2_r32 Dim = TextureDim*AppliedScale;
@ -396,7 +396,7 @@ static void W_BuildNavEditor(workspace_view *View)
UI_SetNextHoverCursor(PlatformCursor_Hand);
UI_SetNextSize(UI_Pixels(Dim.x, 1), UI_Pixels(Dim.y, 1));
ui_box *ItemBox = UI_MakeBoxF(UI_BoxFlag_Clickable|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY|((Node==Editor->SelectedItem)?UI_BoxFlag_DrawBorder:0),
"View Item Box %i", ItemIndex);
"View Item Box %i", ItemIndex);
UI_EquipBoxCustomDrawCallback(ItemBox, BuildNavItemDrawCallback, Data);
if(Node == Editor->SelectedItem)

View File

@ -4,7 +4,7 @@
static mutable_string MutableStringAllocate(u64 Size)
{
mutable_string Result = {};
Result.Arena = ArenaAlloc(Size);
Result.Arena = ArenaAlloc(Size, false, "Mutable String");
ArenaSetAlign(Result.Arena, 1);
Result.String = MakeString(PushArray(Result.Arena, u8, 1), 0LL);
return(Result);
@ -114,8 +114,8 @@ static void W_TextEditorApplyChanges(workspace_view_text_editor *Editor)
Editor->Tokens = TextData.Tokens;
Editor->Lines = TextData.Lines;
Editor->MaxLineCount = TextData.MaxLineCount;
Editor->Compiled = S_ScriptFromText(Editor->ProcessingArena, Editor->Text.String);
if(Editor->Compiled.IsValid)
Editor->Compiled = S2_CompiledFromString(Editor->ProcessingArena, Editor->Text.String);
if(Editor->Compiled.Messages.Count == 0)
{
SV_SetCurrentSource(&Editor->Compiled);
}
@ -187,85 +187,27 @@ static b32 W_ProcessTextEditorEvent(workspace_view_text_editor *Editor, platform
return(CursorHasBeenModified);
}
static void W_BuildTextEditorInfoBar(workspace_view_text_editor *Editor)
static b32 W_ProcessDigitalKeyEvent(workspace_view_text_editor *Editor, platform_event_type Type, u32 Data)
{
UI_SetNextLayoutAxis(Axis2_X);
UI_WidthFill UI_Height(UI_Em(1.75f, 1)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawDropShadow, "")) UI_Padding(UI_Em(1, 1))
{
UI_Width(UI_TextContent(0, 1))
{
UI_Font(Font_Icons) UI_LabelF("%U", FontIcon_Attention);
UI_Spacer(UI_Em(0.5f, 1));
UI_LabelF("%i", Editor->Compiled.Errors.Count);
}
}
}
static void W_BuildTextEditorErrorList(workspace_view_text_editor *Editor)
{
r32 TargetFooterHeightEm = 2.25f*Min(Editor->Compiled.Errors.Count, 10LL);
UI_Size(UI_Percent(1, 0), UI_Em(AC_AnimateValueF(TargetFooterHeightEm, TargetFooterHeightEm, 0.3, "Error Lister %p", Editor), 1)) UI_Column() UI_Height(UI_TextContent(0, 1))
platform_event Event = {};
Event.Type = Type;
if(Type == PlatformEvent_Press)
{
s64 Index = 0;
for(scene_compile_error *Error = Editor->Compiled.Errors.First; Error != 0; Error = Error->Next, Index += 1)
{
UI_SetNextHeight(UI_ChildrenSum(1, 1));
UI_SetNextLayoutAxis(Axis2_X);
UI_Parent(UI_MakeBoxF(0, "Editor Error Lister Container %p", Error)) UI_Padding(UI_Em(1, 1)) UI_Height(UI_Em(1.75f, 1))
{
UI_SetNextBackgroundColor(SetAlpha(Theme_BorderColor, 0.8f));
UI_SetNextCornerRadius(4);
UI_SetNextLayoutAxis(Axis2_X);
UI_SetNextHoverCursor(PlatformCursor_Hand);
ui_box *ContainerBox = UI_MakeBoxF(UI_BoxFlag_Clickable|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_DrawBorder, "Container Box");
UI_Parent(ContainerBox) UI_Padding(UI_Em(1, 1)) UI_Width(UI_TextContent(0, 1))
{
UI_Font(Font_Icons) UI_LabelF("%U", FontIcon_Attention);
UI_Spacer(UI_Em(0.5f, 1));
// sixten(TODO): this is dumb, slow and downright stupid.
text_point Point = TextPointFromOffset(Editor->Text.String, Error->Token.Range.Min);
UI_LabelF("%i:%i", Point.Line, Point.Column);
UI_Spacer(UI_Em(0.5f, 1));
UI_Label(Error->Message);
UI_Spacer(UI_Percent(1, 0));
}
ui_signal Signal = UI_SignalFromBox(ContainerBox);
if(Signal.Hovering)
{
UI_TooltipLabel(StrLit("Goto in source"), UI_MouseP());
// sixten(TODO): ACTUALLY GO TO THE SOURCE LOCATION
}
}
UI_Spacer(UI_Em(0.5, 1));
}
Event.Key = (platform_key)Data;
}
}
UI_CUSTOM_DRAW_CALLBACK(W_TextEditorLinesBarDrawCallback)
{
workspace_view_text_editor *Editor = (workspace_view_text_editor *)Data;
//- sixten: calculate dimensions
ui_box *Parent = Box->Parent;
v2_r32 ParentDim = DimOfRange(Parent->Rect);
r32 FontSize = Editor->FontSize;
r32 LineHeight = FontSize + 4.0f;
s64 LineStart = Floor(-Parent->Offset.y/LineHeight);
s64 LineEnd = Min(Editor->Lines.Count, (s64)Floor((ParentDim.y-Parent->Offset.y)/LineHeight)+1);
s64 LineNumberCount = (s64)(Log(Editor->Lines.Count)/Log(10))+1;
for(s64 Line = LineStart; Line < LineEnd; Line += 1)
else if(Type == PlatformEvent_Text)
{
PushTextF(Group, Atlas, Font_Monospace, Box->Rect.Min+V2R32(0, Line*LineHeight), Editor->FontSize, Color_Grey, " %*i", LineNumberCount, Line+1);
Event.Codepoint = Data;
}
return(W_ProcessTextEditorEvent(Editor, &Event));
}
UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback)
////////////////////////////////
//~ sixten: Workspace Text Editor Draw Callbacks
static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback)
{
workspace_view_text_editor *Editor = (workspace_view_text_editor *)Data;
temp Scratch = GetScratch();
@ -276,11 +218,11 @@ UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback)
//- sixten: rendering properties
r32 FontSize = Editor->FontSize;
r32 LineHeight = FontSize + 4.0f;
r32 LineHeight = FontSize*1.25f; // + 4.0f
//- sixten: calculate the dimensions of the glyphs
glyph *Glyph = GetGlyph(Atlas, Font_Monospace, 'A', FontSize, 0);
r32 GlyphAdvance = Glyph->Advance;
glyph *Glyph = F_GlyphFromAtlas(Atlas, Font_Monospace, 'A', FontSize, 0);
v2_r32 GlyphDim = V2R32(Glyph->Advance, LineHeight);
//- sixten: find the text point
text_point CursorTextP = TextPointFromOffset(Editor->Text.String, Editor->EditState.Cursor);
@ -296,191 +238,279 @@ UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback)
token *TokensEnd = TokensBegin + Tokens.Count;
v2_r32 StartTokenP = Box->Rect.Min;
//- sixten: find the first visible token
token *VisibleTokensBegin = TokensBegin;
for(s64 LinesFound = 0; LinesFound < LineStart && VisibleTokensBegin < TokensEnd; VisibleTokensBegin += 1)
{
if(VisibleTokensBegin->Kind == TokenKind_Newline)
{
LinesFound += 1;
//- sixten: find the first visible token
token *VisibleTokensBegin = TokensBegin;
for(s64 LinesFound = 0; LinesFound < LineStart && VisibleTokensBegin < TokensEnd; VisibleTokensBegin += 1)
{
if(VisibleTokensBegin->Kind == TokenKind_Newline)
{
LinesFound += 1;
StartTokenP.y += LineHeight;
}
}
}
}
//- sixten: find the last visible token
token *VisibleTokensEnd = VisibleTokensBegin;
for(s64 LinesFound = 0; LinesFound < LineEnd-LineStart && VisibleTokensEnd < TokensEnd; VisibleTokensEnd += 1)
{
if(VisibleTokensEnd->Kind == TokenKind_Newline)
{
LinesFound += 1;
}
}
//- sixten: find the last visible token
token *VisibleTokensEnd = VisibleTokensBegin;
for(s64 LinesFound = 0; LinesFound < LineEnd-LineStart && VisibleTokensEnd < TokensEnd; VisibleTokensEnd += 1)
{
if(VisibleTokensEnd->Kind == TokenKind_Newline)
{
LinesFound += 1;
}
}
#if 0
#if 1
//- sixten: render gradient on current line
{
v4_r32 ColorBegin = SetAlpha(Theme_HighlightBorderColor, 0.5);
v4_r32 ColorBegin = SetAlpha(Theme_HighlightBorderColor, 0.3*AC_AnimateValueF(Editor->EditState.Mark == Editor->EditState.Cursor,
Editor->EditState.Mark == Editor->EditState.Cursor,
0.1f, "Text Editor Gradient Fade %p", Box));
v4_r32 ColorEnd = SetAlpha(Theme_HighlightBorderColor, 0.0);
range2_r32 LineDest = Range2R32(Box->Rect.Min+V2R32(0, (CursorTextP.Line-1)*LineHeight), Box->Rect.Min+V2R32(400, CursorTextP.Line*LineHeight));
PushQuad(Group, LineDest, ColorBegin, ColorEnd, ColorBegin, ColorEnd, 0, 0, 0);
PushQuad(Group, LineDest, Theme_BackgroundColor, Theme_BackgroundColor, Theme_BackgroundColor, Theme_BackgroundColor, 4.0f, 14, 0);
range2_r32 LineDest = Range2R32(Box->Rect.Min+V2R32(0, AC_AnimateValueF((CursorTextP.Line-1)*LineHeight, (CursorTextP.Line-1)*LineHeight, 0.1f, "Text Editor Gradient %p", Box)),
Box->Rect.Min+V2R32(ParentDim.x, CursorTextP.Line*LineHeight));
PushQuad(Group, LineDest, ColorBegin, LinearBlend(ColorBegin, ColorEnd, 0.5f), LinearBlend(ColorBegin, ColorEnd, 0.3f), ColorEnd, 0, 1.5f, 0);
//PushQuad(Group, LineDest, Theme_BackgroundColor, Theme_BackgroundColor, Theme_BackgroundColor, Theme_BackgroundColor, 4.0f, 14, 0);
}
#endif
//- sixten: render tokens
//- sixten: render tokens
v2_r32 TokenP = StartTokenP;
for(token *Token = VisibleTokensBegin; Token < VisibleTokensEnd; Token += 1)
{
string TokenString = T_StringFromToken(Editor->Text.String, *Token);
{
string TokenString = T_StringFromToken(Editor->Text.String, *Token);
//- sixten: get color & font from token
font_id Font = Font_Monospace;
v4 Color = Color_Cyan;
if(Token->Kind == TokenKind_Comment) { Color = Color_Grey; Font = Font_MonospaceOblique; }
else if(Token->Kind > TokenKind_SymbolsBegin && Token->Kind < TokenKind_SymbolsEnd) { Color = Color_Grey; }
else if(Token->Kind == TokenKind_StringLiteral) { Color = ColorFromHex(0xffa900ff); }
else if(Token->Kind == TokenKind_Numeric) { Color = ColorFromHex(0xffa900ff); }
else if(Token->Kind > TokenKind_KeywordsBegin && Token->Kind < TokenKind_KeywordsEnd)
{
if(Token->Kind == TokenKind_True || Token->Kind == TokenKind_False)
{
Color = ColorFromHex(0xffa900ff);
}
else
{
Color = ColorFromHex(0xf0c674ff);
}
}
else if(Token->Kind == TokenKind_Identifier)
{
Color = Theme_TextColor;
}
//- sixten: get color & font from token
font_id Font = Font_Monospace;
v4_r32 Color = Color_Cyan;
if(Token->Kind == TokenKind_Comment) { Color = Color_Grey; Font = Font_MonospaceOblique; }
else if(Token->Kind > TokenKind_SymbolsBegin && Token->Kind < TokenKind_SymbolsEnd) { Color = Color_Grey; }
else if(Token->Kind == TokenKind_StringLiteral) { Color = ColorFromHex(0xffa900ff); }
else if(Token->Kind == TokenKind_Numeric) { Color = ColorFromHex(0xffa900ff); }
else if(Token->Kind > TokenKind_KeywordsBegin && Token->Kind < TokenKind_KeywordsEnd)
{
if(Token->Kind == TokenKind_True || Token->Kind == TokenKind_False)
{
Color = ColorFromHex(0xffa900ff);
}
else
{
Color = ColorFromHex(0xf0c674ff);
}
}
else if(Token->Kind == TokenKind_Identifier)
{
Color = Theme_TextColor;
}
//- sixten: check for errors
b32 ConsideredError = false;
for(scene_compile_error *Error = Editor->Compiled.Errors.First; Error != 0; Error = Error->Next)
{
if(Error->Token.Range.Min == Token->Range.Min &&
Error->Token.Range.Max == Token->Range.Max)
{
ConsideredError = true;
break;
}
}
//- sixten: check for errors
b32 ConsideredError = false;
for(scene2_message *Message = Editor->Compiled.Messages.First; Message != 0; Message = Message->Next)
{
if(Message->Token.Range.Min == Token->Range.Min &&
Message->Token.Range.Max == Token->Range.Max)
{
ConsideredError = true;
break;
}
}
//- sixten: render & advance by token
if(!(T_IsWhitespace(Token->Kind)))
{
if(Token->Kind == TokenKind_Comment)
{
//- sixten: advance to newline and push text
// sixten(TODO): proper multiline comment rendering.
u8 *TextBegin = TokenString.Data;
u8 *TextEnd = TextBegin+TokenString.Count;
u8 *Marker = TextBegin;
for(u8 *Byte = TextBegin; Byte <= TextEnd; Byte += 1)
{
if(*Byte == '\n' || Byte == TextEnd)
{
PushText(Group, Atlas, Font, TokenP, FontSize, Color, MakeString(Marker, Byte-Marker));
Marker = Byte+1;
//- sixten: render & advance by token
if(!(T_IsWhitespace(Token->Kind)))
{
if(Token->Kind == TokenKind_Comment)
{
//- sixten: advance to newline and push text
// sixten(TODO): proper multiline comment rendering.
u8 *TextBegin = TokenString.Data;
u8 *TextEnd = TextBegin+TokenString.Count;
u8 *Marker = TextBegin;
for(u8 *Byte = TextBegin; Byte <= TextEnd; Byte += 1)
{
if(*Byte == '\n' || Byte == TextEnd)
{
TokenP.x += PushText(Group, Atlas, Font, TokenP, FontSize, Color, MakeString(Marker, Byte-Marker));
Marker = Byte+1;
if(*Byte == '\n' && Byte != TextEnd)
{
TokenP.x = StartTokenP.x;
TokenP.y += LineHeight;
}
}
}
}
else
{
r32 TokenWidth = PushText(Group, Atlas, Font, TokenP, FontSize, Color, TokenString);
if(*Byte == '\n' && Byte != TextEnd)
{
TokenP.x = StartTokenP.x;
TokenP.y += LineHeight;
}
}
}
}
else
{
r32 TokenWidth = PushText(Group, Atlas, Font, TokenP, FontSize, Color, TokenString);
//- sixten: render error highlight
if(ConsideredError)
{
range2_r32 Dest = Range2R32(TokenP+V2R32(0, LineHeight-3), TokenP+V2R32(TokenWidth, LineHeight));
v4_r32 ErrorColor = V4R32(0.9f, 0.3f, 0.3f, 0.8f);
PushQuad(Group, Dest, ErrorColor, ErrorColor, ErrorColor, ErrorColor, 3, 0.4, 0);
}
TokenP.x += TokenWidth;
}
}
else
{
if(Token->Kind == TokenKind_Newline)
{
TokenP.x = StartTokenP.x;
TokenP.y += LineHeight;
}
else
{
u8 *StringBegin = TokenString.Data;
u8 *StringEnd = StringBegin + TokenString.Count;
for(u8 *Char = StringBegin; Char < StringEnd; Char += 1)
{
if(*Char == ' ' || *Char == '\t')
{
TokenP.x += GlyphAdvance;
}
}
}
}
}
//- sixten: render error highlight
if(ConsideredError)
{
range2_r32 Dest = Range2R32(TokenP+V2R32(0, LineHeight-3), TokenP+V2R32(TokenWidth, LineHeight));
v4_r32 ErrorColor = V4R32(0.9f, 0.3f, 0.3f, 0.8f);
PushQuad(Group, Dest, ErrorColor, ErrorColor, ErrorColor, ErrorColor, 3, 0.4, 0);
}
TokenP.x += TokenWidth;
}
}
else
{
if(Token->Kind == TokenKind_Newline)
{
TokenP.x = StartTokenP.x;
TokenP.y += LineHeight;
}
else
{
u8 *StringBegin = TokenString.Data;
u8 *StringEnd = StringBegin + TokenString.Count;
for(u8 *Char = StringBegin; Char < StringEnd; Char += 1)
{
if(*Char == ' ' || *Char == '\t')
{
TokenP.x += GlyphDim.x;
}
}
}
}
}
//- sixten: render the selection
{
text_range Selection = TextRange(CursorTextP, MarkTextP);
range1_s64 LineRange = Range1S64(Selection.Min.Line, Selection.Max.Line);
for(s64 LineIndex = LineStart; LineIndex < LineEnd; LineIndex += 1)
{
if(Contains(LineRange, LineIndex + 1))
{
range1_s64 ColumnRange = Editor->Lines.Ranges[LineIndex];
range1_s64 NormalizedColumnRange = Range1S64(0, DimOfRange(ColumnRange));
if(LineIndex+1 == LineRange.Min && LineIndex+1 == LineRange.Max)
{
NormalizedColumnRange = Range1S64(Editor->EditState.Cursor - ColumnRange.Min, Editor->EditState.Mark - ColumnRange.Min);
}
else if(LineIndex+1 == LineRange.Min)
{
NormalizedColumnRange = Range1S64(Min(Editor->EditState.Mark, Editor->EditState.Cursor) - ColumnRange.Min, DimOfRange(ColumnRange));
}
else if(LineIndex+1 == LineRange.Max)
{
NormalizedColumnRange = Range1S64(0, Max(Editor->EditState.Mark, Editor->EditState.Cursor) - ColumnRange.Min);
}
{
text_range Selection = TextRange(CursorTextP, MarkTextP);
range1_s64 LineRange = Range1S64(Selection.Min.Line, Selection.Max.Line);
for(s64 LineIndex = LineStart; LineIndex < LineEnd; LineIndex += 1)
{
if(Contains(LineRange, LineIndex + 1))
{
range1_s64 ColumnRange = Editor->Lines.Ranges[LineIndex];
range1_s64 NormalizedColumnRange = Range1S64(0, DimOfRange(ColumnRange));
if(LineIndex+1 == LineRange.Min && LineIndex+1 == LineRange.Max)
{
NormalizedColumnRange = Range1S64(Editor->EditState.Cursor - ColumnRange.Min, Editor->EditState.Mark - ColumnRange.Min);
}
else if(LineIndex+1 == LineRange.Min)
{
NormalizedColumnRange = Range1S64(Min(Editor->EditState.Mark, Editor->EditState.Cursor) - ColumnRange.Min, DimOfRange(ColumnRange));
}
else if(LineIndex+1 == LineRange.Max)
{
NormalizedColumnRange = Range1S64(0, Max(Editor->EditState.Mark, Editor->EditState.Cursor) - ColumnRange.Min);
}
string Line = Substring(Editor->Text.String, ColumnRange);
range1_s64 ColumnOffsetRange = Range1S64(UTF8OffsetFromIndex(Line, NormalizedColumnRange.Min),
string Line = Substring(Editor->Text.String, ColumnRange);
range1_s64 ColumnOffsetRange = Range1S64(UTF8OffsetFromIndex(Line, NormalizedColumnRange.Min),
UTF8OffsetFromIndex(Line, NormalizedColumnRange.Max));
r32 LineY = LineIndex*LineHeight;
v4_r32 LineHighlightColor = ColorFromHex(0x66B3CC4C);
range2_r32 LineHighlightBox = Range2R32(Box->Rect.Min+V2(ColumnOffsetRange.Min*GlyphAdvance, LineY),
Box->Rect.Min+V2(ColumnOffsetRange.Max*GlyphAdvance, LineY+LineHeight));
PushQuad(Group, LineHighlightBox, LineHighlightColor, LineHighlightColor, LineHighlightColor, LineHighlightColor, 4, 1.4, 0);
}
r32 LineY = LineIndex*LineHeight;
v4_r32 LineHighlightColor = ColorFromHex(0x66B3CC4C);
range2_r32 LineHighlightBox = Range2R32(Box->Rect.Min+V2R32(ColumnOffsetRange.Min*GlyphDim.x, LineY),
Box->Rect.Min+V2R32(ColumnOffsetRange.Max*GlyphDim.x, LineY+LineHeight));
PushQuad(Group, LineHighlightBox, LineHighlightColor, LineHighlightColor, LineHighlightColor, LineHighlightColor, 4, 1.4, 0);
}
}
}
//- sixten: render cursor
{
s64 LineIndex = CursorTextP.Line-1;
string Line = Substring(Editor->Text.String, Editor->Lines.Ranges[LineIndex]);
s64 ColumnIndex = CursorTextP.Column-1;
s64 ColumnOffset = UTF8OffsetFromIndex(Line, ColumnIndex);
v2_r32 TargetCursorP = V2R32(ColumnOffset, LineIndex);
v2_r32 CursorP = V2R32(AC_AnimateValueF(TargetCursorP.x, TargetCursorP.x, 0.1, "Workspace Text Editor Cursor X %p", Editor),
AC_AnimateValueF(TargetCursorP.y, TargetCursorP.y, 0.1, "Workspace Text Editor Cursor Y %p", Editor));
v2_r32 CursorDim = V2R32(LineHeight/16, LineHeight);
range2_r32 CursorRect = Range2R32(Box->Rect.Min+CursorP*GlyphDim, Box->Rect.Min+CursorP*GlyphDim+CursorDim);
v4_r32 CursorColor = SetAlpha(ColorFromHex(0x10FF20FF), UI_Blink());
PushQuad(Group, CursorRect, CursorColor, CursorColor, CursorColor, CursorColor, 2, 0.4, 0);
}
ReleaseScratch(Scratch);
}
static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorLinesBarDrawCallback)
{
workspace_view_text_editor *Editor = (workspace_view_text_editor *)Data;
//- sixten: calculate dimensions
ui_box *Parent = Box->Parent;
v2_r32 ParentDim = DimOfRange(Parent->Rect);
r32 FontSize = Editor->FontSize;
r32 LineHeight = FontSize*1.25f; // + 4.0f
s64 LineStart = Floor(-Parent->Offset.y/LineHeight);
s64 LineEnd = Min(Editor->Lines.Count, (s64)Floor((ParentDim.y-Parent->Offset.y)/LineHeight)+1);
s64 LineNumberCount = (s64)(Log(Editor->Lines.Count)/Log(10))+1;
for(s64 Line = LineStart; Line < LineEnd; Line += 1)
{
PushTextF(Group, Atlas, Font_Monospace, Box->Rect.Min+V2R32(0, Line*LineHeight), Editor->FontSize, Color_Grey, " %*i", LineNumberCount, Line+1);
}
}
////////////////////////////////
//~ sixten: Workspace Text Editor Builder Functions
static void W_BuildTextEditorInfoBar(workspace_view_text_editor *Editor)
{
UI_SetNextLayoutAxis(Axis2_X);
UI_WidthFill UI_Height(UI_Em(1.75f, 1)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawDropShadow, "")) UI_Padding(UI_Em(1, 1))
{
UI_Width(UI_TextContent(0, 1))
{
UI_Font(Font_Icons) UI_LabelF("%U", FontIcon_Attention);
UI_Spacer(UI_Em(0.5f, 1));
UI_LabelF("%i", Editor->Compiled.Messages.Count);
}
}
}
//- sixten: render cursor
{
s64 LineIndex = CursorTextP.Line-1;
string Line = Substring(Editor->Text.String, Editor->Lines.Ranges[LineIndex]);
s64 ColumnIndex = CursorTextP.Column-1;
s64 ColumnOffset = UTF8OffsetFromIndex(Line, ColumnIndex);
static void W_BuildTextEditorErrorList(workspace_view_text_editor *Editor)
{
r32 TargetFooterHeightEm = 2.25f*Min(Editor->Compiled.Messages.Count, 10LL);
UI_Size(UI_Percent(1, 0), UI_Em(AC_AnimateValueF(TargetFooterHeightEm, TargetFooterHeightEm, 0.3, "Error Lister %p", Editor), 1)) UI_Column() UI_Height(UI_TextContent(0, 1))
{
s64 Index = 0;
for(scene2_message *Message = Editor->Compiled.Messages.First; Message != 0; Message = Message->Next, Index += 1)
{
UI_SetNextHeight(UI_ChildrenSum(1, 1));
UI_SetNextLayoutAxis(Axis2_X);
UI_Parent(UI_MakeBoxF(0, "Editor Error Lister Container %p", Message)) UI_Padding(UI_Em(1, 1)) UI_Height(UI_Em(1.75f, 1))
{
UI_SetNextBackgroundColor(SetAlpha(Theme_BorderColor, 0.8f));
UI_SetNextCornerRadius(4);
UI_SetNextLayoutAxis(Axis2_X);
UI_SetNextHoverCursor(PlatformCursor_Hand);
ui_box *ContainerBox = UI_MakeBoxF(UI_BoxFlag_Clickable|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_DrawBorder, "Container Box");
v2 TargetCursorP = Box->Rect.Min+V2(ColumnOffset*GlyphAdvance, LineIndex*LineHeight);
v2 CursorP = V2(AC_AnimateValueF(TargetCursorP.x, TargetCursorP.x, 0.1, "Workspace Text Editor Cursor X %p", Editor),
AC_AnimateValueF(TargetCursorP.y, TargetCursorP.y, 0.1, "Workspace Text Editor Cursor Y %p", Editor));
v2 CursorDim = V2(2, LineHeight);
range2_r32 CursorRect = Range2R32(CursorP, CursorP+CursorDim);
v4 CursorColor = ColorFromHex(0x10FF20FF);
PushQuad(Group, CursorRect, CursorColor, CursorColor, CursorColor, CursorColor, 2, 0.4, 0);
}
UI_Parent(ContainerBox) UI_Padding(UI_Em(1, 1)) UI_Width(UI_TextContent(0, 1))
{
UI_Font(Font_Icons) UI_LabelF("%U", FontIcon_Attention);
UI_Spacer(UI_Em(0.5f, 1));
// sixten(TODO): this is dumb, slow and downright stupid.
text_point Point = TextPointFromOffset(Editor->Text.String, Message->Token.Range.Min);
UI_LabelF("%i:%i", Point.Line, Point.Column);
UI_Spacer(UI_Em(0.5f, 1));
UI_Label(Message->Message);
UI_Spacer(UI_Percent(1, 0));
}
ui_signal Signal = UI_SignalFromBox(ContainerBox);
if(Signal.Hovering)
{
UI_TooltipLabel(StrLit("Goto in source"), UI_MouseP());
// sixten(TODO): ACTUALLY GO TO THE SOURCE LOCATION
}
}
UI_Spacer(UI_Em(0.5, 1));
}
}
}
static void W_BuildTextEditor(workspace_view *View)
@ -489,9 +519,9 @@ static void W_BuildTextEditor(workspace_view *View)
//- sixten: calculate dimensions
r32 FontSize = Editor->FontSize;
r32 LineHeight = FontSize + 4.0f;
r32 LineHeight = FontSize*1.25f; // + 4.0f
glyph *Glyph = GetGlyph(UI_GlyphAtlas(), Font_Monospace, 'A', FontSize, 0);
glyph *Glyph = F_GlyphFromAtlas(UI_GlyphAtlas(), Font_Monospace, 'A', FontSize, 0);
r32 GlyphAdvance = Glyph->Advance;
s64 LineCount = Editor->Lines.Count;
@ -503,6 +533,10 @@ static void W_BuildTextEditor(workspace_view *View)
v2_r32 TextEditorDim = V2R32((MaxLineCount+LineNumberCount+2)*GlyphAdvance, (LineCount+1)*LineHeight);
v2_r32 VisibleRegionDim; // sixten(NOTE): This is set further down
//- sixten: animated offset
AC_AnimateValueDirect(Editor->Offset.x, 0.3f, &Editor->AnimatedOffset.x);
AC_AnimateValueDirect(Editor->Offset.y, 0.3f, &Editor->AnimatedOffset.y);
b32 CursorHasBeenModified = false;
//- sixten: layout editor
@ -516,9 +550,7 @@ static void W_BuildTextEditor(workspace_view *View)
UI_Row(0, StrLit("Scroll Region")) // contains lines bar & text editor
{
v2_r32 ScrollRegionDim = DimOfRange(UI_TopParent()->Rect);
v2_r32 AnimatedOffset = V2R32(AC_AnimateValueF(Editor->Offset.x, Editor->Offset.x, 0.3f, "%p Offset X", View),
AC_AnimateValueF(Editor->Offset.y, Editor->Offset.y, 0.3f, "%p Offset Y", View));
v2_r32 AnimatedOffset = Editor->AnimatedOffset;
// sixten(NOTE): We put the lines bar & text editor in containers to be able to easily offset them.
UI_SetNextBackgroundColor(ColorFromHex(0x10203080));
@ -536,6 +568,7 @@ static void W_BuildTextEditor(workspace_view *View)
ui_box *EditorContainerBox = UI_TopParent();
VisibleRegionDim = DimOfRange(EditorContainerBox->Rect);
ui_signal EditorContainerSignal = UI_SignalFromBox(EditorContainerBox);
//- sixten: text editor scrolling
if(AreEqual(UI_HotKey(), EditorContainerBox->Key))
{
@ -557,7 +590,7 @@ static void W_BuildTextEditor(workspace_view *View)
if(EditorContainerSignal.Dragging)
{
//- sixten: translate mouse position to text point
v2 MouseOffset = EditorContainerSignal.MouseP - TextEditorBox->Rect.Min;
v2_r32 MouseOffset = EditorContainerSignal.MouseP - TextEditorBox->Rect.Min;
s64 LineIndex = Clamp((s64)(MouseOffset.y / LineHeight), 0, Editor->Lines.Count);
string Line = Substring(Editor->Text.String, Editor->Lines.Ranges[LineIndex]);
s64 ColumnOffset = (s64)(MouseOffset.x / GlyphAdvance);
@ -685,6 +718,7 @@ static void W_BuildTextEditor(workspace_view *View)
{
Editor->EditState.Mark = 0;
Editor->EditState.Cursor = Editor->Text.String.Count;
CursorHasBeenModified = true;
}
//- sixten: keyboard input -> text op
@ -725,25 +759,15 @@ static void W_BuildTextEditor(workspace_view *View)
//- sixten: auto close bracket
if(Event->Codepoint == '{')
{
platform_event FakeEvent = {};
FakeEvent.Codepoint = '}';
FakeEvent.Type = PlatformEvent_Text;
CursorHasBeenModified |= W_ProcessTextEditorEvent(Editor, &FakeEvent);
FakeEvent.Key = Key_Left;;
FakeEvent.Type = PlatformEvent_Press;
CursorHasBeenModified |= W_ProcessTextEditorEvent(Editor, &FakeEvent);
CursorHasBeenModified |= W_ProcessDigitalKeyEvent(Editor, PlatformEvent_Text, '}');
CursorHasBeenModified |= W_ProcessDigitalKeyEvent(Editor, PlatformEvent_Press, Key_Left);
}
//- sixten: auto close string literal
if(Event->Codepoint == '"')
{
platform_event FakeEvent = {};
FakeEvent.Codepoint = '"';
FakeEvent.Type = PlatformEvent_Text;
CursorHasBeenModified |= W_ProcessTextEditorEvent(Editor, &FakeEvent);
FakeEvent.Key = Key_Left;;
FakeEvent.Type = PlatformEvent_Press;
CursorHasBeenModified |= W_ProcessTextEditorEvent(Editor, &FakeEvent);
CursorHasBeenModified |= W_ProcessDigitalKeyEvent(Editor, PlatformEvent_Text, '"');
CursorHasBeenModified |= W_ProcessDigitalKeyEvent(Editor, PlatformEvent_Press, Key_Left);
}
//- sixten: default event
@ -754,15 +778,9 @@ static void W_BuildTextEditor(workspace_view *View)
}
//- sixten: apply indent
for(s64 IndentIndex = 0; IndentIndex < Indent; IndentIndex += 1)
{
platform_event FakeTab = {};
FakeTab.Codepoint = '\t';
FakeTab.Type = PlatformEvent_Text;
for(s64 IndentIndex = 0; IndentIndex < Indent; IndentIndex += 1)
{
CursorHasBeenModified |= W_ProcessTextEditorEvent(Editor, &FakeTab);
}
CursorHasBeenModified |= W_ProcessDigitalKeyEvent(Editor, PlatformEvent_Text, '\t');
}
}
}
@ -776,7 +794,7 @@ static void W_BuildTextEditor(workspace_view *View)
s64 ColumnIndex = Point.Column-1;
s64 ColumnOffset = UTF8OffsetFromIndex(Line, ColumnIndex);
v2 CursorP = V2(ColumnOffset*GlyphAdvance, LineIndex*LineHeight);
v2_r32 CursorP = V2R32(ColumnOffset*GlyphAdvance, LineIndex*LineHeight);
if(CursorP.y < Editor->Offset.y)
{
@ -805,6 +823,7 @@ static void W_BuildTextEditor(workspace_view *View)
Editor->LastTextPoint.Line = Point.Line;
Editor->LastTextPoint.Column = Max(Editor->LastTextPoint.Column, Point.Column);
}
UI_ResetBlink();
}
}
}

View File

@ -52,7 +52,7 @@ struct workspace_view_text_editor
token_array Tokens;
range1_s64_array Lines;
s64 MaxLineCount;
compiled_scene Compiled;
compiled_scene2 Compiled;
// sixten: text being edited
string FileName;
@ -72,7 +72,8 @@ struct workspace_view_text_editor
history_node *SavePoint;
// sixten: ui building & rendering
v2 Offset;
v2_r32 Offset;
v2_r32 AnimatedOffset;
};
////////////////////////////////
@ -82,26 +83,37 @@ static mutable_string MutableStringAllocate(u64 Size);
static void MutableStringRelease(mutable_string *String);
static void MutableStringReplaceRange(mutable_string *String, string ReplaceString, range1_s64 Range);
////////////////////////////////
//~ sixten: History & Undo Functions
static history_entry HistoryEntry(arena *Arena, string ReplaceString, range1_s64 Range);
static void AppendToHistory(arena *Arena, history_list *List, history_entry Forward, history_entry Backward);
////////////////////////////////
//~ sixten: Workspace Text Editing Functions
static workspace_text_data W_TextDataFromString(arena *Arena, string Text);
static void W_TextEditorApplyChanges(workspace_view_text_editor *Editor);
static void W_SaveTextEditorToFile(workspace_view_text_editor *Editor);
static b32 W_ProcessTextEditorEvent(workspace_view_text_editor *Editor, platform_event *Event);
static b32 W_ProcessDigitalKeyEvent(workspace_view_text_editor *Editor, platform_event_type Type, u32 Data);
////////////////////////////////
//~ sixten: Workspace Text Editor Draw Callbacks
static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback);
static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorLinesBarDrawCallback);
////////////////////////////////
//~ sixten: Workspace Text Editor Builder Functions
static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback);
static b32 W_ProcessTextEditorEvent(workspace_view_text_editor *Editor, platform_event *Event);
static void W_BuildTextEditorInfoBar(workspace_view_text_editor *Editor);
static void W_BuildTextEditorErrorList(workspace_view_text_editor *Editor);
static void W_BuildTextEditor(workspace_view *View);
#endif //VN_WORKSPACE_TEXT_EDITOR_H

View File

@ -1,7 +1,7 @@
//- sixten: Views
inline workspace_view *W_CreateNewView(workspace_view_kind Kind, workspace_panel *Parent)
{
arena *Arena = ArenaAlloc(Kilobytes(4), true);
arena *Arena = ArenaAlloc(Kilobytes(4), true, "Workspace View %i", Kind);
workspace_view *View = PushStruct(Arena, workspace_view);
View->Arena = Arena;
View->Kind = Kind;
@ -18,7 +18,7 @@ inline workspace_view *W_CreateNewView(workspace_view_kind Kind, workspace_panel
{
workspace_view_file_lister *Lister = PushStruct(View->Arena, workspace_view_file_lister);
View->Data = Lister;
Lister->Path = StrLit("data");
Lister->Path = PushString(View->Arena, StrLit("data"));
Lister->SelectedItem = -1;
} break;
@ -28,9 +28,9 @@ inline workspace_view *W_CreateNewView(workspace_view_kind Kind, workspace_panel
View->Data = PushStruct(View->Arena, workspace_view_text_editor);
workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data;
Editor->ProcessingArena = ArenaAlloc(Gigabytes(1));
Editor->ProcessingArena = ArenaAlloc(Gigabytes(1), false, "Workspace View Text Editor Processing Arena");
Editor->Text = MutableStringAllocate(Gigabytes(1));
Editor->HistoryArena = ArenaAlloc(Gigabytes(1));
Editor->HistoryArena = ArenaAlloc(Gigabytes(1), false, "Workspace View Text Editor History Arena");
SenDLLInit(&Editor->History.Sentinel);
Editor->History.At = &Editor->History.Sentinel;
@ -40,7 +40,7 @@ inline workspace_view *W_CreateNewView(workspace_view_kind Kind, workspace_panel
Editor->Tokens = TextData.Tokens;
Editor->Lines = TextData.Lines;
Editor->FontSize = 15.0f;
Editor->FontSize = 14.0f;
} break;
case W_ViewKind_NavEditor:
@ -53,10 +53,6 @@ inline workspace_view *W_CreateNewView(workspace_view_kind Kind, workspace_panel
View->Data = PushStruct(View->Arena, workspace_view_image_viewer);
workspace_view_image_viewer *Viewer = (workspace_view_image_viewer *)View->Data;
Viewer->Scale = 1.0f;
//- sixten(TODO): write an image viewer
// beign with loading the image from the file lister load thingy
// show it on build
// release the handle when done (and add a way to remove texture ig)
} break;
case W_ViewKind_Error:
@ -95,6 +91,12 @@ inline void W_DestroyView(workspace_view *View)
GlobalRenderCommands->DeallocateTexture(Viewer->Texture);
} break;
case W_ViewKind_BytecodeViewer:
{
//workspace_view_bytecode_viewer *Viewer = (workspace_view_bytecode_viewer *)View->Data;
} break;
default: break;
}
@ -189,7 +191,7 @@ static void W_BuildSettingsTabButton(workspace_view_settings *Settings, char *Na
{
b32 IsSelected = (Settings->Category == Category);
v4 Color = LinearBlend(Theme_TextColor, Theme_HighlightBorderColor, AC_AnimateValueF(IsSelected, IsSelected, 0.3, "Workspace Settings %s %p", Name, Settings));
v4_r32 Color = LinearBlend(Theme_TextColor, Theme_HighlightBorderColor, AC_AnimateValueF(IsSelected, IsSelected, 0.3, "Workspace Settings %s %p", Name, Settings));
UI_SetNextFont(Font_Bold);
UI_SetNextHeight(UI_TextContent(0, 1));
@ -246,7 +248,7 @@ static b32 UI_DropdownSelection(char **Alternatives, s32 AlternativeCount, b32 *
{
UI_Tooltip
{
UI_SetNextFixedP(V2(DropdownBox->Rect.Min.x, DropdownBox->Rect.Max.y));
UI_SetNextFixedP(V2R32(DropdownBox->Rect.Min.x, DropdownBox->Rect.Max.y));
UI_SetNextCornerRadius(4);
UI_SetNextWidth(UI_Pixels(200, 1));
UI_SetNextHeight(UI_ChildrenSum(OpenTransition, 1));
@ -294,12 +296,12 @@ UI_CUSTOM_DRAW_CALLBACK(W_ImageViewerUICallback)
v2_r32 ImageDim = ConvertV2ToR32(DimFromTexture(Viewer->Texture));
v2_r32 ScaleImageDim = ImageDim*Viewer->Scale;
v4 Color = Color_White;
v4_r32 Color = Color_White;
range2_r32 Dest;
Dest.Min = (Box->Rect.Max+Box->Rect.Min)*0.5-ScaleImageDim*0.5+Viewer->Offset*Viewer->Scale;
Dest.Max = Dest.Min+ScaleImageDim;
range2_r32 Source = Range2R32(V2R32(0, 0), ImageDim);
PushTexturedQuad(Group, Dest, Source, Color, Color, Color, Color, 0, 0, 0, Viewer->Texture);
PushTexturedQuad(Group, Dest, Source, Color, Color, Color, Color, 0, 0, 0, 0, 0, 0, Viewer->Texture);
}
static void W_BuildImageViewer(workspace_view *View)
@ -354,6 +356,59 @@ static void W_BuildImageViewer(workspace_view *View)
}
}
static void W_BuildBytecodeViewer(workspace_view *View)
{
scene_view *SceneView = SV_GetState();
compiled_scene2 *Compiled = &SceneView->Compiled;
scene2_runtime *Runtime = &SceneView->Runtime;
v4_r32 Colors[] =
{
ColorFromHex(0xECEE8180), ColorFromHex(0x8DDFCB80), ColorFromHex(0x82A0D880), ColorFromHex(0xEDB7ED80)
};
persist r32 ScrollY = 0;
{
UI_Row() UI_Width(UI_Percent(0.5, 1))
{
UI_WidthFill UI_Column() UI_Font(Font_Monospace)
{
for(u64 InstructionIndex = 0; InstructionIndex < Compiled->InstructionCount; InstructionIndex += 1) UI_Height(UI_Em(1.5, 1))
{
UI_WidthFill UI_BackgroundColor(Darken(Theme_BackgroundColor, 1+InstructionIndex%2)) UI_Row(UI_BoxFlag_DrawBackground)
{
scene2_instruction *Instruction = Compiled->Instructions + InstructionIndex;
UI_Font(Font_Icons) UI_TextColor(Color_Yellow)
UI_Width(UI_Em(2.0f, 1)) UI_LabelF("%U", (InstructionIndex == Runtime->InstructionPointer) ? FontIcon_RightDir : 0);
UI_Width(UI_Em(6.0f, 1)) UI_LabelF("%04x", InstructionIndex);
UI_Width(UI_TextContent(1, 1)) UI_LabelF("%S#%i", S2_InstructionInfoLookup[Instruction->Opcode], InstructionIndex);
UI_Spacer(UI_Percent(1, 0));
}
}
}
UI_WidthFill UI_Column()
{
u64 Index = 0;
for(scene2_proc_node *Node = Compiled->ProcList.First; Node != 0; Node = Node->Next, Index += 1)
{
scene2_proc_info *Info = &Node->Info;
UI_SetNextHeight(UI_Em(1.5f*(Info->InstructionEnd-Info->InstructionBegin), 1));
v4_r32 Color = Colors[Index%ArrayCount(Colors)];
UI_SetNextBackgroundColor(Color);
ui_box *Box = UI_MakeBoxF(UI_BoxFlag_Clickable|
UI_BoxFlag_DrawText|
UI_BoxFlag_DrawBorder|
UI_BoxFlag_DrawBackground|
UI_BoxFlag_HotAnimation, "%S", Node->Info.Name);
UI_SignalFromBox(Box);
}
}
}
}
}
static void W_BuildSceneView(workspace_view *View)
{
workspace *Workspace = W_GetState();
@ -505,7 +560,12 @@ static void W_BuildView(workspace_view *View)
W_BuildImageViewer(View);
} break;
case W_ViewKind_TextEditor:
case W_ViewKind_BytecodeViewer:
{
W_BuildBytecodeViewer(View);
} break;
case W_ViewKind_TextEditor:
{
W_BuildTextEditor(View);
} break;
@ -523,7 +583,7 @@ static void W_BuildView(workspace_view *View)
workspace_file_lister_action Action = W_BuildFileLister(View);
if(Action.HasRequestedFile)
{
workspace_file_lister_action *ActionOnDataArena = W_FileListerActionCopy(W_GetState()->CommandDataArena, &Action);
workspace_file_lister_action *ActionOnDataArena = W_FileListerActionCopy(W_GetState()->CommandArena, &Action);
W_IssueCommand(W_Command_OpenFile, PointerToU64(ActionOnDataArena));
W_IssueCommand(W_Command_CloseView, PointerToU64(View));

View File

@ -28,7 +28,9 @@ enum workspace_view_kind
W_ViewKind_SceneView,
W_ViewKind_NavEditor,
W_ViewKind_ImageViewer,
W_ViewKind_Error,
W_ViewKind_BytecodeViewer,
//W_ViewKind_MemoryInspector,
W_ViewKind_Error,
};
struct workspace_view_error
@ -60,6 +62,11 @@ struct workspace_view_image_viewer
v2_r32 Offset;
};
struct workspace_view_bytecode_viewer
{
};
////////////////////////////////
//~ sixten: Workspace View Functions

Binary file not shown.

View File

@ -109,23 +109,27 @@ static PLATFORM_OPEN_FILE(Win32_OpenFile)
{
CreationAttributes = OPEN_EXISTING;
}
if(FileAccess & PlatformAccess_Write)
{
CreationAttributes = CREATE_ALWAYS;
}
if(FileAccess & PlatformAccess_Write)
{
CreationAttributes = CREATE_ALWAYS;
}
if(FileAccess & PlatformAccess_OpenAlways)
{
CreationAttributes = OPEN_ALWAYS;
}
temp Scratch = GetScratch(0, 0);
temp Scratch = GetScratch(0, 0);
string FullPath = PushFormat(Scratch.Arena, "%S\\%S", Global_Win32State.ContentsPath, Path);
HANDLE File = CreateFileA((char *)FullPath.Data, DesiredAccess, 0, 0, CreationAttributes, 0, 0);
string FullPath = PushFormat(Scratch.Arena, "%S\\%S", Global_Win32State.ContentsPath, Path);
HANDLE File = CreateFileA((char *)FullPath.Data, DesiredAccess, 0, 0, CreationAttributes, 0, 0);
ReleaseScratch(Scratch);
ReleaseScratch(Scratch);
platform_file_handle Result = {};
Result.Platform = (u64)File;
Result.IsValid = (File != INVALID_HANDLE_VALUE);
platform_file_handle Result = {};
Result.Platform = (u64)File;
Result.IsValid = (File != INVALID_HANDLE_VALUE);
return(Result);
return(Result);
}
static PLATFORM_CLOSE_FILE(Win32_CloseFile)
@ -144,8 +148,6 @@ static PLATFORM_READ_FILE(Win32_ReadFile)
{
DWORD BytesRead;
ReadFile(File, Dest, Size, &BytesRead, 0);
//Assert(BytesRead == Size);
}
}
@ -409,22 +411,22 @@ static PLATFORM_GET_CLIPBOARD(Win32_GetClipboard)
return(Result);
}
inline v2 Win32_GetMouseP(HWND Window)
inline v2_r32 Win32_GetMouseP(HWND Window)
{
POINT Point;
GetCursorPos(&Point);
ScreenToClient(Window, &Point);
v2 Result = V2(Point.x, Point.y);
v2_r32 Result = V2R32(Point.x, Point.y);
return(Result);
}
inline v2 Win32_GetWindowDim(HWND Window)
inline v2_r32 Win32_GetWindowDim(HWND Window)
{
RECT ClientRect;
GetClientRect(Window, &ClientRect);
v2 Result = V2(ClientRect.right - ClientRect.left, ClientRect.bottom - ClientRect.top);
v2_r32 Result = V2R32(ClientRect.right - ClientRect.left, ClientRect.bottom - ClientRect.top);
return(Result);
}
@ -681,8 +683,8 @@ static void Win32_ProcessInput(vn_input *Input, HWND Window, r32 dtForFrame)
Input->EventList = &State->EventList;
v2 NewMouseP = Win32_GetMouseP(Window);
v2 OldMouseP = Input->MouseP;
v2_r32 NewMouseP = Win32_GetMouseP(Window);
v2_r32 OldMouseP = Input->MouseP;
Input->dMouseP = NewMouseP - OldMouseP;
Input->MouseP = NewMouseP;
@ -766,7 +768,7 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
QueryPerformanceFrequency(&FrequencyQuery);
State->PerformanceFrequency = FrequencyQuery.QuadPart;
State->EventArena = ArenaAlloc(Gigabytes(1));
State->EventArena = ArenaAlloc(Gigabytes(1), false, "Win32 Event Arena");
State->SleepIsGranular = (timeBeginPeriod(1) == TIMERR_NOERROR);
}
@ -781,7 +783,7 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
{
HWND Window = CreateWindowEx(0,
WindowClass.lpszClassName,
"vn - December 2023 Build",
"vn - January 2024 Build",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,

View File

@ -6,7 +6,7 @@ Platform
Dev
{
RenderUIDebugRects = false;
RenderFPSCounter = false;
RenderFPSCounter = true;
ListHotAndActive = false;
ShowWelcomeMessage = false;
}

Binary file not shown.

View File

@ -0,0 +1,33 @@
proc main
//call text_append("hello, line, paint, color, design, address, brightness")
//wait
//call text_clear()
//call ctr_set("Arthur", 5)
//call ctr_set_talking("Arthur")
//call text_append("hello, line, paint, color, design, address, iida")
//wait
//call text_clear()
//call ctr_remove("Arthur")
$ "There was something stange with the setting. Something hanging in the air that you couldn't quite explain."
$ "Your insticts told you to run away, burn it with fire, and assert that it would never see the light of day ever again."
$ "Still it beckoned you..."
$("Arthur", ArthurNormal) "WOAH! Easy there buddy!"
$("Arthur", ArthurHappy) "Wouldn't want you sticking your nose were it don't belong now do we?"
$ "Arthur was his usual friendly self, but something about his tone startled me. It was almost as if he explicily wanted me to know he was hiding something, simply by his mannerisms alone."
$("Arthur") "How about we just forget this ever happened, okay? Look, I'll get you a beer if you just head over to the bar. Tell the bartender I sent you, alright sport?"
call ctr_remove("Arthur")
$ "Without thinking, I started moving towards the bar."
$ "Not necissarily because I wanted what he offered. Or atleast not the beer."
$ "But the idea of just forgetting what I saw. That THING, whatever it was..."
$ "That alone was enticing enough."
call proc_set("main")
end

10
data/proc_test.vns 100644
View File

@ -0,0 +1,10 @@
proc main
$ "yooooooooooooo"
call proc_set("stuff")
end
proc stuff
$("Arthur", ArthurNormal) "Hi! I'm Arthur!"
call ctr_remove("Arthur")
call proc_set("main")
end

Binary file not shown.

View File

@ -1,55 +0,0 @@
nav "data/scene.vnn";
background DemoBackground;
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...";
jump main;
}
"Okay!"
{
}
}
}
proc item
{
"I inspect the strange element";
"It's shimmering outlines intrigue me, however I do not dare lay a finger on it";
"Well, no time to waste!";
}
proc arthur_talk
{
@arthur(normal) "Hi! Thanks for talking to me.";
@arthur "Do you want my rundown once again?";
branch
{
"Yes!"
{
@arthur "Okay then!";
jump main;
}
"No"
{
@arthur "Alright!";
}
}
}
proc monika_talk
{
@monika(leaning) "Okay everyone!";
}

View File

@ -0,0 +1,18 @@
proc main
call text_clear()
a = 5
call stack_sanity(0)
while a == 0 then
call text_append(a)
if a != 1 then
call text_append(", ")
end
wait
a = a - 1
end
$("Arthur", ArthurNormal) "Yo! It works!"
call proc_set("main")
end