Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_LineGeneratorBaseEntity.c
Go to the documentation of this file.
4
8class SCR_LineGeneratorBaseEntity : SCR_GeneratorBaseEntity
9{
10 /*
11 Shape Usage
12 */
13
14 [Attribute(defvalue: "0 0 0", desc: "-/+ meanings:\n- X: Left/Right (POINT relative)\n- Y: Down/Up (SHAPE relative)\n- Z: Backward/Forward (POINT relative)\n", params: "-100 100", category: "Shape Usage")]
15 protected vector m_vShapeOffset;
16
17 [Attribute(defvalue: "1", desc: "Use Y offset in shape space (perpendicular to shape's relative Y), otherwise use in point space (perpendicular to point's next point direction)", category: "Shape Usage")]
18 protected bool m_bYOffsetInShapeSpace;
19
20 [Attribute(uiwidget: UIWidgets.None)] // obsolete, kept for Prefabs and layers retrocompatibility (since 2024-10-01)
21 protected float m_fShapeOffset;
22
23 [Attribute(defvalue: "0.95", desc: "Safety distance from the original spline in which no points can exist\nDistance is measured in 2D or 3D based on Next Point Measurement XZ below and in percentage of Shape Offset above\n- does not apply to Polyline\n- be aware that using Z offset may remove many points", uiwidget: UIWidgets.Slider, params: "0 1 0.01", precision: 2, category: "Shape Usage")]
24 protected float m_fSplineSafetyDistanceRatio;
25
26 [Attribute(defvalue: "1", desc: "Offset shape is snapped to the ground", category: "Shape Usage")]
27 protected bool m_bSnapOffsetShapeToTheGround;
28
29 [Attribute(defvalue: "1", desc: "The \"next point\" distance is measured in 2D (XZ plane) instead of 3D", category: "Shape Usage")]
30 protected bool m_bNextPointMeasurementXZ;
31
32#ifdef WORKBENCH
33 protected ref SCR_ShapeNextPointHelper m_ShapeNextPointHelper;
34 protected ref SCR_DebugShapeManager m_OffsetDebugShapeManager;
35 protected ref array<Shape> m_aOffsetShapeShapes = {};
36 protected bool m_bIsSelectedAlone;
37 protected bool m_bForceOffsetShapeShapesRefresh;
38
39 //------------------------------------------------------------------------------------------------
40 protected void ResetShapeNextPointHelper()
41 {
42 m_ShapeNextPointHelper = null;
43
44 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
45 if (!worldEditorAPI)
46 return;
47
48 IEntitySource newGeneratorSource = worldEditorAPI.EntityToSource(this);
49 if (!newGeneratorSource)
50 return; // huh?
51
52 if (!m_ParentShapeSource)
53 return;
54
55 ShapeEntity shapeEntity = ShapeEntity.Cast(worldEditorAPI.SourceToEntity(m_ParentShapeSource));
56 if (!shapeEntity)
57 return;
58
59 array<vector> offsetAnchorPoints = {};
60 array<vector> offsetTesselatedPoints = {};
61 array<int> anchorIndices = {};
62 if (!SCR_ParallelShapeHelper.GetAnchorsAndTesselatedPointsFromShape(shapeEntity, m_vShapeOffset, m_bYOffsetInShapeSpace, offsetAnchorPoints, offsetTesselatedPoints, anchorIndices))
63 {
64 PrintFormat("[SCR_LineGeneratorBaseEntity.ResetShapeNextPointHelper] error getting shape points from shape with %1 points - %2", shapeEntity.GetPointCount(), Debug.GetEntityLinkString(shapeEntity), level: LogLevel.WARNING);
65 return;
66 }
67
68 if (m_bSnapOffsetShapeToTheGround)
69 {
70 BaseWorld world = shapeEntity.GetWorld();
71 if (world)
72 {
73 vector tempVector;
74 foreach (int i, vector point : offsetAnchorPoints)
75 {
76 tempVector = shapeEntity.CoordToParent(point);
77 tempVector[1] = world.GetSurfaceY(tempVector[0], tempVector[2]) + m_vShapeOffset[1];
78 tempVector = shapeEntity.CoordToLocal(tempVector);
79
80 if (point[0] == tempVector[0] && point[2] == tempVector[2])
81 point[1] = tempVector[1]; // avoids changing point's x/z
82 else
83 point = tempVector; // unless shape is not vector.Up aligned
84
85 offsetAnchorPoints[i] = point;
86 }
87
88 foreach (int i, vector point : offsetTesselatedPoints)
89 {
90 tempVector = shapeEntity.CoordToParent(point);
91 tempVector[1] = world.GetSurfaceY(tempVector[0], tempVector[2]) + m_vShapeOffset[1];
92 tempVector = shapeEntity.CoordToLocal(tempVector);
93
94 if (point[0] == tempVector[0] && point[2] == tempVector[2])
95 point[1] = tempVector[1]; // avoids changing point's x/z
96 else
97 point = tempVector; // unless shape is not vector.Up aligned
98
99 offsetTesselatedPoints[i] = point;
100 }
101 }
102 }
103
104 if (m_vShapeOffset != vector.Zero)
105 m_OffsetDebugShapeManager = new SCR_DebugShapeManager();
106 else
107 m_OffsetDebugShapeManager = null;
108
109 if (m_fSplineSafetyDistanceRatio != 0 && (m_vShapeOffset[0] != 0 || m_vShapeOffset[2] != 0) && SplineShapeEntity.Cast(shapeEntity) != null) // isSpline
110 {
111 SCR_ShapeDistanceRuler ruler = SCR_ShapeDistanceRuler.CreateFromShape(shapeEntity);
112 float safetyDistance;
113 safetyDistance = float.MAX;
114 foreach (vector offsetAnchorPoint : offsetAnchorPoints)
115 {
116 float distance;
117 if (m_bNextPointMeasurementXZ)
118 distance = ruler.GetDistanceXZ(offsetAnchorPoint);
119 else
120 distance = ruler.GetDistance(offsetAnchorPoint);
121
122 if (distance < safetyDistance)
123 safetyDistance = distance;
124 }
125
126 safetyDistance *= m_fSplineSafetyDistanceRatio;
127
128 bool anchorPointRefusal;
129 for (int i = offsetTesselatedPoints.Count() - 2; i >= 1; --i) // avoid first and last point
130 {
131 bool removePoint;
132 if (m_bNextPointMeasurementXZ)
133 removePoint = ruler.IsWithinDistanceXZ(offsetTesselatedPoints[i], safetyDistance, false);
134 else
135 removePoint = ruler.IsWithinDistance(offsetTesselatedPoints[i], safetyDistance, false);
136
137 if (removePoint)
138 {
139 if (anchorIndices.Contains(i))
140 {
141 anchorPointRefusal = true;
142 continue;
143 }
144
145 if (m_OffsetDebugShapeManager)
146 m_OffsetDebugShapeManager.AddArrow(shapeEntity.CoordToParent(offsetTesselatedPoints[i] + 2 * vector.Up), shapeEntity.CoordToParent(offsetTesselatedPoints[i]));
147
148 offsetTesselatedPoints.RemoveOrdered(i);
149 }
150 }
151
152 if (anchorPointRefusal)
153 {
154 PrintFormat("Cannot remove offset anchor points near %1 shape; only intermediate spline points can be removed", Debug.GetEntityLinkString(shapeEntity), level: LogLevel.NORMAL);
155 Print("Solution: make this curve with an anchor point on each side instead of one at the curve's apex", LogLevel.NORMAL);
156 }
157 }
158
159 m_ShapeNextPointHelper = SCR_ShapeNextPointHelper.CreateFromPoints(offsetAnchorPoints, offsetTesselatedPoints);
160 }
161
162 //------------------------------------------------------------------------------------------------
163 protected override void OnShapeChangedInternal(IEntitySource shapeEntitySrc, ShapeEntity shapeEntity, array<vector> mins, array<vector> maxes)
164 {
165 super.OnShapeChangedInternal(shapeEntitySrc, shapeEntity, mins, maxes);
166
167 ResetShapeNextPointHelper();
168 }
169
170 //------------------------------------------------------------------------------------------------
171 protected override bool _WB_OnKeyChanged(BaseContainer src, string key, BaseContainerList ownerContainers, IEntity parent)
172 {
173 if (!super._WB_OnKeyChanged(src, key, ownerContainers, parent))
174 return false;
175
176 m_bForceOffsetShapeShapesRefresh = true;
177
178 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
179 if (!worldEditorAPI || worldEditorAPI.UndoOrRedoIsRestoring())
180 return false;
181
182 if (key == "m_fSplineSafetyDistance")
183 {
184 if (m_vShapeOffset == vector.Zero)
185 return false;
186
187 if (m_ParentShapeSource && m_ParentShapeSource.GetClassName().ToType() && m_ParentShapeSource.GetClassName().ToType().IsInherited(PolylineShapeEntity))
188 return false;
189 }
190
191 BaseContainerTools.WriteToInstance(this, _WB_GetEditorAPI().EntityToSource(this));
192 ResetShapeNextPointHelper();
193
194 return true;
195 }
196
197 //------------------------------------------------------------------------------------------------
198 protected override void _WB_OnParentChange(IEntitySource src, IEntitySource prevParentSrc)
199 {
200 super._WB_OnParentChange(src, prevParentSrc);
201
202 ResetShapeNextPointHelper();
203 }
204
205 //------------------------------------------------------------------------------------------------
206 protected override void _WB_OnInit(inout vector mat[4], IEntitySource src)
207 {
208 super._WB_OnInit(mat, src);
209
210 ResetShapeNextPointHelper();
211 }
212
213 //------------------------------------------------------------------------------------------------
214 protected override void _WB_AfterWorldUpdate(float timeSlice)
215 {
216 super._WB_AfterWorldUpdate(timeSlice);
217
218 if (!m_Source || !m_OffsetDebugShapeManager)
219 return;
220
221 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
222 if (!worldEditorAPI)
223 return;
224
225 bool isSelectedAlone = worldEditorAPI.IsEntitySelected(m_Source) && worldEditorAPI.GetSelectedEntitiesCount() == 1;
226 if (m_bForceOffsetShapeShapesRefresh)
227 m_bForceOffsetShapeShapesRefresh = false;
228 else if (m_bIsSelectedAlone == isSelectedAlone)
229 return;
230
231 m_bIsSelectedAlone = isSelectedAlone;
232
233 foreach (Shape offsetShapeShape : m_aOffsetShapeShapes)
234 {
235 if (offsetShapeShape)
236 m_OffsetDebugShapeManager.Remove(offsetShapeShape);
237 }
238
239 if (!m_bIsSelectedAlone || m_vShapeOffset == vector.Zero || !m_ShapeNextPointHelper || !m_ParentShapeSource)
240 return;
241
242 ShapeEntity shapeEntity = ShapeEntity.Cast(_WB_GetEditorAPI().SourceToEntity(m_ParentShapeSource));
243 if (!shapeEntity)
244 return;
245
246 // draw offset shape
247 array<vector> offsetTesselatedPoints = m_ShapeNextPointHelper.GetTesselatedPoints();
248 vector prevPoint;
249 foreach (int i, vector point : offsetTesselatedPoints)
250 {
251 if (i != 0)
252 m_aOffsetShapeShapes.Insert(
253 m_OffsetDebugShapeManager.AddLine(
254 shapeEntity.CoordToParent(prevPoint),
255 shapeEntity.CoordToParent(point),
256 Color.ORANGE));
257
258 prevPoint = point;
259 }
260 }
261
262 //------------------------------------------------------------------------------------------------
263 protected override int _WB_GetAfterWorldUpdateSpecs(IEntitySource src)
264 {
265 super._WB_GetAfterWorldUpdateSpecs(src);
266 return EEntityFrameUpdateSpecs.CALL_WHEN_ENTITY_VISIBLE;
267 }
268
269#endif // WORKBENCH
270}
params precision
override void _WB_OnInit(IEntity owner, inout vector mat[4], IEntitySource src)
override bool _WB_OnKeyChanged(IEntity owner, BaseContainer src, string key, BaseContainerList ownerContainers, IEntity parent)
Any property value has been changed. You can use editor API here and do some additional edit actions ...
float distance
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
enum EVehicleType IEntity
bool IsWithinDistance(vector relativePos, float distance, bool equalCounts=true)
float GetDistance(vector relativePos)
bool IsWithinDistanceXZ(vector relativePos, float distance, bool equalCounts=true)
float GetDistanceXZ(vector relativePos)
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
proto void PrintFormat(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL, LogLevel level=LogLevel.NORMAL)
SCR_FieldOfViewSettings Attribute
void OnShapeChangedInternal(IEntitySource shapeEntitySrc, ShapeEntity shapeEntity, array< vector > mins, array< vector > maxes)
void Debug()
Definition Types.c:327