static u64 S2_CallFunctionIndexFromString(string String) { u64 Result = 0; for(u64 Index = 0; Index < ArrayCount(S2_CallNameLookup); Index += 1) { if(AreEqual(String, S2_CallNameLookup[Index])) { Result = Index; break; } } return(Result); } static scene2_call_function *S2_CallFunctionFromString(string String) { scene2_call_function *Result = S2_Call_Stub; for(u64 Index = 0; Index < ArrayCount(S2_CallNameLookup); Index += 1) { if(AreEqual(String, S2_CallNameLookup[Index])) { Result = S2_CallBindingLookup[Index]; break; } } return(Result); } static S2_CALL_FUNCTION(S2_Call_StackSanity) { scene2_object Value = S2_StackPop(Runtime); Assert(Value.Kind == S2_ObjectKind_Number && Runtime->StackPointer == (u64)Value.As.Number); } static S2_CALL_FUNCTION(S2_Call_TextClear) { scene_view *SceneView = (scene_view *)Runtime->Data; SceneView->TextboxUsed = 0; SceneView->TextboxRevealed = 0; } static S2_CALL_FUNCTION(S2_Call_NewLine) { scene_view *SceneView = (scene_view *)Runtime->Data; if(SceneView->TextboxUsed < ArrayCount(SceneView->TextboxData)) { SceneView->TextboxData[SceneView->TextboxUsed++] = '\n'; } } static S2_CALL_FUNCTION(S2_Call_TextAppend) { scene_view *SceneView = (scene_view *)Runtime->Data; temp Scratch = GetScratch(); string Addend = S2_StringFromObject(Scratch.Arena, S2_StackPop(Runtime)); Addend.Count = Min(Addend.Count, ArrayCount(SceneView->TextboxData)-SceneView->TextboxUsed); Copy(SceneView->TextboxData+SceneView->TextboxUsed, Addend.Data, Addend.Count); SceneView->TextboxUsed += Addend.Count; ReleaseScratch(Scratch); } static S2_CALL_FUNCTION(S2_Call_ProcSet) { temp Scratch = GetScratch(); S2_SetCurrentProc(Runtime, S2_ProcFromName(Compiled, S2_StringFromObject(Scratch.Arena, S2_StackPop(Runtime)))); ReleaseScratch(Scratch); } static S2_CALL_FUNCTION(S2_Call_CharacterSet) { scene_view *SceneView = (scene_view *)Runtime->Data; scene2_object IDObject = S2_StackPop(Runtime); scene2_object TargetObject = S2_StackPop(Runtime); // sixten(TODO): this should fail gracefully Assert(IDObject.Kind == S2_ObjectKind_Number || IDObject.Kind == S2_ObjectKind_Nil); Assert(TargetObject.Kind == S2_ObjectKind_String); string Target = TargetObject.As.String; asset_id ID = IDObject.Kind == S2_ObjectKind_Number ? (asset_id)IDObject.As.Number : AssetID_None; scene_view_character_data *CharacterBegin = SceneView->Characters; scene_view_character_data *CharacterUsedEnd = SceneView->Characters+SceneView->CharactersUsed; scene_view_character_data *CharacterEnd = SceneView->Characters+ArrayCount(SceneView->Characters); scene_view_character_data *Character = CharacterBegin; for(;Character < CharacterEnd; Character += 1) { // sixten: check if the character doesn't exist if(Character == CharacterUsedEnd) { // sixten: "create" new character ZeroStruct(Character); Character->Name = PushString(SceneView->SceneArena, Target); SceneView->CharactersUsed += 1; Character->PctP = ((r32)SceneView->CharactersUsed / (r32)(SceneView->CharactersUsed+1)); break; } // sixten: check if character exists if(AreEqual(Character->Name, Target)) { break; } } if(Character != CharacterEnd) { Character->Active = true; if(ID != AssetID_None) { Character->Info.Texture = A_TextureFromAssetID(ID); Character->Info.Scale = A_ScaleFromAssetID(ID); } } else { // sixten: we've run out of characters } } static S2_CALL_FUNCTION(S2_Call_CharacterRemove) { scene_view *SceneView = (scene_view *)Runtime->Data; scene2_object TargetObject = S2_StackPop(Runtime); // sixten(TODO): this should fail gracefully Assert(TargetObject.Kind == S2_ObjectKind_String); 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; // sixten: check if the character exists for(;Character < CharacterEnd; Character += 1) { if(AreEqual(Character->Name, Target)) { break; } } // sixten: if the character exists, request its deletion if(Character != CharacterEnd) { Character->Active = false; Character->Talking = false; } } static S2_CALL_FUNCTION(S2_Call_CharacterSetTalking) { scene_view *SceneView = (scene_view *)Runtime->Data; scene2_object TargetObject = S2_StackPop(Runtime); // sixten(TODO): this should fail gracefully Assert(TargetObject.Kind == S2_ObjectKind_String); 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; // sixten: check if the character exists for(;Character < CharacterEnd; Character += 1) { if(AreEqual(Character->Name, Target)) { break; } } // sixten: if the character exists, request its deletion if(Character != CharacterEnd) { Character->Talking = true; } } static S2_CALL_FUNCTION(S2_Call_CharacterUnsetAllTalking) { scene_view *SceneView = (scene_view *)Runtime->Data; scene_view_character_data *CharacterBegin = SceneView->Characters; scene_view_character_data *CharacterEnd = SceneView->Characters+SceneView->CharactersUsed; scene_view_character_data *Character = CharacterBegin; for(;Character < CharacterEnd; Character += 1) { 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)); }