2024-01-20 11:18:57 +00:00
|
|
|
#include "vn_scene_commands.cpp"
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
per_thread scene_view *ThreadLocal_SceneView = 0;
|
2023-08-22 03:19:51 +00:00
|
|
|
|
|
|
|
static void SV_SetState(scene_view *View)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
ThreadLocal_SceneView = View;
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static scene_view *SV_GetState()
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
return(ThreadLocal_SceneView);
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
static void SV_NewFrame(scene_view *View, platform_event_list *EventList, r32 dtForFrame)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
SV_SetState(View);
|
|
|
|
View->EventList = EventList;
|
|
|
|
View->dtForFrame = dtForFrame;
|
2023-10-04 17:21:15 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void SV_Reset(void)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
|
|
|
|
// sixten: reset onscreen characters
|
2024-01-20 11:18:57 +00:00
|
|
|
SceneView->CharactersUsed = 0;
|
2023-12-23 07:27:22 +00:00
|
|
|
}
|
|
|
|
|
2024-01-21 20:01:00 +00:00
|
|
|
static void SV_LoadNavItems(string FileName)
|
2023-12-23 07:27:22 +00:00
|
|
|
{
|
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
temp Scratch = GetScratch();
|
2024-01-21 20:01:00 +00:00
|
|
|
string NavData = Platform_ReadEntireFile(Scratch.Arena, FileName);
|
2023-12-23 07:27:22 +00:00
|
|
|
|
|
|
|
if(NavData.Count != 0)
|
|
|
|
{
|
|
|
|
u8 *Byte = NavData.Data;
|
|
|
|
SceneView->NavItemCount = *(u16 *)Byte;
|
|
|
|
Byte += 2;
|
|
|
|
|
|
|
|
SceneView->NavItems = PushArrayNoClear(SceneView->SceneArena, scene_nav_item, SceneView->NavItemCount);
|
|
|
|
|
|
|
|
//- sixten: parse items
|
|
|
|
for(u64 ItemIndex = 0; ItemIndex < SceneView->NavItemCount; ItemIndex += 1)
|
|
|
|
{
|
|
|
|
scene_nav_item *Item = &SceneView->NavItems[ItemIndex];
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
switch(*Byte++)
|
|
|
|
{
|
|
|
|
case S_NavItemOp_TextureID:
|
|
|
|
{
|
|
|
|
string AssetName;
|
|
|
|
AssetName.Count = *(u16 *)Byte;
|
|
|
|
Byte += sizeof(u16);
|
|
|
|
AssetName.Data = Byte;
|
|
|
|
Byte += AssetName.Count;
|
|
|
|
|
|
|
|
Item->TextureID = AssetID_Error;
|
|
|
|
for(u64 AssetIndex = 0; AssetIndex < AssetID_COUNT; AssetIndex += 1)
|
|
|
|
{
|
|
|
|
if(AreEqual(MakeString(AssetNameLUT[AssetIndex]), AssetName))
|
|
|
|
{
|
|
|
|
Item->TextureID = AssetIndex;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} goto Next;
|
|
|
|
case S_NavItemOp_Scale:
|
|
|
|
{
|
|
|
|
Item->Scale = *(r32 *)Byte;
|
|
|
|
Byte += sizeof(r32);
|
|
|
|
} goto Next;
|
|
|
|
case S_NavItemOp_Origin:
|
|
|
|
{
|
|
|
|
Item->Origin = *(v2_r32 *)Byte;
|
|
|
|
Byte += sizeof(v2_r32);
|
|
|
|
} goto Next;
|
|
|
|
case S_NavItemOp_P:
|
|
|
|
{
|
|
|
|
Item->P = *(v2_r32 *)Byte;
|
|
|
|
Byte += sizeof(v2_r32);
|
|
|
|
} goto Next;
|
|
|
|
case S_NavItemOp_HoverText:
|
|
|
|
{
|
|
|
|
Item->HoverText.Count = *(u16 *)Byte;
|
|
|
|
Byte += 2;
|
|
|
|
|
|
|
|
Item->HoverText.Data = PushArrayNoClear(SceneView->SceneArena, u8, Item->HoverText.Count);
|
|
|
|
Copy(Item->HoverText.Data, Byte, Item->HoverText.Count);
|
|
|
|
Byte += Item->HoverText.Count;
|
|
|
|
} goto Next;
|
|
|
|
case S_NavItemOp_Action:
|
|
|
|
{
|
|
|
|
Item->Action.Kind = (scene_nav_action_kind)*Byte;
|
|
|
|
Byte += 1;
|
|
|
|
|
|
|
|
Item->Action.Content.Count = *(u16 *)Byte;
|
|
|
|
Byte += 2;
|
|
|
|
|
|
|
|
Item->Action.Content.Data = PushArrayNoClear(SceneView->SceneArena, u8, Item->Action.Content.Count);
|
|
|
|
Copy(Item->Action.Content.Data, Byte, Item->Action.Content.Count);
|
|
|
|
Byte += Item->Action.Content.Count;
|
|
|
|
} goto Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: no op found, assume item done
|
|
|
|
break;
|
|
|
|
|
|
|
|
Next:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ReleaseScratch(Scratch);
|
2023-10-29 10:00:34 +00:00
|
|
|
}
|
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
static void SV_SetCurrentSource(compiled_scene2 *Compiled)
|
2023-08-22 03:19:51 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
scene_view *SceneView = SV_GetState();
|
2024-01-20 11:18:57 +00:00
|
|
|
scene2_runtime *Runtime = &SceneView->Runtime;
|
2023-12-23 07:27:22 +00:00
|
|
|
|
|
|
|
// sixten(TODO): extract runtime information required to seamlessly transition between compilations
|
|
|
|
SV_Reset();
|
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
ArenaClear(SceneView->SceneArena);
|
2023-12-23 07:27:22 +00:00
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
SceneView->Compiled = S2_CopyCompiledScene(SceneView->SceneArena, Compiled);
|
|
|
|
S2_SetCurrentProc(Runtime, S2_ProcFromName(Compiled, StrLit("main")));
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
static void SV_Init(scene_view *SceneView)
|
2023-08-22 03:19:51 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
SV_SetState(SceneView);
|
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
SceneView->SceneArena = ArenaAlloc(Kilobytes(16), true, "Scene View Scene Arena");
|
|
|
|
SceneView->MessageArena = ArenaAlloc(Kilobytes(16), true, "Scene View Message Arena");
|
|
|
|
|
|
|
|
S2_Init(&SceneView->Runtime);
|
|
|
|
|
|
|
|
SceneView->Runtime.Data = SceneView;
|
|
|
|
|
|
|
|
SV_Reset();
|
2023-10-29 10:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static b32 SV_CurrentlyInProc(void)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
scene_view *SceneView = SV_GetState();
|
2024-01-20 11:18:57 +00:00
|
|
|
b32 Result = (SceneView->Runtime.CurrentProc.Name.Count != 0);
|
2023-12-23 07:27:22 +00:00
|
|
|
return(Result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static scene_view_character_data *SV_FindTalkingCharacter(void)
|
|
|
|
{
|
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
scene_view_character_data *Result = 0;
|
2024-01-20 11:18:57 +00:00
|
|
|
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
|
2023-12-23 07:27:22 +00:00
|
|
|
{
|
|
|
|
scene_view_character_data *Character = SceneView->Characters+CharacterIndex;
|
|
|
|
if(Character->Talking)
|
|
|
|
{
|
|
|
|
Result = Character;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(Result);
|
|
|
|
}
|
|
|
|
|
2023-08-22 03:19:51 +00:00
|
|
|
struct text_properties
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
font_id Font;
|
|
|
|
r32 FontSize;
|
|
|
|
r32 LineHeight;
|
2023-08-22 03:19:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void RenderAnimatedText(render_group *Group, glyph_atlas *Atlas, text_properties Properties, string Text, r32 CharsToRender, v2_r32 P, r32 WrapWidth)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
v2_r32 Offset = V2R32(0, 0);
|
|
|
|
v2_r32 ShadowOffset = V2R32(Properties.FontSize*0.1, Properties.FontSize*0.1);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
PushText(Group, Atlas, Properties.Font, P+Offset+ShadowOffset, Properties.FontSize, Color_Black, Word);
|
|
|
|
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;
|
|
|
|
|
|
|
|
if(Byte == TextEnd || CharsToRender < 1)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Byte += Decode.Size;
|
|
|
|
TrueWordEnd += Decode.Size;
|
|
|
|
if(CharsToRender >= 1)
|
|
|
|
{
|
|
|
|
WordEnd += Decode.Size;
|
|
|
|
CharsToRender -= 1;
|
|
|
|
}
|
|
|
|
}
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
|
|
|
|
static r32 CalculateGlobalScaleFromDim(v2_r32 Dim)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
r32 GlobalScale = SquareRoot(Dim.x*Dim.y)/45;
|
|
|
|
return(GlobalScale);
|
2023-10-04 17:21:15 +00:00
|
|
|
}
|
2023-08-22 03:19:51 +00:00
|
|
|
static r32 CalculateGlobalScaleFromRootBox(ui_box *Box)
|
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
v2_r32 RenderDim = UI_CalculateBoxDim(Box);
|
2023-12-23 07:27:22 +00:00
|
|
|
r32 GlobalScale = SquareRoot(RenderDim.x*RenderDim.y)/45;
|
|
|
|
return(GlobalScale);
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct scene_textbox_data
|
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
char *TextboxData;
|
|
|
|
u64 TextboxUsed;
|
|
|
|
r32 TextboxRevealed;
|
|
|
|
ui_box *SceneViewBox;
|
2023-12-23 07:27:22 +00:00
|
|
|
string Name;
|
|
|
|
r32 NameT;
|
2023-08-22 03:19:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
UI_CUSTOM_DRAW_CALLBACK(BuildSceneTextboxDrawCallback)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
scene_textbox_data *TextboxData = (scene_textbox_data *)Data;
|
|
|
|
|
|
|
|
r32 GlobalScale = CalculateGlobalScaleFromRootBox(TextboxData->SceneViewBox);
|
|
|
|
|
|
|
|
//- sixten: render textbox
|
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
v4_r32 TopColor = V4R32(0, 0, 0, 0.8f);
|
|
|
|
v4_r32 BottomColor = V4R32(0, 0, 0, 0.5f);
|
|
|
|
range2_r32 Dest = Pad(Range2R32(Box->Rect.Min, Box->Rect.Max), V2R32(GlobalScale, GlobalScale)*2.0f);
|
2023-12-23 07:27:22 +00:00
|
|
|
PushQuad(Group, Dest, TopColor, TopColor, BottomColor, BottomColor, 0, GlobalScale, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: render text
|
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
string Text = MakeString((u8 *)TextboxData->TextboxData, TextboxData->TextboxUsed);
|
|
|
|
r32 RevealedT = TextboxData->TextboxRevealed;
|
2023-12-23 07:27:22 +00:00
|
|
|
text_properties Properties = {};
|
|
|
|
Properties.Font = Font_Fancy;
|
|
|
|
Properties.FontSize = GlobalScale;
|
|
|
|
Properties.LineHeight = GlobalScale*1.5f;
|
|
|
|
r32 Padding = 1.5f*GlobalScale;
|
2024-01-20 11:18:57 +00:00
|
|
|
v2_r32 Offset = V2R32(Padding, Padding);
|
|
|
|
RenderAnimatedText(Group, Atlas, Properties, Text, RevealedT, Box->Rect.Min+Offset, DimOfRange(Box->Rect).x-2*Padding);
|
2023-12-23 07:27:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: render character name
|
|
|
|
{
|
|
|
|
string Name = TextboxData->Name;
|
|
|
|
r32 T = TextboxData->NameT;
|
2024-01-20 11:18:57 +00:00
|
|
|
v2_r32 TextP = Box->Rect.Min + V2R32(1.5f*GlobalScale, -GlobalScale*T);
|
|
|
|
PushText(Group, Atlas, Font_Fancy, TextP+V2R32(GlobalScale*0.1, GlobalScale*0.1), GlobalScale, SetAlpha(Color_Black, T), Name);
|
2023-12-23 07:27:22 +00:00
|
|
|
PushText(Group, Atlas, Font_Fancy, TextP, GlobalScale, SetAlpha(Color_White, T), Name);
|
|
|
|
}
|
|
|
|
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
2023-12-07 15:50:57 +00:00
|
|
|
static void SV_DrawBackground(scene_view *SceneView, ui_box *Box, render_group *Group)
|
2023-08-22 03:19:51 +00:00
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
v2_r32 RenderDim = DimOfRange(Box->Rect);
|
2023-12-23 07:27:22 +00:00
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
render_handle Texture = A_TextureFromAssetID(AssetID_DemoBackground);;//A_TextureFromAssetID(SceneView->Runtime.Compiled.BackgroundTexture);
|
2023-12-23 07:27:22 +00:00
|
|
|
|
|
|
|
//- sixten: render background
|
2023-10-29 10:00:34 +00:00
|
|
|
#if 0
|
2023-12-23 07:27:22 +00:00
|
|
|
persist r32 Time = 0;
|
|
|
|
Time += 1 / 1200.0f;
|
|
|
|
r32 r = 30;
|
2024-01-20 11:18:57 +00:00
|
|
|
v2_r32 Offset = V2R32(Sin(Time)+0.5*Sin(43+2.43*Time)+Sin(424+Time*16)*0.1, Sin(8+Time)+0.5*Sin(43+2.43*Time)+Sin(4242+Time*16)*0.1)*(1.0f/1.6f)*r;
|
|
|
|
range2_r32 BackgroundDest = Range2R32(Box->Rect.Min-V2R32(r, r)+Offset, RenderDim+Box->Rect.Min+V2R32(r, r)+Offset);
|
|
|
|
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(Texture)));
|
2023-12-23 07:27:22 +00:00
|
|
|
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, Texture);
|
2023-10-29 10:00:34 +00:00
|
|
|
#else
|
2023-12-23 07:27:22 +00:00
|
|
|
range2_r32 BackgroundDest = Range2R32(Box->Rect.Min, RenderDim+Box->Rect.Min);
|
2024-01-20 11:18:57 +00:00
|
|
|
range2_r32 BackgroundSource = Range2R32(V2R32(0, 0), ConvertV2ToR32(DimFromTexture(Texture)));
|
|
|
|
PushTexturedQuad(Group, BackgroundDest, BackgroundSource, Color_White, Color_White, Color_White, Color_White, 0, 0, 0, 0, 0, 0, Texture);
|
2023-10-29 10:00:34 +00:00
|
|
|
#endif
|
2023-12-07 15:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UI_CUSTOM_DRAW_CALLBACK(BuildSceneDrawCallback)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
scene_view *SceneView = (scene_view *)Data;
|
|
|
|
|
|
|
|
SV_DrawBackground(SceneView, Box, Group);
|
2024-01-20 11:18:57 +00:00
|
|
|
v2_r32 RenderDim = DimOfRange(Box->Rect);
|
2023-12-23 07:27:22 +00:00
|
|
|
r32 GlobalScale = CalculateGlobalScaleFromDim(RenderDim);
|
|
|
|
|
|
|
|
//- sixten: render characters
|
2024-01-20 11:18:57 +00:00
|
|
|
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
|
2023-12-23 07:27:22 +00:00
|
|
|
{
|
|
|
|
scene_view_character_data *Character = SceneView->Characters + CharacterIndex;
|
|
|
|
|
|
|
|
v4_r32 BlendColor = LinearBlend(Color_White, Color_Black, 0.5-Character->TalkingT*0.5);
|
|
|
|
BlendColor.a = Character->ActiveT;
|
|
|
|
r32 Scale = (Character->Info.Scale + Character->TalkingT*0.001)*(0.95+Character->ActiveT*0.05)*GlobalScale;
|
|
|
|
render_handle CharacterHandle = Character->Info.Texture;
|
|
|
|
v2_r32 CharacterDim = ConvertV2ToR32(DimFromTexture(CharacterHandle));
|
|
|
|
v2_r32 CharacterOriginP = V2R32(RenderDim.x*Character->PctP, RenderDim.y);
|
|
|
|
v2_r32 CharacterMidP = Box->Rect.Min+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);
|
2024-01-20 11:18:57 +00:00
|
|
|
PushTexturedQuad(Group, CharacterDest, CharacterSource, BlendColor, BlendColor, BlendColor, BlendColor, 0, 0, 0, 0, 0, 0, CharacterHandle);
|
2023-12-23 07:27:22 +00:00
|
|
|
}
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
2023-12-07 15:50:57 +00:00
|
|
|
static b32 BuildSceneBranchButton(string Text, r32 GlobalScale)
|
2023-08-22 03:19:51 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
UI_SetNextFontSize(GlobalScale);
|
|
|
|
UI_SetNextFont(Font_Fancy);
|
|
|
|
UI_SetNextCornerRadius(5.0f);
|
|
|
|
|
|
|
|
b32 Result = UI_Button(Text).Clicked;
|
|
|
|
return(Result);
|
2023-12-07 15:50:57 +00:00
|
|
|
}
|
|
|
|
|
2023-12-23 07:27:22 +00:00
|
|
|
static void BuildProcView(scene_view *View, ui_box *Box, v2_r32 BoxDim)
|
|
|
|
{
|
|
|
|
temp Scratch = GetScratch();
|
|
|
|
|
|
|
|
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
|
|
|
|
r32 ActiveScale = GlobalScale * 0.75f;
|
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
//scene2_runtime *Runtime = &View->Runtime;
|
|
|
|
//textbox *Textbox = &View->Textbox;
|
2023-12-23 07:27:22 +00:00
|
|
|
|
|
|
|
//- sixten: build branches
|
|
|
|
UI_FillPadding UI_WidthFill UI_Height(UI_Pixels(2*ActiveScale, 1)) UI_Row() UI_FillPadding UI_Column() UI_FillPadding
|
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
#if 0
|
2023-12-23 07:27:22 +00:00
|
|
|
b32 FoundOffset = false;
|
|
|
|
s64 Offset = 0;
|
|
|
|
for(s32 BranchIndex = 0; BranchIndex < Runtime->BranchCount; BranchIndex += 1)
|
|
|
|
{
|
|
|
|
branch_case *Branch = &Runtime->Branches[BranchIndex];
|
|
|
|
if(BuildSceneBranchButton(PushFormat(Scratch.Arena, "%S#%i", Branch->Name, BranchIndex), ActiveScale))
|
|
|
|
{
|
|
|
|
Offset = Branch->Offset;
|
|
|
|
FoundOffset = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(BranchIndex != Runtime->BranchCount - 1)
|
|
|
|
{
|
|
|
|
UI_Spacer(UI_Em(1, 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(FoundOffset)
|
|
|
|
{
|
|
|
|
Runtime->IP += 1+Offset;
|
|
|
|
Runtime->BranchCount = 0;
|
|
|
|
}
|
2024-01-20 11:18:57 +00:00
|
|
|
#endif
|
2023-12-23 07:27:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: build textbox
|
|
|
|
UI_Size(UI_Percent(1, 1), UI_Percent(0.3, 1))
|
|
|
|
{
|
|
|
|
ui_box *TextBox = UI_MakeBox(0, StrLit("Scene Textbox"));
|
|
|
|
|
|
|
|
scene_textbox_data *TextboxData = PushStruct(UI_FrameArena(), scene_textbox_data);
|
2024-01-20 11:18:57 +00:00
|
|
|
TextboxData->TextboxData = View->TextboxData;
|
|
|
|
TextboxData->TextboxUsed = View->TextboxUsed;
|
|
|
|
TextboxData->TextboxRevealed = View->TextboxRevealed;
|
2023-12-23 07:27:22 +00:00
|
|
|
TextboxData->SceneViewBox = Box;
|
|
|
|
|
|
|
|
scene_view_character_data *TalkingCharacter = SV_FindTalkingCharacter();
|
2024-01-20 11:18:57 +00:00
|
|
|
TextboxData->Name = TalkingCharacter ? TalkingCharacter->Name : StrLit("");
|
2023-12-23 07:27:22 +00:00
|
|
|
TextboxData->NameT = AC_AnimateValueF(TalkingCharacter != 0, 0, 0.3f, "Scene View Talking Character %p", View);
|
|
|
|
|
|
|
|
UI_EquipBoxCustomDrawCallback(TextBox, BuildSceneTextboxDrawCallback, TextboxData);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseScratch(Scratch);
|
2023-12-07 15:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct scene_nav_item_info
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
scene_nav_item *Item;
|
|
|
|
ui_signal Signal;
|
2023-12-07 15:50:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
UI_CUSTOM_DRAW_CALLBACK(BuildNavItemDrawCallback)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
scene_nav_item_info *Info = (scene_nav_item_info *)Data;
|
2024-01-20 11:18:57 +00:00
|
|
|
render_handle Texture = A_TextureFromAssetID(Info->Item->TextureID);
|
2023-12-23 07:27:22 +00:00
|
|
|
v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture));
|
|
|
|
|
|
|
|
range2_r32 DestRect = Range2R32(Box->Rect.Min, Box->Rect.Max);
|
|
|
|
range2_r32 SourceRect = Range2R32(V2R32(0, 0), TextureDim);
|
|
|
|
|
|
|
|
v4_r32 Color = LinearBlend(Color_Grey, Color_White, Info->Signal.Hovering);
|
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
PushTexturedQuad(Group, DestRect, SourceRect, Color, Color, Color, Color, 0, 0, 0, 0, 0, 0, Texture);
|
2023-12-07 15:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline u32 U32FromRawR32(r32 Value)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
u32 Result = *(u32 *)&Value;
|
|
|
|
return(Result);
|
2023-12-07 15:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ui_signal SV_BuildNavItem(scene_nav_item *Item, r32 GlobalScale, v2_r32 GlobalDim)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
r32 AppliedScale = GlobalScale*Item->Scale;
|
|
|
|
|
|
|
|
scene_nav_item_info *Data = PushStruct(UI_FrameArena(), scene_nav_item_info);
|
|
|
|
Data->Item = Item;
|
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
render_handle Texture = A_TextureFromAssetID(Item->TextureID);
|
2023-12-23 07:27:22 +00:00
|
|
|
|
|
|
|
v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture));
|
|
|
|
v2_r32 TextureOrigin = Hadamard(TextureDim, Item->Origin);
|
|
|
|
|
|
|
|
v2_r32 OffsetP = GlobalDim*(V2R32(1, 1) + Item->P)*0.5f;
|
|
|
|
v2_r32 OriginP = TextureOrigin*AppliedScale;
|
|
|
|
v2_r32 Dim = TextureDim*AppliedScale;
|
|
|
|
range2_r32 Dest = Range2R32(OffsetP-OriginP, OffsetP-OriginP+Dim);
|
|
|
|
|
|
|
|
UI_SetNextFixedP(Dest.Min);
|
|
|
|
UI_SetNextSize(UI_Pixels(Dim.x, 1), UI_Pixels(Dim.y, 1));
|
|
|
|
UI_SetNextHoverCursor(PlatformCursor_Hand);
|
|
|
|
|
|
|
|
ui_box *ItemBox = UI_MakeBoxF(UI_BoxFlag_Clickable|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY,
|
2023-12-26 10:53:10 +00:00
|
|
|
"View Item Box %i %S %p",
|
|
|
|
(U32FromRawR32(Item->Scale)<<4)+
|
|
|
|
(U32FromRawR32(Item->Origin.x)<<17)+
|
|
|
|
(U32FromRawR32(Item->Origin.y)<<11),
|
|
|
|
Item->HoverText, Item);
|
2023-12-23 07:27:22 +00:00
|
|
|
UI_EquipBoxCustomDrawCallback(ItemBox, BuildNavItemDrawCallback, Data);
|
|
|
|
|
|
|
|
ui_signal Signal = UI_SignalFromBox(ItemBox);
|
|
|
|
Data->Signal = Signal;
|
|
|
|
|
|
|
|
return(Signal);
|
2023-12-07 15:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ui_signal BuildNavItemAndLabel(scene_nav_item *Item, r32 GlobalScale, v2_r32 GlobalDim)
|
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
ui_signal Signal = SV_BuildNavItem(Item, GlobalScale, GlobalDim);
|
|
|
|
if(Item->HoverText.Count && Signal.Hovering)
|
|
|
|
{
|
|
|
|
UI_FontSize(GlobalScale*0.5f) UI_Font(Font_Fancy) UI_CornerRadius(4.0f)
|
|
|
|
UI_TooltipLabel(Item->HoverText, UI_MouseP());
|
|
|
|
}
|
|
|
|
return(Signal);
|
2023-12-07 15:50:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-21 20:01:00 +00:00
|
|
|
static UI_CUSTOM_DRAW_CALLBACK(Puzzle15DrawCallback)
|
2023-12-23 07:27:22 +00:00
|
|
|
{
|
2024-01-21 20:01:00 +00:00
|
|
|
scene_view *SceneView = (scene_view *)Data;
|
|
|
|
render_handle Texture = A_TextureFromAssetID(AssetID_Duck);
|
|
|
|
v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture));
|
|
|
|
v2_r32 PieceDim = DimOfRange(Box->Rect)*0.25f;
|
|
|
|
v2_r32 Offset = Box->Rect.Min+V2R32(0, (1.0f - SceneView->BoardOpenT)*PieceDim.y);
|
|
|
|
if(SceneView->TimeSinceBoardClear < 2)
|
|
|
|
{
|
|
|
|
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
|
|
|
|
{
|
|
|
|
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
|
|
|
|
{
|
|
|
|
v2_r32 SourceDim = TextureDim*0.25f;
|
|
|
|
u8 BoardValue = SceneView->Board[BoardY][BoardX];
|
|
|
|
if(BoardValue)
|
|
|
|
{
|
|
|
|
s32 PrevBoardX = BoardX;
|
|
|
|
s32 PrevBoardY = BoardY;
|
|
|
|
if(SceneView->PrevBoard[PrevBoardY][PrevBoardX] != BoardValue)
|
|
|
|
{
|
|
|
|
for(PrevBoardY = 0; PrevBoardY < 4; PrevBoardY += 1)
|
|
|
|
{
|
|
|
|
for(PrevBoardX = 0; PrevBoardX < 4; PrevBoardX += 1)
|
|
|
|
{
|
|
|
|
if(SceneView->PrevBoard[PrevBoardY][PrevBoardX] == BoardValue)
|
|
|
|
{
|
|
|
|
goto FoundPrevTile;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FoundPrevTile:;
|
|
|
|
}
|
|
|
|
|
|
|
|
BoardValue -= 1;
|
|
|
|
s32 SourceX = BoardValue % 4;
|
|
|
|
s32 SourceY = BoardValue / 4;
|
|
|
|
|
|
|
|
v2_r32 BoardP = LinearBlend(V2R32(PrevBoardX, PrevBoardY), V2R32(BoardX, BoardY), Clamp01(Pow(SceneView->TimeSinceBoardUpdate*5, 4)));
|
|
|
|
|
|
|
|
range2_r32 Source = Range2R32(V2R32(SourceX*SourceDim.x, SourceY*SourceDim.y), V2R32((SourceX+1)*SourceDim.x, (SourceY+1)*SourceDim.y));
|
|
|
|
range2_r32 Dest = Range2R32(Offset+BoardP*PieceDim, Offset+(BoardP+V2R32(1, 1))*PieceDim);
|
|
|
|
v4_r32 Color = SetAlpha(Color_White, SceneView->BoardOpenT);
|
|
|
|
PushTexturedQuad(Group, Dest, Source, Color, Color, Color, Color, 3, 3, 3, 3, 1.5f, 0, Texture);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(SceneView->BoardIsComplete)
|
|
|
|
{
|
|
|
|
r32 CompleteT = Clamp01(Pow(SceneView->TimeSinceBoardClear, 5))*Clamp01(3-SceneView->TimeSinceBoardClear);
|
|
|
|
range2_r32 Source = Range2R32(V2R32(0, 0), TextureDim);
|
|
|
|
range2_r32 Dest = Pad(Box->Rect, PieceDim*(1.0f-CompleteT));
|
|
|
|
v4_r32 Color = SetAlpha(Color_White, CompleteT);
|
|
|
|
PushTexturedQuad(Group, Dest, Source, Color, Color, Color, Color, 3, 3, 3, 3, 1.5f, 0, Texture);
|
|
|
|
}
|
2023-12-07 15:50:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-21 20:01:00 +00:00
|
|
|
static void BuildScene(scene_view *SceneView)
|
2023-12-07 15:50:57 +00:00
|
|
|
{
|
2024-01-21 20:01:00 +00:00
|
|
|
v2_r32 ParentDim = UI_CalculateBoxDim(UI_TopParent());
|
|
|
|
|
|
|
|
r32 TargetRatio = 16.0f/9.0f;
|
|
|
|
r32 ActualRatio = ParentDim.x/ParentDim.y;
|
|
|
|
|
|
|
|
v2_r32 BoxDim = ParentDim;
|
|
|
|
|
|
|
|
if(ActualRatio > TargetRatio)
|
|
|
|
{
|
|
|
|
BoxDim.x = BoxDim.y*TargetRatio;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BoxDim.y = BoxDim.x/TargetRatio;
|
|
|
|
}
|
|
|
|
|
|
|
|
UI_SetNextWidth(UI_Pixels(BoxDim.x, 1));
|
|
|
|
UI_SetNextHeight(UI_Pixels(BoxDim.y, 1));
|
|
|
|
UI_SetNextLayoutAxis(Axis2_Y);
|
|
|
|
UI_SetNextFixedP((ParentDim-BoxDim)*0.5f);
|
|
|
|
ui_box *Box = UI_MakeBox(UI_BoxFlag_Clip|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, StrLit("Scene View"));
|
|
|
|
UI_EquipBoxCustomDrawCallback(Box, BuildSceneDrawCallback, SceneView);
|
|
|
|
|
|
|
|
r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim);
|
|
|
|
|
|
|
|
UI_Parent(Box)
|
|
|
|
{
|
|
|
|
switch(SceneView->Mode)
|
|
|
|
{
|
|
|
|
case SV_Mode_Scene:
|
|
|
|
{
|
|
|
|
// sixten(NOTE): when this is rewritten, put it inside THIS function.
|
|
|
|
BuildProcView(SceneView, Box, BoxDim);
|
|
|
|
} break;
|
|
|
|
case SV_Mode_Nav:
|
|
|
|
{
|
|
|
|
for(int ItemIndex = 0; ItemIndex < SceneView->NavItemCount; ++ItemIndex)
|
|
|
|
{
|
|
|
|
scene_nav_item *Item = SceneView->NavItems+ItemIndex;
|
|
|
|
if(BuildNavItemAndLabel(Item, GlobalScale, BoxDim).Clicked)
|
|
|
|
{
|
|
|
|
// sixten: apply the action
|
|
|
|
if(Item->Action.Kind == S_NavAction_Proc)
|
|
|
|
{
|
|
|
|
S2_SetCurrentProc(&SceneView->Runtime, S2_ProcFromName(&SceneView->Compiled, Item->Action.Content));
|
|
|
|
}
|
|
|
|
else if(Item->Action.Kind == S_NavAction_Scene)
|
|
|
|
{
|
|
|
|
temp Scratch = GetScratch();
|
|
|
|
string Filepath = PushFormat(Scratch.Arena, "data/%S.vns", Item->Action.Content);;
|
|
|
|
|
|
|
|
string SceneInput = Platform_ReadEntireFile(Scratch.Arena, Filepath);
|
|
|
|
compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, SceneInput);
|
|
|
|
SV_SetCurrentSource(&Scene);
|
|
|
|
|
|
|
|
ReleaseScratch(Scratch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case SV_Mode_P15:
|
|
|
|
{
|
|
|
|
UI_WidthFill UI_HeightFill UI_BackgroundColor(SetAlpha(Color_Black, 0.5*SceneView->BoardOpenT*Clamp01(2-SceneView->TimeSinceBoardClear*0.5))) UI_LayoutAxis(Axis2_X)
|
|
|
|
UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBackground, StrLit("15 Puzzle Darken")))
|
|
|
|
{
|
|
|
|
UI_Padding(UI_Percent(1, 0)) UI_Width(UI_ChildrenSum(1, 1)) UI_Column() UI_Padding(UI_Percent(1, 0))
|
|
|
|
{
|
|
|
|
UI_SetNextSize(UI_Em(25, 1), UI_Em(25, 1));
|
|
|
|
ui_box *PuzzleBox = UI_MakeBox(0, StrLit("Puzzle Box"));
|
|
|
|
UI_EquipBoxCustomDrawCallback(PuzzleBox, Puzzle15DrawCallback, SceneView);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
2024-01-20 11:18:57 +00:00
|
|
|
static void BuildErrorScreen(scene_view *SceneView, vn_input *Input)
|
2023-08-22 03:19:51 +00:00
|
|
|
{
|
2024-01-21 20:01:00 +00:00
|
|
|
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;
|
2024-01-20 11:18:57 +00:00
|
|
|
for(scene2_message *Message = SceneView->Messages.First; Message != 0; Message = Message->Next, ErrorIndex += 1)
|
2024-01-21 20:01:00 +00:00
|
|
|
{
|
|
|
|
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))
|
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
UI_Label(Message->Message);
|
2024-01-21 20:01:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
ZeroStruct(&SceneView->Messages);
|
|
|
|
ArenaClear(SceneView->MessageArena);
|
2024-01-21 20:01:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
SV_Reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
UI_Spacer(UI_Em(1, 1));
|
|
|
|
if(UI_ButtonF("Exit Program").Clicked)
|
|
|
|
{
|
|
|
|
Input->ExitRequested = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
2023-10-04 17:21:15 +00:00
|
|
|
static scene_view_character_data *SV_CharacterDataFromName(string Name)
|
|
|
|
{
|
2024-01-21 20:01:00 +00:00
|
|
|
scene_view_character_data *Result = 0;
|
2024-01-20 11:18:57 +00:00
|
|
|
|
2024-01-21 20:01:00 +00:00
|
|
|
scene_view *View = SV_GetState();
|
|
|
|
|
|
|
|
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
|
|
|
|
{
|
|
|
|
scene_view_character_data *Character = View->Characters + CharacterIndex;
|
|
|
|
if(AreEqual(Character->Name, Name))
|
|
|
|
{
|
|
|
|
Result = Character;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: create character if not initialized
|
|
|
|
if(!Result && View->CharactersUsed < ArrayCount(View->Characters))
|
|
|
|
{
|
|
|
|
s32 CharacterIndex = View->CharactersUsed;
|
|
|
|
View->CharactersUsed += 1;
|
2024-01-20 11:18:57 +00:00
|
|
|
|
2024-01-21 20:01:00 +00:00
|
|
|
Result = View->Characters + CharacterIndex;
|
|
|
|
*Result = {};
|
|
|
|
Result->Name = Name;
|
|
|
|
Result->Active = true;
|
|
|
|
Result->PctP = (r32)(CharacterIndex + 1) / (View->CharactersUsed + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(Result);
|
2023-10-29 10:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static r32 SV_CalculateTargetPctP(s32 TrueCharacterIndex)
|
|
|
|
{
|
2024-01-21 20:01:00 +00:00
|
|
|
scene_view *View = SV_GetState();
|
|
|
|
s32 CharacterCount = 0;
|
|
|
|
s32 AssumedCharacterIndex = 0;
|
|
|
|
for(s32 CharacterIndex = 0; CharacterIndex < View->CharactersUsed; CharacterIndex += 1)
|
|
|
|
{
|
|
|
|
scene_view_character_data *Data = View->Characters + CharacterIndex;
|
|
|
|
if(Data->Active)
|
|
|
|
{
|
|
|
|
CharacterCount += 1;
|
|
|
|
if(CharacterIndex < TrueCharacterIndex)
|
|
|
|
{
|
|
|
|
AssumedCharacterIndex += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r32 Result = (r32)(AssumedCharacterIndex + 1) / (Max(CharacterCount, 1) + 1);
|
|
|
|
return(Result);
|
2023-10-04 17:21:15 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void SV_UpdateInDialog(arena *FrameArena)
|
2023-08-22 03:19:51 +00:00
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
|
|
|
|
//- sixten: gather user input
|
|
|
|
b32 MousePressed = false;
|
|
|
|
for(platform_event *Event = SceneView->EventList->First; Event != 0; Event = Event->Next)
|
|
|
|
{
|
|
|
|
if(Event->Type == PlatformEvent_Press && Event->Key == Key_MouseLeft)
|
|
|
|
{
|
|
|
|
MousePressed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
b32 PlayerAction = (Platform_KeyPress(SceneView->EventList, Key_Space)||MousePressed);
|
|
|
|
|
|
|
|
//- sixten: check if we can skip the current textbox
|
|
|
|
if(PlayerAction && SceneView->TextboxRevealed < SceneView->TextboxUsed)
|
|
|
|
{
|
|
|
|
PlayerAction = false;
|
|
|
|
SceneView->TextboxRevealed = SceneView->TextboxUsed;
|
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: update the textbox
|
|
|
|
r32 CharsPerSecond = 25.0f;
|
|
|
|
SceneView->TextboxRevealed = Min((r32)SceneView->TextboxUsed, SceneView->TextboxRevealed+CharsPerSecond*SceneView->dtForFrame);
|
|
|
|
|
|
|
|
|
|
|
|
//- sixten: run the runtime
|
|
|
|
scene2_run_result RunResult = S2_Run(FrameArena, &SceneView->Runtime, &SceneView->Compiled, PlayerAction);
|
|
|
|
|
|
|
|
//- sixten: append messages
|
|
|
|
S2_ConcatMessageList(SceneView->MessageArena, &SceneView->Messages, &RunResult.Messages);
|
|
|
|
|
|
|
|
for(scene2_action *Action = RunResult.Actions.First; Action != 0; Action = Action->Next)
|
|
|
|
{
|
|
|
|
switch(Action->Kind)
|
|
|
|
{
|
|
|
|
case S2_ActionKind_None: { InvalidCodepath; } break;
|
|
|
|
InvalidDefaultCase;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
textbox *Textbox = &SceneView->Textbox;
|
|
|
|
scene2_runtime *Runtime = &SceneView->Runtime;
|
|
|
|
platform_event_list *EventList = SceneView->EventList;
|
|
|
|
r32 dtForFrame = SceneView->dtForFrame;
|
|
|
|
compiled_scene2 *Compiled = &Runtime->Compiled;
|
|
|
|
|
|
|
|
if(Compiled && Compiled->IsValid)
|
|
|
|
{
|
|
|
|
//- sixten: gather user input
|
|
|
|
b32 MousePressed = false;
|
|
|
|
for(platform_event *Event = EventList->First; Event != 0; Event = Event->Next)
|
|
|
|
{
|
|
|
|
if(Event->Type == PlatformEvent_Press && Event->Key == Key_MouseLeft)
|
|
|
|
{
|
|
|
|
MousePressed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
b32 PlayerAction = (Platform_KeyPress(EventList, Key_Space)||MousePressed);
|
|
|
|
|
|
|
|
//- sixten: run the scene
|
|
|
|
if(!Runtime->LastResult.HadError)
|
|
|
|
{
|
|
|
|
b32 AdvanceOnAwait = (Textbox->CharsRevealed >= Textbox->String.Count) && PlayerAction;
|
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
scene_runtime_result RunResult = S_Run(Runtime, FrameArena, AdvanceOnAwait);
|
|
|
|
if(RunResult.ReachedAwait || RunResult.HadError)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: advance textbox
|
|
|
|
{
|
|
|
|
r32 CharsPerSecond = 25.0f;
|
|
|
|
Textbox->CharsRevealed += dtForFrame*CharsPerSecond;
|
|
|
|
Textbox->CharsRevealed = Min(Textbox->CharsRevealed, (r32)Textbox->String.Count);
|
|
|
|
|
|
|
|
if(Textbox->CharsRevealed < Textbox->String.Count && PlayerAction)
|
|
|
|
{
|
|
|
|
Textbox->CharsRevealed = Textbox->String.Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
AC_AnimateValueDirect(Textbox->CharsRevealed, 0.05f, &Textbox->CharsRevealedT);
|
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: apply the textbox actions
|
|
|
|
for(scene_textbox_action *Action = Runtime->FirstTextboxAction; Action != 0; Action = Action->Next)
|
|
|
|
{
|
|
|
|
if(Action->Kind == S_TextboxActionKind_Set)
|
|
|
|
{
|
|
|
|
string ReplaceString = Action->String;
|
|
|
|
Textbox->String.Count = Min(ReplaceString.Count, Textbox->Capacity);
|
|
|
|
Copy(Textbox->String.Data, ReplaceString.Data, Textbox->String.Count);
|
|
|
|
Textbox->CharsRevealedT = 0;
|
|
|
|
Textbox->CharsRevealed = 0;
|
|
|
|
}
|
|
|
|
else if(Action->Kind == S_TextboxActionKind_Append)
|
|
|
|
{
|
|
|
|
string Addend = Action->String;
|
|
|
|
Textbox->CharsRevealedT = 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;
|
|
|
|
|
|
|
|
// sixten: update character state only if there has been a change
|
|
|
|
if(Runtime->FirstCharacterAction != 0)
|
|
|
|
{
|
|
|
|
//- sixten: make all characters non-talking
|
|
|
|
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
|
|
|
|
{
|
|
|
|
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
|
|
|
|
Data->Talking = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//- 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->StateModified)
|
|
|
|
{
|
|
|
|
if(Action->State == AssetID_None)
|
|
|
|
{
|
|
|
|
Data->Active = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Data->Info = SV_CharacterTextureFromAction(Action);
|
|
|
|
Data->Talking = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Data->Talking = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Runtime->FirstCharacterAction = Runtime->LastCharacterAction = 0;
|
|
|
|
}
|
|
|
|
#endif
|
2023-08-22 03:19:51 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void SV_Update(arena *FrameArena)
|
|
|
|
{
|
2024-01-21 20:01:00 +00:00
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
|
|
|
|
//- sixten: update the characters
|
|
|
|
{
|
|
|
|
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
|
|
|
|
{
|
|
|
|
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
|
|
|
|
|
|
|
|
if(!SV_CurrentlyInProc())
|
|
|
|
{
|
|
|
|
Data->Active = false;
|
|
|
|
Data->Talking = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
AC_AnimateValueDirect(Data->Active, 0.5f, &Data->ActiveT);
|
|
|
|
AC_AnimateValueDirect(Data->Talking, 0.4f, &Data->TalkingT);
|
|
|
|
|
|
|
|
r32 TargetPctP;
|
|
|
|
if(Data->Active)
|
|
|
|
{
|
|
|
|
TargetPctP = SV_CalculateTargetPctP(CharacterIndex);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TargetPctP = (r32)(CharacterIndex+1)/(SceneView->CharactersUsed+1);
|
|
|
|
}
|
|
|
|
AC_AnimateValueDirect(TargetPctP, 0.4f, &Data->PctP);
|
|
|
|
}
|
2024-01-20 11:18:57 +00:00
|
|
|
|
|
|
|
// sixten: prune any unactive characters
|
|
|
|
for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1)
|
|
|
|
{
|
|
|
|
scene_view_character_data *Data = SceneView->Characters + CharacterIndex;
|
|
|
|
if(!Data->Active && Data->ActiveT < 0.01)
|
|
|
|
{
|
|
|
|
Move(Data, Data+1, (SceneView->CharactersUsed-CharacterIndex-1)*sizeof(scene_view_character_data));
|
|
|
|
SceneView->CharactersUsed -= 1;
|
|
|
|
CharacterIndex -= 1;
|
|
|
|
}
|
|
|
|
}
|
2024-01-21 20:01:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// sixten(HACK): if a scene has been triggered, switch mode
|
|
|
|
if(SceneView->Mode == SV_Mode_Nav && SV_CurrentlyInProc())
|
|
|
|
{
|
|
|
|
SceneView->Mode = SV_Mode_Scene;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(SceneView->Mode)
|
|
|
|
{
|
|
|
|
case SV_Mode_Scene:
|
|
|
|
{
|
|
|
|
//- sixten: gather user input
|
|
|
|
b32 MousePressed = false;
|
|
|
|
for(platform_event *Event = SceneView->EventList->First; Event != 0; Event = Event->Next)
|
|
|
|
{
|
|
|
|
if(Event->Type == PlatformEvent_Press && Event->Key == Key_MouseLeft)
|
|
|
|
{
|
|
|
|
MousePressed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
b32 PlayerAction = (Platform_KeyPress(SceneView->EventList, Key_Space)||MousePressed);
|
|
|
|
|
|
|
|
//- sixten: check if we can skip the current textbox
|
|
|
|
if(PlayerAction && SceneView->TextboxRevealed < SceneView->TextboxUsed)
|
|
|
|
{
|
|
|
|
PlayerAction = false;
|
|
|
|
SceneView->TextboxRevealed = SceneView->TextboxUsed;
|
|
|
|
}
|
|
|
|
|
|
|
|
//- sixten: update the textbox
|
|
|
|
r32 CharsPerSecond = 25.0f;
|
|
|
|
SceneView->TextboxRevealed = Min((r32)SceneView->TextboxUsed, SceneView->TextboxRevealed+CharsPerSecond*SceneView->dtForFrame);
|
|
|
|
|
|
|
|
//- sixten: run the runtime
|
|
|
|
scene2_run_result RunResult = S2_Run(FrameArena, &SceneView->Runtime, &SceneView->Compiled, PlayerAction);
|
|
|
|
|
|
|
|
//- sixten: append messages
|
|
|
|
S2_ConcatMessageList(SceneView->MessageArena, &SceneView->Messages, &RunResult.Messages);
|
|
|
|
|
|
|
|
for(scene2_action *Action = RunResult.Actions.First; Action != 0; Action = Action->Next)
|
|
|
|
{
|
|
|
|
switch(Action->Kind)
|
|
|
|
{
|
|
|
|
case S2_ActionKind_None: { InvalidCodepath; } break;
|
|
|
|
InvalidDefaultCase;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// sixten: check if the scene is finished
|
|
|
|
if(!SV_CurrentlyInProc() && SceneView->Mode == SV_Mode_Scene)
|
|
|
|
{
|
|
|
|
SceneView->Mode = SV_Mode_Nav;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case SV_Mode_Nav:
|
|
|
|
{
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case SV_Mode_P15:
|
|
|
|
{
|
|
|
|
SceneView->TimeSinceBoardUpdate += SceneView->dtForFrame;
|
|
|
|
AC_AnimateValueDirect(1, 2.0f, &SceneView->BoardOpenT);
|
|
|
|
|
|
|
|
if(SceneView->BoardIsComplete)
|
|
|
|
{
|
|
|
|
SceneView->TimeSinceBoardClear += SceneView->dtForFrame;
|
|
|
|
if(SceneView->TimeSinceBoardClear > 3.5f)
|
|
|
|
{
|
|
|
|
SceneView->Mode = SV_Mode_Scene;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
v2_s32 BoardDelta = V2S32(0, 0);
|
|
|
|
|
|
|
|
if(Platform_KeyPress(SceneView->EventList, Key_Up)) { BoardDelta.y += 1; }
|
|
|
|
if(Platform_KeyPress(SceneView->EventList, Key_Down)) { BoardDelta.y -= 1; }
|
|
|
|
if(Platform_KeyPress(SceneView->EventList, Key_Left)) { BoardDelta.x += 1; }
|
|
|
|
if(Platform_KeyPress(SceneView->EventList, Key_Right)) { BoardDelta.x -= 1; }
|
|
|
|
|
|
|
|
if(BoardDelta.x != 0 || BoardDelta.y != 0)
|
|
|
|
{
|
|
|
|
if(BoardDelta.x && BoardDelta.y)
|
|
|
|
{
|
|
|
|
BoardDelta.y = 0;
|
|
|
|
}
|
|
|
|
// sixten: find the current empty square
|
|
|
|
v2_s32 EmptyP = V2S32(-10, -10);
|
|
|
|
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
|
|
|
|
{
|
|
|
|
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
|
|
|
|
{
|
|
|
|
if(SceneView->Board[BoardY][BoardX] == 0)
|
|
|
|
{
|
|
|
|
EmptyP = V2S32(BoardX, BoardY);
|
|
|
|
goto FoundEmptyP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FoundEmptyP:;
|
|
|
|
|
|
|
|
// sixten: check if we are able to perform an action
|
|
|
|
range2_s32 BoardRange = Range2S32(V2S32(0, 0), V2S32(4, 4));
|
|
|
|
v2_s32 NewEmptyP = EmptyP+BoardDelta;
|
|
|
|
if(InRange(BoardRange, NewEmptyP))
|
|
|
|
{
|
|
|
|
SceneView->TimeSinceBoardUpdate = 0;
|
|
|
|
Copy(SceneView->PrevBoard, SceneView->Board, sizeof(SceneView->Board));
|
|
|
|
|
|
|
|
SceneView->Board[EmptyP.y][EmptyP.x] = SceneView->Board[NewEmptyP.y][NewEmptyP.x];
|
|
|
|
SceneView->Board[NewEmptyP.y][NewEmptyP.x] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// sixten: check if board is completed
|
|
|
|
b32 BoardIsComplete = true;
|
|
|
|
for(s32 BoardY = 0; BoardY < 4; BoardY += 1)
|
|
|
|
{
|
|
|
|
for(s32 BoardX = 0; BoardX < 4; BoardX += 1)
|
|
|
|
{
|
|
|
|
if(SceneView->Board[BoardY][BoardX] != (1+BoardX+BoardY*4)%16)
|
|
|
|
{
|
|
|
|
BoardIsComplete = false;
|
|
|
|
goto BoardNotComplete;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BoardNotComplete:;
|
|
|
|
|
|
|
|
if(BoardIsComplete)
|
|
|
|
{
|
|
|
|
SceneView->BoardIsComplete = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
2023-10-29 10:00:34 +00:00
|
|
|
}
|
|
|
|
|
2023-08-22 03:19:51 +00:00
|
|
|
static void SV_BuildSceneView(vn_input *Input)
|
|
|
|
{
|
2024-01-20 11:18:57 +00:00
|
|
|
scene_view *SceneView = SV_GetState();
|
|
|
|
if(SceneView->Messages.Count != 0)
|
|
|
|
{
|
|
|
|
BuildErrorScreen(SceneView, Input);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BuildScene(SceneView);
|
|
|
|
}
|
2024-01-21 20:01:00 +00:00
|
|
|
}
|