8class SCR_LineGeneratorBaseEntity : SCR_GeneratorBaseEntity
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;
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;
21 protected float m_fShapeOffset;
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;
27 protected bool m_bSnapOffsetShapeToTheGround;
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;
35 protected ref array<Shape> m_aOffsetShapeShapes = {};
36 protected bool m_bIsSelectedAlone;
37 protected bool m_bForceOffsetShapeShapesRefresh;
40 protected void ResetShapeNextPointHelper()
42 m_ShapeNextPointHelper = null;
44 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
48 IEntitySource newGeneratorSource = worldEditorAPI.EntityToSource(
this);
49 if (!newGeneratorSource)
52 if (!m_ParentShapeSource)
55 ShapeEntity shapeEntity = ShapeEntity.Cast(worldEditorAPI.SourceToEntity(m_ParentShapeSource));
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))
64 PrintFormat(
"[SCR_LineGeneratorBaseEntity.ResetShapeNextPointHelper] error getting shape points from shape with %1 points - %2", shapeEntity.GetPointCount(),
Debug.GetEntityLinkString(shapeEntity), level:
LogLevel.WARNING);
68 if (m_bSnapOffsetShapeToTheGround)
70 BaseWorld world = shapeEntity.GetWorld();
74 foreach (
int i, vector point : offsetAnchorPoints)
76 tempVector = shapeEntity.CoordToParent(point);
77 tempVector[1] = world.GetSurfaceY(tempVector[0], tempVector[2]) + m_vShapeOffset[1];
78 tempVector = shapeEntity.CoordToLocal(tempVector);
80 if (point[0] == tempVector[0] && point[2] == tempVector[2])
81 point[1] = tempVector[1];
85 offsetAnchorPoints[i] = point;
88 foreach (
int i, vector point : offsetTesselatedPoints)
90 tempVector = shapeEntity.CoordToParent(point);
91 tempVector[1] = world.GetSurfaceY(tempVector[0], tempVector[2]) + m_vShapeOffset[1];
92 tempVector = shapeEntity.CoordToLocal(tempVector);
94 if (point[0] == tempVector[0] && point[2] == tempVector[2])
95 point[1] = tempVector[1];
99 offsetTesselatedPoints[i] = point;
104 if (m_vShapeOffset != vector.Zero)
105 m_OffsetDebugShapeManager =
new SCR_DebugShapeManager();
107 m_OffsetDebugShapeManager = null;
109 if (m_fSplineSafetyDistanceRatio != 0 && (m_vShapeOffset[0] != 0 || m_vShapeOffset[2] != 0) && SplineShapeEntity.Cast(shapeEntity) != null)
111 SCR_ShapeDistanceRuler ruler = SCR_ShapeDistanceRuler.CreateFromShape(shapeEntity);
112 float safetyDistance;
113 safetyDistance =
float.MAX;
114 foreach (vector offsetAnchorPoint : offsetAnchorPoints)
117 if (m_bNextPointMeasurementXZ)
126 safetyDistance *= m_fSplineSafetyDistanceRatio;
128 bool anchorPointRefusal;
129 for (
int i = offsetTesselatedPoints.Count() - 2; i >= 1; --i)
132 if (m_bNextPointMeasurementXZ)
133 removePoint = ruler.
IsWithinDistanceXZ(offsetTesselatedPoints[i], safetyDistance,
false);
135 removePoint = ruler.
IsWithinDistance(offsetTesselatedPoints[i], safetyDistance,
false);
139 if (anchorIndices.Contains(i))
141 anchorPointRefusal =
true;
145 if (m_OffsetDebugShapeManager)
146 m_OffsetDebugShapeManager.AddArrow(shapeEntity.CoordToParent(offsetTesselatedPoints[i] + 2 * vector.Up), shapeEntity.CoordToParent(offsetTesselatedPoints[i]));
148 offsetTesselatedPoints.RemoveOrdered(i);
152 if (anchorPointRefusal)
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);
159 m_ShapeNextPointHelper = SCR_ShapeNextPointHelper.CreateFromPoints(offsetAnchorPoints, offsetTesselatedPoints);
163 protected override void OnShapeChangedInternal(IEntitySource shapeEntitySrc, ShapeEntity shapeEntity, array<vector> mins, array<vector> maxes)
165 super.OnShapeChangedInternal(shapeEntitySrc, shapeEntity, mins, maxes);
167 ResetShapeNextPointHelper();
171 protected override bool _WB_OnKeyChanged(BaseContainer src,
string key, BaseContainerList ownerContainers,
IEntity parent)
173 if (!super._WB_OnKeyChanged(src, key, ownerContainers, parent))
176 m_bForceOffsetShapeShapesRefresh =
true;
178 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
179 if (!worldEditorAPI || worldEditorAPI.UndoOrRedoIsRestoring())
182 if (key ==
"m_fSplineSafetyDistance")
184 if (m_vShapeOffset == vector.Zero)
187 if (m_ParentShapeSource && m_ParentShapeSource.GetClassName().ToType() && m_ParentShapeSource.GetClassName().ToType().IsInherited(PolylineShapeEntity))
191 BaseContainerTools.WriteToInstance(
this, _WB_GetEditorAPI().EntityToSource(
this));
192 ResetShapeNextPointHelper();
198 protected override void _WB_OnParentChange(IEntitySource src, IEntitySource prevParentSrc)
200 super._WB_OnParentChange(src, prevParentSrc);
202 ResetShapeNextPointHelper();
206 protected override void _WB_OnInit(inout vector mat[4], IEntitySource src)
208 super._WB_OnInit(mat, src);
210 ResetShapeNextPointHelper();
214 protected override void _WB_AfterWorldUpdate(
float timeSlice)
216 super._WB_AfterWorldUpdate(timeSlice);
218 if (!m_Source || !m_OffsetDebugShapeManager)
221 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
225 bool isSelectedAlone = worldEditorAPI.IsEntitySelected(m_Source) && worldEditorAPI.GetSelectedEntitiesCount() == 1;
226 if (m_bForceOffsetShapeShapesRefresh)
227 m_bForceOffsetShapeShapesRefresh =
false;
228 else if (m_bIsSelectedAlone == isSelectedAlone)
231 m_bIsSelectedAlone = isSelectedAlone;
233 foreach (Shape offsetShapeShape : m_aOffsetShapeShapes)
235 if (offsetShapeShape)
236 m_OffsetDebugShapeManager.Remove(offsetShapeShape);
239 if (!m_bIsSelectedAlone || m_vShapeOffset == vector.Zero || !m_ShapeNextPointHelper || !m_ParentShapeSource)
242 ShapeEntity shapeEntity = ShapeEntity.Cast(_WB_GetEditorAPI().SourceToEntity(m_ParentShapeSource));
247 array<vector> offsetTesselatedPoints = m_ShapeNextPointHelper.GetTesselatedPoints();
249 foreach (
int i, vector point : offsetTesselatedPoints)
252 m_aOffsetShapeShapes.Insert(
253 m_OffsetDebugShapeManager.AddLine(
254 shapeEntity.CoordToParent(prevPoint),
255 shapeEntity.CoordToParent(point),
263 protected override int _WB_GetAfterWorldUpdateSpecs(IEntitySource src)
265 super._WB_GetAfterWorldUpdateSpecs(src);
266 return EEntityFrameUpdateSpecs.CALL_WHEN_ENTITY_VISIBLE;
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 ...
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.
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)