Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
BakeMLOD.c
Go to the documentation of this file.
1#ifdef WORKBENCH
2
3static const int TEXTURE_SIZES[3] = {512, 1024, 2048};
4static const int TEXTURE_IMPORT_SIZES[4] = {-1, 256, 512, 1024};
5static const int SUPER_SAMPLING[3] = {1, 2, 4};
6
7class ParamEnumTextureSize : array<ref ParamEnum>
8{
9 static ParamEnumArray FromEnum()
10 {
11 ParamEnumArray params = new ParamEnumArray();
12
13 for (int i, max = StaticArray.Length(TEXTURE_SIZES); i < max; i++)
14 {
15 params.Insert(new ParamEnum(TEXTURE_SIZES[i].ToString(), i.ToString()));
16 }
17
18 return params;
19 }
20}
21
22class ParamEnumTextureImportSize : array<ref ParamEnum>
23{
24 static ParamEnumArray FromEnum()
25 {
26 ParamEnumArray params = new ParamEnumArray();
27
28 params.Insert(new ParamEnum("No limit", "0"));
29
30 for (int i = 1, max = StaticArray.Length(TEXTURE_IMPORT_SIZES); i < max; i++)
31 {
32 params.Insert(new ParamEnum(TEXTURE_IMPORT_SIZES[i].ToString(), i.ToString()));
33 }
34
35 return params;
36 }
37}
38
39class ParamEnumSuperSampling : array<ref ParamEnum>
40{
41 static ParamEnumArray FromEnum()
42 {
43 ParamEnumArray params = new ParamEnumArray();
44
45 params.Insert(new ParamEnum("None", "0"));
46 params.Insert(new ParamEnum("2x", "1"));
47 params.Insert(new ParamEnum("4x", "2"));
48
49 return params;
50 }
51}
52
53enum FixRayMissType
54{
55 FAST,
56 SMOOTH_CAGE_BAKE
57}
58
59enum FixRayMissExtents
60{
61 BROAD,
62 MINIMUM
63}
64
65[WorkbenchPluginAttribute(name: "EBT: Bake MLOD", wbModules: { "ResourceManager" }, resourceTypes: { "fbx", "xob" }, awesomeFontCode: 0xf7ec)]
66class BakeMLODPlugin : WorkbenchPlugin
67{
68 [Attribute("16", UIWidgets.EditBox, "", category : "Settings")]
69 protected int m_iNumberOfSamples;
70
71 [Attribute("True", UIWidgets.EditBox, "", category : "Development")]
72 protected bool m_bRunInBackground = true;
73
74 //------------------------------------------------------------------------------------------------
75 protected static ref StartBakeDialogXOB s_StartBakeDialogXOB = new StartBakeDialogXOB("Bake XOB MLOD");
76
77 static ref StartBakeDialogET s_StartBakeDialogET = new StartBakeDialogET("Bake ET MLOD");
78
79 protected static BakeMLODPlugin s_Instance;
80
81 void BakeMLODPlugin()
82 {
83 if (!s_Instance)
84 s_Instance = this;
85 }
86
87 static BakeMLODPlugin GetInstance()
88 {
89 return s_Instance;
90 }
91
92 static bool GetOperatorDescription(StartBakeDialog startBakeDialog, ResourceName resourceName, int noOfSamples, out BlenderOperatorDescription operatorDescription)
93 {
94 string pathToResourceParam;
95 Workbench.GetAbsolutePath(resourceName.GetPath(), pathToResourceParam);
96
97 if (resourceName.EndsWith(".xob"))
98 pathToResourceParam.Replace(".xob", ".fbx");
99
100 if (!FileIO.FileExists(pathToResourceParam))
101 {
102 Print("Resource couldn't be imported to blender because .fbx file is missing", LogLevel.WARNING);
103 return false;
104 }
105
106 //Common params
107 int textureSize= TEXTURE_SIZES[startBakeDialog.m_iTextureSize];
108 int textureImportSize= TEXTURE_IMPORT_SIZES[startBakeDialog.m_iTextureImportSize];
109 int superSamplingSize = SUPER_SAMPLING[startBakeDialog.m_iSuperSampling];
110
111 operatorDescription.AddParam("file_path", pathToResourceParam);
112 operatorDescription.AddParam("clear_color", startBakeDialog.m_ClearColor);
113 operatorDescription.AddParam("texture_size", textureSize);
114 operatorDescription.AddParam("texture_import_size", textureImportSize);
115 operatorDescription.AddParam("cage_extrusion", startBakeDialog.m_fCageExtrusion);
116 operatorDescription.AddParam("ray_distance", startBakeDialog.m_fRayDistance);
117 operatorDescription.AddParam("skip_interior", startBakeDialog.m_bSkipInterior);
118 operatorDescription.AddParam("no_of_samples", noOfSamples);
119 operatorDescription.AddParam("fix_ray_miss_type", startBakeDialog.m_eFixRayType);
120 operatorDescription.AddParam("fix_ray_miss_extents", startBakeDialog.m_eFixRayExtents);
121 operatorDescription.AddParam("super_sampling", superSamplingSize);
122
123
124 if (startBakeDialog.Type() == StartBakeDialogXOB)
125 {
126 StartBakeDialogXOB dialog = StartBakeDialogXOB.Cast(startBakeDialog);
127
128 string absTexturePath = "";
129 // When you wanna get absolute path but no param, then it will give you the root of... The last addon?
130 if(dialog.m_sTexturePath != "")
131 {
132 Workbench.GetAbsolutePath(dialog.m_sTexturePath,absTexturePath);
133 }
134 operatorDescription.blIDName = "ebt.bake_workbench_background_xob_mlod";
135 operatorDescription.AddParam("re_uv", dialog.m_bReUV);
136 operatorDescription.AddParam("skip_transparent", dialog.m_bSkipTransparent);
137 operatorDescription.AddParam("create_new_texture", dialog.m_bCreateNewTexture);
138 operatorDescription.AddParam("texture_name",dialog.m_sTextureName);
139 operatorDescription.AddParam("texture_path",absTexturePath);
140 }
141 else
142 {
143 string baseFbx;
144 if (!PrefabImporterBake.GetBaseFBX(resourceName, baseFbx))
145 {
146 Print("Could not get Base FBX", LogLevel.WARNING);
147 return false;
148 }
149
150 operatorDescription.blIDName = "ebt.bake_workbench_background_et_mlod";
151 operatorDescription.AddParam("base_fbx", baseFbx);
152 operatorDescription.AddParam("new_texture", StartBakeDialogET.Cast(startBakeDialog).m_sNewTextureName);
153 }
154
155 return true;
156 }
157
158
159 void StartBake(ResourceName resource)
160 {
161 if (!EBTConfigPlugin.HasBlenderRegistered())
162 return;
163
164 StartBakeDialog bakeDialog = s_StartBakeDialogET;
165
166 if (resource.EndsWith(".xob") || resource.EndsWith(".fbx"))
167 bakeDialog = s_StartBakeDialogXOB;
168
169 if (!Workbench.ScriptDialog(bakeDialog.m_sTitle, "Make sure you have supported version of Blender and newest EBT installed.", bakeDialog))
170 return;
171
172
173 string pathToExecutable;
174 if (!EBTConfigPlugin.GetDefaultBlenderPath(pathToExecutable))
175 return;
176
177 BlenderOperatorDescription operatorDescription = new BlenderOperatorDescription("bake");
178
179 if (GetOperatorDescription(bakeDialog, resource, m_iNumberOfSamples, operatorDescription))
180 {
181 StartBlenderWithOperator(operatorDescription, m_bRunInBackground);
182 return;
183 }
184
185 Print("Could not create a operatorDescription", LogLevel.WARNING);
186
187 }
188
189 void VoidPrint(void param)
190 {
191 Print(param);
192 }
193
194 //------------------------------------------------------------------------------------------------
195 override void OnResourceContextMenu(notnull array<ResourceName> resources)
196 {
197 if (resources.IsEmpty())
198 {
199 Print("No selected resources", LogLevel.WARNING);
200 return;
201 }
202
203 StartBake(resources[0]);
204 }
205
206 //------------------------------------------------------------------------------------------------
207 [ButtonAttribute("OK")]
208 protected void ButtonOK() {}
209
210 //------------------------------------------------------------------------------------------------
211 override void Configure()
212 {
213 Workbench.ScriptDialog("MLOD Baker Settings", "", this);
214 }
215}
216
217class StartBakeDialog
218{
219 [Attribute("1024", UIWidgets.ComboBox, "", "", enums: ParamEnumTextureSize.FromEnum(), category : "Settings")]
220 int m_iTextureSize;
221
222 //Hidden for now
223 //[Attribute("0", UIWidgets.ComboBox, "", "", enums: ParamEnumSuperSampling.FromEnum(), category : "Settings")]
224 int m_iSuperSampling;
225
226 [Attribute("1024", UIWidgets.ComboBox, "", "", enums: ParamEnumTextureImportSize.FromEnum(), category : "Settings")]
227 int m_iTextureImportSize;
228
229 [Attribute("0.5 0.5 0.5 1", UIWidgets.ColorPicker, "", category: "Settings")]
230 ref Color m_ClearColor = new Color(0.5, 0.5, 0.5, 1);
231
232 [Attribute("2.5", UIWidgets.EditBox, "", category: "Settings")]
233 float m_fCageExtrusion = 2.5;
234
235 [Attribute("0.3", UIWidgets.EditBox, "", category: "Settings")]
236 float m_fRayDistance = 0.3;
237
238 [Attribute("0", UIWidgets.ComboBox, "", "", enums: ParamEnumArray.FromEnum(FixRayMissType), category : "Settings")]
239 FixRayMissType m_eFixRayType;
240
241 [Attribute("0", UIWidgets.ComboBox, "", "", enums: ParamEnumArray.FromEnum(FixRayMissExtents), category : "Settings")]
242 FixRayMissExtents m_eFixRayExtents;
243
244 [Attribute("False", UIWidgets.EditBox, "", category : "Settings")]
245 bool m_bSkipInterior;
246
247
248 string m_sTitle = "";
249
250 //------------------------------------------------------------------------------------------------
251 void StartBakeDialog(string title)
252 {
253 m_sTitle = title;
254 }
255
256 //------------------------------------------------------------------------------------------------
257 [ButtonAttribute("OK")]
258 bool OkButton()
259 {
260 return true;
261 }
262
263 //------------------------------------------------------------------------------------------------
264 [ButtonAttribute("Cancel")]
265 bool ButtonCancel()
266 {
267 return false;
268 }
269}
270
271class StartBakeDialogXOB : StartBakeDialog
272{
273 [Attribute("False", UIWidgets.EditBox, "", category : "Settings")]
274 bool m_bSkipTransparent;
275
276 [Attribute("False", UIWidgets.EditBox, "", category : "Settings")]
277 bool m_bReUV;
278
279 [Attribute(uiwidget: UIWidgets.FileNamePicker, desc: "Root directory to search", params:"unregFolders", category : "New Texture")]
280 string m_sTexturePath;
281
282 [Attribute("", UIWidgets.Auto, desc:"Name of the new texture",category: "New Texture")]
283 string m_sTextureName;
284
285 [Attribute("", UIWidgets.EditBox, "", category: "Settings")]
286 bool m_bCreateNewTexture;
287
288
289}
290
291class StartBakeDialogET : StartBakeDialog
292{
293 [Attribute("", UIWidgets.EditBox, "", category: "Settings")]
294 string m_sNewTextureName;
295}
296
297class BakeInfoRequest : JsonApiStruct
298{
299 string msg;
300
301 void BakeInfoRequest()
302 {
303 RegV("msg");
304 }
305}
306
307static ResourceName GetOpenedPrefab(WorldEditor worldEditor, WorldEditorAPI api)
308{
309 IEntitySource entitySource = null;
310
311 if (worldEditor.IsPrefabEditMode() && api.GetEditorEntityCount() == 2)
312 entitySource = api.GetEditorEntity(1);
313
314 if (entitySource)
315 {
316 BaseContainer ancestor = entitySource.GetAncestor();
317 if (ancestor)
318 return ancestor.GetResourceName();
319 }
320
321 return string.Empty;
322}
323
324
325[WorkbenchToolAttribute(name: "Bake MLOD Texture", description: "Bakes MLOD Texture", wbModules: { "WorldEditor" }, shortcut: "Ctrl+B", awesomeFontCode: 0xf7ec)]
326class BakeMlodTool : WorldEditorTool
327{
328 override void OnActivate()
329 {
330 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
331
332 if (!worldEditor.IsPrefabEditMode())
333 {
334 Print("MLOD Baking is possible only in Edit Mode", LogLevel.WARNING);
335 return;
336 }
337
338 BakeMLODPlugin bakePlugin = BakeMLODPlugin.GetInstance();
339
340 //(E): @"scripts/WorkbenchGameCommon/EnfusionBlenderTools/BakeMLOD.c,387": Can't find variable 'SCR_WorldEditorToolHelper'
341 //ResourceName openedPrefab = SCR_WorldEditorToolHelper.GetPrefabEditModeResourceName();
342
343
344 ResourceName openedPrefab = GetOpenedPrefab(worldEditor, m_API);
345
346 if (openedPrefab)
347 {
348 bakePlugin.StartBake(openedPrefab);
349 return;
350 }
351
352 Print("Prefab not compatible for MLOD baking", LogLevel.WARNING);
353 }
354}
355
356class BakeInfoResponse : JsonApiStruct
357{
358 string Output;
359
360 void BakeInfoResponse()
361 {
362 RegV("Output");
363 }
364}
365
366class BakeInfoDialog
367{
368 [ButtonAttribute("OK")]
369 void OkButton(){}
370}
371
372class BakeInfo : NetApiHandler
373{
374 //------------------------------------------------------------------------------------------------
375 override JsonApiStruct GetRequest()
376 {
377 return new BakeInfoRequest();
378 }
379
380 //------------------------------------------------------------------------------------------------
381 override JsonApiStruct GetResponse(JsonApiStruct request)
382 {
383 BakeInfoRequest req = BakeInfoRequest.Cast(request);
384 BakeInfoResponse response = new BakeInfoResponse();
385
386 BakeInfoDialog dialog = new BakeInfoDialog();
387
388 Workbench.ScriptDialog("MLOD Baker", req.msg, dialog);
389
390 return response;
391 }
392}
393
394class OverrideMeshObjectMaterialRequest : JsonApiStruct
395{
396 string prefabAbsPath;
397 string materialAbsPath;
398 string textureAbsPath;
399 string sourceMaterial;
400
401 void OverrideMeshObjectMaterialRequest()
402 {
403 RegV("prefabAbsPath");
404 RegV("materialAbsPath");
405 RegV("textureAbsPath");
406 RegV("sourceMaterial");
407 }
408}
409
410class OverrideMeshObjectMaterialResponse : JsonApiStruct
411{
412 string Output;
413
414 void OverrideMeshObjectMaterialResponse()
415 {
416 RegV("Output");
417 }
418}
419
420static void BakeCreateEmat(string absPath, array<string> properties)
421{
422 Resource res = BaseContainerTools.CreateContainer("MatPBRBasic");
423 BaseContainer cont = res.GetResource().ToBaseContainer();
424
425 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
426
427 // looping through properties from blender
428 for (int i = 0; i < properties.Count(); i+=2)
429 {
430 if (FilePath.IsAbsolutePath(properties[i+ 1]))
431 {
432 string importPath = properties[i+ 1];
433
434 //Error
435 if (!LoadedProjects.InLoadedProjects(importPath))
436 Print("NO TEXTURE!!!!", LogLevel.WARNING);
437
438 MetaFile meta = resourceManager.GetMetaFile(importPath);
439 properties[i+ 1] = meta.GetResourceID();
440 cont.Set(properties[i], properties[i+ 1]);
441 }
442 else
443 {
444 cont.Set(properties[i], properties[i+ 1]);
445 }
446 }
447
448 BaseContainerTools.SaveContainer(cont, "", absPath);
449
450 resourceManager.RegisterResourceFile(absPath, true);
451 resourceManager.WaitForFile(absPath, 3000);
452
453}
454
455static bool ResourceExistsAndIsRegistered(string absPath)
456{
457 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
458 MetaFile metaFile = resourceManager.GetMetaFile(absPath);
459 string dummyResult;
460
461 if (metaFile)
462 return Workbench.GetAbsolutePath(metaFile.GetResourceID().GetPath(), dummyResult, true);
463
464 return false;
465}
466
467class OverrideMeshObjectMaterial : NetApiHandler
468{
469 //------------------------------------------------------------------------------------------------
470 override JsonApiStruct GetRequest()
471 {
472 return new OverrideMeshObjectMaterialRequest();
473 }
474
475 //------------------------------------------------------------------------------------------------
476 int GetPrefabParamIndex(BaseContainer prefab, string name)
477 {
478 BaseContainerList srcList = prefab.GetObjectArray(EBTContainerFields.components);
479 for (int i = 0; i < srcList.Count(); i++)
480 {
481 prefab = srcList.Get(i);
482 if (prefab.GetClassName() == name)
483 {
484 return i;
485 }
486 }
487 return -1;
488 }
489
490 //------------------------------------------------------------------------------------------------
491 override JsonApiStruct GetResponse(JsonApiStruct request)
492 {
493 OverrideMeshObjectMaterialRequest req = OverrideMeshObjectMaterialRequest.Cast(request);
494
495 //Get Prefab
496 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
497 MetaFile prefabMeta = resourceManager.GetMetaFile(req.prefabAbsPath);
498 Resource resource = Resource.Load(prefabMeta.GetResourceID());
499 BaseContainer prefab = resource.GetResource().ToBaseContainer();
500
501 //Get base xob form the prefab, so we could fetch EXT_MLOD material source from it,
502 //that we will use to define material overide in the prefab
503 BaseContainerList components = prefab.GetObjectArray(EBTContainerFields.components);
504 int meshParamID = GetPrefabParamIndex(prefab, EBTContainerFields.meshObject);
505 BaseContainer prefabMeshObject = components.Get(meshParamID);
506
507 // TODO: handle errors here when we have more then one matches or we don't have matches
508 string sourceMaterialSlot = req.sourceMaterial;
509
510 if (ResourceExistsAndIsRegistered(req.materialAbsPath))
511 {
512 Print("MLOD BAKER: Material Already Exist. Skipping Creation", LogLevel.NORMAL);
513 }
514 else
515 {
516 array<string> materialProps = {"BCRMap", req.textureAbsPath, "MetalnessScale", "0,0", "DisableInteriorProbes", "1"};
517 BakeCreateEmat(req.materialAbsPath, materialProps);
518 }
519
520 MetaFile materialMeta = resourceManager.GetMetaFile(req.materialAbsPath);
521 ResourceName materialResourceName = materialMeta.GetResourceID();
522
523 BaseContainerList prefabMaterials = prefabMeshObject.GetObjectArray("Materials");
524
525 if (prefabMaterials.Count() != 0)
526 {
527 for (int i = 0; i < prefabMaterials.Count(); i++)
528 {
529 BaseContainer material = prefabMaterials.Get(i);
530 ResourceName nameSrc;
531
532 material.Get("SourceMaterial", nameSrc);
533
534 if (nameSrc == sourceMaterialSlot)
535 {
536 ResourceName nameAssgn;
537 material.Get("AssignedMaterial", nameAssgn);
538 if (nameAssgn == materialResourceName)
539 {
540 Print("MLOD BAKER: Material Already Assigned. Skipping Assignment", LogLevel.NORMAL);
541 break;
542 }
543
544 WorldEditor worldEditorModule = Workbench.GetModule(WorldEditor);
545 WorldEditorAPI api = worldEditorModule.GetApi();
546
547 if (!api)
548 {
549 Workbench.OpenModule(WorldEditor);
550 api = worldEditorModule.GetApi();
551 }
552
553 ResourceName openedPrefab = GetOpenedPrefab(worldEditorModule, api);
554 if (openedPrefab != prefabMeta.GetResourceID())
555 worldEditorModule.SetOpenedResource(prefabMeta.GetResourceID());
556
557 bool manageEditAction = !api.IsDoingEditAction();
558
559 if (manageEditAction)
560 api.BeginEntityAction();
561
562 api.SetVariableValue(prefab, {ContainerIdPathEntry("MeshObject"), ContainerIdPathEntry("Materials", i)}, "AssignedMaterial", materialResourceName);
563 api.SaveEntityTemplate(prefab);
564
565 if (manageEditAction)
566 api.EndEntityAction();
567 break;
568 }
569 }
570 }
571 else
572 {
573 WorldEditor worldEditorModule = Workbench.GetModule(WorldEditor);
574 WorldEditorAPI api = worldEditorModule.GetApi();
575
576 if (!api)
577 {
578 Workbench.OpenModule(WorldEditor);
579 api = worldEditorModule.GetApi();
580 }
581
582 ResourceName openedPrefab = GetOpenedPrefab(worldEditorModule, api);
583 if (openedPrefab != prefabMeta.GetResourceID())
584 worldEditorModule.SetOpenedResource(prefabMeta.GetResourceID());
585
586 bool manageEditAction = !api.IsDoingEditAction();
587
588 if (manageEditAction)
589 api.BeginEntityAction();
590
591 api.CreateObjectArrayVariableMember(prefab, {ContainerIdPathEntry("MeshObject")}, "Materials", "MaterialAssignClass", 0);
592 api.SetVariableValue(prefab, {ContainerIdPathEntry("MeshObject"), ContainerIdPathEntry("Materials", 0)}, "SourceMaterial", sourceMaterialSlot);
593 api.SetVariableValue(prefab, {ContainerIdPathEntry("MeshObject"), ContainerIdPathEntry("Materials", 0)}, "AssignedMaterial", materialResourceName);
594
595 if (manageEditAction)
596 api.EndEntityAction();
597
598 api.SaveEntityTemplate(prefab);
599
600 }
601
602 OverrideMeshObjectMaterialResponse response = new OverrideMeshObjectMaterialResponse();
603
604 return response;
605 }
606}
607#endif
override JsonApiStruct GetResponse(JsonApiStruct request)
void ParamEnum(string key, string value, string desc="")
Definition attributes.c:25
ParamEnum Managed FromEnum(typename e)
Definition attributes.c:20
void ContainerIdPathEntry(string propertyName, int index=-1)
Definition worldEditor.c:30
ExportTerrainRequest Output
GenerateFlowMaps WorkbenchPlugin WorkbenchPluginAttribute("Regenerate river flow-maps", "Generate and save/overwrite river flow-maps", "", "", {"WorldEditor"}, "", 0xf773)
Definition FlowmapTool.c:59
int GetPrefabParamIndex(BaseContainer prefab, string name)
SCR_AICombatMoveRequestBase GetRequest()
ResourceName resourceName
Definition SCR_AIGroup.c:66
override void OnActivate()
bool ButtonCancel()
bool ButtonOK()
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
override void Configure()
class WorkbenchDialog_AbortRetryIgnore ButtonAttribute("OK", true)
base classes for filtering in server browser
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
proto external string ToString()
Plain C++ pointer, no weak pointers, no memory management.