Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_FloatersFixerPlugin.c
Go to the documentation of this file.
1#ifdef WORKBENCH
2// [WorkbenchPluginAttribute(name: "Floaters Fixer", wbModules: { "WorldEditor" }, shortcut: "Ctrl+Alt+Page Down", awesomeFontCode: 0xE069)] // 0xE069 = plane-slash
3class SCR_FloatersFixerPlugin : WorkbenchPlugin
4{
5 [Attribute(defvalue: "1", desc: "Set object's origin from OBJECTS or terrain (2× slower as it uses Trace)")]
6 protected bool m_bSetOnTerrainAndEntitiesSurface;
7
8 [Attribute(defvalue: "50", desc: "Trace origin's distance from above the object/terrain", uiwidget: UIWidgets.Slider, params: "10 500 10")]
9 protected int m_iTraceOriginDistance;
10
11 [Attribute(defvalue: "0", desc: "If set, uses the Prefab's vertical offset range; otherwise, uses below settings")]
12 protected bool m_bUsePrefabVerticalOffset;
13
14 [Attribute(defvalue: "1", desc: "If set, uses the Prefab's align to normal setting; otherwise uses Align To Normal Override")]
15 protected bool m_bUsePrefabAlignToNormal;
16
17 [Attribute(defvalue: "0", desc: "Forces Align To Normal; requires Use Prefab Align To Normal above to be off")]
18 protected bool m_bAlignToNormalOverride;
19
20 protected BaseWorld m_BaseWorld;
21
22 protected static const ResourceName BUSH_BASE = "{D7163D1B571F4C0C}Prefabs/Vegetation/Core/Bush_Base.et";
23 protected static const ResourceName TREE_BASE = "{388AE316D09D0680}Prefabs/Vegetation/Core/Tree_Base.et";
24 protected static const int MANY_ENTITIES_THRESHOLD = 10; // threshold between detailed logs and batch logs (inclusive, 1-10 = detailed)
25
26 //------------------------------------------------------------------------------------------------
27 override void Run()
28 {
29 if (!Init())
30 return;
31
32 Print("Floaters Fixer - Run method started", LogLevel.NORMAL);
33
34 IEntity entity;
35 IEntitySource entitySource;
36 BaseContainerList editorData;
37 BaseContainer firstEditorData;
38 vector entityPos, entityPosOffset, entityYawPitchRoll, normalAngles, randomVerticalOffset;
39 float altitude, terrainY;
40 bool alignToSurfaceNormal;
41 TraceParam traceParam = new TraceParam();
42 float traceRatio;
43 float minVerticalOffset, maxVerticalOffset, maxPitch, maxRoll;
44
45 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
46
47 int selectedEntitiesCount = worldEditorAPI.GetSelectedEntitiesCount();
48 bool manyEntities = selectedEntitiesCount > MANY_ENTITIES_THRESHOLD;
49 RandomGenerator randomGenerator = new RandomGenerator();
50
51 if (selectedEntitiesCount < 1)
52 return;
53
54 int firstTick = System.GetTickCount();
55 worldEditorAPI.BeginEntityAction();
56 for (int i; i < selectedEntitiesCount; i++)
57 {
58 entitySource = worldEditorAPI.GetSelectedEntity(i);
59 if (!entitySource)
60 continue;
61
62 entity = worldEditorAPI.SourceToEntity(entitySource);
63 editorData = null;
64 alignToSurfaceNormal = m_bAlignToNormalOverride;
65 minVerticalOffset = 0;
66 maxVerticalOffset = 0;
67 maxPitch = 0;
68 maxRoll = 0;
69
70 editorData = entitySource.GetObjectArray("editorData");
71 if (editorData && editorData.Count() /* > 0 */)
72 {
73 firstEditorData = editorData.Get(0);
74
75 randomVerticalOffset = vector.Zero;
76 firstEditorData.Get("randomVertOffset", randomVerticalOffset);
77 minVerticalOffset = randomVerticalOffset[0];
78 maxVerticalOffset = randomVerticalOffset[1];
79
80 firstEditorData.Get("randomPitchAngle", maxPitch);
81 firstEditorData.Get("randomRollAngle", maxRoll);
82
83 if (!m_bAlignToNormalOverride && m_bUsePrefabAlignToNormal)
84 firstEditorData.Get("alignToNormal", alignToSurfaceNormal);
85 }
86
87 // --------------------------------------------------
88 // get terrainY
89 // if alignToNormal or if aboveEntities
90 // trace
91 // set new Y
92 // set normal
93 // if alignToNormal
94 // align to normal
95 // set pos
96 // --------------------------------------------------
97
98 // origin
99 entityPosOffset = vector.Zero;
100 entityPos = entity.GetOrigin();
101 entityPosOffset = entityPos - SCR_BaseContainerTools.GetLocalCoords(entitySource.GetParent(), entityPos);
102
103 // altitude
104 terrainY = worldEditorAPI.GetTerrainSurfaceY(entityPos[0], entityPos[2]);
105 altitude = entityPos[1] - terrainY;
106 if (altitude < 0)
107 entityPos[1] = terrainY;
108
109 // trace if alignToNormal or Entities check
110 if (m_bUsePrefabAlignToNormal || alignToSurfaceNormal || m_bSetOnTerrainAndEntitiesSurface)
111 {
112 traceParam.Exclude = entity;
113
114 if (m_bSetOnTerrainAndEntitiesSurface)
115 {
116 traceParam.Start = { entityPos[0], entityPos[1] + m_iTraceOriginDistance, entityPos[2] };
117 traceParam.End = { entityPos[0], terrainY, entityPos[2] };
118 traceParam.Flags = TraceFlags.ENTS | TraceFlags.WORLD;
119
120 traceRatio = m_BaseWorld.TraceMove(traceParam, FilterNonVegetationCallback);
121
122 if (!manyEntities)
123 {
124 Print("----- Tracing -----", LogLevel.NORMAL);
125 Print(string.Format(".OBJ %1", entityPos), LogLevel.NORMAL);
126 Print(string.Format("FROM %1", traceParam.Start), LogLevel.NORMAL);
127 Print(string.Format("..TO %1", traceParam.End), LogLevel.NORMAL);
128 Print(string.Format("DIST %1", traceParam.Start[1] - terrainY), LogLevel.NORMAL);
129 Print(string.Format("DONE %1pct (%2m)", Math.Round(traceRatio * 10000) * 0.01, (traceParam.Start[1] - terrainY) * traceRatio), LogLevel.NORMAL);
130 }
131 }
132 else // terrain only
133 {
134 traceParam.Start = { entityPos[0], terrainY + 1, entityPos[2] };
135 traceParam.End = { entityPos[0], terrainY - 1, entityPos[2] };
136 traceParam.Flags = TraceFlags.WORLD;
137
138 traceRatio = m_BaseWorld.TraceMove(traceParam, null);
139 }
140
141 if (alignToSurfaceNormal)
142 {
143 normalAngles = GetXYZAnglesFromNormal(entity, traceParam.TraceNorm);
144 worldEditorAPI.SetVariableValue(entitySource, null, "angles", normalAngles.ToString(false));
145 }
146
147 if (m_bSetOnTerrainAndEntitiesSurface)
148 entityPos[1] = traceParam.Start[1] - (traceParam.Start[1] - traceParam.End[1]) * traceRatio;
149 else
150 entityPos[1] = terrainY;
151 }
152
153 entityPos -= entityPosOffset;
154
155 // ATL vs World
156 if (entity.GetFlags() & EntityFlags.RELATIVE_Y)
157 entityPos[1] = entityPos[1] - terrainY;
158
159 if (m_bUsePrefabVerticalOffset && (minVerticalOffset != 0 || maxVerticalOffset != 0))
160 entityPos[1] = entityPos[1] + randomGenerator.RandFloatXY(minVerticalOffset, maxVerticalOffset);
161
162 worldEditorAPI.SetVariableValue(entitySource, null, "coords", entityPos.ToString(false));
163 }
164 worldEditorAPI.EndEntityAction();
165
166 Print(string.Format("Fixed %1 floating entities in %2ms", selectedEntitiesCount, System.GetTickCount() - firstTick), LogLevel.NORMAL);
167 Print("Floaters Fixer - Run method ended", LogLevel.NORMAL);
168 }
169
170 //------------------------------------------------------------------------------------------------
171 protected bool Init()
172 {
173 if (!SCR_Global.IsEditMode())
174 {
175 Print("Floaters Fixer - Run method stopped because non-Workbench run", LogLevel.NORMAL);
176 return false;
177 }
178
179 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
180 if (!worldEditor)
181 {
182 Print("Floaters Fixer - Run method stopped because… World Editor is unavailable from World Editor? o_o", LogLevel.WARNING);
183 return false;
184 }
185
186 if (worldEditor.IsPrefabEditMode())
187 {
188 Print("Floaters Fixer - Run method stopped because World Editor is in Prefab edit mode", LogLevel.NORMAL);
189 return false;
190 }
191
192 WorldEditorAPI worldEditorAPI = worldEditor.GetApi();
193 if (!worldEditorAPI)
194 {
195 Print("Floaters Fixer - Run method stopped because World Editor API was not found", LogLevel.WARNING);
196 return false;
197 }
198
199 BaseWorld baseWorld = worldEditorAPI.GetWorld();
200 if (!baseWorld)
201 {
202 Print("Floaters Fixer - Run method stopped because base world was not found", LogLevel.WARNING);
203 return false;
204 }
205
206 m_BaseWorld = baseWorld;
207
208 return true;
209 }
210
211 //------------------------------------------------------------------------------------------------
212 protected bool FilterNonVegetationCallback(notnull IEntity entity, vector start = "0 0 0", vector dir = "0 0 0")
213 {
214 if (entity.IsInherited(GenericTerrainEntity))
215 return true;
216
217 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
218 IEntitySource source = worldEditorAPI.EntityToSource(entity);
219 if (!source)
220 return false;
221
222 string resourceName = SCR_BaseContainerTools.GetTopMostAncestor(source).GetResourceName();
223 return
224 resourceName != BUSH_BASE &&
225 resourceName != TREE_BASE;
226 }
227
228 //------------------------------------------------------------------------------------------------
229 protected vector GetXYZAnglesFromNormal(IEntity entity, vector normal)
230 {
231 // TODO
232 vector worldTransform[4];
233 entity.GetWorldTransform(worldTransform);
234 Math3D.DirectionAndUpMatrix(worldTransform[2], normal, worldTransform);
235
236 // Print("normal = " + normal, LogLevel.DEBUG);
237 // Print("angles = " + Math3D.MatrixToAngles(worldTransform), LogLevel.DEBUG);
238
239 return normal;
240 }
241
242 //------------------------------------------------------------------------------------------------
243 override void Configure()
244 {
245 Workbench.ScriptDialog("Configure 'Floaters Finder' plugin", "", this);
246 }
247
248 //------------------------------------------------------------------------------------------------
249 [ButtonAttribute("Close", true)]
250 protected bool ButtonOK()
251 {
252 return true;
253 }
254}
255#endif // WORKBENCH
override void Init()
ResourceName resourceName
Definition SCR_AIGroup.c:66
override void Run()
bool ButtonOK()
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
enum EVehicleType IEntity
override void Configure()
class WorkbenchDialog_AbortRetryIgnore ButtonAttribute("OK", true)
proto external EntityFlags GetFlags()
proto external vector GetOrigin()
proto external void GetWorldTransform(out vector mat[])
See IEntity::GetTransform.
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
EntityFlags
Various entity flags.
Definition EntityFlags.c:14
TraceFlags
Definition TraceFlags.c:13