Skip to content

Commit 0a24173

Browse files
committed
Unity Blender Decimate
1 parent a63b97b commit 0a24173

File tree

6 files changed

+196
-0
lines changed

6 files changed

+196
-0
lines changed

Decimate.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import bpy
2+
import sys
3+
4+
argv = sys.argv
5+
#Get only our arguments
6+
argv = argv[argv.index("--") + 1:]
7+
print(argv)
8+
objPath = argv[0]
9+
decimateValue = argv[1]
10+
11+
#Delete default objects:cube,camera,light
12+
bpy.ops.object.select_all(action='SELECT')
13+
bpy.ops.object.delete(use_global=False)
14+
15+
imported_object = bpy.ops.import_scene.obj(filepath=objPath)
16+
obj_object = bpy.context.selected_objects[0]
17+
decimate = obj_object.modifiers.new(name="Decimate", type = 'DECIMATE')
18+
decimate.ratio = float(decimateValue)
19+
20+
#Export as obj
21+
bpy.ops.export_scene.obj(filepath=objPath)

Decimate.py.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

UnityBlenderDecimate.cs

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

UnityBlenderDecimate.cs.meta

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

UnityToBlender.uxml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" editor-extension-mode="True">
2+
<ui:Label text="Unity Blender Decimate" style="-unity-text-align: upper-center; font-size: 20px; -unity-font-style: bold;" />
3+
<ui:VisualElement style="height: 4px; width: 504px;" />
4+
<ui:VisualElement name="blenderPathStep" style="flex-direction: row;">
5+
<ui:Button name="blenderPathSelect" text="Edit Blender Path" />
6+
<ui:Label name="blenderPath" style="-unity-text-align: middle-left;" />
7+
</ui:VisualElement>
8+
<uie:ObjectField label="Python Script" name="pythonScript" type="UnityEditor.DefaultAsset, UnityEditor.CoreModule" />
9+
<ui:VisualElement name="inputObjectStep">
10+
<uie:ObjectField name="inputObject" label="OBJ Model" type="UnityEngine.GameObject, UnityEngine.CoreModule" allow-scene-objects="false" />
11+
</ui:VisualElement>
12+
<ui:VisualElement name="blenderExecuteStep">
13+
<ui:Slider name="decimate" label="Decimate" value="1" high-value="1" show-input-field="true" />
14+
<ui:Button name="execute" text="Run" display-tooltip-when-elided="true" />
15+
</ui:VisualElement>
16+
</ui:UXML>

UnityToBlender.uxml.meta

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)