-
Notifications
You must be signed in to change notification settings - Fork 0
/
UnityBlenderDecimate.cs
134 lines (111 loc) · 5.25 KB
/
UnityBlenderDecimate.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using System;
using System.Diagnostics;
using System.IO;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;
namespace Editor.UnityBlenderDecimate
{
public class UnityBlenderDecimate : EditorWindow
{
[MenuItem("Tools/Unity To Blender")]
public static void ShowExample()
{
UnityBlenderDecimate window = GetWindow<UnityBlenderDecimate>();
window.titleContent = new GUIContent("Unity Blender Decimate");
}
[SerializeField] private VisualTreeAsset visualTreeAsset;
[SerializeField] private string blenderPath;
private Button BlenderPathSelectButton => rootVisualElement.Q<Button>("blenderPathSelect");
private Label BlenderPathLabel => rootVisualElement.Q<Label>("blenderPath");
private ObjectField PythonScriptField => rootVisualElement.Q<ObjectField>("pythonScript");
private ObjectField InputObject => rootVisualElement.Q<ObjectField>("inputObject");
private GameObject selectedGameObject;
private string pythonScriptPath;
public void CreateGUI()
{
rootVisualElement.Add(visualTreeAsset.Instantiate());
#if UNITY_EDITOR_OSX
SetupOSXBlenderPath();
#else
BlenderPathSelectButton.RegisterCallback<ClickEvent>(OnBlenderSelectPathClick);
#endif
PythonScriptField.RegisterValueChangedCallback(OnPythonScriptSelect);
InputObject.RegisterValueChangedCallback(CheckSelectedInputObject);
rootVisualElement.Q<Button>("execute").RegisterCallback<ClickEvent>(Execute);
UpdateNextStep();
}
private void SetupOSXBlenderPath()
{
BlenderPathSelectButton.SetEnabled(false);
BlenderPathLabel.text = IsAvailableBlender() ? blenderPath : "Can't find Blender in Applications folder =(";
bool IsAvailableBlender()
{
blenderPath = Path.Combine("/Applications", "Blender.app", "Contents", "MacOS", "Blender");
return File.Exists(blenderPath);
}
}
private void UpdateNextStep()
{
Func<(bool isValidStep, string stepName)>[] steps =
{
() => (File.Exists(blenderPath), "blenderPathStep"),
() => (string.IsNullOrEmpty(pythonScriptPath) == false, "pythonScript"),
() => (selectedGameObject != null, "inputObjectStep"),
() => (true, "blenderExecuteStep")
};
var failedStep = Array.FindIndex(steps, func => func.Invoke().isValidStep == false);
for (var i = 0; i < steps.Length; i++)
{
var stepName = steps[i].Invoke().stepName;
var element = rootVisualElement.Q<VisualElement>(stepName);
element?.SetEnabled(failedStep >= i || failedStep == -1);
}
}
private void OnBlenderSelectPathClick(ClickEvent @event)
{
var path = string.IsNullOrEmpty(blenderPath) ? Application.dataPath : blenderPath;
var executableExtension = "exe";
blenderPath = EditorUtility.OpenFilePanel("Select Blender executable", path, executableExtension);
BlenderPathLabel.text = blenderPath;
UpdateNextStep();
}
private void OnPythonScriptSelect(ChangeEvent<Object> @event)
{
var path = AssetDatabase.GetAssetPath(@event.newValue);
pythonScriptPath = Path.GetExtension(path) == ".py" ? Path.GetFullPath(path) : null;
UpdateNextStep();
}
private void CheckSelectedInputObject(ChangeEvent<Object> @event)
{
PrefabAssetType prefabType = PrefabAssetType.NotAPrefab;
var go = @event.newValue as GameObject;
if (go != null)
{
var prefabAssetType = PrefabUtility.GetPrefabAssetType(go);
var fileExtension = Path.GetExtension(AssetDatabase.GetAssetPath(go));
var isObjModel = prefabAssetType == PrefabAssetType.Model && fileExtension == ".obj";
prefabType = isObjModel ? PrefabAssetType.Model : PrefabAssetType.NotAPrefab;
}
selectedGameObject = prefabType == PrefabAssetType.Model ? go : null;
InputObject.value = selectedGameObject;
UpdateNextStep();
}
private void Execute(ClickEvent @event)
{
var decimateValue = rootVisualElement.Q<Slider>("decimate").value;
var objPath = AddQuotes(Path.GetFullPath(AssetDatabase.GetAssetPath(selectedGameObject)));
var scriptPath = AddQuotes(pythonScriptPath);
var blenderProcess = new Process();
blenderProcess.StartInfo.FileName = blenderPath;
blenderProcess.StartInfo.Arguments = $"--background --python {scriptPath} -- {objPath} {decimateValue}";
blenderProcess.Start();
//TODO: Don't lock Unity
blenderProcess.WaitForExit();
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
string AddQuotes(string str) => '"' + str + '"';
}
}
}