Completed Nav Editor.
|
@ -1,45 +0,0 @@
|
||||||
UI_Column()
|
|
||||||
{
|
|
||||||
UI_Spacer(UI_Em(1, 1));
|
|
||||||
UI_Height(UI_Em(1, 1)) UI_Row()
|
|
||||||
{
|
|
||||||
UI_Width(UI_TextContent(15, 1)) UI_LabelF("Scrollbar T:");
|
|
||||||
|
|
||||||
UI_SetNextWidth(UI_Em(20, 1));
|
|
||||||
UI_SetNextCornerRadius(UI_TopFontSize()*0.5f);
|
|
||||||
ui_box *Container = UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, "Scrollable");
|
|
||||||
UI_Parent(Container)
|
|
||||||
{
|
|
||||||
UI_SetNextCornerRadius(UI_TopFontSize()*0.5f);
|
|
||||||
UI_SetNextSize(UI_Em(1, 1), UI_Em(1, 1));
|
|
||||||
UI_SetNextFixedX((DimOfRange(Container->Rect).x-UI_TopFontSize())*ScrollbarT);
|
|
||||||
ui_box *Box = UI_MakeBoxF(UI_BoxFlag_DrawBackground|
|
|
||||||
UI_BoxFlag_DrawBorder|
|
|
||||||
UI_BoxFlag_HotAnimation|
|
|
||||||
UI_BoxFlag_ActiveAnimation|
|
|
||||||
UI_BoxFlag_Clickable|
|
|
||||||
UI_BoxFlag_FloatingX|
|
|
||||||
0, "Dragable");
|
|
||||||
ui_signal Signal = UI_SignalFromBox(Box);
|
|
||||||
if(Signal.Dragging)
|
|
||||||
{
|
|
||||||
if(Signal.Pressed)
|
|
||||||
{
|
|
||||||
UI_StoreDragR32(ScrollbarT);
|
|
||||||
}
|
|
||||||
|
|
||||||
r32 StartT = UI_GetDragR32();
|
|
||||||
r32 EndT = StartT + Signal.DragDelta.x/(DimOfRange(Container->Rect).x-UI_TopFontSize());
|
|
||||||
ScrollbarT = Clamp01(EndT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UI_Width(UI_TextContent(30, 1)) UI_Height(UI_Em(2, 1))
|
|
||||||
{
|
|
||||||
if(UI_ButtonF("Reset Dialog").Pressed)
|
|
||||||
{
|
|
||||||
Time = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -162,8 +162,7 @@ IsNull(p) ? (SetNull((n)->prev), (n)->next = (f), (IsNull(f) ? (0) : ((f)->prev
|
||||||
#define DLLIsEmpty(First) ((First) == 0)
|
#define DLLIsEmpty(First) ((First) == 0)
|
||||||
|
|
||||||
#define SenDLLInit(Sentinel)\
|
#define SenDLLInit(Sentinel)\
|
||||||
(Sentinel)->Next = (Sentinel);\
|
do { (Sentinel)->Next = (Sentinel); (Sentinel)->Prev = (Sentinel); } while(0)
|
||||||
(Sentinel)->Prev = (Sentinel);
|
|
||||||
|
|
||||||
#define SenDLLInsertFirst(Sentinel, Element)\
|
#define SenDLLInsertFirst(Sentinel, Element)\
|
||||||
(Element)->Next = (Sentinel)->Next;\
|
(Element)->Next = (Sentinel)->Next;\
|
||||||
|
|
|
@ -111,7 +111,7 @@ static void *ArenaPushNoClear(arena *Arena, u64 Size)
|
||||||
if(Size <= Arena->Size)
|
if(Size <= Arena->Size)
|
||||||
{
|
{
|
||||||
arena *Target = Arena->Prev; // sixten: We always append to the end of the list.
|
arena *Target = Arena->Prev; // sixten: We always append to the end of the list.
|
||||||
if(Target->Position + Size > Target->Size)
|
if(Target->Position + Size + Arena->Align > Target->Size)
|
||||||
{
|
{
|
||||||
arena *New = ArenaAlloc(Arena->Size, true);
|
arena *New = ArenaAlloc(Arena->Size, true);
|
||||||
New->NotFirst = true;
|
New->NotFirst = true;
|
||||||
|
@ -235,15 +235,15 @@ static void ArenaSetAlign(arena *Arena, u64 Align)
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//- sixten: Temporary Memory Functions
|
//- sixten: Temporary Memory Functions
|
||||||
|
|
||||||
static temporary_memory BeginTemporaryMemory(arena *Arena)
|
static temp BeginTemp(arena *Arena)
|
||||||
{
|
{
|
||||||
temporary_memory Temp;
|
temp Temp;
|
||||||
Temp.Arena = Arena;
|
Temp.Arena = Arena;
|
||||||
Temp.Position = Arena->Position;
|
Temp.Position = Arena->Position;
|
||||||
return(Temp);
|
return(Temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EndTemporaryMemory(temporary_memory Temp)
|
static void EndTemp(temp Temp)
|
||||||
{
|
{
|
||||||
ArenaPopTo(Temp.Arena, Temp.Position);
|
ArenaPopTo(Temp.Arena, Temp.Position);
|
||||||
}
|
}
|
|
@ -42,10 +42,9 @@ struct arena
|
||||||
b32 NotFirst;
|
b32 NotFirst;
|
||||||
arena *Next;
|
arena *Next;
|
||||||
arena *Prev;
|
arena *Prev;
|
||||||
u64 Unused[1];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct temporary_memory
|
struct temp
|
||||||
{
|
{
|
||||||
arena *Arena;
|
arena *Arena;
|
||||||
u64 Position;
|
u64 Position;
|
||||||
|
@ -75,7 +74,7 @@ static void ArenaSetAlign(arena *Arena, u64 Align);
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//- sixten: Temporary Memory Functions
|
//- sixten: Temporary Memory Functions
|
||||||
|
|
||||||
static temporary_memory BeginTemporaryMemory(arena *Arena);
|
static temp BeginTemp(arena *Arena);
|
||||||
static void EndTemporaryMemory(temporary_memory Temp);
|
static void EndTemp(temp Temp);
|
||||||
|
|
||||||
#endif //CORE_MEMORY_H
|
#endif //CORE_MEMORY_H
|
||||||
|
|
|
@ -308,7 +308,7 @@ static string StringFromCodepoint(arena *Arena, u32 Codepoint)
|
||||||
|
|
||||||
static r64 DoubleFromString(string String)
|
static r64 DoubleFromString(string String)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
string NullTerminated = PushString(Scratch.Arena, String);
|
string NullTerminated = PushString(Scratch.Arena, String);
|
||||||
r64 Result = strtod((char *)NullTerminated.Data, 0);
|
r64 Result = strtod((char *)NullTerminated.Data, 0);
|
||||||
ReleaseScratch(Scratch);
|
ReleaseScratch(Scratch);
|
||||||
|
|
|
@ -20,9 +20,9 @@ static thread_context *GetThreadContext(void)
|
||||||
return(ThreadLocal_ThreadContext);
|
return(ThreadLocal_ThreadContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
static temporary_memory GetScratch(arena **Conflicts, u64 ConflictCount)
|
static temp GetScratch(arena **Conflicts, u64 ConflictCount)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = {};
|
temp Scratch = {};
|
||||||
thread_context *Context = GetThreadContext();
|
thread_context *Context = GetThreadContext();
|
||||||
|
|
||||||
for(u64 ArenaIndex = 0;
|
for(u64 ArenaIndex = 0;
|
||||||
|
@ -44,7 +44,7 @@ static temporary_memory GetScratch(arena **Conflicts, u64 ConflictCount)
|
||||||
|
|
||||||
if(!FoundConflict)
|
if(!FoundConflict)
|
||||||
{
|
{
|
||||||
Scratch = BeginTemporaryMemory(Context->Arenas[ArenaIndex]);
|
Scratch = BeginTemp(Context->Arenas[ArenaIndex]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ static void SetThreadContext(thread_context *Context);
|
||||||
static thread_context *GetThreadContext(void);
|
static thread_context *GetThreadContext(void);
|
||||||
|
|
||||||
//- sixten: Scratch
|
//- sixten: Scratch
|
||||||
static temporary_memory GetScratch(arena **Conflicts = 0, u64 ConflictCount = 0);
|
static temp GetScratch(arena **Conflicts = 0, u64 ConflictCount = 0);
|
||||||
#define ReleaseScratch(Scratch) EndTemporaryMemory(Scratch)
|
#define ReleaseScratch(Scratch) EndTemp(Scratch)
|
||||||
|
|
||||||
#endif //CORE_THREAD_CONTEXT_H
|
#endif //CORE_THREAD_CONTEXT_H
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
char * AssetPathLUT[5] =
|
char * AssetPathLUT[7] =
|
||||||
{
|
{
|
||||||
"",
|
"",
|
||||||
|
"backgrounds/unknown.png",
|
||||||
"backgrounds/test.jpg",
|
"backgrounds/test.jpg",
|
||||||
|
"backgrounds/ddlc.png",
|
||||||
"characters/test_normal.png",
|
"characters/test_normal.png",
|
||||||
"characters/test_happy.png",
|
"characters/test_happy.png",
|
||||||
"characters/monika_leaning.png",
|
"characters/monika_leaning.png",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool AssetIsPermanentLUT[5] =
|
bool AssetIsPermanentLUT[7] =
|
||||||
{
|
{
|
||||||
|
true,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
@ -16,10 +20,12 @@ false,
|
||||||
false,
|
false,
|
||||||
};
|
};
|
||||||
|
|
||||||
char * AssetNameLUT[5] =
|
char * AssetNameLUT[7] =
|
||||||
{
|
{
|
||||||
"None",
|
"None",
|
||||||
|
"Error",
|
||||||
"DemoBackground",
|
"DemoBackground",
|
||||||
|
"DDLCBackground",
|
||||||
"ArthurNormal",
|
"ArthurNormal",
|
||||||
"ArthurHappy",
|
"ArthurHappy",
|
||||||
"MonikaLeaning",
|
"MonikaLeaning",
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
enum asset_id
|
extern char * AssetPathLUT[7];
|
||||||
|
|
||||||
|
extern bool AssetIsPermanentLUT[7];
|
||||||
|
|
||||||
|
extern char * AssetNameLUT[7];
|
||||||
|
|
||||||
|
typedef s32 asset_id;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
AssetID_None,
|
AssetID_None,
|
||||||
|
AssetID_Error,
|
||||||
AssetID_DemoBackground,
|
AssetID_DemoBackground,
|
||||||
|
AssetID_DDLCBackground,
|
||||||
AssetID_ArthurNormal,
|
AssetID_ArthurNormal,
|
||||||
AssetID_ArthurHappy,
|
AssetID_ArthurHappy,
|
||||||
AssetID_MonikaLeaning,
|
AssetID_MonikaLeaning,
|
||||||
AssetID_COUNT,
|
AssetID_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern char * AssetPathLUT[5];
|
|
||||||
|
|
||||||
extern bool AssetIsPermanentLUT[5];
|
|
||||||
|
|
||||||
extern char * AssetNameLUT[5];
|
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ static void OpenGL_DebugMessageCallback(GLenum Source, GLenum Type, GLuint ID, G
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline render_handle OpenGL_GetHandleFromTexture(opengl_texture Texture)
|
inline render_handle OpenGL_HandleFromTexture(opengl_texture Texture)
|
||||||
{
|
{
|
||||||
render_handle Result = {};
|
render_handle Result = {};
|
||||||
Result.U32[0] = Texture.ID;
|
Result.U32[0] = Texture.ID;
|
||||||
|
@ -23,7 +23,7 @@ inline render_handle OpenGL_GetHandleFromTexture(opengl_texture Texture)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline opengl_texture OpenGL_GetTextureFromHandle(render_handle Handle)
|
inline opengl_texture OpenGL_TextureFromHandle(render_handle Handle)
|
||||||
{
|
{
|
||||||
opengl_texture Result = {};
|
opengl_texture Result = {};
|
||||||
Result.ID = Handle.U32[0];
|
Result.ID = Handle.U32[0];
|
||||||
|
@ -33,7 +33,7 @@ inline opengl_texture OpenGL_GetTextureFromHandle(render_handle Handle)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u32 OpenGL_GetInternalFormatFromTextureFormat(render_texture_format Format)
|
inline u32 OpenGL_InternalFormatFromTextureFormat(render_texture_format Format)
|
||||||
{
|
{
|
||||||
u32 InternalFormat = GL_INVALID_ENUM;
|
u32 InternalFormat = GL_INVALID_ENUM;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ global GLint Global_OpenGL_SwizzleMaskR8[4] = {GL_ONE, GL_ONE, GL_ONE, GL_RED};
|
||||||
global GLint Global_OpenGL_SwizzleMaskRGB8[4] = {GL_RED, GL_GREEN, GL_BLUE, GL_ONE};
|
global GLint Global_OpenGL_SwizzleMaskRGB8[4] = {GL_RED, GL_GREEN, GL_BLUE, GL_ONE};
|
||||||
global GLint Global_OpenGL_SwizzleMaskRGBA8[4] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
global GLint Global_OpenGL_SwizzleMaskRGBA8[4] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||||
|
|
||||||
inline GLint *OpenGL_GetSwizzleFromTextureFormat(render_texture_format Format)
|
inline GLint *OpenGL_SwizzleFromTextureFormat(render_texture_format Format)
|
||||||
{
|
{
|
||||||
GLint *Swizzle = 0;
|
GLint *Swizzle = 0;
|
||||||
if(Format == Render_TextureFormat_R8)
|
if(Format == Render_TextureFormat_R8)
|
||||||
|
@ -93,8 +93,8 @@ static RENDER_ALLOCATE_TEXTURE(OpenGL_AllocateTexture)
|
||||||
glGenTextures(1, &Texture.ID);
|
glGenTextures(1, &Texture.ID);
|
||||||
Assert(Texture.ID);
|
Assert(Texture.ID);
|
||||||
|
|
||||||
u32 InternalFormat = OpenGL_GetInternalFormatFromTextureFormat(Format);
|
u32 InternalFormat = OpenGL_InternalFormatFromTextureFormat(Format);
|
||||||
GLint *SwizzleMask = OpenGL_GetSwizzleFromTextureFormat(Format);
|
GLint *SwizzleMask = OpenGL_SwizzleFromTextureFormat(Format);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, Texture.ID);
|
glBindTexture(GL_TEXTURE_2D, Texture.ID);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Dim.x, Dim.y, 0, InternalFormat, GL_UNSIGNED_BYTE, Data);
|
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Dim.x, Dim.y, 0, InternalFormat, GL_UNSIGNED_BYTE, Data);
|
||||||
|
@ -115,18 +115,24 @@ static RENDER_ALLOCATE_TEXTURE(OpenGL_AllocateTexture)
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_handle Handle = OpenGL_GetHandleFromTexture(Texture);
|
render_handle Handle = OpenGL_HandleFromTexture(Texture);
|
||||||
return(Handle);
|
return(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RENDER_DEALLOCATE_TEXTURE(OpenGL_DeallocateTexture)
|
||||||
|
{
|
||||||
|
opengl_texture Texture = OpenGL_TextureFromHandle(Handle);
|
||||||
|
glDeleteTextures(1, &Texture.ID);
|
||||||
|
}
|
||||||
|
|
||||||
static RENDER_FILL_REGION(OpenGL_FillRegion)
|
static RENDER_FILL_REGION(OpenGL_FillRegion)
|
||||||
{
|
{
|
||||||
opengl_texture Texture = OpenGL_GetTextureFromHandle(Handle);
|
opengl_texture Texture = OpenGL_TextureFromHandle(Handle);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, Texture.ID);
|
glBindTexture(GL_TEXTURE_2D, Texture.ID);
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||||
DestP.x, DestP.y, DestDim.x, DestDim.y,
|
DestP.x, DestP.y, DestDim.x, DestDim.y,
|
||||||
OpenGL_GetInternalFormatFromTextureFormat(Texture.Format),
|
OpenGL_InternalFormatFromTextureFormat(Texture.Format),
|
||||||
GL_UNSIGNED_BYTE, Data);
|
GL_UNSIGNED_BYTE, Data);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
@ -350,7 +356,7 @@ Out_Color = Color*TextureFactor*BorderFactor*SDFFactor;
|
||||||
glUseProgram(Program.ID);
|
glUseProgram(Program.ID);
|
||||||
Program.UniformResolutionLocation = glGetUniformLocation(Program.ID, "Uniform_Resolution");
|
Program.UniformResolutionLocation = glGetUniformLocation(Program.ID, "Uniform_Resolution");
|
||||||
|
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
for(s32 TextureIndex = 0;
|
for(s32 TextureIndex = 0;
|
||||||
TextureIndex < MAX_BOUND_TEXTURES;
|
TextureIndex < MAX_BOUND_TEXTURES;
|
||||||
++TextureIndex)
|
++TextureIndex)
|
||||||
|
@ -492,7 +498,7 @@ Out_Color = Color*SDFFactor*BorderFactor*TextureFactor;
|
||||||
glUseProgram(Program.ID);
|
glUseProgram(Program.ID);
|
||||||
Program.UniformResolutionLocation = glGetUniformLocation(Program.ID, "Uniform_Resolution");
|
Program.UniformResolutionLocation = glGetUniformLocation(Program.ID, "Uniform_Resolution");
|
||||||
|
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
for(s32 TextureIndex = 0;
|
for(s32 TextureIndex = 0;
|
||||||
TextureIndex < MAX_BOUND_TEXTURES;
|
TextureIndex < MAX_BOUND_TEXTURES;
|
||||||
++TextureIndex)
|
++TextureIndex)
|
||||||
|
@ -647,6 +653,7 @@ static opengl_context OpenGL_SetupContext(vn_render_commands *RenderCommands, um
|
||||||
RenderCommands->WhiteTexture = OpenGL_AllocateTexture(V2S32(1, 1), Render_TextureFormat_RGBA8, false, &WhiteData);
|
RenderCommands->WhiteTexture = OpenGL_AllocateTexture(V2S32(1, 1), Render_TextureFormat_RGBA8, false, &WhiteData);
|
||||||
|
|
||||||
RenderCommands->AllocateTexture = OpenGL_AllocateTexture;
|
RenderCommands->AllocateTexture = OpenGL_AllocateTexture;
|
||||||
|
RenderCommands->DeallocateTexture = OpenGL_DeallocateTexture;
|
||||||
RenderCommands->FillRegion = OpenGL_FillRegion;
|
RenderCommands->FillRegion = OpenGL_FillRegion;
|
||||||
|
|
||||||
#if VN_SLOW&&0
|
#if VN_SLOW&&0
|
||||||
|
@ -727,7 +734,7 @@ static void OpenGL_EndFrame(opengl_context *Context, vn_render_commands *RenderC
|
||||||
TextureIndex < Mapping->TexturesUsed;
|
TextureIndex < Mapping->TexturesUsed;
|
||||||
++TextureIndex)
|
++TextureIndex)
|
||||||
{
|
{
|
||||||
opengl_texture Texture = OpenGL_GetTextureFromHandle(Mapping->Textures[TextureIndex]);
|
opengl_texture Texture = OpenGL_TextureFromHandle(Mapping->Textures[TextureIndex]);
|
||||||
glActiveTexture(GL_TEXTURE0 + TextureIndex);
|
glActiveTexture(GL_TEXTURE0 + TextureIndex);
|
||||||
glBindTexture(GL_TEXTURE_2D, Texture.ID);
|
glBindTexture(GL_TEXTURE_2D, Texture.ID);
|
||||||
}
|
}
|
||||||
|
@ -783,7 +790,7 @@ static void OpenGL_EndFrame(opengl_context *Context, vn_render_commands *RenderC
|
||||||
TextureIndex < Mapping->TexturesUsed;
|
TextureIndex < Mapping->TexturesUsed;
|
||||||
++TextureIndex)
|
++TextureIndex)
|
||||||
{
|
{
|
||||||
opengl_texture Texture = OpenGL_GetTextureFromHandle(Mapping->Textures[TextureIndex]);
|
opengl_texture Texture = OpenGL_TextureFromHandle(Mapping->Textures[TextureIndex]);
|
||||||
glActiveTexture(GL_TEXTURE0 + TextureIndex);
|
glActiveTexture(GL_TEXTURE0 + TextureIndex);
|
||||||
glBindTexture(GL_TEXTURE_2D, Texture.ID);
|
glBindTexture(GL_TEXTURE_2D, Texture.ID);
|
||||||
}
|
}
|
||||||
|
|
59
code/vn.cpp
|
@ -32,6 +32,9 @@ global debug_settings *DEBUG_DebugSettings = 0;
|
||||||
|
|
||||||
#if VN_INTERNAL
|
#if VN_INTERNAL
|
||||||
#include "vn_workspace.h"
|
#include "vn_workspace.h"
|
||||||
|
#include "vn_debug_info.h"
|
||||||
|
|
||||||
|
global vn_render_commands *GlobalRenderCommands = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "generated/vn_character.meta.c"
|
#include "generated/vn_character.meta.c"
|
||||||
|
@ -49,6 +52,7 @@ global debug_settings *DEBUG_DebugSettings = 0;
|
||||||
|
|
||||||
#if VN_INTERNAL
|
#if VN_INTERNAL
|
||||||
#include "vn_workspace.cpp"
|
#include "vn_workspace.cpp"
|
||||||
|
#include "vn_debug_info.cpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct vn_state
|
struct vn_state
|
||||||
|
@ -71,50 +75,21 @@ struct vn_state
|
||||||
scene_view SceneView;
|
scene_view SceneView;
|
||||||
|
|
||||||
#if VN_INTERNAL
|
#if VN_INTERNAL
|
||||||
|
debug_info *DebugInfo;
|
||||||
workspace Workspace;
|
workspace Workspace;
|
||||||
debug_settings DebugSettings;
|
debug_settings DebugSettings;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static render_handle CreateTextureFromPath(vn_render_commands *Commands, string Path)
|
|
||||||
{
|
|
||||||
render_handle Result = {};
|
|
||||||
|
|
||||||
temporary_memory Scratch = GetScratch();
|
|
||||||
platform_file_handle File = Platform.OpenFile(Path, PlatformAccess_Read);
|
|
||||||
if(File.IsValid)
|
|
||||||
{
|
|
||||||
u64 DataCount = Platform.GetFileSize(File);
|
|
||||||
u8 *Data = PushArray(Scratch.Arena, u8, DataCount);
|
|
||||||
Platform.ReadFile(File, Data, 0, DataCount);
|
|
||||||
|
|
||||||
s32 Width, Height, BPP;
|
|
||||||
u8 *TextureData = stbi_load_from_memory(Data, DataCount, &Width, &Height, &BPP, 0);
|
|
||||||
|
|
||||||
render_texture_format TextureFormat = Render_TextureFormat_Invalid;
|
|
||||||
switch(BPP)
|
|
||||||
{
|
|
||||||
InvalidDefaultCase;
|
|
||||||
case 1: { TextureFormat = Render_TextureFormat_R8; } break;
|
|
||||||
case 3: { TextureFormat = Render_TextureFormat_RGB8; } break;
|
|
||||||
case 4: { TextureFormat = Render_TextureFormat_RGBA8; } break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result = Commands->AllocateTexture(V2S32(Width, Height), TextureFormat, true, TextureData);
|
|
||||||
|
|
||||||
stbi_image_free(TextureData);
|
|
||||||
|
|
||||||
Platform.CloseFile(File);
|
|
||||||
}
|
|
||||||
ReleaseScratch(Scratch);
|
|
||||||
return(Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
||||||
{
|
{
|
||||||
SetThreadContext(ThreadContext);
|
SetThreadContext(ThreadContext);
|
||||||
Platform = Memory->PlatformAPI;
|
Platform = Memory->PlatformAPI;
|
||||||
|
|
||||||
|
#if VN_INTERNAL
|
||||||
|
GlobalRenderCommands = RenderCommands;
|
||||||
|
#endif
|
||||||
|
|
||||||
vn_state *State = Memory->State;
|
vn_state *State = Memory->State;
|
||||||
|
|
||||||
//- sixten: initialize application state
|
//- sixten: initialize application state
|
||||||
|
@ -138,6 +113,8 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
||||||
{
|
{
|
||||||
Config_BindS32(State->Config, StrLit("Platform/RefreshRate"), &Input->RefreshRate, 60);
|
Config_BindS32(State->Config, StrLit("Platform/RefreshRate"), &Input->RefreshRate, 60);
|
||||||
#if VN_INTERNAL
|
#if VN_INTERNAL
|
||||||
|
State->DebugInfo = DI_DebugInfoAlloc();
|
||||||
|
|
||||||
DEBUG_DebugSettings = &State->DebugSettings;
|
DEBUG_DebugSettings = &State->DebugSettings;
|
||||||
Config_BindB32(State->Config, StrLit("Dev/RenderUIDebugRects"), &DEBUG_DebugSettings->RenderUIDebugRects, 0);
|
Config_BindB32(State->Config, StrLit("Dev/RenderUIDebugRects"), &DEBUG_DebugSettings->RenderUIDebugRects, 0);
|
||||||
Config_BindB32(State->Config, StrLit("Dev/RenderFPSCounter"), &DEBUG_DebugSettings->RenderFPSCounter, 0);
|
Config_BindB32(State->Config, StrLit("Dev/RenderFPSCounter"), &DEBUG_DebugSettings->RenderFPSCounter, 0);
|
||||||
|
@ -152,7 +129,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
||||||
SV_Init(SceneView, State->Arena);
|
SV_Init(SceneView, State->Arena);
|
||||||
|
|
||||||
//- sixten: load startup scene
|
//- sixten: load startup scene
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, StrLit("data/scene.vns"));
|
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, StrLit("data/scene.vns"));
|
||||||
compiled_scene Scene = S_ScriptFromText(Scratch.Arena, SceneInput);
|
compiled_scene Scene = S_ScriptFromText(Scratch.Arena, SceneInput);
|
||||||
SV_SetCurrentSource(&Scene);
|
SV_SetCurrentSource(&Scene);
|
||||||
|
@ -174,6 +151,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if VN_INTERNAL
|
#if VN_INTERNAL
|
||||||
|
DI_BeginFrame(State->DebugInfo);
|
||||||
DEBUG_DebugSettings = &State->DebugSettings;
|
DEBUG_DebugSettings = &State->DebugSettings;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -190,10 +168,14 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
||||||
State->EditorMode = !State->EditorMode;
|
State->EditorMode = !State->EditorMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- sixten: update the scene
|
||||||
|
SV_Update(State->FrameArena);
|
||||||
|
|
||||||
//- sixten: build the ui
|
//- sixten: build the ui
|
||||||
UI_BeginBuild(RenderCommands->RenderDim);
|
UI_BeginBuild(RenderCommands->RenderDim);
|
||||||
{
|
{
|
||||||
#if VN_INTERNAL
|
#if VN_INTERNAL
|
||||||
|
DI_BuildInfo();
|
||||||
if(State->EditorMode)
|
if(State->EditorMode)
|
||||||
{
|
{
|
||||||
W_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas);
|
W_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas);
|
||||||
|
@ -209,9 +191,6 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
||||||
UI_EndBuild();
|
UI_EndBuild();
|
||||||
|
|
||||||
|
|
||||||
//- sixten: update the scene
|
|
||||||
SV_Update(State->FrameArena);
|
|
||||||
|
|
||||||
//- sixten: consume all remaining evetns
|
//- sixten: consume all remaining evetns
|
||||||
for(platform_event *Event = Input->EventList->First;
|
for(platform_event *Event = Input->EventList->First;
|
||||||
Event != 0;
|
Event != 0;
|
||||||
|
@ -243,5 +222,9 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if VN_INTERNAL
|
||||||
|
DI_EndFrame();
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -110,7 +110,7 @@ inline r32 AC_AnimateValue(r32 Target, r32 Initial, r32 Duration, string Name)
|
||||||
|
|
||||||
inline r32 AC_AnimateValueF(r32 Target, r32 Initial, r32 Duration, char *Format, ...)
|
inline r32 AC_AnimateValueF(r32 Target, r32 Initial, r32 Duration, char *Format, ...)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
|
|
||||||
va_list Arguments;
|
va_list Arguments;
|
||||||
va_start(Arguments, Format);
|
va_start(Arguments, Format);
|
||||||
|
|
|
@ -19,7 +19,7 @@ static void LoadAsset(asset_id ID)
|
||||||
|
|
||||||
if(!Asset->IsLoaded)
|
if(!Asset->IsLoaded)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
|
|
||||||
string Filepath = PushFormat(Scratch.Arena, "data/%s", AssetPathLUT[ID]);
|
string Filepath = PushFormat(Scratch.Arena, "data/%s", AssetPathLUT[ID]);
|
||||||
platform_file_handle File = Platform.OpenFile(Filepath, PlatformAccess_Read);
|
platform_file_handle File = Platform.OpenFile(Filepath, PlatformAccess_Read);
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
@table(Name, Path, IsPermanent) assets_desc:
|
@table(Name, Path, IsPermanent) assets_desc:
|
||||||
{
|
{
|
||||||
{ None, "", false }
|
{ None, "", true }
|
||||||
|
{ Error, "backgrounds/unknown.png", true }
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ sixten: backgrounds
|
//~ sixten: backgrounds
|
||||||
{ DemoBackground, "backgrounds/test.jpg", false }
|
{ DemoBackground, "backgrounds/test.jpg", false }
|
||||||
|
{ DDLCBackground, "backgrounds/ddlc.png", false }
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ sixten: characters
|
//~ sixten: characters
|
||||||
|
@ -19,10 +21,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@table_gen_enum asset_id:
|
@table_gen
|
||||||
{
|
{
|
||||||
|
`typedef s32 asset_id;`
|
||||||
|
`enum`
|
||||||
|
`{`
|
||||||
@expand(assets_desc s) `AssetID_$(s.Name),`;
|
@expand(assets_desc s) `AssetID_$(s.Name),`;
|
||||||
`AssetID_COUNT,`;
|
`AssetID_COUNT,`;
|
||||||
|
`};`
|
||||||
}
|
}
|
||||||
|
|
||||||
@table_gen_data(`char *`) AssetPathLUT:
|
@table_gen_data(`char *`) AssetPathLUT:
|
||||||
|
|
|
@ -83,7 +83,7 @@ static void Config_ParseError(string Message, string FileText, s64 Offset, arena
|
||||||
|
|
||||||
static void Config_ReadFile(config *Config, string Path)
|
static void Config_ReadFile(config *Config, string Path)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
|
|
||||||
//- sixten: read & tokenize input file
|
//- sixten: read & tokenize input file
|
||||||
string Text = Platform_ReadEntireFile(Scratch.Arena, Path);
|
string Text = Platform_ReadEntireFile(Scratch.Arena, Path);
|
||||||
|
@ -250,7 +250,7 @@ static string Config_ParseListJoin(arena *Arena, config_parse_list *List)
|
||||||
static void Config_WriteFile(config *Config, string Path)
|
static void Config_WriteFile(config *Config, string Path)
|
||||||
{
|
{
|
||||||
string_list Out = {};
|
string_list Out = {};
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
|
|
||||||
string LastDir = MakeString(0, 0LL);
|
string LastDir = MakeString(0, 0LL);
|
||||||
for(config_entry *Entry = Config->FirstInternal;
|
for(config_entry *Entry = Config->FirstInternal;
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
////////////////////////////////
|
||||||
|
//~ sixten: Debug Info Functions
|
||||||
|
|
||||||
|
per_thread debug_info *ThreadLocal_DebugInfo = 0;
|
||||||
|
|
||||||
|
//- sixten: manage state
|
||||||
|
static debug_info *DI_DebugInfoAlloc(void)
|
||||||
|
{
|
||||||
|
arena *Arena = ArenaAlloc(Kilobytes(1), true);
|
||||||
|
debug_info *Result = PushStruct(Arena, debug_info);
|
||||||
|
Result->Arena = Arena;
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DI_BeginFrame(debug_info *DebugInfo)
|
||||||
|
{
|
||||||
|
ThreadLocal_DebugInfo = DebugInfo;
|
||||||
|
DebugInfo->FrameTemp = BeginTemp(DebugInfo->Arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DI_EndFrame()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//- sixten: user interface
|
||||||
|
static void DI_Info(string Message)
|
||||||
|
{
|
||||||
|
debug_info *DebugInfo = ThreadLocal_DebugInfo;
|
||||||
|
debug_info_node *Node = PushStruct(DebugInfo->Arena, debug_info_node);
|
||||||
|
Node->Message = PushString(DebugInfo->Arena, Message);
|
||||||
|
DLLInsertLast(DebugInfo->First, DebugInfo->Last, Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DI_InfoF(char *Format, ...)
|
||||||
|
{
|
||||||
|
debug_info *DebugInfo = ThreadLocal_DebugInfo;
|
||||||
|
va_list Arguments;
|
||||||
|
va_start(Arguments, Format);
|
||||||
|
temp Scratch = GetScratch();
|
||||||
|
string Message = PushFormatVariadic(DebugInfo->Arena, Format, Arguments);
|
||||||
|
DI_Info(Message);
|
||||||
|
ReleaseScratch(Scratch);
|
||||||
|
va_end(Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DI_BuildInfo(void)
|
||||||
|
{
|
||||||
|
debug_info *DebugInfo = ThreadLocal_DebugInfo;
|
||||||
|
AC_AnimateValueDirect(DebugInfo->Open, 0.3f, &DebugInfo->OpenT);
|
||||||
|
if(!DLLIsEmpty(DebugInfo->First))
|
||||||
|
{
|
||||||
|
UI_Tooltip
|
||||||
|
{
|
||||||
|
UI_SetNextBackgroundColor(SetAlpha(Theme_BackgroundColor, 0.5f));
|
||||||
|
UI_SetNextSize(UI_Em(15, 1), UI_ChildrenSum(1, 1));
|
||||||
|
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_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))
|
||||||
|
{
|
||||||
|
UI_Font(Font_Bold) UI_LabelF("Debug Info");
|
||||||
|
UI_Spacer(UI_Percent(1, 0));
|
||||||
|
UI_Font(Font_Icons)
|
||||||
|
{
|
||||||
|
ui_box *ExpandBox = UI_MakeBoxF(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable|UI_BoxFlag_HotAnimation, "%U", DebugInfo->Open?FontIcon_DownDir:FontIcon_RightDir);
|
||||||
|
ui_signal ExpandBoxSignal = UI_SignalFromBox(ExpandBox);
|
||||||
|
if(ExpandBoxSignal.Pressed)
|
||||||
|
{
|
||||||
|
DebugInfo->Open = !DebugInfo->Open;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Height(UI_ChildrenSum(DebugInfo->OpenT, 1)) UI_Column()
|
||||||
|
{
|
||||||
|
UI_Width(UI_TextContent(15, 1)) UI_Height(UI_TextContent(15, 1))
|
||||||
|
for(debug_info_node *Node = DebugInfo->First; Node != 0; Node = Node->Next)
|
||||||
|
{
|
||||||
|
ui_box *MessageBox = UI_MakeBoxF(UI_BoxFlag_DrawText, "%p", Node);
|
||||||
|
UI_EquipBoxText(MessageBox, Node->Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_signal Signal = UI_SignalFromBox(Box);
|
||||||
|
if(Signal.Dragging)
|
||||||
|
{
|
||||||
|
if(Signal.Pressed)
|
||||||
|
{
|
||||||
|
UI_StoreDragV2(DebugInfo->RelativeP);
|
||||||
|
}
|
||||||
|
|
||||||
|
v2 StartP = UI_GetDragV2();
|
||||||
|
v2 EndP = StartP + Signal.DragDelta;
|
||||||
|
DebugInfo->RelativeP = EndP;
|
||||||
|
}
|
||||||
|
Box->FixedP = DebugInfo->RelativeP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sixten: after building we assume that the data should be released
|
||||||
|
EndTemp(DebugInfo->FrameTemp);
|
||||||
|
DebugInfo->First = DebugInfo->Last = 0;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* date = December 9th 2023 0:37 pm */
|
||||||
|
|
||||||
|
#ifndef VN_DEBUG_INFO_H
|
||||||
|
#define VN_DEBUG_INFO_H
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ sixten: Debug Info Types
|
||||||
|
|
||||||
|
struct debug_info_node
|
||||||
|
{
|
||||||
|
debug_info_node *Next;
|
||||||
|
debug_info_node *Prev;
|
||||||
|
string Message;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct debug_info
|
||||||
|
{
|
||||||
|
arena *Arena;
|
||||||
|
temp FrameTemp;
|
||||||
|
debug_info_node *First;
|
||||||
|
debug_info_node *Last;
|
||||||
|
v2_r32 RelativeP;
|
||||||
|
b32 Open;
|
||||||
|
r32 OpenT;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ sixten: Debug Info Functions
|
||||||
|
|
||||||
|
//- sixten: manage state
|
||||||
|
static debug_info *DI_DebugInfoAlloc(void);
|
||||||
|
static void DI_BeginFrame(debug_info *DebugInfo);
|
||||||
|
static void DI_EndFrame(void);
|
||||||
|
|
||||||
|
//- sixten: user interface
|
||||||
|
static void DI_Info(string Message);
|
||||||
|
static void DI_InfoF(char *Format, ...);
|
||||||
|
static void DI_BuildInfo(void);
|
||||||
|
|
||||||
|
#endif //VN_DEBUG_INFO_H
|
|
@ -176,7 +176,7 @@ static void PushTextF(render_group *Group, glyph_atlas *Atlas, font_id Font,
|
||||||
v2 P, r32 Size, v4 Color,
|
v2 P, r32 Size, v4 Color,
|
||||||
char *Format, ...)
|
char *Format, ...)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
|
|
||||||
va_list Arguments;
|
va_list Arguments;
|
||||||
va_start(Arguments, Format);
|
va_start(Arguments, Format);
|
||||||
|
|
|
@ -62,7 +62,7 @@ enum font_id
|
||||||
#define FontIcon_DocumentFileCode 0xf1c9
|
#define FontIcon_DocumentFileCode 0xf1c9
|
||||||
#define FontIcon_UserPlus 0xf234
|
#define FontIcon_UserPlus 0xf234
|
||||||
#define FontIcon_UserTimes 0xf235
|
#define FontIcon_UserTimes 0xf235
|
||||||
#define FontIcon_History 0xf235
|
#define FontIcon_History 0xf1da
|
||||||
#define FontIcon_Trash 0xf1f8
|
#define FontIcon_Trash 0xf1f8
|
||||||
#define FontIcon_Debug 0xf188
|
#define FontIcon_Debug 0xf188
|
||||||
#define FontIcon_Gamepad 0xf11b
|
#define FontIcon_Gamepad 0xf11b
|
||||||
|
|
|
@ -139,12 +139,16 @@ static platform_api Platform;
|
||||||
#define RENDER_ALLOCATE_TEXTURE(name) render_handle name(v2_s32 Dim, render_texture_format Format, b32 GenerateMipmap, void *Data)
|
#define RENDER_ALLOCATE_TEXTURE(name) render_handle name(v2_s32 Dim, render_texture_format Format, b32 GenerateMipmap, void *Data)
|
||||||
typedef RENDER_ALLOCATE_TEXTURE(render_allocate_texture);
|
typedef RENDER_ALLOCATE_TEXTURE(render_allocate_texture);
|
||||||
|
|
||||||
|
#define RENDER_DEALLOCATE_TEXTURE(name) void name(render_handle Handle)
|
||||||
|
typedef RENDER_DEALLOCATE_TEXTURE(render_deallocate_texture);
|
||||||
|
|
||||||
#define RENDER_FILL_REGION(name) void name(render_handle Handle, v2_s32 DestP, v2_s32 DestDim, void *Data)
|
#define RENDER_FILL_REGION(name) void name(render_handle Handle, v2_s32 DestP, v2_s32 DestDim, void *Data)
|
||||||
typedef RENDER_FILL_REGION(render_fill_region);
|
typedef RENDER_FILL_REGION(render_fill_region);
|
||||||
|
|
||||||
struct vn_render_commands
|
struct vn_render_commands
|
||||||
{
|
{
|
||||||
render_allocate_texture *AllocateTexture;
|
render_allocate_texture *AllocateTexture;
|
||||||
|
render_deallocate_texture *DeallocateTexture;
|
||||||
render_fill_region *FillRegion;
|
render_fill_region *FillRegion;
|
||||||
|
|
||||||
render_handle WhiteTexture;
|
render_handle WhiteTexture;
|
||||||
|
|
|
@ -179,13 +179,79 @@ static void S_ParseTopLevelDeclaration(scene_compiler *Compiler)
|
||||||
Compiler->At += 1;
|
Compiler->At += 1;
|
||||||
S_ParseVariableDeclaration(Compiler);
|
S_ParseVariableDeclaration(Compiler);
|
||||||
}
|
}
|
||||||
|
else if(Compiler->At[0].Kind == TokenKind_Nav)
|
||||||
|
{
|
||||||
|
Compiler->At += 1;
|
||||||
|
S_ParseNavFilePath(Compiler);
|
||||||
|
}
|
||||||
|
else if(Compiler->At[0].Kind == TokenKind_Background)
|
||||||
|
{
|
||||||
|
Compiler->At += 1;
|
||||||
|
S_ParseBackgroundAsset(Compiler);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
S_ParseError(Compiler, "Expected top-level declaration (proc or var).", 0);
|
S_ParseError(Compiler, "Expected top-level declaration (proc, var, background or nav).", 0);
|
||||||
Compiler->At += 1;
|
Compiler->At += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void S_ParseNavFilePath(scene_compiler *Compiler)
|
||||||
|
{
|
||||||
|
token NameToken = Compiler->At[0];
|
||||||
|
Compiler->At += 1;
|
||||||
|
|
||||||
|
if(NameToken.Kind == TokenKind_StringLiteral)
|
||||||
|
{
|
||||||
|
Compiler->NavFileName = Substring(Compiler->Text, Pad(NameToken.Range, -1));
|
||||||
|
if(Compiler->At[0].Kind == TokenKind_Semicolon)
|
||||||
|
{
|
||||||
|
// sixten: all good
|
||||||
|
Compiler->At += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
S_ParseError(Compiler, "Expected ';'.", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
S_ParseError(Compiler, "Expected nav file name.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void S_ParseBackgroundAsset(scene_compiler *Compiler)
|
||||||
|
{
|
||||||
|
token AssetNameToken = Compiler->At[0];
|
||||||
|
Compiler->At += 1;
|
||||||
|
if(AssetNameToken.Kind == TokenKind_Identifier)
|
||||||
|
{
|
||||||
|
//- sixten: find asset id by name
|
||||||
|
string AssetName = Substring(Compiler->Text, AssetNameToken.Range);
|
||||||
|
Compiler->BackgroundTexture = AssetID_None;
|
||||||
|
for(u64 AssetIndex = 0; AssetIndex < AssetID_COUNT; AssetIndex += 1)
|
||||||
|
{
|
||||||
|
if(AreEqual(MakeString(AssetNameLUT[AssetIndex]), AssetName))
|
||||||
|
{
|
||||||
|
Compiler->BackgroundTexture = AssetIndex;
|
||||||
|
goto ValidAssetFound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
S_ParseError(Compiler, "Invalid asset name.");
|
||||||
|
|
||||||
|
ValidAssetFound:;
|
||||||
|
if(Compiler->At[0].Kind == TokenKind_Semicolon)
|
||||||
|
{
|
||||||
|
// sixten: all good
|
||||||
|
Compiler->At += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
S_ParseError(Compiler, "Expected ';'.", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void S_ParseProcedure(scene_compiler *Compiler)
|
static void S_ParseProcedure(scene_compiler *Compiler)
|
||||||
{
|
{
|
||||||
token NameToken = S_ConsumeToken(Compiler, TokenKind_Identifier, "Expected procedure name after 'proc'");
|
token NameToken = S_ConsumeToken(Compiler, TokenKind_Identifier, "Expected procedure name after 'proc'");
|
||||||
|
@ -389,7 +455,7 @@ static void S_ParseJumpStatement(scene_compiler *Compiler)
|
||||||
|
|
||||||
static void S_ParseBranchStatement(scene_compiler *Compiler)
|
static void S_ParseBranchStatement(scene_compiler *Compiler)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
|
|
||||||
scene_branch_case *FirstBranch = 0, *LastBranch = 0;
|
scene_branch_case *FirstBranch = 0, *LastBranch = 0;
|
||||||
|
|
||||||
|
@ -646,7 +712,7 @@ static compiled_scene S_ScriptFromText(arena *Arena, string Text)
|
||||||
{
|
{
|
||||||
compiled_scene Result = {};
|
compiled_scene Result = {};
|
||||||
|
|
||||||
temporary_memory Scratch = GetScratch(&Arena, 1);
|
temp Scratch = GetScratch(&Arena, 1);
|
||||||
tokenize_result TokenizeResult = T_TokenizeFromText(Arena, Text, T_IsIrregular);
|
tokenize_result TokenizeResult = T_TokenizeFromText(Arena, Text, T_IsIrregular);
|
||||||
|
|
||||||
scene_compiler Compiler = {};
|
scene_compiler Compiler = {};
|
||||||
|
@ -723,6 +789,12 @@ static compiled_scene S_ScriptFromText(arena *Arena, string Text)
|
||||||
|
|
||||||
Result.Errors.Count = Compiler.Errors.Count;
|
Result.Errors.Count = Compiler.Errors.Count;
|
||||||
|
|
||||||
|
//- sixten: copy nav file name
|
||||||
|
Result.NavFileName = Compiler.NavFileName;
|
||||||
|
|
||||||
|
//- sixten: copy background texture handle
|
||||||
|
Result.BackgroundTexture = Compiler.BackgroundTexture;
|
||||||
|
|
||||||
// sixten(IMPORTANT): The text is assumed to remain in memory for the duration of the scene.
|
// sixten(IMPORTANT): The text is assumed to remain in memory for the duration of the scene.
|
||||||
Result.Source = Text;
|
Result.Source = Text;
|
||||||
|
|
||||||
|
@ -736,7 +808,8 @@ static compiled_scene S_CopyCompiledScene(arena *Arena, compiled_scene *Compiled
|
||||||
{
|
{
|
||||||
compiled_scene Result = {};
|
compiled_scene Result = {};
|
||||||
|
|
||||||
Assert(Compiled->Errors.Count == 0);
|
//- sixten(TODO): copy over the errors
|
||||||
|
//Assert(Compiled->Errors.Count == 0);
|
||||||
|
|
||||||
//- sixten: copy the global scope
|
//- sixten: copy the global scope
|
||||||
if(Compiled->GlobalScope)
|
if(Compiled->GlobalScope)
|
||||||
|
@ -772,7 +845,13 @@ static compiled_scene S_CopyCompiledScene(arena *Arena, compiled_scene *Compiled
|
||||||
//- sixten: copy the source
|
//- sixten: copy the source
|
||||||
Result.Source = PushString(Arena, Compiled->Source);
|
Result.Source = PushString(Arena, Compiled->Source);
|
||||||
|
|
||||||
Result.IsValid = true;//Compiled->IsValid; sixten(TODO): I don't know why this is commented out.
|
//- sixten: copy nav file
|
||||||
|
Result.NavFileName = PushString(Arena, Compiled->NavFileName);
|
||||||
|
|
||||||
|
//- sixten: copy background texture handle
|
||||||
|
Result.BackgroundTexture = Compiled->BackgroundTexture;
|
||||||
|
|
||||||
|
Result.IsValid = true;//Compiled->IsValid; // sixten(TODO): I don't know why this is commented out.
|
||||||
|
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,6 +189,9 @@ struct scene_compiler
|
||||||
scene_value_chunk *FirstValueChunk;
|
scene_value_chunk *FirstValueChunk;
|
||||||
scene_value_chunk *LastValueChunk;
|
scene_value_chunk *LastValueChunk;
|
||||||
s64 ValueCount;
|
s64 ValueCount;
|
||||||
|
|
||||||
|
string NavFileName;
|
||||||
|
asset_id BackgroundTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
@ -217,6 +220,8 @@ struct compiled_scene
|
||||||
scene_value *Values;
|
scene_value *Values;
|
||||||
s64 ValueCount;
|
s64 ValueCount;
|
||||||
string Source;
|
string Source;
|
||||||
|
string NavFileName;
|
||||||
|
asset_id BackgroundTexture;
|
||||||
scene_compile_error_list Errors;
|
scene_compile_error_list Errors;
|
||||||
b32 IsValid;
|
b32 IsValid;
|
||||||
};
|
};
|
||||||
|
@ -422,6 +427,8 @@ static void S_ParseDeclaration(scene_compiler *Compiler);
|
||||||
static void S_ParseVariableDeclaration(scene_compiler *Compiler);
|
static void S_ParseVariableDeclaration(scene_compiler *Compiler);
|
||||||
static void S_ParseVariable(scene_compiler *Compiler, b32 CanAssign);
|
static void S_ParseVariable(scene_compiler *Compiler, b32 CanAssign);
|
||||||
static void S_ParseNamedVariable(scene_compiler *Compiler, token Token, 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_ParseLineEntry(scene_compiler *Compiler);
|
||||||
static void S_ParseJumpStatement(scene_compiler *Compiler);
|
static void S_ParseJumpStatement(scene_compiler *Compiler);
|
||||||
static void S_ParseBranchStatement(scene_compiler *Compiler);
|
static void S_ParseBranchStatement(scene_compiler *Compiler);
|
||||||
|
|
|
@ -27,11 +27,96 @@ static void SV_Reset(void)
|
||||||
// sixten: reset textbox
|
// sixten: reset textbox
|
||||||
SceneView->Textbox.String.Count = 0;
|
SceneView->Textbox.String.Count = 0;
|
||||||
|
|
||||||
// sixten: reset last talking character
|
// sixten: reset onscreen characters
|
||||||
SceneView->LastTalkingCharacter.Count = 0;
|
SceneView->CharacterCount = 0;
|
||||||
SceneView->CharacterIsTalking = false;
|
}
|
||||||
|
|
||||||
SceneView->OnscreenCharacterCount = 0;
|
static void SV_LoadNavItems(void)
|
||||||
|
{
|
||||||
|
scene_view *SceneView = SV_GetState();
|
||||||
|
temp Scratch = GetScratch();
|
||||||
|
string NavData = Platform_ReadEntireFile(Scratch.Arena, SceneView->Runtime.Compiled.NavFileName);
|
||||||
|
|
||||||
|
if(NavData.Count != 0)
|
||||||
|
{
|
||||||
|
u8 *Byte = NavData.Data;
|
||||||
|
SceneView->NavItemCount = *(u16 *)Byte;
|
||||||
|
Byte += 2;
|
||||||
|
|
||||||
|
SceneView->NavItems = PushArrayNoClear(SceneView->SceneArena, scene_nav_item, SceneView->NavItemCount);
|
||||||
|
|
||||||
|
//- sixten: parse items
|
||||||
|
for(u64 ItemIndex = 0; ItemIndex < SceneView->NavItemCount; ItemIndex += 1)
|
||||||
|
{
|
||||||
|
scene_nav_item *Item = &SceneView->NavItems[ItemIndex];
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
switch(*Byte++)
|
||||||
|
{
|
||||||
|
case S_NavItemOp_TextureID:
|
||||||
|
{
|
||||||
|
string AssetName;
|
||||||
|
AssetName.Count = *(u16 *)Byte;
|
||||||
|
Byte += sizeof(u16);
|
||||||
|
AssetName.Data = Byte;
|
||||||
|
Byte += AssetName.Count;
|
||||||
|
|
||||||
|
Item->TextureID = AssetID_Error;
|
||||||
|
for(u64 AssetIndex = 0; AssetIndex < AssetID_COUNT; AssetIndex += 1)
|
||||||
|
{
|
||||||
|
if(AreEqual(MakeString(AssetNameLUT[AssetIndex]), AssetName))
|
||||||
|
{
|
||||||
|
Item->TextureID = AssetIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_Scale:
|
||||||
|
{
|
||||||
|
Item->Scale = *(r32 *)Byte;
|
||||||
|
Byte += sizeof(r32);
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_Origin:
|
||||||
|
{
|
||||||
|
Item->Origin = *(v2_r32 *)Byte;
|
||||||
|
Byte += sizeof(v2_r32);
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_P:
|
||||||
|
{
|
||||||
|
Item->P = *(v2_r32 *)Byte;
|
||||||
|
Byte += sizeof(v2_r32);
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_HoverText:
|
||||||
|
{
|
||||||
|
Item->HoverText.Count = *(u16 *)Byte;
|
||||||
|
Byte += 2;
|
||||||
|
|
||||||
|
Item->HoverText.Data = PushArrayNoClear(SceneView->SceneArena, u8, Item->HoverText.Count);
|
||||||
|
Copy(Item->HoverText.Data, Byte, Item->HoverText.Count);
|
||||||
|
Byte += Item->HoverText.Count;
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_Action:
|
||||||
|
{
|
||||||
|
Item->Action.Kind = (scene_nav_action_kind)*Byte;
|
||||||
|
Byte += 1;
|
||||||
|
|
||||||
|
Item->Action.Content.Count = *(u16 *)Byte;
|
||||||
|
Byte += 2;
|
||||||
|
|
||||||
|
Item->Action.Content.Data = PushArrayNoClear(SceneView->SceneArena, u8, Item->Action.Content.Count);
|
||||||
|
Copy(Item->Action.Content.Data, Byte, Item->Action.Content.Count);
|
||||||
|
Byte += Item->Action.Content.Count;
|
||||||
|
} goto Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- sixten: no op found, assume item done
|
||||||
|
break;
|
||||||
|
|
||||||
|
Next:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReleaseScratch(Scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SV_SetCurrentSource(compiled_scene *Compiled)
|
static void SV_SetCurrentSource(compiled_scene *Compiled)
|
||||||
|
@ -45,11 +130,14 @@ static void SV_SetCurrentSource(compiled_scene *Compiled)
|
||||||
ArenaClear(SceneView->SceneArena);
|
ArenaClear(SceneView->SceneArena);
|
||||||
Runtime->Compiled = S_CopyCompiledScene(SceneView->SceneArena, Compiled);
|
Runtime->Compiled = S_CopyCompiledScene(SceneView->SceneArena, Compiled);
|
||||||
|
|
||||||
|
SV_LoadNavItems();
|
||||||
|
|
||||||
|
|
||||||
//- sixten: run top level
|
//- sixten: run top level
|
||||||
Runtime->CurrentProc = Runtime->Compiled.GlobalScope;
|
Runtime->CurrentProc = Runtime->Compiled.GlobalScope;
|
||||||
if(Runtime->CurrentProc)
|
if(Runtime->CurrentProc)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
scene_runtime_result RunResult = S_Run(Runtime, Scratch.Arena, false);
|
scene_runtime_result RunResult = S_Run(Runtime, Scratch.Arena, false);
|
||||||
|
@ -86,6 +174,39 @@ static b32 SV_CurrentlyInProc(void)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
scene_view_character_data *Character = SceneView->Characters+CharacterIndex;
|
||||||
|
if(Character->Talking)
|
||||||
|
{
|
||||||
|
Result = Character;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
struct text_properties
|
||||||
{
|
{
|
||||||
font_id Font;
|
font_id Font;
|
||||||
|
@ -166,7 +287,7 @@ static r32 CalculateGlobalScaleFromDim(v2_r32 Dim)
|
||||||
}
|
}
|
||||||
static r32 CalculateGlobalScaleFromRootBox(ui_box *Box)
|
static r32 CalculateGlobalScaleFromRootBox(ui_box *Box)
|
||||||
{
|
{
|
||||||
v2 RenderDim = DimOfRange(Box->Rect);
|
v2 RenderDim = UI_CalculateBoxDim(Box);
|
||||||
r32 GlobalScale = SquareRoot(RenderDim.x*RenderDim.y)/45;
|
r32 GlobalScale = SquareRoot(RenderDim.x*RenderDim.y)/45;
|
||||||
return(GlobalScale);
|
return(GlobalScale);
|
||||||
}
|
}
|
||||||
|
@ -222,6 +343,8 @@ static void SV_DrawBackground(scene_view *SceneView, ui_box *Box, render_group *
|
||||||
{
|
{
|
||||||
v2 RenderDim = DimOfRange(Box->Rect);
|
v2 RenderDim = DimOfRange(Box->Rect);
|
||||||
|
|
||||||
|
render_handle Texture = TextureFromAssetID(SceneView->Runtime.Compiled.BackgroundTexture);
|
||||||
|
|
||||||
//- sixten: render background
|
//- sixten: render background
|
||||||
// sixten(TODO, but soon): Currently we add Box->Rect.Min to everything, but that should really be a transform
|
// sixten(TODO, but soon): Currently we add Box->Rect.Min to everything, but that should really be a transform
|
||||||
// on the render group.
|
// on the render group.
|
||||||
|
@ -232,11 +355,11 @@ static void SV_DrawBackground(scene_view *SceneView, ui_box *Box, render_group *
|
||||||
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;
|
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 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)));
|
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(SceneView->BackgroundTexture)));
|
||||||
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, SceneView->BackgroundTexture);
|
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, Texture);
|
||||||
#else
|
#else
|
||||||
range2_r32 BackgroundDest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min);
|
range2_r32 BackgroundDest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min);
|
||||||
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(SceneView->BackgroundTexture)));
|
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(SceneView->BackgroundTexture)));
|
||||||
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, SceneView->BackgroundTexture);
|
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, Texture);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -250,9 +373,9 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback)
|
||||||
r32 GlobalScale = CalculateGlobalScaleFromDim(RenderDim);
|
r32 GlobalScale = CalculateGlobalScaleFromDim(RenderDim);
|
||||||
|
|
||||||
//- sixten: render characters
|
//- sixten: render characters
|
||||||
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1)
|
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
|
||||||
{
|
{
|
||||||
scene_view_character_data *Character = SceneView->OnscreenCharacters + CharacterIndex;
|
scene_view_character_data *Character = SceneView->Characters + CharacterIndex;
|
||||||
|
|
||||||
v4_r32 BlendColor = LinearBlend(Color_White, Color_Black, 0.5-Character->TalkingT*0.5);
|
v4_r32 BlendColor = LinearBlend(Color_White, Color_Black, 0.5-Character->TalkingT*0.5);
|
||||||
BlendColor.a = Character->ActiveT;
|
BlendColor.a = Character->ActiveT;
|
||||||
|
@ -277,11 +400,11 @@ static b32 BuildSceneBranchButton(string Text, r32 GlobalScale)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BuildProcView(scene_view *View, ui_box *Box)
|
static void BuildProcView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
|
|
||||||
r32 GlobalScale = CalculateGlobalScaleFromRootBox(Box);
|
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
|
||||||
r32 ActiveScale = GlobalScale * 0.75f;
|
r32 ActiveScale = GlobalScale * 0.75f;
|
||||||
|
|
||||||
scene_runtime *Runtime = &View->Runtime;
|
scene_runtime *Runtime = &View->Runtime;
|
||||||
|
@ -321,8 +444,11 @@ static void BuildProcView(scene_view *View, ui_box *Box)
|
||||||
scene_textbox_data *TextboxData = PushStruct(UI_FrameArena(), scene_textbox_data);
|
scene_textbox_data *TextboxData = PushStruct(UI_FrameArena(), scene_textbox_data);
|
||||||
TextboxData->Textbox = Textbox;
|
TextboxData->Textbox = Textbox;
|
||||||
TextboxData->SceneViewBox = Box;
|
TextboxData->SceneViewBox = Box;
|
||||||
TextboxData->Name = View->LastTalkingCharacter;
|
|
||||||
TextboxData->NameT = View->CharacterIsTalkingT;
|
scene_view_character_data *TalkingCharacter = SV_FindTalkingCharacter();
|
||||||
|
TextboxData->Name = SV_DisplayNameFromCharacter(TalkingCharacter);
|
||||||
|
TextboxData->NameT = AC_AnimateValueF(TalkingCharacter != 0, 0, 0.3f, "Scene View Talking Character %p", View);
|
||||||
|
|
||||||
UI_EquipBoxCustomDrawCallback(TextBox, BuildSceneTextboxDrawCallback, TextboxData);
|
UI_EquipBoxCustomDrawCallback(TextBox, BuildSceneTextboxDrawCallback, TextboxData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +519,7 @@ static ui_signal SV_BuildNavItem(scene_nav_item *Item, r32 GlobalScale, v2_r32 G
|
||||||
static ui_signal BuildNavItemAndLabel(scene_nav_item *Item, r32 GlobalScale, v2_r32 GlobalDim)
|
static ui_signal BuildNavItemAndLabel(scene_nav_item *Item, r32 GlobalScale, v2_r32 GlobalDim)
|
||||||
{
|
{
|
||||||
ui_signal Signal = SV_BuildNavItem(Item, GlobalScale, GlobalDim);
|
ui_signal Signal = SV_BuildNavItem(Item, GlobalScale, GlobalDim);
|
||||||
if(Signal.Hovering)
|
if(Item->HoverText.Count && Signal.Hovering)
|
||||||
{
|
{
|
||||||
UI_FontSize(GlobalScale*0.5f) UI_Font(Font_Fancy) UI_CornerRadius(4.0f)
|
UI_FontSize(GlobalScale*0.5f) UI_Font(Font_Fancy) UI_CornerRadius(4.0f)
|
||||||
UI_TooltipLabel(Item->HoverText, UI_MouseP());
|
UI_TooltipLabel(Item->HoverText, UI_MouseP());
|
||||||
|
@ -401,40 +527,14 @@ static ui_signal BuildNavItemAndLabel(scene_nav_item *Item, r32 GlobalScale, v2_
|
||||||
return(Signal);
|
return(Signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_nav_item Items[] =
|
static void BuildNavView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
|
||||||
{
|
{
|
||||||
{
|
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
|
||||||
AssetID_ArthurHappy,
|
|
||||||
0.01f,
|
|
||||||
V2R32(0.5f, 1.0f),
|
|
||||||
V2R32(0.15f, 0.6f),
|
|
||||||
StrLit("Talk to Arthur"),
|
|
||||||
{
|
|
||||||
S_NavAction_Proc,
|
|
||||||
StrLit("arthur_talk"),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AssetID_MonikaLeaning,
|
|
||||||
0.02f,
|
|
||||||
V2R32(0.5f, 1.0f),
|
|
||||||
V2R32(-0.4f, 0.6f),
|
|
||||||
StrLit("Talk to Monika"),
|
|
||||||
{
|
|
||||||
S_NavAction_Scene,
|
|
||||||
StrLit("ddlc"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static void BuildNavView(scene_view *View, ui_box *Box)
|
for(int ItemIndex = 0; ItemIndex < View->NavItemCount; ++ItemIndex)
|
||||||
{
|
{
|
||||||
r32 GlobalScale = CalculateGlobalScaleFromRootBox(Box);
|
scene_nav_item *Item = View->NavItems+ItemIndex;
|
||||||
|
if(BuildNavItemAndLabel(Item, GlobalScale, BoxDim).Clicked)
|
||||||
for(int ItemIndex = 0; ItemIndex < ArrayCount(Items); ++ItemIndex)
|
|
||||||
{
|
|
||||||
scene_nav_item *Item = Items+ItemIndex;
|
|
||||||
if(BuildNavItemAndLabel(Item, GlobalScale, DimOfRange(Box->Rect)).Clicked)
|
|
||||||
{
|
{
|
||||||
// sixten: apply the action
|
// sixten: apply the action
|
||||||
if(Item->Action.Kind == S_NavAction_Proc)
|
if(Item->Action.Kind == S_NavAction_Proc)
|
||||||
|
@ -443,7 +543,7 @@ static void BuildNavView(scene_view *View, ui_box *Box)
|
||||||
}
|
}
|
||||||
else if(Item->Action.Kind == S_NavAction_Scene)
|
else if(Item->Action.Kind == S_NavAction_Scene)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
string Filepath = PushFormat(Scratch.Arena, "data/%S.vns", Item->Action.Content);;
|
string Filepath = PushFormat(Scratch.Arena, "data/%S.vns", Item->Action.Content);;
|
||||||
|
|
||||||
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, Filepath);
|
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, Filepath);
|
||||||
|
@ -458,21 +558,38 @@ static void BuildNavView(scene_view *View, ui_box *Box)
|
||||||
|
|
||||||
static void BuildScene(scene_view *View)
|
static void BuildScene(scene_view *View)
|
||||||
{
|
{
|
||||||
UI_SetNextWidth(UI_Percent(1, 0));
|
v2_r32 ParentDim = UI_CalculateBoxDim(UI_TopParent());
|
||||||
UI_SetNextHeight(UI_Percent(1, 0));
|
|
||||||
|
r32 TargetRatio = 16.0f/9.0f;
|
||||||
|
r32 ActualRatio = ParentDim.x/ParentDim.y;
|
||||||
|
|
||||||
|
v2_r32 BoxDim = ParentDim;
|
||||||
|
|
||||||
|
if(ActualRatio>TargetRatio)
|
||||||
|
{
|
||||||
|
BoxDim.x = BoxDim.y*TargetRatio;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BoxDim.y = BoxDim.x/TargetRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_SetNextWidth(UI_Pixels(BoxDim.x, 1));
|
||||||
|
UI_SetNextHeight(UI_Pixels(BoxDim.y, 1));
|
||||||
UI_SetNextLayoutAxis(Axis2_Y);
|
UI_SetNextLayoutAxis(Axis2_Y);
|
||||||
ui_box *Box = UI_MakeBox(0, StrLit("Scene View"));
|
UI_SetNextFixedP((ParentDim-BoxDim)*0.5f);
|
||||||
|
ui_box *Box = UI_MakeBox(UI_BoxFlag_Clip|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, StrLit("Scene View"));
|
||||||
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View);
|
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View);
|
||||||
|
|
||||||
UI_Parent(Box)
|
UI_Parent(Box)
|
||||||
{
|
{
|
||||||
if(SV_CurrentlyInProc())
|
if(SV_CurrentlyInProc())
|
||||||
{
|
{
|
||||||
BuildProcView(View, Box);
|
BuildProcView(View, Box, BoxDim);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BuildNavView(View, Box);
|
BuildNavView(View, Box, BoxDim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,9 +656,9 @@ static scene_view_character_data *SV_CharacterDataFromName(string Name)
|
||||||
|
|
||||||
scene_view *View = SV_GetState();
|
scene_view *View = SV_GetState();
|
||||||
|
|
||||||
for(s32 CharacterIndex = 0; CharacterIndex < View->OnscreenCharacterCount; CharacterIndex += 1)
|
for(s32 CharacterIndex = 0; CharacterIndex < View->CharacterCount; CharacterIndex += 1)
|
||||||
{
|
{
|
||||||
scene_view_character_data *Character = View->OnscreenCharacters + CharacterIndex;
|
scene_view_character_data *Character = View->Characters + CharacterIndex;
|
||||||
if(AreEqual(Character->Name, Name))
|
if(AreEqual(Character->Name, Name))
|
||||||
{
|
{
|
||||||
Result = Character;
|
Result = Character;
|
||||||
|
@ -550,16 +667,16 @@ static scene_view_character_data *SV_CharacterDataFromName(string Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
//- sixten: create character if not initialized
|
//- sixten: create character if not initialized
|
||||||
if(!Result && View->OnscreenCharacterCount < ArrayCount(View->OnscreenCharacters))
|
if(!Result && View->CharacterCount < ArrayCount(View->Characters))
|
||||||
{
|
{
|
||||||
s32 CharacterIndex = View->OnscreenCharacterCount;
|
s32 CharacterIndex = View->CharacterCount;
|
||||||
View->OnscreenCharacterCount += 1;
|
View->CharacterCount += 1;
|
||||||
|
|
||||||
Result = View->OnscreenCharacters + CharacterIndex;
|
Result = View->Characters + CharacterIndex;
|
||||||
*Result = {};
|
*Result = {};
|
||||||
Result->Name = Name;
|
Result->Name = Name;
|
||||||
Result->Active = true;
|
Result->Active = true;
|
||||||
Result->PctP = (r32)(CharacterIndex + 1) / (View->OnscreenCharacterCount + 1);
|
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharacterCount + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(Result);
|
return(Result);
|
||||||
|
@ -601,9 +718,9 @@ static r32 SV_CalculateTargetPctP(s32 TrueCharacterIndex)
|
||||||
scene_view *View = SV_GetState();
|
scene_view *View = SV_GetState();
|
||||||
s32 CharacterCount = 0;
|
s32 CharacterCount = 0;
|
||||||
s32 AssumedCharacterIndex = 0;
|
s32 AssumedCharacterIndex = 0;
|
||||||
for(s32 CharacterIndex = 0; CharacterIndex < View->OnscreenCharacterCount; CharacterIndex += 1)
|
for(s32 CharacterIndex = 0; CharacterIndex < View->CharacterCount; CharacterIndex += 1)
|
||||||
{
|
{
|
||||||
scene_view_character_data *Data = View->OnscreenCharacters + CharacterIndex;
|
scene_view_character_data *Data = View->Characters + CharacterIndex;
|
||||||
if(Data->Active)
|
if(Data->Active)
|
||||||
{
|
{
|
||||||
CharacterCount += 1;
|
CharacterCount += 1;
|
||||||
|
@ -628,8 +745,19 @@ static void SV_UpdateInDialog(arena *FrameArena)
|
||||||
|
|
||||||
if(Compiled && Compiled->IsValid)
|
if(Compiled && Compiled->IsValid)
|
||||||
{
|
{
|
||||||
b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||Platform_KeyPress(EventList, Key_MouseLeft));
|
//- 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||MousePressed);
|
||||||
|
|
||||||
|
//- sixten: run the scene
|
||||||
if(!Runtime->LastResult.HadError)
|
if(!Runtime->LastResult.HadError)
|
||||||
{
|
{
|
||||||
b32 AdvanceOnAwait = (Textbox->CharsRevealed >= Textbox->String.Count) && PlayerAction;
|
b32 AdvanceOnAwait = (Textbox->CharsRevealed >= Textbox->String.Count) && PlayerAction;
|
||||||
|
@ -643,6 +771,9 @@ static void SV_UpdateInDialog(arena *FrameArena)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- sixten: advance textbox
|
||||||
|
{
|
||||||
r32 CharsPerSecond = 25.0f;
|
r32 CharsPerSecond = 25.0f;
|
||||||
Textbox->CharsRevealed += dtForFrame*CharsPerSecond;
|
Textbox->CharsRevealed += dtForFrame*CharsPerSecond;
|
||||||
Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count);
|
Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count);
|
||||||
|
@ -653,6 +784,7 @@ static void SV_UpdateInDialog(arena *FrameArena)
|
||||||
}
|
}
|
||||||
|
|
||||||
AC_AnimateValueDirect(Textbox->CharsRevealed, 0.05f, &Textbox->CharsRevealedT);
|
AC_AnimateValueDirect(Textbox->CharsRevealed, 0.05f, &Textbox->CharsRevealedT);
|
||||||
|
}
|
||||||
|
|
||||||
//- sixten: apply the textbox actions
|
//- sixten: apply the textbox actions
|
||||||
for(scene_textbox_action *Action = Runtime->FirstTextboxAction; Action != 0; Action = Action->Next)
|
for(scene_textbox_action *Action = Runtime->FirstTextboxAction; Action != 0; Action = Action->Next)
|
||||||
|
@ -680,18 +812,16 @@ static void SV_UpdateInDialog(arena *FrameArena)
|
||||||
}
|
}
|
||||||
Runtime->FirstTextboxAction = Runtime->LastTextboxAction = 0;
|
Runtime->FirstTextboxAction = Runtime->LastTextboxAction = 0;
|
||||||
|
|
||||||
//- sixten: make all characters non-talking
|
// sixten: update character state only if there has been a change
|
||||||
if(Runtime->FirstCharacterAction != 0)
|
if(Runtime->FirstCharacterAction != 0)
|
||||||
{
|
{
|
||||||
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1)
|
//- sixten: make all characters non-talking
|
||||||
|
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
|
||||||
{
|
{
|
||||||
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
|
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
|
||||||
Data->Talking = false;
|
Data->Talking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneView->CharacterIsTalking = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- sixten: apply character actions
|
//- sixten: apply character actions
|
||||||
for(scene_character_action *Action = Runtime->FirstCharacterAction; Action != 0; Action = Action->Next)
|
for(scene_character_action *Action = Runtime->FirstCharacterAction; Action != 0; Action = Action->Next)
|
||||||
{
|
{
|
||||||
|
@ -706,21 +836,17 @@ static void SV_UpdateInDialog(arena *FrameArena)
|
||||||
{
|
{
|
||||||
if(Action->State != CR_State_Invalid)
|
if(Action->State != CR_State_Invalid)
|
||||||
{
|
{
|
||||||
Data->Info = SV_CharacterTextureFromAction(Action);;
|
Data->Info = SV_CharacterTextureFromAction(Action);
|
||||||
}
|
}
|
||||||
Data->Talking = true;
|
Data->Talking = true;
|
||||||
|
|
||||||
SceneView->CharacterIsTalking = true;
|
|
||||||
|
|
||||||
string CharacterName = Action->Target;
|
string CharacterName = Action->Target;
|
||||||
scene_named_value *CharacterNameValue = S_FindGlobalVariableByName(Runtime, CharacterName, false);
|
scene_named_value *CharacterNameValue = S_FindGlobalVariableByName(Runtime, CharacterName, false);
|
||||||
if(CharacterNameValue && CharacterNameValue->Value.Kind == S_ValueKind_String)
|
if(CharacterNameValue && CharacterNameValue->Value.Kind == S_ValueKind_String)
|
||||||
{
|
{
|
||||||
CharacterName = CharacterNameValue->Value.String;
|
CharacterName = CharacterNameValue->Value.String;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
SceneView->LastTalkingCharacter = MakeString(SceneView->LastTalkingCharacterBuffer, CharacterName.Count);
|
|
||||||
Copy(SceneView->LastTalkingCharacterBuffer, CharacterName.Data, CharacterName.Count);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,11 +860,9 @@ static void SV_Update(arena *FrameArena)
|
||||||
|
|
||||||
//- sixten: update the characters
|
//- sixten: update the characters
|
||||||
{
|
{
|
||||||
AC_AnimateValueDirect(SceneView->CharacterIsTalking, 0.3f, &SceneView->CharacterIsTalkingT);
|
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
|
||||||
|
|
||||||
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1)
|
|
||||||
{
|
{
|
||||||
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
|
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
|
||||||
|
|
||||||
if(!SV_CurrentlyInProc())
|
if(!SV_CurrentlyInProc())
|
||||||
{
|
{
|
||||||
|
@ -756,20 +880,20 @@ static void SV_Update(arena *FrameArena)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->OnscreenCharacterCount+1);
|
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharacterCount+1);
|
||||||
}
|
}
|
||||||
AC_AnimateValueDirect(TargetPctP, 0.4f, &Data->PctP);
|
AC_AnimateValueDirect(TargetPctP, 0.4f, &Data->PctP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- sixten: prune any unactive characters
|
//- sixten: prune any unactive characters
|
||||||
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->OnscreenCharacterCount; CharacterIndex += 1)
|
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
|
||||||
{
|
{
|
||||||
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
|
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
|
||||||
if(!Data->Active && Data->ActiveT < 0.01)
|
if(!Data->Active && Data->ActiveT < 0.01)
|
||||||
{
|
{
|
||||||
Move(Data, Data+1, (SceneView->OnscreenCharacterCount-CharacterIndex-1)*sizeof(scene_view_character_data));
|
Move(Data, Data+1, (SceneView->CharacterCount-CharacterIndex-1)*sizeof(scene_view_character_data));
|
||||||
SceneView->OnscreenCharacterCount -= 1;
|
SceneView->CharacterCount -= 1;
|
||||||
CharacterIndex -= 1;
|
CharacterIndex -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,14 +55,16 @@ struct scene_nav_item
|
||||||
scene_nav_action Action;
|
scene_nav_action Action;
|
||||||
};
|
};
|
||||||
|
|
||||||
global read_only scene_nav_item G_DefaultSceneNavItem =
|
typedef u8 scene_nav_item_op;
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
AssetID_ArthurNormal,
|
S_NavItemOp_None = 0,
|
||||||
0.01f,
|
S_NavItemOp_TextureID,
|
||||||
V2R32(0.5f, 1.0f),
|
S_NavItemOp_Scale,
|
||||||
V2R32(0.0f, 0.0f),
|
S_NavItemOp_Origin,
|
||||||
StrLit(""),
|
S_NavItemOp_P,
|
||||||
S_NavAction_None
|
S_NavItemOp_HoverText,
|
||||||
|
S_NavItemOp_Action,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scene_nav
|
struct scene_nav
|
||||||
|
@ -80,14 +82,13 @@ struct scene_view
|
||||||
scene_runtime Runtime;
|
scene_runtime Runtime;
|
||||||
textbox Textbox;
|
textbox Textbox;
|
||||||
|
|
||||||
u8 LastTalkingCharacterBuffer[32];
|
//- sixten: characters
|
||||||
string LastTalkingCharacter;
|
s32 CharacterCount;
|
||||||
|
scene_view_character_data Characters[16];
|
||||||
|
|
||||||
b32 CharacterIsTalking;
|
//- sixten: nav items
|
||||||
r32 CharacterIsTalkingT;
|
scene_nav_item *NavItems;
|
||||||
|
u64 NavItemCount;
|
||||||
s32 OnscreenCharacterCount;
|
|
||||||
scene_view_character_data OnscreenCharacters[16];
|
|
||||||
|
|
||||||
//- sixten: input per frame
|
//- sixten: input per frame
|
||||||
platform_event_list *EventList;
|
platform_event_list *EventList;
|
||||||
|
@ -111,6 +112,9 @@ static void SV_Init(scene_view *View, arena *TextboxArena);
|
||||||
|
|
||||||
static b32 SV_CurrentlyInProc(void);
|
static b32 SV_CurrentlyInProc(void);
|
||||||
|
|
||||||
|
static scene_view_character_data *SV_FindTalkingCharacter(void);
|
||||||
|
static string SV_DisplayNameFromCharacter(scene_view_character_data *Character);
|
||||||
|
|
||||||
static void SV_DrawBackground(scene_view *SceneView, ui_box *Box, render_group *Group);
|
static void SV_DrawBackground(scene_view *SceneView, ui_box *Box, render_group *Group);
|
||||||
|
|
||||||
static ui_signal SV_BuildNavItem(scene_nav_item * Item, r32 GlobalScale, v2_r32 GlobalDim);
|
static ui_signal SV_BuildNavItem(scene_nav_item * Item, r32 GlobalScale, v2_r32 GlobalDim);
|
||||||
|
|
|
@ -56,6 +56,6 @@ static temporary_memory GetScratch(memory_arena **Conflicts = 0, u64 ConflictCou
|
||||||
return(Scratch);
|
return(Scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ReleaseScratch(Scratch) EndTemporaryMemory(Scratch)
|
#define ReleaseScratch(Scratch) EndTemp(Scratch)
|
||||||
|
|
||||||
#endif //VN_THREAD_CONTEXT_H
|
#endif //VN_THREAD_CONTEXT_H
|
||||||
|
|
|
@ -54,7 +54,7 @@ static void T_MessageListPush(arena *Arena, tokenizer_message_list *List, tokeni
|
||||||
|
|
||||||
static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_filter_function *ExcludeFilter)
|
static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_filter_function *ExcludeFilter)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch(&Arena, 1);
|
temp Scratch = GetScratch(&Arena, 1);
|
||||||
token_chunk_list Tokens = {};
|
token_chunk_list Tokens = {};
|
||||||
tokenizer_message_list Messages = {};
|
tokenizer_message_list Messages = {};
|
||||||
u8 *TextStart = Text.Data;
|
u8 *TextStart = Text.Data;
|
||||||
|
@ -175,7 +175,8 @@ static tokenize_result T_TokenizeFromText(arena *Arena, string Text, tokenizer_f
|
||||||
else if(AreEqual(String, StrLit("true"))) { TokenKind = TokenKind_True; }
|
else if(AreEqual(String, StrLit("true"))) { TokenKind = TokenKind_True; }
|
||||||
else if(AreEqual(String, StrLit("var"))) { TokenKind = TokenKind_Var; }
|
else if(AreEqual(String, StrLit("var"))) { TokenKind = TokenKind_Var; }
|
||||||
else if(AreEqual(String, StrLit("while"))) { TokenKind = TokenKind_While; }
|
else if(AreEqual(String, StrLit("while"))) { TokenKind = TokenKind_While; }
|
||||||
else if(AreEqual(String, StrLit("define"))) { TokenKind = TokenKind_Define; }
|
else if(AreEqual(String, StrLit("nav"))) { TokenKind = TokenKind_Nav; }
|
||||||
|
else if(AreEqual(String, StrLit("background"))) { TokenKind = TokenKind_Background; }
|
||||||
}
|
}
|
||||||
|
|
||||||
//- sixten: numerics
|
//- sixten: numerics
|
||||||
|
|
|
@ -55,7 +55,8 @@ enum token_kind
|
||||||
TokenKind_True,
|
TokenKind_True,
|
||||||
TokenKind_Var,
|
TokenKind_Var,
|
||||||
TokenKind_While,
|
TokenKind_While,
|
||||||
TokenKind_Define,
|
TokenKind_Nav,
|
||||||
|
TokenKind_Background,
|
||||||
TokenKind_KeywordsEnd,
|
TokenKind_KeywordsEnd,
|
||||||
|
|
||||||
// sixten: whitespace
|
// sixten: whitespace
|
||||||
|
|
|
@ -125,6 +125,16 @@ static r64 UI_Time(void)
|
||||||
return(UI_GetState()->Time);
|
return(UI_GetState()->Time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static r64 UI_Blink(void)
|
||||||
|
{
|
||||||
|
return(Cos(UI_GetState()->BlinkTime*10.0f)*0.5f+0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UI_ResetBlink(void)
|
||||||
|
{
|
||||||
|
UI_GetState()->BlinkTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline ui_key UI_EmptyKey(void)
|
inline ui_key UI_EmptyKey(void)
|
||||||
{
|
{
|
||||||
ui_key Key = {};
|
ui_key Key = {};
|
||||||
|
@ -233,7 +243,14 @@ inline ui_box *UI_MakeBox(ui_box_flags Flags, string String)
|
||||||
|
|
||||||
ui_box *Parent = UI_TopParent();
|
ui_box *Parent = UI_TopParent();
|
||||||
|
|
||||||
ui_key BaseKey = UI_KeyFromString(String);
|
string KeyString = String;
|
||||||
|
s64 HashIndex = LastIndexOf(KeyString, StrLit("##"));
|
||||||
|
if(HashIndex != -1)
|
||||||
|
{
|
||||||
|
KeyString = Suffix(KeyString, KeyString.Count-HashIndex-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_key BaseKey = UI_KeyFromString(KeyString);
|
||||||
ui_key Seed = UI_SeedKey(BaseKey, Parent ? Parent->Seed : UI_EmptyKey());
|
ui_key Seed = UI_SeedKey(BaseKey, Parent ? Parent->Seed : UI_EmptyKey());
|
||||||
ui_key Key = BaseKey.Value ? Seed : UI_EmptyKey();
|
ui_key Key = BaseKey.Value ? Seed : UI_EmptyKey();
|
||||||
|
|
||||||
|
@ -263,11 +280,18 @@ 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)
|
if(HashIndex != -1)
|
||||||
{
|
{
|
||||||
Box->String = Prefix(Box->String, HashIndex);
|
Box->String = Prefix(Box->String, HashIndex);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HashIndex = LastIndexOf(Box->String, '#');
|
||||||
|
if(HashIndex != -1)
|
||||||
|
{
|
||||||
|
Box->String = Prefix(Box->String, HashIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UI_ApplyStyles(Box);
|
UI_ApplyStyles(Box);
|
||||||
|
|
||||||
|
@ -794,20 +818,9 @@ static void UI_LayoutBox(ui_box *Box)
|
||||||
for(ui_box *Child = Box->First;
|
for(ui_box *Child = Box->First;
|
||||||
Child != 0;
|
Child != 0;
|
||||||
Child = Child->Next)
|
Child = Child->Next)
|
||||||
{
|
|
||||||
if(Child->Flags & UI_BoxFlag_AnimatePosition)
|
|
||||||
{
|
|
||||||
Child->ApproachingRelativeP.x = AC_AnimateValueF(Child->ComputedRelativeP.x, Child->ComputedRelativeP.x, 0.5, "Box P.X %p", Child);
|
|
||||||
Child->ApproachingRelativeP.y = AC_AnimateValueF(Child->ComputedRelativeP.y, Child->ComputedRelativeP.y, 0.5, "Box P.Y %p", Child);
|
|
||||||
|
|
||||||
Child->Rect.Min = Box->Rect.Min + Child->ApproachingRelativeP + Box->Offset;
|
|
||||||
Child->Rect.Max = Child->Rect.Min + Child->ComputedDim;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
Child->Rect.Min = Box->Rect.Min + Child->ComputedRelativeP + Box->Offset;
|
Child->Rect.Min = Box->Rect.Min + Child->ComputedRelativeP + Box->Offset;
|
||||||
Child->Rect.Max = Child->Rect.Min + Child->ComputedDim;
|
Child->Rect.Max = Child->Rect.Min + Child->ComputedDim;
|
||||||
}
|
|
||||||
UI_LayoutBox(Child);
|
UI_LayoutBox(Child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -920,6 +933,7 @@ static void UI_NewFrame(ui *UI, platform_event_list *EventList, v2 MouseP, r32 d
|
||||||
UI->dMouseP = MouseP - UI->MouseP;
|
UI->dMouseP = MouseP - UI->MouseP;
|
||||||
UI->MouseP = MouseP;
|
UI->MouseP = MouseP;
|
||||||
UI->Time += dtForFrame;
|
UI->Time += dtForFrame;
|
||||||
|
UI->BlinkTime += dtForFrame;
|
||||||
|
|
||||||
UI->GlyphAtlas = GlyphAtlas;
|
UI->GlyphAtlas = GlyphAtlas;
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,6 @@ enum
|
||||||
UI_BoxFlag_FloatingX = (1 << 10),
|
UI_BoxFlag_FloatingX = (1 << 10),
|
||||||
UI_BoxFlag_FloatingY = (1 << 11),
|
UI_BoxFlag_FloatingY = (1 << 11),
|
||||||
UI_BoxFlag_Scrollable = (1 << 12),
|
UI_BoxFlag_Scrollable = (1 << 12),
|
||||||
UI_BoxFlag_AnimatePosition = (1 << 13),
|
|
||||||
};
|
};
|
||||||
typedef u32 ui_box_flags;
|
typedef u32 ui_box_flags;
|
||||||
|
|
||||||
|
@ -147,6 +146,8 @@ struct ui
|
||||||
ui_key Active;
|
ui_key Active;
|
||||||
|
|
||||||
r64 Time;
|
r64 Time;
|
||||||
|
r64 BlinkTime;
|
||||||
|
r64 Blink;
|
||||||
|
|
||||||
ui_key NextHot;
|
ui_key NextHot;
|
||||||
b32 NextHotSet;
|
b32 NextHotSet;
|
||||||
|
@ -188,6 +189,8 @@ inline void *UI_GetDragDataPointer(void);
|
||||||
|
|
||||||
//- sixten: Helpers
|
//- sixten: Helpers
|
||||||
static r64 UI_Time(void);
|
static r64 UI_Time(void);
|
||||||
|
static r64 UI_Blink(void);
|
||||||
|
static void UI_ResetBlink(void);
|
||||||
|
|
||||||
//- sixten: Key functions
|
//- sixten: Key functions
|
||||||
static ui_key UI_EmptyKey(void);
|
static ui_key UI_EmptyKey(void);
|
||||||
|
|
|
@ -72,7 +72,7 @@ static ui_box *UI_NamedSpacer(ui_size Size, string String)
|
||||||
|
|
||||||
static ui_box *UI_NamedSpacerF(ui_size Size, char *Format, ...)
|
static ui_box *UI_NamedSpacerF(ui_size Size, char *Format, ...)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
|
|
||||||
va_list Arguments;
|
va_list Arguments;
|
||||||
va_start(Arguments, Format);
|
va_start(Arguments, Format);
|
||||||
|
@ -103,7 +103,7 @@ static ui_box *UI_Label(string String)
|
||||||
|
|
||||||
static ui_box *UI_LabelF(char *Format, ...)
|
static ui_box *UI_LabelF(char *Format, ...)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
|
|
||||||
va_list Arguments;
|
va_list Arguments;
|
||||||
va_start(Arguments, Format);
|
va_start(Arguments, Format);
|
||||||
|
@ -133,7 +133,7 @@ static ui_signal UI_Button(string String)
|
||||||
|
|
||||||
static ui_signal UI_ButtonF(char *Format, ...)
|
static ui_signal UI_ButtonF(char *Format, ...)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
|
|
||||||
UI_SetNextHoverCursor(PlatformCursor_Hand);
|
UI_SetNextHoverCursor(PlatformCursor_Hand);
|
||||||
|
|
||||||
|
@ -434,3 +434,167 @@ static void UI_TooltipLabel(string Label, v2 P)
|
||||||
Label);
|
Label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ui_line_edit_callback_data
|
||||||
|
{
|
||||||
|
text_edit_state State;
|
||||||
|
b32 Focus;
|
||||||
|
};
|
||||||
|
|
||||||
|
UI_CUSTOM_DRAW_CALLBACK(UI_LineEditCallback)
|
||||||
|
{
|
||||||
|
ui_line_edit_callback_data *EditData = (ui_line_edit_callback_data *)Data;
|
||||||
|
s64 ClampedCursor = Clamp(0, Box->String.Count, EditData->State.Cursor);
|
||||||
|
s64 ClampedMark = Clamp(0, Box->String.Count, EditData->State.Mark);
|
||||||
|
string ToCursor = MakeString(Box->String.Data, ClampedCursor);
|
||||||
|
string ToMark = MakeString(Box->String.Data, ClampedMark);
|
||||||
|
|
||||||
|
r32 TargetCursorX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToCursor);
|
||||||
|
r32 TargetMarkerX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToMark);
|
||||||
|
|
||||||
|
r32 CursorX = AC_AnimateValueF(TargetCursorX, 0, 0.175, "UI Input Cursor %p", Box);
|
||||||
|
r32 MarkerX = AC_AnimateValueF(TargetMarkerX, 0, 0.175, "UI Input Mark %p", Box);
|
||||||
|
|
||||||
|
v2 BoxDim = DimOfRange(Box->Rect);
|
||||||
|
|
||||||
|
// sixten: Draw selection
|
||||||
|
{
|
||||||
|
v2 Offset = V2(7.5, (BoxDim.y - Box->FontSize) / 2);
|
||||||
|
v2 Dim = V2(0, Box->FontSize);
|
||||||
|
if(CursorX > MarkerX)
|
||||||
|
{
|
||||||
|
Offset.x += MarkerX;
|
||||||
|
Dim.x = CursorX - MarkerX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Offset.x += CursorX;
|
||||||
|
Dim.x = MarkerX - CursorX;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2 P = Box->Rect.Min + Offset;
|
||||||
|
v4 Color = V4(0.4, 0.7, 0.8, 0.3);
|
||||||
|
PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sixten: Draw cursor
|
||||||
|
{
|
||||||
|
range1_r32 CursorSpan = Range1R32(CursorX, TargetCursorX);
|
||||||
|
r32 Height = Box->FontSize + 4;
|
||||||
|
v2 Offset = V2(7.5F + CursorSpan.Min, (BoxDim.y - Height) / 2);
|
||||||
|
v2 Dim = V2(1.25F + CursorSpan.Max - CursorSpan.Min, Height);
|
||||||
|
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);
|
||||||
|
PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sixten(NOTE): this function only kinda works. it is meant for single line text, if that is any indication of its scope.
|
||||||
|
static s64 UI_TextIndexFromP(ui_box *Box, v2_r32 P)
|
||||||
|
{
|
||||||
|
// sixten: yes, usually I don't like doing this, but hey there is only one glyph atlas used throughout the entire application, nobody will notice ._.
|
||||||
|
glyph_atlas *Atlas = UI_GetState()->GlyphAtlas;
|
||||||
|
|
||||||
|
s64 Result = 0;
|
||||||
|
// sixten(NOTE): from now on, we ignore the y-axis
|
||||||
|
r32 Dim = CalculateRasterizedTextWidth(UI_GetState()->GlyphAtlas, Box->Font, Box->FontSize, Box->String);
|
||||||
|
r32 Offset = P.x - Box->Rect.Min.x - (Box->Rect.Max.x - Box->Rect.Min.x - Dim)*0.5;
|
||||||
|
|
||||||
|
r32 Advance = 0;
|
||||||
|
u8 *TextBegin = Box->String.Data;
|
||||||
|
u8 *TextEnd = TextBegin+Box->String.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, Box->Font, Codepoint, Box->FontSize*Font_Oversample, GetSubpixelSegmentAtP(Advance*Font_Oversample));
|
||||||
|
Assert(Glyph);
|
||||||
|
|
||||||
|
Advance += Glyph->Advance/Font_Oversample;
|
||||||
|
if(Advance > Offset)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ui_signal UI_LineEdit(text_edit_state *State, u64 BufferSize, u8 *Buffer, s64 *BufferUsed, string String, b32 Focused)
|
||||||
|
{
|
||||||
|
temp Scratch = GetScratch();
|
||||||
|
if(Focused)
|
||||||
|
{
|
||||||
|
for(platform_event *Event = UI_EventList()->First; Event != 0; Event = Event->Next)
|
||||||
|
{
|
||||||
|
if((Event->Type == PlatformEvent_Press || Event->Type == PlatformEvent_Text) && (Event->Codepoint != '/' && Event->Codepoint != '\\'))
|
||||||
|
{
|
||||||
|
text_action Action = SingleLineTextActionFromEvent(Event);
|
||||||
|
if(IsValid(&Action))
|
||||||
|
{
|
||||||
|
text_op Op = TextOpFromAction(Scratch.Arena, MakeString(Buffer, *BufferUsed), State, &Action);
|
||||||
|
if(Op.NewCursor >= 0 && Op.NewMark >= 0)
|
||||||
|
{
|
||||||
|
string Left = MakeString(Buffer, Op.Range.Min);
|
||||||
|
string Right = MakeString(Buffer + Op.Range.Max, *BufferUsed - Op.Range.Max);
|
||||||
|
|
||||||
|
u64 NewStringSize = Left.Count + Right.Count + Op.ReplaceString.Count;
|
||||||
|
char *NewString = PushArray(Scratch.Arena, char, NewStringSize);
|
||||||
|
Copy(NewString, Left.Data, Left.Count);
|
||||||
|
Copy(NewString + Left.Count, Op.ReplaceString.Data, Op.ReplaceString.Count);
|
||||||
|
Copy(NewString + Left.Count + Op.ReplaceString.Count, Right.Data, Right.Count);
|
||||||
|
*BufferUsed = Minimum(BufferSize, NewStringSize);
|
||||||
|
Copy(Buffer, NewString, *BufferUsed);
|
||||||
|
|
||||||
|
State->Cursor = Minimum(Op.NewCursor, *BufferUsed);
|
||||||
|
State->Mark = Minimum(Op.NewMark, *BufferUsed);
|
||||||
|
Platform_ConsumeEvent(UI_EventList(), Event);
|
||||||
|
|
||||||
|
UI_ResetBlink();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_SetNextHoverCursor(PlatformCursor_IBeam);
|
||||||
|
ui_box *Container = UI_MakeBox(UI_BoxFlag_Clip|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clickable, String);
|
||||||
|
ui_box *InputBox = 0;
|
||||||
|
|
||||||
|
UI_Parent(Container) UI_Height(UI_Percent(1, 1))
|
||||||
|
{
|
||||||
|
UI_SetNextWidth(UI_TextContent(15, 1));
|
||||||
|
InputBox = UI_MakeBox(UI_BoxFlag_DrawText, StrLit("Text Input"));
|
||||||
|
UI_EquipBoxText(InputBox, MakeString(Buffer, *BufferUsed));
|
||||||
|
ui_line_edit_callback_data *Data = PushStruct(UI_FrameArena(), ui_line_edit_callback_data);
|
||||||
|
Data->State = *State;
|
||||||
|
Data->Focus = Focused;
|
||||||
|
UI_EquipBoxCustomDrawCallback(InputBox, UI_LineEditCallback, Data);
|
||||||
|
|
||||||
|
UI_Spacer(UI_Percent(1, 0));
|
||||||
|
}
|
||||||
|
ReleaseScratch(Scratch);
|
||||||
|
|
||||||
|
//- sixten: handle mouse dragging
|
||||||
|
ui_signal Signal = UI_SignalFromBox(Container);
|
||||||
|
if(Signal.Dragging)
|
||||||
|
{
|
||||||
|
if(Signal.Pressed)
|
||||||
|
{
|
||||||
|
State->Cursor = State->Mark = UI_TextIndexFromP(InputBox, UI_MouseP());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
State->Cursor = UI_TextIndexFromP(InputBox, UI_MouseP());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(Signal);
|
||||||
|
}
|
|
@ -57,5 +57,6 @@ static ui_signal UI_ButtonF(char *Format, ...);
|
||||||
static ui_signal UI_Checkbox(b32 *Checked, string String);
|
static ui_signal UI_Checkbox(b32 *Checked, string String);
|
||||||
static r32 UI_Slider(r32 Value, range1_r32 Range);
|
static r32 UI_Slider(r32 Value, range1_r32 Range);
|
||||||
static void UI_TooltipLabel(string Label, v2 P);
|
static void UI_TooltipLabel(string Label, v2 P);
|
||||||
|
static b32 UI_LineEdit(text_edit_state *State, u64 BufferSize, u8 *Buffer, u64 *BufferUsed, string String, b32 Focused);
|
||||||
|
|
||||||
#endif //VN_UI_UTILS_H
|
#endif //VN_UI_UTILS_H
|
||||||
|
|
|
@ -147,7 +147,7 @@ static ui_signal W_BuildToolbarButton(char *Text, workspace_toolbar_menu Menu)
|
||||||
|
|
||||||
static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut)
|
static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
|
|
||||||
UI_SetNextLayoutAxis(Axis2_X);
|
UI_SetNextLayoutAxis(Axis2_X);
|
||||||
UI_SetNextHoverCursor(PlatformCursor_Hand);
|
UI_SetNextHoverCursor(PlatformCursor_Hand);
|
||||||
|
@ -233,8 +233,7 @@ static void W_BuildToolbar(void)
|
||||||
{
|
{
|
||||||
workspace_view_kind ViewKind = W_ViewKind_None;
|
workspace_view_kind ViewKind = W_ViewKind_None;
|
||||||
if(W_BuildMenuItem(FontIcon_None, "Welcome", "").Clicked) {ViewKind = W_ViewKind_Startup;}
|
if(W_BuildMenuItem(FontIcon_None, "Welcome", "").Clicked) {ViewKind = W_ViewKind_Startup;}
|
||||||
if(W_BuildMenuItem(FontIcon_Pencil, "File Lister", "Ctrl + O").Clicked) {ViewKind = W_ViewKind_FileLister;}
|
if(W_BuildMenuItem(FontIcon_FolderOpen, "File Lister", "Ctrl + O").Clicked) {ViewKind = W_ViewKind_FileLister;}
|
||||||
if(W_BuildMenuItem(FontIcon_Users, "Navigation Editor", "").Clicked) {ViewKind = W_ViewKind_NavEditor;}
|
|
||||||
if(W_BuildMenuItem(FontIcon_Terminal, "Scene View", "").Clicked) {ViewKind = W_ViewKind_SceneView;}
|
if(W_BuildMenuItem(FontIcon_Terminal, "Scene View", "").Clicked) {ViewKind = W_ViewKind_SceneView;}
|
||||||
if(W_BuildMenuItem(FontIcon_Wrench, "Settings", "Ctrl + Shift + P").Clicked) {ViewKind = W_ViewKind_Settings;}
|
if(W_BuildMenuItem(FontIcon_Wrench, "Settings", "Ctrl + Shift + P").Clicked) {ViewKind = W_ViewKind_Settings;}
|
||||||
|
|
||||||
|
@ -423,7 +422,7 @@ static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View)
|
||||||
b32 ViewIsCurrent = (Panel->CurrentView == View);
|
b32 ViewIsCurrent = (Panel->CurrentView == View);
|
||||||
b32 PanelIsCurrent = (Workspace->CurrentPanel == Panel);
|
b32 PanelIsCurrent = (Workspace->CurrentPanel == Panel);
|
||||||
|
|
||||||
string Name = W_GetViewName(UI_FrameArena(), View);
|
string Name = W_NameFromView(UI_FrameArena(), View);
|
||||||
|
|
||||||
b32 Open = !(W_ViewIsDragged(View) && Workspace->DragPayloadState != W_DragPayload_Released);
|
b32 Open = !(W_ViewIsDragged(View) && Workspace->DragPayloadState != W_DragPayload_Released);
|
||||||
r32 OpenT = AC_AnimateValueF(Open, 0.0f, 0.3f, "Workspace Tab Item %p", View);
|
r32 OpenT = AC_AnimateValueF(Open, 0.0f, 0.3f, "Workspace Tab Item %p", View);
|
||||||
|
@ -771,7 +770,7 @@ static void W_BuildDragPayload()
|
||||||
{
|
{
|
||||||
workspace_view *DraggedView = Payload.View;
|
workspace_view *DraggedView = Payload.View;
|
||||||
UI_SetNextCornerRadius(4);
|
UI_SetNextCornerRadius(4);
|
||||||
UI_TooltipLabel(W_GetViewName(UI_FrameArena(), DraggedView), UI_MouseP());
|
UI_TooltipLabel(W_NameFromView(UI_FrameArena(), DraggedView), UI_MouseP());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -798,16 +797,6 @@ static void W_Init(workspace *Workspace)
|
||||||
{
|
{
|
||||||
W_CreateNewView(W_ViewKind_Startup, Workspace->RootPanel);
|
W_CreateNewView(W_ViewKind_Startup, Workspace->RootPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sixten: build text editor / scene view layout
|
|
||||||
if(0)
|
|
||||||
{
|
|
||||||
W_CreateNewView(W_ViewKind_TextEditor, Workspace->RootPanel);
|
|
||||||
W_SplitPanel(Workspace->RootPanel, Axis2_X);
|
|
||||||
W_CreateNewView(W_ViewKind_SceneView, Workspace->RootPanel->Last);
|
|
||||||
}
|
|
||||||
|
|
||||||
W_CreateNewView(W_ViewKind_NavEditor, Workspace->RootPanel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands, vn_input *Input, glyph_atlas *GlyphAtlas)
|
static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands, vn_input *Input, glyph_atlas *GlyphAtlas)
|
||||||
|
|
|
@ -38,6 +38,7 @@ WORKSPACE_COMMAND(W_Command_ClosePanel)
|
||||||
Parent->First = Child->First;
|
Parent->First = Child->First;
|
||||||
Parent->Last = Child->Last;
|
Parent->Last = Child->Last;
|
||||||
Parent->SplitAxis = Child->SplitAxis;
|
Parent->SplitAxis = Child->SplitAxis;
|
||||||
|
Parent->CurrentView = Child->CurrentView;
|
||||||
|
|
||||||
// sixten: Update the parents of the children.
|
// sixten: Update the parents of the children.
|
||||||
for(workspace_view *View = Parent->FirstView;
|
for(workspace_view *View = Parent->FirstView;
|
||||||
|
@ -110,7 +111,7 @@ WORKSPACE_COMMAND(W_Command_CloseView)
|
||||||
|
|
||||||
WORKSPACE_COMMAND(W_Command_OpenFile)
|
WORKSPACE_COMMAND(W_Command_OpenFile)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
|
|
||||||
workspace *Workspace = W_GetState();
|
workspace *Workspace = W_GetState();
|
||||||
workspace_file_lister_action *Action = (workspace_file_lister_action *)U64ToPointer(Argument);
|
workspace_file_lister_action *Action = (workspace_file_lister_action *)U64ToPointer(Argument);
|
||||||
|
@ -146,7 +147,31 @@ WORKSPACE_COMMAND(W_Command_OpenFile)
|
||||||
Platform.ReadFile(File, Contents.Data, 0, Contents.Count);
|
Platform.ReadFile(File, Contents.Data, 0, Contents.Count);
|
||||||
|
|
||||||
workspace_view *View = W_CreateNewView(W_ViewKind_NavEditor, Workspace->CurrentPanel);
|
workspace_view *View = W_CreateNewView(W_ViewKind_NavEditor, Workspace->CurrentPanel);
|
||||||
W_SetupNavEditor(View, Contents);
|
W_NavEditorSetup(View, Action->Path, Action->Name, Contents);
|
||||||
|
}
|
||||||
|
else if(AreEqual(FileExtension, StrLit("png")) || AreEqual(FileExtension, StrLit("jpg")))
|
||||||
|
{
|
||||||
|
s64 FileSize = Platform.GetFileSize(File);
|
||||||
|
string Contents = MakeString(PushArrayNoClear(Scratch.Arena, u8, FileSize), FileSize);
|
||||||
|
Platform.ReadFile(File, Contents.Data, 0, Contents.Count);
|
||||||
|
workspace_view *View = W_CreateNewView(W_ViewKind_ImageViewer, Workspace->CurrentPanel);
|
||||||
|
b32 CouldOpenImage = W_ImageViewerSetup(View, Action->Name, Contents);
|
||||||
|
if(!CouldOpenImage)
|
||||||
|
{
|
||||||
|
//- sixten: destroy the view and show an error message instead
|
||||||
|
workspace_panel *Panel = View->Parent;
|
||||||
|
|
||||||
|
DLLRemove(Panel->FirstView, Panel->LastView, View);
|
||||||
|
if(Panel->CurrentView == View)
|
||||||
|
{
|
||||||
|
Panel->CurrentView = Panel->FirstView;
|
||||||
|
}
|
||||||
|
W_DestroyView(View);
|
||||||
|
|
||||||
|
View = W_CreateNewView(W_ViewKind_Error, Workspace->CurrentPanel);
|
||||||
|
workspace_view_error *Error = (workspace_view_error *)View->Data;
|
||||||
|
Error->Message = PushFormat(View->Arena, "Unknown to open file: %S", Filepath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,69 +87,45 @@ static b32 W_BuildFileListerItem(string Text, u32 Icon, b32 Selected, b32 EnterP
|
||||||
|
|
||||||
static workspace_file_lister_action W_BuildFileLister(workspace_view *View)
|
static workspace_file_lister_action W_BuildFileLister(workspace_view *View)
|
||||||
{
|
{
|
||||||
workspace_view_file_lister *Lister = (workspace_view_file_lister *)View->Data;
|
|
||||||
|
|
||||||
workspace_file_lister_action ListerAction = {};
|
workspace_file_lister_action ListerAction = {};
|
||||||
temporary_memory Scratch = GetScratch();
|
|
||||||
UI_Size(UI_Percent(1, 1), UI_Percent(1, 1))
|
workspace_view_file_lister *Lister = (workspace_view_file_lister *)View->Data;
|
||||||
{
|
|
||||||
|
|
||||||
b32 EnterPressed = Platform_KeyPress(UI_EventList(), Key_Return);
|
b32 EnterPressed = Platform_KeyPress(UI_EventList(), Key_Return);
|
||||||
s32 SelectedItemDelta = 0;
|
s32 SelectedItemDelta = 0;
|
||||||
|
|
||||||
s32 ListerCount = 0;
|
s32 ListerCount = 0;
|
||||||
|
s64 LastSlash = LastIndexOf(Lister->Path, '/');
|
||||||
|
b32 RequestedParentDirectory = false;
|
||||||
|
|
||||||
|
temp Scratch = GetScratch();
|
||||||
|
UI_Size(UI_Percent(1, 1), UI_Percent(1, 1))
|
||||||
|
{
|
||||||
//- sixten: filename input field
|
//- sixten: filename input field
|
||||||
if(W_ViewIsCurrent(View))
|
if(W_ViewIsCurrent(View))
|
||||||
{
|
{
|
||||||
for(platform_event *Event = UI_EventList()->First; Event != 0; Event = Event->Next)
|
for(platform_event *Event = UI_EventList()->First; Event != 0; Event = Event->Next)
|
||||||
{
|
{
|
||||||
if((Event->Type == PlatformEvent_Press || Event->Type == PlatformEvent_Text) && (Event->Codepoint != '/' && Event->Codepoint != '\\'))
|
|
||||||
{
|
|
||||||
text_action Action = SingleLineTextActionFromEvent(Event);
|
|
||||||
if(IsValid(&Action))
|
|
||||||
{
|
|
||||||
text_op Op = TextOpFromAction(Scratch.Arena, MakeString(Lister->Input, Lister->InputUsed), &Lister->InputEditState, &Action);
|
|
||||||
if(Op.NewCursor >= 0 && Op.NewMark >= 0)
|
|
||||||
{
|
|
||||||
string Left = MakeString(Lister->Input, Op.Range.Min);
|
|
||||||
string Right = MakeString(Lister->Input + Op.Range.Max, Lister->InputUsed - Op.Range.Max);
|
|
||||||
|
|
||||||
u64 NewStringSize = Left.Count + Right.Count + Op.ReplaceString.Count;
|
|
||||||
char *NewString = PushArray(Scratch.Arena, char, NewStringSize);
|
|
||||||
Copy(NewString, Left.Data, Left.Count);
|
|
||||||
Copy(NewString + Left.Count, Op.ReplaceString.Data, Op.ReplaceString.Count);
|
|
||||||
Copy(NewString + Left.Count + Op.ReplaceString.Count, Right.Data, Right.Count);
|
|
||||||
Lister->InputUsed = Minimum(ArrayCount(Lister->Input), NewStringSize);
|
|
||||||
Copy(Lister->Input, NewString, Lister->InputUsed);
|
|
||||||
|
|
||||||
Lister->InputEditState.Cursor = Minimum(Op.NewCursor, Lister->InputUsed);
|
|
||||||
Lister->InputEditState.Mark = Minimum(Op.NewMark, Lister->InputUsed);
|
|
||||||
Platform_ConsumeEvent(UI_EventList(), Event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Event->Type == PlatformEvent_Press && (Event->Key == Key_Up || Event->Key == Key_Down))
|
if(Event->Type == PlatformEvent_Press && (Event->Key == Key_Up || Event->Key == Key_Down))
|
||||||
{
|
{
|
||||||
SelectedItemDelta = Event->Key == Key_Up ? -1 : 1;
|
SelectedItemDelta = Event->Key == Key_Up ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
if(Event->Type == PlatformEvent_Press && Event->Key == Key_Backspace && Lister->InputEditState.Cursor == 0)
|
||||||
|
{
|
||||||
|
RequestedParentDirectory = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- sixten: build navbar
|
//- sixten: build navbar
|
||||||
UI_Height(UI_Em(2, 1)) UI_Row(UI_BoxFlag_DrawBorder)
|
UI_Height(UI_Em(2, 1)) UI_Row(UI_BoxFlag_DrawBorder)
|
||||||
{
|
{
|
||||||
|
|
||||||
UI_SetNextBackgroundColor(ColorFromHex(0x2D5790FF));
|
UI_SetNextBackgroundColor(ColorFromHex(0x2D5790FF));
|
||||||
UI_SetNextWidth(UI_TextContent(20, 1));
|
UI_SetNextWidth(UI_TextContent(20, 1));
|
||||||
UI_MakeBox(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawText, Lister->Path);
|
UI_MakeBox(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawText, Lister->Path);
|
||||||
|
|
||||||
UI_SetNextWidth(UI_TextContent(15, 1));
|
UI_Width(UI_Percent(1, 0))
|
||||||
ui_box *InputBox = UI_MakeBox(UI_BoxFlag_DrawText, StrLit("Text Lister Lister Input"));
|
UI_LineEdit(&Lister->InputEditState, ArrayCount(Lister->Input), Lister->Input, &Lister->InputUsed, StrLit("File Lister Text Input"), W_ViewIsCurrent(View));
|
||||||
UI_EquipBoxText(InputBox, MakeString(Lister->Input, Lister->InputUsed));
|
|
||||||
UI_EquipBoxCustomDrawCallback(InputBox, W_FileListerInputCallback, Lister);
|
|
||||||
|
|
||||||
UI_Padding(UI_Percent(1, 0));
|
|
||||||
|
|
||||||
UI_SetNextWidth(UI_TextContent(20, 1));
|
UI_SetNextWidth(UI_TextContent(20, 1));
|
||||||
if(UI_ButtonF("Open/Create").Clicked || EnterPressed)
|
if(UI_ButtonF("Open/Create").Clicked || EnterPressed)
|
||||||
|
@ -165,16 +141,12 @@ static workspace_file_lister_action W_BuildFileLister(workspace_view *View)
|
||||||
UI_Height(UI_Em(2, 1))
|
UI_Height(UI_Em(2, 1))
|
||||||
{
|
{
|
||||||
//- sixten: display "parent directory button"
|
//- sixten: display "parent directory button"
|
||||||
s64 LastSlash = LastIndexOf(Lister->Path, '/');
|
|
||||||
if(LastSlash != -1)
|
if(LastSlash != -1)
|
||||||
{
|
{
|
||||||
b32 BackspacePressed = Lister->InputUsed == 0 && Platform_KeyPress(UI_EventList(), Key_Backspace);
|
if(W_BuildFileListerItem(StrLit("Parent Directory"), FontIcon_Reply, Lister->SelectedItem == ListerCount, EnterPressed))
|
||||||
if(W_BuildFileListerItem(StrLit("Parent Directory"), FontIcon_Reply, Lister->SelectedItem == ListerCount, EnterPressed) ||
|
|
||||||
BackspacePressed)
|
|
||||||
{
|
{
|
||||||
Lister->Path = Prefix(Lister->Path, LastSlash);
|
RequestedParentDirectory = true;
|
||||||
Lister->InputUsed = 0;
|
ListerAction.HasRequestedFile = false; // sixten: if we have selected a folder, but typed a name we want to open the folder.
|
||||||
Lister->SelectedItem = -1;
|
|
||||||
}
|
}
|
||||||
ListerCount += 1;
|
ListerCount += 1;
|
||||||
}
|
}
|
||||||
|
@ -229,7 +201,7 @@ static workspace_file_lister_action W_BuildFileLister(workspace_view *View)
|
||||||
Lister->SelectedItem += SelectedItemDelta;
|
Lister->SelectedItem += SelectedItemDelta;
|
||||||
if(Lister->SelectedItem < 0)
|
if(Lister->SelectedItem < 0)
|
||||||
{
|
{
|
||||||
Lister->SelectedItem += ListerCount;
|
Lister->SelectedItem = ListerCount - 1;
|
||||||
}
|
}
|
||||||
else if(Lister->SelectedItem >= ListerCount)
|
else if(Lister->SelectedItem >= ListerCount)
|
||||||
{
|
{
|
||||||
|
@ -241,6 +213,15 @@ static workspace_file_lister_action W_BuildFileLister(workspace_view *View)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- sixten: goto parent directory
|
||||||
|
if(RequestedParentDirectory && LastSlash != -1)
|
||||||
|
{
|
||||||
|
Lister->Path = Prefix(Lister->Path, LastSlash);
|
||||||
|
Lister->InputUsed = 0;
|
||||||
|
Lister->SelectedItem = -1;
|
||||||
|
}
|
||||||
|
|
||||||
ReleaseScratch(Scratch);
|
ReleaseScratch(Scratch);
|
||||||
return(ListerAction);
|
return(ListerAction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct workspace_view_file_lister
|
||||||
string Path;
|
string Path;
|
||||||
r32 Scroll;
|
r32 Scroll;
|
||||||
u8 Input[256];
|
u8 Input[256];
|
||||||
s32 InputUsed;
|
s64 InputUsed;
|
||||||
text_edit_state InputEditState;
|
text_edit_state InputEditState;
|
||||||
s32 SelectedItem;
|
s32 SelectedItem;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,81 @@ UI_CUSTOM_DRAW_CALLBACK(BuildNavViewDrawCallback)
|
||||||
SV_DrawBackground(SceneView, Box, Group);
|
SV_DrawBackground(SceneView, Box, Group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void W_NavEditorSerializeItems(workspace_view_nav_editor *Editor)
|
||||||
|
{
|
||||||
|
temp Scratch = GetScratch();
|
||||||
|
|
||||||
|
//- sixten: find total size
|
||||||
|
u64 TotalSize = sizeof(u16); // item count
|
||||||
|
for(scene_nav_item_node *Node = Editor->Items.First; Node != 0; Node = Node->Next)
|
||||||
|
{
|
||||||
|
string AssetName = MakeString(AssetNameLUT[Node->Item.TextureID]);
|
||||||
|
|
||||||
|
TotalSize += 1; TotalSize += sizeof(u16); TotalSize += AssetName.Count; // texture id
|
||||||
|
TotalSize += 1; TotalSize += sizeof(r32); // scale
|
||||||
|
TotalSize += 1; TotalSize += sizeof(v2_r32); // origin
|
||||||
|
TotalSize += 1; TotalSize += sizeof(v2_r32); // p
|
||||||
|
TotalSize += 1; TotalSize += sizeof(u16); TotalSize += Node->Item.HoverText.Count; // hover text
|
||||||
|
TotalSize += 1; TotalSize += sizeof(u16); TotalSize += sizeof(u8); TotalSize += Node->Item.Action.Content.Count; // action
|
||||||
|
TotalSize += 1; // end of item
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *FileData = PushArray(Scratch.Arena, u8, TotalSize);
|
||||||
|
u8 *Data = FileData;
|
||||||
|
|
||||||
|
*(u16 *)Data = Editor->Items.Count;
|
||||||
|
Data += sizeof(u16);
|
||||||
|
|
||||||
|
#define WriteByte(Op) do { *Data++ = Op; } while(0)
|
||||||
|
#define WriteField(Op, type, Member) do { *Data++ = Op; *(type *)Data = Member; Data += sizeof(type); } while(0)
|
||||||
|
#define WriteString(String) do { *(u16 *)Data = (u16)String.Count; Data += sizeof(u16); Copy(Data, String.Data, String.Count); Data += String.Count; } while(0)
|
||||||
|
|
||||||
|
for(scene_nav_item_node *Node = Editor->Items.First; Node != 0; Node = Node->Next)
|
||||||
|
{
|
||||||
|
scene_nav_item *Item = &Node->Item;
|
||||||
|
string AssetName = MakeString(AssetNameLUT[Node->Item.TextureID]);
|
||||||
|
WriteByte(S_NavItemOp_TextureID); WriteString(AssetName);
|
||||||
|
WriteField(S_NavItemOp_Scale, r32, Item->Scale);
|
||||||
|
WriteField(S_NavItemOp_Origin, v2_r32, Item->Origin);
|
||||||
|
WriteField(S_NavItemOp_P, v2_r32, Item->P);
|
||||||
|
WriteByte(S_NavItemOp_HoverText); WriteString(Item->HoverText);
|
||||||
|
WriteByte(S_NavItemOp_Action); WriteByte(Item->Action.Kind); WriteString(Item->Action.Content);
|
||||||
|
WriteByte(S_NavItemOp_None);
|
||||||
|
}
|
||||||
|
#undef WriteByte
|
||||||
|
#undef WriteField
|
||||||
|
#undef WriteString
|
||||||
|
|
||||||
|
platform_file_handle File = Platform.OpenFile(PushFormat(Scratch.Arena, "%S/%S", Editor->FilePath, Editor->FileName), PlatformAccess_Write);
|
||||||
|
if(File.IsValid)
|
||||||
|
{
|
||||||
|
Platform.WriteFile(File, FileData, 0, TotalSize);
|
||||||
|
Platform.CloseFile(File);
|
||||||
|
}
|
||||||
|
ReleaseScratch(Scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static workspace_string_chunk *W_StringChunkAlloc(arena *Arena, workspace_string_chunk_list *FreeList)
|
||||||
|
{
|
||||||
|
workspace_string_chunk *Result = FreeList->First;
|
||||||
|
if(Result)
|
||||||
|
{
|
||||||
|
DLLRemove(FreeList->First, FreeList->Last, Result);
|
||||||
|
*Result = {};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = PushStruct(Arena, workspace_string_chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void W_StringChunkRelease(workspace_string_chunk_list *FreeList, workspace_string_chunk *Chunk)
|
||||||
|
{
|
||||||
|
DLLInsertLast(FreeList->First, FreeList->Last, Chunk);
|
||||||
|
}
|
||||||
|
|
||||||
static scene_nav_item_node *W_SceneNavItemNodeAlloc(arena *Arena, workspace_view_nav_editor *Editor)
|
static scene_nav_item_node *W_SceneNavItemNodeAlloc(arena *Arena, workspace_view_nav_editor *Editor)
|
||||||
{
|
{
|
||||||
scene_nav_item_node *Result = Editor->FirstFree;
|
scene_nav_item_node *Result = Editor->FirstFree;
|
||||||
|
@ -17,6 +92,12 @@ static scene_nav_item_node *W_SceneNavItemNodeAlloc(arena *Arena, workspace_view
|
||||||
Result = PushStruct(Arena, scene_nav_item_node);
|
Result = PushStruct(Arena, scene_nav_item_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result->HoverTextStringChunk = W_StringChunkAlloc(Arena, &Editor->FreeStrings);
|
||||||
|
Result->ActionStringChunk = W_StringChunkAlloc(Arena, &Editor->FreeStrings);
|
||||||
|
|
||||||
|
Result->Item.HoverText.Data = Result->HoverTextStringChunk->Data;
|
||||||
|
Result->Item.Action.Content.Data = Result->ActionStringChunk->Data;
|
||||||
|
|
||||||
DLLInsertLast(Editor->Items.First, Editor->Items.Last, Result);
|
DLLInsertLast(Editor->Items.First, Editor->Items.Last, Result);
|
||||||
Editor->Items.Count += 1;
|
Editor->Items.Count += 1;
|
||||||
return(Result);
|
return(Result);
|
||||||
|
@ -24,13 +105,109 @@ static scene_nav_item_node *W_SceneNavItemNodeAlloc(arena *Arena, workspace_view
|
||||||
|
|
||||||
static void W_SceneNavItemNodeRelease(workspace_view_nav_editor *Editor, scene_nav_item_node *Node)
|
static void W_SceneNavItemNodeRelease(workspace_view_nav_editor *Editor, scene_nav_item_node *Node)
|
||||||
{
|
{
|
||||||
|
W_StringChunkRelease(&Editor->FreeStrings, Node->HoverTextStringChunk);
|
||||||
|
W_StringChunkRelease(&Editor->FreeStrings, Node->ActionStringChunk);
|
||||||
|
DLLRemove(Editor->Items.First, Editor->Items.Last, Node);
|
||||||
DLLInsertLast(Editor->FirstFree, Editor->LastFree, Node);
|
DLLInsertLast(Editor->FirstFree, Editor->LastFree, Node);
|
||||||
Editor->Items.Count -= 1;
|
Editor->Items.Count -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void W_SetupNavEditor(workspace_view *View, string FileContents)
|
static void W_NavEditorInspectNode(workspace_view_nav_editor *Editor, scene_nav_item_node *Node)
|
||||||
{
|
{
|
||||||
//- sixten(TODO): deserialize data
|
Editor->SelectedItem = Node;
|
||||||
|
Editor->TextureDropdownOpen = false;
|
||||||
|
Editor->NavActionDropdownOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void W_NavEditorSetup(workspace_view *View, string FilePath, string FileName, string FileContents)
|
||||||
|
{
|
||||||
|
workspace_view_nav_editor *Editor = (workspace_view_nav_editor *)View->Data;
|
||||||
|
|
||||||
|
//- sixten: setup file info
|
||||||
|
Editor->FileName = PushString(View->Arena, FileName);
|
||||||
|
Editor->FilePath = PushString(View->Arena, FilePath);
|
||||||
|
|
||||||
|
//- sixten: deserialize data
|
||||||
|
if(FileContents.Count != 0)
|
||||||
|
{
|
||||||
|
u8 *DataBegin = FileContents.Data;
|
||||||
|
u8 *Byte = DataBegin;
|
||||||
|
|
||||||
|
u16 ItemCount = *(u16 *)Byte;
|
||||||
|
Byte += 2;
|
||||||
|
|
||||||
|
//- sixten: parse items
|
||||||
|
for(u64 ItemIndex = 0; ItemIndex < ItemCount; ItemIndex += 1)
|
||||||
|
{
|
||||||
|
scene_nav_item_node *Node = W_SceneNavItemNodeAlloc(View->Arena, Editor);
|
||||||
|
scene_nav_item *Item = &Node->Item;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
switch(*Byte++)
|
||||||
|
{
|
||||||
|
case S_NavItemOp_TextureID:
|
||||||
|
{
|
||||||
|
string AssetName;
|
||||||
|
AssetName.Count = *(u16 *)Byte;
|
||||||
|
Byte += sizeof(u16);
|
||||||
|
AssetName.Data = Byte;
|
||||||
|
Byte += AssetName.Count;
|
||||||
|
|
||||||
|
Item->TextureID = AssetID_Error;
|
||||||
|
for(u64 AssetIndex = 0; AssetIndex < AssetID_COUNT; AssetIndex += 1)
|
||||||
|
{
|
||||||
|
if(AreEqual(MakeString(AssetNameLUT[AssetIndex]), AssetName))
|
||||||
|
{
|
||||||
|
Item->TextureID = AssetIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_Scale:
|
||||||
|
{
|
||||||
|
Item->Scale = *(r32 *)Byte;
|
||||||
|
Byte += sizeof(r32);
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_Origin:
|
||||||
|
{
|
||||||
|
Item->Origin = *(v2_r32 *)Byte;
|
||||||
|
Byte += sizeof(v2_r32);
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_P:
|
||||||
|
{
|
||||||
|
Item->P = *(v2_r32 *)Byte;
|
||||||
|
Byte += sizeof(v2_r32);
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_HoverText:
|
||||||
|
{
|
||||||
|
Item->HoverText.Count = *(u16 *)Byte;
|
||||||
|
Byte += 2;
|
||||||
|
Assert(Item->HoverText.Count <= W_STRING_CHUNK_SIZE-2*sizeof(void *));
|
||||||
|
|
||||||
|
Copy(Item->HoverText.Data, Byte, Item->HoverText.Count);
|
||||||
|
Byte += Item->HoverText.Count;
|
||||||
|
} goto Next;
|
||||||
|
case S_NavItemOp_Action:
|
||||||
|
{
|
||||||
|
Item->Action.Kind = (scene_nav_action_kind)*Byte;
|
||||||
|
Byte += 1;
|
||||||
|
|
||||||
|
Item->Action.Content.Count = *(u16 *)Byte;
|
||||||
|
Byte += 2;
|
||||||
|
Assert(Item->Action.Content.Count <= W_STRING_CHUNK_SIZE-2*sizeof(void *));
|
||||||
|
|
||||||
|
Copy(Item->Action.Content.Data, Byte, Item->Action.Content.Count);
|
||||||
|
Byte += Item->Action.Content.Count;
|
||||||
|
} goto Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- sixten: no op found, assume item done
|
||||||
|
break;
|
||||||
|
|
||||||
|
Next:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void W_BuildNavEditor(workspace_view *View)
|
static void W_BuildNavEditor(workspace_view *View)
|
||||||
|
@ -41,70 +218,166 @@ static void W_BuildNavEditor(workspace_view *View)
|
||||||
UI_BackgroundColor(V4(0.25, 0.25, 0.25, 1))
|
UI_BackgroundColor(V4(0.25, 0.25, 0.25, 1))
|
||||||
UI_BorderColor(V4(0.45, 0.45, 0.45, 1))
|
UI_BorderColor(V4(0.45, 0.45, 0.45, 1))
|
||||||
UI_WidthFill UI_Height(UI_Em(2.0f, 1.0f))
|
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"))
|
UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, "Workspace Nav Editor Toolbar"))
|
||||||
{
|
{
|
||||||
UI_Width(UI_TextContent(10, 1.0f)) UI_Font(Font_Icons) if(UI_ButtonF("%U", FontIcon_UserPlus).Clicked)
|
UI_Width(UI_Em(2.0f, 1.0f)) UI_Font(Font_Icons) UI_CornerRadius(4.0f)
|
||||||
{
|
{
|
||||||
scene_nav_item_node *NewNode = W_SceneNavItemNodeAlloc(View->Arena, Editor);
|
//- sixten: create nav item button
|
||||||
NewNode->Item = G_DefaultSceneNavItem;
|
if(UI_ButtonF("%U", FontIcon_UserPlus).Clicked)
|
||||||
|
{
|
||||||
|
scene_nav_item_node *Node = W_SceneNavItemNodeAlloc(View->Arena, Editor);
|
||||||
|
|
||||||
|
//- sixten: apply default options
|
||||||
|
Node->Item.Scale = 0.01f;
|
||||||
|
Node->Item.Origin = V2R32(0.5, 1.0f);
|
||||||
|
Node->Item.P = V2R32(0.0, 0.0f);
|
||||||
|
Node->Item.TextureID = AssetID_ArthurNormal;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- sixten: create save nav items button
|
||||||
|
if(UI_ButtonF("%U", FontIcon_Floppy).Clicked)
|
||||||
|
{
|
||||||
|
W_NavEditorSerializeItems(Editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- sixten: create force reload
|
||||||
|
if(UI_ButtonF("%U", FontIcon_ArrowsCW).Clicked)
|
||||||
|
{
|
||||||
|
SV_LoadNavItems();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UI_Row()
|
UI_Row()
|
||||||
{
|
{
|
||||||
//- sixten: build inspector panel
|
//- sixten: build inspector panel
|
||||||
UI_Width(UI_Percent(0.2f, 1.0f)) UI_HeightFill
|
|
||||||
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBorder, StrLit("Workspace Nav Editor Inspector")))
|
|
||||||
{
|
|
||||||
scene_nav_item_node *SelectedItem = Editor->SelectedItem;
|
scene_nav_item_node *SelectedItem = Editor->SelectedItem;
|
||||||
|
UI_SetNextLayoutAxis(Axis2_X);
|
||||||
|
UI_Width(UI_Em(24.0f*AC_AnimateValueF(SelectedItem != 0, 0, 0.3f, "Workspace Nav Editor Inspector %p", Editor), 1.0f)) UI_HeightFill
|
||||||
|
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBorder, StrLit("Workspace Nav Editor Inspector")))
|
||||||
|
UI_Padding(UI_Em(1, 1)) UI_Width(UI_Percent(1.0f, 0.0f)) UI_Column()
|
||||||
|
{
|
||||||
if(SelectedItem)
|
if(SelectedItem)
|
||||||
{
|
{
|
||||||
}
|
UI_CornerRadius(4.0f) UI_Width(UI_Percent(1, 1)) UI_Height(UI_TextContent(15, 1))
|
||||||
else UI_WidthFill
|
|
||||||
{
|
{
|
||||||
UI_LabelF("No item selected.");
|
//- sixten: inspect position
|
||||||
|
UI_Row() UI_Width(UI_Percent(0.5f, 1.0f)) {UI_LabelF("Position X:"); UI_Font(Font_Monospace) UI_LabelF("%f", SelectedItem->Item.P.x);}
|
||||||
|
UI_Row() UI_Width(UI_Percent(0.5f, 1.0f)) {UI_LabelF("Position Y:"); UI_Font(Font_Monospace) UI_LabelF("%f", SelectedItem->Item.P.y);}
|
||||||
|
|
||||||
|
//- sixten: inspect scale
|
||||||
|
UI_Row() UI_Width(UI_Percent(0.5f, 1.0f))
|
||||||
|
{
|
||||||
|
UI_LabelF("Scale:");
|
||||||
|
UI_Font(Font_Monospace)
|
||||||
|
{
|
||||||
|
UI_SetNextHoverCursor(PlatformCursor_ArrowHorizontal);
|
||||||
|
ui_box *ScaleBox = UI_MakeBoxF(UI_BoxFlag_Clickable|UI_BoxFlag_DrawText, "%f##Scale", SelectedItem->Item.Scale);
|
||||||
|
|
||||||
|
ui_signal ScaleSignal = UI_SignalFromBox(ScaleBox);
|
||||||
|
if(ScaleSignal.Dragging)
|
||||||
|
{
|
||||||
|
if(ScaleSignal.Pressed)
|
||||||
|
{
|
||||||
|
UI_StoreDragR32(SelectedItem->Item.Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedItem->Item.Scale = UI_GetDragR32() + ScaleSignal.DragDelta.x*0.001f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- sixten: inspect texture
|
||||||
|
UI_Row(0, StrLit("Texture")) UI_Width(UI_Percent(0.5f, 1.0f))
|
||||||
|
{
|
||||||
|
UI_LabelF("Texture:");
|
||||||
|
UI_DropdownSelection(AssetNameLUT, ArrayCount(AssetNameLUT), &Editor->TextureDropdownOpen, &SelectedItem->Item.TextureID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- sixten: inspect nav action kind
|
||||||
|
UI_Row(0, StrLit("Nav Action")) UI_Width(UI_Percent(0.5f, 1.0f))
|
||||||
|
{
|
||||||
|
UI_LabelF("Nav Action Type:");
|
||||||
|
char *Actions[] = { "None", "Trigger Proc", "Change Scene" };
|
||||||
|
UI_DropdownSelection(Actions, ArrayCount(Actions), &Editor->NavActionDropdownOpen, (s32 *)&SelectedItem->Item.Action);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- sixten: inspect nav action contents
|
||||||
|
UI_Row(0, StrLit("Nav Action String")) UI_Width(UI_Percent(0.5f, 1.0f))
|
||||||
|
{
|
||||||
|
UI_LabelF("Nav Action Contents:");
|
||||||
|
ui_signal Signal = UI_LineEdit(&Editor->NavActionStringEditState, ArrayCount(SelectedItem->ActionStringChunk->Data), SelectedItem->ActionStringChunk->Data, &SelectedItem->Item.Action.Content.Count, StrLit("Nav Action Text"), Editor->ActiveTextThing == 1);
|
||||||
|
if(AreEqual(UI_ActiveKey(), Signal.Box->Key))
|
||||||
|
{
|
||||||
|
Editor->ActiveTextThing = 1;
|
||||||
|
}
|
||||||
|
else if(!AreEqual(UI_ActiveKey(), UI_EmptyKey()) && Editor->ActiveTextThing == 1)
|
||||||
|
{
|
||||||
|
Editor->ActiveTextThing = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- sixten: inspect hover text
|
||||||
|
UI_Row(0, StrLit("Hover Text")) UI_Width(UI_Percent(0.5f, 1.0f))
|
||||||
|
{
|
||||||
|
UI_LabelF("Hover Text:");
|
||||||
|
ui_signal Signal = UI_LineEdit(&Editor->HoverTextEditState, ArrayCount(SelectedItem->HoverTextStringChunk->Data), SelectedItem->HoverTextStringChunk->Data, &SelectedItem->Item.HoverText.Count, StrLit("Hover Text Input"), Editor->ActiveTextThing == 2);
|
||||||
|
if(AreEqual(UI_ActiveKey(), Signal.Box->Key))
|
||||||
|
{
|
||||||
|
Editor->ActiveTextThing = 2;
|
||||||
|
}
|
||||||
|
else if(!AreEqual(UI_ActiveKey(), UI_EmptyKey()) && Editor->ActiveTextThing == 2)
|
||||||
|
{
|
||||||
|
Editor->ActiveTextThing = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Spacer(UI_TextContent(15, 1));
|
||||||
|
|
||||||
|
UI_Row() UI_FillPadding
|
||||||
|
{
|
||||||
|
UI_Width(UI_TextContent(15, 1)) if(UI_ButtonF("Remove Item").Pressed)
|
||||||
|
{
|
||||||
|
W_SceneNavItemNodeRelease(Editor, SelectedItem);
|
||||||
|
Editor->SelectedItem = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- sixten: build nav view
|
//- sixten: build nav view
|
||||||
UI_Row()
|
UI_Width(UI_Percent(1, 0)) UI_Height(UI_Percent(1, 0)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_Clip, "Workspace View Nav Editor Thing"))
|
||||||
{
|
{
|
||||||
//- sixten: calculate nav view size
|
//- sixten: calculate nav view size
|
||||||
r32 VerticalPad = 0;
|
v2_r32 ParentDim = DimOfRange(UI_TopParent()->Rect);
|
||||||
r32 HorizontalPad = 0;
|
v2_r32 BoxDim = ParentDim;
|
||||||
{
|
|
||||||
ui_box *ParentBox = UI_TopParent();
|
|
||||||
v2_r32 ParentDim = DimOfRange(ParentBox->Rect);
|
|
||||||
|
|
||||||
r32 WidthOverHeight = ParentDim.x / ParentDim.y;
|
|
||||||
r32 TargetRatio = 16.0f/9.0f;
|
r32 TargetRatio = 16.0f/9.0f;
|
||||||
if(WidthOverHeight > TargetRatio)
|
r32 ActualRatio = ParentDim.x/ParentDim.y;
|
||||||
|
|
||||||
|
if(ActualRatio>TargetRatio)
|
||||||
{
|
{
|
||||||
VerticalPad = ParentDim.x - ParentDim.y*TargetRatio;
|
BoxDim.x = BoxDim.y*TargetRatio;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HorizontalPad = ParentDim.y - ParentDim.x/TargetRatio;
|
BoxDim.y = BoxDim.x/TargetRatio;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
//- sixten: do the building of the nav view
|
|
||||||
UI_Padding(UI_Pixels(VerticalPad/2, 1))
|
|
||||||
{
|
|
||||||
UI_Column() UI_Padding(UI_Pixels(HorizontalPad/2, 1))
|
|
||||||
{
|
|
||||||
UI_SetNextWidth(UI_Percent(1, 0));
|
|
||||||
UI_SetNextHeight(UI_Percent(1, 0));
|
|
||||||
UI_SetNextLayoutAxis(Axis2_Y);
|
|
||||||
|
|
||||||
ui_box *Box = UI_MakeBox(UI_BoxFlag_Clip, StrLit("Nav View"));
|
UI_SetNextWidth(UI_Pixels(BoxDim.x, 1));
|
||||||
|
UI_SetNextHeight(UI_Pixels(BoxDim.y, 1));
|
||||||
|
UI_SetNextLayoutAxis(Axis2_Y);
|
||||||
|
UI_SetNextFixedP((ParentDim-BoxDim)*0.5f);
|
||||||
|
ui_box *Box = UI_MakeBoxF(UI_BoxFlag_Clip|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY|UI_BoxFlag_Clickable, "Nav View %p", View);
|
||||||
UI_EquipBoxCustomDrawCallback(Box, BuildNavViewDrawCallback, SceneView);
|
UI_EquipBoxCustomDrawCallback(Box, BuildNavViewDrawCallback, SceneView);
|
||||||
|
|
||||||
v2_r32 BoxDim = UI_CalculateBoxDim(Box);
|
|
||||||
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
|
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
|
||||||
|
|
||||||
//- sixten: build all nav items
|
//- sixten: build all nav items
|
||||||
s32 ItemIndex = 0;
|
s32 ItemIndex = 0;
|
||||||
for(scene_nav_item_node *Node = Editor->Items.First; Node != 0; Node = Node->Next, ItemIndex += 1)
|
UI_Parent(Box) for(scene_nav_item_node *Node = Editor->Items.First; Node != 0; Node = Node->Next, ItemIndex += 1)
|
||||||
{
|
{
|
||||||
scene_nav_item *Item = &Node->Item;
|
scene_nav_item *Item = &Node->Item;
|
||||||
|
|
||||||
|
@ -122,19 +395,24 @@ static void W_BuildNavEditor(workspace_view *View)
|
||||||
|
|
||||||
UI_SetNextHoverCursor(PlatformCursor_Hand);
|
UI_SetNextHoverCursor(PlatformCursor_Hand);
|
||||||
UI_SetNextSize(UI_Pixels(Dim.x, 1), UI_Pixels(Dim.y, 1));
|
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,
|
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);
|
UI_EquipBoxCustomDrawCallback(ItemBox, BuildNavItemDrawCallback, Data);
|
||||||
|
|
||||||
|
if(Node == Editor->SelectedItem)
|
||||||
|
{
|
||||||
|
// sixten(TODO): this:
|
||||||
|
//ui_box *OriginBox = UI_MakeBoxF(UI_BoxFlag_Clickable|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, "View Item Origin Box %i", ItemIndex);
|
||||||
|
}
|
||||||
//- sixten: handle signals
|
//- sixten: handle signals
|
||||||
{
|
{
|
||||||
ui_signal Signal = UI_SignalFromBox(ItemBox);
|
ui_signal Signal = UI_SignalFromBox(ItemBox);
|
||||||
Data->Signal = Signal;
|
Data->Signal = Signal;
|
||||||
|
|
||||||
//- sixten: inspect pressed item
|
//- sixten: inspect pressed item
|
||||||
if(Signal.Pressed)
|
if(Signal.Clicked && Signal.DragDelta == V2R32(0, 0))
|
||||||
{
|
{
|
||||||
Editor->SelectedItem = Node;
|
W_NavEditorInspectNode(Editor, Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- sixten: handle dragging
|
//- sixten: handle dragging
|
||||||
|
@ -153,7 +431,11 @@ static void W_BuildNavEditor(workspace_view *View)
|
||||||
v2_r32 OffsetP = BoxDim*(V2R32(1, 1) + Item->P)*0.5f;
|
v2_r32 OffsetP = BoxDim*(V2R32(1, 1) + Item->P)*0.5f;
|
||||||
ItemBox->FixedP = (OffsetP-OriginP);
|
ItemBox->FixedP = (OffsetP-OriginP);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
ui_signal BackgroundSignal = UI_SignalFromBox(Box);
|
||||||
|
if(BackgroundSignal.Pressed)
|
||||||
|
{
|
||||||
|
W_NavEditorInspectNode(Editor, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,28 @@
|
||||||
#ifndef VN_WORKSPACE_NAV_EDITOR_H
|
#ifndef VN_WORKSPACE_NAV_EDITOR_H
|
||||||
#define VN_WORKSPACE_NAV_EDITOR_H
|
#define VN_WORKSPACE_NAV_EDITOR_H
|
||||||
|
|
||||||
|
#define W_STRING_CHUNK_SIZE 128
|
||||||
|
|
||||||
|
struct workspace_string_chunk
|
||||||
|
{
|
||||||
|
workspace_string_chunk *Next;
|
||||||
|
workspace_string_chunk *Prev;
|
||||||
|
u8 Data[W_STRING_CHUNK_SIZE - 2*sizeof(workspace_string_chunk *)];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct workspace_string_chunk_list
|
||||||
|
{
|
||||||
|
workspace_string_chunk *First;
|
||||||
|
workspace_string_chunk *Last;
|
||||||
|
};
|
||||||
|
|
||||||
struct scene_nav_item_node
|
struct scene_nav_item_node
|
||||||
{
|
{
|
||||||
scene_nav_item_node *Next;
|
scene_nav_item_node *Next;
|
||||||
scene_nav_item_node *Prev;
|
scene_nav_item_node *Prev;
|
||||||
|
|
||||||
|
workspace_string_chunk *HoverTextStringChunk;
|
||||||
|
workspace_string_chunk *ActionStringChunk;
|
||||||
scene_nav_item Item;
|
scene_nav_item Item;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,13 +42,29 @@ struct workspace_view_nav_editor
|
||||||
scene_nav_item_node *FirstFree;
|
scene_nav_item_node *FirstFree;
|
||||||
scene_nav_item_node *LastFree;
|
scene_nav_item_node *LastFree;
|
||||||
|
|
||||||
|
//- sixten: strings
|
||||||
|
workspace_string_chunk_list FreeStrings;
|
||||||
|
|
||||||
|
//- sixten: inspect info
|
||||||
scene_nav_item_node *SelectedItem;
|
scene_nav_item_node *SelectedItem;
|
||||||
|
b32 TextureDropdownOpen;
|
||||||
|
b32 NavActionDropdownOpen;
|
||||||
|
text_edit_state NavActionStringEditState;
|
||||||
|
text_edit_state HoverTextEditState;
|
||||||
|
s32 ActiveTextThing;
|
||||||
|
|
||||||
|
//- sixten: file info
|
||||||
|
string FileName;
|
||||||
|
string FilePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void W_NavEditorSerializeItems(workspace_view_nav_editor *Editor);
|
||||||
|
|
||||||
static scene_nav_item_node *W_SceneNavItemNodeAlloc(arena *Arena, workspace_view_nav_editor *Editor);
|
static scene_nav_item_node *W_SceneNavItemNodeAlloc(arena *Arena, workspace_view_nav_editor *Editor);
|
||||||
static void W_SceneNavItemNodeRelease(workspace_view_nav_editor *Editor, scene_nav_item_node *Node);
|
static void W_SceneNavItemNodeRelease(workspace_view_nav_editor *Editor, scene_nav_item_node *Node);
|
||||||
|
|
||||||
static void W_SetupNavEditor(workspace_view *View, string FileContents);
|
static void W_NavEditorInspectNode(scene_nav_item_node *Node);
|
||||||
|
static void W_NavEditorSetup(workspace_view *View, string FilePath, string FileName, string FileContents);
|
||||||
static void W_BuildNavEditor(workspace_view *View);
|
static void W_BuildNavEditor(workspace_view *View);
|
||||||
|
|
||||||
#endif //VN_WORKSPACE_NAV_EDITOR_H
|
#endif //VN_WORKSPACE_NAV_EDITOR_H
|
||||||
|
|
|
@ -64,7 +64,7 @@ static void AppendToHistory(arena *Arena, history_list *List, history_entry Forw
|
||||||
|
|
||||||
static workspace_text_data W_TextDataFromString(arena *Arena, string Text)
|
static workspace_text_data W_TextDataFromString(arena *Arena, string Text)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch(&Arena, 1);
|
temp Scratch = GetScratch(&Arena, 1);
|
||||||
|
|
||||||
//- sixten: clear the target arena
|
//- sixten: clear the target arena
|
||||||
ArenaClear(Arena);
|
ArenaClear(Arena);
|
||||||
|
@ -116,7 +116,7 @@ static void W_TextEditorApplyChanges(workspace_view_text_editor *Editor)
|
||||||
|
|
||||||
static void W_SaveTextEditorToFile(workspace_view_text_editor *Editor)
|
static void W_SaveTextEditorToFile(workspace_view_text_editor *Editor)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
|
|
||||||
if(Editor->SavePoint != Editor->History.At)
|
if(Editor->SavePoint != Editor->History.At)
|
||||||
{
|
{
|
||||||
|
@ -138,7 +138,7 @@ static void W_SaveTextEditorToFile(workspace_view_text_editor *Editor)
|
||||||
|
|
||||||
static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback)
|
static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
workspace_view_text_editor *Editor = (workspace_view_text_editor *)Data;
|
workspace_view_text_editor *Editor = (workspace_view_text_editor *)Data;
|
||||||
|
|
||||||
//- sixten: get dimensions & scroll offset from container
|
//- sixten: get dimensions & scroll offset from container
|
||||||
|
@ -380,7 +380,7 @@ static UI_CUSTOM_DRAW_CALLBACK(W_TextEditorDrawCallback)
|
||||||
static b32 W_ProcessTextEditorEvent(workspace_view_text_editor *Editor, platform_event *Event)
|
static b32 W_ProcessTextEditorEvent(workspace_view_text_editor *Editor, platform_event *Event)
|
||||||
{
|
{
|
||||||
b32 CursorHasBeenModified = false;
|
b32 CursorHasBeenModified = false;
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
text_action Action = MultiLineTextActionFromEvent(Event);
|
text_action Action = MultiLineTextActionFromEvent(Event);
|
||||||
if(IsValid(&Action))
|
if(IsValid(&Action))
|
||||||
{
|
{
|
||||||
|
@ -439,7 +439,7 @@ static void W_BuildTextEditor(workspace_view *View)
|
||||||
{
|
{
|
||||||
workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data;
|
workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data;
|
||||||
|
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
|
|
||||||
//- sixten: rendering properties
|
//- sixten: rendering properties
|
||||||
r32 FontSize = Editor->FontSize = 13.0f;
|
r32 FontSize = Editor->FontSize = 13.0f;
|
||||||
|
|
|
@ -18,6 +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);
|
workspace_view_file_lister *Lister = PushStruct(View->Arena, workspace_view_file_lister);
|
||||||
View->Data = Lister;
|
View->Data = Lister;
|
||||||
|
Lister->Path = StrLit("data");
|
||||||
|
|
||||||
Lister->SelectedItem = -1;
|
Lister->SelectedItem = -1;
|
||||||
} break;
|
} break;
|
||||||
|
@ -45,6 +46,17 @@ inline workspace_view *W_CreateNewView(workspace_view_kind Kind, workspace_panel
|
||||||
View->Data = PushStruct(View->Arena, workspace_view_nav_editor);
|
View->Data = PushStruct(View->Arena, workspace_view_nav_editor);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case W_ViewKind_ImageViewer:
|
||||||
|
{
|
||||||
|
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:
|
case W_ViewKind_Error:
|
||||||
{
|
{
|
||||||
View->Data = PushStruct(View->Arena, workspace_view_error);
|
View->Data = PushStruct(View->Arena, workspace_view_error);
|
||||||
|
@ -75,6 +87,12 @@ inline void W_DestroyView(workspace_view *View)
|
||||||
ArenaRelease(Editor->HistoryArena);
|
ArenaRelease(Editor->HistoryArena);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case W_ViewKind_ImageViewer:
|
||||||
|
{
|
||||||
|
workspace_view_image_viewer *Viewer = (workspace_view_image_viewer *)View->Data;
|
||||||
|
GlobalRenderCommands->DeallocateTexture(Viewer->Texture);
|
||||||
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +108,7 @@ inline b32 W_ViewIsCurrent(workspace_view *View)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline string W_GetViewName(arena *Arena, workspace_view *View)
|
inline string W_NameFromView(arena *Arena, workspace_view *View)
|
||||||
{
|
{
|
||||||
string Result = StrLit("Unnamed view");
|
string Result = StrLit("Unnamed view");
|
||||||
switch(View->Kind)
|
switch(View->Kind)
|
||||||
|
@ -106,7 +124,6 @@ inline string W_GetViewName(arena *Arena, workspace_view *View)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//if(Editor->History.At == &Editor->History.Sentinel)
|
|
||||||
if(Editor->History.At == Editor->SavePoint)
|
if(Editor->History.At == Editor->SavePoint)
|
||||||
{
|
{
|
||||||
Result = PushString(Arena, Editor->FileName);
|
Result = PushString(Arena, Editor->FileName);
|
||||||
|
@ -120,6 +137,11 @@ inline string W_GetViewName(arena *Arena, workspace_view *View)
|
||||||
case W_ViewKind_SceneView: { Result = StrLit("Scene View"); } break;
|
case W_ViewKind_SceneView: { Result = StrLit("Scene View"); } break;
|
||||||
case W_ViewKind_NavEditor: { Result = StrLit("Navigation Editor"); } break;
|
case W_ViewKind_NavEditor: { Result = StrLit("Navigation Editor"); } break;
|
||||||
case W_ViewKind_FileLister: { Result = StrLit("File Lister"); } break;
|
case W_ViewKind_FileLister: { Result = StrLit("File Lister"); } break;
|
||||||
|
case W_ViewKind_ImageViewer:
|
||||||
|
{
|
||||||
|
workspace_view_image_viewer *Viewer = (workspace_view_image_viewer *)View->Data;
|
||||||
|
Result = PushString(Arena, Viewer->FileName);
|
||||||
|
} break;
|
||||||
case W_ViewKind_Error: { Result = StrLit("Error"); } break;
|
case W_ViewKind_Error: { Result = StrLit("Error"); } break;
|
||||||
default: {} break;
|
default: {} break;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +149,38 @@ inline string W_GetViewName(arena *Arena, workspace_view *View)
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static b32 W_ImageViewerSetup(workspace_view *View, string Name, string Contents)
|
||||||
|
{
|
||||||
|
b32 Result = false;
|
||||||
|
workspace_view_image_viewer *Viewer = (workspace_view_image_viewer *)View->Data;
|
||||||
|
Viewer->Texture = EmptyRenderHandle();
|
||||||
|
if(Contents.Count && Contents.Data)
|
||||||
|
{
|
||||||
|
s32 Width, Height, BPP;
|
||||||
|
u8 *TextureData = stbi_load_from_memory(Contents.Data, Contents.Count, &Width, &Height, &BPP, 0);
|
||||||
|
if(TextureData)
|
||||||
|
{
|
||||||
|
render_texture_format TextureFormat = Render_TextureFormat_Invalid;
|
||||||
|
switch(BPP)
|
||||||
|
{
|
||||||
|
InvalidDefaultCase;
|
||||||
|
case 1: { TextureFormat = Render_TextureFormat_R8; } break;
|
||||||
|
case 3: { TextureFormat = Render_TextureFormat_RGB8; } break;
|
||||||
|
case 4: { TextureFormat = Render_TextureFormat_RGBA8; } break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Viewer->Texture = GlobalRenderCommands->AllocateTexture(V2S32(Width, Height), TextureFormat, true, TextureData);
|
||||||
|
|
||||||
|
Result = true;
|
||||||
|
|
||||||
|
stbi_image_free(TextureData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Viewer->FileName = PushString(View->Arena, Name);
|
||||||
|
|
||||||
|
return(Result);
|
||||||
|
}
|
||||||
|
|
||||||
//- sixten: Builder code
|
//- sixten: Builder code
|
||||||
|
|
||||||
static void W_BuildSettingsTabButton(workspace_view_settings *Settings, char *Name, workspace_settings_category Category)
|
static void W_BuildSettingsTabButton(workspace_view_settings *Settings, char *Name, workspace_settings_category Category)
|
||||||
|
@ -157,17 +211,8 @@ static void W_BuildSettingsTabButton(workspace_view_settings *Settings, char *Na
|
||||||
static b32 UI_DropdownSelection(char **Alternatives, s32 AlternativeCount, b32 *Open, s32 *Selected)
|
static b32 UI_DropdownSelection(char **Alternatives, s32 AlternativeCount, b32 *Open, s32 *Selected)
|
||||||
{
|
{
|
||||||
b32 Result = false;
|
b32 Result = false;
|
||||||
|
|
||||||
UI_SetNextLayoutAxis(Axis2_X);
|
|
||||||
UI_Parent(UI_MakeBoxF(0, ""))
|
|
||||||
{
|
|
||||||
UI_LabelF("Refresh Rate:");
|
|
||||||
UI_Spacer(UI_Pixels(10, 1));
|
|
||||||
|
|
||||||
b32 ActiveInDropdown = false;
|
b32 ActiveInDropdown = false;
|
||||||
|
|
||||||
UI_SetNextWidth(UI_Pixels(200, 1));
|
|
||||||
UI_SetNextCornerRadius(4);
|
|
||||||
UI_SetNextLayoutAxis(Axis2_X);
|
UI_SetNextLayoutAxis(Axis2_X);
|
||||||
ui_box *DropdownBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
|
ui_box *DropdownBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
|
||||||
UI_BoxFlag_DrawBorder |
|
UI_BoxFlag_DrawBorder |
|
||||||
|
@ -179,7 +224,7 @@ static b32 UI_DropdownSelection(char **Alternatives, s32 AlternativeCount, b32 *
|
||||||
{
|
{
|
||||||
UI_Width(UI_Percent(1, 0)) UI_LabelF(Alternatives[*Selected]);
|
UI_Width(UI_Percent(1, 0)) UI_LabelF(Alternatives[*Selected]);
|
||||||
UI_BackgroundColor(Theme_BorderColor) UI_Width(UI_Pixels(1, 1)) UI_MakeBoxF(UI_BoxFlag_DrawBackground, "");
|
UI_BackgroundColor(Theme_BorderColor) UI_Width(UI_Pixels(1, 1)) UI_MakeBoxF(UI_BoxFlag_DrawBackground, "");
|
||||||
UI_Width(UI_Pixels(25, 1)) UI_Font(Font_Icons) UI_LabelF("%U", FontIcon_DownDir);
|
UI_Width(UI_Pixels(25, 1)) UI_Font(Font_Icons) UI_LabelF("%U", *Open?FontIcon_DownDir:FontIcon_RightDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_signal DropdownSignal = UI_SignalFromBox(DropdownBox);
|
ui_signal DropdownSignal = UI_SignalFromBox(DropdownBox);
|
||||||
|
@ -206,7 +251,7 @@ static b32 UI_DropdownSelection(char **Alternatives, s32 AlternativeCount, b32 *
|
||||||
UI_Parent(UI_MakeBoxF(UI_BoxFlag_Clip |
|
UI_Parent(UI_MakeBoxF(UI_BoxFlag_Clip |
|
||||||
UI_BoxFlag_DrawDropShadow |
|
UI_BoxFlag_DrawDropShadow |
|
||||||
UI_BoxFlag_FloatingX |
|
UI_BoxFlag_FloatingX |
|
||||||
UI_BoxFlag_FloatingY, "Dropdown Contents"))
|
UI_BoxFlag_FloatingY, "Dropdown Contents %p%p", Alternatives, Open))
|
||||||
{
|
{
|
||||||
UI_PushWidth(UI_Percent(1, 1));
|
UI_PushWidth(UI_Percent(1, 1));
|
||||||
|
|
||||||
|
@ -236,11 +281,77 @@ static b32 UI_DropdownSelection(char **Alternatives, s32 AlternativeCount, b32 *
|
||||||
{
|
{
|
||||||
*Open = false;
|
*Open = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UI_CUSTOM_DRAW_CALLBACK(W_ImageViewerUICallback)
|
||||||
|
{
|
||||||
|
workspace_view_image_viewer *Viewer = (workspace_view_image_viewer *)Data;
|
||||||
|
v2_r32 ImageDim = ConvertV2ToR32(DimFromTexture(Viewer->Texture));
|
||||||
|
v2_r32 ScaleImageDim = ImageDim*Viewer->Scale;
|
||||||
|
|
||||||
|
v4 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void W_BuildImageViewer(workspace_view *View)
|
||||||
|
{
|
||||||
|
workspace_view_image_viewer *Viewer = (workspace_view_image_viewer *)View->Data;
|
||||||
|
|
||||||
|
//- sixten: find image dim
|
||||||
|
v2_r32 ImageDim = ConvertV2ToR32(DimFromTexture(Viewer->Texture));
|
||||||
|
|
||||||
|
UI_WidthFill UI_HeightFill
|
||||||
|
{
|
||||||
|
ui_box *ImageBox = UI_MakeBoxF(UI_BoxFlag_DrawBorder|UI_BoxFlag_Clickable, "Workspace View Image Viewer %p", View);
|
||||||
|
UI_EquipBoxCustomDrawCallback(ImageBox, W_ImageViewerUICallback, Viewer);
|
||||||
|
|
||||||
|
//- sixten: handle scrolling
|
||||||
|
if(AreEqual(UI_HotKey(), ImageBox->Key))
|
||||||
|
{
|
||||||
|
for(platform_event *Event = UI_EventList()->First;
|
||||||
|
Event != 0;
|
||||||
|
Event = Event->Next)
|
||||||
|
{
|
||||||
|
if(Event->Type == PlatformEvent_MouseScroll && Event->Scroll.y != 0)
|
||||||
|
{
|
||||||
|
Viewer->Scale *= Pow(1.10f, Event->Scroll.y);
|
||||||
|
Platform_ConsumeEvent(UI_EventList(), Event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_signal Signal = UI_SignalFromBox(ImageBox);
|
||||||
|
if(Signal.Dragging)
|
||||||
|
{
|
||||||
|
if(Signal.Pressed)
|
||||||
|
{
|
||||||
|
UI_StoreDragV2(Viewer->Offset);
|
||||||
|
}
|
||||||
|
v2_r32 StartOffset = UI_GetDragV2();
|
||||||
|
v2_r32 EndOffset = StartOffset+Signal.DragDelta*(1.0f/Viewer->Scale);
|
||||||
|
|
||||||
|
Viewer->Offset = EndOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UI_WidthFill UI_Height(UI_Em(3, 1))
|
||||||
|
UI_Row(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder)
|
||||||
|
{
|
||||||
|
UI_Width(UI_TextContent(15, 1))
|
||||||
|
{
|
||||||
|
UI_Label(Viewer->FileName);
|
||||||
|
UI_LabelF("Width: %i Height: %i", (int)ImageDim.x, (int)ImageDim.y);
|
||||||
|
}
|
||||||
|
UI_Spacer(UI_Percent(1, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void W_BuildSceneView(workspace_view *View)
|
static void W_BuildSceneView(workspace_view *View)
|
||||||
{
|
{
|
||||||
workspace *Workspace = W_GetState();
|
workspace *Workspace = W_GetState();
|
||||||
|
@ -307,12 +418,20 @@ static void W_BuildSettings(workspace_view *View)
|
||||||
s32 DropdownSelected;
|
s32 DropdownSelected;
|
||||||
FindIndexOfElement(DropdownSelected, AlternativeMapping, 0, Workspace->Input->RefreshRate);
|
FindIndexOfElement(DropdownSelected, AlternativeMapping, 0, Workspace->Input->RefreshRate);
|
||||||
|
|
||||||
|
UI_Row()
|
||||||
|
{
|
||||||
|
UI_LabelF("Refresh Rate:");
|
||||||
|
UI_Spacer(UI_Pixels(10, 1));
|
||||||
|
|
||||||
|
UI_SetNextWidth(UI_Pixels(200, 1));
|
||||||
|
UI_SetNextCornerRadius(4);
|
||||||
if(UI_DropdownSelection(Alternatives, ArrayCount(Alternatives),
|
if(UI_DropdownSelection(Alternatives, ArrayCount(Alternatives),
|
||||||
&Settings->GeneralDropdownOpen, &DropdownSelected))
|
&Settings->GeneralDropdownOpen, &DropdownSelected))
|
||||||
{
|
{
|
||||||
Workspace->Input->RefreshRate = AlternativeMapping[DropdownSelected];
|
Workspace->Input->RefreshRate = AlternativeMapping[DropdownSelected];
|
||||||
Settings->GeneralDropdownOpen = false;
|
Settings->GeneralDropdownOpen = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UI_Spacer(UI_Pixels(50, 1));
|
UI_Spacer(UI_Pixels(50, 1));
|
||||||
}
|
}
|
||||||
|
@ -379,6 +498,11 @@ static void W_BuildView(workspace_view *View)
|
||||||
W_BuildSettings(View);
|
W_BuildSettings(View);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case W_ViewKind_ImageViewer:
|
||||||
|
{
|
||||||
|
W_BuildImageViewer(View);
|
||||||
|
} break;
|
||||||
|
|
||||||
case W_ViewKind_TextEditor:
|
case W_ViewKind_TextEditor:
|
||||||
{
|
{
|
||||||
W_BuildTextEditor(View);
|
W_BuildTextEditor(View);
|
||||||
|
|
|
@ -27,6 +27,7 @@ enum workspace_view_kind
|
||||||
W_ViewKind_TextEditor,
|
W_ViewKind_TextEditor,
|
||||||
W_ViewKind_SceneView,
|
W_ViewKind_SceneView,
|
||||||
W_ViewKind_NavEditor,
|
W_ViewKind_NavEditor,
|
||||||
|
W_ViewKind_ImageViewer,
|
||||||
W_ViewKind_Error,
|
W_ViewKind_Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,6 +52,14 @@ struct workspace_view_settings
|
||||||
b32 GeneralDropdownOpen;
|
b32 GeneralDropdownOpen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct workspace_view_image_viewer
|
||||||
|
{
|
||||||
|
string FileName;
|
||||||
|
render_handle Texture;
|
||||||
|
r32 Scale;
|
||||||
|
v2_r32 Offset;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ sixten: Workspace View Functions
|
//~ sixten: Workspace View Functions
|
||||||
|
|
||||||
|
@ -58,11 +67,18 @@ struct workspace_view_settings
|
||||||
inline workspace_view *W_CreateNewView(workspace_view_kind Type, workspace_panel *Parent);
|
inline workspace_view *W_CreateNewView(workspace_view_kind Type, workspace_panel *Parent);
|
||||||
inline void W_DestroyView(workspace_view *View);
|
inline void W_DestroyView(workspace_view *View);
|
||||||
inline b32 W_ViewIsCurrent(workspace_view *View);
|
inline b32 W_ViewIsCurrent(workspace_view *View);
|
||||||
inline string W_GetViewName(arena *Arena, workspace_view *View);
|
inline string W_NameFromView(arena *Arena, workspace_view *View);
|
||||||
|
|
||||||
//- sixten: Builder code
|
//- sixten: Builder code
|
||||||
static void W_ViewListerInputCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data);
|
static void W_ViewListerInputCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data);
|
||||||
static void W_BuildViewTypeLister(workspace_view *View);
|
static void W_BuildViewTypeLister(workspace_view *View);
|
||||||
static void W_BuildView(workspace_view *View);
|
static void W_BuildView(workspace_view *View);
|
||||||
|
|
||||||
|
//- sixten: View Implementations
|
||||||
|
static b32 W_ImageViewerSetup(workspace_view *View, string Name, string Contents);
|
||||||
|
static void W_BuildImageViewer(workspace_view *View);
|
||||||
|
static void W_BuildSceneView(workspace_view *View);
|
||||||
|
static void W_BuildSettings(workspace_view *View);
|
||||||
|
|
||||||
|
|
||||||
#endif //VN_WORKSPACE_VIEW_H
|
#endif //VN_WORKSPACE_VIEW_H
|
||||||
|
|
|
@ -114,7 +114,7 @@ static PLATFORM_OPEN_FILE(Win32_OpenFile)
|
||||||
CreationAttributes = CREATE_ALWAYS;
|
CreationAttributes = CREATE_ALWAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
|
|
||||||
string FullPath = PushFormat(Scratch.Arena, "%S\\%S", Global_Win32State.ContentsPath, Path);
|
string FullPath = PushFormat(Scratch.Arena, "%S\\%S", Global_Win32State.ContentsPath, Path);
|
||||||
HANDLE File = CreateFileA((char *)FullPath.Data, DesiredAccess, 0, 0, CreationAttributes, 0, 0);
|
HANDLE File = CreateFileA((char *)FullPath.Data, DesiredAccess, 0, 0, CreationAttributes, 0, 0);
|
||||||
|
@ -145,7 +145,7 @@ static PLATFORM_READ_FILE(Win32_ReadFile)
|
||||||
DWORD BytesRead;
|
DWORD BytesRead;
|
||||||
ReadFile(File, Dest, Size, &BytesRead, 0);
|
ReadFile(File, Dest, Size, &BytesRead, 0);
|
||||||
|
|
||||||
Assert(BytesRead == Size);
|
//Assert(BytesRead == Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ static PLATFORM_SET_CURSOR(Win32_SetCursor)
|
||||||
static PLATFORM_BEGIN_FILE_ITER(Win32_BeginFileIter)
|
static PLATFORM_BEGIN_FILE_ITER(Win32_BeginFileIter)
|
||||||
{
|
{
|
||||||
win32_file_find_data *FileFindData = PushStruct(Arena, win32_file_find_data);
|
win32_file_find_data *FileFindData = PushStruct(Arena, win32_file_find_data);
|
||||||
temporary_memory Scratch = GetScratch(&Arena, 1);
|
temp Scratch = GetScratch(&Arena, 1);
|
||||||
Path = PushFormat(Scratch.Arena, "%S/%S*", Global_Win32State.ContentsPath, Path);
|
Path = PushFormat(Scratch.Arena, "%S/%S*", Global_Win32State.ContentsPath, Path);
|
||||||
string16 Path16 = String16FromString8(Scratch.Arena, Path);
|
string16 Path16 = String16FromString8(Scratch.Arena, Path);
|
||||||
FileFindData->Handle = FindFirstFileW((WCHAR *)Path16.Data, &FileFindData->FindData);
|
FileFindData->Handle = FindFirstFileW((WCHAR *)Path16.Data, &FileFindData->FindData);
|
||||||
|
@ -367,7 +367,7 @@ static PLATFORM_TOGGLE_FULLSCREEN(Win32_ToggleFullscreen)
|
||||||
|
|
||||||
static PLATFORM_SET_CLIPBOARD(Win32_SetClipboard)
|
static PLATFORM_SET_CLIPBOARD(Win32_SetClipboard)
|
||||||
{
|
{
|
||||||
temporary_memory Scratch = GetScratch();
|
temp Scratch = GetScratch();
|
||||||
if(OpenClipboard(0))
|
if(OpenClipboard(0))
|
||||||
{
|
{
|
||||||
EmptyClipboard();
|
EmptyClipboard();
|
||||||
|
@ -454,7 +454,7 @@ static LRESULT Win32_WindowCallback(HWND Window, UINT Message, WPARAM WParam, LP
|
||||||
|
|
||||||
win32_state *State = &Global_Win32State;
|
win32_state *State = &Global_Win32State;
|
||||||
|
|
||||||
temporary_memory Scratch = GetScratch(0, 0);
|
temp Scratch = GetScratch(0, 0);
|
||||||
|
|
||||||
platform_event *Event = 0;
|
platform_event *Event = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Platform
|
Platform
|
||||||
{
|
{
|
||||||
RefreshRate = 144;
|
RefreshRate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dev
|
Dev
|
||||||
|
|
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 833 KiB |
Before Width: | Height: | Size: 758 KiB |
Before Width: | Height: | Size: 969 KiB |
Before Width: | Height: | Size: 969 KiB |
Before Width: | Height: | Size: 2.1 MiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 1.2 MiB |
|
@ -1,22 +0,0 @@
|
||||||
RULES
|
|
||||||
-Credit "Noraneko Games"
|
|
||||||
-For games: credit can be given in the in-game credits, in a note accompanying the game, or on a website where the project is downloaded. Any one of those is fine. It doesn't have to be all of them.
|
|
||||||
-For Art: Credit must accompany the picture where it is posted or on the image itself.
|
|
||||||
-For Vtubing/video: Credit can be given in the description or in a panel of your streaming platform or on the video itself. Any of those are fine.
|
|
||||||
-If this pack is re-uploaded to another site for download as is, do not remove this text file or any part of it.
|
|
||||||
-These assets cannot be sold as is. For merchandising options, contact me and we can discuss options.
|
|
||||||
-Modifications are allowed. (Change colors, add blood splatters, draw characters in the image, etc)
|
|
||||||
-Using for 18+ is fine as long as it doesn't contain illegal themes/content (such as homophobia, racism, threats to real people, or pedophilia) that could reflect poorly on the Noraneko Games name and reputation.
|
|
||||||
-Commercial use in a game is ok if you can provide proof of credit if I contact you for it and it follows all other rules. Contact me for commercial use outside of games.
|
|
||||||
-If you aren't making money from your project, you can use without contacting me if you'd prefer.
|
|
||||||
-Using this asset for Game Jams and Contests is okay!
|
|
||||||
-If you want to use this media for anything other than a game, make sure it follows the rules above.
|
|
||||||
|
|
||||||
|
|
||||||
Find more of my work at:
|
|
||||||
@NoranekoGames on Twitter
|
|
||||||
Noranekokgames.itch.io
|
|
||||||
|
|
||||||
Not required, but I would love for you to link me to your project!
|
|
||||||
|
|
||||||
Good luck with your project!
|
|
Before Width: | Height: | Size: 994 KiB |
Before Width: | Height: | Size: 871 KiB |
Before Width: | Height: | Size: 999 KiB |
Before Width: | Height: | Size: 951 KiB |
Before Width: | Height: | Size: 626 KiB |
Before Width: | Height: | Size: 793 KiB |
Before Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 4.1 KiB |
|
@ -1,12 +0,0 @@
|
||||||
proc main
|
|
||||||
{
|
|
||||||
"One line test";
|
|
||||||
@arthur(normal) "Welcome to this fine estate!";
|
|
||||||
@arthur(happy) "I am pleased to see you.";
|
|
||||||
|
|
||||||
"An inbetweener if you were";
|
|
||||||
|
|
||||||
@arthur(none);
|
|
||||||
|
|
||||||
jump main; // return to start
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
proc main
|
|
||||||
{
|
|
||||||
"There's a ghost, in my home - but it's better than being alone. Reading read receipts with no replying.";
|
|
||||||
"Yes my house is haunted. That's just what I wanted. Read receipts with no replying.";
|
|
||||||
"Scene test 123" #noclear;
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
proc main
|
|
||||||
{
|
|
||||||
"I see an annoying girl running toward me from the distance, waving her arms in the air like she's totally oblivious to any attention she might draw to herself.";
|
|
||||||
"That girl is Sayori, my neighbor and good friend since we were children.";
|
|
||||||
"You know, the kind of friend you'd never see yourself making today, but it just kind of works out because you've known each other for so long?";
|
|
||||||
"We used to walk to school together on days like this, but starting around high school she would oversleep more and more frequently, and I would get tired of waiting up.";
|
|
||||||
"But if she's going to chase after me like this, I almost feel better off running away.";
|
|
||||||
"However, I just sigh and idle in front of the crosswalk and let Sayori catch up to me.";
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
var monika = "Monika";
|
|
||||||
var arthur = "Arthur";
|
|
||||||
|
|
||||||
proc main
|
|
||||||
{
|
|
||||||
"hello, line, paint, color, design, address, brightness";
|
|
||||||
|
|
||||||
@monika(leaning) "Hi";
|
|
||||||
|
|
||||||
@arthur(normal) "Wasssap!";
|
|
||||||
|
|
||||||
@monika(leaning) "This is completely normal";
|
|
||||||
|
|
||||||
@monika(none);
|
|
||||||
|
|
||||||
@arthur(normal) "Wow, what a rude person";
|
|
||||||
@arthur(happy) "But hey! They left atleast!";
|
|
||||||
|
|
||||||
@arthur(none);
|
|
||||||
|
|
||||||
"Something inbetween!";
|
|
||||||
|
|
||||||
@monika(leaning) @arthur(happy) "BOOOO!";
|
|
||||||
|
|
||||||
"Gotcha'!";
|
|
||||||
|
|
||||||
@arthur(none) @monika(none);
|
|
||||||
|
|
||||||
jump main;
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
proc main
|
|
||||||
{
|
|
||||||
"This is the editor";
|
|
||||||
"You can write text in here";
|
|
||||||
|
|
||||||
"If you want to add a branch, you use the branch keyword";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
jump main; // to not hit the "end of proc" error
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
proc main
|
|
||||||
{
|
|
||||||
for(var idx = 0; idx < 10; idx = idx + 1)
|
|
||||||
{
|
|
||||||
print("hello, line, paint, color, design, address, brightness");
|
|
||||||
}
|
|
||||||
}
|
|
51
data/gpt.vns
|
@ -1,51 +0,0 @@
|
||||||
proc main
|
|
||||||
{
|
|
||||||
"morning, sunlight, birdsong, aroma, coffee, kitchen";
|
|
||||||
|
|
||||||
"You wake up to the sound of birds singing outside your window. The sunlight filters through the curtains, casting a warm glow on your room.";
|
|
||||||
|
|
||||||
branch
|
|
||||||
{
|
|
||||||
"Get up and make coffee"
|
|
||||||
{
|
|
||||||
"You head to the kitchen and start brewing a fresh pot of coffee. The aroma fills the air, and you can't help but smile as you anticipate that first sip.";
|
|
||||||
|
|
||||||
branch
|
|
||||||
{
|
|
||||||
"Enjoy the coffee in peace"
|
|
||||||
{
|
|
||||||
"You take your coffee to the cozy corner by the window. As you sip it, you watch the world go by outside, feeling a sense of calm wash over you.";
|
|
||||||
}
|
|
||||||
|
|
||||||
"Invite your roommate to join"
|
|
||||||
{
|
|
||||||
"You hear your roommate stirring in their room. You decide to invite them over to share the morning coffee.";
|
|
||||||
|
|
||||||
branch
|
|
||||||
{
|
|
||||||
"Roommate joins you"
|
|
||||||
{
|
|
||||||
"Your roommate joins you at the table. You both chat about your plans for the day and share a few laughs as you enjoy your coffee together.";
|
|
||||||
}
|
|
||||||
|
|
||||||
"Roommate declines"
|
|
||||||
{
|
|
||||||
"Your roommate declines your invitation, mentioning they have some work to catch up on. You enjoy your coffee solo, lost in your thoughts.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"Stay in bed a little longer"
|
|
||||||
{
|
|
||||||
"You decide to indulge yourself and stay in bed a little longer. The warmth of the blankets cocoon you, and you drift in and out of pleasant dreams.";
|
|
||||||
|
|
||||||
"Eventually, you decide it's time to start the day.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"Time seems to pass peacefully as you enjoy the simple pleasures of the morning.";
|
|
||||||
|
|
||||||
jump main;
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
proc main
|
|
||||||
{
|
|
||||||
"人類社会のすべての構成員の固有の尊厳と平等で譲ることのできない権利とを承認することは";
|
|
||||||
"Yup, I added fucking support for japanese.";
|
|
||||||
"WHY DID I DO THIS!?!?!?!" #noawait;
|
|
||||||
branch
|
|
||||||
{
|
|
||||||
"Because you're stupid"
|
|
||||||
{
|
|
||||||
"HEY! You don't get to call me stupid!";
|
|
||||||
}
|
|
||||||
|
|
||||||
"Because you're dumb"
|
|
||||||
{
|
|
||||||
"Yeah, fair enough...";
|
|
||||||
}
|
|
||||||
|
|
||||||
"Because you're SOOO smart"
|
|
||||||
{
|
|
||||||
"HEY! NO SARCASM ALLOWED ON THIS CHRISTIAN MINECRAFT SERVER OKAY?";
|
|
||||||
"I WANT TO SEE ABSOLUTELY ZERO, OKAY!?!?!?!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Anyways, we're going to another function now, okay?";
|
|
||||||
jump test;
|
|
||||||
}
|
|
||||||
|
|
||||||
proc test
|
|
||||||
{
|
|
||||||
"hi it's me sans undertale, from undertale";
|
|
||||||
"let me show you some lit memmes";
|
|
||||||
"DUHDUH DUH DUH - DUH DUH DUH DUHDUHDUH";
|
|
||||||
jump main;
|
|
||||||
}
|
|
BIN
data/scene.vnn
|
@ -1,3 +1,6 @@
|
||||||
|
nav "data/scene.vnn";
|
||||||
|
background DemoBackground;
|
||||||
|
|
||||||
var arthur = "Arthur";
|
var arthur = "Arthur";
|
||||||
var monika = "Monika";
|
var monika = "Monika";
|
||||||
|
|
||||||
|
@ -20,6 +23,13 @@ proc main
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
proc arthur_talk
|
||||||
{
|
{
|
||||||
@arthur(normal) "Hi! Thanks for talking to me.";
|
@arthur(normal) "Hi! Thanks for talking to me.";
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
// This just experiments with the scripting language
|
|
||||||
|
|
||||||
var times = 0;
|
|
||||||
|
|
||||||
proc "Start"
|
|
||||||
{
|
|
||||||
"so, I actually changed my mind.";
|
|
||||||
"the editor will not be node based";
|
|
||||||
"I realised that it would just be slower to write dialog that way soooo...";
|
|
||||||
"instead, I present to you the..........";
|
|
||||||
"vn scene - scripting language";
|
|
||||||
|
|
||||||
"btw something happens if you go through this dialog 10 times";
|
|
||||||
|
|
||||||
times += 1;
|
|
||||||
|
|
||||||
branch
|
|
||||||
{
|
|
||||||
"Return to start"
|
|
||||||
{
|
|
||||||
jump "Start";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(times >= 10)
|
|
||||||
{
|
|
||||||
"SUPER EPIC SECRET"
|
|
||||||
{
|
|
||||||
jump "Epic Scene";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc "Epic Scene"
|
|
||||||
{
|
|
||||||
"woah... so epic";
|
|
||||||
@s "oh, right. almost forgot to mention that you can talk as different characters.";
|
|
||||||
@s "you know... ";
|
|
||||||
wait;
|
|
||||||
@s #noclear "the usual";
|
|
||||||
}
|
|
37
data/vns.txt
|
@ -1,37 +0,0 @@
|
||||||
program -> declaration* EOF;
|
|
||||||
|
|
||||||
declaration -> proc_decl |
|
|
||||||
var_decl |
|
|
||||||
statement;
|
|
||||||
|
|
||||||
proc_decl -> "proc" IDENTIFIER block;
|
|
||||||
var_decl -> "var" IDENTIFIER ("=" expression)? ";";
|
|
||||||
|
|
||||||
statement -> expression_statement |
|
|
||||||
for_statement |
|
|
||||||
if_statement |
|
|
||||||
block;
|
|
||||||
|
|
||||||
expression_statement -> expression ";";
|
|
||||||
for_statement -> "for" "(" (var_decl|expression_statement|";")
|
|
||||||
expression? ";" expression? ")" statement;
|
|
||||||
if_statement -> "if" "(" expression ")" statement
|
|
||||||
("else" statement)?;
|
|
||||||
block -> "{" declaration* "}";
|
|
||||||
|
|
||||||
expression -> assignment;
|
|
||||||
|
|
||||||
assignment -> (call ".")? IDENTIFIER "=" assignment |
|
|
||||||
logic_or;
|
|
||||||
|
|
||||||
logic_or -> logic_and ("or" logic_and)*;
|
|
||||||
logic_and -> equality ("and" equality)*;
|
|
||||||
equality -> comparison (("!=" | "==") comparison)*;
|
|
||||||
comparison -> term ((">" | ">=" < "<" | "<=") term)*;
|
|
||||||
term -> factor (("-" | "+") factor)*;
|
|
||||||
factor -> unary (("/" | "*") unary)*;
|
|
||||||
|
|
||||||
unary -> ("!" | "-") unary | call;
|
|
||||||
call -> primary "(" arguments? ")";
|
|
||||||
primary -> "true" | "false" | NUMBER | STRING |
|
|
||||||
IDENTIFIER | "(" expression ")";
|
|
|
@ -1,5 +0,0 @@
|
||||||
vn - release 1
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Right, so we need to have some tools to make a visual novel. In lieu of actual GOOD tools, we will deal with subpar ones instead. Thusly, this first release will only include the bearest tools to get you started, but it should be enough for some basic (text only) scenes.
|
|
||||||
|
|
31
test
|
@ -1,31 +0,0 @@
|
||||||
proc main
|
|
||||||
{
|
|
||||||
"Hello!";
|
|
||||||
|
|
||||||
"This is a little text editor with syntax highlighting";
|
|
||||||
|
|
||||||
"Is it cool?" #noawait;
|
|
||||||
|
|
||||||
branch
|
|
||||||
{
|
|
||||||
"Yes"
|
|
||||||
{
|
|
||||||
"I know right?";
|
|
||||||
}
|
|
||||||
|
|
||||||
"No"
|
|
||||||
{
|
|
||||||
"Wow, no need to be a hater dude.";
|
|
||||||
"Seriously";
|
|
||||||
"...";
|
|
||||||
"Grow up";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"Oh, forgot to mention that it also supports unicode.";
|
|
||||||
"Which makes it able to use all langages that use left to right writing.";
|
|
||||||
"Assuming that the character system isn't too complex.";
|
|
||||||
"Мой домашний питомец";
|
|
||||||
"悠輝さんに渡すつもりです";
|
|
||||||
jump main;
|
|
||||||
}
|
|
12
todo.txt
|
@ -1,12 +0,0 @@
|
||||||
This is a list of things that needs doing in a SUGGESTED order.
|
|
||||||
|
|
||||||
* UI
|
|
||||||
- Incorrect behaviour when closing panels in a certain order, most likely some things are not being copied over properly.
|
|
||||||
|
|
||||||
* Rendering
|
|
||||||
- Fix texture clipping
|
|
||||||
- Control over each corner when rounding
|
|
||||||
|
|
||||||
Completed
|
|
||||||
* UI
|
|
||||||
- Settings / Preferences view. (Including saving and loading of these settings/preferences)
|
|
18
weeks.txt
|
@ -1,18 +0,0 @@
|
||||||
[0] - Characters
|
|
||||||
- Get characters names displaying while they talk V
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
[1] - Environments & Time
|
|
||||||
|
|
||||||
[2] - Map & Notebook
|
|
||||||
|
|
||||||
[3] - UI
|
|
||||||
- Keyboard Navigation
|
|
||||||
- Blinking Caret
|
|
||||||
|
|
||||||
[4] - Minigames
|
|
||||||
|
|
||||||
[5] - Rendering
|
|
||||||
- Check up on texture mappings, something seems to be weird
|
|
||||||
|
|
||||||
[6] - Data Submission
|
|