The script used for the File->Export->Decimate > Auto UV-Map > Export.
1import coat
2import os
3
4
5_debugmode = False
6
7
8def _print(*args, **kwargs):
9 if _debugmode:
10 print(*args, **kwargs)
11
12
13class AutoExport:
14 def __init__(self):
15
16
17 self.TexRes = 4
18
19 self.ReducedPolycount = 40000
20 self.pReducedPolycount = self.ReducedPolycount
21
22
24
25
26 self.ReductionPercent = 80
27 self.pReductionPercent = self.ReductionPercent
28
29 self.DecimateFromAllVolumes = False
30 self.pDecimateFromAllVolumes = False
31
33 self.CurrentPolycount = vol.getPolycount()
34
35
36 self.EachVolumeToSeparateAsset = False
37
38 self.CenterEachAssetAroundBoundBox = False
39
40 self.EachAssetToOwnFolder = False
41
42 self.DropToBlender = False
43
44 self.UE5_optimized = False
45
46 self.RegularExport = True
47
48 self.SkipFilenamePreffix = True
49
50 self.ScanDepthPercent = 2.0
51
52
53 self.exportMesh = ""
54
55 self.texturesExportPath = ""
56
57
58 def process(self):
59 if self.ReductionPercent != self.pReductionPercent:
60 self.ReducedPolycount = int(self.CurrentPolycount * (100.0 - self.ReductionPercent) / 100.0)
61 self.pReducedPolycount = self.ReducedPolycount
62
63
64 if self.CurrentPolycount > 0:
65 self.ReductionPercent = int(100.0 - (self.ReducedPolycount * 100.0) / self.CurrentPolycount)
66 if self.ReductionPercent < 0:
67 self.ReductionPercent = 0
68
69
70 if self.DecimateFromAllVolumes != self.pDecimateFromAllVolumes:
71 self.pDecimateFromAllVolumes = self.DecimateFromAllVolumes
72
73
74 if self.DecimateFromAllVolumes:
75 self.CurrentPolycount = 0
77 root.iterateVisibleSubtree(lambda e: self._update_polycount(e))
78
79
80 else:
82 self.CurrentPolycount = vol.getPolycount()
83 self.pReductionPercent = self.ReductionPercent
84 self.pReducedPolycount = self.ReducedPolycount
85 return False
86 def UE5_YouTube():
88 def ui(self):
89 self.process()
90 items = []
91 items.append("RegularExport, group1")
92 items.append("DropToBlender, group1")
93 if self.UE5_optimized :
94 items.append("[2 1]")
95
96 items.append("UE5_optimized,group1")
97 if self.UE5_optimized :
98 items.append("UE5_YouTube")
99
100 items.append("---")
101 items.append("EachVolumeToSeparateAsset")
102 items.append("CenterEachAssetAroundBoundBox")
103 if not self.EachVolumeToSeparateAsset :
104 items.append("DecimateFromAllVolumes")
105 else:
106 items.append("EachAssetToOwnFolder")
107 if not self.EachAssetToOwnFolder :
108 items.append("SkipFilenamePreffix")
109
110
111 if self.UE5_optimized :
112 items.append("exportMesh,save:*.usdz,*.usd")
113 elif self.DropToBlender :
114 items.append("exportMesh,save:*.fbx")
115 else:
117 items.append("texturesExportPath,folder")
118 items.append("TexRes,[#256x256|#512x512|#1024x1024|#2048x2048|#4096x4096|#8192x8192]")
119
120 if self.RegularExport :
121 items.append("expPreset,[EXPPRESETS|]")
122 items.append("---")
123 items.append("#" + str(self.CurrentPolycount))
124 items.append("ReductionPercent,[0,99]")
125 items.append("[[] 6]")
126 items.append("#{maticon arrow_forward}")
127 items.append("ReducedPolycount")
128 items.append("ScanDepthPercent,[0.01,100]")
129 return items
130
131def RemovePaintObjects():
132
134
135
136 for k in range(n):
138
139def DecimateAutoMapExport():
140 se = AutoExport()
143
144 if coat.dialog().ok().cancel().text(
"SimpSculptExportHint").caption(
"SimpSculptExportHintCap").params(se).show() == 1 :
145 if coat.dialog().ok().cancel().text(
"RunBakeScriptInfo").caption(
"SimpSculptExportHintCap").dontShowAgainCheckbox().show() <= 1:
146
148
150
153 if se.DropToBlender :
154
156
157
158
164 if se.UE5_optimized :
165
171
174
175 volumes = []
176 if se.EachVolumeToSeparateAsset :
177 se.DecimateFromAllVolumes = False
179 else :
181
182 for i in range (len(volumes)):
183 vol = volumes[i]
184 _print("Processing volume: " + vol.inScene().name())
185
186 if se.EachVolumeToSeparateAsset :
187 vol.inScene().selectOne()
189 ab.SetEmpty()
190 if not se.DecimateFromAllVolumes :
191 ab = vol.calcWorldSpaceAABB()
192 else :
193 coat.Scene.sculptRoot().iterateVisibleSubtree(
lambda e: ab.AddBounds(e.Volume().calcWorldSpaceAABB()))
194 center = ab.GetCenter()
195 _print("Center: " + str(center))
196 def transform(t):
197 if se.CenterEachAssetAroundBoundBox :
198 if not se.DecimateFromAllVolumes :
199 vol.inScene().transform_single(t)
200 else :
203 d = ab.GetDiagonal() * se.ScanDepthPercent / 100.0
204 cp = vol.getPolycount()
205 _print("Polycount: " + str(cp))
206 if se.DecimateFromAllVolumes:
207 cp = 0
208 def accum(e):
209 cp += e.Volume().getPolycount()
210 return False
212 if cp > 0 :
213
214 per = 100.0 - se.ReducedPolycount * 100.0 / float(cp)
215 if per > 100.0 :
216 per = 99.0
217 if per < 0.0 :
218 per = 0.0
219
220
222 RemovePaintObjects()
230 coat.ui.cmd(
"$DecimateAllToRetopo" if se.DecimateFromAllVolumes
else "$DecimateToRetopo",
lambda:
coat.ui.cmd(
"$DialogButton#1"))
231
233
235
237
239
241
242 texSize = str(256 << se.TexRes)
243
246
247 def inbake():
248
249 b1 =
coat.ui.cmd(
"$COMBOBOX_TEXTURE_SIZE_X" + texSize)
250 _print("inbake1: " + str(b1))
251
252 b1 =
coat.ui.cmd(
"$COMBOBOX_TEXTURE_SIZE_Y" + texSize)
253 _print("inbake2: " + str(b1))
254
256 _print("Baking...")
260
261 name = se.exportMesh
262 if se.EachVolumeToSeparateAsset :
263 name, ext = os.path.splitext(name)
264 if se.EachAssetToOwnFolder :
265 name += "/"
266 name += vol.inScene().name()
267 name += "/"
268 name += vol.inScene().name()
269 name += ext
270 else :
271 if se.SkipFilenamePreffix :
272 name = os.path.dirname(name)
273 name += "/"
274 else :
275 name += "_"
276 name += vol.inScene().name()
277 name += ext
278 if se.UE5_optimized :
279 name, ext = os.path.splitext(name)
280 if not ("usd" in ext.lower()):
281 name += ".usdz"
282 if se.DropToBlender :
283
284 name = os.path.splitext(name)[0]
285 name += ".fbx"
286
289 else :
290 def inexport() :
291
293 _print("inexport: " + "$COMBOBOX_" + preset + " : " + str(b1))
296 _print("inexport: $ExportOpt::ExportMeshName " + name + " : " + str(b1))
297
299 _print("inexport: $ExportOpt::ExportTextures : " + str(b1))
300
302 _print("inexport: $ExportOpt::ExportGeometry : " + str(b1))
303
305
307 _print("inexport: $DialogButton#1 : " + str(b1))
308 _print("Export...")
310
311 RemovePaintObjects()
314
318
320
322
323DecimateAutoMapExport()
int PaintObjectsCount()
Get the count of paint objects in scene.
Definition coat.py:2845
SceneElement sculptRoot()
get the root of all sculpt objects
Definition coat.py:2687
RemovePaintObject(int idx)
Remove the paint object.
Definition coat.py:2857
SceneElement current()
returns the current sculpt object
Definition coat.py:2683
fromJsonFile(any obj, str filename)
Restore the object from the json file.
Definition coat.py:3805
bool fileExists(str path)
check if file exists
Definition coat.py:3591
str supportedMeshesFormats()
returns the list of supported images formats
Definition coat.py:3749
showPythonConsole()
Show the python console, clear it and pop up.
Definition coat.py:3786
str toJson(any obj, str filename="")
Store the object to the file or string as json.
Definition coat.py:3800
exec(str command, str arguments=None)
execute command.
Definition coat.py:3719
step(int count=1)
perform rendering cycles
Definition coat.py:3714
mat4 Translation(float X, float Y)
Definition coat.py:554
bool setBool(str ID, bool value)
set the boolean value to the settings
Definition coat.py:2636
bool setString(str ID, str value)
set the string value to the settings
Definition coat.py:2642
bool getBool(str ID)
get the boolen value from the settings
Definition coat.py:2615
bool setEditBoxValue(str id, str value)
set the edit box value
Definition coat.py:3229
bool getBoolField(str id)
Get the bool field from the checkbox in UI.
Definition coat.py:3264
str currentRoom()
get the current room name
Definition coat.py:3274
bool setBoolValue(str id, bool value)
Set the value for the checkbox in UI.
Definition coat.py:3270
str getIdTranslation(str id)
Get the translation for the text identifier.
Definition coat.py:3372
bool cmd(str id, any fn=None)
execute some action in UI as if you pressed on some control
Definition coat.py:3186
toRoom(str name, bool Force=False)
switch to the room
Definition coat.py:3284
setFileForFileDialog(str filename)
Set the file for the next file dialog that will be triggered by user.
Definition coat.py:3259
hideDontShowAgainMessage(str id)
Hides the "Don't show again dialog" for the current session (not forever)
Definition coat.py:3315
bool setOption(str id, str value)
set the value to preferences
Definition coat.py:3307
str getEnumValueByIndex(str enumID, int index)
get the value from the global strings list by index.
Definition coat.py:3882
int getEnumValue(str enumID, str key)
get the integer value that corresponds to the string value from the global strings list.
Definition coat.py:3888