// Deletes the particle effect with that ID. public void DeleteParticleEffect(string particleEffectId) { Sojo sojo = sojoSystem.GetSojoById(particleEffectId); if (sojo == null) { return; } ClaimableUndoUtil.ClaimableUndoItem undoItem = new ClaimableUndoUtil.ClaimableUndoItem(); undoItem.resourceId = PFX_CLAIM_PREFIX + particleEffectId; undoItem.resourceName = sojo.name; undoItem.label = $"Deleting particle effect {sojo.name}"; undoItem.cannotDoReason = () => { return(null); }; undoItem.cannotUndoReason = () => { return(null); }; undoItem.doIt = () => { sojoSystem.DeleteSojo(particleEffectId); }; undoItem.undo = () => { sojoSystem.PutSojo(sojo); }; ClaimableUndoUtil.PushUndoForResource(undoStack, claimKeeper, undoItem); }
public void Put(string id, VoosActor actor, Texture2D thumbnail) { string json = ExportToJson(actor, thumbnail); Sojo sojo = new Sojo(ToSojoId(id), actor.GetDisplayName(), SojoType.ActorPrefab, json); sojoSystem.PutSojo(sojo); }
void PutSojoRPC(byte[] zippedJson) { string sojoJson = Util.UnGZipString(zippedJson); Sojo sojo = Sojo.Load(JsonUtility.FromJson <Sojo.Saved>(sojoJson)); PutSojoLocal(sojo); }
public void Import(string id, SavedActorPrefab prefab) { string json = JsonUtility.ToJson(prefab, true); Sojo sojo = new Sojo(ToSojoId(id), prefab.label, SojoType.ActorPrefab, json); sojoSystem.PutSojo(sojo); }
public void PutSojo(Sojo sojo) { PutSojoLocal(sojo); string json = JsonUtility.ToJson(sojo.Save()); byte[] zippedJson = Util.GZipString(json); photonView.RPC("PutSojoRPC", PhotonTargets.AllViaServer, zippedJson); }
private void OnSojoDelete(Sojo sojo) { if (sojo.contentType != SojoType.SoundEffect) { return; } audioClipCache.Remove(sojo.id); onSoundEffectRemoved?.Invoke(sojo.id); }
private void PreloadImageForSojo(Sojo sojo) { string url = GetImageUrl(sojo.id); if (url != null) { imageLoader.Request(url); } }
public void PutSojo(Sojo sojo) { // We must first delete it to keep our cache consistent. DeleteSojo(sojo.id); // Now add it. sojosById[sojo.id] = sojo; cacheByName[sojo.name] = sojo; namesKnownNotToExist.Remove(sojo.name); }
private void DeleteSojoLocal(string sojoId) { Sojo sojo = database.GetSojoById(sojoId); if (sojo != null) { database.DeleteSojo(sojoId); onSojoDelete?.Invoke(sojo); } }
void OnSojoDelete(Sojo newSojo) { if (newSojo.contentType != SojoType.ActorPrefab) { return; } string id = FromSojoId(newSojo.id); onActorDelete?.Invoke(id); }
ActorPrefabImpl Deserialize(Sojo sojo) { SavedActorPrefab saved = JsonUtility.FromJson <SavedActorPrefab>(sojo.content); saved.PerformUpgrades(); Texture2D thumbnail = null; if (!saved.thumbnailJZB64.IsNullOrEmpty()) { thumbnail = Util.ZippedJpegToTexture2D(System.Convert.FromBase64String(saved.thumbnailJZB64), false); } return(new ActorPrefabImpl(saved, thumbnail, FromSojoId(sojo.id), sojoSystem)); }
// Gets a particle effect by ID. public ParticleEffect GetParticleEffect(string id) { Sojo sojo = sojoSystem.GetSojoById(id); if (sojo == null) { return(null); } if (sojo.contentType != SojoType.ParticleEffect) { throw new System.Exception("SOJO is not a particle effect: " + sojo); } return(new ParticleEffect(id, sojo.name, JsonUtility.FromJson <ParticleEffectContent>(sojo.content))); }
// Gets a sound effect by name (not unique). public SoundEffect GetSoundEffectByName(string name) { Sojo sojo = sojoSystem.GetSojoByName(name); if (sojo == null) { return(null); } if (sojo.contentType != SojoType.SoundEffect) { throw new System.Exception("SOJO is not a sound effect: " + sojo); } return(new SoundEffect(sojo.id, sojo.name, JsonUtility.FromJson <SoundEffectContent>(sojo.content))); }
private void OnSojoPut(Sojo sojo) { if (sojo.contentType != SojoType.SoundEffect) { return; } audioClipCache.Remove(sojo.id); SoundEffect effect = GetSoundEffect(sojo.id); if (effect != null) { PreloadAndCacheSoundEffect(effect); } onSoundEffectChanged?.Invoke(sojo.id); }
public void Load(Saved database) { Reset(); string builtinSojoJson = Resources.Load <TextAsset>(BUILTIN_SOJOS_RESOURCE_FILE).text; SojoDatabase.Saved builtIn = JsonUtility.FromJson <SojoDatabase.Saved>(builtinSojoJson); foreach (Sojo.Saved saved in builtIn.sojos) { PutSojo(Sojo.Load(saved)); } foreach (Sojo.Saved saved in database.sojos) { PutSojo(Sojo.Load(saved)); } }
public string GetImageUrl(string imageId) { if (!imageId.StartsWith(SOJO_ID_PREFIX)) { return(null); } Sojo sojo = sojoSystem.GetSojoById(imageId); if (sojo == null || sojo.contentType != SojoType.Image) { return(null); } // The URL is everything after the prefix in the ID. return(sojo.id.Substring(SOJO_ID_PREFIX.Length)); }
SavedActorPrefab ToPrefab(VoosActor root, Texture2D thumbnail) { List <VoosActor.PersistedState> savedActors = new List <VoosActor.PersistedState>(); Behaviors.Database brainDatabase = new Behaviors.Database(); List <Sojo.Saved> sojos = new List <Sojo.Saved>(); void ExportActorRecursive(VoosActor actor) { savedActors.Add(actor.Save()); actor.GetBehaviorSystem().ExportBrain(actor.GetBrainName(), brainDatabase); foreach (string sojoId in GetUsedSojoIds(actor)) { Sojo sojo = sojoSystem.GetSojoById(sojoId); if (sojo == null) { Util.LogError($"Could not find sojo of id {sojoId} for actor {actor.name}"); continue; } sojos.Add(sojo.Save()); } foreach (VoosActor child in actor.GetChildActors()) { ExportActorRecursive(child); } } ExportActorRecursive(root); return(new SavedActorPrefab { version = SavedActorPrefab.CurrentVersion, label = root.GetDisplayName(), thumbnailJZB64 = System.Convert.ToBase64String(Util.TextureToZippedJpeg(thumbnail)), brainDatabase = brainDatabase.Save(), sojos = sojos.ToArray(), actors = savedActors.ToArray() }); }
private void PutSojoLocal(Sojo sojo) { database.PutSojo(sojo); onSojoPut?.Invoke(sojo); }
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]); }