36 #ifdef ENABLE_DESTRUCTION
38 protected static ref array<SCR_FragmentEntity> s_FragmentList = {};
39 protected static ref array<SCR_FragmentEntity> s_FragmentToCheckList = {};
40 protected static ref array<SCR_FragmentEntity> s_FragmentCheckedList = {};
45 [
Attribute(
"0",
UIWidgets.CheckBox,
"Check to generate fragment hierarchies for each fractal variant",
category:
"EDITOR: Destruction Fractal")]
46 protected bool GenerateFragmentHierarchies;
48 [
Attribute(
"0",
UIWidgets.CheckBox,
"Check to toggle display of visualizers in the World Editor",
category:
"EDITOR: Destruction Fractal")]
49 protected bool ToggleVisualizers;
51 static bool s_WBDisplayVisualizers =
false;
53 static ref array<SCR_PreviewEntity> s_WBFragmentList = {};
56 protected static void ClearVisualizers()
58 s_WBVisualizeEntity = null;
62 fragVis = s_WBFragmentList[i];
65 s_WBFragmentList.Clear();
76 if (!api || api.UndoOrRedoIsRestoring())
81 case "GenerateFragmentHierarchies":
83 src.ClearVariable(
"GenerateFragmentHierarchies");
85 Print(
"SCR_DestructionFractalComponent: Generating fragment hierarchies...",
LogLevel.NORMAL);
87 BaseContainerList srcFractalVariantList = src.GetObjectArray(
"m_FractalVariants");
88 int numVariants = m_FractalVariants.Count();
89 for (
int v = 0; v < numVariants; v++)
91 BaseContainer srcFractalVariant = srcFractalVariantList.Get(v);
93 fractalVariant.
m_Hierarchy =
new SCR_FragmentHierarchy;
94 fractalVariant.
m_Hierarchy.GenerateHierarchy(fractalVariant);
95 srcFractalVariant.Set(
"m_Hierarchy", fractalVariant.
m_Hierarchy);
103 case "ToggleVisualizers":
105 src.ClearVariable(
"ToggleVisualizers");
108 s_WBDisplayVisualizers = !s_WBDisplayVisualizers;
109 if (!s_WBDisplayVisualizers)
189 if (src.GetClassName() ==
"SCR_DestructionFractalComponent")
191 srcFractalComp = src;
195 for (
int c = 0, srcCount = ownerContainers.Count(); c < srcCount; c++)
198 if (compSrc.GetClassName() !=
"SCR_DestructionFractalComponent")
201 srcFractalComp = compSrc;
209 BaseContainerList srcFVariantList = srcFractalComp.GetObjectArray(
"m_FractalVariants");
210 int numVariants = m_FractalVariants.Count();
211 bool needResave =
false;
212 for (
int v = 0; v < numVariants; v++)
218 BaseContainer srcHier = srcFVariant.GetObject(
"m_Hierarchy");
248 bool isAnchor =
false;
251 VObject asset = resource.GetResource().ToVObject();
252 string materials[256];
253 int numMats = asset.GetMaterials(materials);
255 for (
int m = 0; m < numMats; m++)
257 remap +=
"$remap '" + materials[m] +
"' '{639855E4E1F52285}Assets/Editor/PlacingPreview/Preview_Scriptable.emat';";
260 const int intensity = 200;
261 const int intensityOther = 16;
264 fragVis.m_Color =
ARGB(255, intensityOther, intensityOther, intensity);
267 fragVis.m_Color =
ARGB(255, intensityOther, intensity, intensityOther);
270 fragVis.m_Color =
ARGB(255, intensity, intensityOther, intensityOther);
273 fragVis.m_Color =
ARGB(255, intensity, intensityOther, intensity);
276 fragVis.m_Color =
ARGB(255, intensityOther, intensity, intensity);
279 fragVis.m_Color =
ARGB(255, intensity, intensity, intensityOther);
281 fragVis.SetObject(asset, remap);
292 return EEntityFrameUpdateSpecs.CALL_WHEN_ENTITY_VISIBLE;
296 override void _WB_AfterWorldUpdate(
IEntity owner,
float timeSlice)
299 if (!s_WBDisplayVisualizers)
301 if (s_WBVisualizeEntity)
310 if (s_WBVisualizeEntity == gEntity)
316 vector textMat[4], camMat[4];
317 gEntity.
GetWorld().GetCurrentCamera(camMat);
318 gEntity.
GetWorld().GetCurrentCamera(textMat);
319 vector camDir = camMat[2];
320 vector camPos = camMat[3];
325 vector entTop =
Vector((entMaxs[0] + entMins[0]) * 0.5, entMaxs[1], (entMaxs[2] + entMins[2]) * 0.5);
326 float distScale =
Math.Clamp(
vector.Distance(camPos, entCenter) * 0.15, 0.1, 3);
329 if (s_WBVisualizeEntity != gEntity)
332 s_WBVisualizeEntity = gEntity;
334 if (!m_UsedFractalData)
337 if (!m_UsedFractalData)
341 for (
int i = 0; i < numFrags; i++)
343 s_WBFragmentList.Insert(CreateFragmentVisualizer(i));
348 if (!m_UsedFractalData)
350 textMat[3] = entTop +
vector.Up * 0.25;
351 CreateSimpleText(
"NO FRACTAL VARIANT", textMat, 0.17 * distScale,
ARGB(255, 255, 0, 0),
ShapeFlags.ONCE |
ShapeFlags.TRANSP |
ShapeFlags.NOZBUFFER, null, 0.7,
true,
ARGB(128, 0, 0, 0));
357 int highlighted = -1;
359 for (
int i = 0; i < numFrags; i++)
364 vector fragToCamDir = (fragCenter - camPos).Normalized();
365 textMat[3] = fragCenter;
367 int textColor =
ARGB(255, 255, 255, 255);
368 int bgColor =
ARGB(128, 0, 0, 0);
369 float textSize = 0.12;
370 if (highlighted == -1 &&
vector.Dot(fragToCamDir, highlightDir) > 0.9997)
373 textColor =
ARGB(255, 0, 255, 0);
374 bgColor =
ARGB(200, 0, 32, 0);
383 vector from = fragCenter +
vector.Up * distScale * -0.2;
384 int numLinked = link.m_aOtherIndexes.Count();
385 for (
int n = 0; n < numLinked; n++)
387 int otherIndex = link.m_aOtherIndexes[n];
388 if (otherIndex < 0 || otherIndex >= numFrags || otherIndex == i)
395 int arrowsColor =
ARGB(255, 255, 0, 0);
396 if (isOtherAnchor || isAnchor)
397 arrowsColor =
ARGB(255, 0, 128, 255);
399 int numArrows =
Math.Ceil(
vector.Distance(fragCenter, fragOtherCenter) * 10 / distScale);
415 textMat[3] = textMat[3] + camMat[1] * textSize * distScale * -0.5;
419 textMat[3] = textMat[3] -
vector.Up * distScale * textSize * 1.6;
420 CreateSimpleText(
"ANCHOR", textMat, textSize * distScale,
ARGB(255, 255, 64, 64),
ShapeFlags.ONCE |
ShapeFlags.TRANSP |
ShapeFlags.NOZBUFFER, null, 1,
true, bgColor);
430 return GetDestroyed();
437 int numFragments = 0;
455 int FillCompleteOrderedFragmentList(notnull array<SCR_FragmentEntity> fragmentList)
457 fragmentList.Clear();
459 for (
int i = 0; i < maxFragments; i++)
461 fragmentList.Insert(null);
470 fragmentList[fragment.GetIndex()] = fragment;
473 return fragmentList.Count();
480 int FillFragmentList(notnull array<SCR_FragmentEntity> fragmentList)
482 fragmentList.Clear();
490 fragmentList.Insert(fragment);
493 return fragmentList.Count();
500 int FillFragmentIndexList(array<int> fragmentIndexList)
502 fragmentIndexList.Clear();
510 fragmentIndexList.Insert(fragment.GetIndex());
513 return fragmentIndexList.Count();
520 return m_UsedFractalData;
527 int numVariants = m_FractalVariants.Count();
528 if (numVariants == 0)
544 int x =
Math.Floor(pos[0] * 1000);
545 int z =
Math.Floor(pos[2] * 1000);
549 s_RandomGenerator.Randomize(seed);
551 int randomVariant = s_RandomGenerator.RandomInt(0, numVariants);
559 void DeleteFragments()
585 if (fragment.GetIndex() ==
index)
598 bool isAnchor =
false;
604 fragment.Initialize(
this,
index, m_fFragmentHealth, assetPath);
612 protected void CreateFragments(
bool addToTraceIgnoreList =
false)
614 if (!m_UsedFractalData)
617 if (addToTraceIgnoreList)
621 for (
int i = 0; i < num; i++)
624 if (addToTraceIgnoreList && fragment)
625 SCR_Global.g_TraceFilterList.Insert(fragment);
639 int numFragments = FillCompleteOrderedFragmentList(s_FragmentList);
642 s_FragmentList[fromFragment.GetIndex()] = null;
654 s_FragmentToCheckList.Clear();
655 for (
int i = fromLinkage.m_aOtherIndexes.Count() - 1; i >= 0; i--)
658 if (!neighborFragment)
661 s_FragmentToCheckList.Insert(neighborFragment);
665 while (!s_FragmentToCheckList.IsEmpty())
668 s_FragmentToCheckList.RemoveItem(checkFragment);
671 s_FragmentCheckedList.Clear();
672 if (!CheckFragmentAnchored(checkFragment, numFragments))
674 s_FragmentList[checkFragment.GetIndex()] = null;
679 int numOther = linkage.m_aOtherIndexes.Count();
680 for (
int i = 0; i < numOther; i++)
682 int otherIndex = linkage.m_aOtherIndexes[i];
683 if (otherIndex < 0 || otherIndex >= numFragments)
687 if (!neighborFragment)
690 if (s_FragmentToCheckList.Find(neighborFragment) == -1)
691 s_FragmentToCheckList.Insert(neighborFragment);
695 checkFragment.QueueDestroy(damageType, damage, hitPosition, hitDirection,
false);
706 if (s_FragmentCheckedList.Find(fragment) >= 0)
709 s_FragmentCheckedList.Insert(fragment);
715 if (linkage.m_bIsAnchor)
718 int numOther = linkage.m_aOtherIndexes.Count();
719 for (
int i = 0; i < numOther; i++)
721 int otherIndex = linkage.m_aOtherIndexes[i];
722 if (otherIndex < 0 || otherIndex >= numFragments)
726 if (!neighborFragment)
729 if (CheckFragmentAnchored(neighborFragment, numFragments))
745 if (m_bDeleteAfterFinalFragment)
755 if (m_bEnableStructuralIntegrity)
756 UpdateStructuralIntegrity(fragment, damageType, damage, hitPosition, hitDirection);
766 override void NetReceiveHitData(
int hitIndex,
EDamageType damageType,
float damage,
vector hitPosition,
vector hitDirection)
772 if (m_bEnableStructuralIntegrity)
773 UpdateStructuralIntegrity(fragment, damageType, damage, hitPosition, hitDirection);
775 fragment.QueueDestroy(damageType, damage, hitPosition, hitDirection);
782 if (m_bDeleteAfterFinalFragment && !m_DestructionHitInfo)
787 EnableOnFrame(
false);
791 super.OnFrame(owner, timeSlice);
800 if (!m_UsedFractalData)
803 bool fractured = GetFractured();
822 m_Owner.SetObject(null,
string.Empty);
829 if (resource.IsValid())
834 VObject asset = baseResource.ToVObject();
837 m_Owner.SetObject(asset,
string.Empty);
844 Print(
"FRACTAL DESTRUCTION::UpdateModel: Could not load visual object '" + assetPath +
"'!!",
LogLevel.WARNING);
847 Print(
"FRACTAL DESTRUCTION::UpdateModel: Could not load base resource for model '" + assetPath +
"'!!",
LogLevel.WARNING);
850 Print(
"FRACTAL DESTRUCTION::UpdateModel: Could not load model '" + assetPath +
"'!!",
LogLevel.WARNING);
858 override void HandleDestruction()
863 if (!m_DestructionHitInfo.m_TotalDestruction)
865 CreateFragments(
true);
867 if (m_bDestroyFragmentOnFracture)
872 param.Start = m_DestructionHitInfo.m_HitPosition + m_DestructionHitInfo.m_HitDirection * -0.25;
873 param.End = m_DestructionHitInfo.m_HitPosition + m_DestructionHitInfo.m_HitDirection * 0.25;
875 param.LayerMask = -1;
876 if (
m_Owner.GetWorld().TraceMove(param,
SCR_Global.FilterCallback_IgnoreNotInList) < 1)
883 if (fragment && param.TraceEnt == fragment)
886 fragment.QueueDestroy(m_DestructionHitInfo.m_DamageType, m_DestructionHitInfo.m_HitDamage, m_DestructionHitInfo.m_HitPosition, m_DestructionHitInfo.m_HitDirection);
887 UpdateStructuralIntegrity(fragment, m_DestructionHitInfo.m_DamageType, m_DestructionHitInfo.m_HitDamage, m_DestructionHitInfo.m_HitPosition, m_DestructionHitInfo.m_HitDirection);
895 delete m_DestructionHitInfo;
903 int fractalVariantIndex;
904 reader.Read(fractalVariantIndex, 32);
905 if (fractalVariantIndex == -1)
912 m_UsedFractalData = m_FractalVariants[fractalVariantIndex];
916 reader.Read(numBitMasks, 32);
917 if (numBitMasks == 0)
922 for (
int i = 0; i < numBitMasks; i++)
925 reader.Read(bitMask, 32);
926 fragmentsBitMaskArray.SetBitMask(i, bitMask);
931 for (
int i = 0; i < numFragmentsMax; i++)
933 if (fragmentsBitMaskArray.GetBit(i))
940 override void NetWriteInit(ScriptBitWriter writer)
942 int fractalVariantIndex = -1;
943 if (m_UsedFractalData)
945 fractalVariantIndex = m_FractalVariants.Find(m_UsedFractalData);
946 writer.Write(fractalVariantIndex, 32);
950 writer.Write(-1, 32);
954 array<int> fragmentIndexList = {};
955 int numFragments = FillFragmentIndexList(fragmentIndexList);
957 if (numFragments == 0)
965 int numBitMasks = fragmentsBitMaskArray.GetNumBitMasks();
966 writer.Write(numBitMasks, 32);
969 for (
int i = 0; i < numFragments; i++)
971 fragmentsBitMaskArray.SetBit(fragmentIndexList[i],
true);
975 for (
int i = 0; i < numBitMasks; i++)
977 int bitMask = fragmentsBitMaskArray.GetBitMask(i);
978 writer.Write(bitMask, 32);
984 override void InitDestruction()
986 m_UsedFractalData = GetRandomFractalVariant();