/// <summary> /// Step the machine. /// Set machine speed to zero and use this method for interactive use. /// It's framerate independent. /// </summary> /// <param name='speed'> /// Speed in degrees per second. /// </param> public void Step(float speed) { step += Time.deltaTime * speed * (Reverse ? -1.0f : 1.0f); //FIXME: individual gear rotated > 360 reset at 0: not through step: if powered gear is smaller than other gear in same machine: larger gear gets out of sync as it has not completed its turn yet. PoweredGear.SetRotation(step); PoweredGear._currentSpeed = speed; // Avoiding recursion through use of a queue instead of the internal stack which is slow and limited. //gearUpdateQueue.Clear(); gearUpdateQueue.Enqueue(PoweredGear); while (gearUpdateQueue.Count > 0) { GFGear parent = gearUpdateQueue.Dequeue(); if (parent != null) { for (int i = 0; i < parent.childrenAsArray.Length; i++) { GFGear child = parent.childrenAsArray[i]; child._currentSpeed = parent.currentSpeed * child.speedMultiplier; child.SetRotation(parent.angle * child.speedMultiplier); gearUpdateQueue.Enqueue(child); } } } }
private void CloneTowardsMousePos(GFGear gear, Vector2 mousePos) { Vector3 mousewpos = GetMouseInWorldCoords(MeshUtils.CalcYAlignedCenterPlane(gear.gameObject), mousePos); Vector3 direction = mousewpos - gear.gameObject.transform.position; direction.Normalize(); CloneGear(gear, direction); }
private void CloneGear(GFGear gear, Vector3 direction) { GameObject newGearGO = gear.Clone(direction); // Mark new gear as dirty UnityEditor.EditorUtility.SetDirty(newGearGO); // Set focus on new gear Selection.activeGameObject = newGearGO; }
void OnEnable() { gearGenObject = (GFGearGen)this.target; lastGearGenObjectMesh = gearGenObject.gameObject.GetComponent <MeshFilter>().sharedMesh; gearGen = new SerializedObject(this.target); gearGenProps = new Dictionary <string, SerializedProperty>(); AddGearGenProperty("numberOfTeeth"); AddGearGenProperty("radius"); AddGearGenProperty("innerRadius"); AddGearGenProperty("innerMinVertexDistance"); AddGearGenProperty("thickness"); AddGearGenProperty("fillCenter"); AddGearGenProperty("fillOutside"); AddGearGenProperty("is3d"); AddGearGenProperty("alignTeethWithParent"); AddGearGenProperty("alignRadiusWithParent"); AddGearGenProperty("twistAngle"); AddGearGenProperty("twistOutside"); AddGearGenProperty("innerTeeth"); AddGearGenProperty("tipLength"); AddGearGenProperty("tipSize"); AddGearGenProperty("valleySize"); AddGearGenProperty("valleyAngleOffset"); AddGearGenProperty("tipAngleOffset"); AddGearGenProperty("skew"); AddGearGenProperty("showNormals"); AddGearGenProperty("splitVerticesAngle"); AddGearGenProperty("generateTextureCoordinates"); AddGearGenProperty("uvTiling"); AddGearGenProperty("uvOffset"); GFGear c = (GFGear)gearGenObject.gameObject.GetComponent(typeof(GFGear)); if (c != null) { gear = new SerializedObject(c); gearProps = new Dictionary <string, SerializedProperty>(); AddGearProperty("numberOfTeeth"); } else { gear = null; } // innerTeethInitialState = gearGenObject.innerTeeth; //Persist(); Undo.undoRedoPerformed = UndoCallback; }
/// <summary> /// Gets the gears driven by currentGear. /// </summary> /// <returns> /// The gears. /// </returns> /// <param name='currentGear'> /// Current gear. /// </param> public GFGear[] GetGears(GFGear currentGear) { List <GFGear> go = new List <GFGear>(); for (int i = 0; i < this.transform.childCount; i++) { GFGear foundGear = this.transform.GetChild(i).gameObject.GetComponent <GFGear>(); if (foundGear != null && (currentGear == null || !foundGear.gameObject.Equals(currentGear.gameObject))) { go.Add(foundGear); } } return(go.ToArray()); }
void AddGears() { if (numberOfInstances < 1) { numberOfInstances = 1; } if (numberOfInstances > 1) { GFGear gear = null; int seqLen = 0; int repeat = 0; int n = 0; Vector3 dir; for (int i = 0; i < numberOfInstances - 1; i += seqLen) { if (repeat == 1) { repeat = 0; seqLen++; } else { repeat++; } for (int g = 0; g < seqLen; g++) { if (instances.Count == numberOfInstances - 1) { i = 0; break; } gear = instances.Count > 0 ? instances[instances.Count - 1] : gearToTest; dir = Quaternion.AngleAxis(90f * n, Vector3.back) * Vector3.right; GFGear newGear = gear.Clone(dir).GetComponent <GFGear>(); instances.Add(newGear); } n++; if (n >= 4) { n = 0; } } machine.RecalculateGears(); } }
/// <summary> /// Clone a gear and place the duplicate version aligned. /// </summary> /// <param name="direction">Direction at which to align it to</param> /// <returns>The cloned gear as gameobject</returns> public GameObject Clone(Vector3 direction) { GFGear gear = this; GFGearGen gearGen = (GFGearGen)this.gameObject.GetComponent(typeof(GFGearGen)); float d; if (gearGen != null) { d = gearGen.radius + (gearGen.radius - gearGen.tipLength); } else { d = (gear.GetRadius() * 2.1f) - gear.toothSize; } GameObject newGearGO = (GameObject)Instantiate(gear.gameObject); newGearGO.transform.parent = gear.gameObject.transform.parent; GFGear newGear = newGearGO.GetComponent(typeof(GFGear)) as GFGear; newGear.DrivenBy = gear; newGear.AutoSetDrivenBy = false; GFGearGen newGearGen = newGear.GetComponent <GFGearGen>(); if (newGearGen != null) { newGearGen.alignTeethWithParent = true; newGearGen.alignRadiusWithParent = true; } newGearGO.transform.position = gear.transform.position + (direction.normalized * d); // Get number that is not followed by any other number string re = @"(\d+)(?!.*\d)"; Match m = Regex.Match(gear.gameObject.name, re); int nmbr = 1; // Add one to the last number (if exists) if (m != null && m.Value != null && m.Value != "" && gear.DrivenBy != null) { nmbr = int.Parse(m.Value) + 1; } // Rename object to sequentially numbered object newGearGO.name = Regex.Replace(gear.gameObject.name, re, "").Trim() + " " + nmbr.ToString(); newGearGen.Align(gearGen); return(newGearGO); }
/// <summary> /// Rotates g1 and g2 with point of collission of front facing center planes as pivot point. /// Calculates scalar products to determine if normals are in opposite direction of eachother and returns false if that's the case. /// </summary> /// <param name='g1'> /// Gear 1 /// </param> /// <param name='g2'> /// Gear 2 /// </param> /// <returns>True if normals align after rotation around point of collision of planes.</returns> private bool Opposing(GFGear g1, GFGear g2) { if (AutoReverseOnReversedOrientation) { Vector3 c1 = g1.transform.position; Vector3 c2 = g2.transform.position; // Calculate planes through center Plane p1 = g1.gameObject.CalcYAlignedCenterPlane(Space.World); Plane p2 = g2.gameObject.CalcYAlignedCenterPlane(Space.World); // Calculate g1.center --> point of nearest collision of the two planes (c1) --> g2.center //Vector3 point = Vector3.zero; //Vector3 direction = Vector3.zero; //MathUtils.PlanePlaneIntersection(out point, out direction, p1, p2, c1, c2); // If parallel planes ? skip pivot rotation // if (direction != Vector3.zero) // { // Calculate triangle: Center (c1) -> Center translated by normal -> Plane intersection point (point) Plane t1 = new Plane(c1, c1 + p1.normal, c2); // Calculate triangle: Center (c2) -> Center translated by normal -> Plane intersection point (point) Plane t2 = new Plane(c2, c2 + p2.normal, c1); /* * Debug.DrawLine(c1, c1+p1.normal, Color.green, 3, false); * Debug.DrawLine(c1+p1.normal, c2, Color.green, 3, false); * Debug.DrawLine(c2, c1, Color.green, 3, false); * Debug.DrawLine(c1, c1+t1.normal, Color.blue, 3, false); * * Debug.DrawLine(c2, c2+p2.normal, Color.magenta, 3, false); * Debug.DrawLine(c2+p2.normal, c1, Color.magenta, 3, false); * Debug.DrawLine(c1, c2, Color.magenta, 3, false); * Debug.DrawLine(c2, c2+t2.normal, Color.cyan, 3, false); */ // Calculate normals of those triangles: directions must be opposite return(t1.normal == t2.normal); /* * } * else * { * // Parallel planes but facing the same sides: return true * return p1.normal == p2.normal; * }*/ } return(false); }
// Update is called once per frame void Update() { if (Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { GFGear gear = hit.transform.GetComponent <GFGear>(); if (gear != null) { gear.SetSpeed(gearSpeed); } } } }
static public void DrawAlignmentHelpers(this GFGear gear1) { if (gear1.AutoAlign) { #if UNITY_EDITOR Color c = Color.green; c.a = 0.2f; Handles.color = c; Handles.DrawSolidDisc(gear1.transform.position, gear1.gameObject.CalcYAlignedCenterPlane().normal, gear1.radius - (gear1.innerTeeth ? 0f : gear1.tipLength)); c.a = 1f; Handles.color = c; Vector3 startP = Vector3.zero; Vector3 endP = Vector3.zero; for (int i = 0; i < gear1.numberOfTeeth; i++) { float angleRad = ((2 * Mathf.PI) / gear1.numberOfTeeth) * i; endP.x = Mathf.Cos(angleRad); endP.y = Mathf.Sin(angleRad); endP.z = 0f; startP = endP * (gear1.radius - gear1.tipLength); endP = endP * gear1.radius; startP = gear1.transform.TransformPoint(startP); endP = gear1.transform.TransformPoint(endP); Handles.DrawAAPolyLine(10f, new Vector3[] { startP, endP }); } /* * Quaternion q = new Quaternion(); * Vector3 v = gear1.DrivenBy.transform.position - gear1.transform.position; * if (v != Vector3.zero) * { * q = Quaternion.LookRotation(v); * Handles.DrawLine(gear1.transform.position, gear1.DrivenBy.transform.position); * Vector3 conePos = gear1.transform.position + ((gear1.DrivenBy.transform.position - gear1.transform.position) / 2.0f); * Handles.ConeCap(0, conePos, q, HandleUtility.GetHandleSize(conePos) / 4.0f); * } */ #endif } }
static public void DrawPoweredBy(this GFGear gear1) { if (gear1.DrivenBy != null) { #if UNITY_EDITOR Handles.color = Color.yellow; Quaternion q = new Quaternion(); Vector3 v = gear1.DrivenBy.transform.position - gear1.transform.position; if (v != Vector3.zero) { q = Quaternion.LookRotation(v); Handles.DrawLine(gear1.transform.position, gear1.DrivenBy.transform.position); Vector3 conePos = gear1.transform.position + ((gear1.DrivenBy.transform.position - gear1.transform.position) / 2.0f); Handles.ConeHandleCap(0, conePos, q, HandleUtility.GetHandleSize(conePos) / 4.0f, EventType.Repaint); } #else Debug.DrawLine(gear1.transform.position, gear1.DrivenBy.transform.position, Color.yellow, 3, false); #endif } }
static void Create() { GameObject gameObject = new GameObject("Gear"); GFGear g = (GFGear)gameObject.AddComponent(typeof(GFGear)); GFGearGen gg = (GFGearGen)gameObject.AddComponent(typeof(GFGearGen)); MeshFilter meshFilter = (MeshFilter)gameObject.GetComponent(typeof(MeshFilter)); meshFilter.mesh = new Mesh(); gg.Rebuild(); gameObject.GetComponent <Renderer>().material = new Material(Shader.Find("Diffuse")); if (g.DrivenBy == null) { gg.alignTeethWithParent = false; gg.alignRadiusWithParent = false; } GFGearGenEditor.Persist(gg); }
/// <summary> /// Inverse the parent hierarchy to become children of the powered gear. /// </summary> private void RebuildHierarchy() { if (PoweredGear != null) { List <GFGear> gearsToInverse = new List <GFGear>(); GFGear parentToInv = PoweredGear; while (parentToInv != null && !gearsToInverse.Contains(parentToInv)) { gearsToInverse.Add(parentToInv); parentToInv = parentToInv.DrivenBy; } for (int i = gearsToInverse.Count - 1; i > 0; i--) { gearsToInverse[i].AutoSetDrivenBy = false; gearsToInverse[i].DrivenBy = gearsToInverse[i - 1]; } PoweredGear.AutoSetDrivenBy = false; PoweredGear.DrivenBy = null; } }
void OnEnable() { gearObject = (GFGear)this.target; gear = new SerializedObject(this.target); gearNumberOfTeeth = gear.FindProperty("numberOfTeeth"); gearRotateX = gear.FindProperty("rotateX"); gearRotateY = gear.FindProperty("rotateY"); gearRotateZ = gear.FindProperty("rotateZ"); gearAutoAlign = gear.FindProperty("AutoAlign"); gearRadius = gear.FindProperty("radius"); gearTipLength = gear.FindProperty("tipLength"); gearInnerTeeth = gear.FindProperty("innerTeeth"); gearDrivenBy = gear.FindProperty("DrivenBy"); gearAutoSetDrivenBy = gear.FindProperty("AutoSetDrivenBy"); gearReverseRotation = gear.FindProperty("ReverseRotation"); gearReverseRotationPlusSubtree = gear.FindProperty("ReverseRotationPlusSubtree"); gearSyncSpeed = gear.FindProperty("SyncSpeed"); GFGearGen c = (GFGearGen)gearObject.gameObject.GetComponent(typeof(GFGearGen)); hasGFGearGen = c != null; }
/// <summary> /// Set machine speed to match a gear speed. /// </summary> /// <param name="gear">Adapt speed to this gear.</param> /// <param name="gearSpeed">Desired new speed of the given gear in degrees per second.</param> public void SetSpeedByGear(GFGear gear, float gearSpeed) { speed = gearSpeed / gear.machineRatio; }
private void RebuildTurnDirections(GFGear poweredBy, bool ccw, float speedMultiplier, float globalMultiplier = 1f) { if (!history.Contains(poweredBy)) { history.Add(poweredBy); poweredBy.CCW = ccw; poweredBy.speedMultiplier = speedMultiplier; poweredBy._machineRatio = globalMultiplier; //if (poweredBy == null) // poweredBy._machineRatio = 1f; foreach (GFGear g in gears) { // Iterate through gears and clean up empty children int i = 0; while (i < g.children.Count) { if (g.children[i] == null) { g.children.RemoveAt(i); } else { i++; } } // Find our gear in the gears collection if (g.DrivenBy == poweredBy) { bool newccw = ccw; if (!poweredBy.children.Contains(g)) { poweredBy.children.Add(g); } // If g is to the left of the gear: turn the otherside around so we don't have to flip it manually // we construct a plane through the center of the gear and determine if the center position of the other gear is on the backside of it if (Opposing(g, poweredBy) || (poweredBy.gearGen != null && poweredBy.gearGen.innerTeeth) || (g.gearGen != null && g.gearGen.innerTeeth)) { newccw = !ccw; } //calculate new speedMultiplier: compare g with poweredBy number of teeth (much more accurate then radius): if (!g.SyncSpeed) { speedMultiplier = GetGearRatio(poweredBy, g); //_machineRatio = poweredBy._machineRatio * g.speedMultiplier; } else { speedMultiplier = 1.0f; } if (poweredBy.ReverseRotationPlusSubtree) { g.ReverseRotation = true; newccw = !newccw; #if UNITY_EDITOR // Tell the unity editor we changed something by code, so it gets saved. UnityEditor.EditorUtility.SetDirty(g); #endif } RebuildTurnDirections(g, !newccw, speedMultiplier, globalMultiplier * speedMultiplier); if (g.ReverseRotation && !g.ReverseRotationPlusSubtree) { g.CCW = !g.CCW; } } } } /* * gearUpdateQueue.Clear(); * * poweredBy.CCW = ccw; * poweredBy.speedMultiplier = speedMultiplier; * gearUpdateQueue.Enqueue(poweredBy); * history.Clear(); * while (gearUpdateQueue.Count > 0) * { * GFGear parent = gearUpdateQueue.Dequeue(); * if (parent != null){ * if (!history.Contains(parent)) * { * history.Add(parent); * * foreach(GFGear g in gears) * { * if (g.DrivenBy == parent) * { * bool newccw = ccw; * * if (!parent.Children.Contains(g)) * parent.Children.Add(g); * * // If g is to the left of the gear: turn the otherside around so we don't have to flip it manually * // we construct a plane through the center of the gear and determine if the center position of the other gear is on the backside of it * if (Opposing(g, parent)) * newccw = !ccw; * * //calculate new speedMultiplier: compare g with poweredBy number of teeth (much more accurate then radius): * if (!g.SyncSpeed) * { * speedMultiplier = GetGearRatio(parent, g); * } * * if (g.ReverseRotationPlusSubtree) * { * newccw = !newccw; * if (!g.ReverseRotation) * { * g.ReverseRotation = true; * // Tell the unity editor we changed something by code, so it gets saved. * UnityEditor.EditorUtility.SetDirty(g); * } * } * * // RebuildTurnDirections(g, !newccw, speedMultiplier); * g.CCW = !newccw; * g.speedMultiplier = speedMultiplier; * * gearUpdateQueue.Enqueue(g); * } * } * } * } * } * * foreach (GFGear g in history){ * if (g.ReverseRotation && !g.ReverseRotationPlusSubtree) * { * g.CCW = !g.CCW; * } * }*/ }
private float GetGearRatio(GFGear gear1, GFGear gear2) { return((float)gear1.numberOfTeeth / (float)gear2.numberOfTeeth); //gear1.radius / gear2.radius; }
public bool Intersects(GFGear otherGear) { MeshUtils.IntersectType it = MeshUtils.Intersect(MeshUtils.CalcOrientedBoundingBox(this.gameObject), MeshUtils.CalcOrientedBoundingBox(otherGear.gameObject)); return(it == MeshUtils.IntersectType.Intersect || it == MeshUtils.IntersectType.Inside); }
// Use this for initialization void Start() { distributionObject = this.gameObject; vectors = new List <Vector3>(); normals = new List <Vector3>(); //normals = new List<Vector3>(); gears = new List <GFGearGen>(); if (distributionObject != null && gearEntity != null) { MeshFilter m = (MeshFilter)distributionObject.GetComponent(typeof(MeshFilter)); if (m != null) { followNormals = followNormals && m.mesh.normals.Length == m.mesh.vertices.Length && m.mesh.normals.Length > 0; // Walk through faces for (int i = 0; i < m.mesh.triangles.Length; i += 3) { int[] triangle = new int[] { m.mesh.triangles[i], m.mesh.triangles[i + 1], m.mesh.triangles[i + 2] }; // For every face, get the three vertices // Get the longest distance between two vertices float d01 = Vector3.Distance(m.mesh.vertices[triangle[0]], m.mesh.vertices[triangle[1]]); float d12 = Vector3.Distance(m.mesh.vertices[triangle[1]], m.mesh.vertices[triangle[2]]); float d20 = Vector3.Distance(m.mesh.vertices[triangle[2]], m.mesh.vertices[triangle[0]]); int idxFrom = 2; int idxTo = 0; // float dist;// = d20; if (d01 > d12 && d01 > d20) { idxFrom = 0; idxTo = 1; // dist = d01; } else { if (d12 > d01 && d12 > d20) { idxFrom = 1; idxTo = 2; // dist = d12; } } // Face normal Vector3 n = Vector3.zero; if (followNormals) { Vector3 n1 = m.mesh.normals[triangle[1]]; Vector3 n2 = m.mesh.normals[triangle[2]]; Vector3 n3 = m.mesh.normals[triangle[0]]; n = (n1 + n2 + n3) / 3.0f; n.Normalize(); } // Get center of line segment Vector3 center = Vector3.Lerp(m.mesh.vertices[triangle[idxFrom]], m.mesh.vertices[triangle[idxTo]], 0.5f); // If center isn't already occupied: add vector if (!vectors.Contains(center)) { vectors.Add(center); if (followNormals) { normals.Add(n); } // normals.Add(center.normalized); } } // Walk through vectors and instantiate a gear GFGearGen gg; for (int i = 0; i < vectors.Count; i++) { Vector3 v = /*distributionObject.transform.localToWorldMatrix * */ vectors[i]; // + m.transform.position;// m.mesh.vertices[i]; Quaternion lr = Quaternion.LookRotation(followNormals ? normals[i] : v.normalized); if (i == 0) { //gearEntity.gameObject.active = false; gearEntity.transform.position = v; //distributionObject.transform.TransformPoint(v); gearEntity.transform.rotation = lr; gearEntity.transform.localRotation.eulerAngles.Set(0.0f, 0.0f, 0.0f); gg = gearEntity; } else { gg = (GFGearGen)Instantiate(gearEntity); //, /*distributionObject.transform.TransformPoint(v)*/v, Quaternion.LookRotation(v.normalized)); gg.transform.parent = gearEntity.transform.parent; gg.transform.position = v; gg.transform.rotation = lr; if (gg.gear != null) { GFGear prevgear = gears[i - 1].gear; if (prevgear != null) { gg.gear.DrivenBy = prevgear; } } } gears.Add(gg); } GFGear gear = gearEntity.gear; // (GFGear)gearEntity.gameObject.GetComponent(typeof(GFGear)); if (gear != null) { if (gear.machine != null) { gear.machine.RecalculateGears(); } } #region Combine meshes to reduce draw calls if (combineMeshes) { //transform.position = distributionObject.transform.position; //transform.rotation = distributionObject.transform.rotation; List <CombineInstance> cmb = new List <CombineInstance>(); for (int i = 0; i < gears.Count; i++) { MeshFilter mf = gears[i].gameObject.GetComponent <MeshFilter>(); if (mf != null) { CombineInstance ci = new CombineInstance(); ci.mesh = mf.sharedMesh; ci.transform = mf.transform.localToWorldMatrix; mf.gameObject.SetActive(false); cmb.Add(ci); } } MeshFilter currentMf = transform.GetComponent <MeshFilter>(); currentMf.SetMesh(new Mesh()); currentMf.sharedMesh.CombineMeshes(cmb.ToArray()); MeshRenderer currentMr = transform.GetComponent <MeshRenderer>(); if (currentMr == null) { currentMr = (MeshRenderer)transform.gameObject.AddComponent(typeof(MeshRenderer)); } transform.gameObject.SetActive(true); } #endregion m.GetComponent <Renderer>().enabled = !hideEmitter; } } }
void OnSceneGUI() { Rect guiArea = new Rect(10, 10, 110, 150); GFGear gear = (GFGear)this.target; if (!Application.isPlaying) { if (UnityEditor.Selection.Contains(gear.gameObject)) { RecalculateGears(gear); GFGearGen gearGen = gear.gameObject.GetComponent <GFGearGen>(); // Show powered by arrow if (gear.machine == null || (gear.machine != null && gear.machine.ShowPoweredByIndicator)) { gear.DrawPoweredBy(); } if (gearGen == null && gear.AutoAlign) { gear.DrawAlignmentHelpers(); } //GUI.enabled = (gear.DrivenBy != null && (gear.machine == null || (gear.machine != null && gear.machine.ShowPoweredByIndicator))); //Handles.color = Color.white; //Handles.DrawLine(gear.transform.position, GetMouseInWorldCoords(MeshUtils.CalcYAlignedCenterPlane(gear.gameObject), Event.current.mousePosition)); #region GUI.enabled then this is visible. // Note: Not drawing this part is not an option as it will destroy your focus on selected element even if it's visible as being focused. //if (GUI.enabled && gear.machine != null && gear.machine.ShowBox) // gear.DrivenBy.gameObject.DrawBoundingBox(Color.yellow); // Draw unlink button Handles.BeginGUI(); GUILayout.BeginArea(guiArea); if (!isInAddGearMode) { if (gear.DrivenBy != null) { GUIContent gcontent = new GUIContent("Unlink", "Manually override linkage.\r\n- Sets \"Driven By\" to: null\n- Sets \"Auto Set Driven By\" to: false"); if (GUILayout.Button(gcontent)) { gear.DrivenBy = null; gear.AutoSetDrivenBy = false; UnityEditor.EditorUtility.SetDirty(gear); } GUI.enabled = true; if (gearGen != null) { #region auto alignment string label = ""; string hint = ""; bool autoAlign = false; if (gearGen.alignTeethWithParent || gearGen.alignRadiusWithParent) { autoAlign = false; label = "Move freely"; hint = "Switch off auto-alignment.\r\n- Sets \"Align Teeth With Parent\" to: false\r\n- Sets \"Align Radius With Parent\" to: false\r\n"; } else { autoAlign = true; label = "Snap to parent"; hint = "Switches on auto-alignment.\r\n- Sets \"Align Teeth With Parent\" to: true\r\n- Sets \"Align Radius With Parent\" to: true\r\n"; } GUIContent gcontent2 = new GUIContent(label, hint); if (GUILayout.Button(gcontent2)) { gearGen.alignTeethWithParent = autoAlign; gearGen.alignRadiusWithParent = autoAlign; UnityEditor.EditorUtility.SetDirty(gearGen); } #endregion } else { #region auto alignment if (gear.DrivenBy != null) { string label = ""; string hint = ""; if (gear.AutoAlign) { label = "Move freely"; hint = "Switch off auto-alignment.\r\n"; } else { label = "Snap to parent"; hint = "Switches on auto-alignment.\r\n"; } GUIContent gcontent3 = new GUIContent(label, hint); if (GUILayout.Button(gcontent3)) { gear.AutoAlign = !gear.AutoAlign; UnityEditor.EditorUtility.SetDirty(gear); } } #endregion } } if (gearGen != null) { GUIContent gnewgear = new GUIContent("Add single", "Adds a new gear that's linked\r\nto last selected gear.");//GFGearEditor.isInAddGearMode ? "Done" : "Link new gear", "Adds a new gear that's linked to selected gear."); if (GUILayout.Button(gnewgear)) { CloneGear(gear, Vector3.right); } GUIContent gnewgearMulti = new GUIContent("Add multiple", "Add multiple gears.\r\nClick in your scene to specify direction.\r\nRight click when finished."); if (GUILayout.Button(gnewgearMulti)) { isInAddGearMode = true; } GUIContent grandomgear = new GUIContent("Randomize", "Rebuilds current gear with\r\ndifferent randomized settings.");//GFGearEditor.isInAddGearMode ? "Done" : "Link new gear", "Adds a new gear that's linked to selected gear."); if (GUILayout.Button(grandomgear)) { gearGen.Randomize(); } } } else { GUIContent gnewgearMulti = new GUIContent("Done", "Finish adding multiple gears.\r\n"); if (GUILayout.Button(gnewgearMulti)) { cancelAddGearMode = true; } } GUILayout.EndArea(); //GUI.Label(new Rect(Screen.width - 250, Screen.height - 70 - 150, 250, 100), GUI.tooltip); Handles.EndGUI(); #endregion if (gear.machine != null && gear.machine.PoweredGear == gear) { Handles.Label(gear.transform.position + ((gear.radius * 1.30f) * Vector3.up) + (gear.radius * Vector3.left), "Machine powered (Speed:" + gear.machine.speed.ToString() + ")"); } } if (isInAddGearMode || cancelAddGearMode) { if (cancelAddGearMode || Event.current.type != EventType.MouseUp || (Event.current.type == EventType.MouseUp && !guiArea.Contains(Event.current.mousePosition))) { if (Event.current.type == EventType.MouseUp || cancelAddGearMode) { if (Event.current.button == 0 && !cancelAddGearMode) { CloneTowardsMousePos(gear, Event.current.mousePosition); } else { cancelAddGearMode = false; CancelAddGearMode(); } } int controlID = GUIUtility.GetControlID(FocusType.Passive); if (Event.current.type == EventType.Layout) { HandleUtility.AddDefaultControl(controlID); } } } } }
public void RecalculateGears(GFGear g1) { GFGear prevDrivenBy = g1.DrivenBy; if (g1.AutoSetDrivenBy) { g1.DrivenBy = null; } foreach (GFGear otherGear in g1.otherGears) { if (!otherGear.gameObject.Equals(g1.gameObject) && ((g1.AutoSetDrivenBy && g1.Intersects(otherGear)) || !g1.AutoSetDrivenBy)) { // Set initial rotation if (g1.machine == null || (g1.machine != null && g1.machine.PoweredGear != g1)) { if (g1.AutoSetDrivenBy && g1.DrivenBy != otherGear) { // If redundant / circular reference is occuring: restore previous link and abort if (otherGear.DrivenBy == g1) { g1.DrivenBy = prevDrivenBy; } else { g1.DrivenBy = otherGear; } } if (g1.DrivenBy != null) { // If gear is auto generated, we can align the teeth GFGearGen gg1 = g1.GetComponent(typeof(GFGearGen)) as GFGearGen; GFGearGen gg2 = g1.DrivenBy.GetComponent(typeof(GFGearGen)) as GFGearGen; if (gg1 != null && gg2 != null) { if (gg1.alignTeethWithParent) { gg1.Align(gg2); } else { if (gg1.alignRadiusWithParent) { gg1.AlignRadius(gg2); } } } else { // If gear is not auto generated, we can align the positions if autoAlign is true. if (gearAutoAlign.boolValue) { g1.Align(g1.DrivenBy); } } } } // Tell the unity editor we changed something by code, so it gets saved. UnityEditor.EditorUtility.SetDirty(g1); // All aligned and set: get the hell out of this loop! break; } } }