Exemple #1
0
        private void Update()
        {
            ActorGroupSpec groupSpec = ActorGroupSpec.FromString((string)editor.data);

            buttonLabel.text = groupSpec.ToUserFriendlyString(engine);
        }
    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]);
    }