Started animating characters
|
@ -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_GetTexParameterfv(GLenum target, GLenum pname, GLfloat *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 GLboolean opengl_IsTexture(GLuint texture);
|
||||
typedef void opengl_LineWidth(GLfloat width);
|
||||
|
@ -121,6 +122,7 @@ global opengl_GetTexLevelParameterfv *glGetTexLevelParameterfv = 0;
|
|||
global opengl_GetTexLevelParameteriv *glGetTexLevelParameteriv = 0;
|
||||
global opengl_GetTexParameterfv *glGetTexParameterfv = 0;
|
||||
global opengl_GetTexParameteriv *glGetTexParameteriv = 0;
|
||||
global opengl_GenerateMipmap *glGenerateMipmap = 0;
|
||||
global opengl_Hint *glHint = 0;
|
||||
global opengl_IsTexture *glIsTexture = 0;
|
||||
global opengl_LineWidth *glLineWidth = 0;
|
||||
|
@ -212,6 +214,7 @@ glGetTexLevelParameterfv = (opengl_GetTexLevelParameterfv *)OpenGL_LoadFunction(
|
|||
glGetTexLevelParameteriv = (opengl_GetTexLevelParameteriv *)OpenGL_LoadFunction("glGetTexLevelParameteriv");
|
||||
glGetTexParameterfv = (opengl_GetTexParameterfv *)OpenGL_LoadFunction("glGetTexParameterfv");
|
||||
glGetTexParameteriv = (opengl_GetTexParameteriv *)OpenGL_LoadFunction("glGetTexParameteriv");
|
||||
glGenerateMipmap = (opengl_GenerateMipmap *)OpenGL_LoadFunction("glGenerateMipmap");
|
||||
glHint = (opengl_Hint *)OpenGL_LoadFunction("glHint");
|
||||
glIsTexture = (opengl_IsTexture *)OpenGL_LoadFunction("glIsTexture");
|
||||
glLineWidth = (opengl_LineWidth *)OpenGL_LoadFunction("glLineWidth");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
enum character_state
|
||||
{
|
||||
CR_State_Invalid = 0,
|
||||
CR_State_None,
|
||||
CR_State_Normal,
|
||||
CR_State_Happy,
|
||||
};
|
||||
|
|
@ -36,6 +36,7 @@ OpenGLFunctions:
|
|||
{GetTexLevelParameteriv `void` `GLenum target, GLint level, GLenum pname, GLint *params`}
|
||||
{GetTexParameterfv `void` `GLenum target, GLenum pname, GLfloat *params`}
|
||||
{GetTexParameteriv `void` `GLenum target, GLenum pname, GLint *params`}
|
||||
{GenerateMipmap `void` `GLenum target` }
|
||||
{Hint `void` `GLenum target, GLenum mode`}
|
||||
{IsTexture `GLboolean` `GLuint texture`}
|
||||
{LineWidth `void` `GLfloat width`}
|
||||
|
|
|
@ -98,9 +98,22 @@ static RENDER_ALLOCATE_TEXTURE(OpenGL_AllocateTexture)
|
|||
|
||||
glBindTexture(GL_TEXTURE_2D, Texture.ID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Dim.x, Dim.y, 0, InternalFormat, GL_UNSIGNED_BYTE, Data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
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_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
render_handle Handle = OpenGL_GetHandleFromTexture(Texture);
|
||||
return(Handle);
|
||||
|
@ -631,7 +644,7 @@ static opengl_context OpenGL_SetupContext(vn_render_commands *RenderCommands, um
|
|||
#endif
|
||||
|
||||
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->FillRegion = OpenGL_FillRegion;
|
||||
|
|
38
code/vn.cpp
|
@ -22,12 +22,12 @@ global debug_settings *DEBUG_DebugSettings = 0;
|
|||
#include "vn_text_op.h"
|
||||
#include "vn_ui.h"
|
||||
#include "vn_ui_utils.h"
|
||||
#include "vn_character.h"
|
||||
#include "vn_scene.h"
|
||||
#include "vn_scene_view.h"
|
||||
#include "vn_workspace.h"
|
||||
#include "vn_animation_curve.h"
|
||||
#include "vn_theme_dark.h"
|
||||
#include "vn_character.h"
|
||||
|
||||
#include "vn_tokenizer.cpp"
|
||||
#include "vn_config.cpp"
|
||||
|
@ -53,6 +53,7 @@ struct vn_state
|
|||
ui UI;
|
||||
workspace Workspace;
|
||||
animation_curve_state AnimationCurveState;
|
||||
b32 EditorMode;
|
||||
|
||||
character_registry CharacterRegistry;
|
||||
render_handle BackgroundTexture;
|
||||
|
@ -88,7 +89,7 @@ static render_handle CreateTextureFromPath(vn_render_commands *Commands, string
|
|||
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);
|
||||
|
||||
|
@ -98,7 +99,6 @@ static render_handle CreateTextureFromPath(vn_render_commands *Commands, string
|
|||
return(Result);
|
||||
}
|
||||
|
||||
|
||||
VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
||||
{
|
||||
SetThreadContext(ThreadContext);
|
||||
|
@ -137,20 +137,23 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
|||
//- sixten: load startup scene
|
||||
scene_view *SceneView = &State->SceneView;
|
||||
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;
|
||||
|
||||
//- sixten: create mock characters
|
||||
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);
|
||||
W_Init(&State->Workspace);
|
||||
AC_Init(&State->AnimationCurveState);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if VN_INTERNAL
|
||||
|
@ -161,13 +164,18 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
|||
ArenaClear(State->FrameArena);
|
||||
AC_NewFrame(&State->AnimationCurveState, Input->dtForFrame);
|
||||
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
|
||||
UI_BeginBuild(RenderCommands->RenderDim);
|
||||
{
|
||||
b32 EditorMode = false;
|
||||
if(EditorMode)
|
||||
if(State->EditorMode)
|
||||
{
|
||||
W_Update(&State->Workspace, RenderCommands, Input, State->GlyphAtlas);
|
||||
}
|
||||
|
@ -180,7 +188,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender)
|
|||
|
||||
|
||||
//- sixten: update the scene
|
||||
SV_Update(State->FrameArena, Input);
|
||||
SV_Update(State->FrameArena);
|
||||
|
||||
//- sixten: consume all remaining evetns
|
||||
for(platform_event *Event = Input->EventList->First;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "generated/vn_character.meta.c"
|
||||
|
||||
global character_registry *Global_CharacterRegistry = 0;
|
||||
|
||||
////////////////////////////////
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#ifndef VN_CHARACTER_H
|
||||
#define VN_CHARACTER_H
|
||||
|
||||
#include "generated/vn_character.meta.h"
|
||||
|
||||
////////////////////////////////
|
||||
//~ sixten: Character String Chunk Types
|
||||
#define CHARACTER_STRING_CHUNK_DATA_SIZE (64 - sizeof(character_string_chunk *))
|
||||
|
@ -21,7 +23,6 @@ struct character_string_list
|
|||
s64 StringCount;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
//~ sixten: Character Registry Types
|
||||
struct character_entry
|
||||
|
@ -62,4 +63,9 @@ static character_list CR_GetCharacters(void);
|
|||
static void CR_Init(void);
|
||||
static character_entry *CR_EntryFromName(string Name);
|
||||
|
||||
////////////////////////////////
|
||||
//~ sixten: Misc. Character Functions
|
||||
static character_state CR_CharacterStateFromString(string Input);
|
||||
static string CR_StringFromCharacterState(character_state State);
|
||||
|
||||
#endif //VN_CHARACTER_H
|
||||
|
|
|
@ -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);`;
|
||||
`}`;
|
||||
}
|
|
@ -115,7 +115,7 @@ static glyph_atlas *CreateGlyphAtlas(vn_render_commands *RenderCommands,
|
|||
Atlas->Glyphs = PushArray(Atlas->Arena, glyph, Atlas->MaxGlyphCount);
|
||||
|
||||
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_Bold].Data = Platform_ReadEntireFile(Atlas->Arena, StrLit("fonts/Roboto-Bold.ttf"));
|
||||
|
|
|
@ -134,7 +134,7 @@ static platform_api Platform;
|
|||
|
||||
#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);
|
||||
|
||||
#define RENDER_FILL_REGION(name) void name(render_handle Handle, v2_s32 DestP, v2_s32 DestDim, void *Data)
|
||||
|
|
|
@ -112,42 +112,45 @@ static void PushTexturedQuad(render_group *Group,
|
|||
{
|
||||
vn_render_commands *Commands = Group->Commands;
|
||||
|
||||
render_command_instanced_quads *Command = (render_command_instanced_quads *)(Group->CurrentCommand + 1);
|
||||
s32 TextureIndex;
|
||||
if(!(Group->CurrentCommand && Group->CurrentCommand->Type == Render_Command_render_command_instanced_quads &&
|
||||
(TextureIndex = GetTextureIndexForCommand(&Command->Mapping, Texture)) != -1))
|
||||
if(!AreEqual(Texture, EmptyRenderHandle()))
|
||||
{
|
||||
Command = PushCommand(Group, render_command_instanced_quads);
|
||||
TextureIndex = GetTextureIndexForCommand(&Command->Mapping, Texture);
|
||||
Command->QuadBufferIndex = Commands->InstancedQuadCount;
|
||||
}
|
||||
|
||||
//if(InRange(Clip, Dest.Min) || InRange(Clip, Dest.Max))
|
||||
{
|
||||
v2_s32 TextureSize = DimFromTexture(Texture);
|
||||
v2_r32 TextureSizeReal = ConvertV2ToR32(TextureSize);
|
||||
|
||||
Source.Min /= TextureSizeReal;
|
||||
Source.Max /= TextureSizeReal;
|
||||
render_command_instanced_quads *Command = (render_command_instanced_quads *)(Group->CurrentCommand + 1);
|
||||
s32 TextureIndex;
|
||||
if(!(Group->CurrentCommand && Group->CurrentCommand->Type == Render_Command_render_command_instanced_quads &&
|
||||
(TextureIndex = GetTextureIndexForCommand(&Command->Mapping, Texture)) != -1))
|
||||
{
|
||||
Command = PushCommand(Group, render_command_instanced_quads);
|
||||
TextureIndex = GetTextureIndexForCommand(&Command->Mapping, Texture);
|
||||
Command->QuadBufferIndex = Commands->InstancedQuadCount;
|
||||
}
|
||||
|
||||
//if(InRange(Clip, Dest.Min) || InRange(Clip, Dest.Max))
|
||||
{
|
||||
v2_s32 TextureSize = DimFromTexture(Texture);
|
||||
v2_r32 TextureSizeReal = ConvertV2ToR32(TextureSize);
|
||||
|
||||
Source.Min /= TextureSizeReal;
|
||||
Source.Max /= TextureSizeReal;
|
||||
|
||||
#if 0
|
||||
Dest.Min.x = Round(Dest.Min.x);
|
||||
Dest.Min.y = Round(Dest.Min.y);
|
||||
Dest.Min.x = Round(Dest.Min.x);
|
||||
Dest.Min.y = Round(Dest.Min.y);
|
||||
#endif
|
||||
|
||||
instanced_quad *Quad = Commands->InstancedQuadBase + Commands->InstancedQuadCount++;
|
||||
Quad->Dest = Dest;
|
||||
Quad->Source = Source;
|
||||
Quad->TextureIndex = TextureIndex;
|
||||
Quad->Color[0] = PackV4ToU32(Color00);
|
||||
Quad->Color[1] = PackV4ToU32(Color01);
|
||||
Quad->Color[2] = PackV4ToU32(Color10);
|
||||
Quad->Color[3] = PackV4ToU32(Color11);
|
||||
Quad->CornerRadius = CornerRadius;
|
||||
Quad->EdgeSoftness = EdgeSoftness;
|
||||
Quad->BorderThickness = BorderThickness;
|
||||
|
||||
Command->QuadCount += 1;
|
||||
|
||||
instanced_quad *Quad = Commands->InstancedQuadBase + Commands->InstancedQuadCount++;
|
||||
Quad->Dest = Dest;
|
||||
Quad->Source = Source;
|
||||
Quad->TextureIndex = TextureIndex;
|
||||
Quad->Color[0] = PackV4ToU32(Color00);
|
||||
Quad->Color[1] = PackV4ToU32(Color01);
|
||||
Quad->Color[2] = PackV4ToU32(Color10);
|
||||
Quad->Color[3] = PackV4ToU32(Color11);
|
||||
Quad->CornerRadius = CornerRadius;
|
||||
Quad->EdgeSoftness = EdgeSoftness;
|
||||
Quad->BorderThickness = BorderThickness;
|
||||
|
||||
Command->QuadCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -160,96 +163,99 @@ static void PushTexturedQuad(render_group *Group,
|
|||
{
|
||||
vn_render_commands *Commands = Group->Commands;
|
||||
|
||||
render_command_quads *Command = (render_command_quads *)(Group->CurrentCommand + 1);
|
||||
s32 TextureIndex;
|
||||
if(!(Group->CurrentCommand && Group->CurrentCommand->Type == Render_Command_render_command_quads &&
|
||||
(TextureIndex = GetTextureIndexForCommand(&Command->Mapping, Texture)) != -1))
|
||||
if(!AreEqual(Texture, EmptyRenderHandle()))
|
||||
{
|
||||
Command = PushCommand(Group, render_command_quads);
|
||||
Command->QuadBufferIndex = Commands->QuadIndexCount;
|
||||
TextureIndex = GetTextureIndexForCommand(&Command->Mapping, Texture);
|
||||
}
|
||||
|
||||
range2_r32 Clip = Group->ClipStack[Group->ClipStackUsed];
|
||||
|
||||
v2 DestMin = Max(Dest.Min, Clip.Min);
|
||||
v2 DestMax = Min(Dest.Max, Clip.Max);
|
||||
|
||||
// sixten(TODO): Proper aabb overlap testing here!
|
||||
if(InRange(Clip, Dest.Min) || InRange(Clip, Dest.Max))
|
||||
{
|
||||
v2 HalfSize = DimOfRange(Dest)*0.5;
|
||||
render_command_quads *Command = (render_command_quads *)(Group->CurrentCommand + 1);
|
||||
s32 TextureIndex;
|
||||
if(!(Group->CurrentCommand && Group->CurrentCommand->Type == Render_Command_render_command_quads &&
|
||||
(TextureIndex = GetTextureIndexForCommand(&Command->Mapping, Texture)) != -1))
|
||||
{
|
||||
Command = PushCommand(Group, render_command_quads);
|
||||
Command->QuadBufferIndex = Commands->QuadIndexCount;
|
||||
TextureIndex = GetTextureIndexForCommand(&Command->Mapping, Texture);
|
||||
}
|
||||
|
||||
v2 P00 = V2(DestMin.x, DestMin.y);
|
||||
v2 P01 = V2(DestMin.x, DestMax.y);
|
||||
v2 P10 = V2(DestMax.x, DestMin.y);
|
||||
v2 P11 = V2(DestMax.x, DestMax.y);
|
||||
v2 Center = (DestMin + DestMax)*0.5;
|
||||
range2_r32 Clip = Group->ClipStack[Group->ClipStackUsed];
|
||||
|
||||
v2 TextureSize = V2(Texture.U32[2], Texture.U32[3]);
|
||||
v2 DestMin = Max(Dest.Min, Clip.Min);
|
||||
v2 DestMax = Min(Dest.Max, Clip.Max);
|
||||
|
||||
Source.Min /= TextureSize;
|
||||
Source.Max /= TextureSize;
|
||||
|
||||
v2 Source00 = Source.Min;
|
||||
v2 Source01 = V2(Source.Min.x, Source.Max.y);
|
||||
v2 Source10 = V2(Source.Max.x, Source.Min.y);
|
||||
v2 Source11 = Source.Max;;
|
||||
|
||||
s32 BaseVertex = Commands->QuadVertexCount;
|
||||
|
||||
quad_vertex *Vertex = Commands->QuadVertexBase + Commands->QuadVertexCount++;
|
||||
Vertex->P = P00;
|
||||
Vertex->SourceP = Source00;
|
||||
Vertex->TextureIndex = TextureIndex;
|
||||
Vertex->Color = PackV4ToU32(Color00);
|
||||
Vertex->ToCenter = Center - P00;
|
||||
Vertex->HalfSize = HalfSize;
|
||||
Vertex->CornerRadius = CornerRadius;
|
||||
Vertex->EdgeSoftness = EdgeSoftness;
|
||||
Vertex->BorderThickness = BorderThickness;
|
||||
|
||||
Vertex = Commands->QuadVertexBase + Commands->QuadVertexCount++;
|
||||
Vertex->P = P10;
|
||||
Vertex->SourceP = Source10;
|
||||
Vertex->TextureIndex = TextureIndex;
|
||||
Vertex->Color = PackV4ToU32(Color10);
|
||||
Vertex->ToCenter = Center - P10;
|
||||
Vertex->HalfSize = HalfSize;
|
||||
Vertex->CornerRadius = CornerRadius;
|
||||
Vertex->EdgeSoftness = EdgeSoftness;
|
||||
Vertex->BorderThickness = BorderThickness;
|
||||
|
||||
Vertex = Commands->QuadVertexBase + Commands->QuadVertexCount++;
|
||||
Vertex->P = P01;
|
||||
Vertex->SourceP = Source01;
|
||||
Vertex->TextureIndex = TextureIndex;
|
||||
Vertex->Color = PackV4ToU32(Color01);
|
||||
Vertex->ToCenter = Center - P01;
|
||||
Vertex->HalfSize = HalfSize;
|
||||
Vertex->CornerRadius = CornerRadius;
|
||||
Vertex->EdgeSoftness = EdgeSoftness;
|
||||
Vertex->BorderThickness = BorderThickness;
|
||||
|
||||
Vertex = Commands->QuadVertexBase + Commands->QuadVertexCount++;
|
||||
Vertex->P = P11;
|
||||
Vertex->SourceP = Source11;
|
||||
Vertex->TextureIndex = TextureIndex;
|
||||
Vertex->Color = PackV4ToU32(Color11);
|
||||
Vertex->ToCenter = Center - P11;
|
||||
Vertex->HalfSize = HalfSize;
|
||||
Vertex->CornerRadius = CornerRadius;
|
||||
Vertex->EdgeSoftness = EdgeSoftness;
|
||||
Vertex->BorderThickness = BorderThickness;
|
||||
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 0;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 3;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 1;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 0;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 2;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 3;
|
||||
|
||||
++Command->QuadCount;
|
||||
// sixten(TODO): Proper aabb overlap testing here!
|
||||
if(InRange(Clip, Dest.Min) || InRange(Clip, Dest.Max))
|
||||
{
|
||||
v2 HalfSize = DimOfRange(Dest)*0.5;
|
||||
|
||||
v2 P00 = V2(DestMin.x, DestMin.y);
|
||||
v2 P01 = V2(DestMin.x, DestMax.y);
|
||||
v2 P10 = V2(DestMax.x, DestMin.y);
|
||||
v2 P11 = V2(DestMax.x, DestMax.y);
|
||||
v2 Center = (DestMin + DestMax)*0.5;
|
||||
|
||||
v2 TextureSize = V2(Texture.U32[2], Texture.U32[3]);
|
||||
|
||||
Source.Min /= TextureSize;
|
||||
Source.Max /= TextureSize;
|
||||
|
||||
v2 Source00 = Source.Min;
|
||||
v2 Source01 = V2(Source.Min.x, Source.Max.y);
|
||||
v2 Source10 = V2(Source.Max.x, Source.Min.y);
|
||||
v2 Source11 = Source.Max;;
|
||||
|
||||
s32 BaseVertex = Commands->QuadVertexCount;
|
||||
|
||||
quad_vertex *Vertex = Commands->QuadVertexBase + Commands->QuadVertexCount++;
|
||||
Vertex->P = P00;
|
||||
Vertex->SourceP = Source00;
|
||||
Vertex->TextureIndex = TextureIndex;
|
||||
Vertex->Color = PackV4ToU32(Color00);
|
||||
Vertex->ToCenter = Center - P00;
|
||||
Vertex->HalfSize = HalfSize;
|
||||
Vertex->CornerRadius = CornerRadius;
|
||||
Vertex->EdgeSoftness = EdgeSoftness;
|
||||
Vertex->BorderThickness = BorderThickness;
|
||||
|
||||
Vertex = Commands->QuadVertexBase + Commands->QuadVertexCount++;
|
||||
Vertex->P = P10;
|
||||
Vertex->SourceP = Source10;
|
||||
Vertex->TextureIndex = TextureIndex;
|
||||
Vertex->Color = PackV4ToU32(Color10);
|
||||
Vertex->ToCenter = Center - P10;
|
||||
Vertex->HalfSize = HalfSize;
|
||||
Vertex->CornerRadius = CornerRadius;
|
||||
Vertex->EdgeSoftness = EdgeSoftness;
|
||||
Vertex->BorderThickness = BorderThickness;
|
||||
|
||||
Vertex = Commands->QuadVertexBase + Commands->QuadVertexCount++;
|
||||
Vertex->P = P01;
|
||||
Vertex->SourceP = Source01;
|
||||
Vertex->TextureIndex = TextureIndex;
|
||||
Vertex->Color = PackV4ToU32(Color01);
|
||||
Vertex->ToCenter = Center - P01;
|
||||
Vertex->HalfSize = HalfSize;
|
||||
Vertex->CornerRadius = CornerRadius;
|
||||
Vertex->EdgeSoftness = EdgeSoftness;
|
||||
Vertex->BorderThickness = BorderThickness;
|
||||
|
||||
Vertex = Commands->QuadVertexBase + Commands->QuadVertexCount++;
|
||||
Vertex->P = P11;
|
||||
Vertex->SourceP = Source11;
|
||||
Vertex->TextureIndex = TextureIndex;
|
||||
Vertex->Color = PackV4ToU32(Color11);
|
||||
Vertex->ToCenter = Center - P11;
|
||||
Vertex->HalfSize = HalfSize;
|
||||
Vertex->CornerRadius = CornerRadius;
|
||||
Vertex->EdgeSoftness = EdgeSoftness;
|
||||
Vertex->BorderThickness = BorderThickness;
|
||||
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 0;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 3;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 1;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 0;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 2;
|
||||
Commands->QuadIndexBase[Commands->QuadIndexCount++] = BaseVertex + 3;
|
||||
|
||||
++Command->QuadCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -233,28 +233,38 @@ static void S_ParseDeclaration(scene_compiler *Compiler)
|
|||
case TokenKind_At:
|
||||
{
|
||||
Compiler->At += 1;
|
||||
|
||||
token IdentifierToken = S_ConsumeToken(Compiler, TokenKind_Identifier, "Expected identifier after '@'");
|
||||
S_EmitConstant(Compiler, S_MakeSourceRef(IdentifierToken));
|
||||
|
||||
if(Compiler->At->Kind == TokenKind_ParenthesisOpen)
|
||||
{
|
||||
Compiler->At += 1;
|
||||
token StateToken = S_ConsumeToken(Compiler, TokenKind_Identifier, "Expected character state.");
|
||||
S_ConsumeToken(Compiler, TokenKind_ParenthesisClose, "Expected ')' after character state.");
|
||||
|
||||
S_EmitConstant(Compiler, S_MakeSourceRef(StateToken));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
S_EmitConstant(Compiler, S_MakeNil());
|
||||
}
|
||||
|
||||
S_EmitByte(Compiler, S_Op_ShowCharacter);
|
||||
|
||||
if(Compiler->At->Kind == TokenKind_Semicolon)
|
||||
{
|
||||
Compiler->At += 1;
|
||||
}
|
||||
} break;
|
||||
case TokenKind_StringLiteral:
|
||||
{
|
||||
S_ParseExpression(Compiler);
|
||||
S_EmitByte(Compiler, S_Op_LineEntry);
|
||||
|
||||
//- sixten: parse tags
|
||||
{
|
||||
b32 EmitAwait = true;
|
||||
scene_line_entry_flag Flags = 0;
|
||||
b32 EmitClear = true;
|
||||
for(;Compiler->At[0].Kind == TokenKind_PoundSign;)
|
||||
{
|
||||
Compiler->At += 1;
|
||||
|
@ -262,7 +272,7 @@ static void S_ParseDeclaration(scene_compiler *Compiler)
|
|||
string TagString = T_StringFromToken(Compiler->Text, TagToken);
|
||||
if(AreEqual(TagString, StrLit("noclear")))
|
||||
{
|
||||
Flags |= S_LineEntryFlag_NoClear;
|
||||
EmitClear = false;
|
||||
}
|
||||
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)
|
||||
{
|
||||
S_EmitByte(Compiler, S_Op_AwaitInput);
|
||||
|
@ -810,6 +827,33 @@ static scene_value S_PopStack(scene_runtime *Runtime)
|
|||
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)
|
||||
{
|
||||
scene_runtime_result Result = {};
|
||||
|
@ -818,6 +862,7 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
|
|||
Assert(Runtime != 0);
|
||||
Assert(Compiled->IsValid);
|
||||
|
||||
//- sixten: default to the main proc
|
||||
if(Runtime->CurrentProc == 0)
|
||||
{
|
||||
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_ReadValue() Compiled->Values[S_ReadU32()]
|
||||
|
||||
//- sixten: run the bytecode interpreter
|
||||
if(Runtime->CurrentProc)
|
||||
{
|
||||
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:
|
||||
{
|
||||
Runtime->IP += 1;
|
||||
scene_value Value1 = S_PopStack(Runtime);
|
||||
scene_value Value2 = S_PopStack(Runtime);
|
||||
scene_value Value1 = S_PopStackAndImplicitConvert(Runtime);
|
||||
scene_value Value2 = S_PopStackAndImplicitConvert(Runtime);
|
||||
if(Value1.Kind == S_ValueKind_Number && Value2.Kind == S_ValueKind_Number)
|
||||
{
|
||||
S_PushStack(Runtime, S_MakeNumber(Value1.Number + Value2.Number));
|
||||
|
@ -979,37 +1025,71 @@ static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameAre
|
|||
Result.ReachedAwait = true;
|
||||
} break;
|
||||
|
||||
default:
|
||||
case S_Op_ClearDialog:
|
||||
{
|
||||
if(Data[Runtime->IP] & S_Op_LineEntry)
|
||||
textbox_action *Action = PushStructNoClear(FrameArena, textbox_action);
|
||||
Action->Kind = TextboxActionKind_Set;
|
||||
Action->String = StrLit("");
|
||||
QueuePush(Runtime->FirstTextboxAction, Runtime->LastTextboxAction, Action);
|
||||
|
||||
Runtime->IP += 1;
|
||||
} break;
|
||||
|
||||
case S_Op_ShowCharacter:
|
||||
{
|
||||
Runtime->IP += 1;
|
||||
|
||||
scene_value State = S_PopStackAndImplicitConvert(Runtime);
|
||||
scene_value CharacterValue = S_PopStackAndImplicitConvert(Runtime);
|
||||
|
||||
string Character = StrLit("");
|
||||
if(CharacterValue.Kind == S_ValueKind_String)
|
||||
{
|
||||
textbox_action *Action = PushStructNoClear(FrameArena, textbox_action);
|
||||
if(Data[Runtime->IP] & S_LineEntryFlag_NoClear)
|
||||
{
|
||||
Action->Kind = TextboxActionKind_Append;
|
||||
}
|
||||
else
|
||||
{
|
||||
Action->Kind = TextboxActionKind_Set;
|
||||
}
|
||||
|
||||
Runtime->IP += 1;
|
||||
|
||||
scene_value Value = S_PopStack(Runtime);
|
||||
if(Value.Kind == S_ValueKind_SourceRef)
|
||||
{
|
||||
Action->String = Substring(Compiled->Source, Pad(Value.SourceRef, -1));
|
||||
QueuePush(Runtime->FirstTextboxAction, Runtime->LastTextboxAction, Action);
|
||||
}
|
||||
else
|
||||
{
|
||||
S_RuntimeErrorF(Runtime, "Incorrect value kind when retrieving line entry.");
|
||||
}
|
||||
Character = CharacterValue.String;
|
||||
}
|
||||
else
|
||||
{
|
||||
S_RuntimeErrorF(Runtime, "Unknown bytecode op: 0x%02x", Data[Runtime->IP]);
|
||||
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;
|
||||
|
||||
scene_value Value = S_PopStack(Runtime);
|
||||
if(Value.Kind == S_ValueKind_SourceRef)
|
||||
{
|
||||
Action->String = Substring(Compiled->Source, Pad(Value.SourceRef, -1));
|
||||
QueuePush(Runtime->FirstTextboxAction, Runtime->LastTextboxAction, Action);
|
||||
}
|
||||
else
|
||||
{
|
||||
S_RuntimeErrorF(Runtime, "Incorrect value kind when retrieving line entry.");
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
S_RuntimeErrorF(Runtime, "Unknown bytecode op: 0x%02x", Data[Runtime->IP]);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,12 +26,6 @@ struct scene_compile_error_list
|
|||
s64 Count;
|
||||
};
|
||||
|
||||
typedef u64 scene_line_entry_flag;
|
||||
enum
|
||||
{
|
||||
S_LineEntryFlag_NoClear = (1<<0),
|
||||
};
|
||||
|
||||
enum scene_opcode
|
||||
{
|
||||
S_Op_Invalid = 0,
|
||||
|
@ -65,10 +59,9 @@ enum scene_opcode
|
|||
S_Op_Halt,
|
||||
|
||||
S_Op_AwaitInput,
|
||||
|
||||
S_Op_ClearDialog,
|
||||
S_Op_LineEntry,
|
||||
S_Op_ShowCharacter,
|
||||
|
||||
S_Op_LineEntry = 0x80, // sixten(NOTE): All opcoodes above are reserved.
|
||||
};
|
||||
|
||||
struct scene_bytecode_chunk
|
||||
|
@ -113,6 +106,7 @@ struct scene_value
|
|||
b32 Boolean;
|
||||
u64 Pointer;
|
||||
range1_s64 SourceRef;
|
||||
string String;
|
||||
s64 Offset;
|
||||
};
|
||||
};
|
||||
|
@ -171,18 +165,13 @@ struct scene_branch_case
|
|||
scene_value *EndOffsetValue;
|
||||
};
|
||||
|
||||
struct scene_character
|
||||
struct scene_character_action
|
||||
{
|
||||
string Name;
|
||||
scene_character *Next;
|
||||
scene_character *Prev;
|
||||
};
|
||||
|
||||
struct scene_character_bucket
|
||||
{
|
||||
scene_character *First;
|
||||
scene_character *Last;
|
||||
s64 Count;
|
||||
scene_character_action *Next;
|
||||
scene_character_action *Prev;
|
||||
|
||||
string Target;
|
||||
character_state State;
|
||||
};
|
||||
|
||||
struct scene_compiler
|
||||
|
@ -283,9 +272,9 @@ struct scene_runtime
|
|||
compiled_scene Compiled;
|
||||
|
||||
// sixten: runtime state
|
||||
memory_arena *RuntimeArena;
|
||||
scene_proc *CurrentProc;
|
||||
s64 IP;
|
||||
memory_arena *Arena;
|
||||
scene_runtime_stack Stack;
|
||||
|
||||
// sixten: errors
|
||||
|
@ -300,6 +289,8 @@ struct scene_runtime
|
|||
// sixten: result
|
||||
textbox_action *FirstTextboxAction;
|
||||
textbox_action *LastTextboxAction;
|
||||
scene_character_action *FirstCharacterAction;
|
||||
scene_character_action *LastCharacterAction;
|
||||
branch_case *FirstBranchCase;
|
||||
scene_runtime_result LastResult;
|
||||
};
|
||||
|
@ -425,6 +416,7 @@ static compiled_scene S_CopyCompiledScene(memory_arena *Arena, compiled_scene *C
|
|||
////////////////////////////////
|
||||
//~ sixten: Scene Runtime Functions
|
||||
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);
|
||||
|
||||
#endif //VN_SCENE_H
|
||||
|
|
|
@ -10,6 +10,13 @@ static scene_view *SV_GetState()
|
|||
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)
|
||||
{
|
||||
scene_view *SceneView = SV_GetState();
|
||||
|
@ -18,9 +25,7 @@ static void SV_SetCurrentSource(compiled_scene *Compiled)
|
|||
|
||||
ArenaClear(SceneView->SceneArena);
|
||||
SceneView->Runtime.Compiled = S_CopyCompiledScene(SceneView->SceneArena, Compiled);
|
||||
SceneView->Runtime.IP = 0;
|
||||
SceneView->Runtime.Stack.Count = 0;
|
||||
SceneView->Runtime.BranchCount = 0;
|
||||
S_ResetRuntime(&SceneView->Runtime);
|
||||
}
|
||||
|
||||
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->Runtime.ErrorArena = ArenaAllocate(Megabytes(1));
|
||||
|
||||
S_ResetRuntime(&SceneView->Runtime);
|
||||
|
||||
SceneView->Textbox.Capacity = 4096;
|
||||
SceneView->Textbox.String.Data = PushArray(TextboxArena, u8, SceneView->Textbox.Capacity);
|
||||
SceneView->Textbox.String.Count = 0;
|
||||
|
@ -89,7 +96,7 @@ static void RenderAnimatedText(render_group *Group, glyph_atlas *Atlas, text_pro
|
|||
|
||||
WordBegin = TrueWordEnd;
|
||||
|
||||
if(Byte==TextEnd || CharsToRender < 1)
|
||||
if(Byte == TextEnd || CharsToRender < 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
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(TODO, but soon): Currently we add Box->Rect.Min to everything, but that should really be a transform
|
||||
// on the render group.
|
||||
v2 RenderDim = DimOfRange(Box->Rect);
|
||||
range2_r32 Dest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min);
|
||||
range2_r32 Source = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(RenderData->BackgroundTexture)));
|
||||
PushTexturedQuad(Group, Dest, Source, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, RenderData->BackgroundTexture);
|
||||
range2_r32 BackgroundDest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min);
|
||||
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(SceneView->BackgroundTexture)));
|
||||
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, SceneView->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_SetNextHeight(UI_Percent(1, 0));
|
||||
UI_SetNextLayoutAxis(Axis2_Y);
|
||||
ui_box *Box = UI_MakeBox(0, StrLit("Scene View"));
|
||||
scene_render_data *Data = PushStruct(UI_FrameArena(), scene_render_data);
|
||||
Data->BackgroundTexture = BackgroundTexture;
|
||||
Data->Runtime = Runtime;
|
||||
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, Data);
|
||||
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View);
|
||||
|
||||
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();
|
||||
textbox *Textbox = &SceneView->Textbox;
|
||||
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;
|
||||
|
||||
//- 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)
|
||||
{
|
||||
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;
|
||||
Textbox->CharsRevealed += Input->dtForFrame*CharsPerSecond;
|
||||
r32 CharsPerSecond = 35.0f;//10.0f;
|
||||
Textbox->CharsRevealed += dtForFrame*CharsPerSecond;
|
||||
Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count);
|
||||
|
||||
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;
|
||||
|
||||
//- 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)
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -10,19 +10,47 @@ struct textbox
|
|||
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
|
||||
{
|
||||
memory_arena *SceneArena;
|
||||
|
||||
// sixten: input
|
||||
platform_event_list *EventList;
|
||||
r32 dtForFrame;
|
||||
|
||||
scene_runtime Runtime;
|
||||
textbox Textbox;
|
||||
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 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_Init(scene_view *View, memory_arena *TextboxArena);
|
||||
static void SV_BuildSceneView(vn_input *Input);
|
||||
static void SV_Update(memory_arena *FrameArena);
|
||||
|
||||
#endif //VN_SCENE_VIEW_H
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
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
|
||||
}
|
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 2.3 MiB |
After Width: | Height: | Size: 263 KiB |
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 262 KiB |
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 2.2 MiB |