Finished config implementation.
parent
aefb393dcc
commit
cab0dac728
114
code/vn.cpp
114
code/vn.cpp
|
@ -1,7 +1,20 @@
|
||||||
#include "vn_platform.h"
|
#include "vn_platform.h"
|
||||||
#include "vn_platform.cpp"
|
#include "vn_platform.cpp"
|
||||||
|
|
||||||
|
#if VN_INTERNAL
|
||||||
|
|
||||||
|
struct debug_settings
|
||||||
|
{
|
||||||
|
b32 RenderUIDebugRects;
|
||||||
|
b32 RenderFPSCounter;
|
||||||
|
};
|
||||||
|
|
||||||
|
per_thread debug_settings *DEBUG_DebugSettings = 0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "vn_config.h"
|
#include "vn_config.h"
|
||||||
|
#include "vn_tokenizer.h"
|
||||||
#include "vn_font.h"
|
#include "vn_font.h"
|
||||||
#include "vn_text_op.h"
|
#include "vn_text_op.h"
|
||||||
#include "vn_ui.h"
|
#include "vn_ui.h"
|
||||||
|
@ -19,50 +32,73 @@
|
||||||
|
|
||||||
struct vn_state
|
struct vn_state
|
||||||
{
|
{
|
||||||
memory_arena Arena;
|
memory_arena Arena;
|
||||||
glyph_atlas *GlyphAtlas;
|
glyph_atlas *GlyphAtlas;
|
||||||
|
|
||||||
config *Config;
|
config *Config;
|
||||||
|
|
||||||
ui UI;
|
ui UI;
|
||||||
workspace Workspace;
|
workspace Workspace;
|
||||||
animation_curve_state AnimationCurveState;
|
animation_curve_state AnimationCurveState;
|
||||||
|
|
||||||
|
#if VN_INTERNAL
|
||||||
|
debug_settings DebugSettings;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
||||||
{
|
{
|
||||||
SetThreadContext(ThreadContext);
|
SetThreadContext(ThreadContext);
|
||||||
Platform = Memory->PlatformAPI;
|
Platform = Memory->PlatformAPI;
|
||||||
|
|
||||||
vn_state *State = Memory->State;
|
|
||||||
|
|
||||||
if(!Memory->State)
|
|
||||||
{
|
|
||||||
State = Memory->State = BootstrapPushStruct(vn_state, Arena);
|
|
||||||
|
|
||||||
State->GlyphAtlas = CreateGlyphAtlas(RenderCommands);
|
vn_state *State = Memory->State;
|
||||||
State->Config = BootstrapPushStruct(config, Arena);
|
|
||||||
|
|
||||||
Config_BindEntry(State->Config, StrLit("Platform/RefreshRate"), Config_Entry_S32, &Input->RefreshRate);
|
if(!Memory->State)
|
||||||
|
{
|
||||||
|
State = Memory->State = BootstrapPushStruct(vn_state, Arena);
|
||||||
|
|
||||||
|
State->GlyphAtlas = CreateGlyphAtlas(RenderCommands);
|
||||||
|
State->Config = BootstrapPushStruct(config, Arena);
|
||||||
|
|
||||||
|
// sixten: Setup config binds and load current config.
|
||||||
|
{
|
||||||
|
Config_BindS32(State->Config, StrLit("Platform/RefreshRate"), &Input->RefreshRate, 60);
|
||||||
|
#if VN_INTERNAL
|
||||||
|
Config_BindB32(State->Config, StrLit("Dev/RenderUIDebugRects"), &State->DebugSettings.RenderUIDebugRects, 0);
|
||||||
|
Config_BindB32(State->Config, StrLit("Dev/RenderFPSCounter"), &State->DebugSettings.RenderFPSCounter, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Config_ReadFile(State->Config, StrLit("config.vn"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Workspace_Init(&State->Workspace);
|
||||||
|
}
|
||||||
|
|
||||||
Workspace_Init(&State->Workspace);
|
#if VN_INTERNAL
|
||||||
}
|
DEBUG_DebugSettings = &State->DebugSettings;
|
||||||
|
#endif
|
||||||
AnimationCurve_NewFrame(&State->AnimationCurveState, Input->dtForFrame);
|
|
||||||
UI_NewFrame(&State->UI, Input->EventList, Input->MouseP);
|
AnimationCurve_NewFrame(&State->AnimationCurveState, Input->dtForFrame);
|
||||||
|
UI_NewFrame(&State->UI, Input->EventList, Input->MouseP);
|
||||||
Workspace_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas);
|
|
||||||
UI_SignalFromBox(UI_GetState()->ContainerNode); // sixten(TODO): Move elsewhere.
|
Workspace_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas);
|
||||||
|
UI_SignalFromBox(UI_GetState()->ContainerNode); // sixten(TODO): Move elsewhere.
|
||||||
for(platform_event *Event = Input->EventList->First;
|
|
||||||
Event != 0;
|
for(platform_event *Event = Input->EventList->First;
|
||||||
Event = Event->Next)
|
Event != 0;
|
||||||
{
|
Event = Event->Next)
|
||||||
Platform_ConsumeEvent(Input->EventList, Event);
|
{
|
||||||
}
|
if(Event->Type == PlatformEvent_WindowClose)
|
||||||
|
{
|
||||||
render_group Group = BeginRenderGroup(RenderCommands);
|
Config_WriteFile(State->Config);
|
||||||
PushClear(&Group, V3(0.1, 0.1, 0.1));
|
Input->ExitRequested = true;
|
||||||
|
}
|
||||||
UI_RenderFrame(&Group, State->GlyphAtlas);
|
|
||||||
|
Platform_ConsumeEvent(Input->EventList, Event);
|
||||||
|
}
|
||||||
|
|
||||||
|
render_group Group = BeginRenderGroup(RenderCommands);
|
||||||
|
PushClear(&Group, V3(0.1, 0.1, 0.1));
|
||||||
|
|
||||||
|
UI_RenderFrame(&Group, State->GlyphAtlas);
|
||||||
}
|
}
|
|
@ -18,7 +18,7 @@ inline animation_curve_key AnimationCurve_GenerateKeyFromString(string String)
|
||||||
return(Key);
|
return(Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static animation_curve_entry *AnimationCurve_GetEntryByKey(animation_curve_key Key, r32 Initial = 0)
|
static animation_curve_entry *AnimationCurve_GetEntryByKey(animation_curve_key Key, r32 Initial)
|
||||||
{
|
{
|
||||||
animation_curve_state *State = AnimationCurve_GetState();
|
animation_curve_state *State = AnimationCurve_GetState();
|
||||||
|
|
||||||
|
|
|
@ -46,4 +46,14 @@ struct animation_curve_state
|
||||||
animation_curve_entry *LastFreeEntry;
|
animation_curve_entry *LastFreeEntry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline void AnimationCurve_SetState(animation_curve_state *State);
|
||||||
|
inline animation_curve_key AnimationCurve_GenerateKeyFromString(string String);
|
||||||
|
static animation_curve_entry *AnimationCurve_GetEntryByKey(animation_curve_key Key, r32 Initial = 0);
|
||||||
|
inline r32 AnimationCurve_GetValue(string Name, r32 Initial);
|
||||||
|
inline void AnimationCurve_SetValue(string Name, r32 Value);
|
||||||
|
inline r32 AnimationCurve_AnimateValueDirect(r32 Target, r32 Duration, r32 *Value);
|
||||||
|
inline r32 AnimationCurve_AnimateValue(r32 Target, r32 Initial, r32 Duration, string Name);
|
||||||
|
inline r32 AnimationCurve_AnimateValueF(r32 Target, r32 Initial, r32 Duration, char *Format, ...);
|
||||||
|
static void AnimationCurve_NewFrame(animation_curve_state *State, r32 dtForFrame);
|
||||||
|
|
||||||
#endif //VN_ANIMATION_CURVE_H
|
#endif //VN_ANIMATION_CURVE_H
|
||||||
|
|
|
@ -19,30 +19,269 @@ static config_entry *Config_FindEntryByName(config *Config, string Name)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Config_ReadFile(config *Config, string Path)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Config_WriteFile(config *Config)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Config_BindEntry(config *Config, string Name, config_entry_type Type, void *Target)
|
static void Config_BindEntry(config *Config, string Name, config_entry_type Type, void *Target)
|
||||||
{
|
{
|
||||||
config_entry *Entry = Config_FindEntryByName(Config, Name);
|
config_entry *Entry = Config_FindEntryByName(Config, Name);
|
||||||
if(!Entry)
|
if(!Entry)
|
||||||
{
|
{
|
||||||
Entry = PushStruct(&Config->Arena, config_entry);
|
Entry = PushStruct(&Config->Arena, config_entry);
|
||||||
Entry->Name = Name;
|
Entry->Name = PushString(&Config->Arena, Name);
|
||||||
Entry->Type = Type;
|
Entry->Type = Type;
|
||||||
|
|
||||||
u32 BucketSlot = HashString(Name) % ArrayCount(Config->EntryBuckets);
|
u32 BucketSlot = HashString(Name) % ArrayCount(Config->EntryBuckets);
|
||||||
config_entry_bucket *Bucket = Config->EntryBuckets + BucketSlot;
|
config_entry_bucket *Bucket = Config->EntryBuckets + BucketSlot;
|
||||||
|
|
||||||
DLLInsertLast(Bucket->First, Bucket->Last, Entry);
|
DLLInsertLast(Bucket->First, Bucket->Last, Entry);
|
||||||
|
|
||||||
|
if(Config->LastInternal)
|
||||||
|
{
|
||||||
|
Config->LastInternal->NextInternal = Entry;
|
||||||
|
Config->LastInternal = Entry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config->FirstInternal = Config->LastInternal = Entry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(Entry->Type == Type);
|
Assert(Entry->Type == Type);
|
||||||
Entry->Target = Target;
|
Entry->Target = Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Config_BindS32(config *Config, string Name, s32 *Target, s32 Default)
|
||||||
|
{
|
||||||
|
*Target = Default;
|
||||||
|
Config_BindEntry(Config, Name, Config_Entry_S32, Target);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Config_BindS64(config *Config, string Name, s64 *Target, s64 Default)
|
||||||
|
{
|
||||||
|
*Target = Default;
|
||||||
|
Config_BindEntry(Config, Name, Config_Entry_S64, Target);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Config_BindB32(config *Config, string Name, b32 *Target, b32 Default)
|
||||||
|
{
|
||||||
|
*Target = Default;
|
||||||
|
Config_BindEntry(Config, Name, Config_Entry_B32, Target);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Config_ParseError(char *Message, memory_arena *Arena)
|
||||||
|
{
|
||||||
|
string String = PushFormat(Arena, "An error occured during config parsing:\n\"%s\"", Message);
|
||||||
|
Platform.ShowMessage(String, Platform_Message_Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Config_ReadFile(config *Config, string Path)
|
||||||
|
{
|
||||||
|
temporary_memory Scratch = GetScratch();
|
||||||
|
|
||||||
|
tokenizer Tokenizer = Tokenizer_BeginTokenization(Platform_ReadEntireFile(Scratch.Arena, Path));
|
||||||
|
if(Tokenizer.Input.Data)
|
||||||
|
{
|
||||||
|
token Token;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
Token = Tokenizer_GetNextToken(&Tokenizer);
|
||||||
|
|
||||||
|
if(Token.Type == Token_Identifier)
|
||||||
|
{
|
||||||
|
string Dir = Token.String;
|
||||||
|
|
||||||
|
if(Tokenizer_RequireToken(&Tokenizer, Token_CurlyOpen))
|
||||||
|
{
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
Token = Tokenizer_GetNextToken(&Tokenizer);
|
||||||
|
|
||||||
|
if(Token.Type == Token_Identifier)
|
||||||
|
{
|
||||||
|
string Name = Token.String;
|
||||||
|
|
||||||
|
if(Tokenizer_RequireToken(&Tokenizer, Token_Equals))
|
||||||
|
{
|
||||||
|
Token = Tokenizer_GetNextToken(&Tokenizer);
|
||||||
|
|
||||||
|
if(Token.Type == Token_IntegerValue)
|
||||||
|
{
|
||||||
|
s64 Value = ConvertStringToS64(Token.String);
|
||||||
|
|
||||||
|
string FullName = PushFormat(Scratch.Arena, "%S/%S", Dir, Name);
|
||||||
|
config_entry *Entry = Config_FindEntryByName(Config, FullName);
|
||||||
|
if(Entry)
|
||||||
|
{
|
||||||
|
if(Entry->Type == Config_Entry_S32)
|
||||||
|
{
|
||||||
|
*(s32 *)Entry->Target = (s32)Value;
|
||||||
|
}
|
||||||
|
else if(Entry->Type == Config_Entry_S64)
|
||||||
|
{
|
||||||
|
*(s64 *)Entry->Target = Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config_ParseError("Entry has wrong data type.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config_ParseError("Cannot find entry.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Token.Type == Token_Identifier)
|
||||||
|
{
|
||||||
|
string FullName = PushFormat(Scratch.Arena, "%S/%S", Dir, Name);
|
||||||
|
config_entry *Entry = Config_FindEntryByName(Config, FullName);
|
||||||
|
if(Entry)
|
||||||
|
{
|
||||||
|
if(AreEqual(Token.String, StrLit("true")))
|
||||||
|
{
|
||||||
|
*(b32 *)Entry->Target = true;
|
||||||
|
}
|
||||||
|
else if(AreEqual(Token.String, StrLit("false")))
|
||||||
|
{
|
||||||
|
*(b32 *)Entry->Target = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config_ParseError("Entry has wrong data type.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config_ParseError("Cannot find entry.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config_ParseError("Expected a value.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Tokenizer_RequireToken(&Tokenizer, Token_Semicolon))
|
||||||
|
{
|
||||||
|
Config_ParseError("Expected a ';'.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config_ParseError("Expected '='.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Token.Type == Token_CurlyClose)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config_ParseError("Expected '}' or identifier.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config_ParseError("Expected '{'.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Token.Type == Token_EndOfFile)
|
||||||
|
{
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config_ParseError("Unexpected token.", Scratch.Arena);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
End:
|
||||||
|
ReleaseScratch(Scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Config_WriteFile(config *Config)
|
||||||
|
{
|
||||||
|
string_list Out = {};
|
||||||
|
temporary_memory Scratch = GetScratch();
|
||||||
|
|
||||||
|
string LastDir = MakeString(0, 0);
|
||||||
|
for(config_entry *Entry = Config->FirstInternal;
|
||||||
|
Entry != 0;
|
||||||
|
Entry = Entry->NextInternal)
|
||||||
|
{
|
||||||
|
s64 LastSlash = LastIndexOf(Entry->Name, '/');
|
||||||
|
Assert(LastSlash != -1);
|
||||||
|
|
||||||
|
string Dir = Prefix(Entry->Name, LastSlash);
|
||||||
|
string Name = Suffix(Entry->Name, Entry->Name.Count - LastSlash - 1);
|
||||||
|
|
||||||
|
if(!AreEqual(Dir, LastDir))
|
||||||
|
{
|
||||||
|
if(!AreEqual(LastDir, MakeString(0, 0)))
|
||||||
|
{
|
||||||
|
AppendString(&Out, StrLit("}\n\n"), Scratch.Arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendString(&Out, Dir, Scratch.Arena);
|
||||||
|
AppendString(&Out, StrLit("\n{\n"), Scratch.Arena);
|
||||||
|
|
||||||
|
LastDir = Dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendString(&Out, StrLit("\t"), Scratch.Arena);
|
||||||
|
AppendString(&Out, Name, Scratch.Arena);
|
||||||
|
AppendString(&Out, StrLit(" = "), Scratch.Arena);
|
||||||
|
|
||||||
|
// sixten: Output the value of the entry
|
||||||
|
if(Entry->Type == Config_Entry_S32 || Entry->Type == Config_Entry_S64)
|
||||||
|
{
|
||||||
|
s64 IntegerValue;
|
||||||
|
if(Entry->Type == Config_Entry_S32)
|
||||||
|
{
|
||||||
|
IntegerValue = *(s32 *)Entry->Target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IntegerValue = *(s64 *)Entry->Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
string Value = ConvertS64ToString(IntegerValue, Scratch.Arena);
|
||||||
|
AppendString(&Out, Value, Scratch.Arena);
|
||||||
|
}
|
||||||
|
else if(Entry->Type == Config_Entry_B32)
|
||||||
|
{
|
||||||
|
string Value = (*(b32 *)Entry->Target)?StrLit("true"):StrLit("false");
|
||||||
|
AppendString(&Out, Value, Scratch.Arena);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UnimplementedCodepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendString(&Out, StrLit(";\n"), Scratch.Arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!AreEqual(LastDir, MakeString(0, 0)))
|
||||||
|
{
|
||||||
|
AppendString(&Out, StrLit("}"), Scratch.Arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
string FinalOut = JoinStringList(&Out, Scratch.Arena);
|
||||||
|
|
||||||
|
platform_file_handle Handle = Platform.OpenFile(StrLit("config.vn"), PlatformAccess_Write);
|
||||||
|
if(Handle.IsValid)
|
||||||
|
{
|
||||||
|
Platform.WriteFile(Handle, FinalOut.Data, 0, FinalOut.Count);
|
||||||
|
Platform.CloseFile(Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseScratch(Scratch);
|
||||||
}
|
}
|
|
@ -18,6 +18,8 @@ struct config_entry
|
||||||
|
|
||||||
config_entry *Next;
|
config_entry *Next;
|
||||||
config_entry *Prev;
|
config_entry *Prev;
|
||||||
|
|
||||||
|
config_entry *NextInternal;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct config_entry_bucket
|
struct config_entry_bucket
|
||||||
|
@ -30,13 +32,20 @@ struct config
|
||||||
{
|
{
|
||||||
memory_arena Arena;
|
memory_arena Arena;
|
||||||
config_entry_bucket EntryBuckets[32];
|
config_entry_bucket EntryBuckets[32];
|
||||||
|
|
||||||
|
// sixten(NOTE): Keeps track of the order in which the entries were declared. (Used during saving)
|
||||||
|
config_entry *FirstInternal;
|
||||||
|
config_entry *LastInternal;
|
||||||
};
|
};
|
||||||
|
|
||||||
static config_entry *Config_FindEntryByName(config *Config, string Name);
|
static config_entry *Config_FindEntryByName(config *Config, string Name);
|
||||||
|
|
||||||
|
static void Config_BindEntry(config *Config, string Name, config_entry_type Type, void *Target);
|
||||||
|
inline void Config_BindS32(config *Config, string Name, s32 *Target, s32 Default);
|
||||||
|
inline void Config_BindS64(config *Config, string Name, s64 *Target, s64 Default);
|
||||||
|
inline void Config_BindB32(config *Config, string Name, b32 *Target, b32 Default);
|
||||||
|
|
||||||
static void Config_ReadFile(config *Config, string Path);
|
static void Config_ReadFile(config *Config, string Path);
|
||||||
static void Config_WriteFile(config *Config);
|
static void Config_WriteFile(config *Config);
|
||||||
|
|
||||||
static void Config_BindEntry(config *Config, string Name, config_entry_type, void *Target);
|
|
||||||
|
|
||||||
#endif //VN_CONFIG_H
|
#endif //VN_CONFIG_H
|
||||||
|
|
|
@ -66,8 +66,9 @@ IsNull(p) ? (SetNull((n)->prev), (n)->next = (f), (IsNull(f) ? (0) : ((f)->prev
|
||||||
|
|
||||||
#include "vn_types.h"
|
#include "vn_types.h"
|
||||||
#include "vn_math.h"
|
#include "vn_math.h"
|
||||||
#include "vn_string.h"
|
|
||||||
|
|
||||||
|
// sixten(TODO): Scuffed AF. Need to make a proper "core" of the codebase.
|
||||||
|
static s64 UTF8FromCodepoint(u8 *Out, u32 Codepoint);
|
||||||
#define STB_SPRINTF_IMPLEMENTATION
|
#define STB_SPRINTF_IMPLEMENTATION
|
||||||
#include "third_party/stb_sprintf.h"
|
#include "third_party/stb_sprintf.h"
|
||||||
|
|
||||||
|
@ -126,6 +127,12 @@ inline void EndTicketMutex(ticket_mutex *Mutex)
|
||||||
AtomicAddU64(&Mutex->Serving, 1);
|
AtomicAddU64(&Mutex->Serving, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline b32 InRange(range_s64 Range, s64 P)
|
||||||
|
{
|
||||||
|
b32 Result = ((P >= Range.Min) && (P < Range.Max));
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
inline b32 InRange(range2_r32 Range, v2 P)
|
inline b32 InRange(range2_r32 Range, v2 P)
|
||||||
{
|
{
|
||||||
b32 Result = ((P.x >= Range.Min.x) &&
|
b32 Result = ((P.x >= Range.Min.x) &&
|
||||||
|
@ -153,6 +160,12 @@ inline range2_r32 Range2R32(v2 A, v2 B)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline s64 DimOfRange(range_s64 Range)
|
||||||
|
{
|
||||||
|
s64 Dim = Range.Max - Range.Min;
|
||||||
|
return(Dim);
|
||||||
|
}
|
||||||
|
|
||||||
inline v2 DimOfRange(range2_r32 Range)
|
inline v2 DimOfRange(range2_r32 Range)
|
||||||
{
|
{
|
||||||
v2 Dim = Range.Max - Range.Min;
|
v2 Dim = Range.Max - Range.Min;
|
||||||
|
|
|
@ -23,6 +23,12 @@ inline r32 Ceil(r32 Value)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline r32 Log(r32 Value)
|
||||||
|
{
|
||||||
|
r32 Result = logf(Value);
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
inline r32 Pow(r32 Base, r32 Exponent)
|
inline r32 Pow(r32 Base, r32 Exponent)
|
||||||
{
|
{
|
||||||
r32 Result = powf(Base, Exponent);
|
r32 Result = powf(Base, Exponent);
|
||||||
|
@ -48,6 +54,18 @@ inline b32 AreAlmostEqual(r32 A, r32 B)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline s64 Min(s64 A, s64 B)
|
||||||
|
{
|
||||||
|
s64 Result = Minimum(A, B);
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline s64 Max(s64 A, s64 B)
|
||||||
|
{
|
||||||
|
s64 Result = Maximum(A, B);
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
inline v2s operator+(v2s A, v2s B)
|
inline v2s operator+(v2s A, v2s B)
|
||||||
{
|
{
|
||||||
v2s Result = {A.x + B.x, A.y + B.y};
|
v2s Result = {A.x + B.x, A.y + B.y};
|
||||||
|
|
|
@ -209,6 +209,9 @@ inline string PushFormat(memory_arena *Arena, char *Format, ...)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sixten(TODO): Scuffed AF. Need to make a proper "core" of the codebase.
|
||||||
|
inline s64 StringLength(char *String);
|
||||||
|
|
||||||
inline string PushCString(memory_arena *Arena, char *CString)
|
inline string PushCString(memory_arena *Arena, char *CString)
|
||||||
{
|
{
|
||||||
string Result;
|
string Result;
|
||||||
|
|
|
@ -44,6 +44,9 @@ typedef PLATFORM_CLOSE_FILE(platform_close_file);
|
||||||
#define PLATFORM_READ_FILE(name) void name(platform_file_handle Handle, void *Dest, u64 Offset, u64 Size)
|
#define PLATFORM_READ_FILE(name) void name(platform_file_handle Handle, void *Dest, u64 Offset, u64 Size)
|
||||||
typedef PLATFORM_READ_FILE(platform_read_file);
|
typedef PLATFORM_READ_FILE(platform_read_file);
|
||||||
|
|
||||||
|
#define PLATFORM_WRITE_FILE(name) void name(platform_file_handle Handle, void *Source, u64 Offset, u64 Size)
|
||||||
|
typedef PLATFORM_WRITE_FILE(platform_write_file);
|
||||||
|
|
||||||
#define PLATFORM_GET_FILE_SIZE(name) u64 name(platform_file_handle Handle)
|
#define PLATFORM_GET_FILE_SIZE(name) u64 name(platform_file_handle Handle)
|
||||||
typedef PLATFORM_GET_FILE_SIZE(platform_get_file_size);
|
typedef PLATFORM_GET_FILE_SIZE(platform_get_file_size);
|
||||||
|
|
||||||
|
@ -71,6 +74,17 @@ typedef PLATFORM_SET_CURSOR(platform_set_cursor);
|
||||||
#define PLATFORM_TOGGLE_FULLSCREEN(name) void name(void)
|
#define PLATFORM_TOGGLE_FULLSCREEN(name) void name(void)
|
||||||
typedef PLATFORM_TOGGLE_FULLSCREEN(platform_toggle_fullscreen);
|
typedef PLATFORM_TOGGLE_FULLSCREEN(platform_toggle_fullscreen);
|
||||||
|
|
||||||
|
enum platform_message_type
|
||||||
|
{
|
||||||
|
Platform_Message_Info,
|
||||||
|
Platform_Message_Warning,
|
||||||
|
Platform_Message_Error,
|
||||||
|
Platform_Message_Fatal,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PLATFORM_SHOW_MESSAGE(name) void name(string Message, platform_message_type Type)
|
||||||
|
typedef PLATFORM_SHOW_MESSAGE(platform_show_message);
|
||||||
|
|
||||||
struct platform_api
|
struct platform_api
|
||||||
{
|
{
|
||||||
platform_allocate_memory *AllocateMemory;
|
platform_allocate_memory *AllocateMemory;
|
||||||
|
@ -79,10 +93,12 @@ struct platform_api
|
||||||
platform_open_file *OpenFile;
|
platform_open_file *OpenFile;
|
||||||
platform_close_file *CloseFile;
|
platform_close_file *CloseFile;
|
||||||
platform_read_file *ReadFile;
|
platform_read_file *ReadFile;
|
||||||
|
platform_write_file *WriteFile;
|
||||||
platform_get_file_size *GetFileSize;
|
platform_get_file_size *GetFileSize;
|
||||||
|
|
||||||
platform_set_cursor *SetCursor;
|
platform_set_cursor *SetCursor;
|
||||||
platform_toggle_fullscreen *ToggleFullscreen;
|
platform_toggle_fullscreen *ToggleFullscreen;
|
||||||
|
platform_show_message *ShowMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum platform_event_type
|
enum platform_event_type
|
||||||
|
@ -91,6 +107,7 @@ enum platform_event_type
|
||||||
PlatformEvent_Release,
|
PlatformEvent_Release,
|
||||||
PlatformEvent_Text,
|
PlatformEvent_Text,
|
||||||
PlatformEvent_MouseScroll,
|
PlatformEvent_MouseScroll,
|
||||||
|
PlatformEvent_WindowClose,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum platform_key
|
enum platform_key
|
||||||
|
@ -201,6 +218,7 @@ struct vn_input
|
||||||
|
|
||||||
// sixten: Application to platform
|
// sixten: Application to platform
|
||||||
s32 RefreshRate;
|
s32 RefreshRate;
|
||||||
|
b32 ExitRequested;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vn_memory
|
struct vn_memory
|
||||||
|
|
474
code/vn_string.h
474
code/vn_string.h
|
@ -5,181 +5,273 @@
|
||||||
|
|
||||||
inline b32 IsWhitespace(char C)
|
inline b32 IsWhitespace(char C)
|
||||||
{
|
{
|
||||||
b32 Result = ((C == ' ') ||
|
b32 Result = ((C == ' ') ||
|
||||||
(C == '\n') ||
|
(C == '\n') ||
|
||||||
(C == '\t') ||
|
(C == '\t') ||
|
||||||
(C == '\r'));
|
(C == '\r'));
|
||||||
return(Result);
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline b32 IsDigit(char C)
|
||||||
|
{
|
||||||
|
b32 Result = ((C >= '0') && (C <= '9'));
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline b32 IsLetter(char C)
|
||||||
|
{
|
||||||
|
b32 Result = ((C >= 'A') && (C <= 'Z')) || ((C >= 'a') && (C <= 'z'));
|
||||||
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline s64 StringLength(char *String)
|
inline s64 StringLength(char *String)
|
||||||
{
|
{
|
||||||
s64 Result = 0;
|
s64 Result = 0;
|
||||||
while(*String++)
|
while(*String++)
|
||||||
{
|
{
|
||||||
++Result;
|
++Result;
|
||||||
}
|
}
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
|
||||||
|
|
||||||
inline u64 HashString(string String)
|
|
||||||
{
|
|
||||||
u64 Result = 5731;
|
|
||||||
for(s64 Index = 0;
|
|
||||||
Index < String.Count;
|
|
||||||
++Index)
|
|
||||||
{
|
|
||||||
Result += String.Data[Index];
|
|
||||||
Result ^= Result << 13;
|
|
||||||
Result ^= Result >> 7;
|
|
||||||
Result ^= Result << 17;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(Result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline string MakeStringFromCString(char *Data)
|
inline string MakeStringFromCString(char *Data)
|
||||||
{
|
{
|
||||||
string Result = {StringLength(Data), (u8 *)Data};
|
string Result = {StringLength(Data), (u8 *)Data};
|
||||||
return(Result);
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 HashString(string String)
|
||||||
|
{
|
||||||
|
u64 Result = 5731;
|
||||||
|
for(s64 Index = 0;
|
||||||
|
Index < String.Count;
|
||||||
|
++Index)
|
||||||
|
{
|
||||||
|
Result += String.Data[Index];
|
||||||
|
Result ^= Result << 13;
|
||||||
|
Result ^= Result >> 7;
|
||||||
|
Result ^= Result << 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline b32 AreEqual(string A, string B)
|
inline b32 AreEqual(string A, string B)
|
||||||
{
|
{
|
||||||
b32 Result = false;
|
b32 Result = false;
|
||||||
if(A.Count == B.Count)
|
if(A.Count == B.Count)
|
||||||
{
|
|
||||||
Result = true;
|
|
||||||
|
|
||||||
for(s64 Index = 0;
|
|
||||||
Index < A.Count;
|
|
||||||
++Index)
|
|
||||||
{
|
{
|
||||||
if(A.Data[Index] != B.Data[Index])
|
Result = true;
|
||||||
{
|
|
||||||
Result = false;
|
for(s64 Index = 0;
|
||||||
break;
|
Index < A.Count;
|
||||||
}
|
++Index)
|
||||||
|
{
|
||||||
|
if(A.Data[Index] != B.Data[Index])
|
||||||
|
{
|
||||||
|
Result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return(Result);
|
||||||
return(Result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline s64 FirstIndexOf(string String, char Char)
|
inline s64 FirstIndexOf(string String, char Char)
|
||||||
{
|
{
|
||||||
s64 Result = -1;
|
s64 Result = -1;
|
||||||
for(s64 Index = 0;
|
for(s64 Index = 0;
|
||||||
Index < String.Count;
|
Index < String.Count;
|
||||||
++Index)
|
++Index)
|
||||||
{
|
|
||||||
if(String.Data[Index] == Char)
|
|
||||||
{
|
{
|
||||||
Result = Index;
|
if(String.Data[Index] == Char)
|
||||||
break;
|
{
|
||||||
|
Result = Index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return(Result);
|
||||||
return(Result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline s64 LastIndexOf(string String, char Char)
|
inline s64 LastIndexOf(string String, char Char)
|
||||||
{
|
{
|
||||||
s64 Result = -1;
|
s64 Result = -1;
|
||||||
for(s64 Index = String.Count-1;
|
for(s64 Index = String.Count-1;
|
||||||
Index >= 0;
|
Index >= 0;
|
||||||
--Index)
|
--Index)
|
||||||
{
|
|
||||||
if(String.Data[Index] == Char)
|
|
||||||
{
|
{
|
||||||
Result = Index;
|
if(String.Data[Index] == Char)
|
||||||
break;
|
{
|
||||||
|
Result = Index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return(Result);
|
||||||
return(Result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline s64 LastIndexOf(string String, string Substring)
|
inline s64 LastIndexOf(string String, string Substring)
|
||||||
{
|
{
|
||||||
s64 Result = -1;
|
s64 Result = -1;
|
||||||
if(String.Count >= Substring.Count)
|
if(String.Count >= Substring.Count)
|
||||||
{
|
|
||||||
for(s64 Index = String.Count-Substring.Count;
|
|
||||||
Index >= 0;
|
|
||||||
--Index)
|
|
||||||
{
|
{
|
||||||
string ToCheck = MakeString((char *)String.Data + Index, Substring.Count);
|
for(s64 Index = String.Count-Substring.Count;
|
||||||
if(AreEqual(ToCheck, Substring))
|
Index >= 0;
|
||||||
{
|
--Index)
|
||||||
Result = Index;
|
{
|
||||||
break;
|
string ToCheck = MakeString((char *)String.Data + Index, Substring.Count);
|
||||||
}
|
if(AreEqual(ToCheck, Substring))
|
||||||
|
{
|
||||||
|
Result = Index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return(Result);
|
||||||
return(Result);
|
}
|
||||||
|
|
||||||
|
static s64 ConvertStringToS64(string String)
|
||||||
|
{
|
||||||
|
s64 Result = 0;
|
||||||
|
b32 IsNegative = false;
|
||||||
|
|
||||||
|
s64 Index = 0;
|
||||||
|
if(String.Data[Index] == '-')
|
||||||
|
{
|
||||||
|
IsNegative = true;
|
||||||
|
++Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;Index < String.Count; ++Index)
|
||||||
|
{
|
||||||
|
u8 Char = String.Data[Index];
|
||||||
|
Assert(IsDigit(Char));
|
||||||
|
Result = Result*10 + (Char-'0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(IsNegative)
|
||||||
|
{
|
||||||
|
Result = -Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static string ConvertS64ToString(s64 Value, memory_arena *Arena)
|
||||||
|
{
|
||||||
|
b32 IsNegative = (Value < 0);
|
||||||
|
if(IsNegative)
|
||||||
|
{
|
||||||
|
Value = -Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 DigitCount = (s64)Floor(Log(Max(Value, 1)) / Log(10)) + 1;
|
||||||
|
|
||||||
|
s64 TotalBufferCount = DigitCount + IsNegative;
|
||||||
|
|
||||||
|
string String = {TotalBufferCount, PushArray(Arena, u8, TotalBufferCount + 1)};
|
||||||
|
String.Data[TotalBufferCount] = 0;
|
||||||
|
|
||||||
|
if(IsNegative)
|
||||||
|
{
|
||||||
|
String.Data[0] = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
for(s64 Index = 0;
|
||||||
|
Index < DigitCount;
|
||||||
|
++Index)
|
||||||
|
{
|
||||||
|
String.Data[TotalBufferCount - 1 - Index] = '0' + (Value % 10);
|
||||||
|
Value /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(String);
|
||||||
|
}
|
||||||
|
|
||||||
|
static string Substring(string String, range_s64 Range)
|
||||||
|
{
|
||||||
|
string Result = MakeString((char *)String.Data + Range.Min, DimOfRange(Range));
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static string Prefix(string String, s64 Count)
|
||||||
|
{
|
||||||
|
range_s64 Range = RangeS64(0, Count);
|
||||||
|
|
||||||
|
string Result = Substring(String, Range);
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static string Suffix(string String, s64 Count)
|
||||||
|
{
|
||||||
|
range_s64 Range = RangeS64(String.Count - Count, String.Count);
|
||||||
|
|
||||||
|
string Result = Substring(String, Range);
|
||||||
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static s64 UTF8FromCodepoint(u8 *Out, u32 Codepoint)
|
static s64 UTF8FromCodepoint(u8 *Out, u32 Codepoint)
|
||||||
{
|
{
|
||||||
s64 Length = 0;
|
s64 Length = 0;
|
||||||
if(Codepoint <= 0x7F)
|
if(Codepoint <= 0x7F)
|
||||||
{
|
{
|
||||||
Out[0] = (u8)Codepoint;
|
Out[0] = (u8)Codepoint;
|
||||||
Length = 1;
|
Length = 1;
|
||||||
}
|
}
|
||||||
else if(Codepoint <= 0x7FF)
|
else if(Codepoint <= 0x7FF)
|
||||||
{
|
{
|
||||||
Out[0] = (0x3 << 6) | ((Codepoint >> 6) & 0x1F);
|
Out[0] = (0x3 << 6) | ((Codepoint >> 6) & 0x1F);
|
||||||
Out[1] = 0x80 | ( Codepoint & 0x3F);
|
Out[1] = 0x80 | ( Codepoint & 0x3F);
|
||||||
Length = 2;
|
Length = 2;
|
||||||
}
|
}
|
||||||
else if(Codepoint <= 0xFFFF)
|
else if(Codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
Out[0] = (0x7 << 5) | ((Codepoint >> 12) & 0x0F);
|
Out[0] = (0x7 << 5) | ((Codepoint >> 12) & 0x0F);
|
||||||
Out[1] = 0x80 | ((Codepoint >> 6) & 0x3F);
|
Out[1] = 0x80 | ((Codepoint >> 6) & 0x3F);
|
||||||
Out[2] = 0x80 | ( Codepoint & 0x3F);
|
Out[2] = 0x80 | ( Codepoint & 0x3F);
|
||||||
Length = 3;
|
Length = 3;
|
||||||
}
|
}
|
||||||
else if(Codepoint <= 0x10FFFF)
|
else if(Codepoint <= 0x10FFFF)
|
||||||
{
|
{
|
||||||
Out[0] = (0xF << 4) | ((Codepoint >> 12) & 0x07);
|
Out[0] = (0xF << 4) | ((Codepoint >> 12) & 0x07);
|
||||||
Out[1] = 0x80 | ((Codepoint >> 12) & 0x3F);
|
Out[1] = 0x80 | ((Codepoint >> 12) & 0x3F);
|
||||||
Out[2] = 0x80 | ((Codepoint >> 6) & 0x3F);
|
Out[2] = 0x80 | ((Codepoint >> 6) & 0x3F);
|
||||||
Out[3] = 0x80 | ( Codepoint & 0x3F);
|
Out[3] = 0x80 | ( Codepoint & 0x3F);
|
||||||
Length = 4;
|
Length = 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Out[0] = '?';
|
Out[0] = '?';
|
||||||
Length = 1;
|
Length = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(Length);
|
return(Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline s64 GetCodepointSize(u32 Codepoint)
|
inline s64 GetCodepointSize(u32 Codepoint)
|
||||||
{
|
{
|
||||||
s64 Result = 0;
|
s64 Result = 0;
|
||||||
if(Codepoint <= 0x7F)
|
if(Codepoint <= 0x7F)
|
||||||
{
|
{
|
||||||
Result = 1;
|
Result = 1;
|
||||||
}
|
}
|
||||||
else if(Codepoint <= 0x7FF)
|
else if(Codepoint <= 0x7FF)
|
||||||
{
|
{
|
||||||
Result = 2;
|
Result = 2;
|
||||||
}
|
}
|
||||||
else if(Codepoint <= 0xFFFF)
|
else if(Codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
Result = 3;
|
Result = 3;
|
||||||
}
|
}
|
||||||
else if(Codepoint <= 0x10FFFF)
|
else if(Codepoint <= 0x10FFFF)
|
||||||
{
|
{
|
||||||
Result = 4;
|
Result = 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Result = 1;
|
Result = 1;
|
||||||
}
|
}
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sixten(TODO): Remove this forward decl.
|
// sixten(TODO): Remove this forward decl.
|
||||||
|
@ -187,61 +279,95 @@ inline string PushCString(struct memory_arena *Arena, char *CString);
|
||||||
|
|
||||||
inline string StringFromCodepoint(struct memory_arena *Arena, u32 Codepoint)
|
inline string StringFromCodepoint(struct memory_arena *Arena, u32 Codepoint)
|
||||||
{
|
{
|
||||||
char Buffer[5] = {};
|
char Buffer[5] = {};
|
||||||
UTF8FromCodepoint((u8 *)Buffer, Codepoint);
|
UTF8FromCodepoint((u8 *)Buffer, Codepoint);
|
||||||
|
|
||||||
string Result = PushCString(Arena, Buffer);
|
string Result = PushCString(Arena, Buffer);
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct utf8_iterator
|
struct utf8_iterator
|
||||||
{
|
{
|
||||||
string Data;
|
string Data;
|
||||||
s64 Index;
|
s64 Index;
|
||||||
|
|
||||||
u32 Codepoint;
|
u32 Codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Advance(utf8_iterator *Iter)
|
inline void Advance(utf8_iterator *Iter)
|
||||||
{
|
{
|
||||||
u8 *At = Iter->Data.Data + Iter->Index;
|
u8 *At = Iter->Data.Data + Iter->Index;
|
||||||
|
|
||||||
if(Iter->Index < Iter->Data.Count)
|
if(Iter->Index < Iter->Data.Count)
|
||||||
{
|
|
||||||
if((At[0] & 0x80) == 0x00)
|
|
||||||
{
|
{
|
||||||
Iter->Codepoint = (At[0] & 0x7F);
|
if((At[0] & 0x80) == 0x00)
|
||||||
Iter->Index += 1;
|
{
|
||||||
|
Iter->Codepoint = (At[0] & 0x7F);
|
||||||
|
Iter->Index += 1;
|
||||||
|
}
|
||||||
|
else if((At[0] & 0xE0) == 0xC0)
|
||||||
|
{
|
||||||
|
Iter->Codepoint = ((At[0] & 0x1F) << 6)|(At[1] & 0x3F);
|
||||||
|
Iter->Index += 2;
|
||||||
|
}
|
||||||
|
else if((At[0] & 0xF0) == 0xE0)
|
||||||
|
{
|
||||||
|
Iter->Codepoint = ((At[0] & 0x0F) << 12)|((At[1] & 0x3F) << 6)|(At[2] & 0x3F);
|
||||||
|
Iter->Index += 3;
|
||||||
|
}
|
||||||
|
else if((Iter->Data.Data[Iter->Index] & 0xF8) == 0xF0)
|
||||||
|
{
|
||||||
|
Iter->Codepoint = ((At[0] & 0x0F) << 18)|((At[1] & 0x3F) << 12)|((At[2] & 0x3F) << 6)|(At[3] & 0x3F);
|
||||||
|
Iter->Index += 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if((At[0] & 0xE0) == 0xC0)
|
else
|
||||||
{
|
{
|
||||||
Iter->Codepoint = ((At[0] & 0x1F) << 6)|(At[1] & 0x3F);
|
Iter->Codepoint = 0;
|
||||||
Iter->Index += 2;
|
|
||||||
}
|
}
|
||||||
else if((At[0] & 0xF0) == 0xE0)
|
|
||||||
{
|
|
||||||
Iter->Codepoint = ((At[0] & 0x0F) << 12)|((At[1] & 0x3F) << 6)|(At[2] & 0x3F);
|
|
||||||
Iter->Index += 3;
|
|
||||||
}
|
|
||||||
else if((Iter->Data.Data[Iter->Index] & 0xF8) == 0xF0)
|
|
||||||
{
|
|
||||||
Iter->Codepoint = ((At[0] & 0x0F) << 18)|((At[1] & 0x3F) << 12)|((At[2] & 0x3F) << 6)|(At[3] & 0x3F);
|
|
||||||
Iter->Index += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Iter->Codepoint = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline utf8_iterator IterateUTF8String(string String)
|
inline utf8_iterator IterateUTF8String(string String)
|
||||||
{
|
{
|
||||||
utf8_iterator Iter = {};
|
utf8_iterator Iter = {};
|
||||||
Iter.Data = String;
|
Iter.Data = String;
|
||||||
Advance(&Iter);
|
Advance(&Iter);
|
||||||
|
|
||||||
return(Iter);
|
return(Iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AppendString(string_list *List, string String, memory_arena *Arena)
|
||||||
|
{
|
||||||
|
string_node *Node = PushStruct(Arena, string_node);
|
||||||
|
Node->String = String;
|
||||||
|
|
||||||
|
List->TotalCount += String.Count;
|
||||||
|
|
||||||
|
DLLInsertLast(List->First, List->Last, Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static string JoinStringList(string_list *List, memory_arena *Arena)
|
||||||
|
{
|
||||||
|
u8 *Buffer = PushArray(Arena, u8, List->TotalCount + 1);
|
||||||
|
Buffer[List->TotalCount] = 0;
|
||||||
|
|
||||||
|
s64 GlobalIndex = 0;
|
||||||
|
|
||||||
|
for(string_node *Node = List->First;
|
||||||
|
Node != 0;
|
||||||
|
Node = Node->Next)
|
||||||
|
{
|
||||||
|
string String = Node->String;
|
||||||
|
for(s64 Index = 0;
|
||||||
|
Index < String.Count;
|
||||||
|
++Index)
|
||||||
|
{
|
||||||
|
Buffer[GlobalIndex++] = String.Data[Index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string Result = MakeString((char *)Buffer, List->TotalCount);
|
||||||
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //VN_STRING_H
|
#endif //VN_STRING_H
|
||||||
|
|
|
@ -22,7 +22,7 @@ inline thread_context *GetThreadContext(void)
|
||||||
return(ThreadLocal_ThreadContext);
|
return(ThreadLocal_ThreadContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
static temporary_memory GetScratch(memory_arena **Conflicts, u64 ConflictCount)
|
static temporary_memory GetScratch(memory_arena **Conflicts = 0, u64 ConflictCount = 0)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = {};
|
temporary_memory Scratch = {};
|
||||||
thread_context *Context = GetThreadContext();
|
thread_context *Context = GetThreadContext();
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/* date = June 18th 2023 5:12 pm */
|
||||||
|
|
||||||
|
#ifndef VN_TOKENIZER_H
|
||||||
|
#define VN_TOKENIZER_H
|
||||||
|
|
||||||
|
enum token_type
|
||||||
|
{
|
||||||
|
Token_EndOfFile,
|
||||||
|
Token_Identifier,
|
||||||
|
Token_IntegerValue,
|
||||||
|
//Token_RealValue,
|
||||||
|
Token_CurlyOpen,
|
||||||
|
Token_CurlyClose,
|
||||||
|
Token_Semicolon,
|
||||||
|
Token_Equals,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tokenizer
|
||||||
|
{
|
||||||
|
string Input;
|
||||||
|
s64 At;
|
||||||
|
s64 Index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct token
|
||||||
|
{
|
||||||
|
token_type Type;
|
||||||
|
string String;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline tokenizer Tokenizer_BeginTokenization(string Input)
|
||||||
|
{
|
||||||
|
tokenizer Result = {};
|
||||||
|
Result.Input = Input;
|
||||||
|
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static token Tokenizer_GetNextToken(tokenizer *Tokenizer)
|
||||||
|
{
|
||||||
|
token Token = {};
|
||||||
|
|
||||||
|
string Input = Tokenizer->Input;
|
||||||
|
u8 *Base = Input.Data;
|
||||||
|
|
||||||
|
// sixten: Consume whitespace
|
||||||
|
while(IsWhitespace(Base[Tokenizer->Index]))
|
||||||
|
{
|
||||||
|
++Tokenizer->Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sixten(NOTE): Assume single char token.
|
||||||
|
Token.String.Data = Base + Tokenizer->Index;
|
||||||
|
Token.String.Count = 1;
|
||||||
|
|
||||||
|
if(Tokenizer->Index < Input.Count)
|
||||||
|
{
|
||||||
|
switch(Base[Tokenizer->Index])
|
||||||
|
{
|
||||||
|
case '{': { Token.Type = Token_CurlyOpen; } break;
|
||||||
|
case '}': { Token.Type = Token_CurlyClose; } break;
|
||||||
|
case ';': { Token.Type = Token_Semicolon; } break;
|
||||||
|
case '=': { Token.Type = Token_Equals; } break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if(IsDigit(Base[Tokenizer->Index]) || Base[Tokenizer->Index] == '-')
|
||||||
|
{
|
||||||
|
// sixten: Parse integer number
|
||||||
|
Token.Type = Token_IntegerValue;
|
||||||
|
|
||||||
|
Token.String.Data = Base + Tokenizer->Index;
|
||||||
|
Token.String.Count = 0;
|
||||||
|
|
||||||
|
while(IsDigit(Token.String.Data[Token.String.Count]) || Token.String.Data[Token.String.Count] == '-')
|
||||||
|
{
|
||||||
|
++Token.String.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// sixten: Parse tokenizer
|
||||||
|
Token.Type = Token_Identifier;
|
||||||
|
|
||||||
|
Token.String.Data = Base + Tokenizer->Index;
|
||||||
|
Token.String.Count = 0;
|
||||||
|
|
||||||
|
while(IsDigit(Token.String.Data[Token.String.Count]) ||
|
||||||
|
IsLetter(Token.String.Data[Token.String.Count]))
|
||||||
|
{
|
||||||
|
++Token.String.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Token.Type = Token_EndOfFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tokenizer->Index += Token.String.Count;
|
||||||
|
|
||||||
|
return(Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline token Tokenizer_PeekNextToken(tokenizer Tokenizer)
|
||||||
|
{
|
||||||
|
// sixten(NOTE): Yup, we just make a copy of the tokenizer and read the next token.
|
||||||
|
token Result = Tokenizer_GetNextToken(&Tokenizer);
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline b32 Tokenizer_RequireToken(tokenizer *Tokenizer, token_type Type)
|
||||||
|
{
|
||||||
|
token Token = Tokenizer_GetNextToken(Tokenizer);
|
||||||
|
|
||||||
|
b32 Result = (Token.Type == Type);
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //VN_TOKENIZER_H
|
|
@ -70,6 +70,21 @@ inline string MakeString16(wchar_t *Data, s64 Count)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct string_node
|
||||||
|
{
|
||||||
|
string String;
|
||||||
|
string_node *Next;
|
||||||
|
string_node *Prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct string_list
|
||||||
|
{
|
||||||
|
string_node *First;
|
||||||
|
string_node *Last;
|
||||||
|
|
||||||
|
s64 TotalCount;
|
||||||
|
};
|
||||||
|
|
||||||
struct v2s
|
struct v2s
|
||||||
{
|
{
|
||||||
s32 x, y;
|
s32 x, y;
|
||||||
|
|
|
@ -1,3 +1,36 @@
|
||||||
|
#include "generated/vn_generated_ui.cpp"
|
||||||
|
|
||||||
|
inline ui_size UI_Pixels(r32 Value, r32 Strictness)
|
||||||
|
{
|
||||||
|
ui_size Result = {UI_SizeType_Pixels, Value, Strictness};
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ui_size UI_Em(r32 Value, r32 Strictness)
|
||||||
|
{
|
||||||
|
ui_size Result = {UI_SizeType_Pixels, Value*UI_TopFontSize(), Strictness};
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ui_size UI_TextContent(r32 Value, r32 Strictness)
|
||||||
|
{
|
||||||
|
ui_size Result = {UI_SizeType_TextContent, Value, Strictness};
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ui_size UI_Percent(r32 Value, r32 Strictness)
|
||||||
|
{
|
||||||
|
ui_size Result = {UI_SizeType_PercentOfParent, Value, Strictness};
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ui_size UI_ChildrenSum(r32 Value, r32 Strictness)
|
||||||
|
{
|
||||||
|
ui_size Result = {UI_SizeType_ChildrenSum, Value, Strictness};
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
per_thread ui *ThreadLocal_UI;
|
per_thread ui *ThreadLocal_UI;
|
||||||
|
|
||||||
inline void UI_SetState(ui *UI)
|
inline void UI_SetState(ui *UI)
|
||||||
|
@ -193,8 +226,6 @@ inline ui_box *UI_GetBoxByKey(ui *UI, ui_key Key)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "generated/vn_generated_ui.cpp"
|
|
||||||
|
|
||||||
inline ui_box *UI_MakeBox(ui_box_flags Flags, string String)
|
inline ui_box *UI_MakeBox(ui_box_flags Flags, string String)
|
||||||
{
|
{
|
||||||
ui *UI = UI_GetState();
|
ui *UI = UI_GetState();
|
||||||
|
@ -231,6 +262,12 @@ inline ui_box *UI_MakeBox(ui_box_flags Flags, string String)
|
||||||
Box->Flags = Flags;
|
Box->Flags = Flags;
|
||||||
Box->String = PushString(&UI->FrameArena, String);
|
Box->String = PushString(&UI->FrameArena, String);
|
||||||
|
|
||||||
|
s64 HashIndex = LastIndexOf(Box->String, '#');
|
||||||
|
if(HashIndex != -1)
|
||||||
|
{
|
||||||
|
Box->String = Prefix(Box->String, HashIndex);
|
||||||
|
}
|
||||||
|
|
||||||
UI_ApplyStyles(Box);
|
UI_ApplyStyles(Box);
|
||||||
|
|
||||||
if(Parent)
|
if(Parent)
|
||||||
|
@ -620,12 +657,16 @@ static void UI_DrawBox(ui_box *Box, render_group *Group, glyph_atlas *GlyphAtlas
|
||||||
Box->DrawCallback(Group, GlyphAtlas, Box, Box->DrawCallbackData);
|
Box->DrawCallback(Group, GlyphAtlas, Box, Box->DrawCallbackData);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // sixten: Render debug rects around boxes.
|
#if VN_INTERNAL
|
||||||
r32 R = (((Box->Key.Value >> 0) & ((1 << 22) - 1)) / (r32)((1 << 22) - 1));
|
if(DEBUG_DebugSettings->RenderUIDebugRects)
|
||||||
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));
|
// sixten: Render debug rects around boxes.
|
||||||
v4 Red = V4(R, G, B, 1);
|
r32 R = (((Box->Key.Value >> 0) & ((1 << 22) - 1)) / (r32)((1 << 22) - 1));
|
||||||
PushQuad(Group, Box->Rect.Min, Box->ComputedDim, Red, Red, Red, Red, 0, 1.8, 1.8);
|
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 = V4(R, G, B, 1);
|
||||||
|
PushQuad(Group, Box->Rect.Min, Box->ComputedDim, Red, Red, Red, Red, 0, 1.8, 1.8);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(Box->Flags & UI_BoxFlag_Clip)
|
if(Box->Flags & UI_BoxFlag_Clip)
|
||||||
|
|
28
code/vn_ui.h
28
code/vn_ui.h
|
@ -46,29 +46,11 @@ struct ui_size
|
||||||
r32 Strictness;
|
r32 Strictness;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline ui_size UI_Pixels(r32 Value, r32 Strictness)
|
inline ui_size UI_Pixels(r32 Value, r32 Strictness);
|
||||||
{
|
inline ui_size UI_Em(r32 Value, r32 Strictness);
|
||||||
ui_size Result = {UI_SizeType_Pixels, Value, Strictness};
|
inline ui_size UI_TextContent(r32 Value, r32 Strictness);
|
||||||
return(Result);
|
inline ui_size UI_Percent(r32 Value, r32 Strictness);
|
||||||
}
|
inline ui_size UI_ChildrenSum(r32 Value, r32 Strictness);
|
||||||
|
|
||||||
inline ui_size UI_TextContent(r32 Value, r32 Strictness)
|
|
||||||
{
|
|
||||||
ui_size Result = {UI_SizeType_TextContent, Value, Strictness};
|
|
||||||
return(Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ui_size UI_Percent(r32 Value, r32 Strictness)
|
|
||||||
{
|
|
||||||
ui_size Result = {UI_SizeType_PercentOfParent, Value, Strictness};
|
|
||||||
return(Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ui_size UI_ChildrenSum(r32 Value, r32 Strictness)
|
|
||||||
{
|
|
||||||
ui_size Result = {UI_SizeType_ChildrenSum, Value, Strictness};
|
|
||||||
return(Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef void ui_draw_callback(render_group *Group, glyph_atlas *Atlas, struct ui_box *Box, void *Data);
|
typedef void ui_draw_callback(render_group *Group, glyph_atlas *Atlas, struct ui_box *Box, void *Data);
|
||||||
|
|
||||||
|
|
|
@ -162,5 +162,36 @@ static ui_signal UI_ButtonF(char *Format, ...)
|
||||||
|
|
||||||
ReleaseScratch(Scratch);
|
ReleaseScratch(Scratch);
|
||||||
|
|
||||||
|
return(Signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ui_signal UI_Checkbox(string String, b32 *Checked)
|
||||||
|
{
|
||||||
|
UI_SetNextSize(UI_ChildrenSum(1, 1), UI_ChildrenSum(1, 1));
|
||||||
|
UI_SetNextLayoutAxis(Axis2_X);
|
||||||
|
|
||||||
|
ui_box *ContainerBox = UI_MakeBox(UI_BoxFlag_Clickable, String);
|
||||||
|
UI_Parent(ContainerBox)
|
||||||
|
{
|
||||||
|
r32 OpacityTransition = AnimationCurve_AnimateValueF(*Checked, *Checked, 0.15, "UI Checkbox Transition %p", Checked);
|
||||||
|
|
||||||
|
v4 TextColor = UI_TopTextColor();
|
||||||
|
TextColor.a = OpacityTransition;
|
||||||
|
|
||||||
|
UI_Size(UI_Em(1, 1), UI_Em(1, 1)) UI_Font(Font_Icons) UI_TextColor(TextColor)
|
||||||
|
UI_MakeBoxF(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawText, "%U", FontIcon_Cancel);
|
||||||
|
|
||||||
|
UI_Size(UI_TextContent(15, 1), UI_Em(1, 1)) UI_Label(String);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_signal Signal = UI_SignalFromBox(ContainerBox);
|
||||||
|
if(Signal.Hovering)
|
||||||
|
{
|
||||||
|
Platform.SetCursor(PlatformCursor_Hand);
|
||||||
|
}
|
||||||
|
if(Signal.Pressed)
|
||||||
|
{
|
||||||
|
*Checked = !*Checked;
|
||||||
|
}
|
||||||
return(Signal);
|
return(Signal);
|
||||||
}
|
}
|
|
@ -150,8 +150,6 @@ static void Workspace_BuildToolbar(workspace *Workspace, r32 dtForFrame)
|
||||||
Workspace_BuildToolbarButton(Workspace, "Panel", ToolbarMenu_Panel);
|
Workspace_BuildToolbarButton(Workspace, "Panel", ToolbarMenu_Panel);
|
||||||
Workspace_BuildToolbarButton(Workspace, "View", ToolbarMenu_View);
|
Workspace_BuildToolbarButton(Workspace, "View", ToolbarMenu_View);
|
||||||
Workspace_BuildToolbarButton(Workspace, "Window", ToolbarMenu_Window);
|
Workspace_BuildToolbarButton(Workspace, "Window", ToolbarMenu_Window);
|
||||||
|
|
||||||
UI_Spacer(UI_Percent(1, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Workspace->Menu != ToolbarMenu_None)
|
if(Workspace->Menu != ToolbarMenu_None)
|
||||||
|
@ -721,9 +719,10 @@ static void Workspace_Init(workspace *Workspace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Workspace_Update(workspace *Workspace, vn_render_commands *RenderCommands, vn_input *Input,
|
static void Workspace_Update(workspace *Workspace, vn_render_commands *RenderCommands,
|
||||||
glyph_atlas *GlyphAtlas)
|
vn_input *Input, glyph_atlas *GlyphAtlas)
|
||||||
{
|
{
|
||||||
|
Workspace->Input = Input;
|
||||||
Workspace->EventList = Input->EventList;
|
Workspace->EventList = Input->EventList;
|
||||||
|
|
||||||
// sixten: Process last frame's commands.
|
// sixten: Process last frame's commands.
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct workspace_drag_payload
|
||||||
|
|
||||||
struct workspace
|
struct workspace
|
||||||
{
|
{
|
||||||
|
vn_input *Input;
|
||||||
platform_event_list *EventList;
|
platform_event_list *EventList;
|
||||||
|
|
||||||
// sixten: Command Allocation
|
// sixten: Command Allocation
|
||||||
|
|
|
@ -225,7 +225,7 @@ static void Workspace_BuildSettingsTabButton(workspace_view_settings *Settings,
|
||||||
{
|
{
|
||||||
b32 IsSelected = (Settings->Category == Category);
|
b32 IsSelected = (Settings->Category == Category);
|
||||||
|
|
||||||
v4 Color = LinearBlend(Theme_TextColor, Theme_HighlightBorderColor, AnimationCurve_AnimateValueF(IsSelected, 0, 0.3, "Workspace Settings %s %p", Name, Settings));
|
v4 Color = LinearBlend(Theme_TextColor, Theme_HighlightBorderColor, AnimationCurve_AnimateValueF(IsSelected, IsSelected, 0.3, "Workspace Settings %s %p", Name, Settings));
|
||||||
|
|
||||||
UI_SetNextFont(Font_Bold);
|
UI_SetNextFont(Font_Bold);
|
||||||
UI_SetNextHeight(UI_TextContent(0, 1));
|
UI_SetNextHeight(UI_TextContent(0, 1));
|
||||||
|
@ -386,10 +386,30 @@ static void Workspace_BuildSettings(workspace *Workspace, workspace_view *View)
|
||||||
char *Alternatives[] = {"60 Hz", "120 Hz", "144 Hz", "Uncapped", "V-Sync"};
|
char *Alternatives[] = {"60 Hz", "120 Hz", "144 Hz", "Uncapped", "V-Sync"};
|
||||||
|
|
||||||
persist b32 DropdownOpen = false;
|
persist b32 DropdownOpen = false;
|
||||||
persist s32 DropdownSelected = 0;
|
|
||||||
|
s32 DropdownSelected;
|
||||||
|
switch(Workspace->Input->RefreshRate)
|
||||||
|
{
|
||||||
|
case 60: { DropdownSelected = 0; } break;
|
||||||
|
case 120:{ DropdownSelected = 1; } break;
|
||||||
|
case 144:{ DropdownSelected = 2; } break;
|
||||||
|
case -1: { DropdownSelected = 3; } break;
|
||||||
|
case 0: { DropdownSelected = 4; } break;
|
||||||
|
default: { DropdownSelected = 0; } break;
|
||||||
|
}
|
||||||
|
|
||||||
if(UI_DropdownSelection(Alternatives, ArrayCount(Alternatives), &DropdownOpen, &DropdownSelected))
|
if(UI_DropdownSelection(Alternatives, ArrayCount(Alternatives), &DropdownOpen, &DropdownSelected))
|
||||||
{
|
{
|
||||||
|
switch(DropdownSelected)
|
||||||
|
{
|
||||||
|
case 0: { Workspace->Input->RefreshRate = 60; } break;
|
||||||
|
case 1: { Workspace->Input->RefreshRate = 120; } break;
|
||||||
|
case 2: { Workspace->Input->RefreshRate = 144; } break;
|
||||||
|
case 3: { Workspace->Input->RefreshRate = -1; } break;
|
||||||
|
case 4: { Workspace->Input->RefreshRate = 0; } break;
|
||||||
|
InvalidDefaultCase;
|
||||||
|
}
|
||||||
|
|
||||||
DropdownOpen = false;
|
DropdownOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,12 +419,9 @@ static void Workspace_BuildSettings(workspace *Workspace, workspace_view *View)
|
||||||
if(!Category || (Category == Workspace_Settings_Developer))
|
if(!Category || (Category == Workspace_Settings_Developer))
|
||||||
{
|
{
|
||||||
UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("Developer");
|
UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("Developer");
|
||||||
UI_LabelF("Render UI Debug Rects:");
|
UI_Checkbox(StrLit("Render UI Debug Rects"), &DEBUG_DebugSettings->RenderUIDebugRects);
|
||||||
UI_LabelF("Render FPS Counter:");
|
UI_Spacer(UI_Pixels(5, 1));
|
||||||
|
UI_Checkbox(StrLit("Render FPS Counter"), &DEBUG_DebugSettings->RenderFPSCounter);
|
||||||
UI_CornerRadius(4)
|
|
||||||
UI_Size(UI_TextContent(20, 1), UI_TextContent(10, 1))
|
|
||||||
UI_ButtonF("Hello Line Paint Color Design Address Brightness");
|
|
||||||
|
|
||||||
UI_Spacer(UI_Pixels(50, 1));
|
UI_Spacer(UI_Pixels(50, 1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,12 @@
|
||||||
#include "win32_main.h"
|
#include "win32_main.h"
|
||||||
#include "win32_opengl.cpp"
|
#include "win32_opengl.cpp"
|
||||||
|
|
||||||
global b32 Global_Running;
|
|
||||||
global win32_state Global_Win32State;
|
global win32_state Global_Win32State;
|
||||||
global WINDOWPLACEMENT Global_WindowPosition = {sizeof(Global_WindowPosition)};;
|
global WINDOWPLACEMENT Global_WindowPosition = {sizeof(Global_WindowPosition)};;
|
||||||
|
|
||||||
static void Win32_PlatformError(char *Message, bool IsFatal)
|
static void Win32_PlatformError(char *Message, bool IsFatal)
|
||||||
{
|
{
|
||||||
MessageBoxA(0, Message, "nv - Platform Error", MB_OK|(IsFatal?MB_ICONSTOP:MB_ICONEXCLAMATION));
|
MessageBoxA(0, Message, "vn - Platform Error", MB_OK|(IsFatal?MB_ICONSTOP:MB_ICONEXCLAMATION));
|
||||||
|
|
||||||
if(IsFatal)
|
if(IsFatal)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +21,30 @@ static void Win32_PlatformError(char *Message, bool IsFatal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLATFORM_SHOW_MESSAGE(Win32_ShowMessage)
|
||||||
|
{
|
||||||
|
DWORD Flags = MB_OK;
|
||||||
|
switch(Type)
|
||||||
|
{
|
||||||
|
case Platform_Message_Info: { Flags |= MB_ICONINFORMATION; } break;
|
||||||
|
case Platform_Message_Warning: { Flags |= MB_ICONWARNING; } break;
|
||||||
|
case Platform_Message_Error: { Flags |= MB_ICONEXCLAMATION; } break;
|
||||||
|
case Platform_Message_Fatal: { Flags |= MB_ICONSTOP; } break;
|
||||||
|
|
||||||
|
InvalidDefaultCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sixten(NOTE): Check for null-termination.
|
||||||
|
Assert(Message.Data[Message.Count] == 0);
|
||||||
|
|
||||||
|
MessageBoxA(0, (char *)Message.Data, "vn - A message from the developer", Flags);
|
||||||
|
|
||||||
|
if(Type == Platform_Message_Fatal)
|
||||||
|
{
|
||||||
|
ExitProcess((UINT)-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static PLATFORM_ALLOCATE_MEMORY(Win32_AllocateMemory)
|
static PLATFORM_ALLOCATE_MEMORY(Win32_AllocateMemory)
|
||||||
{
|
{
|
||||||
win32_state *State = &Global_Win32State;
|
win32_state *State = &Global_Win32State;
|
||||||
|
@ -83,6 +106,10 @@ static PLATFORM_OPEN_FILE(Win32_OpenFile)
|
||||||
{
|
{
|
||||||
CreationAttributes = OPEN_EXISTING;
|
CreationAttributes = OPEN_EXISTING;
|
||||||
}
|
}
|
||||||
|
if(FileAccess & PlatformAccess_Write)
|
||||||
|
{
|
||||||
|
CreationAttributes = CREATE_ALWAYS;
|
||||||
|
}
|
||||||
|
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temporary_memory Scratch = GetScratch(0, 0);
|
||||||
|
|
||||||
|
@ -119,6 +146,18 @@ static PLATFORM_READ_FILE(Win32_ReadFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLATFORM_WRITE_FILE(Win32_WriteFile)
|
||||||
|
{
|
||||||
|
HANDLE File = (HANDLE)Handle.Platform;
|
||||||
|
if(File != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
DWORD BytesWritten;
|
||||||
|
WriteFile(File, Source, Size, &BytesWritten, 0);
|
||||||
|
|
||||||
|
Assert(BytesWritten == Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static PLATFORM_GET_FILE_SIZE(Win32_GetFileSize)
|
static PLATFORM_GET_FILE_SIZE(Win32_GetFileSize)
|
||||||
{
|
{
|
||||||
u64 Result = 0;
|
u64 Result = 0;
|
||||||
|
@ -307,7 +346,8 @@ static LRESULT Win32_WindowCallback(HWND Window, UINT Message, WPARAM WParam, LP
|
||||||
{
|
{
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
{
|
{
|
||||||
Global_Running = false;
|
Event = PushStruct(&State->EventArena, platform_event);
|
||||||
|
Event->Type = PlatformEvent_WindowClose;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_WINDOWPOSCHANGED:
|
case WM_WINDOWPOSCHANGED:
|
||||||
|
@ -604,7 +644,7 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
|
||||||
State->MemorySentinel.Next = &State->MemorySentinel;
|
State->MemorySentinel.Next = &State->MemorySentinel;
|
||||||
State->MemorySentinel.Prev = &State->MemorySentinel;
|
State->MemorySentinel.Prev = &State->MemorySentinel;
|
||||||
|
|
||||||
State->SleepIsGranular = (timeBeginPeriod(1) != TIMERR_NOERROR);
|
State->SleepIsGranular = (timeBeginPeriod(1) == TIMERR_NOERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sixten: Setup platform layer
|
// sixten: Setup platform layer
|
||||||
|
@ -614,9 +654,11 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
|
||||||
Platform.OpenFile = Win32_OpenFile;
|
Platform.OpenFile = Win32_OpenFile;
|
||||||
Platform.CloseFile = Win32_CloseFile;
|
Platform.CloseFile = Win32_CloseFile;
|
||||||
Platform.ReadFile = Win32_ReadFile;
|
Platform.ReadFile = Win32_ReadFile;
|
||||||
|
Platform.WriteFile = Win32_WriteFile;
|
||||||
Platform.GetFileSize = Win32_GetFileSize;
|
Platform.GetFileSize = Win32_GetFileSize;
|
||||||
Platform.SetCursor = Win32_SetCursor;
|
Platform.SetCursor = Win32_SetCursor;
|
||||||
Platform.ToggleFullscreen = Win32_ToggleFullscreen;
|
Platform.ToggleFullscreen = Win32_ToggleFullscreen;
|
||||||
|
Platform.ShowMessage = Win32_ShowMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
WNDCLASS WindowClass = {};
|
WNDCLASS WindowClass = {};
|
||||||
|
@ -639,9 +681,9 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
|
||||||
Global_Win32State.Window = Window;
|
Global_Win32State.Window = Window;
|
||||||
|
|
||||||
vn_input Input = {};
|
vn_input Input = {};
|
||||||
|
vn_render_commands RenderCommands = {};
|
||||||
|
|
||||||
// sixten: Setup OpenGL
|
// sixten: Setup OpenGL
|
||||||
vn_render_commands RenderCommands = {};
|
|
||||||
HDC DeviceContext = GetDC(Window);
|
HDC DeviceContext = GetDC(Window);
|
||||||
Win32_CreateOpenGLContext(DeviceContext);
|
Win32_CreateOpenGLContext(DeviceContext);
|
||||||
opengl_context OpenGLContext = OpenGL_SetupContext(&RenderCommands, 16*1024);
|
opengl_context OpenGLContext = OpenGL_SetupContext(&RenderCommands, 16*1024);
|
||||||
|
@ -655,8 +697,7 @@ int WinMain(HINSTANCE Instance, HINSTANCE PreviousInstance, LPSTR CommandLine, i
|
||||||
|
|
||||||
u64 CurrentTime = Win32_GetWallClock();
|
u64 CurrentTime = Win32_GetWallClock();
|
||||||
|
|
||||||
Global_Running = true;
|
while(!Input.ExitRequested)
|
||||||
while(Global_Running)
|
|
||||||
{
|
{
|
||||||
u64 NewTime = Win32_GetWallClock();
|
u64 NewTime = Win32_GetWallClock();
|
||||||
r64 dtForFrame = Win32_GetSecondsElapsed(CurrentTime, NewTime);
|
r64 dtForFrame = Win32_GetSecondsElapsed(CurrentTime, NewTime);
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
Platform
|
||||||
|
{
|
||||||
|
RefreshRate = 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dev
|
||||||
|
{
|
||||||
|
RenderUIDebugRects = false;
|
||||||
|
RenderFPSCounter = false;
|
||||||
|
}
|
Loading…
Reference in New Issue