Skip to content
Snippets Groups Projects
Commit b6fee6fe authored by Tobias Schöner's avatar Tobias Schöner
Browse files

feat: FactExplorer now displays lines between facts

Implemented UILine

Parent facts are connected to the main fact by a direct dashed line whereas child facts are connected by a jagged continuous line.
parent 46c7d790
No related branches found
No related tags found
No related merge requests found
...@@ -78,6 +78,103 @@ MonoBehaviour: ...@@ -78,6 +78,103 @@ MonoBehaviour:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_HorizontalFit: 2 m_HorizontalFit: 2
m_VerticalFit: 2 m_VerticalFit: 2
--- !u!1 &196909836272952088
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 294307632257003305}
- component: {fileID: 3259288062294702885}
- component: {fileID: 5601304647299485279}
- component: {fileID: 2468798738105667105}
m_Layer: 5
m_Name: Highlight
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &294307632257003305
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 196909836272952088}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2636669742664082113}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 110, y: 110}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &3259288062294702885
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 196909836272952088}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 1
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!222 &5601304647299485279
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 196909836272952088}
m_CullTransparentMesh: 1
--- !u!114 &2468798738105667105
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 196909836272952088}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 0.49803922, b: 0, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &2146237966352740759 --- !u!1 &2146237966352740759
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
...@@ -87,6 +184,7 @@ GameObject: ...@@ -87,6 +184,7 @@ GameObject:
serializedVersion: 6 serializedVersion: 6
m_Component: m_Component:
- component: {fileID: 2636669742664082113} - component: {fileID: 2636669742664082113}
- component: {fileID: 8821645608645168199}
m_Layer: 5 m_Layer: 5
m_Name: MainFact m_Name: MainFact
m_TagString: Untagged m_TagString: Untagged
...@@ -105,7 +203,8 @@ RectTransform: ...@@ -105,7 +203,8 @@ RectTransform:
m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children:
- {fileID: 294307632257003305}
m_Father: {fileID: 3406631590813364790} m_Father: {fileID: 3406631590813364790}
m_RootOrder: 2 m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
...@@ -114,6 +213,14 @@ RectTransform: ...@@ -114,6 +213,14 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0} m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100} m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8821645608645168199
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2146237966352740759}
m_CullTransparentMesh: 1
--- !u!1 &5592893003942163674 --- !u!1 &5592893003942163674
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
...@@ -253,11 +360,11 @@ MonoBehaviour: ...@@ -253,11 +360,11 @@ MonoBehaviour:
mainFactUI: {fileID: 2636669742664082113} mainFactUI: {fileID: 2636669742664082113}
factChildrenUI: {fileID: 9153153668998730241} factChildrenUI: {fileID: 9153153668998730241}
linesUI: {fileID: 8009565381998387591} linesUI: {fileID: 8009565381998387591}
factExplorerLineParents_Prefab: {fileID: 602666608487228118, guid: 6cdb6cc4d5af8db409745afbc201068b, factSpotPrefab: {fileID: 7124463502404826001, guid: 04d12e0a0a5aa884c8c7dff56f4963f6,
type: 3} type: 3}
factExplorerLineChildren_Prefab: {fileID: 4365600632079246398, guid: a9fcb9d279efe6849a46855110d5e794, parentLine: {fileID: 602666608487228118, guid: 6cdb6cc4d5af8db409745afbc201068b,
type: 3} type: 3}
factSpotPrefab: {fileID: 7124463502404826001, guid: 04d12e0a0a5aa884c8c7dff56f4963f6, childLine: {fileID: 4903779976374899580, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3} type: 3}
--- !u!1 &7302347448387664938 --- !u!1 &7302347448387664938
GameObject: GameObject:
...@@ -369,10 +476,10 @@ RectTransform: ...@@ -369,10 +476,10 @@ RectTransform:
m_Father: {fileID: 3406631590813364790} m_Father: {fileID: 3406631590813364790}
m_RootOrder: 0 m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0.5, y: 0.5} m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0} m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100} m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &835707716098452998 --- !u!114 &835707716098452998
MonoBehaviour: MonoBehaviour:
......
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4903779976374899580
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 911949952148793464}
- component: {fileID: -137166815004959870}
- component: {fileID: 2132054669896436896}
- component: {fileID: 4832178158615009880}
m_Layer: 0
m_Name: FactExplorer_Line
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &911949952148793464
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4903779976374899580}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &-137166815004959870
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4903779976374899580}
m_CullTransparentMesh: 1
--- !u!114 &2132054669896436896
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4903779976374899580}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 1
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!114 &4832178158615009880
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4903779976374899580}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8ed745d97410d6740921398c899d9ec0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.3137255, g: 0.3137255, b: 0.3137255, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
points: []
width: 4
roundCorners: 1
roundStart: 1
roundEnd: 1
dashed: 0
dashLength: 10
dashSpacing: 5
fileFormatVersion: 2
guid: 7f47b2a4ac81f444eb5e18b8efabc644
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &5499075457957573034
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_Pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_RootOrder
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_AnchorMax.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_AnchorMax.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_AnchorMin.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_AnchorMin.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 911949952148793464, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4832178158615009880, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: dashed
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4903779976374899580, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_Name
value: FactExplorer_Line_Dashed
objectReference: {fileID: 0}
- target: {fileID: 8455242915356568467, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_Materials.Array.size
value: 1
objectReference: {fileID: 0}
- target: {fileID: 8455242915356568467, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_Positions.Array.size
value: 2
objectReference: {fileID: 0}
- target: {fileID: 8455242915356568467, guid: 7f47b2a4ac81f444eb5e18b8efabc644,
type: 3}
propertyPath: m_Materials.Array.data[0]
value:
objectReference: {fileID: 2100000, guid: 3be144593ef3bac42812ba90847c1cff, type: 2}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 7f47b2a4ac81f444eb5e18b8efabc644, type: 3}
fileFormatVersion: 2
guid: 6cdb6cc4d5af8db409745afbc201068b
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
public class FactExplorer : MonoBehaviour public class FactExplorer : MonoBehaviour
{ {
#region InspectorVariables
[Header("PrefabComponents")] [Header("PrefabComponents")]
[SerializeField] private Transform factParentsUI; [SerializeField] private Transform factParentsUI;
[SerializeField] private Transform mainFactUI; [SerializeField] private Transform mainFactUI;
...@@ -16,13 +17,17 @@ public class FactExplorer : MonoBehaviour ...@@ -16,13 +17,17 @@ public class FactExplorer : MonoBehaviour
[Header("Prefabs")] [Header("Prefabs")]
[SerializeField] private GameObject factSpotPrefab; [SerializeField] private GameObject factSpotPrefab;
[SerializeField] private GameObject parentLine;
[SerializeField] private GameObject childLine;
#endregion InspectorVariables
#region Variables
private Fact mainFact; private Fact mainFact;
private List<Fact> parentFacts; private List<Fact> parentFacts;
private List<Fact> childFacts; private List<Fact> childFacts;
#endregion Variables
#region UnityMethods
private void Update() private void Update()
{ {
DestroyIfClickedOutside(); DestroyIfClickedOutside();
...@@ -30,7 +35,6 @@ private void Update() ...@@ -30,7 +35,6 @@ private void Update()
public void Initialize(Fact fact) public void Initialize(Fact fact)
{ {
mainFact = fact; mainFact = fact;
parentFacts = GetParentFacts(); parentFacts = GetParentFacts();
childFacts = GetChildFacts(); childFacts = GetChildFacts();
...@@ -40,6 +44,7 @@ public void Initialize(Fact fact) ...@@ -40,6 +44,7 @@ public void Initialize(Fact fact)
UpdateFactExplorerUI(); UpdateFactExplorerUI();
} }
#endregion UnityMethods
#region Implementation #region Implementation
private List<Fact> GetParentFacts() private List<Fact> GetParentFacts()
...@@ -72,18 +77,88 @@ private void UpdateFactExplorerUI() ...@@ -72,18 +77,88 @@ private void UpdateFactExplorerUI()
SpawnUIFacts(factParentsUI, parentFacts); SpawnUIFacts(factParentsUI, parentFacts);
SpawnUIFacts(mainFactUI, new List<Fact>() { mainFact }); SpawnUIFacts(mainFactUI, new List<Fact>() { mainFact });
SpawnUIFacts(factChildrenUI, childFacts); SpawnUIFacts(factChildrenUI, childFacts);
// Force rebuild of FactExplorer layout, since the positions of the factObjects will be wrong otherwise
LayoutRebuilder.ForceRebuildLayoutImmediate(transform.GetComponent<RectTransform>());
SpawnParentLines(factParentsUI.gameObject, mainFactUI);
SpawnChildLines(factChildrenUI.gameObject, mainFactUI);
} }
private void DestroyIfClickedOutside() private void DestroyIfClickedOutside()
{ {
if ((Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1)) && // Destroy on tab press or left click outside of FactExplorer
!RectTransformUtility.RectangleContainsScreenPoint(transform.GetComponent<RectTransform>(), Input.mousePosition, null)) if (Input.GetKeyDown(KeyCode.Tab)
|| (Input.GetMouseButtonDown(0) && !RectTransformUtility.RectangleContainsScreenPoint(transform.GetComponent<RectTransform>(), Input.mousePosition, null)))
{ {
Destroy(gameObject); Destroy(gameObject);
} }
} }
#endregion Implementation #endregion Implementation
#region Spawner
private void SpawnUIFacts(Transform uiParent, List<Fact> toSpawn)
{
// if uiParent has no children: deactivate it
if (toSpawn.Count == 0)
uiParent.gameObject.SetActive(false);
foreach (Fact f in toSpawn)
{
var spot = Instantiate(factSpotPrefab, uiParent);
// TODO: this link to DisplayFacts is not ideal: maybe refactor to SciptableObject or such
var display = f.instantiateDisplay(DisplayFacts.prefabDictionary[f.GetType()], spot.transform);
display.transform.localPosition = Vector3.zero;
}
}
private void SpawnParentLines(GameObject parent, Transform mainFactUI)
{
var mainTransform = mainFactUI.GetComponent<RectTransform>();
var factWidth = mainTransform.rect.width;
// transform.positions are weird due to LayoutGroups => manually calculate offset
float xOffset = -factParentsUI.GetComponent<RectTransform>().rect.width / 2 + factWidth / 2;
float yOffset = transform.GetComponent<VerticalLayoutGroup>().spacing;
parent.ForAllChildren(par =>
{
// position at the bottom center of par rect
var position = par.transform.TransformPoint(new Vector2(0, par.GetComponent<RectTransform>().rect.yMin));
var line = Instantiate(parentLine, position, Quaternion.identity, par.transform);
var uiLine = line.GetComponent<UILine>();
uiLine.points = new List<Vector2>() { Vector2.zero, new Vector2(-xOffset, -yOffset) };
xOffset += factWidth + factParentsUI.GetComponent<HorizontalLayoutGroup>().spacing;
});
}
private void SpawnChildLines(GameObject parent, Transform mainFactUI)
{
var mainTransform = mainFactUI.GetComponent<RectTransform>();
var factWidth = mainTransform.rect.width;
// transform.positions are weird due to LayoutGroups => manually calculate offset
float xOffset = -factChildrenUI.GetComponent<RectTransform>().rect.width / 2 + factWidth / 2;
float yOffset = -transform.GetComponent<VerticalLayoutGroup>().spacing;
parent.ForAllChildren(par =>
{
// position at the top center of par rect
var position = par.transform.TransformPoint(new Vector2(0, par.GetComponent<RectTransform>().rect.yMax));
var line = Instantiate(childLine, position, Quaternion.identity, par.transform);
var uiLine = line.GetComponent<UILine>();
uiLine.points = new List<Vector2>() {
Vector2.zero,
new Vector2(0, -yOffset/2),
new Vector2(-xOffset, -yOffset/2),
new Vector2(-xOffset, -yOffset)
};
xOffset += factWidth + factChildrenUI.GetComponent<HorizontalLayoutGroup>().spacing;
});
}
#endregion Spawner
#region Helper #region Helper
/// <summary> /// <summary>
/// Check all fields of a Fact for references to other facts and return their ids /// Check all fields of a Fact for references to other facts and return their ids
...@@ -96,18 +171,5 @@ private static IEnumerable<string> GetReferencedPids(Fact f) ...@@ -96,18 +171,5 @@ private static IEnumerable<string> GetReferencedPids(Fact f)
.Where(field => field.FieldType == typeof(string) && field.Name.ToLower().StartsWith("pid")) .Where(field => field.FieldType == typeof(string) && field.Name.ToLower().StartsWith("pid"))
).Select(fi => (string)fi.GetValue(f)); ).Select(fi => (string)fi.GetValue(f));
} }
private void SpawnUIFacts(Transform uiParent, List<Fact> toSpawn)
{
uiParent.gameObject.DestroyAllChildren();
foreach (Fact f in toSpawn)
{
var spot = Instantiate(factSpotPrefab, uiParent);
// TODO: this link to DisplayFacts is not ideal: maybe refactor to SciptableObject or such
var display = f.instantiateDisplay(DisplayFacts.prefabDictionary[f.GetType()], spot.transform);
display.transform.localPosition = Vector3.zero;
}
}
#endregion Helper #endregion Helper
} }
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
public class UILine : Graphic
{
#region InspectorVariables
[Header("General")]
public List<Vector2> points = new();
public float width = 5f;
[Header("Rounding")]
public bool roundCorners = true;
public bool roundStart = false;
public bool roundEnd = false;
[Header("Dashed")]
public bool dashed = false;
public int dashLength = 10;
public int dashSpacing = 5;
#endregion InspectorVariables
#region UnityMethods
protected override void OnPopulateMesh(VertexHelper vh)
{
// clear old vertecies and triangles
vh.Clear();
// a line with less than 2 points does not make any sense => return
if (points.Count < 2)
return;
if (dashed)
GenerateLinesDashed(vh);
else
GenerateLinesStandard(vh);
if (roundStart)
CreateCircle(vh, points[0], width);
if (roundEnd)
CreateCircle(vh, points[^1], width);
}
#endregion UnityMethods
#region Implementation
#region GenerateLines
private void GenerateLinesStandard(VertexHelper vh)
{
points.Zip(points.Skip(1), (a, b) => Tuple.Create(a, b))
.ToList()
.ForEach(tup => CreateSegment(vh, tup.Item1, tup.Item2));
if (roundCorners)
{
// take all points except for start and end and apply rounding
points.Take(points.Count - 1).Skip(1).ToList()
.ForEach(p => CreateCircle(vh, p, width));
}
}
private void GenerateLinesDashed(VertexHelper vh)
{
float restLen = dashLength;
bool isDash = true;
var lines = points.Zip(points.Skip(1), (a, b) => Tuple.Create(a, b)).ToList();
for (int i = 0; i < lines.Count; i++)
{
var tup = lines[i];
Vector2 start = tup.Item1;
Vector2 end = tup.Item2;
Vector2 dir = (end - start).normalized;
// main spacing algorithm
Vector2 current = start;
while (Vector2.Distance(current, end) >= restLen)
{
Vector2 segmentEnd = current + restLen * dir;
if (isDash)
CreateSegment(vh, current, segmentEnd);
current = segmentEnd;
isDash = !isDash;
restLen = isDash ? dashLength : dashSpacing;
}
// is there a dash wrapping around a corner?
bool dashOverCorner = false;
float distLeft = Vector2.Distance(current, end);
if (!isDash)
restLen -= distLeft;
// dont fill remaining distance with dash, if it would be short (shorter than width/2)
else if (isDash && distLeft > width/2)
{
CreateSegment(vh, current, end);
restLen -= distLeft;
dashOverCorner = true;
}
// discard rest of dash if it is too short (shorter than width/2)
if (isDash && restLen < width/2)
{
isDash = false;
restLen = dashSpacing;
dashOverCorner = false; // dash does not wrap around corner as dashSpacing will follow
}
// only create round corners if roundCorners are enabled and there is a dash wrapping around the corner and not last corner (aka end)
if (roundCorners && dashOverCorner && i != lines.Count-1)
CreateCircle(vh, end, width);
}
}
#endregion GenerateLines
#region CreateLine
private void CreateSegment(VertexHelper vh, Vector2 start, Vector2 end)
{
//start += (Vector2)transform.position;
//end += (Vector2)transform.position;
UIVertex vertex = UIVertex.simpleVert;
vertex.color = color;
Vector2 dir = end - start;
Vector2 perp = Vector2.Perpendicular(dir).normalized;
Vector2 off = perp * width / 2;
vertex.position = new Vector3(start.x + off.x, start.y + off.y);
vh.AddVert(vertex);
vertex.position = new Vector3(end.x + off.x, end.y + off.y);
vh.AddVert(vertex);
vertex.position = new Vector3(end.x - off.x, end.y - off.y);
vh.AddVert(vertex);
vertex.position = new Vector3(start.x - off.x, start.y - off.y);
vh.AddVert(vertex);
int offset = vh.currentVertCount - 4;
vh.AddTriangle(0 + offset, 1 + offset, 2 + offset);
vh.AddTriangle(2 + offset, 3 + offset, 0 + offset);
}
#endregion CreateLine
#region Rounding
private void CreateCircle(VertexHelper vh, Vector2 center, float diameter, int sideCount = 20)
{
//center += (Vector2)transform.position;
UIVertex vertex = UIVertex.simpleVert;
vertex.color = color;
Vector3[] vertices = GetCirclePoints(diameter/2, sideCount, center).Union(new Vector3[] { center }).ToArray();
vertices.ToList().ForEach(vert => {
vertex.position = vert;
vh.AddVert(vertex);
}
);
int startVert = vh.currentVertCount - vertices.Length;
for (int i = 0; i < vertices.Length - 1; i++)
{
vh.AddTriangle(
vh.currentVertCount - 1, // center
startVert + i,
startVert + ((i + 1) % (vertices.Length - 1))
);
}
return;
}
protected static Vector3[] GetCirclePoints(float circleRadius, int pointCount, Vector3 offset)
{
Vector3[] circle = new Vector3[pointCount];
float slice = (2f * Mathf.PI) / pointCount;
for (int i = 0; i < pointCount; i++)
{
float angle = i * slice;
circle[i] = new Vector3(circleRadius * Mathf.Sin(angle), circleRadius * Mathf.Cos(angle)) + offset;
}
return circle;
}
#endregion Rounding
#endregion Implementation
}
fileFormatVersion: 2
guid: 8ed745d97410d6740921398c899d9ec0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment