// TODO we could just use this to level the final objects rather than the horror-story ray casts. // public float terrainHeight; //to get relative object height (since all of the terrain data is 0-1). //TODO: maybe move it to HeightData in "Height in meters" task // TODO we could limit the perframe activities mid-spawn // public int objsPerIteration = 500; public void Apply(Terrain terrain) { // unless there is no spline data if (splines == null || splines.Count == 0 || splines[0].lines.Length == 0) { return; } // By this point this should absolutely exist - int totalNumberOfListsOfSplineMeshSplines = splines.Count; // There is nothing in the list if (totalNumberOfListsOfSplineMeshSplines == 0) { return; } List <GameObject> thingsToActivate = new List <GameObject>(); Coord data_area_cood = terrain.transform.parent.localPosition.ToCoord() * 0.001f; Coord locality = TownGlobalObject.GetIndexAtCoord(data_area_cood); // SplinePowerExtended var DynamicHolder = TownHolder.Instance.MapMagicObjectReference.transform.Find(string.Format("Tile {0},{1}", data_area_cood.x, data_area_cood.z)); // Create splines holder var splineHolder = new GameObject { name = "SPLINE_FOR_" + string.Format("Tile_{0},{1}", data_area_cood.x, data_area_cood.z) }; splineHolder.transform.parent = DynamicHolder; splineHolder.transform.localPosition = new Vector3(); Coord tilecoord = splineHolder.transform.parent.GetComponent <TerrainTile>().coord; // We walk over the nodes assuming pairs? for (int i = 0; i < totalNumberOfListsOfSplineMeshSplines; i++) { SplineSys spline = splines[i]; var myarray = new List <SplineMesh.SplineNode>(); // No splines for us... if (spline.NodesCount == 0) { continue; } var global = new List <SplineNode>(); var positionalFactor = 1f; myarray = new List <SplineNode>(); SplineNode refnode = new SplineNode(Vector3.positiveInfinity, Vector3.positiveInfinity); SplineNode startnode = refnode; SplineNode endnode = refnode; Segment lastSegment = new Segment(); Segment thissegment = new Segment(); lastSegment.end.pos = thissegment.start.pos = Vector3.positiveInfinity; foreach (var road in spline.lines.Reverse()) { if (!splines[i].mergeSegments) { myarray = new List <SplineNode>(); } foreach (var current in road.segments) { // We need to check if the last segments end connects to the next segments start or RenderOutSplinesSoFar; thissegment = road.segments.Where(x => x.GetHashCode() == current.GetHashCode()).First(); thissegment.start.pos -= DynamicHolder.transform.localPosition; thissegment.end.pos -= DynamicHolder.transform.localPosition; if (splines[i].mergeSegments) { // Render out the segments if they are far apart (square root of 200) - have some data get parsed - and have been selected for merging if (Vector3.SqrMagnitude(lastSegment.end.pos - thissegment.start.pos) > 200f && myarray.Count > 1) { RenderOutSplinesSoFar(splineHolder, i, myarray); myarray = new List <SplineNode>(); } } lastSegment = thissegment; // setup bool fence for list. // add start if we didnt. bool startExists = global.Exists(element => element.Position == thissegment.start.pos * positionalFactor); if (!startExists) { startnode = new SplineMesh.SplineNode(thissegment.start.pos * positionalFactor, thissegment.start.pos * positionalFactor); myarray.Add(startnode); global.Add(startnode); } // and add end if we didnt. bool endExists = global.Exists(element => element.Position == thissegment.end.pos * positionalFactor); if (!endExists) { endnode = new SplineMesh.SplineNode(thissegment.end.pos * positionalFactor, thissegment.end.pos * positionalFactor); myarray.Add(endnode); global.Add(endnode); } } if (myarray.Count == 0) { continue; } if (myarray.Count == 1) { // give us two by hook or crook if (myarray.Contains(startnode)) { endnode = new SplineMesh.SplineNode(lastSegment.end.pos * positionalFactor, lastSegment.end.pos * positionalFactor); myarray.Add(endnode); } else { startnode = new SplineMesh.SplineNode(lastSegment.start.pos * positionalFactor, lastSegment.start.pos * positionalFactor); myarray.Add(startnode); } continue; } if ((myarray[1].Position - myarray[0].Position).sqrMagnitude == 0) { continue; } // Render out as just segment node pairs if (!splines[i].mergeSegments) { RenderOutSplinesSoFar(splineHolder, i, myarray); } } // Attempt to merge near pairs if (splines[i].mergeSegments) { RenderOutSplinesSoFar(splineHolder, i, myarray); } } }
void OnSceneGUI() { Event e = Event.current; if (e.type == EventType.MouseDown) { Undo.RegisterCompleteObjectUndo(spline, "change spline topography"); // if alt key pressed, we will have to create a new node if node position is changed if (e.alt) { mustCreateNewNode = true; } } if (e.type == EventType.MouseUp) { mustCreateNewNode = false; } // disable game object transform gyzmo if (Selection.activeGameObject == spline.gameObject) { Tools.current = Tool.None; if (selection == null && spline.nodes.Count > 0) { selection = spline.nodes[0]; } } // draw a bezier curve for each curve in the spline foreach (CubicBezierCurve curve in spline.GetCurves()) { Handles.DrawBezier(spline.transform.TransformPoint(curve.n1.Position), spline.transform.TransformPoint(curve.n2.Position), spline.transform.TransformPoint(curve.n1.Direction), spline.transform.TransformPoint(curve.GetInverseDirection()), CURVE_COLOR, null, 3); } // draw the selection handles switch (selectionType) { case SelectionType.Node: // place a handle on the node and manage position change Vector3 newPosition = spline.transform.InverseTransformPoint(Handles.PositionHandle(spline.transform.TransformPoint(selection.Position), Quaternion.identity)); if (newPosition != selection.Position) { // position handle has been moved if (mustCreateNewNode) { mustCreateNewNode = false; selection = AddClonedNode(selection); selection.Direction += newPosition - selection.Position; selection.Position = newPosition; } else { selection.Direction += newPosition - selection.Position; selection.Position = newPosition; } } break; case SelectionType.Direction: var result = Handles.PositionHandle(spline.transform.TransformPoint(selection.Direction), Quaternion.identity); selection.Direction = spline.transform.InverseTransformPoint(result); break; case SelectionType.InverseDirection: result = Handles.PositionHandle(2 * spline.transform.TransformPoint(selection.Position) - spline.transform.TransformPoint(selection.Direction), Quaternion.identity); selection.Direction = 2 * selection.Position - spline.transform.InverseTransformPoint(result); break; case SelectionType.Up: result = Handles.PositionHandle(spline.transform.TransformPoint(selection.Position + selection.Up), Quaternion.LookRotation(selection.Direction - selection.Position)); selection.Up = (spline.transform.InverseTransformPoint(result) - selection.Position).normalized; break; } // draw the handles of all nodes, and manage selection motion Handles.BeginGUI(); foreach (SplineNode n in spline.nodes) { var dir = spline.transform.TransformPoint(n.Direction); var pos = spline.transform.TransformPoint(n.Position); var invDir = spline.transform.TransformPoint(2 * n.Position - n.Direction); var up = spline.transform.TransformPoint(n.Position + n.Up); // first we check if at least one thing is in the camera field of view if (!(CameraUtility.IsOnScreen(pos) || CameraUtility.IsOnScreen(dir) || CameraUtility.IsOnScreen(invDir) || (showUpVector && CameraUtility.IsOnScreen(up)))) { continue; } Vector3 guiPos = HandleUtility.WorldToGUIPoint(pos); if (n == selection) { Vector3 guiDir = HandleUtility.WorldToGUIPoint(dir); Vector3 guiInvDir = HandleUtility.WorldToGUIPoint(invDir); Vector3 guiUp = HandleUtility.WorldToGUIPoint(up); // for the selected node, we also draw a line and place two buttons for directions Handles.color = Color.red; Handles.DrawLine(guiDir, guiInvDir); // draw quads direction and inverse direction if they are not selected if (selectionType != SelectionType.Node) { if (Button(guiPos, directionButtonStyle)) { selectionType = SelectionType.Node; } } if (selectionType != SelectionType.Direction) { if (Button(guiDir, directionButtonStyle)) { selectionType = SelectionType.Direction; } } if (selectionType != SelectionType.InverseDirection) { if (Button(guiInvDir, directionButtonStyle)) { selectionType = SelectionType.InverseDirection; } } if (showUpVector) { Handles.color = Color.green; Handles.DrawLine(guiPos, guiUp); if (selectionType != SelectionType.Up) { if (Button(guiUp, upButtonStyle)) { selectionType = SelectionType.Up; } } } } else { if (Button(guiPos, nodeButtonStyle)) { selection = n; selectionType = SelectionType.Node; } } } Handles.EndGUI(); if (GUI.changed) { EditorUtility.SetDirty(target); } }
private void drawNodeData(SerializedProperty nodeProperty, SplineNode node) { using (var check = new EditorGUI.ChangeCheckScope()) { var positionProp = nodeProperty.FindPropertyRelative("position"); EditorGUILayout.PropertyField(positionProp, new GUIContent("Position")); if (check.changed) { node.Position = positionProp.vector3Value; } } using (var check = new EditorGUI.ChangeCheckScope()) { var directionTypeProp = nodeProperty.FindPropertyRelative("directionType"); EditorGUILayout.PropertyField(directionTypeProp, new GUIContent("Direction Type")); if (check.changed) { node.DirectionType = (SplineNode.TangentType)directionTypeProp.enumValueIndex; } } // hidden, to use DirectionIn and DirectionOut //using (var check = new EditorGUI.ChangeCheckScope()) //{ // var directionProp = nodeProperty.FindPropertyRelative("direction"); // EditorGUILayout.PropertyField(directionProp, new GUIContent("Direction")); // if (check.changed) // { // node.Direction = directionProp.vector3Value; // } //} if (true || node.directionType != SplineNode.TangentType.Mirrored) { using (var check = new EditorGUI.ChangeCheckScope()) { var directionInProp = nodeProperty.FindPropertyRelative("directionIn"); EditorGUILayout.PropertyField(directionInProp, new GUIContent("DirectionIn")); if (check.changed) { node.DirectionIn = directionInProp.vector3Value; } } } using (var check = new EditorGUI.ChangeCheckScope()) { var directionOutProp = nodeProperty.FindPropertyRelative("directionOut"); EditorGUILayout.PropertyField(directionOutProp, new GUIContent("DirectionOut")); if (check.changed) { node.DirectionOut = directionOutProp.vector3Value; } } using (var check = new EditorGUI.ChangeCheckScope()) { var upProp = nodeProperty.FindPropertyRelative("up"); EditorGUILayout.PropertyField(upProp, new GUIContent("Up")); if (check.changed) { node.Up = upProp.vector3Value; } } using (var check = new EditorGUI.ChangeCheckScope()) { var scaleProp = nodeProperty.FindPropertyRelative("scale"); EditorGUILayout.PropertyField(scaleProp, new GUIContent("Scale")); if (check.changed) { node.Scale = scaleProp.vector2Value; } } using (var check = new EditorGUI.ChangeCheckScope()) { var rollProp = nodeProperty.FindPropertyRelative("roll"); EditorGUILayout.PropertyField(rollProp, new GUIContent("Roll")); if (check.changed) { node.Roll = rollProp.floatValue; } } }
public override void OnInspectorGUI() { serializedObject.Update(); // hint EditorGUILayout.HelpBox("Hold Alt and drag a node to create a new one.", MessageType.Info); // add button if (selection == null) { GUI.enabled = false; } if (GUILayout.Button("Add node after selected")) { Undo.RecordObject(spline, "add spline node"); SplineNode newNode = new SplineNode(selection.Direction, selection.Direction + selection.Direction - selection.Position); var index = spline.nodes.IndexOf(selection); if (index == spline.nodes.Count - 1) { spline.AddNode(newNode); } else { spline.InsertNode(index + 1, newNode); } selection = newNode; serializedObject.Update(); } GUI.enabled = true; // delete button if (selection == null || spline.nodes.Count <= 2) { GUI.enabled = false; } if (GUILayout.Button("Delete selected node")) { Undo.RecordObject(spline, "delete spline node"); spline.RemoveNode(selection); selection = null; serializedObject.Update(); } GUI.enabled = true; showUpVector = GUILayout.Toggle(showUpVector, "Show up vector"); spline.IsLoop = GUILayout.Toggle(spline.IsLoop, "Is loop (experimental)"); // nodes EditorGUILayout.PropertyField(nodesProp); EditorGUI.indentLevel++; if (nodesProp.isExpanded) { for (int i = 0; i < nodesProp.arraySize; i++) { SerializedProperty nodeProp = nodesProp.GetArrayElementAtIndex(i); EditorGUILayout.PropertyField(nodeProp); EditorGUI.indentLevel++; if (nodeProp.isExpanded) { drawNodeData(nodeProp, spline.nodes[i]); } EditorGUI.indentLevel--; } } EditorGUI.indentLevel--; if (selection != null) { int index = spline.nodes.IndexOf(selection); SerializedProperty nodeProp = nodesProp.GetArrayElementAtIndex(index); EditorGUILayout.LabelField("Selected node (node " + index + ")"); EditorGUI.indentLevel++; drawNodeData(nodeProp, selection); EditorGUI.indentLevel--; } else { EditorGUILayout.LabelField("No selected node"); } serializedObject.ApplyModifiedProperties(); }
void OnSceneGUI() { if (e.type == EventType.MouseDown) { Undo.RegisterCompleteObjectUndo(spline, "change spline topography"); // if alt key pressed, we will have to create a new node if node position is changed if (e.alt) { mustCreateNewNode = true; } } if (e.type == EventType.MouseUp) { mustCreateNewNode = false; } // disable game object transform gizmo if (Selection.activeGameObject == spline.gameObject) { if (isEditingSpline == true) { Tools.current = Tool.None; } else { Selection.SetActiveObjectWithContext(spline.gameObject, spline); Tools.current = Tool.Move; } if (selection == null && spline.nodes.Count > 0) { selection = spline.nodes[0]; } } if (isEditingSpline == true) { // draw the selection handles // place a handle on the node and manage position change float HandleSizeMult = 0.1f; var HandlePos = Vector3.zero; var HandleSize = 0.0f; Color defaultColor = Handles.color; Vector3 sceneCamPos = SceneView.currentDrawingSceneView.camera.transform.position; Vector3 newPosition; Vector3 discNormal = sceneCamPos - spline.transform.TransformPoint(selection.Position); if (selectionType == SelectionType.Node) { HandlePos = spline.transform.TransformPoint(selection.Position); HandleSize = HandleUtility.GetHandleSize(HandlePos) * HandleSizeMult; newPosition = spline.transform.InverseTransformPoint(Handles.PositionHandle(HandlePos, Quaternion.identity)); if (newPosition != selection.Position) { // position handle has been moved if (mustCreateNewNode) { mustCreateNewNode = false; selection = AddClonedNode(selection); selection.Direction += newPosition - selection.Position; selection.Position = newPosition; } else { selection.Direction += newPosition - selection.Position; selection.Position = newPosition; } } } Handles.color = new Color(1.0f, .65f, .26f, 1.0f); HandlePos = spline.transform.TransformPoint(selection.Direction); HandleSize = HandleUtility.GetHandleSize(HandlePos) * HandleSizeMult; var Dirresult = Handles.FreeMoveHandle(HandlePos, Quaternion.identity, HandleSize, Vector3.zero, Handles.RectangleHandleCap); if (e.type == EventType.Repaint) { Handles.DrawSolidDisc(HandlePos, discNormal, HandleSize); } selection.Direction = spline.transform.InverseTransformPoint(Dirresult); HandlePos = 2 * spline.transform.TransformPoint(selection.Position) - spline.transform.TransformPoint(selection.Direction); HandleSize = HandleUtility.GetHandleSize(HandlePos) * HandleSizeMult; var Invresult = Handles.FreeMoveHandle(HandlePos, Quaternion.identity, HandleSize, Vector3.zero, Handles.RectangleHandleCap); if (e.type == EventType.Repaint) { Handles.DrawSolidDisc(HandlePos, discNormal, HandleSize); } selection.Direction = 2 * selection.Position - spline.transform.InverseTransformPoint(Invresult); if (showUpVector) { Handles.color = new Color(0.15f, 0.87f, 0.24f, 1f); HandlePos = spline.transform.TransformPoint(selection.Position + selection.Up); HandleSize = HandleUtility.GetHandleSize(HandlePos) * HandleSizeMult; if (e.type == EventType.Repaint) { Handles.DrawSolidDisc(HandlePos, discNormal, HandleSize); } if (selectionType == SelectionType.Up) { var Upresult = Handles.FreeMoveHandle(HandlePos, Quaternion.LookRotation(selection.Direction - selection.Position), HandleSize, Vector3.zero, Handles.RectangleHandleCap); selection.Up = (spline.transform.InverseTransformPoint(Upresult) - selection.Position).normalized; } } // draw the handles of all nodes, and manage selection motion Handles.BeginGUI(); foreach (SplineNode n in spline.nodes) { var dir = spline.transform.TransformPoint(n.Direction); var pos = spline.transform.TransformPoint(n.Position); var invDir = spline.transform.TransformPoint(2 * n.Position - n.Direction); var up = spline.transform.TransformPoint(n.Position + n.Up); // first we check if at least one thing is in the camera field of view if (!(CameraUtility.IsOnScreen(pos) || CameraUtility.IsOnScreen(dir) || CameraUtility.IsOnScreen(invDir) || (showUpVector && CameraUtility.IsOnScreen(up)))) { continue; } Vector3 guiPos = HandleUtility.WorldToGUIPoint(pos); Color defaultCol = GUI.color; if (n == selection) { Vector3 guiDir = HandleUtility.WorldToGUIPoint(dir); Vector3 guiInvDir = HandleUtility.WorldToGUIPoint(invDir); Vector3 guiUp = HandleUtility.WorldToGUIPoint(up); // for the selected node, we also draw a line and place two buttons for directions Handles.color = Color.red; //Handles.DrawLine(guiDir, guiInvDir); Handles.DrawBezier( guiDir, guiInvDir, guiDir, guiInvDir, Color.red, null, 3 ); if (showUpVector) { Handles.color = Color.green; Handles.DrawLine(guiPos, guiUp); if (selectionType != SelectionType.Up) { if (Button(guiUp, upButtonStyle)) { selectionType = SelectionType.Up; } } } } // GUI.color = CURVE_BUTTON_COLOR; GUI.backgroundColor = new Color(75f / 255f, 200f / 255f, 245 / 255f, 1.0f); if (Button(guiPos, nodeButtonStyle)) { selection = n; selectionType = SelectionType.Node; } GUI.backgroundColor = Color.white; } } Handles.EndGUI(); // Don't allow clicking over empty space to deselect the object if (isEditingSpline == true) { if (e.type == EventType.Layout) { HandleUtility.AddDefaultControl(0); } } if (GUI.changed) { EditorUtility.SetDirty(target); } }