public void Remap(SplineNode node, SplineFormer toFormer) { RemoveNodeImmediately(node); toFormer.Nodes.Add(node); node.SplineFormer = toFormer; InvalidateMesh(); toFormer.InvalidateMesh(); }
/// <summary> /// Refreshs the node. /// </summary> public void RefreshNode() { Clean(); if (SplineFormer == null) { return; } RecalculateBasicValues(); RecalculateLocalPosition(); if (_lastPostion != LocalPosition) { SplineFormer.InvalidateMesh(); } _lastPostion = LocalPosition; }
public override void OnInspectorGUI() { GetSplineFormer(); DrawHeaderTexture(); bool needRebuildMesh = false; bool needAddNode = false; Color defaultBackColor = GUI.backgroundColor; Color defaultColor = GUI.color; EditorGUILayout.LabelField("Lofting Groups"); var groups = _splineFormer.LoftingGroups.ToList(); EditorGUILayout.BeginVertical(); EditorGUI.DrawRect(EditorGUILayout.GetControlRect(GUILayout.Height(2)), _separatorsColor); EditorGUI.indentLevel++; foreach (var group in groups) { GUI.backgroundColor = group.IsValid ? _valid : _invalid; int groupIndex = groups.IndexOf(group); if (groupIndex != 0) { EditorGUI.DrawRect(EditorGUILayout.GetControlRect(GUILayout.Height(1)), _separatorsColor); } EditorGUILayout.LabelField( String.Format("#{0} - {1}", groupIndex, group.IsValid ? "Ready" : "Not ready") ); EditorGUI.BeginChangeCheck(); //====================== EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Segment Mesh", GUILayout.MinWidth(_fieldWidth)); EditorGUILayout.LabelField("MeshFilter", GUILayout.MinWidth(_fieldWidth)); EditorGUILayout.LabelField("MeshCollider", GUILayout.MinWidth(_fieldWidth)); EditorGUILayout.EndHorizontal(); EditorGUI.BeginChangeCheck(); EditorGUILayout.BeginHorizontal(); group.SegmentMesh = (Mesh)EditorGUILayout.ObjectField(group.SegmentMesh, typeof(Mesh), false, GUILayout.MinWidth(_fieldWidth)); group.MeshFilter = EditorGUILayout.ObjectField(group.MeshFilter, typeof(MeshFilter), true, GUILayout.MinWidth(_fieldWidth)) as MeshFilter; group.MeshCollider = EditorGUILayout.ObjectField(group.MeshCollider, typeof(MeshCollider), true, GUILayout.MinWidth(_fieldWidth)) as MeshCollider; EditorGUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { if (group.MeshFilter != null) { group.MeshFilter.sharedMesh = null; } if (group.MeshCollider != null) { group.MeshCollider.sharedMesh = null; } } EditorGUILayout.LabelField("Interval"); group.StartPosition = EditorGUILayout.Slider("Start Position", group.StartPosition, 0f, 1f); group.EndPosition = EditorGUILayout.Slider("End Position", group.EndPosition, 0f, 1f); //=========================== if (FoldoutOption("Caps", group)) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Start Piece"); group.StartPiece = (Mesh)EditorGUILayout.ObjectField(group.StartPiece, typeof(Mesh), false, GUILayout.MinWidth(_fieldWidth * 2)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("End Piece"); group.EndPiece = (Mesh)EditorGUILayout.ObjectField(group.EndPiece, typeof(Mesh), true, GUILayout.MinWidth(_fieldWidth * 2)); EditorGUILayout.EndHorizontal(); } //==================== if (FoldoutOption("Processing", group)) { group.ProcessOriginNormals = EditorGUILayout.ToggleLeft("Process Origin Normals", group.ProcessOriginNormals); if (group.ProcessOriginNormals) { group.RecalculateNormals = false; group.SmoothNormals = false; } group.ProcessOriginTangents = EditorGUILayout.ToggleLeft("Process Origin Tangents", group.ProcessOriginTangents); group.Weld = EditorGUILayout.ToggleLeft("Weld Close Vertices", group.Weld); float value = Mathf.Sqrt(group.WeldingDistance * 10f); value = EditorGUILayout.Slider("Welding Distance", value, 0.01f, 2f); group.WeldingDistance = (value * value) * 0.1f; group.RecalculateNormals = EditorGUILayout.ToggleLeft("Recalculate Normals", group.RecalculateNormals); if (!group.RecalculateNormals) { group.SmoothNormals = false; } if (group.RecalculateNormals) { group.ProcessOriginNormals = false; } group.SmoothNormals = EditorGUILayout.ToggleLeft("Smooth Normals", group.SmoothNormals); if (group.SmoothNormals) { group.RecalculateNormals = true; group.ProcessOriginNormals = false; } } //==================== if (EditorGUI.EndChangeCheck()) { needRebuildMesh = true; } //================ GUI.backgroundColor = defaultBackColor; EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Remove", GUILayout.Width(_buttonWidth))) { RecordUndo(); _splineFormer.LoftingGroups.Remove(group); } EditorGUILayout.Space(); EditorGUI.BeginDisabledGroup(group.ResultMesh == null); string filename = "-"; if (group.ResultMesh != null) { filename = group.ResultMesh.name; } if (GUILayout.Button("Save to OBJ", GUILayout.Width(_buttonWidth))) { Exporter.MeshToObjFile(group.ResultMesh, filename, _splineFormer.ExportOptions); } if (GUILayout.Button("Save to Asset", GUILayout.Width(_buttonWidth))) { Exporter.MeshToAsset(group.ResultMesh, filename, _splineFormer.ExportOptions); } EditorGUI.EndDisabledGroup(); EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); } EditorGUI.indentLevel--; EditorGUI.DrawRect(EditorGUILayout.GetControlRect(GUILayout.Height(2)), _separatorsColor); EditorGUILayout.EndVertical(); GUI.backgroundColor = defaultBackColor; GUI.color = defaultColor; if (GUILayout.Button("Add Group", GUILayout.Width(_buttonWidth))) { RecordUndo(); _splineFormer.LoftingGroups.Add(new SplineFormer.LoftingGroup()); } EditorGUI.BeginChangeCheck(); _splineFormer.SegmentsNumber = Mathf.Max(1, EditorGUILayout.IntField("Segments Count", _splineFormer.SegmentsNumber)); _splineFormer.Coefficient = Mathf.Max(0.01f, EditorGUILayout.FloatField("Coefficient", _splineFormer.Coefficient)); _splineFormer.LoftAngle = EditorGUILayout.Slider("Loft Angle", _splineFormer.LoftAngle, 0f, 360f); _splineFormer.LoftDirection = EditorGUILayout.Vector3Field("Loft Direction", _splineFormer.LoftDirection); if (_splineFormer.LoftDirection.sqrMagnitude < 0.1f) { _splineFormer.LoftDirection = Vector3.forward; } _splineFormer.SegmentScale = EditorGUILayout.Vector3Field("Segment Scale", _splineFormer.SegmentScale); _splineFormer.QuadraticSmooth = EditorGUILayout.Toggle("Quadratic Smooth", _splineFormer.QuadraticSmooth); var loop = EditorGUILayout.Toggle("Loop", _splineFormer.Loop); _splineFormer.RollerCoasterFix = EditorGUILayout.Toggle("Roller Coaster Fix", _splineFormer.RollerCoasterFix); EditorGUILayout.Separator(); if (EditorGUI.EndChangeCheck()) { needRebuildMesh = true; RecordDeepUndo(); if (_splineFormer.Loop != loop) { Undo.RecordObject(_splineFormer.StartNode.transform, "StartNode move"); Undo.RecordObject(_splineFormer.EndNode.transform, "EndNode move"); _splineFormer.Loop = loop; } } EditorGUILayout.Separator(); _showVisualOptions = EditorGUILayout.Foldout(_showVisualOptions, "Visual Options"); if (_showVisualOptions) { EditorGUI.BeginChangeCheck(); _splineFormer.VisualOptions.NodeSize = Mathf.Max(0.001f, EditorGUILayout.FloatField("Node Size", _splineFormer.VisualOptions.NodeSize)); _splineFormer.VisualOptions.ShowNodeLinks = EditorGUILayout.Toggle("Show Node Links", _splineFormer.VisualOptions.ShowNodeLinks); _splineFormer.VisualOptions.ShowSegmentsPath = EditorGUILayout.Toggle("Show Segments Path", _splineFormer.VisualOptions.ShowSegmentsPath); _splineFormer.VisualOptions.ShowTangentNodes = EditorGUILayout.Toggle("Show Tangent Nodes", _splineFormer.VisualOptions.ShowTangentNodes); _splineFormer.VisualOptions.ShowTangents = EditorGUILayout.Toggle("Show Tangents", _splineFormer.VisualOptions.ShowTangents); if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(target); } } _showExportOptions = EditorGUILayout.Foldout(_showExportOptions, "Export Options"); if (_showExportOptions) { EditorGUI.BeginChangeCheck(); _splineFormer.ExportOptions.ShowSaveAsDialog = EditorGUILayout.Toggle("Show \"Save As\" Dialog", _splineFormer.ExportOptions.ShowSaveAsDialog); _splineFormer.ExportOptions.ShowExportResultDialog = EditorGUILayout.Toggle("Show Export Result Dialog", _splineFormer.ExportOptions.ShowExportResultDialog); EditorGUILayout.BeginHorizontal(); var assetsFolder = Path.GetFullPath("Assets/").Replace('\\', '/'); EditorGUILayout.LabelField("Default Export Folder", _splineFormer.ExportOptions.DefaultFolder); if (GUILayout.Button("Select")) { var defaultFolder = _splineFormer.ExportOptions.DefaultFolder; if (!Directory.Exists(defaultFolder)) { defaultFolder = assetsFolder; } var selectedFolder = EditorUtility.SaveFolderPanel("Default Export Folder", defaultFolder, "Splines"); if (!selectedFolder.Contains(assetsFolder)) { EditorUtility.DisplayDialog( "Path is outside the assets folder", String.Format("Asset can't be saved outside of the folder \"{0}\"", assetsFolder), "OK"); } else { _splineFormer.ExportOptions.DefaultFolder = selectedFolder.Replace(assetsFolder, ""); } } EditorGUILayout.EndHorizontal(); _splineFormer.ExportOptions.ExtendedNaming = EditorGUILayout.Toggle("Extended Naming", _splineFormer.ExportOptions.ExtendedNaming); if (_splineFormer.ExportOptions.ExtendedNaming) { EditorGUI.indentLevel++; _splineFormer.ExportOptions.AddObjectName = EditorGUILayout.Toggle("Add Object Name", _splineFormer.ExportOptions.AddObjectName); _splineFormer.ExportOptions.AddLoftingGroupIndex = EditorGUILayout.Toggle("Add Lofting Group Index", _splineFormer.ExportOptions.AddLoftingGroupIndex); _splineFormer.ExportOptions.CustomName = EditorGUILayout.TextField("Custom Name", _splineFormer.ExportOptions.CustomName); _splineFormer.ExportOptions.AddDateTime = EditorGUILayout.Toggle("Add Date/Time Stamp", _splineFormer.ExportOptions.AddDateTime); _splineFormer.ExportOptions.AddAutoIncrementNumber = EditorGUILayout.Toggle("Add Auto Increment Number", _splineFormer.ExportOptions.AddAutoIncrementNumber); EditorGUI.indentLevel--; } if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(target); } } EditorGUILayout.BeginHorizontal(); needAddNode |= GUILayout.Button("Add Node", GUILayout.Width(_buttonWidth)); needRebuildMesh |= GUILayout.Button("Refresh", GUILayout.Width(_buttonWidth)); EditorGUILayout.EndHorizontal(); if (needAddNode) { _splineFormer.AddNewNode(); } if (needRebuildMesh || needAddNode) { _splineFormer.InvalidateMesh(); EditorUtility.SetDirty(target); } }
// Gets new data from Sense public void NewData(string d) { // Remove any existing sankey foreach (Transform child in transform) { GameObject.Destroy(child.gameObject); } transform.rotation = Quaternion.identity; transform.position = new Vector3(0, 0, 0); pathGOs.Clear(); Debug.Log("data: " + d); JSONNode JPaths = JSON.Parse(d); //var pathList = new List<Path>(); var Paths = new Dictionary <int, Dictionary <string, int> >(); var CompletedPaths = new Dictionary <int, float>(); var Groups = new Dictionary <int, Dictionary <string, float> >(); int MaxSteps = 0; for (int i = 0; i < JPaths.AsArray.Count; i++) { // Splice path string p = JPaths[i]; //Debug.Log("path: " + p); string path = p.Substring(1, p.Length - 2); string[] nodes = path.Split(','); if (nodes.Length < 2) { continue; } for (int j = 0; j < nodes.Length; j++) { string n = nodes[j]; //Debug.Log("node: " + n); if (Paths.ContainsKey(j)) { if (Paths[j].ContainsKey(n)) { Paths[j][n]++; } else { Paths[j][n] = 1; } } else { Paths.Add(j, new Dictionary <string, int>()); Paths[j][n] = 1; } MaxSteps = MaxSteps > Paths[j][n] ? MaxSteps : Paths[j][n]; //Original //MaxSteps = MaxSteps > Paths[j][n] ? MaxSteps : Paths[j][n]; MaxSteps = MaxSteps > nodes.Length ? MaxSteps : nodes.Length; Debug.Log("SANKEY MaxSteps: " + MaxSteps); } } for (int i = 0; i < JPaths.AsArray.Count; i++) { string p = JPaths[i]; string path = p.Substring(1, p.Length - 2); string[] nodes = path.Split(','); if (nodes.Length < 2) { continue; } if (nodes.Length < Paths.Count) { Paths[Paths.Count - 1][nodes[nodes.Length - 1]] = 1; } } Debug.Log("Last pos length: " + Paths[Paths.Count - 1].Count); for (int i = 0; i < JPaths.AsArray.Count; i++) { // Splice path string p = JPaths[i]; Debug.Log("path: " + p); string path = p.Substring(1, p.Length - 2); string[] nodes = path.Split(','); if (nodes.Length < 2) { continue; } GameObject go = createSpline(); Vector3 pp = transform.position; // go.transform.position = new Vector3(pp.x, chartHeight / (float)JPaths.AsArray.Count * (float)i, pp.z); go.transform.position = new Vector3(pp.x, pp.y, pp.z); pathGOs.Add(go); // Setup nodes SplineFormer sf = go.GetComponent <SplineFormer>(); for (int j = 0; j < nodes.Length; j++) { string n = nodes[j]; //Debug.Log("node: " + n); // float zStep= chartLength / (nodes.Length-1); float zStep = chartLength / MaxSteps; // float zPos = zStep * (float)j; float zPos; zPos = j < (nodes.Length - 1) ? zStep * (float)j : chartLength; if (j < nodes.Length - 1) { if (CompletedPaths.ContainsKey(j)) { CompletedPaths[j]++; } else { CompletedPaths.Add(j, 1f); } } else { if (CompletedPaths.ContainsKey(Paths[Paths.Count - 1].Count)) { CompletedPaths[Paths[Paths.Count - 1].Count]++; } else { CompletedPaths.Add(Paths[Paths.Count - 1].Count, 1f); } } SplineNode sn = null; if (j > 1) { sn = sf.AddNodeImmediately(); Vector3 f = sn.transform.position; float hOffset; if (j < nodes.Length - 1) { if (Groups.ContainsKey(j)) { if (Groups[j].ContainsKey(n)) { hOffset = Groups[j][n]; } else { Groups[j][n] = chartHeight / (float)(Paths[j].Count + 1) * CompletedPaths[j]; hOffset = Groups[j][n]; } } else { Groups.Add(j, new Dictionary <string, float>()); Groups[j][n] = chartHeight / (float)(Paths[j].Count + 1) * CompletedPaths[j]; hOffset = Groups[j][n]; } } else { //hOffset = chartHeight / (float)(Paths[Paths.Count - 1].Count + 1) * CompletedPaths[Paths[Paths.Count - 1].Count]; if (Groups.ContainsKey(Paths.Count - 1)) { if (Groups[Paths.Count - 1].ContainsKey(n)) { hOffset = Groups[Paths.Count - 1][n]; } else { Groups[Paths.Count - 1][n] = chartHeight / (float)(Paths[Paths.Count - 1].Count + 1) * CompletedPaths[Paths[Paths.Count - 1].Count]; hOffset = Groups[Paths.Count - 1][n]; } } else { Groups.Add(Paths.Count - 1, new Dictionary <string, float>()); Groups[Paths.Count - 1][n] = chartHeight / (float)(Paths[Paths.Count - 1].Count + 1) * CompletedPaths[Paths[Paths.Count - 1].Count]; hOffset = Groups[Paths.Count - 1][n]; } } f = f + Vector3.up * hOffset; sn.transform.position = new Vector3(f.x, f.y, zPos); } else if (j == 1) { sn = sf.Nodes[j]; Vector3 f = sn.transform.position; float hOffset; if (j < nodes.Length - 1) { //Debug.Log("Path count: " + Paths[j][n]); if (Paths[j][n] > 1) { if (Groups.ContainsKey(j)) { if (Groups[j].ContainsKey(n)) { hOffset = Groups[j][n]; } else { Groups[j][n] = chartHeight / (float)(Paths[j].Count + 1) * CompletedPaths[j]; hOffset = Groups[j][n]; } } else { Groups.Add(j, new Dictionary <string, float>()); Groups[j][n] = chartHeight / (float)(Paths[j].Count + 1) * CompletedPaths[j]; hOffset = Groups[j][n]; } } else { hOffset = chartHeight / (float)(Paths[j].Count + 1) * CompletedPaths[j]; } } else { //hOffset = chartHeight / (float)(Paths[Paths.Count - 1].Count + 1) * CompletedPaths[Paths[Paths.Count - 1].Count]; if (Groups.ContainsKey(Paths.Count - 1)) { if (Groups[Paths.Count - 1].ContainsKey(n)) { hOffset = Groups[Paths.Count - 1][n]; } else { Groups[Paths.Count - 1][n] = chartHeight / (float)(Paths[Paths.Count - 1].Count + 1) * CompletedPaths[Paths[Paths.Count - 1].Count]; hOffset = Groups[Paths.Count - 1][n]; } } else { Groups.Add(Paths.Count - 1, new Dictionary <string, float>()); Groups[Paths.Count - 1][n] = chartHeight / (float)(Paths[Paths.Count - 1].Count + 1) * CompletedPaths[Paths[Paths.Count - 1].Count]; hOffset = Groups[Paths.Count - 1][n]; } } f = f + Vector3.up * hOffset; sn.transform.position = new Vector3(f.x, f.y, zPos); } else if (j == 0) { sn = sf.Nodes[j]; Vector3 f = sn.transform.position; float yStep = chartHeight / (float)JPaths.AsArray.Count; //// f = f + Vector3.up * -((float)i-1f) * yStep; // f = f + Vector3.up * chartHeight / (float)(Paths[j].Count+1); //Debug.Log("NumNodesAtPos " + j + ": " + Paths[j].Count + " for path " + i + " = " + chartHeight / (float)(Paths[j].Count + 1)); if (Groups.ContainsKey(j)) { if (!Groups[j].ContainsKey(n)) { Groups[j][n] = chartHeight / (float)(Paths[j].Count + 1); } } else { Groups.Add(j, new Dictionary <string, float>()); Groups[j][n] = chartHeight / (float)(Paths[j].Count + 1); } f = f + Vector3.up * Groups[j][n]; sn.transform.position = f; } // Add Sphere Nodes to nodes GameObject spNode = (GameObject)Instantiate(Resources.Load("SankeyNode"), sn.transform.position, sn.transform.rotation); Vector3 vec = new Vector3(0f, 1f, 0f); spNode.transform.Rotate(vec, 180f); spNode.transform.SetParent(sn.transform); float _nodeScaler = Mathf.Lerp(0.1f, 0.2f, Paths[j][n] / MaxSteps); spNode.transform.localScale = new Vector3(_nodeScaler, _nodeScaler, _nodeScaler); // Add Text Labels to nodes GameObject label = spNode.transform.GetChild(0).gameObject; label.transform.RotateAround(sn.transform.position, Vector3.up, 90); GameObject txt = label.transform.GetChild(0).gameObject; txt.GetComponent <UnityEngine.UI.Text>().text = n; // Add Tap Handler SelectMgr hit = spNode.AddComponent <SelectMgr>(); } sf.InvalidateMesh(); } // Move Sankey above patient /*Vector3 pPos = patient.transform.position; * pPos.x -= 0.4f; * pPos.y += 0.8f; * pPos.z -= 0.5f; * gameObject.transform.position = pPos; * Quaternion pRot = patient.transform.rotation; * pRot.y -= Mathf.PI * 0.25f; * gameObject.transform.rotation = pRot; */ ReTag(gameObject.transform, LayerMask.NameToLayer("Sankey")); }
void Update() { splineFormer.LoftAngle = 180 * Mathf.Sin(Time.timeSinceLevelLoad); splineFormer.InvalidateMesh(); }