Ejemplo n.º 1
0
        void ConsumeJobYield(JobState jobState)
        {
            if (jobState.HasException)
            {
                Debug.LogException(jobState.Exception);
            }
            else
            {
                var jobSpecification = jobState.Specification;
                var jobYield         = jobState.Yield;

                bonePresenceAlfaBuffer.Clear();
                bonePresenceBravoBuffer.Clear();

                foreach (var kvp in jobSpecification.NodeMetadata)
                {
                    bonePresenceAlfaBuffer[kvp.Key]  = kvp.Value.IsConsideredSevered;
                    bonePresenceBravoBuffer[kvp.Key] = !kvp.Value.IsConsideredSevered;
                }

                var originalSubjectTransform = jobSpecification.Subject.transform;

                bool useAlternateForFront, useAlternateForBack;

                if (jobSpecification.Hackable.alternatePrefab == null)
                {
                    useAlternateForFront = false;
                    useAlternateForBack  = false;
                }
                else
                {
                    useAlternateForFront = jobSpecification.Hackable.cloneAlternate(bonePresenceAlfaBuffer);
                    useAlternateForBack  = jobSpecification.Hackable.cloneAlternate(bonePresenceBravoBuffer);
                }

                GameObject alfaObject, bravoObject;

                var backIsNew = useAlternateForBack;

                if (backIsNew)
                {
                    var backSource = useAlternateForBack ? jobSpecification.Hackable.alternatePrefab : jobSpecification.Subject;
                    bravoObject      = (GameObject)Instantiate(backSource);
                    bravoObject.name = string.Format("{0} (Bravo)", jobSpecification.Subject);
                }
                else
                {
                    bravoObject = jobSpecification.Subject;
                }

                var alfaSource = useAlternateForFront ? jobSpecification.Hackable.alternatePrefab : jobSpecification.Subject;
                alfaObject = (GameObject)Instantiate(alfaSource);

                HandleHierarchy(alfaObject.transform, bonePresenceAlfaBuffer, jobSpecification.NodeMetadata);
                HandleHierarchy(bravoObject.transform, bonePresenceBravoBuffer, jobSpecification.NodeMetadata);

                var parent = originalSubjectTransform.parent;

                var position = originalSubjectTransform.localPosition;
                var scale    = originalSubjectTransform.localScale;

                var rotation = originalSubjectTransform.localRotation;

                alfaObject.transform.parent        = parent;
                alfaObject.transform.localPosition = position;
                alfaObject.transform.localScale    = scale;

                alfaObject.transform.localRotation = rotation;

                alfaObject.layer = jobSpecification.Subject.layer;

                alfaObject.name = string.Format("{0} (Alfa)", jobSpecification.Subject);

                if (backIsNew)
                {
                    bravoObject.transform.parent        = parent;
                    bravoObject.transform.localPosition = position;
                    bravoObject.transform.localScale    = scale;

                    bravoObject.transform.localRotation = rotation;

                    bravoObject.layer = jobSpecification.Subject.layer;

                    Destroy(jobSpecification.Subject);
                }

                ApplySnapshotsToRoot(alfaObject, jobYield.Alfa);
                ApplySnapshotsToRoot(bravoObject, jobYield.Bravo);

                var results = new GameObject[] {
                    alfaObject, bravoObject
                };

                jobSpecification.Hackable.handleSlice(results);
            }
        }
Ejemplo n.º 2
0
        public void SeverByJoint(GameObject subject, string jointName, float rootTipProgression, Vector3?planeNormal)
        {
            //Sanity check: are we already slicing this?
            foreach (var extantState in jobStates)
            {
                if (ReferenceEquals(extantState.Specification.Subject, subject))
                {
                    //Debug.LogErrorFormat("Turbo Slicer was asked to slice '{0}' but this target is already enqueued.", subject.name);
                    return;
                }
            }

            rootTipProgression = Mathf.Clamp01(rootTipProgression);

            //These here are in local space because they're only used to copy to the resultant meshes; they're not used
            //to transform the vertices. We expect a world-space slice input.

            Hackable hackable = null;

            {
                var hackables = subject.GetComponentsInChildren <Hackable>();

                if (hackables.Length > 0)
                {
                    if (hackables.Length > 1)
                    {
                        Debug.LogWarning("Limb Hacker found multiple slice configurations on object '" + subject.name + "'! Behavior is undefined.");
                    }

                    hackable = hackables[0];
                }
                else
                {
                    Debug.LogWarning("Limb Hacker found no slice configuration on object '" + subject.name + "'.");
                    return;
                }
            }

            //We need information about which BONES are getting severed.
            var metadataByNodeName = new Dictionary <string, NodeMetadata>();
            {
                var childTransformByName = new Dictionary <string, Transform>();
                var parentKeyByKey       = new Dictionary <string, string>();

                foreach (Transform t in GetConcatenatedHierarchy(subject.transform))
                {
                    childTransformByName[t.name] = t;

                    var parent = t.parent;

                    if (t == subject.transform)
                    {
                        parent = null;
                    }

                    parentKeyByKey[t.name] = parent == null ? null : parent.name;
                }

                var severedByChildName = new Dictionary <string, bool>();
                {
                    foreach (string childName in childTransformByName.Keys)
                    {
                        severedByChildName[childName] = childName == jointName;
                    }

                    bool changesMade;
                    do
                    {
                        changesMade = false;

                        foreach (string childKey in childTransformByName.Keys)
                        {
                            bool severed = severedByChildName[childKey];

                            if (severed)
                            {
                                continue;
                            }

                            string parentKey = parentKeyByKey[childKey];

                            bool parentSevered;

                            if (severedByChildName.TryGetValue(parentKey, out parentSevered) == false)
                            {
                                continue;
                            }

                            if (parentSevered)
                            {
                                severedByChildName[childKey] = true;

                                changesMade = true;
                            }
                        }
                    }while (changesMade);
                }

                foreach (var kvp in severedByChildName)
                {
                    var t = childTransformByName[kvp.Key];
                    var isConsideredSevered = kvp.Value;
                    metadataByNodeName[kvp.Key] = new NodeMetadata(t, isConsideredSevered);
                }
            }

            IEnumerable <MeshSnapshot> snapshots;
            var forwardPassAgent = subject.GetComponent <ForwardPassAgent>();

            if (forwardPassAgent == null)
            {
                var snapshotBuilder      = new List <MeshSnapshot>();
                var skinnedMeshRenderers = subject.GetComponentsInChildren <SkinnedMeshRenderer>(true);
                foreach (var smr in skinnedMeshRenderers)
                {
                    var mesh = smr.sharedMesh;

                    var boneMetadata = new BoneMetadata[smr.bones.Length];

                    var bones     = smr.bones;
                    var bindPoses = mesh.bindposes;

                    for (int i = 0; i < boneMetadata.Length; i++)
                    {
                        boneMetadata[i] = new BoneMetadata(i, bones[i].name, bindPoses[i]);
                    }

                    int?infillIndex = null;
                    if (hackable.infillMaterial != null)
                    {
                        var mats = smr.sharedMaterials;
                        for (int i = 0; i < mats.Length; i++)
                        {
                            if (hackable.infillMaterial == mats[i])
                            {
                                infillIndex = i;
                                break;
                            }
                        }
                    }

                    MeshSnapshot snapshot;

                    MeshSnapshot preloadedFragment;
                    if (preloadedMeshes.TryGetValue(mesh.GetInstanceID(), out preloadedFragment))
                    {
                        //The preloaded fragments are missing data which is particular to the SMR. We'll combine it with such data here.

                        snapshot = preloadedFragment.WithKey(smr.name).WithMaterials(smr.sharedMaterials).WithBoneMetadata(boneMetadata).WithInfillIndex(infillIndex);
                    }
                    else
                    {
                        var indices = new int[mesh.subMeshCount][];
                        for (int i = 0; i < mesh.subMeshCount; i++)
                        {
                            indices[i] = mesh.GetIndices(i);
                        }

                        snapshot = new MeshSnapshot(
                            smr.name,
                            mesh.vertices,
                            mesh.normals,
                            mesh.uv,
                            mesh.tangents,
                            mesh.boneWeights,
                            smr.sharedMaterials,
                            boneMetadata,
                            infillIndex,
                            indices);
                    }

                    snapshotBuilder.Add(snapshot);
                }
                snapshots = snapshotBuilder;
            }
            else
            {
                snapshots = forwardPassAgent.Snapshot;
            }

            var jobSpec  = new JobSpecification(subject, hackable, snapshots, metadataByNodeName, hackable.infillMaterial, jointName, rootTipProgression, planeNormal, hackable.infillMode, true);
            var jobState = new JobState(jobSpec);

            try
            {
                switch (workerThreadMode)
                {
                case WorkerThreadMode.Asynchronous:
                    jobStates.Add(jobState);
                        #if NETFX_CORE && !UNITY_EDITOR
                    System.Threading.Tasks.Task.Factory.StartNew(ThreadSafeHack.Slice, jobState);
                        #else
                    System.Threading.ThreadPool.QueueUserWorkItem(ThreadSafeHack.Slice, jobState);
                        #endif
                    break;

                case WorkerThreadMode.Synchronous:
                    ThreadSafeHack.Slice(jobState);
                    if (jobState.HasYield)
                    {
                        ConsumeJobYield(jobState);
                    }
                    else if (jobState.HasException)
                    {
                        throw jobState.Exception;
                    }
                    break;

                default:
                    throw new System.NotImplementedException();
                }
            }
            catch (System.Exception ex)
            {
                Debug.LogException(ex, subject);
            }
        }