public ActorBehaviorsEditor(string actorId, VoosEngine engine, UndoStack undoStack) { this.actorId = actorId; this.engine = engine; this.undoStack = undoStack; this.behaviorSystem = actor.GetBehaviorSystem(); }
// Best-effort semantics. This will silently fail and just not call thenFunc // is the actor can't be found or can't be owned before timeout. public static void GetValidActorThen( VoosEngine engineRef, string actorName, System.Action <VoosActor> thenFunc) { VoosActor currentActor = engineRef.GetActor(actorName); if (currentActor == null) { return; } currentActor.RequestOwnershipThen(() => thenFunc(currentActor)); }
public static string GetUnableToEditActorReason(VoosEngine engineRef, string actorName) { VoosActor currentActor = engineRef.GetActor(actorName); if (currentActor == null) { return($"The actor does not exist anymore."); } if (currentActor.IsLockedByAnother()) { return($"{currentActor.GetLockingOwnerNickName()} is editing '{currentActor.GetDisplayName()}'."); } return(null); }
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) }); }
public IEnumerator Setup() { TestUtil.TestScene scene = new TestUtil.TestScene("main"); yield return(scene.LoadAndWait()); behaviorSystem = scene.FindRootComponent <BehaviorSystem>("ScriptingSystems"); voosEngine = scene.FindRootComponent <VoosEngine>("ScriptingSystems"); // Wait for loading done.. while (true) { if (voosEngine.GetIsRunning()) { yield break; } yield return(null); } }
public Services( TerrainManager terrainSystem, VoosEngine engine, GameUiMain gameUiMain, SoundEffectSystem soundEffectSystem, ParticleEffectSystem particleEffectSystem, VirtualPlayerManager virtualPlayerManager, PlayerControlsManager playerControlsManager, GameBuilderStage gbStage) { this.terrainSystem = terrainSystem; this.engine = engine; this.gameUiMain = gameUiMain; this.soundEffectSystem = soundEffectSystem; this.particleEffectSystem = particleEffectSystem; this.virtualPlayerManager = virtualPlayerManager; this.playerControlsManager = playerControlsManager; this.gbStage = gbStage; }
public string ToUserFriendlyString(VoosEngine engine) { switch (mode) { case Mode.NONE: return("(Nothing)"); case Mode.BY_TAG: return((tagOrName == "player") ? "(Player)" : "Tag: " + tagOrName); case Mode.BY_NAME: VoosActor actor = engine.GetActor(tagOrName); return(actor != null?actor.GetDisplayName() : "(invalid)"); case Mode.ANY: return("(any actor)"); default: throw new System.Exception("Invalid mode " + mode); } }
public void Load(SaveGame saved, string voosFilePath = null) { StartCoroutine(PerformDeferredBehaviorUpgrades(saved.version)); bool removeUnusedBehaviors = saved.version < FirstVersionAllowingUnusedBehaviors; var usedBrainIds = VoosEngine.GetUsedBrainIds(saved.voosEngineState.actors); if (saved.version < FirstVersionWithLegacyWarning) { behaviors.returnEmptyForMissingBuiltinBehaviors = true; } behaviors.LoadDatabase(saved.behaviorDatabase, removeUnusedBehaviors, usedBrainIds); engine.SetPersistedState(saved.voosEngineState); // Load stage before terrain..dependency there for world size. Not sure if good...shouldn't terrain just have its own size? stage.Load(saved.stage); terrain.SetPersistedState(stage.GetGroundSize(), saved.gridState); sojoSystem.Reset(); if (saved.version >= FirstVersionWithSojoDatabase) { sojoSystem.LoadDatabase(saved.sojoDatabase); } if (saved.cardPacks != null) { behaviors.LoadCardPacks(saved.cardPacks); } if (saved.actorPacks != null) { sceneActorLibrary.LoadActorPacks(saved.actorPacks); } if (saved.version < FirstVersionWithLegacyWarning && !SuppressLegacyWarning) { popups.ShowTwoButtons(OLD_SAVE_MESSAGE, "Open Project Location", () => { Application.OpenURL("file://" + System.IO.Path.GetDirectoryName(voosFilePath)); }, "OK", null, 800f); } }
public static void PushUndoForMany(this UndoStack stack, VoosEngine engine, IEnumerable <VoosActor> actors, string verb, System.Action <VoosActor> doIt, System.Action <VoosActor> undo) { List <string> actorNames = (from actor in actors select actor.GetName()).ToList(); if (actorNames.Count == 1) { // Special case this to be the fancier. string actorName = actorNames[0]; if (GetUnableToEditActorReason(engine, actorName) == null) { VoosActor actor = engine.GetActor(actorName); stack.PushUndoForActor(actor, $"{verb} {actor.GetDisplayName()}", doIt, undo); } return; } stack.Push(new UndoStack.Item { actionLabel = $"{verb} {actorNames.Count} actors", // We'll just do best effort for all this - so never block it. getUnableToDoReason = () => null, getUnableToUndoReason = () => null, doIt = () => { foreach (string name in actorNames) { GetValidActorThen(engine, name, doIt); } }, undo = () => { foreach (string name in actorNames) { GetValidActorThen(engine, name, undo); } } }); }
public virtual VoosActor Instantiate(VoosEngine engine, BehaviorSystem behaviorSystem, Vector3 position, Quaternion rotation, System.Action <VoosActor> setupActor) { // TODO TODO we should make a copy of 'saved' in case Instantiate is called again.. if (this.saved.sojos != null) { foreach (var savedSojo in this.saved.sojos) { if (sojos.GetSojoById(savedSojo.id) == null) { sojos.PutSojo(Sojo.Load(savedSojo)); } } } // Import behaviors. For now, create entirely new brain IDs. var brainIdMap = new Dictionary <string, string>(); for (int i = 0; i < this.saved.brainDatabase.brainIds.Length; i++) { string brainId = this.saved.brainDatabase.brainIds[i]; string newId = behaviorSystem.GenerateUniqueId(); brainIdMap[brainId] = newId; this.saved.brainDatabase.brainIds[i] = newId; } // Use the new brain IDs.. for (int i = 0; i < saved.actors.Length; i++) { if (brainIdMap.ContainsKey(saved.actors[i].brainName)) { saved.actors[i].brainName = brainIdMap[saved.actors[i].brainName]; } else { // Always default to default brain. Some prefabs have dangling brain // IDs, and bad stuff can happen if we just keep those. Util.LogWarning($"WARNING: Actor prefab '{saved.actors[i].displayName}' ({saved.actors[i].name}) had dangling brainName: {saved.actors[i].brainName}"); saved.actors[i].brainName = VoosEngine.DefaultBrainUid; } } var expectedBrainIds = new HashSet <string>(from actor in this.saved.actors select actor.brainName); behaviorSystem.MergeNonOverwrite(saved.brainDatabase, expectedBrainIds); // Instantiate the actor hierarchy - very important we update the parent // references, as well as any property references in the use.. // Create new names for all actors var actorNameMap = new Dictionary <string, string>(); foreach (var savedActor in saved.actors) { actorNameMap[savedActor.name] = engine.GenerateUniqueId(); } // Compute xform to go from saved to instance... then just apply to all. var savedRoot = saved.actors[0]; Matrix4x4 savedRootLocalToWorld = new Matrix4x4(); savedRootLocalToWorld.SetTRS(savedRoot.position, savedRoot.rotation, savedRoot.localScale); Matrix4x4 instRootLocalToWorld = new Matrix4x4(); instRootLocalToWorld.SetTRS(position, rotation, savedRoot.localScale); Matrix4x4 savedToInstance = instRootLocalToWorld * savedRootLocalToWorld.inverse; // Instantiate the tree. List <VoosActor> instances = new List <VoosActor>(); foreach (var savedActor in saved.actors) { string instanceName = actorNameMap[savedActor.name]; Vector3 instPos = savedToInstance * savedActor.position.ToHomogeneousPosition(); Quaternion instRot = savedToInstance.rotation * savedActor.rotation; System.Action <VoosActor> setupThisActor = actor => { Debug.Assert(actor.GetName() == instanceName, "New instance did not have the new name we generated"); // Push the saved data to this new actor var actorDataCopy = savedActor; actorDataCopy.position = instPos; actorDataCopy.rotation = instRot; actorDataCopy.name = instanceName; // Make sure we update the transform parent! if (!actorDataCopy.transformParent.IsNullOrEmpty() && actorNameMap.ContainsKey(actorDataCopy.transformParent)) { actorDataCopy.transformParent = actorNameMap[actorDataCopy.transformParent]; } if (!actorDataCopy.spawnTransformParent.IsNullOrEmpty() && actorNameMap.ContainsKey(actorDataCopy.spawnTransformParent)) { actorDataCopy.spawnTransformParent = actorNameMap[actorDataCopy.spawnTransformParent]; } actor.UpdateFrom(actorDataCopy); setupActor(actor); }; VoosActor instance = engine.CreateActor(instPos, instRot, setupThisActor, instanceName); instances.Add(instance); } // FINALLY...fix up any actor refs! foreach (VoosActor inst in instances) { var brain = ActorBehaviorsEditor.FromActor(inst); foreach (var assigned in brain.GetAssignedBehaviors()) { foreach (var prop in assigned.GetProperties()) { if (prop.propType == BehaviorProperties.PropType.Actor) { string refActorName = (string)prop.data; if (!refActorName.IsNullOrEmpty() && actorNameMap.ContainsKey(refActorName)) { prop.SetData(actorNameMap[refActorName]); } } else if (prop.propType == BehaviorProperties.PropType.ActorGroup) { ActorGroupSpec group = ActorGroupSpec.FromString((string)prop.data); if (group.mode == ActorGroupSpec.Mode.BY_NAME && actorNameMap.ContainsKey(group.tagOrName)) { group = group.WithTagOrName(actorNameMap[group.tagOrName]); prop.SetData(group.ToString()); } } } } } return(instances[0]); }
public int GetLineNumberForError(string errorMessage) { return(VoosEngine.ExtractFirstLineNumberForModuleError(this.behaviorUri, errorMessage)); }