add some extra assets FX and SFX
This commit is contained in:
@@ -0,0 +1,637 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NobleMuffins.LimbHacker.Guts
|
||||
{
|
||||
public class LimbHackerAgent : MonoBehaviour
|
||||
{
|
||||
public Mesh[] preloadMeshes;
|
||||
public WorkerThreadMode workerThreadMode;
|
||||
|
||||
private readonly HashSet<JobState> jobStates = new HashSet<JobState> ();
|
||||
private readonly List<JobState> jobStateQueue = new List<JobState> ();
|
||||
private readonly ICollection<JobState> jobStateRemovalQueue = new List<JobState> ();
|
||||
|
||||
private readonly IDictionary<int, MeshSnapshot> preloadedMeshes = new Dictionary<int, MeshSnapshot> ();
|
||||
|
||||
private static LimbHackerAgent _instance;
|
||||
|
||||
public static LimbHackerAgent instance {
|
||||
get {
|
||||
if (_instance == null) {
|
||||
GameObject go = new GameObject ();
|
||||
_instance = go.AddComponent<LimbHackerAgent> ();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public void Awake ()
|
||||
{
|
||||
#if UNITY_WEBGL
|
||||
if (workerThreadMode == WorkerThreadMode.Asynchronous) {
|
||||
Debug.LogWarning ("Turbo Slicer will run synchronously because WebGL does not support threads.", this);
|
||||
workerThreadMode = WorkerThreadMode.Synchronous;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (preloadMeshes != null) {
|
||||
for (int i = 0; i < preloadMeshes.Length; i++) {
|
||||
var mesh = preloadMeshes [i];
|
||||
var indices = new int[mesh.subMeshCount][];
|
||||
for (int j = 0; j < mesh.subMeshCount; j++) {
|
||||
indices [j] = mesh.GetIndices (j);
|
||||
}
|
||||
|
||||
//Note that this is NOT a usable mesh snapshot. It will need to be combined with live data at runtime.
|
||||
var rom = new MeshSnapshot (null, mesh.vertices, mesh.normals, mesh.uv, mesh.tangents, mesh.boneWeights, new Material[0], new BoneMetadata[0], null, indices);
|
||||
preloadedMeshes [mesh.GetInstanceID ()] = rom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start ()
|
||||
{
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
//These buffers are used in ConsumeJobYield. This method is executed only on the event dispatch thread and therefore will not be clobbered.
|
||||
readonly Dictionary<string, bool> bonePresenceAlfaBuffer = new Dictionary<string, bool> ();
|
||||
readonly Dictionary<string, bool> bonePresenceBravoBuffer = new Dictionary<string, bool> ();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ApplySnapshotsToRoot (alfaObject, jobYield.Alfa);
|
||||
ApplySnapshotsToRoot (bravoObject, jobYield.Bravo);
|
||||
|
||||
var results = new GameObject[] {
|
||||
alfaObject, bravoObject
|
||||
};
|
||||
|
||||
jobSpecification.Hackable.handleSlice (results, jobState.Yield.PlaneInWorldSpace, jobState.Yield.FocalPointInWorldSpace);
|
||||
|
||||
if (backIsNew) {
|
||||
// print ("destroy sliced object value " + jobSpecification.Hackable.ignoreDestroyOriginalObject);
|
||||
|
||||
if (jobSpecification.Hackable.ignoreDestroyOriginalObject) {
|
||||
jobSpecification.Hackable.eventsOnIgnoreDestroyOriginalObject.Invoke ();
|
||||
|
||||
if (jobSpecification.Hackable.setCustomIDOnSliceSpieces) {
|
||||
Hackable alfaObjectHackable = alfaObject.GetComponent<Hackable> ();
|
||||
|
||||
if (alfaObjectHackable != null) {
|
||||
alfaObjectHackable.setCustomIDOnSliceSpieces = true;
|
||||
|
||||
alfaObjectHackable.setRandomString (jobSpecification.Hackable.getRandomString ());
|
||||
}
|
||||
|
||||
Hackable bravoObjectHackable = bravoObject.GetComponent<Hackable> ();
|
||||
|
||||
if (bravoObjectHackable != null) {
|
||||
bravoObjectHackable.setCustomIDOnSliceSpieces = true;
|
||||
|
||||
bravoObjectHackable.setRandomString (jobSpecification.Hackable.getRandomString ());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Destroy (jobSpecification.Subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//These buffers are used in HandleHierarchy. This method is executed only on the event dispatch thread and therefore will not be clobbered.
|
||||
readonly ICollection<Transform> boneBuffer = new HashSet<Transform> ();
|
||||
readonly ICollection<GameObject> rendererHolderBuffer = new HashSet<GameObject> ();
|
||||
readonly List<Transform> childrenBuffer = new List<Transform> ();
|
||||
|
||||
private void HandleHierarchy (Transform root, Dictionary<string, bool> bonePresenceByName, IDictionary<string, NodeMetadata> originalsByName)
|
||||
{
|
||||
boneBuffer.Clear ();
|
||||
|
||||
var smrs = root.GetComponentsInChildren<SkinnedMeshRenderer> ();
|
||||
|
||||
rendererHolderBuffer.Clear ();
|
||||
|
||||
foreach (var smr in smrs) {
|
||||
rendererHolderBuffer.Add (smr.gameObject);
|
||||
|
||||
var _bones = smr.bones;
|
||||
|
||||
for (int i = 0; i < _bones.Length; i++) {
|
||||
var bone = _bones [i];
|
||||
|
||||
boneBuffer.Add (bone);
|
||||
|
||||
// Hierarchies often have transforms between bones and the root that are not
|
||||
// part of the bones collection pulled from the SMR. However if we turn these
|
||||
// intermediaries off, the ragdoll will not work. For the purposes of this
|
||||
// procedure, we're going to treat these AS bones.
|
||||
|
||||
boneBuffer.Add (bone.parent);
|
||||
}
|
||||
}
|
||||
|
||||
childrenBuffer.Clear ();
|
||||
if (childrenBuffer.Capacity < bonePresenceByName.Count) {
|
||||
childrenBuffer.Capacity = bonePresenceByName.Count;
|
||||
}
|
||||
|
||||
ConcatenateHierarchy (root, childrenBuffer);
|
||||
|
||||
for (int i = 0; i < childrenBuffer.Count; i++) {
|
||||
var t = childrenBuffer [i];
|
||||
var go = t.gameObject;
|
||||
var thisIsTheSkinnedMeshRenderer = rendererHolderBuffer.Contains (go);
|
||||
var shouldBePresent = true;
|
||||
|
||||
var presenceKeySource = t;
|
||||
do {
|
||||
string presenceKey = presenceKeySource.name;
|
||||
if (bonePresenceByName.ContainsKey (presenceKey)) {
|
||||
shouldBePresent = bonePresenceByName [presenceKey];
|
||||
break;
|
||||
} else {
|
||||
presenceKeySource = presenceKeySource.parent;
|
||||
}
|
||||
} while (childrenBuffer.Contains (presenceKeySource));
|
||||
|
||||
NodeMetadata sourceMetadata;
|
||||
if (originalsByName.TryGetValue (t.name, out sourceMetadata)) {
|
||||
t.localPosition = sourceMetadata.LocalPosition;
|
||||
t.localRotation = sourceMetadata.LocalRotation;
|
||||
t.localScale = sourceMetadata.LocalScale;
|
||||
|
||||
shouldBePresent &= sourceMetadata.IsActive;
|
||||
}
|
||||
|
||||
bool isBone = boneBuffer.Contains (t);
|
||||
|
||||
if (!shouldBePresent && isBone) {
|
||||
var c = t.GetComponent<Collider> ();
|
||||
if (c != null) {
|
||||
c.enabled = shouldBePresent;
|
||||
}
|
||||
|
||||
var r = t.GetComponent<Rigidbody> ();
|
||||
if (r != null) {
|
||||
r.mass = float.Epsilon;
|
||||
}
|
||||
} else {
|
||||
shouldBePresent |= thisIsTheSkinnedMeshRenderer;
|
||||
|
||||
go.SetActive (shouldBePresent || thisIsTheSkinnedMeshRenderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ICollection<Transform> GetConcatenatedHierarchy (Transform t)
|
||||
{
|
||||
var children = new HashSet<Transform> () as ICollection<Transform>;
|
||||
ConcatenateHierarchy (t, children);
|
||||
return children;
|
||||
}
|
||||
|
||||
static void ConcatenateHierarchy (Transform root, ICollection<Transform> resultBuffer)
|
||||
{
|
||||
for (int i = 0; i < root.childCount; i++) {
|
||||
var child = root.GetChild (i);
|
||||
resultBuffer.Add (child);
|
||||
ConcatenateHierarchy (child, resultBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void ApplySnapshotsToRoot (GameObject root, IEnumerable<MeshSnapshot> snapshots)
|
||||
{
|
||||
var skinnedMeshRenderers = root.GetComponentsInChildren<SkinnedMeshRenderer> (true);
|
||||
|
||||
foreach (var snapshot in snapshots) {
|
||||
for (int i = 0; i < skinnedMeshRenderers.Length; i++) {
|
||||
if (skinnedMeshRenderers [i] != null) {
|
||||
if (skinnedMeshRenderers [i].name.Equals (snapshot.key)) {
|
||||
var skinnedMeshRenderer = skinnedMeshRenderers [i];
|
||||
|
||||
if (snapshot.vertices.Length > 0) {
|
||||
var bindPoses = new Matrix4x4[snapshot.boneMetadata.Length];
|
||||
|
||||
for (int j = 0; j < bindPoses.Length; j++) {
|
||||
bindPoses [j] = snapshot.boneMetadata [j].BindPose;
|
||||
}
|
||||
|
||||
//Note that we do not explicitly call recalculate bounds because (as per the manual) this is implicit in an
|
||||
//assignment to vertices whenever the vertex count changes from zero to non-zero.
|
||||
|
||||
var mesh = new Mesh ();
|
||||
|
||||
skinnedMeshRenderer.materials = snapshot.materials;
|
||||
|
||||
mesh.vertices = snapshot.vertices;
|
||||
mesh.normals = snapshot.normals;
|
||||
mesh.uv = snapshot.coords;
|
||||
mesh.boneWeights = snapshot.boneWeights;
|
||||
mesh.tangents = snapshot.tangents;
|
||||
mesh.subMeshCount = snapshot.indices.Length;
|
||||
mesh.bindposes = bindPoses;
|
||||
|
||||
for (int j = 0; j < snapshot.indices.Length; j++) {
|
||||
mesh.SetTriangles (snapshot.indices [j], j, false);
|
||||
}
|
||||
|
||||
mesh.UploadMeshData (true);
|
||||
|
||||
skinnedMeshRenderer.sharedMesh = mesh;
|
||||
} else {
|
||||
DestroyImmediate (skinnedMeshRenderer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var forwardPassAgent = root.GetComponent<ForwardPassAgent> ();
|
||||
|
||||
if (forwardPassAgent == null)
|
||||
forwardPassAgent = root.AddComponent<ForwardPassAgent> ();
|
||||
|
||||
forwardPassAgent.Snapshot = snapshots;
|
||||
}
|
||||
|
||||
public static bool DetermineSlice (Hackable hackable, Vector3 pointInWorldSpace, ref string boneName, ref float rootTipProgression)
|
||||
{
|
||||
const int nothing = -1;
|
||||
|
||||
var severables = hackable.severables;
|
||||
|
||||
|
||||
//in progress to add an option to priorize certain body parts to slice
|
||||
//Transform [] temporalSeverables = new Transform [2];
|
||||
//for (var i = 0; i < temporalSeverables.Length; i++) {
|
||||
// temporalSeverables [i] = severables [i];
|
||||
//}
|
||||
|
||||
//severables = new Transform [temporalSeverables.Length];
|
||||
|
||||
//for (var i = 0; i < temporalSeverables.Length; i++) {
|
||||
// severables [i] = temporalSeverables [i];
|
||||
//}
|
||||
|
||||
//print (severables.Length);
|
||||
|
||||
|
||||
var indexByObject = new Dictionary<Transform, int> ();
|
||||
for (var i = 0; i < severables.Length; i++) {
|
||||
indexByObject [severables [i]] = i;
|
||||
}
|
||||
|
||||
var severablesInThreeSpace = new Vector3[severables.Length];
|
||||
for (var i = 0; i < severables.Length; i++) {
|
||||
severablesInThreeSpace [i] = severables [i].position;
|
||||
}
|
||||
|
||||
var deltas = new Vector3[severables.Length];
|
||||
for (var i = 0; i < severables.Length; i++) {
|
||||
deltas [i] = severablesInThreeSpace [i] - pointInWorldSpace;
|
||||
}
|
||||
|
||||
var mags = new float[severables.Length];
|
||||
for (var i = 0; i < severables.Length; i++) {
|
||||
mags [i] = deltas [i].magnitude;
|
||||
}
|
||||
|
||||
var indexOfNearestThing = nothing;
|
||||
var distanceToNearestThing = float.PositiveInfinity;
|
||||
for (var i = 0; i < severables.Length; i++) {
|
||||
if (mags [i] < distanceToNearestThing) {
|
||||
indexOfNearestThing = i;
|
||||
distanceToNearestThing = mags [i];
|
||||
}
|
||||
}
|
||||
|
||||
if (indexOfNearestThing != nothing) {
|
||||
var nearestThing = severables [indexOfNearestThing];
|
||||
|
||||
if (indexByObject.ContainsKey (nearestThing.parent)) {
|
||||
var parentIndex = indexByObject [nearestThing.parent];
|
||||
|
||||
var hereDelta = severablesInThreeSpace [indexOfNearestThing] - severablesInThreeSpace [parentIndex];
|
||||
|
||||
var touchDelta = pointInWorldSpace - severablesInThreeSpace [parentIndex];
|
||||
|
||||
//If the touch is closer to the parent than the severable is, than it's between them.
|
||||
//We'll use that and then use the root tip progression to slice just the right spot.
|
||||
if (touchDelta.magnitude < hereDelta.magnitude) {
|
||||
indexOfNearestThing = parentIndex;
|
||||
nearestThing = severables [indexOfNearestThing];
|
||||
}
|
||||
}
|
||||
|
||||
var childIndices = new List<int> ();
|
||||
|
||||
for (var i = 0; i < severables.Length; i++) {
|
||||
var candidate = severables [i];
|
||||
|
||||
if (candidate.parent == nearestThing) {
|
||||
childIndices.Add (i);
|
||||
}
|
||||
}
|
||||
|
||||
rootTipProgression = 0f;
|
||||
|
||||
if (childIndices.Count > 0) {
|
||||
var aggregatedChildPositions = Vector3.zero;
|
||||
|
||||
foreach (var i in childIndices) {
|
||||
aggregatedChildPositions += severablesInThreeSpace [i];
|
||||
}
|
||||
|
||||
var meanChildPosition = aggregatedChildPositions / childIndices.Count;
|
||||
|
||||
var alfa = (pointInWorldSpace - nearestThing.position).sqrMagnitude;
|
||||
var bravo = (pointInWorldSpace - meanChildPosition).sqrMagnitude;
|
||||
|
||||
rootTipProgression = Mathf.Clamp (alfa / bravo, 0.0f, 0.99f);
|
||||
}
|
||||
|
||||
boneName = nearestThing.name;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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.Equals (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);
|
||||
}
|
||||
}
|
||||
|
||||
void Update ()
|
||||
{
|
||||
jobStateRemovalQueue.Clear ();
|
||||
jobStateQueue.Clear ();
|
||||
jobStateQueue.AddRange (jobStates);
|
||||
foreach (var jobState in jobStateQueue) {
|
||||
if (jobState.IsDone) {
|
||||
try {
|
||||
if (jobState.HasYield) {
|
||||
ConsumeJobYield (jobState);
|
||||
} else if (jobState.HasException) {
|
||||
throw jobState.Exception;
|
||||
}
|
||||
} catch (System.Exception ex) {
|
||||
Debug.LogException (ex, jobState.Specification.Subject);
|
||||
|
||||
} finally {
|
||||
jobStateRemovalQueue.Add (jobState);
|
||||
}
|
||||
}
|
||||
}
|
||||
jobStates.ExceptWith (jobStateRemovalQueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user