//  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);
            }
        }
Example #3
0
        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();
        }
Example #5
0
        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);
            }
        }