2023-08-22 03:19:51 +00:00
|
|
|
thread_local scene_view *ThreadLocal_SceneView = 0;
|
|
|
|
|
|
|
|
static void SV_SetState(scene_view *View)
|
|
|
|
{
|
|
|
|
ThreadLocal_SceneView = View;
|
|
|
|
}
|
|
|
|
|
|
|
|
static scene_view *SV_GetState()
|
|
|
|
{
|
|
|
|
return(ThreadLocal_SceneView);
|
|
|
|
}
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
static void SV_NewFrame(scene_view *View, platform_event_list *EventList, r32 dtForFrame)
|
|
|
|
{
|
|
|
|
SV_SetState(View);
|
|
|
|
View->EventList = EventList;
|
|
|
|
View->dtForFrame = dtForFrame;
|
|
|
|
}
|
|
|
|
|
2023-08-22 03:19:51 +00:00
|
|
|
static void SV_SetCurrentSource(compiled_scene *Compiled)
|
|
|
|
{
|
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
|
|
|
|
// sixten(TODO): extract runtime information required to seamlessly transition between compilations
|
|
|
|
|
|
|
|
ArenaClear(SceneView->SceneArena);
|
|
|
|
SceneView->Runtime.Compiled = S_CopyCompiledScene(SceneView->SceneArena, Compiled);
|
2023-10-04 17:21:15 +00:00
|
|
|
S_ResetRuntime(&SceneView->Runtime);
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void SV_Init(scene_view *SceneView, memory_arena *TextboxArena)
|
|
|
|
{
|
|
|
|
SV_SetState(SceneView);
|
|
|
|
|
|
|
|
SceneView->SceneArena = ArenaAllocate(Gigabytes(1));
|
|
|
|
SceneView->Runtime.ErrorArena = ArenaAllocate(Megabytes(1));
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
S_ResetRuntime(&SceneView->Runtime);
|
|
|
|
|
2023-08-22 03:19:51 +00:00
|
|
|
SceneView->Textbox.Capacity = 4096;
|
|
|
|
SceneView->Textbox.String.Data = PushArray(TextboxArena, u8, SceneView->Textbox.Capacity);
|
|
|
|
SceneView->Textbox.String.Count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct text_properties
|
|
|
|
{
|
|
|
|
font_id Font;
|
|
|
|
r32 FontSize;
|
|
|
|
r32 LineHeight;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void RenderAnimatedText(render_group *Group, glyph_atlas *Atlas, text_properties Properties, string Text, r32 CharsToRender, v2_r32 P, r32 WrapWidth)
|
|
|
|
{
|
|
|
|
v2_r32 Offset = V2R32(0, 0);
|
|
|
|
|
|
|
|
u8 *TextBegin = Text.Data;
|
|
|
|
u8 *TextEnd = TextBegin+Text.Count;
|
|
|
|
u8 *Byte = TextBegin;
|
|
|
|
|
|
|
|
u8 *WordBegin = TextBegin;
|
|
|
|
u8 *WordEnd = WordBegin;
|
|
|
|
u8 *TrueWordEnd = WordBegin;
|
|
|
|
|
|
|
|
string_decode LastVisibleDecode = {};
|
|
|
|
|
|
|
|
Byte = TextBegin;
|
|
|
|
for(;Byte<=TextEnd;)
|
|
|
|
{
|
|
|
|
string_decode Decode = DecodeUTF8Codepoint(Byte, TextEnd-Byte);
|
|
|
|
|
|
|
|
if(CharsToRender >= 1)
|
|
|
|
{
|
|
|
|
LastVisibleDecode = Decode;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Decode.Codepoint == ' ' || Byte==TextEnd)
|
|
|
|
{
|
|
|
|
string TrueWord = MakeString(WordBegin, TrueWordEnd);
|
|
|
|
string Word = MakeString(WordBegin, WordEnd);
|
|
|
|
r32 WordWidth = CalculateRasterizedTextWidth(Atlas, Properties.Font, Properties.FontSize, TrueWord);
|
|
|
|
if(Offset.x+WordWidth > WrapWidth)
|
|
|
|
{
|
|
|
|
Offset.x = 0;
|
|
|
|
Offset.y += Properties.LineHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
Offset.x += PushText(Group, Atlas, Properties.Font, P+Offset, Properties.FontSize, Color_White, Word);
|
|
|
|
|
|
|
|
if(WordEnd != TrueWordEnd)
|
|
|
|
{
|
|
|
|
string LastChar = MakeString(WordEnd, LastVisibleDecode.Size);
|
|
|
|
r32 TransitionAmount = Mod(CharsToRender, 1);
|
|
|
|
Offset.y += (1-TransitionAmount)*5;
|
|
|
|
PushText(Group, Atlas, Properties.Font, P+Offset, Properties.FontSize, SetAlpha(Color_White, TransitionAmount), LastChar);
|
|
|
|
}
|
|
|
|
|
|
|
|
WordBegin = TrueWordEnd;
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
if(Byte == TextEnd || CharsToRender < 1)
|
2023-08-22 03:19:51 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Byte += Decode.Size;
|
|
|
|
TrueWordEnd += Decode.Size;
|
|
|
|
if(CharsToRender >= 1)
|
|
|
|
{
|
|
|
|
WordEnd += Decode.Size;
|
|
|
|
CharsToRender -= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
|
|
|
|
static r32 CalculateGlobalScaleFromDim(v2_r32 Dim)
|
|
|
|
{
|
|
|
|
r32 GlobalScale = SquareRoot(Dim.x*Dim.y)/45;
|
|
|
|
return(GlobalScale);
|
|
|
|
}
|
2023-08-22 03:19:51 +00:00
|
|
|
static r32 CalculateGlobalScaleFromRootBox(ui_box *Box)
|
|
|
|
{
|
|
|
|
v2 RenderDim = DimOfRange(Box->Rect);
|
|
|
|
r32 GlobalScale = SquareRoot(RenderDim.x*RenderDim.y)/45;
|
|
|
|
return(GlobalScale);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct scene_textbox_data
|
|
|
|
{
|
|
|
|
textbox *Textbox;
|
|
|
|
ui_box *SceneViewBox;
|
|
|
|
};
|
|
|
|
|
|
|
|
UI_CUSTOM_DRAW_CALLBACK(BuildSceneTextboxDrawCallback)
|
|
|
|
{
|
|
|
|
scene_textbox_data *TextboxData = (scene_textbox_data *)Data;
|
|
|
|
textbox *Textbox = TextboxData->Textbox;
|
|
|
|
|
|
|
|
//- sixten: render textbox
|
|
|
|
v4 TopColor = V4(0, 0, 0, 0.8f);
|
|
|
|
v4 BottomColor = V4(0, 0, 0, 0.5f);
|
|
|
|
range2_r32 Dest = Range2R32(Box->Rect.Min, Box->Rect.Max);
|
|
|
|
PushQuad(Group, Dest, TopColor, TopColor, BottomColor, BottomColor, 0, 0, 0);
|
|
|
|
|
|
|
|
//- sixten: render text
|
|
|
|
string Text = Textbox->String;
|
|
|
|
r32 CharsRevealed = Textbox->CharsRevealed;
|
|
|
|
r32 GlobalScale = CalculateGlobalScaleFromRootBox(TextboxData->SceneViewBox);
|
|
|
|
text_properties Properties = {};
|
2023-09-05 17:50:49 +00:00
|
|
|
Properties.Font = Font_Fancy;
|
2023-08-22 03:19:51 +00:00
|
|
|
Properties.FontSize = GlobalScale;
|
|
|
|
Properties.LineHeight = GlobalScale*1.5f;
|
|
|
|
r32 Padding = 1.5f*GlobalScale;
|
|
|
|
v2 Offset = V2R32(Padding, Padding);
|
|
|
|
RenderAnimatedText(Group, Atlas, Properties, Text, CharsRevealed, Box->Rect.Min+Offset, DimOfRange(Box->Rect).x-2*Padding);
|
|
|
|
}
|
|
|
|
|
|
|
|
UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback)
|
|
|
|
{
|
2023-10-04 17:21:15 +00:00
|
|
|
scene_view *SceneView = (scene_view *)Data;
|
|
|
|
|
|
|
|
v2 RenderDim = DimOfRange(Box->Rect);
|
|
|
|
r32 GlobalScale = CalculateGlobalScaleFromDim(RenderDim);
|
2023-08-22 03:19:51 +00:00
|
|
|
|
|
|
|
//- 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.
|
2023-10-04 17:21:15 +00:00
|
|
|
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);
|
|
|
|
}
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
static void BuildScene(scene_view *View)
|
2023-08-22 03:19:51 +00:00
|
|
|
{
|
2023-10-04 17:21:15 +00:00
|
|
|
scene_runtime *Runtime = &View->Runtime;
|
|
|
|
textbox *Textbox = &View->Textbox;
|
2023-08-22 03:19:51 +00:00
|
|
|
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"));
|
2023-10-04 17:21:15 +00:00
|
|
|
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, View);
|
2023-08-22 03:19:51 +00:00
|
|
|
|
|
|
|
UI_Parent(Box)
|
|
|
|
{
|
|
|
|
UI_WidthFill UI_Height(UI_Percent(1, 0)) UI_Row() UI_FillPadding UI_Column() UI_FillPadding
|
|
|
|
{
|
|
|
|
b32 FoundOffset = false;
|
|
|
|
s64 Offset = 0;
|
|
|
|
for(s32 BranchIndex = 0; BranchIndex < Runtime->BranchCount; BranchIndex += 1)
|
|
|
|
{
|
|
|
|
branch_case *Branch = &Runtime->Branches[BranchIndex];
|
|
|
|
if(UI_ButtonF("%S#%i", Branch->Name, BranchIndex).Clicked)
|
|
|
|
{
|
|
|
|
Offset = Branch->Offset;
|
|
|
|
FoundOffset = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(FoundOffset)
|
|
|
|
{
|
|
|
|
Runtime->IP += 1+Offset;
|
|
|
|
Runtime->BranchCount = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UI_SetNextWidth(UI_Percent(1, 1));
|
|
|
|
UI_SetNextHeight(UI_Percent(0.3, 1));
|
|
|
|
ui_box *TextBox = UI_MakeBox(0, StrLit("Scene Textbox"));
|
|
|
|
scene_textbox_data *TextboxData = PushStruct(UI_FrameArena(), scene_textbox_data);
|
|
|
|
TextboxData->Textbox = Textbox;
|
|
|
|
TextboxData->SceneViewBox = Box;
|
|
|
|
UI_EquipBoxCustomDrawCallback(TextBox, BuildSceneTextboxDrawCallback, TextboxData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void BuildErrorScreen(scene_runtime *Runtime, vn_input *Input)
|
|
|
|
{
|
|
|
|
UI_SetNextLayoutAxis(Axis2_X);
|
|
|
|
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("Container")))
|
|
|
|
{
|
|
|
|
UI_Padding(UI_Em(3, 1)) UI_Width(UI_Percent(1, 0)) UI_Column() UI_Padding(UI_Em(3, 1))
|
|
|
|
{
|
|
|
|
UI_Font(Font_Bold) UI_Size(UI_TextContent(0, 1), UI_TextContent(0, 1)) UI_FontSize(32) UI_LabelF("A runtime error has occurred");
|
|
|
|
s64 ErrorIndex = 0;
|
|
|
|
for(scene_runtime_error *Error = Runtime->FirstError; Error != 0; Error = Error->Next, ErrorIndex += 1)
|
|
|
|
{
|
|
|
|
UI_Spacer(UI_Em(3, 1));
|
|
|
|
UI_SetNextCornerRadius(3);
|
|
|
|
UI_Size(UI_Percent(1, 1), UI_Percent(1, 0)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawDropShadow|UI_BoxFlag_DrawBorder, "%i", ErrorIndex))
|
|
|
|
UI_Size(UI_TextContent(30, 1), UI_TextContent(30, 1))
|
|
|
|
{
|
|
|
|
UI_LabelF("Message: %S", Error->Message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UI_Spacer(UI_Em(3, 1));
|
|
|
|
UI_Size(UI_Percent(1, 1), UI_Em(2, 1)) UI_Row()
|
|
|
|
UI_Width(UI_TextContent(30, 1)) UI_CornerRadius(4)
|
|
|
|
{
|
|
|
|
ui_signal IgnoreSignal = UI_ButtonF("Ignore");
|
|
|
|
if(IgnoreSignal.Hovering)
|
|
|
|
{
|
|
|
|
UI_TooltipLabel(StrLit("Continue running the script, may lead to more errors."), UI_MouseP());
|
|
|
|
}
|
|
|
|
if(IgnoreSignal.Clicked)
|
|
|
|
{
|
|
|
|
Runtime->FirstError = Runtime->LastError = 0;
|
|
|
|
ArenaClear(Runtime->ErrorArena);
|
|
|
|
}
|
|
|
|
|
|
|
|
UI_Spacer(UI_Em(1, 1));
|
|
|
|
|
|
|
|
ui_signal RestartSignal = UI_ButtonF("Restart");
|
|
|
|
if(RestartSignal.Hovering)
|
|
|
|
{
|
|
|
|
UI_TooltipLabel(StrLit("Restarts the script, may lose progress."), UI_MouseP());
|
|
|
|
}
|
|
|
|
if(RestartSignal.Clicked)
|
|
|
|
{
|
|
|
|
Runtime->FirstError = Runtime->LastError = 0;
|
|
|
|
Runtime->IP = 0;
|
|
|
|
Runtime->CurrentProc = 0;
|
|
|
|
ArenaClear(Runtime->ErrorArena);
|
|
|
|
}
|
|
|
|
|
|
|
|
UI_Spacer(UI_Em(1, 1));
|
|
|
|
if(UI_ButtonF("Exit Program").Clicked)
|
|
|
|
{
|
|
|
|
Input->ExitRequested = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
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)
|
2023-08-22 03:19:51 +00:00
|
|
|
{
|
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
textbox *Textbox = &SceneView->Textbox;
|
|
|
|
scene_runtime *Runtime = &SceneView->Runtime;
|
2023-10-04 17:21:15 +00:00
|
|
|
platform_event_list *EventList = SceneView->EventList;
|
|
|
|
r32 dtForFrame = SceneView->dtForFrame;
|
2023-08-22 03:19:51 +00:00
|
|
|
compiled_scene *Compiled = &Runtime->Compiled;
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
//- 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-22 03:19:51 +00:00
|
|
|
if(Compiled && Compiled->IsValid)
|
|
|
|
{
|
|
|
|
b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||Platform_KeyPress(EventList, Key_MouseLeft));
|
|
|
|
|
|
|
|
if(DLLIsEmpty(Runtime->FirstError))
|
|
|
|
{
|
|
|
|
b32 AdvanceOnAwait = (Textbox->CharsRevealed >= Textbox->String.Count) && PlayerAction;
|
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
scene_runtime_result RunResult = S_Run(Runtime, FrameArena, AdvanceOnAwait);
|
|
|
|
if(RunResult.ReachedAwait || RunResult.HadError)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-04 17:21:15 +00:00
|
|
|
r32 CharsPerSecond = 35.0f;//10.0f;
|
|
|
|
Textbox->CharsRevealed += dtForFrame*CharsPerSecond;
|
2023-08-22 03:19:51 +00:00
|
|
|
Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count);
|
|
|
|
|
|
|
|
if(Textbox->CharsRevealed < Textbox->String.Count && PlayerAction)
|
|
|
|
{
|
|
|
|
Textbox->CharsRevealed = Textbox->String.Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: apply the textbox actions
|
|
|
|
for(textbox_action *Action = Runtime->FirstTextboxAction; Action != 0; Action = Action->Next)
|
|
|
|
{
|
|
|
|
if(Action->Kind == TextboxActionKind_Set)
|
|
|
|
{
|
|
|
|
string ReplaceString = Action->String;
|
|
|
|
Textbox->String.Count = Min(ReplaceString.Count, Textbox->Capacity);
|
|
|
|
Copy(Textbox->String.Data, ReplaceString.Data, Textbox->String.Count);
|
|
|
|
Textbox->CharsRevealed = 0;
|
|
|
|
}
|
|
|
|
else if(Action->Kind == TextboxActionKind_Append)
|
|
|
|
{
|
|
|
|
string Addend = Action->String;
|
|
|
|
Textbox->CharsRevealed = Textbox->String.Count;
|
|
|
|
s64 NewCount = Min(Textbox->String.Count+Addend.Count, Textbox->Capacity-1);
|
|
|
|
Copy(Textbox->String.Data+Textbox->String.Count, Action->String.Data, NewCount-Textbox->String.Count);
|
|
|
|
Textbox->String.Count = NewCount;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
InvalidCodepath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Runtime->FirstTextboxAction = Runtime->LastTextboxAction = 0;
|
2023-10-04 17:21:15 +00:00
|
|
|
|
|
|
|
//- 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;
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SV_BuildSceneView(vn_input *Input)
|
|
|
|
{
|
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
scene_runtime_result LastRun = SceneView->Runtime.LastResult;
|
|
|
|
if(LastRun.HadError)
|
|
|
|
{
|
|
|
|
BuildErrorScreen(&SceneView->Runtime, Input);
|
|
|
|
}
|
|
|
|
else if(SceneView->Runtime.Compiled.IsValid)
|
|
|
|
{
|
2023-10-04 17:21:15 +00:00
|
|
|
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
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UI_LabelF("Invalid source");
|
|
|
|
}
|
|
|
|
}
|