Started animating characters

main
sixtenhugosson 2023-10-04 19:21:15 +02:00
parent 10c5793a1d
commit 6e93783b03
27 changed files with 550 additions and 218 deletions

View File

@ -33,6 +33,7 @@ typedef void opengl_GetTexLevelParameterfv(GLenum target, GLint level, GLenum pn
typedef void opengl_GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params); typedef void opengl_GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
typedef void opengl_GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params); typedef void opengl_GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
typedef void opengl_GetTexParameteriv(GLenum target, GLenum pname, GLint *params); typedef void opengl_GetTexParameteriv(GLenum target, GLenum pname, GLint *params);
typedef void opengl_GenerateMipmap(GLenum target);
typedef void opengl_Hint(GLenum target, GLenum mode); typedef void opengl_Hint(GLenum target, GLenum mode);
typedef GLboolean opengl_IsTexture(GLuint texture); typedef GLboolean opengl_IsTexture(GLuint texture);
typedef void opengl_LineWidth(GLfloat width); typedef void opengl_LineWidth(GLfloat width);
@ -121,6 +122,7 @@ global opengl_GetTexLevelParameterfv *glGetTexLevelParameterfv = 0;
global opengl_GetTexLevelParameteriv *glGetTexLevelParameteriv = 0; global opengl_GetTexLevelParameteriv *glGetTexLevelParameteriv = 0;
global opengl_GetTexParameterfv *glGetTexParameterfv = 0; global opengl_GetTexParameterfv *glGetTexParameterfv = 0;
global opengl_GetTexParameteriv *glGetTexParameteriv = 0; global opengl_GetTexParameteriv *glGetTexParameteriv = 0;
global opengl_GenerateMipmap *glGenerateMipmap = 0;
global opengl_Hint *glHint = 0; global opengl_Hint *glHint = 0;
global opengl_IsTexture *glIsTexture = 0; global opengl_IsTexture *glIsTexture = 0;
global opengl_LineWidth *glLineWidth = 0; global opengl_LineWidth *glLineWidth = 0;
@ -212,6 +214,7 @@ glGetTexLevelParameterfv = (opengl_GetTexLevelParameterfv *)OpenGL_LoadFunction(
glGetTexLevelParameteriv = (opengl_GetTexLevelParameteriv *)OpenGL_LoadFunction("glGetTexLevelParameteriv"); glGetTexLevelParameteriv = (opengl_GetTexLevelParameteriv *)OpenGL_LoadFunction("glGetTexLevelParameteriv");
glGetTexParameterfv = (opengl_GetTexParameterfv *)OpenGL_LoadFunction("glGetTexParameterfv"); glGetTexParameterfv = (opengl_GetTexParameterfv *)OpenGL_LoadFunction("glGetTexParameterfv");
glGetTexParameteriv = (opengl_GetTexParameteriv *)OpenGL_LoadFunction("glGetTexParameteriv"); glGetTexParameteriv = (opengl_GetTexParameteriv *)OpenGL_LoadFunction("glGetTexParameteriv");
glGenerateMipmap = (opengl_GenerateMipmap *)OpenGL_LoadFunction("glGenerateMipmap");
glHint = (opengl_Hint *)OpenGL_LoadFunction("glHint"); glHint = (opengl_Hint *)OpenGL_LoadFunction("glHint");
glIsTexture = (opengl_IsTexture *)OpenGL_LoadFunction("glIsTexture"); glIsTexture = (opengl_IsTexture *)OpenGL_LoadFunction("glIsTexture");
glLineWidth = (opengl_LineWidth *)OpenGL_LoadFunction("glLineWidth"); glLineWidth = (opengl_LineWidth *)OpenGL_LoadFunction("glLineWidth");

View File

@ -0,0 +1,10 @@
static character_state CR_CharacterStateFromString(string String)
{
character_state Result = CR_State_Invalid;
if(0) {}
else if(AreEqual(String, StrLit("none"))) { Result = CR_State_None; }
else if(AreEqual(String, StrLit("normal"))) { Result = CR_State_Normal; }
else if(AreEqual(String, StrLit("happy"))) { Result = CR_State_Happy; }
return(Result);
}

View File

@ -0,0 +1,8 @@
enum character_state
{
CR_State_Invalid = 0,
CR_State_None,
CR_State_Normal,
CR_State_Happy,
};

View File

@ -36,6 +36,7 @@ OpenGLFunctions:
{GetTexLevelParameteriv `void` `GLenum target, GLint level, GLenum pname, GLint *params`} {GetTexLevelParameteriv `void` `GLenum target, GLint level, GLenum pname, GLint *params`}
{GetTexParameterfv `void` `GLenum target, GLenum pname, GLfloat *params`} {GetTexParameterfv `void` `GLenum target, GLenum pname, GLfloat *params`}
{GetTexParameteriv `void` `GLenum target, GLenum pname, GLint *params`} {GetTexParameteriv `void` `GLenum target, GLenum pname, GLint *params`}
{GenerateMipmap `void` `GLenum target` }
{Hint `void` `GLenum target, GLenum mode`} {Hint `void` `GLenum target, GLenum mode`}
{IsTexture `GLboolean` `GLuint texture`} {IsTexture `GLboolean` `GLuint texture`}
{LineWidth `void` `GLfloat width`} {LineWidth `void` `GLfloat width`}

View File

@ -98,9 +98,22 @@ static RENDER_ALLOCATE_TEXTURE(OpenGL_AllocateTexture)
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);
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, SwizzleMask);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if(GenerateMipmap)
{
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, SwizzleMask); }
render_handle Handle = OpenGL_GetHandleFromTexture(Texture); render_handle Handle = OpenGL_GetHandleFromTexture(Texture);
return(Handle); return(Handle);
@ -631,7 +644,7 @@ static opengl_context OpenGL_SetupContext(vn_render_commands *RenderCommands, um
#endif #endif
u32 WhiteData = 0xFFFFFFFF; u32 WhiteData = 0xFFFFFFFF;
RenderCommands->WhiteTexture = OpenGL_AllocateTexture(V2S32(1, 1), Render_TextureFormat_RGBA8, &WhiteData); RenderCommands->WhiteTexture = OpenGL_AllocateTexture(V2S32(1, 1), Render_TextureFormat_RGBA8, false, &WhiteData);
RenderCommands->AllocateTexture = OpenGL_AllocateTexture; RenderCommands->AllocateTexture = OpenGL_AllocateTexture;
RenderCommands->FillRegion = OpenGL_FillRegion; RenderCommands->FillRegion = OpenGL_FillRegion;

View File

@ -22,12 +22,12 @@ global debug_settings *DEBUG_DebugSettings = 0;
#include "vn_text_op.h" #include "vn_text_op.h"
#include "vn_ui.h" #include "vn_ui.h"
#include "vn_ui_utils.h" #include "vn_ui_utils.h"
#include "vn_character.h"
#include "vn_scene.h" #include "vn_scene.h"
#include "vn_scene_view.h" #include "vn_scene_view.h"
#include "vn_workspace.h" #include "vn_workspace.h"
#include "vn_animation_curve.h" #include "vn_animation_curve.h"
#include "vn_theme_dark.h" #include "vn_theme_dark.h"
#include "vn_character.h"
#include "vn_tokenizer.cpp" #include "vn_tokenizer.cpp"
#include "vn_config.cpp" #include "vn_config.cpp"
@ -53,6 +53,7 @@ struct vn_state
ui UI; ui UI;
workspace Workspace; workspace Workspace;
animation_curve_state AnimationCurveState; animation_curve_state AnimationCurveState;
b32 EditorMode;
character_registry CharacterRegistry; character_registry CharacterRegistry;
render_handle BackgroundTexture; render_handle BackgroundTexture;
@ -88,7 +89,7 @@ static render_handle CreateTextureFromPath(vn_render_commands *Commands, string
case 4: { TextureFormat = Render_TextureFormat_RGBA8; } break; case 4: { TextureFormat = Render_TextureFormat_RGBA8; } break;
} }
Result = Commands->AllocateTexture(V2S32(Width, Height), TextureFormat, TextureData); Result = Commands->AllocateTexture(V2S32(Width, Height), TextureFormat, true, TextureData);
stbi_image_free(TextureData); stbi_image_free(TextureData);
@ -98,7 +99,6 @@ static render_handle CreateTextureFromPath(vn_render_commands *Commands, string
return(Result); return(Result);
} }
VN_UPDATE_AND_RENDER(VN_UpdateAndRender) VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
{ {
SetThreadContext(ThreadContext); SetThreadContext(ThreadContext);
@ -137,20 +137,23 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
//- sixten: load startup scene //- sixten: load startup scene
scene_view *SceneView = &State->SceneView; scene_view *SceneView = &State->SceneView;
SV_Init(SceneView, State->Arena); SV_Init(SceneView, State->Arena);
temporary_memory Scratch = GetScratch();
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, StrLit("data/character.vns"));
compiled_scene Scene = S_ScriptFromText(Scratch.Arena, SceneInput);
SV_SetCurrentSource(&Scene);
ReleaseScratch(Scratch);
SceneView->TestHappy = CreateTextureFromPath(RenderCommands, StrLit("data/characters/test_happy.png"));
SceneView->TestNormal = CreateTextureFromPath(RenderCommands, StrLit("data/characters/test_normal.png"));
SceneView->BackgroundTexture = State->BackgroundTexture; SceneView->BackgroundTexture = State->BackgroundTexture;
//- sixten: create mock characters
CR_Init(&State->CharacterRegistry); CR_Init(&State->CharacterRegistry);
character_entry *Arthur = CR_EntryFromName(StrLit("Arthur"));
UnusedVariable(Arthur);
CR_EntryFromName(StrLit("Catherine"));
CR_EntryFromName(StrLit("Quinn"));
CR_EntryFromName(StrLit("Margaret"));
UI_Init(&State->UI); UI_Init(&State->UI);
W_Init(&State->Workspace); W_Init(&State->Workspace);
AC_Init(&State->AnimationCurveState); AC_Init(&State->AnimationCurveState);
return;
} }
#if VN_INTERNAL #if VN_INTERNAL
@ -161,13 +164,18 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
ArenaClear(State->FrameArena); ArenaClear(State->FrameArena);
AC_NewFrame(&State->AnimationCurveState, Input->dtForFrame); AC_NewFrame(&State->AnimationCurveState, Input->dtForFrame);
UI_NewFrame(&State->UI, Input->EventList, Input->MouseP, State->GlyphAtlas); UI_NewFrame(&State->UI, Input->EventList, Input->MouseP, State->GlyphAtlas);
SV_SetState(&State->SceneView); SV_NewFrame(&State->SceneView, Input->EventList, Input->dtForFrame);
//- sixten: check for toggle between modes
if(Platform_KeyPress(Input->EventList, Key_Return, PlatformModifier_Ctrl))
{
State->EditorMode = !State->EditorMode;
}
//- sixten: build the ui //- sixten: build the ui
UI_BeginBuild(RenderCommands->RenderDim); UI_BeginBuild(RenderCommands->RenderDim);
{ {
b32 EditorMode = false; if(State->EditorMode)
if(EditorMode)
{ {
W_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas); W_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas);
} }
@ -180,7 +188,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
//- sixten: update the scene //- sixten: update the scene
SV_Update(State->FrameArena, Input); 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;

View File

@ -1,3 +1,5 @@
#include "generated/vn_character.meta.c"
global character_registry *Global_CharacterRegistry = 0; global character_registry *Global_CharacterRegistry = 0;
//////////////////////////////// ////////////////////////////////

View File

@ -3,6 +3,8 @@
#ifndef VN_CHARACTER_H #ifndef VN_CHARACTER_H
#define VN_CHARACTER_H #define VN_CHARACTER_H
#include "generated/vn_character.meta.h"
//////////////////////////////// ////////////////////////////////
//~ sixten: Character String Chunk Types //~ sixten: Character String Chunk Types
#define CHARACTER_STRING_CHUNK_DATA_SIZE (64 - sizeof(character_string_chunk *)) #define CHARACTER_STRING_CHUNK_DATA_SIZE (64 - sizeof(character_string_chunk *))
@ -21,7 +23,6 @@ struct character_string_list
s64 StringCount; s64 StringCount;
}; };
//////////////////////////////// ////////////////////////////////
//~ sixten: Character Registry Types //~ sixten: Character Registry Types
struct character_entry struct character_entry
@ -62,4 +63,9 @@ static character_list CR_GetCharacters(void);
static void CR_Init(void); static void CR_Init(void);
static character_entry *CR_EntryFromName(string Name); static character_entry *CR_EntryFromName(string Name);
////////////////////////////////
//~ sixten: Misc. Character Functions
static character_state CR_CharacterStateFromString(string Input);
static string CR_StringFromCharacterState(character_state State);
#endif //VN_CHARACTER_H #endif //VN_CHARACTER_H

View File

@ -0,0 +1,26 @@
@table(TypedName, EnumName) character_states:
{
{ "none", None },
{ "normal", Normal },
{ "happy", Happy },
}
@table_gen
{
`enum character_state`;
`{`;
`CR_State_Invalid = 0,`
@expand(character_states s) `CR_State_$(s.EnumName),`
`};`;
}
@table_gen @c
{
`static character_state CR_CharacterStateFromString(string String)`;
`{`;
`character_state Result = CR_State_Invalid;`;
`if(0) {}`;
@expand(character_states s) `else if(AreEqual(String, StrLit("$(s.TypedName)")))$(=>40) { Result = CR_State_$(s.EnumName); }`;
`return(Result);`;
`}`;
}

View File

@ -115,7 +115,7 @@ static glyph_atlas *CreateGlyphAtlas(vn_render_commands *RenderCommands,
Atlas->Glyphs = PushArray(Atlas->Arena, glyph, Atlas->MaxGlyphCount); Atlas->Glyphs = PushArray(Atlas->Arena, glyph, Atlas->MaxGlyphCount);
Atlas->RenderCommands = RenderCommands; Atlas->RenderCommands = RenderCommands;
Atlas->Texture = RenderCommands->AllocateTexture(V2S32(BitmapSize, BitmapSize), Render_TextureFormat_R8, 0); Atlas->Texture = RenderCommands->AllocateTexture(V2S32(BitmapSize, BitmapSize), Render_TextureFormat_R8, false, 0);
Atlas->Fonts[Font_Regular].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/Roboto-Regular.ttf")); Atlas->Fonts[Font_Regular].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/Roboto-Regular.ttf"));
Atlas->Fonts[Font_Bold].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/Roboto-Bold.ttf")); Atlas->Fonts[Font_Bold].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/Roboto-Bold.ttf"));

View File

@ -134,7 +134,7 @@ static platform_api Platform;
#include "vn_render.h" #include "vn_render.h"
#define RENDER_ALLOCATE_TEXTURE(name) render_handle name(v2_s32 Dim, render_texture_format Format, 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_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)

View File

@ -112,6 +112,8 @@ static void PushTexturedQuad(render_group *Group,
{ {
vn_render_commands *Commands = Group->Commands; vn_render_commands *Commands = Group->Commands;
if(!AreEqual(Texture, EmptyRenderHandle()))
{
render_command_instanced_quads *Command = (render_command_instanced_quads *)(Group->CurrentCommand + 1); render_command_instanced_quads *Command = (render_command_instanced_quads *)(Group->CurrentCommand + 1);
s32 TextureIndex; s32 TextureIndex;
if(!(Group->CurrentCommand && Group->CurrentCommand->Type == Render_Command_render_command_instanced_quads && if(!(Group->CurrentCommand && Group->CurrentCommand->Type == Render_Command_render_command_instanced_quads &&
@ -150,6 +152,7 @@ static void PushTexturedQuad(render_group *Group,
Command->QuadCount += 1; Command->QuadCount += 1;
} }
} }
}
#else #else
static void PushTexturedQuad(render_group *Group, static void PushTexturedQuad(render_group *Group,
range2_r32 Dest, range2_r32 Dest,
@ -160,6 +163,8 @@ static void PushTexturedQuad(render_group *Group,
{ {
vn_render_commands *Commands = Group->Commands; vn_render_commands *Commands = Group->Commands;
if(!AreEqual(Texture, EmptyRenderHandle()))
{
render_command_quads *Command = (render_command_quads *)(Group->CurrentCommand + 1); render_command_quads *Command = (render_command_quads *)(Group->CurrentCommand + 1);
s32 TextureIndex; s32 TextureIndex;
if(!(Group->CurrentCommand && Group->CurrentCommand->Type == Render_Command_render_command_quads && if(!(Group->CurrentCommand && Group->CurrentCommand->Type == Render_Command_render_command_quads &&
@ -252,6 +257,7 @@ static void PushTexturedQuad(render_group *Group,
++Command->QuadCount; ++Command->QuadCount;
} }
} }
}
#endif #endif
inline void PushQuad(render_group *Group, range2_r32 Dest, inline void PushQuad(render_group *Group, range2_r32 Dest,

View File

@ -233,28 +233,38 @@ static void S_ParseDeclaration(scene_compiler *Compiler)
case TokenKind_At: case TokenKind_At:
{ {
Compiler->At += 1; Compiler->At += 1;
token IdentifierToken = S_ConsumeToken(Compiler, TokenKind_Identifier, "Expected identifier after '@'"); token IdentifierToken = S_ConsumeToken(Compiler, TokenKind_Identifier, "Expected identifier after '@'");
S_EmitConstant(Compiler, S_MakeSourceRef(IdentifierToken));
if(Compiler->At->Kind == TokenKind_ParenthesisOpen) if(Compiler->At->Kind == TokenKind_ParenthesisOpen)
{ {
Compiler->At += 1; Compiler->At += 1;
token StateToken = S_ConsumeToken(Compiler, TokenKind_Identifier, "Expected character state."); token StateToken = S_ConsumeToken(Compiler, TokenKind_Identifier, "Expected character state.");
S_ConsumeToken(Compiler, TokenKind_ParenthesisClose, "Expected ')' after character state."); S_ConsumeToken(Compiler, TokenKind_ParenthesisClose, "Expected ')' after character state.");
S_EmitConstant(Compiler, S_MakeSourceRef(StateToken));
} }
else else
{ {
S_EmitConstant(Compiler, S_MakeNil());
}
S_EmitByte(Compiler, S_Op_ShowCharacter);
if(Compiler->At->Kind == TokenKind_Semicolon)
{
Compiler->At += 1;
} }
} break; } break;
case TokenKind_StringLiteral: case TokenKind_StringLiteral:
{ {
S_ParseExpression(Compiler); S_ParseExpression(Compiler);
S_EmitByte(Compiler, S_Op_LineEntry);
//- sixten: parse tags //- sixten: parse tags
{ {
b32 EmitAwait = true; b32 EmitAwait = true;
scene_line_entry_flag Flags = 0; b32 EmitClear = true;
for(;Compiler->At[0].Kind == TokenKind_PoundSign;) for(;Compiler->At[0].Kind == TokenKind_PoundSign;)
{ {
Compiler->At += 1; Compiler->At += 1;
@ -262,7 +272,7 @@ static void S_ParseDeclaration(scene_compiler *Compiler)
string TagString = T_StringFromToken(Compiler->Text, TagToken); string TagString = T_StringFromToken(Compiler->Text, TagToken);
if(AreEqual(TagString, StrLit("noclear"))) if(AreEqual(TagString, StrLit("noclear")))
{ {
Flags |= S_LineEntryFlag_NoClear; EmitClear = false;
} }
else if(AreEqual(TagString, StrLit("noawait"))) else if(AreEqual(TagString, StrLit("noawait")))
{ {
@ -274,6 +284,13 @@ static void S_ParseDeclaration(scene_compiler *Compiler)
} }
} }
if(EmitClear)
{
S_EmitByte(Compiler, S_Op_ClearDialog);
}
S_EmitByte(Compiler, S_Op_LineEntry);
if(EmitAwait) if(EmitAwait)
{ {
S_EmitByte(Compiler, S_Op_AwaitInput); S_EmitByte(Compiler, S_Op_AwaitInput);
@ -810,6 +827,33 @@ static scene_value S_PopStack(scene_runtime *Runtime)
return(Result); return(Result);
} }
static scene_value S_PopStackAndImplicitConvert(scene_runtime *Runtime)
{
scene_value Result = S_PopStack(Runtime);
if(Result.Kind == S_ValueKind_SourceRef)
{
Result.Kind = S_ValueKind_String;
Result.String = Substring(Runtime->Compiled.Source, Result.SourceRef);
}
return(Result);
}
static void S_ResetRuntime(scene_runtime *Runtime)
{
Runtime->IP = 0;
Runtime->CurrentProc = 0;
Runtime->BranchCount = 0;
if(Runtime->RuntimeArena)
{
ArenaClear(Runtime->RuntimeArena);
}
else
{
Runtime->RuntimeArena = ArenaAllocate(Megabytes(32));
}
}
static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameArena, b32 AdvanceOnAwait) static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameArena, b32 AdvanceOnAwait)
{ {
scene_runtime_result Result = {}; scene_runtime_result Result = {};
@ -818,6 +862,7 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
Assert(Runtime != 0); Assert(Runtime != 0);
Assert(Compiled->IsValid); Assert(Compiled->IsValid);
//- sixten: default to the main proc
if(Runtime->CurrentProc == 0) if(Runtime->CurrentProc == 0)
{ {
Runtime->CurrentProc = S_FindProcByName(Compiled, StrLit("main")); Runtime->CurrentProc = S_FindProcByName(Compiled, StrLit("main"));
@ -827,6 +872,7 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
#define S_ReadU32() (Runtime->IP += 4, *(u32 *)(Data+Runtime->IP-4)) #define S_ReadU32() (Runtime->IP += 4, *(u32 *)(Data+Runtime->IP-4))
#define S_ReadValue() Compiled->Values[S_ReadU32()] #define S_ReadValue() Compiled->Values[S_ReadU32()]
//- sixten: run the bytecode interpreter
if(Runtime->CurrentProc) if(Runtime->CurrentProc)
{ {
if(Runtime->IP < Runtime->CurrentProc->Count) if(Runtime->IP < Runtime->CurrentProc->Count)
@ -868,8 +914,8 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
case S_Op_Add: case S_Op_Add:
{ {
Runtime->IP += 1; Runtime->IP += 1;
scene_value Value1 = S_PopStack(Runtime); scene_value Value1 = S_PopStackAndImplicitConvert(Runtime);
scene_value Value2 = S_PopStack(Runtime); scene_value Value2 = S_PopStackAndImplicitConvert(Runtime);
if(Value1.Kind == S_ValueKind_Number && Value2.Kind == S_ValueKind_Number) if(Value1.Kind == S_ValueKind_Number && Value2.Kind == S_ValueKind_Number)
{ {
S_PushStack(Runtime, S_MakeNumber(Value1.Number + Value2.Number)); S_PushStack(Runtime, S_MakeNumber(Value1.Number + Value2.Number));
@ -979,20 +1025,53 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
Result.ReachedAwait = true; Result.ReachedAwait = true;
} break; } break;
default: case S_Op_ClearDialog:
{
if(Data[Runtime->IP] & S_Op_LineEntry)
{ {
textbox_action *Action = PushStructNoClear(FrameArena, textbox_action); textbox_action *Action = PushStructNoClear(FrameArena, textbox_action);
if(Data[Runtime->IP] & S_LineEntryFlag_NoClear) Action->Kind = TextboxActionKind_Set;
Action->String = StrLit("");
QueuePush(Runtime->FirstTextboxAction, Runtime->LastTextboxAction, Action);
Runtime->IP += 1;
} break;
case S_Op_ShowCharacter:
{ {
Action->Kind = TextboxActionKind_Append; Runtime->IP += 1;
scene_value State = S_PopStackAndImplicitConvert(Runtime);
scene_value CharacterValue = S_PopStackAndImplicitConvert(Runtime);
string Character = StrLit("");
if(CharacterValue.Kind == S_ValueKind_String)
{
Character = CharacterValue.String;
} }
else else
{ {
Action->Kind = TextboxActionKind_Set; S_RuntimeErrorF(Runtime, "Incorrect value kind when retrieving character name.");
} }
// sixten: create & apply character action
scene_character_action *Action = PushStruct(FrameArena, scene_character_action);
Action->Target = Character;
if(State.Kind == S_ValueKind_Nil)
{
Action->State = CR_State_None;
}
else
{
Action->State = CR_CharacterStateFromString(State.String);
}
DLLInsertLast(Runtime->FirstCharacterAction, Runtime->LastCharacterAction, Action);
} break;
case S_Op_LineEntry:
{
textbox_action *Action = PushStructNoClear(FrameArena, textbox_action);
Action->Kind = TextboxActionKind_Append;
Runtime->IP += 1; Runtime->IP += 1;
scene_value Value = S_PopStack(Runtime); scene_value Value = S_PopStack(Runtime);
@ -1005,11 +1084,12 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
{ {
S_RuntimeErrorF(Runtime, "Incorrect value kind when retrieving line entry."); S_RuntimeErrorF(Runtime, "Incorrect value kind when retrieving line entry.");
} }
}
else } break;
default:
{ {
S_RuntimeErrorF(Runtime, "Unknown bytecode op: 0x%02x", Data[Runtime->IP]); S_RuntimeErrorF(Runtime, "Unknown bytecode op: 0x%02x", Data[Runtime->IP]);
}
} break; } break;
} }
} }

View File

@ -26,12 +26,6 @@ struct scene_compile_error_list
s64 Count; s64 Count;
}; };
typedef u64 scene_line_entry_flag;
enum
{
S_LineEntryFlag_NoClear = (1<<0),
};
enum scene_opcode enum scene_opcode
{ {
S_Op_Invalid = 0, S_Op_Invalid = 0,
@ -65,10 +59,9 @@ enum scene_opcode
S_Op_Halt, S_Op_Halt,
S_Op_AwaitInput, S_Op_AwaitInput,
S_Op_ClearDialog,
S_Op_LineEntry,
S_Op_ShowCharacter, S_Op_ShowCharacter,
S_Op_LineEntry = 0x80, // sixten(NOTE): All opcoodes above are reserved.
}; };
struct scene_bytecode_chunk struct scene_bytecode_chunk
@ -113,6 +106,7 @@ struct scene_value
b32 Boolean; b32 Boolean;
u64 Pointer; u64 Pointer;
range1_s64 SourceRef; range1_s64 SourceRef;
string String;
s64 Offset; s64 Offset;
}; };
}; };
@ -171,18 +165,13 @@ struct scene_branch_case
scene_value *EndOffsetValue; scene_value *EndOffsetValue;
}; };
struct scene_character struct scene_character_action
{ {
string Name; scene_character_action *Next;
scene_character *Next; scene_character_action *Prev;
scene_character *Prev;
};
struct scene_character_bucket string Target;
{ character_state State;
scene_character *First;
scene_character *Last;
s64 Count;
}; };
struct scene_compiler struct scene_compiler
@ -283,9 +272,9 @@ struct scene_runtime
compiled_scene Compiled; compiled_scene Compiled;
// sixten: runtime state // sixten: runtime state
memory_arena *RuntimeArena;
scene_proc *CurrentProc; scene_proc *CurrentProc;
s64 IP; s64 IP;
memory_arena *Arena;
scene_runtime_stack Stack; scene_runtime_stack Stack;
// sixten: errors // sixten: errors
@ -300,6 +289,8 @@ struct scene_runtime
// sixten: result // sixten: result
textbox_action *FirstTextboxAction; textbox_action *FirstTextboxAction;
textbox_action *LastTextboxAction; textbox_action *LastTextboxAction;
scene_character_action *FirstCharacterAction;
scene_character_action *LastCharacterAction;
branch_case *FirstBranchCase; branch_case *FirstBranchCase;
scene_runtime_result LastResult; scene_runtime_result LastResult;
}; };
@ -425,6 +416,7 @@ static compiled_scene S_CopyCompiledScene(memory_arena *Arena, compiled_scene *C
//////////////////////////////// ////////////////////////////////
//~ sixten: Scene Runtime Functions //~ sixten: Scene Runtime Functions
static scene_proc *S_FindProcByName(compiled_scene *Compiled, string Name); static scene_proc *S_FindProcByName(compiled_scene *Compiled, string Name);
static void S_ResetRuntime(scene_runtime *Runtime);
static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameArena, b32 AdvanceOnAwait); static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameArena, b32 AdvanceOnAwait);
#endif //VN_SCENE_H #endif //VN_SCENE_H

View File

@ -10,6 +10,13 @@ static scene_view *SV_GetState()
return(ThreadLocal_SceneView); return(ThreadLocal_SceneView);
} }
static void SV_NewFrame(scene_view *View, platform_event_list *EventList, r32 dtForFrame)
{
SV_SetState(View);
View->EventList = EventList;
View->dtForFrame = dtForFrame;
}
static void SV_SetCurrentSource(compiled_scene *Compiled) static void SV_SetCurrentSource(compiled_scene *Compiled)
{ {
scene_view *SceneView = SV_GetState(); scene_view *SceneView = SV_GetState();
@ -18,9 +25,7 @@ static void SV_SetCurrentSource(compiled_scene *Compiled)
ArenaClear(SceneView->SceneArena); ArenaClear(SceneView->SceneArena);
SceneView->Runtime.Compiled = S_CopyCompiledScene(SceneView->SceneArena, Compiled); SceneView->Runtime.Compiled = S_CopyCompiledScene(SceneView->SceneArena, Compiled);
SceneView->Runtime.IP = 0; S_ResetRuntime(&SceneView->Runtime);
SceneView->Runtime.Stack.Count = 0;
SceneView->Runtime.BranchCount = 0;
} }
static void SV_Init(scene_view *SceneView, memory_arena *TextboxArena) static void SV_Init(scene_view *SceneView, memory_arena *TextboxArena)
@ -30,6 +35,8 @@ static void SV_Init(scene_view *SceneView, memory_arena *TextboxArena)
SceneView->SceneArena = ArenaAllocate(Gigabytes(1)); SceneView->SceneArena = ArenaAllocate(Gigabytes(1));
SceneView->Runtime.ErrorArena = ArenaAllocate(Megabytes(1)); SceneView->Runtime.ErrorArena = ArenaAllocate(Megabytes(1));
S_ResetRuntime(&SceneView->Runtime);
SceneView->Textbox.Capacity = 4096; SceneView->Textbox.Capacity = 4096;
SceneView->Textbox.String.Data = PushArray(TextboxArena, u8, SceneView->Textbox.Capacity); SceneView->Textbox.String.Data = PushArray(TextboxArena, u8, SceneView->Textbox.Capacity);
SceneView->Textbox.String.Count = 0; SceneView->Textbox.String.Count = 0;
@ -105,6 +112,12 @@ static void RenderAnimatedText(render_group *Group, glyph_atlas *Atlas, text_pro
} }
} }
static r32 CalculateGlobalScaleFromDim(v2_r32 Dim)
{
r32 GlobalScale = SquareRoot(Dim.x*Dim.y)/45;
return(GlobalScale);
}
static r32 CalculateGlobalScaleFromRootBox(ui_box *Box) static r32 CalculateGlobalScaleFromRootBox(ui_box *Box)
{ {
v2 RenderDim = DimOfRange(Box->Rect); v2 RenderDim = DimOfRange(Box->Rect);
@ -142,36 +155,47 @@ UI_CUSTOM_DRAW_CALLBACK(BuildSceneTextboxDrawCallback)
RenderAnimatedText(Group, Atlas, Properties, Text, CharsRevealed, Box->Rect.Min+Offset, DimOfRange(Box->Rect).x-2*Padding); RenderAnimatedText(Group, Atlas, Properties, Text, CharsRevealed, Box->Rect.Min+Offset, DimOfRange(Box->Rect).x-2*Padding);
} }
// sixten(NOTE): This is most likely temporarary and just contains all the data required to render the scene.
struct scene_render_data
{
render_handle BackgroundTexture;
scene_runtime *Runtime;
};
UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback) UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback)
{ {
scene_render_data *RenderData = (scene_render_data *)Data; scene_view *SceneView = (scene_view *)Data;
v2 RenderDim = DimOfRange(Box->Rect);
r32 GlobalScale = CalculateGlobalScaleFromDim(RenderDim);
//- 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.
v2 RenderDim = DimOfRange(Box->Rect); range2_r32 BackgroundDest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min);
range2_r32 Dest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min); range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(SceneView->BackgroundTexture)));
range2_r32 Source = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(RenderData->BackgroundTexture))); PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, SceneView->BackgroundTexture);
PushTexturedQuad(Group, Dest, Source, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, RenderData->BackgroundTexture);
//- sixten: render characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Character = SceneView->OnscreenCharacters + CharacterIndex;
v4_r32 BlendColor = LinearBlend(Color_White, Color_Black, 0.5-Character->TalkingT*0.5);
BlendColor.a = Character->ActiveT;
r32 Scale = (Character->TextureScale + Character->TalkingT*0.001)*(0.95+Character->ActiveT*0.05)*GlobalScale;
render_handle CharacterHandle = Character->Texture;
v2_r32 CharacterDim = ConvertV2ToR32(DimFromTexture(CharacterHandle));
v2_r32 CharacterOriginP = V2R32(RenderDim.x*Character->PctP, RenderDim.y);
v2_r32 CharacterMidP = V2R32(CharacterOriginP.x, CharacterOriginP.y - CharacterDim.y*Scale/2);
range2_r32 CharacterDest = Range2R32(CharacterMidP-CharacterDim*0.5f*Scale, CharacterMidP+CharacterDim*0.5f*Scale);
range2_r32 CharacterSource = Range2R32(V2R32(0, 0), CharacterDim);
PushTexturedQuad(Group, CharacterDest, CharacterSource, BlendColor, BlendColor, BlendColor, BlendColor, 0, 0, 0, CharacterHandle);
}
} }
static void BuildScene(scene_runtime *Runtime, render_handle BackgroundTexture, textbox *Textbox) static void BuildScene(scene_view *View)
{ {
scene_runtime *Runtime = &View->Runtime;
textbox *Textbox = &View->Textbox;
UI_SetNextWidth(UI_Percent(1, 0)); UI_SetNextWidth(UI_Percent(1, 0));
UI_SetNextHeight(UI_Percent(1, 0)); UI_SetNextHeight(UI_Percent(1, 0));
UI_SetNextLayoutAxis(Axis2_Y); UI_SetNextLayoutAxis(Axis2_Y);
ui_box *Box = UI_MakeBox(0, StrLit("Scene View")); ui_box *Box = UI_MakeBox(0, StrLit("Scene View"));
scene_render_data *Data = PushStruct(UI_FrameArena(), scene_render_data); UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View);
Data->BackgroundTexture = BackgroundTexture;
Data->Runtime = Runtime;
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, Data);
UI_Parent(Box) UI_Parent(Box)
{ {
@ -264,14 +288,90 @@ static void BuildErrorScreen(scene_runtime *Runtime, vn_input *Input)
} }
} }
static void SV_Update(memory_arena *FrameArena, vn_input *Input) static scene_view_character_data *SV_CharacterDataFromName(string Name)
{
scene_view_character_data *Result = 0;
scene_view *View = SV_GetState();
for(s32 CharacterIndex = 0; CharacterIndex < View->CharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Character = View->OnscreenCharacters + CharacterIndex;
if(AreEqual(Character->Name, Name))
{
Result = Character;
break;
}
}
//- sixten: create character if not initialized
if(!Result && View->CharacterCount < ArrayCount(View->OnscreenCharacters))
{
s32 CharacterIndex = View->CharacterCount;
View->CharacterCount += 1;
Result = View->OnscreenCharacters + CharacterIndex;
*Result = {};
Result->Name = Name;
Result->Active = true;
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharacterCount + 1);
}
return(Result);
}
static render_handle SV_CharacterTextureFromAction(scene_character_action *Action)
{
render_handle Result = EmptyRenderHandle();
scene_view *View = SV_GetState();
if(AreEqual(StrLit("arthur"), Action->Target))
{
switch(Action->State)
{
case CR_State_Normal: { Result = View->TestNormal; } break;
case CR_State_Happy: { Result = View->TestHappy; } break;
default: break;
}
}
return(Result);
}
static void SV_Update(memory_arena *FrameArena)
{ {
scene_view *SceneView = SV_GetState(); scene_view *SceneView = SV_GetState();
textbox *Textbox = &SceneView->Textbox; textbox *Textbox = &SceneView->Textbox;
scene_runtime *Runtime = &SceneView->Runtime; scene_runtime *Runtime = &SceneView->Runtime;
platform_event_list *EventList = Input->EventList; platform_event_list *EventList = SceneView->EventList;
r32 dtForFrame = SceneView->dtForFrame;
compiled_scene *Compiled = &Runtime->Compiled; compiled_scene *Compiled = &Runtime->Compiled;
//- sixten: update the characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
AC_AnimateValueDirect(Data->Active, 0.3f, &Data->ActiveT);
AC_AnimateValueDirect(Data->Talking, 0.3f, &Data->TalkingT);
r32 TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharacterCount+1);
AC_AnimateValueDirect(TargetPctP, 0.3f, &Data->PctP);
}
//- sixten: prune any unactive characters
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharacterCount; CharacterIndex += 1)
{
scene_view_character_data *Data = SceneView->OnscreenCharacters + CharacterIndex;
if(!Data->Active && Data->ActiveT < 0.01)
{
Move(Data, Data+1, SceneView->CharacterCount-CharacterIndex-1);
SceneView->CharacterCount -= 1;
CharacterIndex -= 1;
}
}
if(Compiled && Compiled->IsValid) if(Compiled && Compiled->IsValid)
{ {
b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||Platform_KeyPress(EventList, Key_MouseLeft)); b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||Platform_KeyPress(EventList, Key_MouseLeft));
@ -289,8 +389,8 @@ static void SV_Update(memory_arena *FrameArena, vn_input *Input)
} }
} }
} }
r32 CharsPerSecond = 10.0f;//35.0f; r32 CharsPerSecond = 35.0f;//10.0f;
Textbox->CharsRevealed += Input->dtForFrame*CharsPerSecond; Textbox->CharsRevealed += dtForFrame*CharsPerSecond;
Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count); Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count);
if(Textbox->CharsRevealed < Textbox->String.Count && PlayerAction) if(Textbox->CharsRevealed < Textbox->String.Count && PlayerAction)
@ -322,6 +422,26 @@ static void SV_Update(memory_arena *FrameArena, vn_input *Input)
} }
} }
Runtime->FirstTextboxAction = Runtime->LastTextboxAction = 0; Runtime->FirstTextboxAction = Runtime->LastTextboxAction = 0;
//- sixten: apply character actions
for(scene_character_action *Action = Runtime->FirstCharacterAction; Action != 0; Action = Action->Next)
{
// sixten: find character
scene_view_character_data *Data = SV_CharacterDataFromName(Action->Target);
if(Action->State == CR_State_None)
{
Data->Active = false;
}
else
{
Data->Texture = SV_CharacterTextureFromAction(Action);
Data->TextureScale = 0.017f;
Data->Talking = true;
}
}
Runtime->FirstCharacterAction = Runtime->LastCharacterAction = 0;
} }
} }
@ -335,7 +455,24 @@ static void SV_BuildSceneView(vn_input *Input)
} }
else if(SceneView->Runtime.Compiled.IsValid) else if(SceneView->Runtime.Compiled.IsValid)
{ {
BuildScene(&SceneView->Runtime, SceneView->BackgroundTexture, &SceneView->Textbox); BuildScene(SceneView);
#if 0
UI_Tooltip
{
UI_SetNextFixedP(V2R32(0, 0));
UI_SetNextSize(UI_ChildrenSum(1, 1), UI_ChildrenSum(1, 1));
UI_Column() UI_Size(UI_TextContent(15, 1), UI_TextContent(15, 1))
{
UI_Row()
{
UI_LabelF("Character Count: %i", SceneView->CharacterCount);
if(UI_ButtonF("+").Clicked) ++SceneView->CharacterCount;
if(UI_ButtonF("-").Clicked) --SceneView->CharacterCount;
}
}
}
#endif
} }
else else
{ {

View File

@ -10,19 +10,47 @@ struct textbox
r32 CharsRevealed; r32 CharsRevealed;
}; };
struct scene_view_character_data
{
string Name;
b32 Active;
b32 Talking;
render_handle Texture;
r32 TextureScale;
r32 ActiveT;
r32 TalkingT;
r32 PctP;
};
struct scene_view struct scene_view
{ {
memory_arena *SceneArena; memory_arena *SceneArena;
// sixten: input
platform_event_list *EventList;
r32 dtForFrame;
scene_runtime Runtime; scene_runtime Runtime;
textbox Textbox; textbox Textbox;
render_handle BackgroundTexture; render_handle BackgroundTexture;
s32 TargetCharacter;
render_handle TestHappy;
render_handle TestNormal;
s32 CharacterCount;
scene_view_character_data OnscreenCharacters[16];
}; };
static void SV_SetState(scene_view *View); static void SV_SetState(scene_view *View);
static scene_view *SV_GetState(); static scene_view *SV_GetState();
static void SV_NewFrame(scene_view *View, platform_event_list *EventList, r32 dtForFrame);
static void SV_SetCurrentSource(compiled_scene *Compiled); static void SV_SetCurrentSource(compiled_scene *Compiled);
static void SV_Init(scene_view *View, memory_arena *TextboxArena); static void SV_Init(scene_view *View, memory_arena *TextboxArena);
static void SV_BuildSceneView(vn_input *Input); static void SV_BuildSceneView(vn_input *Input);
static void SV_Update(memory_arena *FrameArena);
#endif //VN_SCENE_VIEW_H #endif //VN_SCENE_VIEW_H

View File

@ -1,6 +1,12 @@
proc main proc main
{ {
@arthur(greeting) "Welcome to this fine estate!"; "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 jump main; // return to start
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

6
weeks.txt 100644
View File

@ -0,0 +1,6 @@
[0] - Characters
[1] - Environments & Time
[2] - Map & Notebook
[3] - UI
[4] - Minigames
[5] - Rendering