392 lines
14 KiB
C#
392 lines
14 KiB
C#
namespace Dreamteck.Splines.Editor
|
|
{
|
|
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using System.IO;
|
|
using Dreamteck.Splines.IO;
|
|
|
|
public class ImportExportTool : SplineTool
|
|
{
|
|
private float scaleFactor = 1f;
|
|
private bool alwaysDraw = true;
|
|
private string importPath = "";
|
|
private string exportPath = "";
|
|
List<SplinePoint[]> originalPoints = new List<SplinePoint[]>();
|
|
List<SplineComputer> imported = new List<SplineComputer>();
|
|
List<SplineComputer> exported = new List<SplineComputer>();
|
|
GameObject importedParent = null;
|
|
|
|
enum Mode { None, Import, Export }
|
|
enum ExportFormat { SVG, CSV }
|
|
enum Axis { X, Y, Z }
|
|
|
|
Mode mode = Mode.None;
|
|
ExportFormat format = ExportFormat.SVG;
|
|
Axis importAxis = Axis.Z;
|
|
Axis exportAxis = Axis.Z;
|
|
|
|
bool importOptions = false;
|
|
|
|
List<CSV.ColumnType> exportColumns = new List<CSV.ColumnType>();
|
|
List<CSV.ColumnType> importColumns = new List<CSV.ColumnType>();
|
|
bool flatCSV = false;
|
|
|
|
public override string GetName()
|
|
{
|
|
return "Import/Export";
|
|
}
|
|
|
|
protected override string GetPrefix()
|
|
{
|
|
return "ImportExport";
|
|
}
|
|
|
|
public override void Open(EditorWindow window)
|
|
{
|
|
base.Open(window);
|
|
importPath = LoadString("importPath", "");
|
|
exportPath = LoadString("exportPath", "");
|
|
alwaysDraw = LoadBool("alwaysDraw", true);
|
|
flatCSV = LoadBool("flatCSV", false);
|
|
importAxis = (Axis)LoadInt("importAxis", 2);
|
|
exportAxis = (Axis)LoadInt("exportAxis", 2);
|
|
LoadColumns("importColumns", ref importColumns);
|
|
LoadColumns("exportColumns", ref exportColumns);
|
|
}
|
|
|
|
void LoadColumns(string name, ref List<CSV.ColumnType> destination)
|
|
{
|
|
string text = LoadString(name, "");
|
|
destination = new List<CSV.ColumnType>();
|
|
if (text == "")
|
|
{
|
|
destination.Add(CSV.ColumnType.Position);
|
|
destination.Add(CSV.ColumnType.Tangent);
|
|
destination.Add(CSV.ColumnType.Tangent2);
|
|
destination.Add(CSV.ColumnType.Normal);
|
|
destination.Add(CSV.ColumnType.Size);
|
|
destination.Add(CSV.ColumnType.Color);
|
|
return;
|
|
}
|
|
string[] elements = text.Split(',');
|
|
foreach (string element in elements)
|
|
{
|
|
int i = 0;
|
|
if (int.TryParse(element, out i)) destination.Add((CSV.ColumnType)i);
|
|
}
|
|
}
|
|
|
|
public override void Close()
|
|
{
|
|
base.Close();
|
|
if(importPath != "") SaveString("importPath", Path.GetDirectoryName(importPath));
|
|
if (exportPath != "") SaveString("exportPath", Path.GetDirectoryName(exportPath));
|
|
string columnString = "";
|
|
foreach(CSV.ColumnType col in importColumns)
|
|
{
|
|
if (columnString != "") columnString += ",";
|
|
columnString += ((int)col).ToString();
|
|
}
|
|
SaveString("importColumns", columnString);
|
|
columnString = "";
|
|
foreach (CSV.ColumnType col in exportColumns)
|
|
{
|
|
if (columnString != "") columnString += ",";
|
|
columnString += ((int)col).ToString();
|
|
}
|
|
SaveString("exportColumns", columnString);
|
|
SaveBool("alwaysDraw", alwaysDraw);
|
|
SaveBool("flatCSV", flatCSV);
|
|
SaveInt("importAxis", (int)importAxis);
|
|
SaveInt("exportAxis", (int)exportAxis);
|
|
|
|
#if UNITY_2019_1_OR_NEWER
|
|
SceneView.duringSceneGui -= OnScene;
|
|
#else
|
|
SceneView.onSceneGUIDelegate -= OnScene;
|
|
#endif
|
|
|
|
}
|
|
|
|
protected override void Save()
|
|
{
|
|
base.Save();
|
|
if (importedParent != null)
|
|
{
|
|
Selection.activeGameObject = importedParent;
|
|
importedParent = null;
|
|
} else
|
|
{
|
|
foreach(SplineComputer comp in imported)
|
|
{
|
|
if(comp != null)
|
|
{
|
|
Selection.activeGameObject = comp.gameObject;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
imported.Clear();
|
|
#if UNITY_2019_1_OR_NEWER
|
|
SceneView.duringSceneGui -= OnScene;
|
|
#else
|
|
SceneView.onSceneGUIDelegate -= OnScene;
|
|
#endif
|
|
|
|
mode = Mode.None;
|
|
}
|
|
|
|
protected override void Cancel()
|
|
{
|
|
base.Cancel();
|
|
foreach (SplineComputer spline in imported) GameObject.DestroyImmediate(spline.gameObject);
|
|
GameObject.DestroyImmediate(importedParent);
|
|
imported.Clear();
|
|
SceneView.RepaintAll();
|
|
#if UNITY_2019_1_OR_NEWER
|
|
SceneView.duringSceneGui -= OnScene;
|
|
#else
|
|
SceneView.onSceneGUIDelegate -= OnScene;
|
|
#endif
|
|
|
|
mode = Mode.None;
|
|
}
|
|
|
|
void CSVColumnUI(List<CSV.ColumnType> columns)
|
|
{
|
|
EditorGUILayout.LabelField("Dataset Columns");
|
|
EditorGUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("-", GUILayout.MaxWidth(30)) && columns.Count > 0) columns.RemoveAt(columns.Count - 1);
|
|
for (int i = 0; i < columns.Count; i++)
|
|
{
|
|
columns[i] = (CSV.ColumnType)EditorGUILayout.EnumPopup(columns[i]);
|
|
}
|
|
if (GUILayout.Button("+", GUILayout.MaxWidth(30)) && columns.Count > 0) columns.Add(CSV.ColumnType.Position);
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
void OnScene(SceneView current)
|
|
{
|
|
for (int i = 0; i < imported.Count; i++)
|
|
{
|
|
DSSplineDrawer.DrawSplineComputer(imported[i]);
|
|
}
|
|
}
|
|
|
|
void ImportUI()
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
scaleFactor = EditorGUILayout.FloatField("Scale Factor", scaleFactor);
|
|
importAxis = (Axis)EditorGUILayout.EnumPopup("Facing Axis", importAxis);
|
|
alwaysDraw = EditorGUILayout.Toggle("Always Draw", alwaysDraw);
|
|
if (EditorGUI.EndChangeCheck()) ApplyPoints();
|
|
SaveCancelUI();
|
|
}
|
|
|
|
void ExportUI()
|
|
{
|
|
if(exported.Count == 0)
|
|
{
|
|
mode = Mode.None;
|
|
return;
|
|
}
|
|
EditorGUILayout.Space();
|
|
format = (ExportFormat)EditorGUILayout.EnumPopup("Format", format);
|
|
if (format == ExportFormat.SVG)
|
|
{
|
|
exportAxis = (Axis)EditorGUILayout.EnumPopup("Projection Axis", exportAxis);
|
|
EditorGUILayout.HelpBox("The SVG is a 2D vector format so the exported spline will be flattened along the selected axis", MessageType.Info);
|
|
}
|
|
else
|
|
{
|
|
CSVColumnUI(exportColumns);
|
|
flatCSV = EditorGUILayout.Toggle("Flat", flatCSV);
|
|
if(flatCSV) exportAxis = (Axis)EditorGUILayout.EnumPopup("Projection Axis", exportAxis);
|
|
EditorGUILayout.HelpBox("The exported splined will be flattened along the selected axis.", MessageType.Info);
|
|
|
|
}
|
|
|
|
if (GUILayout.Button("Save File"))
|
|
{
|
|
string extension = "*";
|
|
switch (format)
|
|
{
|
|
case ExportFormat.SVG: extension = "svg"; break;
|
|
case ExportFormat.CSV: extension = "csv"; break;
|
|
}
|
|
exportPath = EditorUtility.SaveFilePanel("Export splines", exportPath, "spline", extension);
|
|
if (exportPath != "")
|
|
{
|
|
if (Directory.Exists(Path.GetDirectoryName(exportPath)))
|
|
{
|
|
switch (format)
|
|
{
|
|
case ExportFormat.SVG: ExportSVG(exportPath); break;
|
|
case ExportFormat.CSV: ExportCSV(exportPath); break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Draw(Rect windowRect)
|
|
{
|
|
if (mode == Mode.Import)
|
|
{
|
|
ImportUI();
|
|
}
|
|
else
|
|
{
|
|
importOptions = EditorGUILayout.Foldout(importOptions, "Import Options");
|
|
if (importOptions) CSVColumnUI(importColumns);
|
|
if (GUILayout.Button("Import"))
|
|
{
|
|
importPath = EditorUtility.OpenFilePanel("Browse File", importPath, "svg,csv");
|
|
if (File.Exists(importPath))
|
|
{
|
|
splines.Clear();
|
|
string ext = Path.GetExtension(importPath).ToLower();
|
|
switch (ext)
|
|
{
|
|
case ".svg": ImportSVG(importPath); break;
|
|
case ".csv": ImportCSV(importPath); break;
|
|
case ".xml": ImportSVG(importPath); break;
|
|
}
|
|
}
|
|
}
|
|
exported = GetSelectedSplines();
|
|
if (exported.Count == 0) GUI.color = new Color(1f, 1f, 1f, 0.5f);
|
|
if (mode == Mode.Export) ExportUI();
|
|
if (mode != Mode.Export)
|
|
{
|
|
if (GUILayout.Button("Export") && exported.Count > 0) mode = Mode.Export;
|
|
}
|
|
}
|
|
}
|
|
|
|
List<SplineComputer> GetSelectedSplines()
|
|
{
|
|
List<SplineComputer> selected = new List<SplineComputer>();
|
|
foreach(GameObject obj in Selection.gameObjects)
|
|
{
|
|
SplineComputer comp = obj.GetComponent<SplineComputer>();
|
|
if (comp != null) selected.Add(comp);
|
|
}
|
|
return selected;
|
|
}
|
|
|
|
void ApplyPoints()
|
|
{
|
|
if (originalPoints.Count != imported.Count) return;
|
|
if (imported.Count == 0) return;
|
|
Quaternion lookRot = Quaternion.identity;
|
|
switch (importAxis)
|
|
{
|
|
case Axis.X: lookRot = Quaternion.LookRotation(Vector3.right); break;
|
|
case Axis.Y: lookRot = Quaternion.LookRotation(Vector3.down); break;
|
|
case Axis.Z: lookRot = Quaternion.LookRotation(Vector3.forward); break;
|
|
}
|
|
for (int i = 0; i < imported.Count; i++)
|
|
{
|
|
SplinePoint[] transformed = new SplinePoint[originalPoints[i].Length];
|
|
originalPoints[i].CopyTo(transformed, 0);
|
|
for (int j = 0; j < transformed.Length; j++)
|
|
{
|
|
transformed[j].position *= scaleFactor;
|
|
transformed[j].tangent *= scaleFactor;
|
|
transformed[j].tangent2 *= scaleFactor;
|
|
|
|
transformed[j].position = lookRot * transformed[j].position;
|
|
transformed[j].tangent = lookRot * transformed[j].tangent;
|
|
transformed[j].tangent2 = lookRot * transformed[j].tangent2;
|
|
transformed[j].normal = lookRot * transformed[j].normal;
|
|
}
|
|
imported[i].SetPoints(transformed);
|
|
if (alwaysDraw)
|
|
{
|
|
DSSplineDrawer.RegisterComputer(imported[i]);
|
|
}
|
|
else
|
|
{
|
|
DSSplineDrawer.UnregisterComputer(imported[i]);
|
|
}
|
|
}
|
|
SceneView.RepaintAll();
|
|
}
|
|
|
|
void GetImportedPoints()
|
|
{
|
|
foreach (SplineComputer comp in imported)
|
|
{
|
|
if (comp != null)
|
|
{
|
|
originalPoints.Add(comp.GetPoints(SplineComputer.Space.Local));
|
|
mode = Mode.Import;
|
|
} else imported.Remove(comp);
|
|
}
|
|
}
|
|
|
|
void ImportSVG(string file)
|
|
{
|
|
SVG svg = new SVG(file);
|
|
originalPoints.Clear();
|
|
imported = svg.CreateSplineComputers(Vector3.zero, Quaternion.identity);
|
|
if (imported.Count == 0) return;
|
|
importedParent = new GameObject(svg.name);
|
|
foreach (SplineComputer comp in imported) comp.transform.parent = importedParent.transform;
|
|
#if UNITY_2019_1_OR_NEWER
|
|
SceneView.duringSceneGui += OnScene;
|
|
#else
|
|
SceneView.onSceneGUIDelegate += OnScene;
|
|
#endif
|
|
|
|
GetImportedPoints();
|
|
ApplyPoints();
|
|
promptSave = true;
|
|
}
|
|
|
|
void ExportSVG(string file)
|
|
{
|
|
SVG svg = new SVG(exported);
|
|
svg.Write(file, (SVG.Axis)((int)exportAxis));
|
|
}
|
|
|
|
void ExportCSV(string file)
|
|
{
|
|
CSV csv = new CSV(exported[0]);
|
|
csv.columns = exportColumns;
|
|
if (flatCSV)
|
|
{
|
|
switch (exportAxis)
|
|
{
|
|
case Axis.X: csv.FlatX(); break;
|
|
case Axis.Y: csv.FlatY(); break;
|
|
case Axis.Z: csv.FlatZ(); break;
|
|
}
|
|
}
|
|
csv.Write(file);
|
|
}
|
|
|
|
|
|
void ImportCSV(string file)
|
|
{
|
|
CSV csv = new CSV(file, importColumns);
|
|
originalPoints.Clear();
|
|
imported.Clear();
|
|
imported.Add(csv.CreateSplineComputer(Vector3.zero, Quaternion.identity));
|
|
if (imported.Count == 0) return;
|
|
#if UNITY_2019_1_OR_NEWER
|
|
SceneView.duringSceneGui += OnScene;
|
|
#else
|
|
SceneView.onSceneGUIDelegate += OnScene;
|
|
#endif
|
|
|
|
GetImportedPoints();
|
|
ApplyPoints();
|
|
promptSave = true;
|
|
}
|
|
}
|
|
}
|