public void Optimize() { int[] remapLinks = RemapLinks(); List <int> remapNodes = new List <int>(); for (int i = 0; i < remapLinks.Length; ++i) { TxLinkHandle link = links[remapLinks[i]]; link.index = i; int node0 = remapNodes.IndexOf(link.node0); if (node0 == -1) { node0 = remapNodes.Count; remapNodes.Add(link.node0); } link.node0 = node0; int node1 = remapNodes.IndexOf(link.node1); if (node1 == -1) { node1 = remapNodes.Count; remapNodes.Add(link.node1); } link.node1 = node1; } foreach (TxNodeHandle n in nodes) { int index = remapNodes.IndexOf(n.index); if (index == -1) { index = remapNodes.Count; remapNodes.Add(n.index); } n.index = index; } foreach (TxFaceHandle f in faces) { f.node0 = nodes[f.node0].index; f.node1 = nodes[f.node1].index; f.node2 = nodes[f.node2].index; } TxTruss data = trussData; foreach (TxTruss.NamedSet s in data.nodesSet) { for (int i = 0; i < s.indices.Length; ++i) { s.indices[i] = nodes[s.indices[i]].index; } } foreach (TxTruss.NamedSet s in data.linksSet) { for (int i = 0; i < s.indices.Length; ++i) { s.indices[i] = links[s.indices[i]].index; } } UpdateHandles(); DestroyHandles(); CreateHandles(); }
void CreateHandles() { TxTruss data = trussData; if (data == null) { return; } nodes = new TxNodeHandle[data.nodeCount]; for (int i = 0; i < data.nodeCount; ++i) { TxNodeHandle node = TxNodeHandle.CreateInstance(); node.index = i; node.name = string.Format("N({0})", i); node.position = data.nodePosition[i]; node.mass = data.nodeMass[i]; nodes[i] = node; } links = new TxLinkHandle[data.linkCount]; for (int i = 0; i < data.linkCount; ++i) { TxLinkHandle link = TxLinkHandle.CreateInstance(); link.index = i; link.node0 = data.linkNodes[i * 2 + 0]; link.node1 = data.linkNodes[i * 2 + 1]; link.name = string.Format("L({0},{1})", link.node0, link.node1); link.stiffness = data.linkStiffness[i]; link.damping = data.linkDamping[i]; link.elastic = data.linkElastic[i]; link.breaking = data.linkBreaking[i]; link.stretching = data.linkStretching.Length > 0 ? data.linkStretching[i] : 1.0f; link.resist = (TxLinkHandle.Resist)(data.linkFlags[i] & 0x3); links[i] = link; } faces = new TxFaceHandle[data.faceCount]; for (int i = 0; i < data.faceCount; ++i) { TxFaceHandle face = TxFaceHandle.CreateInstance(); face.index = i; face.node0 = data.faceNodes[i * 3 + 0]; face.node1 = data.faceNodes[i * 3 + 1]; face.node2 = data.faceNodes[i * 3 + 2]; face.name = string.Format("F({0},{1},{2})", face.node0, face.node1, face.node2); face.collision = (data.faceFlags[i] & (1 << 0)) != 0; face.skinning = (data.faceFlags[i] & (1 << 1)) != 0; face.matter = data.faceMatter.Length > 0 ? data.faceMatter[i] : 0; face.envelope = data.faceEnvelope[i]; faces[i] = face; } }
void UpdateHandles() { TxTruss data = trussData; if (data == null) { return; } data.nodeCount = nodes.Length; foreach (TxNodeHandle n in nodes) { data.nodePosition[n.index] = n.position; data.nodeMass[n.index] = n.mass; } data.linkCount = links.Length; foreach (TxLinkHandle l in links) { data.linkNodes[l.index * 2 + 0] = l.node0; data.linkNodes[l.index * 2 + 1] = l.node1; data.linkLength[l.index] = Vector3.Distance(data.nodePosition[l.node0], data.nodePosition[l.node1]); data.linkStiffness[l.index] = l.stiffness; data.linkDamping[l.index] = l.damping; data.linkElastic[l.index] = l.elastic; data.linkBreaking[l.index] = l.breaking; data.linkStretching[l.index] = l.stretching; data.linkFlags[l.index] = (int)l.resist; } data.faceCount = faces.Length; foreach (TxFaceHandle f in faces) { data.faceNodes[f.index * 3 + 0] = f.node0; data.faceNodes[f.index * 3 + 1] = f.node1; data.faceNodes[f.index * 3 + 2] = f.node2; data.faceFlags[f.index] = (f.collision ? (1 << 0) : 0) | (f.skinning ? (1 << 1) : 0); data.faceMatter[f.index] = f.matter; data.faceEnvelope[f.index] = f.envelope; } }
void OnSceneGUI() { Color yellow = new Color(1.0f, 0.5f, 0.0f); Color green = new Color(0.0f, 0.5f, 0.0f); Color blue = new Color(0.0f, 0.5f, 1.0f); Color red = new Color(0.5f, 0.0f, 0.0f); float size = 0.1f; foreach (TxConstraint constraint in m_targets) { if (!constraint.enabled || constraint.isBroken) { continue; } TxSoftBody bodyA = constraint.attachedBody; TxTruss trussA = bodyA.truss; if (trussA == null) { continue; } if (constraint.enableMotor) { int[] motorAxis = trussA.FindNodeSet(constraint.motorAxis); if (motorAxis != null && motorAxis.Length == 2) { Vector3 axis0 = bodyA.nodePosition[motorAxis[0]]; Vector3 axis1 = bodyA.nodePosition[motorAxis[1]]; Handles.color = red; Handles.DrawLine(axis0, axis1); } } if (constraint.baseBody is TxSoftBody) { Handles.color = yellow; TxSoftBody bodyB = constraint.baseBody as TxSoftBody; TxTruss trussB = bodyB.truss; if (trussB == null) { continue; } TxConstraint.Snap[] snaps = constraint.snaps; foreach (var s in snaps) { if (!s.show) { continue; } int[] indicesA = trussA.FindNodeSet(s.node); if (indicesA != null && indicesA.Length == 1) { Vector3 positionA = bodyA.nodePosition[indicesA[0]]; int[] indicesB = trussB.FindNodeSet(s.featureB); if (indicesB != null) { switch (s.type) { case TxConstraint.SnapType.Node: if (indicesB.Length == 1) { Matrix4x4 matrixB = bodyB.transform.localToWorldMatrix; Vector3 positionB = bodyB.nodePosition[indicesB[0]]; if (Vector3.Distance(positionA, positionB) > 0.001f) { Handles.color = yellow; size = HandleUtility.GetHandleSize(positionA) * 0.08f; Handles.SphereCap(-1, positionA, Quaternion.identity, size); Handles.color = blue; size = HandleUtility.GetHandleSize(positionB) * 0.08f; Handles.SphereCap(-1, positionB, Quaternion.identity, size); Handles.color = green; Handles.DrawLine(positionA, positionB); } else { Handles.color = green; size = HandleUtility.GetHandleSize(positionA) * 0.08f; Handles.SphereCap(-1, positionA, Quaternion.identity, size); } if (s.maxLimit > 0.001f) { if (s.minLimit < s.maxLimit - 0.001f) { Handles.color = blue; Handles.DrawWireDisc(positionB, matrixB.GetColumn(0), s.minLimit); Handles.DrawWireDisc(positionB, matrixB.GetColumn(1), s.minLimit); Handles.DrawWireDisc(positionB, matrixB.GetColumn(2), s.minLimit); Handles.color = yellow; Handles.DrawWireDisc(positionB, matrixB.GetColumn(0), s.maxLimit); Handles.DrawWireDisc(positionB, matrixB.GetColumn(1), s.maxLimit); Handles.DrawWireDisc(positionB, matrixB.GetColumn(2), s.maxLimit); } else { Handles.color = green; Handles.DrawWireDisc(positionB, matrixB.GetColumn(0), s.maxLimit); Handles.DrawWireDisc(positionB, matrixB.GetColumn(1), s.maxLimit); Handles.DrawWireDisc(positionB, matrixB.GetColumn(2), s.maxLimit); } } } break; case TxConstraint.SnapType.Edge: if (indicesB.Length == 2) { Vector3 positionB0 = bodyB.nodePosition[indicesB[0]]; Vector3 positionB1 = bodyB.nodePosition[indicesB[1]]; Handles.color = blue; size = HandleUtility.GetHandleSize(positionB0) * 0.08f; Handles.SphereCap(-1, positionB0, Quaternion.identity, size); size = HandleUtility.GetHandleSize(positionB1) * 0.08f; Handles.SphereCap(-1, positionB1, Quaternion.identity, size); Handles.DrawLine(positionB0, positionB1); Vector3 positionB = positionB0 + (positionB1 - positionB0) * Vector3.Dot(positionB1 - positionB0, positionA - positionB0) / (positionB1 - positionB0).sqrMagnitude; if (Vector3.Distance(positionA, positionB) > 0.001f) { Handles.color = yellow; size = HandleUtility.GetHandleSize(positionA) * 0.08f; Handles.SphereCap(-1, positionA, Quaternion.identity, size); Handles.color = blue; size = HandleUtility.GetHandleSize(positionB) * 0.08f; Handles.SphereCap(-1, positionB, Quaternion.identity, size); Handles.color = green; Handles.DrawLine(positionA, positionB); } else { Handles.color = green; size = HandleUtility.GetHandleSize(positionA) * 0.08f; Handles.SphereCap(-1, positionA, Quaternion.identity, size); } if (s.maxLimit > 0.001f) { Vector3 normal = (positionB1 - positionB0).normalized; if (s.minLimit < s.maxLimit - 0.001f) { Handles.color = blue; Handles.DrawWireDisc(positionB0, normal, s.minLimit); Handles.DrawWireDisc((positionB0 + positionB1) * 0.5f, normal, s.minLimit); Handles.DrawWireDisc(positionB1, normal, s.minLimit); Handles.color = yellow; Handles.DrawWireDisc(positionB0, normal, s.maxLimit); Handles.DrawWireDisc((positionB0 + positionB1) * 0.5f, normal, s.maxLimit); Handles.DrawWireDisc(positionB1, normal, s.maxLimit); } else { Handles.color = green; Handles.DrawWireDisc(positionB0, normal, s.maxLimit); Handles.DrawWireDisc((positionB0 + positionB1) * 0.5f, normal, s.maxLimit); Handles.DrawWireDisc(positionB1, normal, s.maxLimit); } } } break; } } } } } else { TxBody bodyB = constraint.baseBody; Matrix4x4 matrixA = Application.isPlaying ? constraint.startMatrix : bodyB ? bodyB.transform.worldToLocalMatrix * bodyA.transform.localToWorldMatrix : bodyA.transform.localToWorldMatrix; Matrix4x4 matrixB = bodyB ? bodyB.transform.localToWorldMatrix : Matrix4x4.identity; TxConstraint.Snap[] snaps = constraint.snaps; foreach (var s in snaps) { if (!s.show) { continue; } int[] indices = trussA.FindNodeSet(s.node); if (indices != null) { foreach (var i in indices) { if (s.maxLimit > 0.001f) { Vector3 positionA = bodyA.nodePosition[i]; Vector3 positionB = matrixB.MultiplyPoint(matrixA.MultiplyPoint(trussA.nodePosition[i])); if (Vector3.Distance(positionA, positionB) > 0.001f) { Handles.color = yellow; size = HandleUtility.GetHandleSize(positionA) * 0.08f; Handles.SphereCap(-1, positionA, Quaternion.identity, size); Handles.color = blue; size = HandleUtility.GetHandleSize(positionB) * 0.08f; Handles.SphereCap(-1, positionB, Quaternion.identity, size); } else { Handles.color = green; size = HandleUtility.GetHandleSize(positionA) * 0.08f; Handles.SphereCap(-1, positionA, Quaternion.identity, size); } Handles.color = green; Handles.DrawWireDisc(positionB, matrixB.GetColumn(0), s.maxLimit); Handles.DrawWireDisc(positionB, matrixB.GetColumn(1), s.maxLimit); Handles.DrawWireDisc(positionB, matrixB.GetColumn(2), s.maxLimit); } else { Vector3 position = matrixB.MultiplyPoint(matrixA.MultiplyPoint(trussA.nodePosition[i])); Handles.color = green; size = HandleUtility.GetHandleSize(position) * 0.08f; Handles.SphereCap(-1, position, Quaternion.identity, size); } } } } } } Handles.color = Color.white; }
public override void OnInspectorGUI() { serializedObject.Update(); TxEditor.LookLikeControls(); bool isPlaying = Application.isPlaying; TxTrussDesigner trussDesigner = m_targets[0].GetComponent <TxTrussDesigner>(); GUI.enabled = (trussDesigner == null && !Application.isPlaying) && !isPlaying; EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(truss); GUI.enabled = (truss.objectReferenceValue != null && !Application.isPlaying); if (GUILayout.Button("Edit", (trussDesigner != null) ? TxEditor.MiniPressedStyle() : TxEditor.MiniUnpressedStyle(), GUILayout.MaxWidth(40))) { if (trussDesigner) { EditorApplication.delayCall += () => Undo.DestroyObjectImmediate(trussDesigner); } else { Undo.AddComponent <TxTrussDesigner>(m_targets[0].gameObject); } } EditorGUILayout.EndHorizontal(); GUI.enabled = true; EditorGUILayout.PropertyField(massScale); if (truss.objectReferenceValue == null || truss.hasMultipleDifferentValues || massScale.hasMultipleDifferentValues) { GUI.enabled = false; EditorGUILayout.TextField("Scaled Mass", "-"); } else { TxTruss trussAsset = truss.objectReferenceValue as TxTruss; if (trussAsset != null) { float scaledMass = 0; foreach (var m in trussAsset.nodeMass) { scaledMass += m; } GUI.enabled = false; EditorGUILayout.FloatField("Scaled Mass", scaledMass * massScale.floatValue); } } GUI.enabled = true && !isPlaying; EditorGUILayout.PropertyField(collision); EditorGUI.indentLevel++; GUI.enabled = collision.boolValue && !isPlaying; EditorGUILayout.PropertyField(margin); EditorGUILayout.PropertyField(matters, true); EditorGUI.indentLevel--; BodyGroupUI(); GUI.enabled = true && !isPlaying; EditorGUILayout.PropertyField(skinning); GUI.enabled = true && !isPlaying; SpawnEnabledUI(); EditorGUI.indentLevel++; EditorGUILayout.PropertyField(spawnActive); EditorGUI.indentLevel--; GUI.enabled = true; EditorGUILayout.PropertyField(deactivation); EditorGUI.indentLevel++; GUI.enabled = deactivation.boolValue; EditorGUILayout.PropertyField(deactivationSpeed, new GUIContent("Speed")); EditorGUILayout.PropertyField(deactivationTime, new GUIContent("Time")); EditorGUI.indentLevel--; GUI.enabled = true; EditorGUILayout.PropertyField(filling); EditorGUI.indentLevel++; GUI.enabled = filling.boolValue; EditorGUILayout.PropertyField(internalPressure); EditorGUILayout.PropertyField(adiabaticIndex); EditorGUI.indentLevel--; if (GUI.changed) { serializedObject.ApplyModifiedProperties(); } }