Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_EditorImageGeneratorEntity.c
Go to the documentation of this file.
1[EntityEditorProps(category: "GameScripted/Editor", description: "Manager of image generators", color: "255 0 0 255", dynamicBox: true)]
2class SCR_EditorImageGeneratorEntityClass: GenericEntityClass
3{
4};
5
8
13{
14 [Attribute("800")]
15 protected int m_iImageWidth;
16
17 [Attribute("600")]
18 protected int m_iImageHeight;
19
20 [Attribute(desc: "When enabled, the system will not iterate through prefabs on its own.\nInstead, you'll have to press 'Space' to continue to next prefab.")]
21 protected bool m_bManualProgress;
22
23 [Attribute(desc: "When enabled, the system will not check for correct viewport resolution and screenshot format upon start, and not capture any screenshots.\nFOR DEBUGGING ONLY!")]
24 protected bool m_bDebugMode;
25
26#ifdef WORKBENCH
27 protected int m_iInit = 0;
28 protected ref SCR_SortedArray<SCR_EditorImagePositionEntity> m_aPositions = new SCR_SortedArray<SCR_EditorImagePositionEntity>();
29 protected ref array<ref SCR_EditorImageGeneratorPrefab> m_aSelectedPrefabs = {};
30 protected int m_iSelectedPrefabsCount;
31 protected static ref array<vector> s_aSelectedPositions = {};
32 protected float m_fTime;
33 protected float m_fTimeNext = -1;
34 protected float m_fTimeRemaining;
35 protected int m_iPrefabIndex = -1;
36 protected SCR_EditorImageGeneratorPrefab m_CurrentPrefab;
37 protected bool m_bIsScreenshotMade;
38
39 //------------------------------------------------------------------------------------------------
40 static SCR_EditorImageGeneratorEntity GetInstance()
41 {
42 return SCR_EditorImageGeneratorEntity.Cast(GetGame().FindEntity("SCR_EditorImageGeneratorEntity"));
43 }
44
45 //------------------------------------------------------------------------------------------------
46 SCR_EditorImagePositionEntity FindSuitablePosition(array<EEditableEntityLabel> labels)
47 {
48 SCR_EditorImagePositionEntity position;
49 for (int i = m_aPositions.Count() - 1; i >= 0; i--)
50 {
51 position = m_aPositions.GetValue(i);
52 if (position.IsSuitable(labels) && IsPositionSelected(position))
53 return position;
54 }
55 return null;
56 }
57
58 //------------------------------------------------------------------------------------------------
59 protected bool IsPositionSelected(SCR_EditorImagePositionEntity position)
60 {
61 if (s_aSelectedPositions.IsEmpty())
62 return true;
63
64 for (int i = 0, count = s_aSelectedPositions.Count(); i < count; i++)
65 {
66 if (vector.DistanceSq(position.GetOrigin(), s_aSelectedPositions[i]) < 1)
67 return true;
68 }
69 return false;
70 }
71
72 //------------------------------------------------------------------------------------------------
73 void AddPosition(SCR_EditorImagePositionEntity position)
74 {
75 m_aPositions.Insert(position.GetPriority(), position);
76 }
77
78 //------------------------------------------------------------------------------------------------
79 static void AddSelectedPosition(SCR_EditorImagePositionEntity position)
80 {
81 s_aSelectedPositions.Insert(position.GetOrigin());
82 }
83
84 //------------------------------------------------------------------------------------------------
90 protected void AddSelectedPrefab(ResourceName prefab, string filePath)
91 {
92 string ext;
93 FilePath.StripExtension(prefab, ext);
94 if (ext != "et")
95 return;
96
97 Resource res = Resource.Load(prefab);
98 if (!res || !res.IsValid())
99 return;
100
101 IEntityComponentSource editableEntitySource = SCR_EditableEntityComponentClass.GetEditableEntitySource(res);
102 if (!editableEntitySource)
103 return;
104
105 SCR_EditableEntityUIInfo info = SCR_EditableEntityComponentClass.GetInfo(editableEntitySource);
106 if (!info)
107 {
108 Print(string.Format("Prefab @\"%1\" does not have UI info defined in SCR_EditableEntityComponent!", prefab.GetPath()), LogLevel.WARNING);
109 return;
110 }
111
112 ResourceName imagePath = info.GetImage();
113 if (imagePath.IsEmpty())
114 {
115 Print(string.Format("Prefab @\"%1\" does not have image path defined in UI info of SCR_EditableEntityComponent!", prefab.GetPath()), LogLevel.WARNING);
116 return;
117 }
118
119 array<EEditableEntityLabel> labels = {};
120 info.GetEntityLabels(labels);
121 SCR_EditorImagePositionEntity position = FindSuitablePosition(labels);
122 if (!position)
123 {
124 if (s_aSelectedPositions.IsEmpty())
125 {
126 string labelsLine;
127 foreach (int i, EEditableEntityLabel label: labels)
128 {
129 if (i > 0)
130 labelsLine += ", ";
131
132 labelsLine += typename.EnumToString(EEditableEntityLabel, label);
133 }
134 Print(string.Format("No suitable position found for @\"%1\" with labels %2!", prefab, labelsLine), LogLevel.WARNING);
135 }
136 return;
137 }
138
139 imagePath = FilePath.StripExtension(imagePath.GetPath());
140 m_aSelectedPrefabs.Insert(new SCR_EditorImageGeneratorPrefab(prefab, imagePath, position));
141 }
142
143 //------------------------------------------------------------------------------------------------
144 protected void RequestClose()
145 {
146 GetGame().RequestClose();
147 }
148
149 //------------------------------------------------------------------------------------------------
150 protected bool Init()
151 {
152 if (m_iInit <= 1 && !SCR_Global.IsEditMode(this))
153 {
154 if (m_iInit == 1)
155 {
156 //--- Validate screen size
157 if (!m_bDebugMode)
158 {
159 float screenW = GetGame().GetWorkspace().GetWidth();
160 float screenH = GetGame().GetWorkspace().GetHeight();
161 if (screenW != m_iImageWidth || screenH != m_iImageHeight)
162 {
163 Debug.Error2(Type().ToString(), string.Format("Cannot generate images! Current resolution is %1x%2, expected %3x%4!\n", screenW, screenH, m_iImageWidth, m_iImageHeight));
164 GetGame().GetCallqueue().CallLater(RequestClose, false, 1);
165 }
166 }
167
168 //--- Validate selected prefabs
169 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
170 worldEditor.GetResourceBrowserSelection(AddSelectedPrefab, true);
171 if (m_aSelectedPrefabs.IsEmpty())
172 {
173 Debug.Error2(Type().ToString(), "No suitable prefabs selected!\n");
174 GetGame().GetCallqueue().CallLater(RequestClose, false, 1);
175 }
176 m_iSelectedPrefabsCount = m_aSelectedPrefabs.Count();
177
178
179 //--- Set initial delay
180 m_fTimeNext = m_fTime + 1;
181
182 if (s_aSelectedPositions.IsEmpty())
183 Print(string.Format("Initiating image generation for %1 prefab(s).", m_iSelectedPrefabsCount), LogLevel.DEBUG);
184 else
185 Print(string.Format("Initiating image generation for %1 prefab(s) on %2 pre-selected position(s).", m_iSelectedPrefabsCount, s_aSelectedPositions.Count()), LogLevel.DEBUG);
186 }
187 m_iInit++; //--- Wait one frame before evaluating screen dimensions, otherwise they will still be default 128x128
188 }
189 return m_iInit > 1;
190 }
191
192 //------------------------------------------------------------------------------------------------
193 override void EOnFrame(IEntity owner, float timeSlice)
194 {
195 if (!Init())
196 return;
197
198 bool canContinue;
199 if (m_fTimeNext != -1 || !m_CurrentPrefab)
200 {
201 canContinue = m_fTime > m_fTimeNext;
202 }
203 else if (Debug.KeyState(KeyCode.KC_SPACE))
204 {
205 Debug.ClearKey(KeyCode.KC_SPACE);
206 canContinue = true;
207 }
208
209 if (canContinue)
210 {
211 //--- Take a screenshot of existing prefab
212 if (m_CurrentPrefab && !m_bIsScreenshotMade)
213 {
214 m_bIsScreenshotMade = true;
215 if (!m_bDebugMode)
216 {
217 string addonName = SCR_AddonTool.GetResourceLastAddon(m_CurrentPrefab.m_Prefab);
218 addonName = SCR_AddonTool.ToFileSystem(addonName);
219 System.MakeScreenshot(addonName + m_CurrentPrefab.m_ImagePath);
220 Print(string.Format("Image of prefab '%1' at position '%2' saved to @\"%3.png\"", FilePath.StripPath(m_CurrentPrefab.m_Prefab), m_CurrentPrefab.m_Position.GetName(), m_CurrentPrefab.m_ImagePath), LogLevel.DEBUG);
221 return; //--- Wait until next frame to give MakeScreenshot function enough time to actually capture the screen
222 }
223 else
224 {
225 Print(string.Format("SIMULATION: Image of prefab '%1' at position '%2' would be saved to @\"%3.png\"", FilePath.StripPath(m_CurrentPrefab.m_Prefab), m_CurrentPrefab.m_Position.GetName(), m_CurrentPrefab.m_ImagePath), LogLevel.VERBOSE);
226 }
227 }
228
229 //--- Next prefab
230 m_iPrefabIndex++;
231 if (m_iPrefabIndex >= m_iSelectedPrefabsCount)
232 {
233 GetGame().GetCallqueue().CallLater(RequestClose, false, 1);
234 return;
235 }
236
237 //--- Delete existing prefab
238 if (m_CurrentPrefab)
239 m_CurrentPrefab.m_Position.DeactivatePosition();
240
241 //--- Create a new prefab
242 m_bIsScreenshotMade = false;
243 SCR_EditorImageGeneratorPrefab currentPrefab = m_aSelectedPrefabs[m_iPrefabIndex];
244 if (currentPrefab.m_Position.ActivatePosition(currentPrefab.m_Prefab))
245 {
246 m_CurrentPrefab = currentPrefab;
247
249 m_fTimeNext = -1;
250 else
251 m_fTimeNext = m_fTime + currentPrefab.m_Position.GetDelay();
252 }
253 else
254 {
255 m_fTimeNext = 0;
256 }
257
258 m_fTimeRemaining = 0;
259 for (int i = m_iPrefabIndex, count = m_aSelectedPrefabs.Count(); i < count; i++)
260 {
261 m_fTimeRemaining += m_aSelectedPrefabs[i].m_Position.GetDelay();
262 }
263 }
264
265 //--- Show progress
266 DbgUI.Begin("SCR_EditorImageGeneratorEntity");
267 if (m_CurrentPrefab)
268 {
269 DbgUI.Text(string.Format("%1\n\n", m_CurrentPrefab.m_Prefab.GetPath()));
270 DbgUI.Text(string.Format("Progress: %1 of %2", m_iPrefabIndex, m_iSelectedPrefabsCount));
271
272 if (m_fTimeNext == -1)
273 DbgUI.Text("Press 'Space' to take screenshot and continue to next prefab\n\n");
274 else
275 DbgUI.Text(string.Format("Estimated remaining time: %1", SCR_FormatHelper.GetTimeFormatting(m_fTimeRemaining, ETimeFormatParam.DAYS | ETimeFormatParam.HOURS)));
276 }
277 else
278 {
279 DbgUI.Text("Initializing...");
280 }
281 DbgUI.End();
282
283 m_fTime += timeSlice;
284 m_fTimeRemaining -= timeSlice;
285 }
286
287 //------------------------------------------------------------------------------------------------
288 void SCR_EditorImageGeneratorEntity(IEntitySource src, IEntity parent)
289 {
290 SetName("SCR_EditorImageGeneratorEntity");
292
293 if (SCR_Global.IsEditMode(this))
294 s_aSelectedPositions.Clear();
295 }
296
297 //------------------------------------------------------------------------------------------------
298 override int _WB_GetAfterWorldUpdateSpecs(IEntitySource src)
299 {
300 return EEntityFrameUpdateSpecs.CALL_ALWAYS;
301 }
302
303 //------------------------------------------------------------------------------------------------
304 override void _WB_AfterWorldUpdate(float timeSlice)
305 {
306 WorldEditorAPI api = _WB_GetEditorAPI();
307 if (!api.IsEntitySelected(api.EntityToSource(this)))
308 return;
309
310 int screenW = api.GetScreenWidth();
311 int screenH = api.GetScreenHeight();
312
313 string textCurrent = string.Format("Current resolution: %1x%2", screenW, screenH);
314 string textTarget = string.Format("Target resolution: %1x%2", m_iImageWidth, m_iImageHeight);
315
316 int color = Color.RED;
317 if (screenW == m_iImageWidth && screenH == m_iImageHeight)
318 color = Color.GREEN;
319 else if (screenW == m_iImageWidth || screenH == m_iImageHeight)
320 color = Color.ORANGE;
321
322 DebugTextScreenSpace.Create(GetWorld(), textCurrent, DebugTextFlags.ONCE, 0, 0, 18, color, Color.BLACK);
323 DebugTextScreenSpace.Create(GetWorld(), textTarget, DebugTextFlags.ONCE, 0, 18, 18, Color.WHITE, Color.BLACK);
324 }
325
326 //------------------------------------------------------------------------------------------------
327 override void _WB_GetBoundBox(inout vector min, inout vector max, IEntitySource src)
328 {
329 GetWorld().GetBoundBox(min, max);
330 }
331
332 /*
333 //------------------------------------------------------------------------------------------------
336 protected void CreatePreviewImageFile()
337 {
338 string sourceFile = FilePath.ReplaceExtension(FilePath.StripPath(targetPath), m_sImagePlaceholderExt);
339 if (sourceFile.IsEmpty() || m_sImagePlaceholderSource.IsEmpty())
340 return;
341
342 //--- Read source meta file
343 string placeholderPath = m_ImagePlaceholder.GetPath();
344 string absolutePath;
345 Workbench.GetAbsolutePath(placeholderPath, absolutePath);
346
347 //--- Create directory
348 string imageDirectoryPath = FilePath.StripFileName(targetPath);
349 if (!config.CreateDirectoryFor(imageDirectoryPath, addonName))
350 return;
351
352 //--- Copy texture source
353 FileIO.CopyFile(m_sImagePlaceholderPath + m_sImagePlaceholderSource, addonName + FilePath.StripFileName(targetPath) + sourceFile);
354
355 //--- Register the file
356 Workbench.GetAbsolutePath(addonName + FilePath.StripFileName(targetPath) + sourceFile, absolutePath, false);
357 MetaFile metaContainer = m_ResourceManager.RegisterResourceFile(absolutePath);
358 if (metaContainer)
359 {
360 //--- Update meta file
361 targetPath = metaContainer.GetResourceID();
362 BaseContainerList configurations = metaContainer.GetObjectArray("Configurations");
363 if (configurations)
364 {
365 configurations.Get(0).Set("ColorSpace", "ToSRGB"); //--- Assume PC is the first
366 metaContainer.Save();
367 Print(string.Format("Editable entity preview image ADDED: @\"%1\"", targetPath), LogLevel.DEBUG);
368 return;
369 }
370 }
371 }
372 */
373#endif
374};
375
376class SCR_EditorImageGeneratorPrefab
377{
378 ResourceName m_Prefab;
379 string m_ImagePath;
380 SCR_EditorImagePositionEntity m_Position;
381
382 void SCR_EditorImageGeneratorPrefab(ResourceName prefab, string imagePath, SCR_EditorImagePositionEntity position)
383 {
384 m_Prefab = prefab;
385 m_ImagePath = imagePath;
386 m_Position = position;
387 }
388};
override void Init()
EEditableEntityLabel
ETimeFormatParam
ArmaReforgerScripted GetGame()
Definition game.c:1398
enum SCR_ECompassType EntityEditorProps(category:"GameScripted/Gadgets", description:"Compass", color:"0 0 255 255")
Prefab data class for compass component.
vector position
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
int Type
event void _WB_GetBoundBox(inout vector min, inout vector max, IEntitySource src)
Editor needs to know a bound box of entity (For ray-casting, visualizers etc.). You can return any cu...
event void _WB_AfterWorldUpdate(float timeSlice)
Called after updating world in Workbench. The entity must be visible in frustum, selected or named....
proto external WorldEditorAPI _WB_GetEditorAPI()
This returns world editor API, which is safe to use from editor events bellow.
event int _WB_GetAfterWorldUpdateSpecs(IEntitySource src)
Called after _WB_OnInit or also later when editor needs to know whether _WB_AfterWorldUpdate needs to...
void IEntity(IEntitySource src, IEntity parent)
protected script Constructor
proto external EntityEvent SetEventMask(EntityEvent e)
void EOnFrame(IEntity owner, float timeSlice)
proto external BaseWorld GetWorld()
proto external void SetName(string name)
int GetEntityLabels(out notnull array< EEditableEntityLabel > entityLabels)
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
DebugTextFlags
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
EntityEvent
Various entity events.
Definition EntityEvent.c:14
KeyCode
Definition KeyCode.c:13
proto external string ToString()
Plain C++ pointer, no weak pointers, no memory management.
void Debug()
Definition Types.c:327