diff --git a/code/generated/vn_assets.meta.c b/code/generated/vn_assets.meta.c index 939ad01..47c203f 100644 --- a/code/generated/vn_assets.meta.c +++ b/code/generated/vn_assets.meta.c @@ -1,4 +1,4 @@ -char * AssetPathLUT[7] = +char * AssetPathLUT[8] = { "", "backgrounds/unknown.png", @@ -7,9 +7,10 @@ char * AssetPathLUT[7] = "characters/test_normal.png", "characters/test_happy.png", "characters/monika_leaning.png", +"puzzles/duck.png", }; -bool AssetIsPermanentLUT[7] = +bool AssetIsPermanentLUT[8] = { true, true, @@ -18,9 +19,10 @@ false, false, false, false, +false, }; -char * AssetNameLUT[7] = +char * AssetNameLUT[8] = { "None", "Error", @@ -29,9 +31,10 @@ char * AssetNameLUT[7] = "ArthurNormal", "ArthurHappy", "MonikaLeaning", +"Duck", }; -r32 AssetScaleLUT[7] = +r32 AssetScaleLUT[8] = { 0, 0, @@ -40,5 +43,6 @@ r32 AssetScaleLUT[7] = 0.017, 0.017, 0.033, +1, }; diff --git a/code/generated/vn_assets.meta.h b/code/generated/vn_assets.meta.h index 0233f87..e9848f3 100644 --- a/code/generated/vn_assets.meta.h +++ b/code/generated/vn_assets.meta.h @@ -1,10 +1,10 @@ -extern char * AssetPathLUT[7]; +extern char * AssetPathLUT[8]; -extern bool AssetIsPermanentLUT[7]; +extern bool AssetIsPermanentLUT[8]; -extern char * AssetNameLUT[7]; +extern char * AssetNameLUT[8]; -extern r32 AssetScaleLUT[7]; +extern r32 AssetScaleLUT[8]; typedef s32 asset_id; enum @@ -16,6 +16,7 @@ AssetID_DDLCBackground, AssetID_ArthurNormal, AssetID_ArthurHappy, AssetID_MonikaLeaning, +AssetID_Duck, AssetID_COUNT, }; diff --git a/code/generated/vn_scene2.meta.h b/code/generated/vn_scene2.meta.h index 474efb1..1c9e3a3 100644 --- a/code/generated/vn_scene2.meta.h +++ b/code/generated/vn_scene2.meta.h @@ -133,6 +133,8 @@ static S2_CALL_FUNCTION(S2_Call_CharacterSet); // sets the state of a charac static S2_CALL_FUNCTION(S2_Call_CharacterRemove); // removes a character static S2_CALL_FUNCTION(S2_Call_CharacterSetTalking); // makes a character talking static S2_CALL_FUNCTION(S2_Call_CharacterUnsetAllTalking); // makes no characters talking +static S2_CALL_FUNCTION(S2_Call_NavLoad); // loads a nav scene +static S2_CALL_FUNCTION(S2_Call_Puzzle15); // plays the 15-puzzle global read_only scene2_call_function *S2_CallBindingLookup[] = { @@ -146,6 +148,8 @@ S2_Call_CharacterSet, S2_Call_CharacterRemove, S2_Call_CharacterSetTalking, S2_Call_CharacterUnsetAllTalking, +S2_Call_NavLoad, +S2_Call_Puzzle15, }; global read_only string S2_CallNameLookup[] = @@ -160,5 +164,7 @@ StrComp("ctr_set"), StrComp("ctr_remove"), StrComp("ctr_set_talking"), StrComp("ctr_unset_all_talking"), +StrComp("nav_load"), +StrComp("puzzle_15"), }; diff --git a/code/vn.cpp b/code/vn.cpp index 7f625b7..8513c05 100644 --- a/code/vn.cpp +++ b/code/vn.cpp @@ -132,7 +132,7 @@ VN_UPDATE_AND_RENDER(VN_UpdateAndRender) //- sixten: load startup scene temp Scratch = GetScratch(); - compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, Platform_ReadEntireFile(Scratch.Arena, StrLit("data/while_test.vns"))); + compiled_scene2 Scene = S2_CompiledFromString(Scratch.Arena, Platform_ReadEntireFile(Scratch.Arena, StrLit("data/omori.vns"))); SV_SetCurrentSource(&Scene); ReleaseScratch(Scratch); diff --git a/code/vn_assets.md b/code/vn_assets.md index 2aa2133..b8ce0b3 100644 --- a/code/vn_assets.md +++ b/code/vn_assets.md @@ -18,6 +18,11 @@ //- sixten: monika { MonikaLeaning, "characters/monika_leaning.png", false, 0.033 } + //////////////////////////////// + //~ sixten: puzzles + + { Duck, "puzzles/duck.png", false, 1 } + } diff --git a/code/vn_scene2.cpp b/code/vn_scene2.cpp index d74a324..5ec92df 100644 --- a/code/vn_scene2.cpp +++ b/code/vn_scene2.cpp @@ -1021,5 +1021,9 @@ static scene2_run_result S2_Run(arena *Arena, scene2_runtime *Runtime, compiled_ } Done:; + if(Runtime->InstructionPointer >= ProcInfo->InstructionEnd) + { + S2_SetCurrentProc(Runtime, S_EmptyProcInfo); + } return(Result); } \ No newline at end of file diff --git a/code/vn_scene2.h b/code/vn_scene2.h index 6b9f57e..5112ea0 100644 --- a/code/vn_scene2.h +++ b/code/vn_scene2.h @@ -91,6 +91,8 @@ struct scene2_proc_info u64 InstructionEnd; }; +global scene2_proc_info S_EmptyProcInfo = {StrComp(""), 0, 0}; + struct scene2_proc_node { scene2_proc_node *Next; @@ -286,7 +288,7 @@ static b32 S2_ObjectIsTrue(scene2_object Object); static compiled_scene2 S2_CompiledFromString(arena *Arena, string String); static compiled_scene2 S2_CopyCompiledScene(arena *Arena, compiled_scene2 *Source); -static void S2_SetCurrentProc(scene2_runtime *Runtime, scene2_proc_info *Info); +static void S2_SetCurrentProc(scene2_runtime *Runtime, scene2_proc_info Info); static scene2_proc_info S2_ProcFromName(compiled_scene2 *Compiled, string Name); #endif //VN_SCENE2_H diff --git a/code/vn_scene2.md b/code/vn_scene2.md index b93e8e1..babc9c2 100644 --- a/code/vn_scene2.md +++ b/code/vn_scene2.md @@ -77,6 +77,11 @@ { ctr_set_talking, S2_Call_CharacterSetTalking, "makes a character talking" }, { ctr_unset_all_talking, S2_Call_CharacterUnsetAllTalking, "makes no characters talking" }, + // sixten: nav management calls + { nav_load, S2_Call_NavLoad, "loads a nav scene" }, + + // sixten: puzzle management calls + { puzzle_15, S2_Call_Puzzle15, "plays the 15-puzzle" }, } @table_gen diff --git a/code/vn_scene_commands.cpp b/code/vn_scene_commands.cpp index ec2973a..2bdb22d 100644 --- a/code/vn_scene_commands.cpp +++ b/code/vn_scene_commands.cpp @@ -135,9 +135,9 @@ static S2_CALL_FUNCTION(S2_Call_CharacterRemove) string Target = TargetObject.As.String; - scene_view_character_data *CharacterBegin = SceneView->Characters; - scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed; - scene_view_character_data *Character = CharacterBegin; + scene_view_character_data *CharacterBegin = SceneView->Characters; + scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed; + scene_view_character_data *Character = CharacterBegin; // sixten: check if the character exists for(;Character < CharacterEnd; Character += 1) @@ -200,3 +200,60 @@ static S2_CALL_FUNCTION(S2_Call_CharacterUnsetAllTalking) Character->Talking = false; } } + +static void SV_LoadNavItems(string FileName); +static S2_CALL_FUNCTION(S2_Call_NavLoad) +{ + scene2_object Object = S2_StackPop(Runtime); + if(Object.Kind == S2_ObjectKind_String) + { + SV_LoadNavItems(Object.As.String); + } +} + +static S2_CALL_FUNCTION(S2_Call_Puzzle15) +{ + scene_view *SceneView = (scene_view *)Runtime->Data; + SceneView->Mode = SV_Mode_P15; + SceneView->BoardOpenT = 0; + SceneView->TimeSinceBoardUpdate = 0; + SceneView->TimeSinceBoardClear = 0; + SceneView->BoardIsComplete = false; + + // sixten: generate random board + for(s32 BoardY = 0; BoardY < 4; BoardY += 1) + { + for(s32 BoardX = 0; BoardX < 4; BoardX += 1) + { + SceneView->Board[BoardY][BoardX] = (1+BoardX+BoardY*4)%16; + } + } + + v2_s32 EmptyP = V2S32(3, 3); + s32 ShuffleCount = 10000; + for(s32 Index = 0; Index < ShuffleCount; Index += 1) + { + s32 DeltaX = (rand() % 2)*2-1; + s32 DeltaY = (rand() % 2)*2-1; + + // sixten: apply x-action + s32 NewEmptyX = EmptyP.x+DeltaX; + if(0 <= NewEmptyX && NewEmptyX < 4) + { + SceneView->Board[EmptyP.y][EmptyP.x] = SceneView->Board[EmptyP.y][NewEmptyX]; + SceneView->Board[EmptyP.y][NewEmptyX] = 0; + EmptyP.x = NewEmptyX; + } + + // sixten: apply y-action + s32 NewEmptyY = EmptyP.y+DeltaY; + if(0 <= NewEmptyY && NewEmptyY < 4) + { + SceneView->Board[EmptyP.y][EmptyP.x] = SceneView->Board[NewEmptyY][EmptyP.x]; + SceneView->Board[NewEmptyY][EmptyP.x] = 0; + EmptyP.y = NewEmptyY; + } + } + + Copy(SceneView->PrevBoard, SceneView->Board, sizeof(SceneView->Board)); +} \ No newline at end of file diff --git a/code/vn_scene_view.cpp b/code/vn_scene_view.cpp index bda246b..2c233b1 100644 --- a/code/vn_scene_view.cpp +++ b/code/vn_scene_view.cpp @@ -27,12 +27,11 @@ static void SV_Reset(void) SceneView->CharactersUsed = 0; } -static void SV_LoadNavItems(void) +static void SV_LoadNavItems(string FileName) { -#if 0 scene_view *SceneView = SV_GetState(); temp Scratch = GetScratch(); - string NavData = Platform_ReadEntireFile(Scratch.Arena, SceneView->Runtime.Compiled.NavFileName); + string NavData = Platform_ReadEntireFile(Scratch.Arena, FileName); if(NavData.Count != 0) { @@ -114,7 +113,6 @@ static void SV_LoadNavItems(void) } } ReleaseScratch(Scratch); -#endif } static void SV_SetCurrentSource(compiled_scene2 *Compiled) @@ -128,10 +126,6 @@ static void SV_SetCurrentSource(compiled_scene2 *Compiled) ArenaClear(SceneView->SceneArena); SceneView->Compiled = S2_CopyCompiledScene(SceneView->SceneArena, Compiled); - - SV_LoadNavItems(); - - //- sixten: find main proc S2_SetCurrentProc(Runtime, S2_ProcFromName(Compiled, StrLit("main"))); } @@ -494,219 +488,250 @@ static ui_signal BuildNavItemAndLabel(scene_nav_item *Item, r32 GlobalScale, v2_ return(Signal); } -static void BuildNavView(scene_view *View, ui_box *Box, v2_r32 BoxDim) +static UI_CUSTOM_DRAW_CALLBACK(Puzzle15DrawCallback) { - r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim); - - for(int ItemIndex = 0; ItemIndex < View->NavItemCount; ++ItemIndex) - { - scene_nav_item *Item = View->NavItems+ItemIndex; - if(BuildNavItemAndLabel(Item, GlobalScale, BoxDim).Clicked) - { - // sixten: apply the action - if(Item->Action.Kind == S_NavAction_Proc) - { - S2_SetCurrentProc(&View->Runtime, S2_ProcFromName(&View->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); - } - } - } + 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); + } } -static void BuildScene(scene_view *View) +static void BuildScene(scene_view *SceneView) { - 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, View); - - UI_Parent(Box) - { - if(SV_CurrentlyInProc()) - { - BuildProcView(View, Box, BoxDim); - } - else - { - BuildNavView(View, Box, BoxDim); - } - } + 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; + } + } } static void BuildErrorScreen(scene_view *SceneView, 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; + 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(scene2_message *Message = SceneView->Messages.First; Message != 0; Message = Message->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_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_Label(Message->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) - { + } + } + 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) + { ZeroStruct(&SceneView->Messages); ArenaClear(SceneView->MessageArena); - } - - 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; - } - } - } - } + } + + 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; + } + } + } + } } 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->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; - - Result = View->Characters + CharacterIndex; - *Result = {}; - Result->Name = Name; - Result->Active = true; - Result->PctP = (r32)(CharacterIndex + 1) / (View->CharactersUsed + 1); - } - - return(Result); -} - -#if 0 -static scene_view_character_texture_info SV_CharacterTextureFromAction(scene_character_action *Action) -{ - scene_view_character_texture_info Result = {}; - Result.Texture = EmptyRenderHandle(); - Result.Scale = 1.0f; - - asset_id AssetID = Action->State; - Result.Texture = A_TextureFromAssetID(AssetID); - Result.Scale = A_ScaleFromAssetID(AssetID); + scene_view_character_data *Result = 0; -#if 0 - if(AreEqual(StrLit("arthur"), Action->Target)) - { - + 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; - switch(Action->State) - { - case CR_State_Normal: { Result.Texture = View->TestNormal; } break; - case CR_State_Happy: { Result.Texture = View->TestHappy; } break; - default: break; - } - - Result.Scale = 0.017f; - } - else if(AreEqual(StrLit("monika"), Action->Target)) - { - switch(Action->State) - { - case CR_State_Leaning: { Result.Texture = View->MonikaLeaning; } break; - default: break; - } - Result.Scale = 0.033f; - } -#endif - return(Result); + Result = View->Characters + CharacterIndex; + *Result = {}; + Result->Name = Name; + Result->Active = true; + Result->PctP = (r32)(CharacterIndex + 1) / (View->CharactersUsed + 1); + } + + return(Result); } -#endif static r32 SV_CalculateTargetPctP(s32 TrueCharacterIndex) { - 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); + 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); } static void SV_UpdateInDialog(arena *FrameArena) @@ -870,34 +895,34 @@ static void SV_UpdateInDialog(arena *FrameArena) static void SV_Update(arena *FrameArena) { - 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); - } + 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); + } // sixten: prune any unactive characters for(s32 CharacterIndex = 0; CharacterIndex < SceneView->CharactersUsed; CharacterIndex += 1) @@ -910,13 +935,144 @@ static void SV_Update(arena *FrameArena) CharacterIndex -= 1; } } - } - - //- sixten: update scene - if(SV_CurrentlyInProc()) - { - SV_UpdateInDialog(FrameArena); - } + } + + // 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; + } } static void SV_BuildSceneView(vn_input *Input) @@ -930,18 +1086,4 @@ static void SV_BuildSceneView(vn_input *Input) { BuildScene(SceneView); } -} - -#if 0 - -scene_user_input Input = SV_GatherInputs(); // note that we here could consume a player interaction for skipping the text -scene_runtime_result Result = S_Run(&Runtime, &Inputs); -for(scene_action *Action = Result.FirstAction; Action != 0; Action = Action->Next) -{ - switch(Action->Kind) - { - ... - } -} - -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/code/vn_scene_view.h b/code/vn_scene_view.h index d6643e0..0a0a0ab 100644 --- a/code/vn_scene_view.h +++ b/code/vn_scene_view.h @@ -66,6 +66,13 @@ struct scene_nav s32 ItemMax; }; +enum scene_view_mode +{ + SV_Mode_Scene, + SV_Mode_Nav, + SV_Mode_P15, +}; + struct scene_view { arena *SceneArena; @@ -73,6 +80,7 @@ struct scene_view //- sixten: state scene2_runtime Runtime; compiled_scene2 Compiled; + scene_view_mode Mode; //- sixten: messages arena *MessageArena; @@ -94,6 +102,14 @@ struct scene_view //- sixten: input per frame platform_event_list *EventList; r32 dtForFrame; + + //- sixten: 15-puzzle + r32 BoardOpenT; + u8 Board[4][4]; + u8 PrevBoard[4][4]; + b32 BoardIsComplete; + r32 TimeSinceBoardUpdate; + r32 TimeSinceBoardClear; }; static void SV_SetState(scene_view *View); diff --git a/code/vn_workspace.cpp b/code/vn_workspace.cpp index d81c7c3..f55e64c 100644 --- a/code/vn_workspace.cpp +++ b/code/vn_workspace.cpp @@ -273,12 +273,12 @@ static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View) UI_SetNextWidth(UI_ChildrenSum(1, 1)); UI_SetNextHeight(UI_Percent(1, 1)); UI_SetNextBackgroundColor(Brighten(BackgroundColor, 1.2f)); - UI_SetNextBorderColor(LinearBlend(UI_TopBackgroundColor(), Color_Grey, 0.5)); + UI_SetNextBorderColor(Darken(LinearBlend(UI_TopBackgroundColor(), Color_White, 0.2f), 1.2f)); UI_SetNextLayoutAxis(Axis2_X); - UI_SetNextCornerRadii(V4R32(3.0, 3.0, 0, 0)); + UI_SetNextCornerRadii(V4R32(5.0, 5.0, 0, 0)); ui_box *TabBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground | - //UI_BoxFlag_DrawBorder | + UI_BoxFlag_DrawBorder | UI_BoxFlag_DrawDropShadow | UI_BoxFlag_HotAnimation | UI_BoxFlag_ActiveAnimation | diff --git a/code/vn_workspace_nav_editor.cpp b/code/vn_workspace_nav_editor.cpp index 1c97601..038e56a 100644 --- a/code/vn_workspace_nav_editor.cpp +++ b/code/vn_workspace_nav_editor.cpp @@ -240,12 +240,6 @@ static void W_BuildNavEditor(workspace_view *View) { W_NavEditorSerializeItems(Editor); } - - //- sixten: create force reload - if(UI_ButtonF("%U", FontIcon_ArrowsCW).Clicked) - { - SV_LoadNavItems(); - } } } diff --git a/code/win32__main.rdbg b/code/win32__main.rdbg index cb78ea4..d9c1117 100644 Binary files a/code/win32__main.rdbg and b/code/win32__main.rdbg differ diff --git a/data/omori.vnn b/data/omori.vnn new file mode 100644 index 0000000..102f48e Binary files /dev/null and b/data/omori.vnn differ diff --git a/data/omori.vns b/data/omori.vns new file mode 100644 index 0000000..0a2938b --- /dev/null +++ b/data/omori.vns @@ -0,0 +1,34 @@ +proc main + call nav_load("data/omori.vnn") + call proc_set("omori_1") +end + +proc omori_1 + s = "Sunny" + + $(s) "There is something I have to tell you." + $(s) "It's about MARI." + $(s) "..." + $(s) "She didn't kill herself." + + $(s) "It was the day of the recital." + $(s) "We had been rehearsing for hours, but no matter how much time we spent it was never good enough." + $(s) "I had just messed up a note when in my anger I stormed out." + $(s) "MARI was quick to follow me, just in time to see me throw the violin to the ground." + $(s) "We were at the top of the stairs when she finally managed to grab my arm." + $(s) "She was so calm... Not mad at all... Just disappointed." + $(s) "But I didn't want to be there. I didn't want her to be there. I just wanted to go away." + $(s) "Before I was able to run away again, she blocked my path and without thinking I pushed and..." + $(s) "...she fell." + $(s) "She fell down the stairs." + + $(s) "That same day, BASIL happened to be visiting." + $(s) "He couldn't believe what he saw and in order to protect me..." + $(s) "...he and I staged MARI's suicide." +end + +proc puzzle_test + $ "Can you beat the IMPOSSIBLE duck puzzle?" + call puzzle_15() + $ "Wow, you actually did it." +end \ No newline at end of file diff --git a/data/puzzles/duck.png b/data/puzzles/duck.png new file mode 100644 index 0000000..08f03e0 Binary files /dev/null and b/data/puzzles/duck.png differ