private void OnPickedFromCreationLibrary(ActorableSearchResult searchResult) { VoosActor actor = assetSearch.RequestActor(searchResult, Vector3.zero, Quaternion.identity, Vector3.one); actor.SetPreferOffstage(true); CloseAndReturn(true, actor.GetName()); }
void SetActorSpawnPosition(VoosActor actor, Vector3 newPosition, bool setParent = false, string spawnParent = null) { Vector3 currPosition = actor.GetSpawnPosition(); Quaternion currRotation = actor.GetSpawnRotation(); string currParent = actor.GetSpawnTransformParent(); undoStack.PushUndoForActor( actor, $"Set actor spawn position", (undoActor) => { undoActor.SetSpawnPosition(newPosition); undoActor.SetSpawnRotation(currRotation); if (setParent) { VoosActor setSpawnParent = undoActor.GetEngine().GetActor(spawnParent); undoActor.SetSpawnTransformParent(setSpawnParent?.GetName()); } }, (undoActor) => { undoActor.SetSpawnPosition(currPosition); undoActor.SetSpawnRotation(currRotation); if (setParent) { VoosActor setSpawnParent = undoActor.GetEngine().GetActor(currParent); undoActor.SetSpawnTransformParent(setSpawnParent?.GetName()); } } ); }
private bool ShouldActorBeListed(bool isOffstageList, VoosActor actor) { return(actor.GetName() != "__GameRules__" && (actor.GetIsOffstageEffective() == isOffstageList) && !actor.GetWasClonedByScript() && (actor.GetDisplayName().ToLower().Contains(searchInput.text.ToLower()))); }
public void DrawActorDebugGUI(VoosActor actor) { using (new Util.GUILayoutFrobArea(actor.transform.position, 100, 500)) { PhotonView photonView = PhotonView.Get(actor); if (photonView == null) { return; } PlayerBody playerBody = actor.GetPlayerBody(); //string pbodyInfo = playerBody == null ? "" : $"Claimed? {playerBody.IsClaimed()} ..play mode? {playerBody.GetIsClaimerPlaying()}"; string color = photonView.isMine ? "yellow" : "grey"; string hash = actor.GetName().Substring(0, 9); bool locked = actor.IsLockedByAnother() || actor.IsLockWantedLocally(); string lockingString = locked ? " LOCKED" : ""; string lastPos = actor.unrel == null ? "" : actor.unrel.lastPosition.x.ToFourDecimalPlaces(); GUILayout.Label($@"<color={color}>{actor.GetDisplayName()} rot: {actor.GetRotation().ToFourDecimalPlaces()} last unrel: {actor.lastUnreliableUpdateTime} lastPX: {lastPos}</color>".Trim()); GUILayout.Toggle(actor.GetReplicantCatchUpMode(), "Catchup?"); actor.debug = GUILayout.Toggle(actor.debug, "Debug"); // owner: {photonView.ownerId}{lockingString} // {hash} view {actor.reliablePhotonView.viewID} // X: {actor.transform.position.x.ToFourDecimalPlaces()} // lastRBMPX: {actor.lastRBMovedPos.x.ToFourDecimalPlaces()} } }
public static void SetCurrentParentForActor( VoosActor actor, VoosActor selectedActor, UndoStack undoStack, bool autosetParent = false) { string newParentName = selectedActor?.GetName(); string prevParentName = actor.GetTransformParent(); string prevSpawnParentName = actor.GetSpawnTransformParent(); undoStack.PushUndoForActor( actor, $"Set actor parent", (undoActor) => { VoosActor newParent = undoActor.GetEngine().GetActor(newParentName); string parentName = VoosActor.IsValidParent(undoActor, newParent) ? newParent?.GetName() : null; undoActor.SetTransformParent(parentName); if (autosetParent) { undoActor.SetSpawnTransformParent(parentName); } }, (undoActor) => { VoosActor prevParent = undoActor.GetEngine().GetActor(prevParentName); undoActor.SetTransformParent(VoosActor.IsValidParent(undoActor, prevParent) ? prevParent?.GetName() : null); if (autosetParent) { VoosActor prevSpawnParent = undoActor.GetEngine().GetActor(prevSpawnParentName); undoActor.SetSpawnTransformParent( VoosActor.IsValidParent(undoActor, prevSpawnParent) ? prevSpawnParent?.GetName() : null); } }); }
public ICardManagerModel GetCardManager(VoosActor actor) { // TODO we should think about, is it possible to return the same instance of // this object for the same actor? Then users could use reference equality, // hold on to old instances, etc...what if the brain changes? There is // implicit state in ABE.. return(new ManagerImpl(new ActorBehaviorsEditor(actor.GetName(), engine, undo))); }
public IEnumerator TestHandleMultipleInOneFrame() { yield return(Setup()); VoosActor actor = voosEngine.CreateActor(new Vector3(1, 2, 3), Quaternion.identity, newActor => { }); actor.SetTint(new Color(0.1f, 0.1f, 0.1f)); Assert.NotNull(actor); Assert.AreEqual(1.0, actor.transform.position.x, 1e-4); string brainId = actor.GetBrainName(); string behaviorId = behaviorSystem.GenerateUniqueId(); string js = @" export function onMoveRight() { const c = getTint(); c.r += 0.1; setTint(c.r, c.g, c.b); } "; behaviorSystem.PutBehavior(behaviorId, new Behaviors.Behavior { javascript = js }); PutTestUse(new TestUse { behaviorUri = IdToEmbeddedBehaviorUri(behaviorId), brainId = brainId }); // We expect x to increment by 2.. voosEngine.EnqueueMessage(new VoosEngine.ActorMessage { name = "MoveRight", targetActor = actor.GetName() }); voosEngine.EnqueueMessage(new VoosEngine.ActorMessage { name = "MoveRight", targetActor = actor.GetName() }); // Let it run at least one voos update yield return(new WaitForEndOfFrame()); yield return(new WaitForEndOfFrame()); Assert.AreEqual(0.3, actor.GetTint().r, 1e-4); }
public void PlaySoundEffect(SoundEffect sfx, VoosActor actor, Vector3 position) { PlaySoundEffectLocal(sfx, actor, position); unreliableMessageSystem.Send <SfxPlayRequest>(NetworkingEventCodes.SFX, new SfxPlayRequest { actorName = actor != null ? actor.GetName() : null, sfxId = sfx.id, position = position }); }
private void BreakLink(bool withUndo = true) { VoosActor actor = currActor; // Save for undo string prevParent = actor.GetCloneParent(); SetActorInternal(null); actor.SetCloneParent(null); actor.MakeOwnCopyOfBrain(); if (withUndo) { // Setup undo item string actorName = actor.GetName(); string newBrain = actor.GetBrainName(); undo.Push(new UndoStack.Item { actionLabel = $"Break copy-link of {actor.GetDisplayName()}", getUnableToDoReason = () => ActorUndoUtil.GetUnableToEditActorReason(voosEngine, actorName), doIt = () => { var redoActor = voosEngine.GetActor(actorName); redoActor.SetCloneParent(null); // A bit sloppy: We're relying on the fact that brains are never deleted // (except on load). redoActor.SetBrainName(newBrain); OnBreakLinkChanged(redoActor); }, getUnableToUndoReason = () => { var prevParentActor = voosEngine.GetActor(prevParent); if (prevParentActor == null) { return($"The original copy no longer exists."); } return(null); }, undo = () => { var undoActor = voosEngine.GetActor(actorName); var prevParentActor = voosEngine.GetActor(prevParent); Debug.Assert(prevParent != null, "BreakLink undo action: prevParent does not exist anymore"); undoActor.SetCloneParent(prevParent); undoActor.SetBrainName(prevParentActor.GetBrainName()); OnBreakLinkChanged(undoActor); } }); } SetActorInternal(actor); }
public static void PushUndoForActor(this UndoStack stack, VoosActor theActor, string label, System.Action <VoosActor> doIt, System.Action <VoosActor> undo) { // IMPORTANT: Do *NOT* use a reference to the actor! It may be deleted, // un-deleted, etc. So use its name, which is stable. string actorName = theActor.GetName(); // Assume the VoosEngine instance is stable. VoosEngine engineRef = theActor.GetEngine(); stack.Push(new UndoStack.Item { actionLabel = label, getUnableToDoReason = () => GetUnableToEditActorReason(engineRef, actorName), getUnableToUndoReason = () => GetUnableToEditActorReason(engineRef, actorName), doIt = () => GetValidActorThen(engineRef, actorName, doIt), undo = () => GetValidActorThen(engineRef, actorName, undo) }); }
static IEnumerable <string> GetUsedSojoIds(VoosActor actor) { string pfxId = actor.GetPfxId(); string sfxId = actor.GetSfxId(); if (!pfxId.IsNullOrEmpty()) { yield return(pfxId); } if (!sfxId.IsNullOrEmpty()) { yield return(sfxId); } var brain = new ActorBehaviorsEditor(actor.GetName(), actor.GetEngine(), null); foreach (var beh in brain.GetAssignedBehaviors()) { foreach (var prop in beh.GetProperties()) { if (prop.propType == BehaviorProperties.PropType.Image || prop.propType == BehaviorProperties.PropType.ParticleEffect || prop.propType == BehaviorProperties.PropType.Prefab || prop.propType == BehaviorProperties.PropType.Sound) { if (prop.propType == BehaviorProperties.PropType.Prefab) { throw new System.Exception("Sorry, exporting an actor with prefab ref is not supported yet."); } // Yes, we should crash if the string cast fails. string sojoId = (string)prop.data; if (!sojoId.IsNullOrEmpty()) { yield return(sojoId); } } } } }
public void Show(VoosActor actor) { // Start with player 0 to avoid warnings/etc. AssignPlayerToActor(0, actor.GetName()); string name = actor.GetDisplayName(); List <PopupButton.Params> buttons = new List <PopupButton.Params>(); int myPlayerNumber = playerControlsManager.GetMyPlayerNumber(); int maxPlayerSlotNumber = 4; // Show at least player 1-4, unless there are more players. foreach (VirtualPlayerManager.VirtualPlayerInfo player in virtualPlayerManager.EnumerateVirtualPlayers()) { maxPlayerSlotNumber = Mathf.Max(player.slotNumber, maxPlayerSlotNumber); } for (int i = 1; i <= maxPlayerSlotNumber; i++) { int thisNumber = i; // For closures below buttons.Add(new PopupButton.Params { getLabel = () => $"Player {thisNumber}" + ((thisNumber == myPlayerNumber) ? " (myself)" : ""), onClick = () => OnClickedPlayerNumber(actor, thisNumber) }); } buttons.Add(new PopupButton.Params { getLabel = () => "Nobody for now", onClick = () => OnClickedPlayerNumber(actor, 0) }); buttons.Add(new PopupButton.Params { getLabel = () => "It's an NPC", onClick = () => OnClickedIsNpc(actor) }); popups.Show(new DynamicPopup.Popup { getMessage = () => $"Who will control this {name}?", buttons = buttons, }); }
public static ActorBehaviorsEditor FromActor(VoosActor actor) { return(new ActorBehaviorsEditor(actor.GetName(), actor.GetEngine(), null)); }
void PrepareInputForScript(ControllerInput input) { if (input == null) { return; } if (userMain == null) { // Not ready yet. return; } inputStateForScript = new InputStateForScript(); if (input.GetKeyDown(PlayerBody.VKEY_JUMP)) { // V1 name: voosActor.EnqueueMessage("JumpTriggered"); // V2 name: voosActor.EnqueueMessage("Jump"); } if (input.GetKeyDown(PlayerBody.VKEY_PRIMARY_ACTION)) { // V1 name: voosActor.EnqueueMessage("Action1Triggered"); // V2 name: voosActor.EnqueueMessage("PrimaryAction"); } if (input.GetKeyDown(PlayerBody.VKEY_SECONDARY_ACTION)) { // V1 name: voosActor.EnqueueMessage("Action2Triggered"); // V2 name: voosActor.EnqueueMessage("SecondaryAction"); } List <string> keysHeld = new List <string>(); List <string> keysJustPressed = new List <string>(); List <string> keysJustReleased = new List <string>(); foreach (string key in ScriptableKeyNames) { bool isDown = input.GetKeyDown(key) && !keysHeldAsReportedToScript.Contains(key); bool isUp = !input.GetKeyHeld(key) && keysHeldAsReportedToScript.Contains(key); bool isHeld = input.GetKeyHeld(key); if (isHeld) { keysHeldAsReportedToScript.Add(key); } else { keysHeldAsReportedToScript.Remove(key); } if (isDown) { voosActor.EnqueueMessage("KeyDown", $"{{\"keyName\": \"{key}\"}}"); keysJustPressed.Add(key); } if (isHeld) { voosActor.EnqueueMessage("KeyHeld", $"{{\"keyName\": \"{key}\"}}"); keysHeld.Add(key); } if (isUp) { voosActor.EnqueueMessage("KeyUp", $"{{\"keyName\": \"{key}\"}}"); keysJustReleased.Add(key); } } bool mouseIsDown = Input.GetMouseButton(0) && !userMain.CursorOverUI() && !userMain.InEditMode(); if (mouseIsDown && !reportedMouseDown) { voosActor.EnqueueMessage("MouseDown"); reportedMouseDown = true; inputStateForScript.mouseButtonJustPressed = true; } if (reportedMouseDown) { voosActor.EnqueueMessage("MouseHeld"); inputStateForScript.mouseButtonIsPressed = true; } if (!mouseIsDown && reportedMouseDown) { voosActor.EnqueueMessage("MouseUp"); reportedMouseDown = false; inputStateForScript.mouseButtonJustReleased = true; } Vector2 mousePosUiCoords; Vector3 mousePosRaw = Input.mousePosition; mousePosUiCoords = gameUiMain.UnityScreenPointToGameUiPoint(mousePosRaw); inputStateForScript.mouseX = mousePosUiCoords.x; inputStateForScript.mouseY = mousePosUiCoords.y; inputStateForScript.keysHeld = keysHeld.ToArray(); inputStateForScript.keysJustPressed = keysJustPressed.ToArray(); inputStateForScript.keysJustReleased = keysJustReleased.ToArray(); Ray mouseRay = userMain.GetCamera().ScreenPointToRay(mousePosRaw); inputStateForScript.mouseRayOrigin = mouseRay.origin; inputStateForScript.mouseRayDirection = mouseRay.direction; if (inputStateForScript.mouseButtonJustPressed) { RaycastHit hit; if (Physics.Raycast(mouseRay.origin, mouseRay.direction, out hit, 1000, VoosActor.LayerMaskValue, QueryTriggerInteraction.Collide)) { VoosActor clickedActor = hit.collider.GetComponentInParent <VoosActor>(); if (clickedActor != null) { clickedActor.GetEngine().EnqueueMessage(new VoosEngine.ActorMessage { name = "ActorClicked", targetActor = clickedActor.GetName(), argsJson = "{}" }); } } } inputStateForScript.mouseWheelRaw = Input.GetAxis("Mouse ScrollWheel"); inputStateForScript.mouseWheel = inputStateForScript.mouseWheelRaw * MOUSEWHEEL_FACTOR; }
void EndTextEditing() { if (IsEditing()) { // Erm, do this first, cuz deactivating stuff could cause this to be // called again recursively. Like deactivating the inputFieldObject! lastActorEdited = actorBeingEdited; actorBeingEdited = null; inputFieldObject.SetActive(false); cooldownRoutine = StartCoroutine(CooldownRoutine()); if (inputField.text == EMPTY_TEXT) { engine.DestroyActor(lastActorEdited); } else { editMain.SetTargetActor(lastActorEdited); // editMain.SetFocusedTargetActor(lastActorEdited); string undoText = actorTextBeforeEditing; if (actorWasJustCreated) { var engine = lastActorEdited.GetEngine(); var actorData = engine.SaveActor(lastActorEdited); undoStack.PushUndoForCreatingActor(lastActorEdited, $"Create text panel"); } else { string currText = lastActorEdited.GetCommentText(); if (ActorUndoUtil.GetUnableToEditActorReason(lastActorEdited.GetEngine(), lastActorEdited.GetName()) == null) { undoStack.PushUndoForActor( lastActorEdited, $"Edit text panel", redoActor => { redoActor.SetCommentText(currText); redoActor.ApplyPropertiesToClones(); }, undoActor => { undoActor.SetCommentText(undoText); undoActor.ApplyPropertiesToClones(); }); } } } } }
private void SetPlayerNumberOnPlayerControlsPanel(VoosActor actor, Behaviors.BehaviorUse use, int playerNumber) { use = use.DeepClone(); use.SetPropertyValue(PLAYER_NUMBER_PROP_NAME, playerNumber); Behaviors.Brain brain = actor.GetBehaviorSystem().GetBrain(actor.GetBrainName()); if (brain == null) { Debug.LogErrorFormat("Could not set player# on actor {0} ({1}). No brain.", actor.GetName(), actor.GetDisplayName()); return; } brain.SetUse(use); actor.GetBehaviorSystem().PutBrain(actor.GetBrainName(), brain); }
private void DeletePlayerControlsPanel(VoosActor actor) { Debug.Assert(actor.IsLocallyOwned(), "Actor should be locally owned"); Behaviors.BehaviorUse playerControlsPanel = TryGetPlayerControlsPanel(actor); if (playerControlsPanel == null) { return; } Behaviors.Brain brain = actor.GetBehaviorSystem().GetBrain(actor.GetBrainName()); if (brain == null) { Debug.LogErrorFormat("Could not set player# on actor {0} ({1}). No brain.", actor.GetName(), actor.GetDisplayName()); return; } // PLAYER_CONTROLS_PANEL_HAS_NO_DECKS_ASSUMPTION // WARNING: this is a naive delete that doesn't recursively look for behavior uses mentioned // in any decks used by the Player Controls panel, so if in the future we do add decks to it, // we need to update this logic to remove the panel properly. brain.DeleteUse(playerControlsPanel.id); actor.GetBehaviorSystem().PutBrain(actor.GetBrainName(), brain); }
// Ideally this wouldn't live here, but for now, whatever. internal void CallService(string serviceName, string argsJson, System.IntPtr reportResultPtr) { Native.ReportResultFunction reportResult = null; if (CacheReportResult) { if (cachedReportResult == null) { cachedReportResult = Marshal.GetDelegateForFunctionPointer <Native.ReportResultFunction>(reportResultPtr); firstReportResultPtr = reportResultPtr; } reportResult = cachedReportResult; Debug.Assert(firstReportResultPtr == reportResultPtr, $"Different reportResultPtr was given!"); } else { reportResult = Marshal.GetDelegateForFunctionPointer <Native.ReportResultFunction>(reportResultPtr); } try { switch (serviceName) { case "BeginProfileSample": { InGameProfiler.BeginSection(argsJson); reportResult("0"); break; } case "EndProfileSample": { InGameProfiler.EndSection(); reportResult("0"); break; } case "OverlapSphere": using (Util.Profile(serviceName)) { var args = JsonUtility.FromJson <OverlapSphereArgs>(argsJson); int numHits = Physics.OverlapSphereNonAlloc(args.center, args.radius, SharedColliderBuffer, VoosActor.LayerMaskValue, QueryTriggerInteraction.Collide); if (numHits == SharedColliderBuffer.Length) { Util.LogError($"The OverlapSphere call exceeded the maximum number of allowed results ({SharedColliderBuffer.Length}). You are probably not getting what you want. Please try to adjust the parameters so you get less hits, like reducing the radius."); } using (Util.Profile("report actors")) { var jsoner = SharedStringBuilder; jsoner.Clear(); jsoner.Append("["); bool gotOneActor = false; for (int i = 0; i < numHits; i++) { Collider obj = SharedColliderBuffer[i]; VoosActor actor = obj.GetComponentInParent <VoosActor>(); if (actor == null) { continue; } if (!args.tag.IsNullOrEmpty()) { if (!actor.HasTag(args.tag)) { continue; } } if (gotOneActor) { jsoner.Append(","); } jsoner.Append("\""); jsoner.Append(actor.GetName()); jsoner.Append("\""); gotOneActor = true; } jsoner.Append("]"); reportResult(jsoner.ToString()); } break; } case "CheckBox": using (Util.Profile(serviceName)) { var args = JsonUtility.FromJson <CheckBoxArgs>(argsJson); bool hitAnything = Physics.CheckBox(args.box.center, args.box.dimensions * 0.5f, args.box.rotation, -1, // We're probably looking for clearance, so return true if the box hits actors OR just static terrain. QueryTriggerInteraction.Ignore // Ignore triggers for checks. We are probably looking for clearance, in which case triggers don't matter. ); reportResult(hitAnything ? "true" : "false"); break; } case "Cast": using (Util.Profile(serviceName)) { PhysicsCastRequest req = JsonUtility.FromJson <PhysicsCastRequest>(argsJson); int layerMask = (req.includeActors ? VoosActor.LayerMaskValue : 0) | (req.includeTerrain ? LayerMask.GetMask("Default") : 0); int numHits = req.radius < 0.01 ? Physics.RaycastNonAlloc(req.origin, req.dir, SharedRaycastHitBuffer, req.maxDist, layerMask, QueryTriggerInteraction.Collide) : Physics.SphereCastNonAlloc(req.origin, req.radius, req.dir, SharedRaycastHitBuffer, req.maxDist, layerMask, QueryTriggerInteraction.Collide); // These variables things are somewhat redundant, but for performance we keep all three and // only use the appropriate ones per req.castMode, to avoid unnecessary allocations. // List of results. Only allocate if we have to. List <PhysicsCastHit> results = null; // Did we have any hit? bool anyHit = false; // The closest hit we got. Only valid if anyHit == true. PhysicsCastHit closestHit = new PhysicsCastHit(); if (req.mode == CastMode.ALL_SORTED || req.mode == CastMode.ALL_UNSORTED) { // We will need to return a list, so allocate it. results = new List <PhysicsCastHit>(); } for (int i = 0; i < numHits; i++) { RaycastHit hit = SharedRaycastHitBuffer[i]; PhysicsCastHit thisHit; if (hit.collider != null && hit.collider.gameObject != null && hit.collider.gameObject.GetComponent <IgnoreRaycastFromScript>() != null) { continue; } if (req.includeActors && IsScriptReadyActor(hit.collider) && GetActorName(hit.collider) != req.excludeActor) { // Hit an actor. // (PhysicsCastHit is a struct, not allocating on heap) thisHit = new PhysicsCastHit { actor = GetActorName(hit.collider), distance = hit.distance, point = hit.point }; } else if (req.includeTerrain && hit.collider.tag == "Ground") { // Hit terrain. // (PhysicsCastHit is a struct, not allocating on heap) thisHit = new PhysicsCastHit { actor = null, distance = hit.distance, point = hit.point }; } else { continue; } closestHit = (!anyHit || thisHit.distance < closestHit.distance) ? thisHit : closestHit; anyHit = true; results?.Add(thisHit); if (req.mode == CastMode.BOOLEAN) { // If we're just returning true/false, that's all we need. break; } } // Sort results by distance, if requested. if (req.mode == CastMode.ALL_SORTED) { results.Sort((a, b) => a.distance.CompareTo(b.distance)); } // Report results as requested. if (req.mode == CastMode.ALL_SORTED || req.mode == CastMode.ALL_UNSORTED) { PhysicsCastResult result = new PhysicsCastResult { hits = results.ToArray() }; reportResult(JsonUtility.ToJson(result)); } else if (req.mode == CastMode.CLOSEST) { reportResult(anyHit ? JsonUtility.ToJson(closestHit) : "null"); } else { reportResult(anyHit ? "true" : "false"); } break; } case "GetPlayerActors": using (Util.Profile(serviceName)) { var jsoner = SharedStringBuilder; jsoner.Clear(); jsoner.Append("["); bool gotOneActor = false; foreach (VoosActor actor in engine.EnumerateActors()) { if (actor.GetIsPlayerControllable()) { if (gotOneActor) { jsoner.Append(","); } jsoner.Append("\""); jsoner.Append(actor.GetName()); jsoner.Append("\""); gotOneActor = true; } } jsoner.Append("]"); reportResult(jsoner.ToString()); break; } case "SetTerrainCell": { var args = JsonUtility.FromJson <TerrainManager.SetCellRpcJsonable>(argsJson); terrainSystem.SetCellValue(args.cell, args.value); reportResult("true"); break; } case "GetTerrainCell": { Vector3 coords = JsonUtility.FromJson <Vector3>(argsJson); TerrainManager.CellValue cellValue = terrainSystem.GetCellValue( new TerrainManager.Cell((int)coords.x, (int)coords.y, (int)coords.z)); GetTerrainCellResult result = new GetTerrainCellResult { shape = (int)cellValue.blockType, dir = (int)cellValue.direction, style = (int)cellValue.style }; reportResult(JsonUtility.ToJson(result)); break; } case "IsMultiplayer": { reportResult(GameBuilderApplication.CurrentGameOptions.playOptions.isMultiplayer ? "true" : "false"); break; } case "TransferPlayerControl": { VoosEngine.TransferPlayerControlRequest request = JsonUtility.FromJson <VoosEngine.TransferPlayerControlRequest>(argsJson); // Engine will handle this asynchronously because the actor might not be immediately // available (maybe it was a clone that was just created, for instance). GetEngine().RequestTransferPlayerControl(request); reportResult("true"); break; } case "GetPlayerControlledActor": { VoosActor actor = GetUserMain().GetPlayerActor(); reportResult(actor == null ? "null" : "\"" + actor.GetName() + "\""); break; } case "IsMasterClient": { reportResult(PhotonNetwork.isMasterClient ? "true" : "false"); break; } case "GetPlayersInfo": { Dictionary <int, string> nicknames = new Dictionary <int, string>(); int i; for (i = 0; i < PhotonNetwork.playerList.Length; i++) { int id = PhotonNetwork.playerList[i].ID; string nick = PhotonNetwork.playerList[i].NickName; nicknames[id] = nick; } VirtualPlayersResult result = new VirtualPlayersResult(); result.allPlayers = new VirtualPlayerResultEntry[virtualPlayerManager.GetVirtualPlayerCount()]; i = 0; foreach (VirtualPlayerManager.VirtualPlayerInfo virtualPlayer in virtualPlayerManager.EnumerateVirtualPlayers()) { Debug.Assert(i < result.allPlayers.Length); result.allPlayers[i].id = virtualPlayer.virtualId; result.allPlayers[i].slotNumber = virtualPlayer.slotNumber; result.allPlayers[i].nickName = virtualPlayer.nickName; ++i; } Debug.Assert(i == result.allPlayers.Length); result.localPlayerId = playerControlsManager.GetVirtualPlayerId(); reportResult(JsonUtility.ToJson(result)); break; } case "RequestUi": { using (Util.Profile("RequestUi")) { GameUiMain.UiCommandList list = JsonUtility.FromJson <GameUiMain.UiCommandList>(argsJson); gameUiMain.SetUiCommands(list); reportResult("true"); } break; } case "GetActorColorField": { GetActorFieldArgs args = JsonUtility.FromJson <GetActorFieldArgs>(argsJson); reportResult(JsonUtility.ToJson(engine.GetActorColor(args.actorId, args.fieldId))); break; } case "SetActorColorField": { SetActorColorFieldArgs args = JsonUtility.FromJson <SetActorColorFieldArgs>(argsJson); engine.SetActorColor(args.actorId, args.fieldId, args.newValue); reportResult("true"); break; } case "CloneActor": using (Util.Profile(serviceName)) { VoosEngine.CloneActorRequest args = JsonUtility.FromJson <VoosEngine.CloneActorRequest>(argsJson); VoosEngine.CloneActorResponse response = GetEngine().CloneActorForScript(args); reportResult(JsonUtility.ToJson(response)); break; } case "InstantiatePrefab": using (Util.Profile(serviceName)) { VoosEngine.InstantiatePrefab.Request args = JsonUtility.FromJson <VoosEngine.InstantiatePrefab.Request>(argsJson); VoosEngine.InstantiatePrefab.Response response = GetEngine().InstantiatePrefabForScript(args); reportResult(JsonUtility.ToJson(response)); break; } case "DestroyActors": using (Util.Profile(serviceName)) { VoosEngine.DestroyActorsRequest args = JsonUtility.FromJson <VoosEngine.DestroyActorsRequest>(argsJson); GetEngine().DestroyActorsForScript(args); reportResult("true"); break; } case "PlaySound": using (Util.Profile(serviceName)) { PlaySoundRequest args = JsonUtility.FromJson <PlaySoundRequest>(argsJson); SoundEffect sfx = soundEffectSystem.GetSoundEffect(args.soundId); if (sfx != null) { if (string.IsNullOrEmpty(args.actorName)) { soundEffectSystem.PlaySoundEffect(sfx, null, args.position); } else { VoosActor actor = engine.GetActor(args.actorName); if (actor == null) { Debug.LogError("Could not play sound on actor. Actor not found: " + args.actorName); reportResult("false"); } soundEffectSystem.PlaySoundEffect(sfx, actor, Vector3.zero); } reportResult("true"); } else { Debug.LogWarning("No SFX with ID: " + args.soundId); reportResult("false"); } break; } case "SpawnParticleEffect": using (Util.Profile(serviceName)) { ParticleEffectRequest args = JsonUtility.FromJson <ParticleEffectRequest>(argsJson); ParticleEffect pfx = particleEffectSystem.GetParticleEffect(args.pfxId); if (pfx != null) { particleEffectSystem.SpawnParticleEffect( pfx, args.position, args.rotation * Mathf.Rad2Deg, args.scale); reportResult("true"); } else { Debug.LogWarning("No particle effect with ID: " + args.pfxId); reportResult("false"); } break; } case "PlayOneShotAnimation": { OneShotAnimationRequest req = JsonUtility.FromJson <OneShotAnimationRequest>(argsJson); VoosActor actor = engine.GetActorByTempId(req.actorTempId); if (actor != null) { actor.PlayOneShotAnimation(req.animationName); } else { Util.LogError($"PlayOneShotAnimation: Could not find actor for temp ID {req.actorTempId}. Ignoring."); } reportResult("true"); break; } case "ProjectPoint": { Camera cam = GetUserMain().GetCamera(); Vector3 point = JsonUtility.FromJson <Vector3>(argsJson); Vector3 screenPoint = cam.WorldToScreenPoint(point); if (screenPoint.z > 0) { Vector2 gameUiPoint = gameUiMain.UnityScreenPointToGameUiPoint(screenPoint); reportResult(JsonUtility.ToJson(gameUiPoint)); } else { reportResult("null"); } break; } case "ProjectSphere": { Camera cam = GetUserMain().GetCamera(); SphereArg inSphere = JsonUtility.FromJson <SphereArg>(argsJson); Vector3 screenCenter = cam.WorldToScreenPoint(inSphere.center); if (screenCenter.z > 0) { Vector3 centerGameUi = gameUiMain.UnityScreenPointToGameUiPoint(screenCenter); Vector3 rightPoint = cam.WorldToScreenPoint(inSphere.center + cam.transform.right * inSphere.radius); Vector3 rightPointGameUi = gameUiMain.UnityScreenPointToGameUiPoint(rightPoint); SphereArg outSphere = new SphereArg { center = centerGameUi, radius = Mathf.Abs(rightPointGameUi.x - centerGameUi.x) }; reportResult(JsonUtility.ToJson(outSphere)); } else { reportResult("null"); } break; } case "GetActorScreenRect": { string actorName = JsonUtility.FromJson <GetActorScreenRectRequest>(argsJson).actor; VoosActor actor = engine.GetActor(actorName); Bounds worldBounds = new Bounds(actor.GetWorldRenderBoundsCenter(), actor.GetWorldRenderBoundsSize()); // Depending on the orientation, any of the 8 corners of the world-space bounding box // can contribute to the screen-space bounding box, so we have to go through them all. Bounds screenBounds = new Bounds(); bool success = true; for (int i = 0; i < 8; i++) { Vector3 worldPoint = new Vector3( (i & 1) > 0 ? worldBounds.min.x : worldBounds.max.x, (i & 2) > 0 ? worldBounds.min.y : worldBounds.max.y, (i & 4) > 0 ? worldBounds.min.z : worldBounds.max.z); Vector3 screenPoint = GetUserMain().GetCamera().WorldToScreenPoint(worldPoint); if (screenPoint.z < 0) { // Off-screen (behind camera). success = false; break; } Vector2 gameUiPoint = gameUiMain.UnityScreenPointToGameUiPoint(screenPoint); if (i == 0) { // Note: due to the Bounds() constructor assuming Vector3.zero as the center // (known Unity bug), we have to reinitialize it here: screenBounds = new Bounds(gameUiPoint, Vector3.zero); } else { screenBounds.Encapsulate(gameUiPoint); } } reportResult(success ? JsonUtility.ToJson(new GetActorScreenRectResponse { x = screenBounds.min.x, y = screenBounds.min.y, w = screenBounds.size.x, h = screenBounds.size.y }) : "null"); break; } case "GetCameraInfo": { Transform cameraTransform = GetUserMain().GetCamera().transform; CameraInfo info = new CameraInfo { pos = cameraTransform.position, rot = cameraTransform.rotation }; reportResult(JsonUtility.ToJson(info)); break; } case "ReportBehaviorException": { Util.LogError($"ReportBehaviorException {argsJson}"); VoosEngine.BehaviorLogItem e = JsonUtility.FromJson <VoosEngine.BehaviorLogItem>(argsJson); engine.HandleBehaviorException(e); reportResult("true"); break; } case "LogBehaviorMessage": { Util.Log($"LogBehaviorMessage {argsJson}"); VoosEngine.BehaviorLogItem msg = JsonUtility.FromJson <VoosEngine.BehaviorLogItem>(argsJson); engine.HandleBehaviorLogMessage(msg); reportResult("true"); break; } case "GetCameraActor": { string cameraActorName = GetUserMain().GetCameraActor()?.GetName(); reportResult(cameraActorName == null ? "null" : ("\"" + cameraActorName + "\"")); break; } case "RequestTempCameraOffset": { TempCameraOffsetRequest request = JsonUtility.FromJson <TempCameraOffsetRequest>(argsJson); if (request.actor == GetUserMain().GetPlayerActor()?.GetName()) { GetUserMain().GetNavigationControls().RequestTemporaryCameraOffset(request.offset); } reportResult("true"); break; } case "GetScreenInfo": { reportResult(JsonUtility.ToJson(gameUiMain.GetScreenInfoForScript())); break; } case "SetSkyType": { JsonWrapper <string> request = JsonUtility.FromJson <JsonWrapper <string> >(argsJson); GameBuilderStage.SkyType skyType; if (Util.TryParseEnum(request.value ?? "", out skyType, true)) { gbStage.SetSkyType(skyType); reportResult("true"); } else { Debug.LogError("Invalid sky type requested: " + request.value); reportResult("false"); } break; } case "GetSkyType": { reportResult(JsonUtility.ToJson(JsonWrapper <string> .Wrap(gbStage.GetSkyType().ToString()))); break; } case "SetSkyColor": { JsonWrapper <Color> request = JsonUtility.FromJson <JsonWrapper <Color> >(argsJson); gbStage.SetSkyColor(request.value); reportResult("true"); break; } case "GetSkyColor": { reportResult(JsonUtility.ToJson(JsonWrapper <Color> .Wrap(gbStage.GetSkyColor()))); break; } case "SetSceneLighting": { JsonWrapper <string> request = JsonUtility.FromJson <JsonWrapper <string> >(argsJson); GameBuilderStage.SceneLightingMode sceneLightingMode; if (Util.TryParseEnum <GameBuilderStage.SceneLightingMode>(request.value, out sceneLightingMode, ignoreCase: true)) { gbStage.SetSceneLightingMode(sceneLightingMode); reportResult("true"); } else { Debug.LogError("Invalid scene lighting mode: " + request.value); reportResult("false"); } break; } case "GetSceneLighting": { reportResult(JsonUtility.ToJson(JsonWrapper <string> .Wrap(gbStage.GetSceneLightingMode().ToString().ToUpperInvariant()))); break; } default: Util.LogError($"VOOS script tried to call unknown service {serviceName}."); break; } } catch (System.Exception e) { // We cannot let exceptions escape. It will tend to crash the process. Util.LogError($"Exception during CallService({serviceName}):\n{e}"); reportResult("false"); } }
void OnClickedIsNpc(VoosActor actor) { AssignPlayerToActor(ASSIGN_ACTOR_AS_NPC, actor.GetName()); }
void OnClickedPlayerNumber(VoosActor actor, int playerNumber) { AssignPlayerToActor(playerNumber, actor.GetName()); }
private void SetSpawnParent() { VoosActor actor = editMain.GetSingleTargetActor(); SelectActor((selectedActor) => { string newParentName = selectedActor?.GetName(); string prevParentName = actor.GetSpawnTransformParent(); undoStack.PushUndoForActor( actor, $"Set actor parent on reset", (undoActor) => { VoosActor newParent = undoActor.GetEngine().GetActor(newParentName); undoActor.SetSpawnTransformParent(VoosActor.IsValidParent(undoActor, newParent) ? newParent?.GetName() : null); }, (undoActor) => { VoosActor prevParent = undoActor.GetEngine().GetActor(prevParentName); undoActor.SetSpawnTransformParent(VoosActor.IsValidParent(undoActor, prevParent) ? prevParent?.GetName() : null); } ); }); }