Autoexport.py

Autoexport.py#

:Autoexport.py
Autoexport.py

The script used for the File->Export->Decimate > Auto UV-Map > Export

1import coat
2import os
3
4# Set this to True to enable debug output
5_debugmode = False
6
7# the debug print function
8def _print(*args, **kwargs):
9 if _debugmode:
10 print(*args, **kwargs)
11
12# the autoexport class
13class AutoExport:
14 def __init__(self):
15 # Initialize variables with default values
16 # the texture resolution
17 self.TexRes = 4
18 # the desirable reduced polycount
19 self.ReducedPolycount = 40000
20 self.pReducedPolycount = self.ReducedPolycount
21
22 # the default export preset
23 self.expPreset = coat.utils.getEnumValue("EXPPRESETS", "PBR+EXR-displacement",)
24
25 # the default reduction percent
26 self.ReductionPercent = 80
27 self.pReductionPercent = self.ReductionPercent
28 # decumate from all volumes or from the current volume
29 self.DecimateFromAllVolumes = False
30 self.pDecimateFromAllVolumes = False
31
32 vol = coat.Scene.current().Volume()
33 self.CurrentPolycount = vol.getPolycount()
34
35 # export each volume to separate asset
36 self.EachVolumeToSeparateAsset = False
37 # center each asset around its bound box
38 self.CenterEachAssetAroundBoundBox = False
39 # export each asset to its own folder
40 self.EachAssetToOwnFolder = False
41 # drop export result directly to blender
42 self.DropToBlender = False
43 # export mesh optimized for UE5
44 self.UE5_optimized = False
45 # the regular export
46 self.RegularExport = True
47 # skip the filename preffix
48 self.SkipFilenamePreffix = True
49 # the scan depth percent (in percents of the diagonal of the bound box)
50 self.ScanDepthPercent = 2.0
51
52 # the mesh export path
53 self.exportMesh = ""
54 # the textures export path (optional)
55 self.texturesExportPath = ""
56
57 # called each frame
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 # Update the reduction percent based on the current polycount
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 # Check for changes in DecimateFromAllVolumes and update accordingly
70 if self.DecimateFromAllVolumes != self.pDecimateFromAllVolumes:
71 self.pDecimateFromAllVolumes = self.DecimateFromAllVolumes
72
73 # If DecimateFromAllVolumes is true, calculate the total polycount
74 if self.DecimateFromAllVolumes:
75 self.CurrentPolycount = 0
76 root = coat.Scene.sculptRoot()
77 root.iterateVisibleSubtree(lambda e: self._update_polycount(e))
78
79 # Otherwise, use the polycount of the current volume
80 else:
81 vol = coat.Scene.current().Volume()
82 self.CurrentPolycount = vol.getPolycount()
83 self.pReductionPercent = self.ReductionPercent
84 self.pReducedPolycount = self.ReducedPolycount
85 return False
86 def UE5_YouTube():
87 coat.io.exec(coat.ui.getIdTranslation("UE5_ExportTutorial"))
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 # gather all supported export extensions
111 if self.UE5_optimized :
112 items.append("exportMesh,save:*.usdz,*.usd")
113 elif self.DropToBlender :
114 items.append("exportMesh,save:*.fbx")
115 else:
116 items.append("exportMesh,save:" + coat.io.supportedMeshesFormats())
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 # Get the count of paint objects in the scene
133 n = coat.Scene.PaintObjectsCount()
134
135 # Loop through the paint objects and remove them
136 for k in range(n):
138
139def DecimateAutoMapExport():
140 se = AutoExport()
141 if coat.io.fileExists("UserPrefs/CoreAPI/auto_export_py.json"):
142 coat.io.fromJsonFile(se, "UserPrefs/CoreAPI/auto_export_py.json")
143 # show the parameters dialog
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 # save settings
147 coat.io.toJson(se, "UserPrefs/CoreAPI/auto_export_py.json")
148 # hide annoying message about textures locking
149 coat.ui.hideDontShowAgainMessage("AttachTextureHint")
150 # don't fade background, but keep it' state, auto_keep allows to save that value in the current scope,
151 fade = coat.settings.getBool("GreyOutBgInModalDialogs")
152 coat.settings.setBool("GreyOutBgInModalDialogs", False)
153 if se.DropToBlender :
154 # the blender applink toes not support embedding
155 coat.settings.setBool("EmbedTexturesToFBX", False)
156 # set blender's specific normalmapping settings
157 # Generally, you may use just English text itens below
158 # but I decided to use the identifiers instead
159 coat.settings.setString("SoftwarePreset", "Blender")
160 coat.settings.setString("NormalsCalculationMethod", "nm_AngleWeighed")
161 coat.settings.setString("NMAP_EXPORT_TYPE", "NM_MAYA")
162 coat.settings.setString("TriangulationMethod", "DelaunayTriangulation")
163 coat.settings.setString("TBNMethod", "MikkTSpace")
164 if se.UE5_optimized :
165 # set UE5 specific normalmapping settings
166 coat.settings.setString("SoftwarePreset", "UnrealEngine")
167 coat.settings.setString("NormalsCalculationMethod", "nm_AngleWeighed")
168 coat.settings.setString("NMAP_EXPORT_TYPE", "NM_3DMAX")
169 coat.settings.setString("TriangulationMethod", "NaiveTriangulation")
170 coat.settings.setString("TBNMethod", "MikkTSpace")
171 # set the export preset
172 coat.settings.setString("ExportPreset", "PBR+EXR-displacement")
173 se.expPreset = coat.utils.getEnumValue("EXPPRESETS", "USD (PBR Standard)")
174 # create the list of volumes we want to handle
175 volumes = []
176 if se.EachVolumeToSeparateAsset :
177 se.DecimateFromAllVolumes = False
178 coat.Scene.sculptRoot().iterateVisibleSubtree(lambda e: volumes.append(e.Volume()))
179 else :
180 volumes.append(coat.Scene.current().Volume())
181 # go through all volumes we want to operate
182 for i in range (len(volumes)):
183 vol = volumes[i]
184 _print("Processing volume: " + vol.inScene().name())
185 # select the volume
186 if se.EachVolumeToSeparateAsset :
187 vol.inScene().selectOne()
188 ab = coat.boundbox()
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 :
201 coat.Scene.sculptRoot().iterateVisibleSubtree(lambda e: e.transform_single(t))
202 transform(coat.mat4.Translation(-center))
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
211 coat.Scene.sculptRoot().iterateVisibleSubtree(accum)
212 if cp > 0 :
213 # calculating the decimation percent
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 # get the name of the export preset, there is index
220 # of the preset in the se.expPreset
221 preset = coat.utils.getEnumValueByIndex("EXPPRESETS",se.expPreset)
222 RemovePaintObjects()
223 coat.ui.toRoom("Retopo")
224 coat.io.step(4)
225 _print("In room: " + coat.ui.currentRoom())
226 nameCorr = coat.ui.getBoolField("$UseNamesCorrespondence")
227 coat.ui.setBoolValue("$UseNamesCorrespondence", True)
228 coat.ui.cmd("$ClearTM")
229 coat.ui.toRoom("Sculpt")
230 coat.ui.cmd("$DecimateAllToRetopo" if se.DecimateFromAllVolumes else "$DecimateToRetopo", lambda: coat.ui.cmd("$DialogButton#1"))
231 # switch to retopo room
232 coat.ui.toRoom("Retopo")
233 # refresh UI
234 coat.io.step(4)
235 # closest along normal to keep shape
236 coat.ui.cmd("$SnapToNearestAlongNormal")
237 # relax the mesh, snapping rurned ON
238 coat.ui.cmd("$ApplyTSm")
239 # refresh UI
240 coat.io.step(4)
241 # the string that contains decimation percent
242 texSize = str(256 << se.TexRes)
243 # set the baking scan depth, the depth is auto-cacculated and substituted by Coat
244 coat.ui.setOption("BakeScanDepthOut", d)
245 coat.ui.setOption("BakeScanDepthIn", d)
246 # call Bake->Bake with normal map+flat displacement
247 def inbake():
248 # set texture width when the field accessible
249 b1 = coat.ui.cmd("$COMBOBOX_TEXTURE_SIZE_X" + texSize)
250 _print("inbake1: " + str(b1))
251 # set texture height
252 b1 = coat.ui.cmd("$COMBOBOX_TEXTURE_SIZE_Y" + texSize)
253 _print("inbake2: " + str(b1))
254 # press OK at the end
255 coat.ui.cmd("$DialogButton#1")
256 _print("Baking...")
257 coat.ui.cmd("$MergeForDPNM_flatdisp", inbake)
258 coat.ui.setBoolValue("$UseNamesCorrespondence", nameCorr)
259 coat.ui.toRoom("Paint")
260 # fill the mesh name
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 # remove file extension
284 name = os.path.splitext(name)[0]
285 name += ".fbx"
286 # call the export dialog
287 coat.ui.setFileForFileDialog(name)
288 coat.ui.cmd("$Blender", lambda: coat.ui.cmd("$DialogButton#1"))
289 else :
290 def inexport() :
291 # set export preset
292 b1 = coat.ui.cmd("$COMBOBOX_" + preset)
293 _print("inexport: " + "$COMBOBOX_" + preset + " : " + str(b1))
294 coat.io.step(2)
295 b1 = coat.ui.setEditBoxValue("$ExportOpt::ExportMeshName", name)
296 _print("inexport: $ExportOpt::ExportMeshName " + name + " : " + str(b1))
297 # enable mesh export
298 b1 = coat.ui.setBoolValue("$ExportOpt::ExportTextures", True)
299 _print("inexport: $ExportOpt::ExportTextures : " + str(b1))
300 # enable textures export
301 b1 = coat.ui.setBoolValue("$ExportOpt::ExportGeometry", True)
302 _print("inexport: $ExportOpt::ExportGeometry : " + str(b1))
303 # set the textures folder path
304 if coat.ui.setEditBoxValue("$ExportOpt::PathForTextures", se.texturesExportPath) :
305 # press Export at the end
306 coat.ui.cmd("$DialogButton#1")
307 _print("inexport: $DialogButton#1 : " + str(b1))
308 _print("Export...")
309 coat.ui.cmd("$EXPORTOBJECT", inexport)
310 # remove all paint objects
311 RemovePaintObjects()
312 coat.ui.toRoom("Retopo")
313 coat.io.step(2)
314 # clear all retopo objects
315 coat.ui.cmd("$ClearTM")
316 coat.ui.toRoom("Sculpt")
317 transform(coat.mat4.Translation(center))
318 # restore the background fade state
319 coat.settings.setBool("GreyOutBgInModalDialogs", fade)
320
321if _debugmode : coat.io.showPythonConsole()
322
323DecimateAutoMapExport()
:Autoexport.py
  1     import coat
  2     import os
  3
  4     # Set this to True to enable debug output
  5     _debugmode = False
  6
  7     # the debug print function
  8     def _print(*args, **kwargs):
  9             if _debugmode:
 10                     print(*args, **kwargs)
 11
 12     # the autoexport class
 13     class AutoExport:
 14             def __init__(self):
 15                     # Initialize variables with default values
 16                     # the texture resolution
 17                     self.TexRes = 4
 18                     # the desirable reduced polycount
 19                     self.ReducedPolycount = 40000
 20                     self.pReducedPolycount = self.ReducedPolycount
 21
 22                     # the default export preset
 23                     self.expPreset = coat.utils.getEnumValue("EXPPRESETS", "PBR+EXR-displacement",)
 24
 25                     # the default reduction percent
 26                     self.ReductionPercent = 80
 27                     self.pReductionPercent = self.ReductionPercent
 28                     # decumate from all volumes or from the current volume
 29                     self.DecimateFromAllVolumes = False
 30                     self.pDecimateFromAllVolumes = False
 31
 32                     vol = coat.Scene.current().Volume()
 33                     self.CurrentPolycount = vol.getPolycount()
 34
 35                     # export each volume to separate asset
 36                     self.EachVolumeToSeparateAsset = False
 37                     # center each asset around its bound box
 38                     self.CenterEachAssetAroundBoundBox = False
 39                     # export each asset to its own folder
 40                     self.EachAssetToOwnFolder = False
 41                     # drop export result directly to blender
 42                     self.DropToBlender = False
 43                     # export mesh optimized for UE5
 44                     self.UE5_optimized = False
 45                     # the regular export
 46                     self.RegularExport = True
 47                     # skip the filename preffix
 48                     self.SkipFilenamePreffix = True
 49                     # the scan depth percent (in percents of the diagonal of the bound box)
 50                     self.ScanDepthPercent = 2.0
 51
 52                     # the mesh export path
 53                     self.exportMesh = ""
 54                     # the textures export path (optional)
 55                     self.texturesExportPath = ""
 56
 57             # called each frame
 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                     # Update the reduction percent based on the current polycount
 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                     # Check for changes in DecimateFromAllVolumes and update accordingly
 70                     if self.DecimateFromAllVolumes != self.pDecimateFromAllVolumes:
 71                             self.pDecimateFromAllVolumes = self.DecimateFromAllVolumes
 72
 73                             # If DecimateFromAllVolumes is true, calculate the total polycount
 74                             if self.DecimateFromAllVolumes:
 75                                     self.CurrentPolycount = 0
 76                                     root = coat.Scene.sculptRoot()
 77                                     root.iterateVisibleSubtree(lambda e: self._update_polycount(e))
 78
 79                             # Otherwise, use the polycount of the current volume
 80                             else:
 81                                     vol = coat.Scene.current().Volume()
 82                                     self.CurrentPolycount = vol.getPolycount()
 83                     self.pReductionPercent = self.ReductionPercent
 84                     self.pReducedPolycount = self.ReducedPolycount
 85                     return False
 86             def UE5_YouTube():
 87                     coat.io.exec(coat.ui.getIdTranslation("UE5_ExportTutorial"))
 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                     # gather all supported export extensions
111                     if self.UE5_optimized :
112                             items.append("exportMesh,save:*.usdz,*.usd")
113                     elif self.DropToBlender :
114                             items.append("exportMesh,save:*.fbx")
115                     else:
116                             items.append("exportMesh,save:" + coat.io.supportedMeshesFormats())
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
131     def RemovePaintObjects():
132             # Get the count of paint objects in the scene
133             n = coat.Scene.PaintObjectsCount()
134
135             # Loop through the paint objects and remove them
136             for k in range(n):
137                     coat.Scene.RemovePaintObject(0)
138
139     def DecimateAutoMapExport():
140             se = AutoExport()
141             if coat.io.fileExists("UserPrefs/CoreAPI/auto_export_py.json"):
142                     coat.io.fromJsonFile(se, "UserPrefs/CoreAPI/auto_export_py.json")
143             # show the parameters dialog
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                             # save settings
147                             coat.io.toJson(se, "UserPrefs/CoreAPI/auto_export_py.json")
148                             # hide annoying message about textures locking
149                             coat.ui.hideDontShowAgainMessage("AttachTextureHint")
150                             # don't fade background, but keep it' state, auto_keep allows to save that value in the current scope,
151                             fade = coat.settings.getBool("GreyOutBgInModalDialogs")
152                             coat.settings.setBool("GreyOutBgInModalDialogs", False)
153                             if se.DropToBlender :
154                                # the blender applink toes not support embedding
155                                     coat.settings.setBool("EmbedTexturesToFBX", False)
156                                     # set blender's specific normalmapping settings
157                                     # Generally, you may use just English text itens below
158                                     # but I decided to use the identifiers instead
159                                     coat.settings.setString("SoftwarePreset", "Blender")
160                                     coat.settings.setString("NormalsCalculationMethod", "nm_AngleWeighed")
161                                     coat.settings.setString("NMAP_EXPORT_TYPE", "NM_MAYA")
162                                     coat.settings.setString("TriangulationMethod", "DelaunayTriangulation")
163                                     coat.settings.setString("TBNMethod", "MikkTSpace")
164                             if se.UE5_optimized :
165                                     # set UE5 specific normalmapping settings
166                                     coat.settings.setString("SoftwarePreset", "UnrealEngine")
167                                     coat.settings.setString("NormalsCalculationMethod", "nm_AngleWeighed")
168                                     coat.settings.setString("NMAP_EXPORT_TYPE", "NM_3DMAX")
169                                     coat.settings.setString("TriangulationMethod", "NaiveTriangulation")
170                                     coat.settings.setString("TBNMethod", "MikkTSpace")
171                                     # set the export preset
172                                     coat.settings.setString("ExportPreset", "PBR+EXR-displacement")
173                                     se.expPreset = coat.utils.getEnumValue("EXPPRESETS", "USD (PBR Standard)")
174                             # create the list of volumes we want to handle
175                             volumes = []
176                             if se.EachVolumeToSeparateAsset :
177                                     se.DecimateFromAllVolumes = False
178                                     coat.Scene.sculptRoot().iterateVisibleSubtree(lambda e: volumes.append(e.Volume()))
179                             else :
180                                     volumes.append(coat.Scene.current().Volume())
181                             # go through all volumes we want to operate
182                             for i in range (len(volumes)):
183                                     vol = volumes[i]
184                                     _print("Processing volume: " + vol.inScene().name())
185                                     # select the volume
186                                     if se.EachVolumeToSeparateAsset :
187                                             vol.inScene().selectOne()
188                                     ab = coat.boundbox()
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
197                                     def transform(t):
198                                             if se.CenterEachAssetAroundBoundBox :
199                                                     if not se.DecimateFromAllVolumes :
200                                                             vol.inScene().transform_single(t)
201                                                     else :
202                                                             coat.Scene.sculptRoot().iterateVisibleSubtree(lambda e: e.transform_single(t))
203                                     transform(coat.mat4.Translation(-center))
204                                     d = ab.GetDiagonal() * se.ScanDepthPercent / 100.0
205                                     cp = vol.getPolycount()
206                                     _print("Polycount: " + str(cp))
207                                     if se.DecimateFromAllVolumes:
208                                             cp = 0
209                                             def accum(e):
210                                                     cp += e.Volume().getPolycount()
211                                                     return False
212                                             coat.Scene.sculptRoot().iterateVisibleSubtree(accum)
213                                     if cp > 0 :
214                                             # calculating the decimation percent
215                                             per = 100.0 - se.ReducedPolycount * 100.0 / float(cp)
216                                             if per > 100.0 :
217                                                     per = 99.0
218                                             if per < 0.0 :
219                                                     per = 0.0
220                                             # get the name of the export preset, there is index
221                                             # of the preset in the se.expPreset
222                                             preset = coat.utils.getEnumValueByIndex("EXPPRESETS",se.expPreset)
223                                             RemovePaintObjects()
224                                             coat.ui.toRoom("Retopo")
225                                             coat.io.step(4)
226                                             _print("In room: " + coat.ui.currentRoom())
227                                             nameCorr = coat.ui.getBoolField("$UseNamesCorrespondence")
228                                             coat.ui.setBoolValue("$UseNamesCorrespondence", True)
229                                             coat.ui.cmd("$ClearTM")
230                                             coat.ui.toRoom("Sculpt")
231                                             coat.ui.cmd("$DecimateAllToRetopo" if se.DecimateFromAllVolumes else "$DecimateToRetopo", lambda: coat.ui.cmd("$DialogButton#1"))
232                                             # switch to retopo room
233                                             coat.ui.toRoom("Retopo")
234                                             # refresh UI
235                                             coat.io.step(4)
236                                             # closest along normal to keep shape
237                                             coat.ui.cmd("$SnapToNearestAlongNormal")
238                                             # relax the mesh, snapping rurned ON
239                                             coat.ui.cmd("$ApplyTSm")
240                                             # refresh UI
241                                             coat.io.step(4)
242                                             # the string that contains decimation percent
243                                             texSize = str(256 << se.TexRes)
244                                             # set the baking scan depth, the depth is auto-cacculated and substituted by Coat
245                                             coat.ui.setOption("BakeScanDepthOut", d)
246                                             coat.ui.setOption("BakeScanDepthIn", d)
247                                             # call Bake->Bake with normal map+flat displacement
248                                             def inbake():
249                                                     # set texture width when the field accessible
250                                                     b1 = coat.ui.cmd("$COMBOBOX_TEXTURE_SIZE_X" + texSize)
251                                                     _print("inbake1: " + str(b1))
252                                                     # set texture height
253                                                     b1 = coat.ui.cmd("$COMBOBOX_TEXTURE_SIZE_Y" + texSize)
254                                                     _print("inbake2: " + str(b1))
255                                                     # press OK at the end
256                                                     coat.ui.cmd("$DialogButton#1")
257                                             _print("Baking...")
258                                             coat.ui.cmd("$MergeForDPNM_flatdisp", inbake)
259                                             coat.ui.setBoolValue("$UseNamesCorrespondence", nameCorr)
260                                             coat.ui.toRoom("Paint")
261                                             # fill the mesh name
262                                             name = se.exportMesh
263                                             if se.EachVolumeToSeparateAsset :
264                                                     name, ext = os.path.splitext(name)
265                                                     if se.EachAssetToOwnFolder :
266                                                             name += "/"
267                                                             name += vol.inScene().name()
268                                                             name += "/"
269                                                             name += vol.inScene().name()
270                                                             name += ext
271                                                     else :
272                                                             if se.SkipFilenamePreffix :
273                                                                     name = os.path.dirname(name)
274                                                                     name += "/"
275                                                             else :
276                                                                     name += "_"
277                                                             name += vol.inScene().name()
278                                                             name += ext
279                                             if se.UE5_optimized :
280                                                     name, ext = os.path.splitext(name)
281                                                     if not ("usd" in ext.lower()):
282                                                             name += ".usdz"
283                                             if se.DropToBlender :
284                                                     # remove file extension
285                                                     name = os.path.splitext(name)[0]
286                                                     name += ".fbx"
287                                                     # call the export dialog
288                                                     coat.ui.setFileForFileDialog(name)
289                                                     coat.ui.cmd("$Blender", lambda: coat.ui.cmd("$DialogButton#1"))
290                                             else :
291                                                     def inexport() :
292                                                             # set export preset
293                                                             b1 = coat.ui.cmd("$COMBOBOX_" + preset)
294                                                             _print("inexport: " + "$COMBOBOX_" + preset + " : " + str(b1))
295                                                             coat.io.step(2)
296                                                             b1 = coat.ui.setEditBoxValue("$ExportOpt::ExportMeshName", name)
297                                                             _print("inexport: $ExportOpt::ExportMeshName " + name + " : " + str(b1))
298                                                             # enable mesh export
299                                                             b1 = coat.ui.setBoolValue("$ExportOpt::ExportTextures", True)
300                                                             _print("inexport: $ExportOpt::ExportTextures : " + str(b1))
301                                                             # enable textures export
302                                                             b1 = coat.ui.setBoolValue("$ExportOpt::ExportGeometry", True)
303                                                             _print("inexport: $ExportOpt::ExportGeometry : " + str(b1))
304                                                             # set the textures folder path
305                                                             if coat.ui.setEditBoxValue("$ExportOpt::PathForTextures", se.texturesExportPath) :
306                                                                     # press Export at the end
307                                                                     coat.ui.cmd("$DialogButton#1")
308                                                                     _print("inexport: $DialogButton#1 : " + str(b1))
309                                                     _print("Export...")
310                                                     coat.ui.cmd("$EXPORTOBJECT", inexport)
311                                             # remove all paint objects
312                                             RemovePaintObjects()
313                                             coat.ui.toRoom("Retopo")
314                                             coat.io.step(2)
315                                             # clear all retopo objects
316                                             coat.ui.cmd("$ClearTM")
317                                             coat.ui.toRoom("Sculpt")
318                                     transform(coat.mat4.Translation(center))
319                             # restore the background fade state
320                             coat.settings.setBool("GreyOutBgInModalDialogs", fade)
321
322     if _debugmode : coat.io.showPythonConsole()
323
324     DecimateAutoMapExport()