diff --git a/Assets/Scenes/RiverWorld.unity b/Assets/Scenes/RiverWorld.unity index a633ddf7a9272cb656f3b8f2cc02ff1314337d73..a44f23726bc6aff29bdbae85b8a5c600df9bd0dd 100644 --- a/Assets/Scenes/RiverWorld.unity +++ b/Assets/Scenes/RiverWorld.unity @@ -14372,8 +14372,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: ca8bc7e0b1ca4384192fec35c8699cd9, type: 3} m_Name: m_EditorClassIdentifier: - snapZoneTop: {fileID: 0} - snapZoneBottom: {fileID: 0} + minimalSolutionHight: 6 --- !u!1001 &645585536 PrefabInstance: m_ObjectHideFlags: 0 @@ -15844,24 +15843,6 @@ Transform: type: 3} m_PrefabInstance: {fileID: 704600771} m_PrefabAsset: {fileID: 0} ---- !u!1 &707042057 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 7000045644623408183, guid: 8590393c51194934a95cdc2075fc4dec, - type: 3} - m_PrefabInstance: {fileID: 6999573641241424516} - m_PrefabAsset: {fileID: 0} ---- !u!114 &707042060 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 707042057} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4298702f3af5da54c9f8d43308ecb160, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1001 &715240475 PrefabInstance: m_ObjectHideFlags: 0 @@ -59575,6 +59556,11 @@ PrefabInstance: propertyPath: m_AnchoredPosition.y value: 75 objectReference: {fileID: 0} + - target: {fileID: 293934904593747527, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} - target: {fileID: 293934904814280933, guid: b996060e27da25c498842defc1996d84, type: 3} propertyPath: preferredStartScrollName @@ -59585,10 +59571,20 @@ PrefabInstance: propertyPath: m_AnchoredPosition.y value: 400 objectReference: {fileID: 0} + - target: {fileID: 293934905101627528, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: LevelReset + objectReference: {fileID: 0} + - target: {fileID: 293934905101627528, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: Restart, Assembly-CSharp + objectReference: {fileID: 0} - target: {fileID: 293934905101627533, guid: b996060e27da25c498842defc1996d84, type: 3} propertyPath: m_IsActive - value: 0 + value: 1 objectReference: {fileID: 0} - target: {fileID: 293934905461160920, guid: b996060e27da25c498842defc1996d84, type: 3} @@ -59735,6 +59731,31 @@ PrefabInstance: propertyPath: m_Name value: FrameITUI objectReference: {fileID: 0} + - target: {fileID: 293934906265310054, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: m_text + value: Restart Level + objectReference: {fileID: 0} + - target: {fileID: 293934906265310054, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: m_textAlignment + value: 65535 + objectReference: {fileID: 0} + - target: {fileID: 293934906265310054, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: m_TextStyleHashCode + value: -1183493901 + objectReference: {fileID: 0} + - target: {fileID: 293934906265310054, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: m_VerticalAlignment + value: 512 + objectReference: {fileID: 0} + - target: {fileID: 293934906265310054, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: m_HorizontalAlignment + value: 2 + objectReference: {fileID: 0} - target: {fileID: 293934906431221846, guid: b996060e27da25c498842defc1996d84, type: 3} propertyPath: m_AnchorMax.x diff --git a/Assets/Scripts/HideUI.cs b/Assets/Scripts/HideUI.cs index d75c46ffd555b47bf83a305f5e6a4da07179ddee..3b3c4dfb4ce56d744a8cb1d12982a2b11715afda 100644 --- a/Assets/Scripts/HideUI.cs +++ b/Assets/Scripts/HideUI.cs @@ -55,11 +55,11 @@ void Update() else if (Input.GetButton(modifier)) { if (Input.GetButtonDown(modundo)) - Facts.undo(); + LevelFacts.undo(); else if (Input.GetButtonDown(modredo)) - Facts.redo(); + LevelFacts.redo(); else if (Input.GetButtonDown(modreset)) - Facts.softreset(); + LevelFacts.softreset(); } /* diff --git a/Assets/Scripts/InteractionEngine/Character_Animations/TaskCharakterAnimation.cs b/Assets/Scripts/InteractionEngine/Character_Animations/TaskCharakterAnimation.cs index 1352120d04d7d4c2565a9221ade0832f14a09205..95100e226e4fced509ec37b55daffaba57a90949 100644 --- a/Assets/Scripts/InteractionEngine/Character_Animations/TaskCharakterAnimation.cs +++ b/Assets/Scripts/InteractionEngine/Character_Animations/TaskCharakterAnimation.cs @@ -26,7 +26,7 @@ public class TaskCharakterAnimation : MonoBehaviour private float rotationTime = 2; private bool happy = false; - private bool happyAnimationDone = false; + private bool LelvelVerifiedSolved = false; private float happyTimer = 0; private float happyTime = 7.5f; @@ -72,10 +72,10 @@ void Update() //Face walkAroundObject to Player (but only on y-Axis, so ignore x-and z-axis) currentTransform.LookAt(new Vector3(player.transform.position.x, currentTransform.position.y, player.transform.position.z)); - if(checkGameSolved() && taskCharacterAddressed && !happyAnimationDone) + if(taskCharacterAddressed && !LelvelVerifiedSolved && checkGameSolved()) { startHappy(); - happyAnimationDone = true; + //LelvelVerifiedSolved = true; } return; diff --git a/Assets/Scripts/InteractionEngine/CommunicationEvents.cs b/Assets/Scripts/InteractionEngine/CommunicationEvents.cs index 3cba5f0c5f7e0faf3b0a505cb3d0284fa934c507..b114c50134a041bb5b51f12d757724d3a60db7e8 100644 --- a/Assets/Scripts/InteractionEngine/CommunicationEvents.cs +++ b/Assets/Scripts/InteractionEngine/CommunicationEvents.cs @@ -5,44 +5,21 @@ public static class CommunicationEvents { - public class HitEvent : UnityEvent<RaycastHit> - { + public class HitEvent : UnityEvent<RaycastHit> { } - } - public class FactEvent : UnityEvent<Fact> - { + public class FactEvent : UnityEvent<Fact> { } - } + public class MouseOverFactEvent : UnityEvent<Transform> { } - public class MouseOverFactEvent : UnityEvent<Transform> - { + public class ToolModeEvent : UnityEvent<int> { } - } - public class ToolModeEvent : UnityEvent<int> { + public class ShinyEvent : UnityEvent<Fact> { } - } + public class SignalEvent : UnityEvent { } - public class ShinyEvent : UnityEvent<Fact> { + public class AnimationEvent : UnityEvent<GameObject, string> { } - } - - public class SignalEvent : UnityEvent { - - } - - public class AnimationEvent : UnityEvent<GameObject, String> { - - } - - public class AnimationEventWithUri : UnityEvent<String> - { - - } - - public class AnimationEventWithUris : UnityEvent<List<string>> - { - - } + public class AnimationEventWithUris : UnityEvent<List<string>> { } @@ -52,7 +29,7 @@ public class AnimationEventWithUris : UnityEvent<List<string>> public static ToolModeEvent ToolModeChangedEvent = new ToolModeEvent(); public static FactEvent AddFactEvent = new FactEvent(); public static FactEvent RemoveFactEvent = new FactEvent(); - + public static ShinyEvent PushoutFactEvent = new ShinyEvent(); public static ShinyEvent PushoutFactEndEvent = new ShinyEvent(); public static ShinyEvent PushoutFactFailEvent = new ShinyEvent(); @@ -60,12 +37,8 @@ public class AnimationEventWithUris : UnityEvent<List<string>> public static SignalEvent gameSucceededEvent = new SignalEvent(); public static SignalEvent gameNotSucceededEvent = new SignalEvent(); public static SignalEvent LevelReset = new SignalEvent(); - public static SignalEvent NewAssignmentEvent = new SignalEvent(); - //TODO: Remove this event after CompletionsDemo isn't necessary anymore - public static AnimationEventWithUri parameterDisplayHint = new AnimationEventWithUri(); - public static AnimationEvent ScrollFactHintEvent = new AnimationEvent(); public static FactEvent AnimateExistingFactEvent = new FactEvent(); public static FactEvent AnimateNonExistingFactEvent = new FactEvent(); @@ -76,8 +49,10 @@ public class AnimationEventWithUris : UnityEvent<List<string>> //-------------------------------Global Variables------------------------------------- //Global Level-List of Facts - public static FactOrganizer Facts = new FactOrganizer(); - + public static FactOrganizer LevelFacts = new FactOrganizer(true); + public static FactOrganizer SolutionManager = new FactOrganizer(false); + //TODO? List<[HashSet<string>, FactComparer]> + public static List<Fact> Solution = new List<Fact>(); public static bool ServerRunning = true; public static string ServerAdress = "localhost:8085"; diff --git a/Assets/Scripts/InteractionEngine/Fact.cs b/Assets/Scripts/InteractionEngine/Fact.cs index e7709422845922222a2b9db4f7db27aa92245689..f9481f1732253ad4df4945515c094dab45497dc9 100644 --- a/Assets/Scripts/InteractionEngine/Fact.cs +++ b/Assets/Scripts/InteractionEngine/Fact.cs @@ -59,6 +59,7 @@ public static AddFactResponse sendAdd(string path, string body) } } +[Serializable] public abstract class Fact { public GameObject Representation; @@ -67,8 +68,14 @@ public abstract class Fact protected string _URI; public string Label; + protected FactOrganizer _Facts; + private static int LabelId = 0; + protected Fact(FactOrganizer organizer) + { + this._Facts = organizer; + } public void rename(string newLabel) { @@ -117,6 +124,8 @@ public int GetFirstEmptyID() public abstract class FactWrappedCRTP<T>: Fact where T: FactWrappedCRTP<T> { + protected FactWrappedCRTP(FactOrganizer organizer) : base(organizer) { } + public override bool Equivalent(Fact f2) { return Equivalent(this, f2); @@ -124,7 +133,7 @@ public override bool Equivalent(Fact f2) public override bool Equivalent(Fact f1, Fact f2) { - return EquivalentWrapped((T)f1, (T)f2); + return f1.GetType() == f2.GetType() && EquivalentWrapped((T)f1, (T)f2); } protected abstract bool EquivalentWrapped(T f1, T f2); @@ -141,12 +150,12 @@ public abstract class AbstractLineFact: FactWrappedCRTP<AbstractLineFact> //only for temporary Use of LineFacts. //public AbstractLineFact() { } - public AbstractLineFact(string pid1, string pid2) + public AbstractLineFact(string pid1, string pid2, FactOrganizer organizer): base(organizer) { set_public_members(pid1, pid2); } - public AbstractLineFact(string pid1, string pid2, string backendURI) + public AbstractLineFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(organizer) { set_public_members(pid1, pid2); this._URI = backendURI; @@ -157,8 +166,8 @@ private void set_public_members(string pid1, string pid2) this.Pid1 = pid1; this.Pid2 = pid2; this.Label = generateLabel(); - PointFact pf1 = Facts[pid1] as PointFact; - PointFact pf2 = Facts[pid2] as PointFact; + PointFact pf1 = _Facts[pid1] as PointFact; + PointFact pf2 = _Facts[pid2] as PointFact; this.Dir = (pf2.Point - pf1.Point).normalized; } @@ -183,9 +192,9 @@ public abstract class AbstractLineFactWrappedCRTP<T>: AbstractLineFact where T: //only for temporary Use of LineFacts. //public AbstractLineFactWrappedCRTP() { } - public AbstractLineFactWrappedCRTP (string pid1, string pid2) : base(pid1, pid2) { } + public AbstractLineFactWrappedCRTP (string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer) { } - public AbstractLineFactWrappedCRTP (string pid1, string pid2, string backendURI) : base(pid1, pid2, backendURI) { } + public AbstractLineFactWrappedCRTP (string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer) { } protected override bool EquivalentWrapped(AbstractLineFact f1, AbstractLineFact f2) { @@ -203,7 +212,7 @@ public class PointFact : FactWrappedCRTP<PointFact> public Vector3 Normal; - public PointFact(Vector3 P, Vector3 N) + public PointFact(Vector3 P, Vector3 N, FactOrganizer organizer) : base(organizer) { this.Point = P; this.Normal = N; @@ -229,7 +238,7 @@ public PointFact(Vector3 P, Vector3 N) Debug.Log(this.URI); } - public PointFact(float a, float b, float c, string uri) + public PointFact(float a, float b, float c, string uri, FactOrganizer organizer) : base(organizer) { this.Point = new Vector3(a, b, c); this.Normal = new Vector3(0, 1, 0); @@ -245,7 +254,7 @@ public static PointFact parseFact(Scroll.ScrollFact fact) { float a = (float)((OMF)df.arguments[0]).f; float b = (float)((OMF)df.arguments[1]).f; float c = (float)((OMF)df.arguments[2]).f; - return new PointFact(a, b, c, uri); + return new PointFact(a, b, c, uri, LevelFacts); } else { return null; @@ -286,12 +295,19 @@ protected override bool EquivalentWrapped(PointFact f1, PointFact f2) public class LineFact : AbstractLineFactWrappedCRTP<LineFact> { - public LineFact(string pid1, string pid2, string backendURI) : base(pid1, pid2, backendURI) { } + public float Distance; + + public LineFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer) + { + SetDistance(); + } - public LineFact(string pid1, string pid2) : base(pid1, pid2) + public LineFact(string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer) { - PointFact pf1 = Facts[pid1] as PointFact; - PointFact pf2 = Facts[pid2] as PointFact; + SetDistance(); + + PointFact pf1 = _Facts[pid1] as PointFact; + PointFact pf2 = _Facts[pid2] as PointFact; string p1URI = pf1.URI; string p2URI = pf2.URI; @@ -323,9 +339,9 @@ public static LineFact parseFact(Scroll.ScrollFact fact) string pointAUri = ((OMS)((OMA)((Scroll.ScrollValueFact)fact).lhs).arguments[0]).uri; string pointBUri = ((OMS)((OMA)((Scroll.ScrollValueFact)fact).lhs).arguments[1]).uri; - if (Facts.ContainsKey(pointAUri) - && Facts.ContainsKey(pointBUri)) - return new LineFact(pointAUri, pointBUri, uri); + if (LevelFacts.ContainsKey(pointAUri) + && LevelFacts.ContainsKey(pointBUri)) + return new LineFact(pointAUri, pointBUri, uri, LevelFacts); //If dependent facts do not exist return null else { @@ -334,14 +350,14 @@ public static LineFact parseFact(Scroll.ScrollFact fact) } protected override string generateLabel() { - return "[" + Facts[Pid1].Label + Facts[Pid2].Label + "]"; + return "[" + _Facts[Pid1].Label + _Facts[Pid2].Label + "]"; } public override GameObject instantiateDisplay(GameObject prefab, Transform transform) { var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform); - obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = Facts[this.Pid1].Label; - obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = Facts[this.Pid2].Label; + obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid1].Label; + obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid2].Label; obj.GetComponent<FactWrapper>().fact = this; return obj; } @@ -352,24 +368,29 @@ protected override bool EquivalentWrapped(LineFact f1, LineFact f2) //(f1.Pid1 == f2.Pid2 && f1.Pid2 == f2.Pid1)) return true; - PointFact p1f1 = (PointFact)Facts[f1.Pid1]; - PointFact p2f1 = (PointFact)Facts[f1.Pid2]; - PointFact p1f2 = (PointFact)Facts[f2.Pid1]; - PointFact p2f2 = (PointFact)Facts[f2.Pid2]; + PointFact p1f1 = (PointFact)_Facts[f1.Pid1]; + PointFact p2f1 = (PointFact)_Facts[f1.Pid2]; + PointFact p1f2 = (PointFact)_Facts[f2.Pid1]; + PointFact p2f2 = (PointFact)_Facts[f2.Pid2]; return (p1f1.Equivalent(p1f2) && p2f1.Equivalent(p2f2)) ;//|| (p1f1.Equivalent(p2f2) && p2f1.Equivalent(p1f2)); } + + private void SetDistance() + { + this.Distance = Vector3.Distance(((PointFact)_Facts[Pid1]).Point, ((PointFact)_Facts[Pid2]).Point); + } } public class RayFact : AbstractLineFactWrappedCRTP<RayFact> { - public RayFact(string pid1, string pid2, string backendURI) : base(pid1, pid2, backendURI) { } + public RayFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer) { } - public RayFact(string pid1, string pid2) : base(pid1, pid2) + public RayFact(string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer) { - PointFact pf1 = Facts[pid1] as PointFact; - PointFact pf2 = Facts[pid2] as PointFact; + PointFact pf1 = _Facts[pid1] as PointFact; + PointFact pf2 = _Facts[pid2] as PointFact; string p1URI = pf1.URI; string p2URI = pf2.URI; @@ -401,9 +422,9 @@ public static RayFact parseFact(Scroll.ScrollFact fact) string pointAUri = ((OMS)((OMA)((Scroll.ScrollSymbolFact)fact).df).arguments[0]).uri; string pointBUri = ((OMS)((OMA)((Scroll.ScrollSymbolFact)fact).df).arguments[1]).uri; - if (Facts.ContainsKey(pointAUri) - && Facts.ContainsKey(pointBUri)) - return new RayFact(pointAUri, pointBUri, uri); + if (LevelFacts.ContainsKey(pointAUri) + && LevelFacts.ContainsKey(pointBUri)) + return new RayFact(pointAUri, pointBUri, uri, LevelFacts); //If dependent facts do not exist return null } @@ -412,7 +433,7 @@ public static RayFact parseFact(Scroll.ScrollFact fact) protected override string generateLabel() { - return "–" + Facts[Pid1].Label + Facts[Pid2].Label + "–"; + return "–" + _Facts[Pid1].Label + _Facts[Pid2].Label + "–"; } public override GameObject instantiateDisplay(GameObject prefab, Transform transform) { @@ -428,9 +449,9 @@ protected override bool EquivalentWrapped(RayFact f1, RayFact f2) if (!Math3d.IsApproximatelyParallel(f1.Dir, f2.Dir)) return false; - PointFact p1f1 = (PointFact)Facts[f1.Pid1]; - PointFact p1f2 = (PointFact)Facts[f2.Pid1]; - PointFact p2f2 = (PointFact)Facts[f2.Pid2]; + PointFact p1f1 = (PointFact)_Facts[f1.Pid1]; + PointFact p1f2 = (PointFact)_Facts[f2.Pid1]; + PointFact p2f2 = (PointFact)_Facts[f2.Pid2]; return Math3d.IsPointApproximatelyOnLine(p1f1.Point, f1.Dir, p1f2.Point) && Math3d.IsPointApproximatelyOnLine(p1f1.Point, f1.Dir, p2f2.Point); @@ -442,14 +463,14 @@ public class OnLineFact : FactWrappedCRTP<OnLineFact> //Id's of the Point and the Line it's on public string Pid, Rid; - public OnLineFact(string pid, string rid) + public OnLineFact(string pid, string rid, FactOrganizer organizer) : base(organizer) { this.Pid = pid; this.Rid = rid; this.Label = generateLabel(); - PointFact pf = Facts[pid] as PointFact; - RayFact rf = Facts[rid] as RayFact; + PointFact pf = _Facts[pid] as PointFact; + RayFact rf = _Facts[rid] as RayFact; string pURI = pf.URI; string rURI = rf.URI; @@ -477,7 +498,7 @@ public OnLineFact(string pid, string rid) Debug.Log(this.URI); } - public OnLineFact(string pid, string rid, string uri) + public OnLineFact(string pid, string rid, string uri, FactOrganizer organizer) : base(organizer) { this.Pid = pid; this.Rid = rid; @@ -491,9 +512,9 @@ public static OnLineFact parseFact(Scroll.ScrollFact fact) string lineUri = ((OMS)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[0]).uri; string pointUri = ((OMS)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[1]).uri; - if (Facts.ContainsKey(pointUri) - && Facts.ContainsKey(lineUri)) - return new OnLineFact(pointUri, lineUri, uri); + if (LevelFacts.ContainsKey(pointUri) + && LevelFacts.ContainsKey(lineUri)) + return new OnLineFact(pointUri, lineUri, uri, LevelFacts); //If dependent facts do not exist return null else @@ -501,7 +522,7 @@ public static OnLineFact parseFact(Scroll.ScrollFact fact) } protected override string generateLabel() { - return Facts[Pid].Label + "∈" + Facts[Rid].Label; + return _Facts[Pid].Label + "∈" + _Facts[Rid].Label; } public override Boolean hasDependentFacts() @@ -517,8 +538,8 @@ public override string[] getDependentFactIds() public override GameObject instantiateDisplay(GameObject prefab, Transform transform) { var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform); - obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = Facts[this.Pid].Label; - obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = Facts[this.Rid].Label; + obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid].Label; + obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Rid].Label; obj.GetComponent<FactWrapper>().fact = this; return obj; } @@ -533,10 +554,10 @@ protected override bool EquivalentWrapped(OnLineFact f1, OnLineFact f2) if (f1.Pid == f2.Pid && f1.Rid == f2.Rid) return true; - PointFact pf1 = (PointFact)Facts[f1.Pid]; - RayFact rf1 = (RayFact)Facts[f1.Rid]; - PointFact pf2 = (PointFact)Facts[f2.Pid]; - RayFact rf2 = (RayFact)Facts[f2.Rid]; + PointFact pf1 = (PointFact)_Facts[f1.Pid]; + RayFact rf1 = (RayFact)_Facts[f1.Rid]; + PointFact pf2 = (PointFact)_Facts[f2.Pid]; + RayFact rf2 = (RayFact)_Facts[f2.Rid]; return pf1.Equivalent(pf2) && rf1.Equivalent(rf2); } @@ -548,15 +569,15 @@ public class AngleFact : FactWrappedCRTP<AngleFact> public string Pid1, Pid2, Pid3; public bool is_right_angle; - public AngleFact(string pid1, string pid2, string pid3) + public AngleFact(string pid1, string pid2, string pid3, FactOrganizer organizer) : base(organizer) { this.Pid1 = pid1; this.Pid2 = pid2; this.Pid3 = pid3; - PointFact pf1 = Facts[pid1] as PointFact; - PointFact pf2 = Facts[pid2] as PointFact; - PointFact pf3 = Facts[pid3] as PointFact; + PointFact pf1 = _Facts[pid1] as PointFact; + PointFact pf2 = _Facts[pid2] as PointFact; + PointFact pf3 = _Facts[pid3] as PointFact; float v = GetAngle(); // sets is_right_angle this.Label = generateLabel(); //needs is_right_angle @@ -580,7 +601,7 @@ public AngleFact(string pid1, string pid2, string pid3) Debug.Log(this.URI); } - public AngleFact(string Pid1, string Pid2, string Pid3, string backendURI) + public AngleFact(string Pid1, string Pid2, string Pid3, string backendURI, FactOrganizer organizer) : base(organizer) { this.Pid1 = Pid1; this.Pid2 = Pid2; @@ -614,11 +635,11 @@ public static AngleFact parseFact(Scroll.ScrollFact fact) pointCUri = ((OMS)((OMA)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[1]).arguments[2]).uri; } - if (Facts.ContainsKey(pointAUri) - && Facts.ContainsKey(pointBUri) - && Facts.ContainsKey(pointCUri)) + if (LevelFacts.ContainsKey(pointAUri) + && LevelFacts.ContainsKey(pointBUri) + && LevelFacts.ContainsKey(pointCUri)) - return new AngleFact(pointAUri, pointBUri, pointCUri, uri); + return new AngleFact(pointAUri, pointBUri, pointCUri, uri, LevelFacts); else //If dependent facts do not exist return null return null; @@ -626,14 +647,14 @@ public static AngleFact parseFact(Scroll.ScrollFact fact) protected override string generateLabel() { - return (is_right_angle ? "⊾" : "∠") + Facts[Pid1].Label + Facts[Pid2].Label + Facts[Pid2].Label; + return (is_right_angle ? "⊾" : "∠") + _Facts[Pid1].Label + _Facts[Pid2].Label + _Facts[Pid3].Label; } private float GetAngle() { - PointFact pf1 = Facts[Pid1] as PointFact; - PointFact pf2 = Facts[Pid2] as PointFact; - PointFact pf3 = Facts[Pid3] as PointFact; + PointFact pf1 = _Facts[Pid1] as PointFact; + PointFact pf2 = _Facts[Pid2] as PointFact; + PointFact pf3 = _Facts[Pid3] as PointFact; float v = Vector3.Angle((pf1.Point - pf2.Point), (pf3.Point - pf2.Point)); this.is_right_angle = Mathf.Abs(v - 90.0f) < 0.01; @@ -695,9 +716,9 @@ public override string[] getDependentFactIds() public override GameObject instantiateDisplay(GameObject prefab, Transform transform) { var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform); - obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = Facts[this.Pid1].Label; - obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = Facts[this.Pid2].Label; - obj.transform.GetChild(2).gameObject.GetComponent<TextMeshProUGUI>().text = Facts[this.Pid3].Label; + obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid1].Label; + obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid2].Label; + obj.transform.GetChild(2).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid3].Label; obj.GetComponent<FactWrapper>().fact = this; return obj; } @@ -713,12 +734,12 @@ protected override bool EquivalentWrapped(AngleFact f1, AngleFact f2) //(f1.Pid1 == f2.Pid3 && f1.Pid2 == f2.Pid2 && f1.Pid3 == f2.Pid1)) return true; - PointFact p1f1 = (PointFact)Facts[f1.Pid1]; - PointFact p2f1 = (PointFact)Facts[f1.Pid2]; - PointFact p3f1 = (PointFact)Facts[f1.Pid3]; - PointFact p1f2 = (PointFact)Facts[f2.Pid1]; - PointFact p2f2 = (PointFact)Facts[f2.Pid2]; - PointFact p3f2 = (PointFact)Facts[f2.Pid3]; + PointFact p1f1 = (PointFact)_Facts[f1.Pid1]; + PointFact p2f1 = (PointFact)_Facts[f1.Pid2]; + PointFact p3f1 = (PointFact)_Facts[f1.Pid3]; + PointFact p1f2 = (PointFact)_Facts[f2.Pid1]; + PointFact p2f2 = (PointFact)_Facts[f2.Pid2]; + PointFact p3f2 = (PointFact)_Facts[f2.Pid3]; return (p1f1.Equivalent(p1f2) && p2f1.Equivalent(p2f2) && p3f1.Equivalent(p3f2)) ;//|| (p1f1.Equivalent(p3f2) && p2f1.Equivalent(p2f2) && p1f1.Equivalent(p3f2)); diff --git a/Assets/Scripts/InteractionEngine/FactComparer.cs b/Assets/Scripts/InteractionEngine/FactComparer.cs new file mode 100644 index 0000000000000000000000000000000000000000..7259946f0fbd04e5daf53ba80f828a215498cd40 --- /dev/null +++ b/Assets/Scripts/InteractionEngine/FactComparer.cs @@ -0,0 +1,50 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public abstract class FactComparer : EqualityComparer<Fact> +{ + protected bool search_righthanded; + + protected abstract bool Compare (Fact search, Fact fact); + + public FactComparer SetSearchRight() + { + search_righthanded = true; + return this; + } + public FactComparer SetSearchLeft() + { + search_righthanded = false; + return this; + } + + public override bool Equals(Fact left, Fact right) + { + return search_righthanded ? Compare(left, right) : Compare(right, left); + } + + public override int GetHashCode(Fact obj) + { + return 0; //obj.GetHashCode(); + } +} + +public class FactEquivalentsComparer : FactComparer +{ + protected override bool Compare (Fact search, Fact fact) + { + return search.Equivalent(fact); + } +} + +class LineFactHightDirectionComparer : FactComparer +{ + protected override bool Compare (Fact search, Fact fact) + { + return fact is LineFact && search is LineFact + && Math3d.IsApproximatelyParallel(((LineFact) fact).Dir, ((LineFact) search).Dir) + && ((LineFact) fact).Distance > ((LineFact) search).Distance + Math3d.vectorPrecission; + // && Mathf.Approximately(((LineFact) x).Distance, ((LineFact) y).Distance); + } +} diff --git a/Assets/Scripts/InteractionEngine/FactComparer.cs.meta b/Assets/Scripts/InteractionEngine/FactComparer.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..a6b2fb0a967f0679396dc6fbe07665c58f90203e --- /dev/null +++ b/Assets/Scripts/InteractionEngine/FactComparer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d7d3beaa8cf49a4d81780b5264532c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/InteractionEngine/FactManager.cs b/Assets/Scripts/InteractionEngine/FactManager.cs index 89a6cc7dfb5fa894d9356e5bddff71c7c8b17999..26bb2b66879dfa02abca925557d67f120c15cbbb 100644 --- a/Assets/Scripts/InteractionEngine/FactManager.cs +++ b/Assets/Scripts/InteractionEngine/FactManager.cs @@ -10,38 +10,38 @@ public class FactManager : MonoBehaviour //TODO! communicate success/ failure public static Fact AddFactIfNotFound(Fact fact, out bool exists, bool samestep) { - return Facts[Facts.Add(fact, out exists, samestep)]; + return LevelFacts[LevelFacts.Add(fact, out exists, samestep)]; } public PointFact AddPointFact(RaycastHit hit, bool samestep = false) { - return (PointFact) AddFactIfNotFound(new PointFact(hit.point, hit.normal), out bool obsolete, samestep); + return (PointFact) AddFactIfNotFound(new PointFact(hit.point, hit.normal, LevelFacts), out bool obsolete, samestep); } public PointFact AddPointFact(Vector3 point, Vector3 normal, bool samestep = false) { - return (PointFact) AddFactIfNotFound(new PointFact(point, normal), out bool obsolete, samestep); + return (PointFact) AddFactIfNotFound(new PointFact(point, normal, LevelFacts), out bool obsolete, samestep); } public OnLineFact AddOnLineFact(string pid, string lid, bool samestep = false) { - return (OnLineFact)AddFactIfNotFound(new OnLineFact(pid, lid), out bool obsolete, samestep); + return (OnLineFact)AddFactIfNotFound(new OnLineFact(pid, lid, LevelFacts), out bool obsolete, samestep); } public LineFact AddLineFact(string pid1, string pid2, bool samestep = false) { - return (LineFact)AddFactIfNotFound(new LineFact(pid1, pid2), out bool obsolete, samestep); + return (LineFact)AddFactIfNotFound(new LineFact(pid1, pid2, LevelFacts), out bool obsolete, samestep); } public RayFact AddRayFact(string pid1, string pid2, bool samestep = false) { - RayFact rayFact = (RayFact)AddFactIfNotFound(new RayFact(pid1, pid2), out bool exists, samestep); + RayFact rayFact = (RayFact)AddFactIfNotFound(new RayFact(pid1, pid2, LevelFacts), out bool exists, samestep); if (exists) return rayFact; //Add all PointFacts on Ray as OnLineFacts - PointFact rayP1 = (PointFact)Facts[rayFact.Pid1]; - PointFact rayP2 = (PointFact)Facts[rayFact.Pid2]; + PointFact rayP1 = (PointFact)LevelFacts[rayFact.Pid1]; + PointFact rayP2 = (PointFact)LevelFacts[rayFact.Pid2]; int layerMask = LayerMask.GetMask("Point"); RaycastHit[] hitsA = Physics.RaycastAll(rayP1.Point, rayFact.Dir, Mathf.Infinity, layerMask); RaycastHit[] hitsB = Physics.RaycastAll(rayP2.Point, -rayFact.Dir, Mathf.Infinity, layerMask); @@ -69,7 +69,7 @@ void AddHitIfOnLine(RaycastHit hit) public AngleFact AddAngleFact(string pid1, string pid2, string pid3, bool samestep = false) { - return (AngleFact)AddFactIfNotFound(new AngleFact(pid1, pid2, pid3), out bool obsolete, samestep); + return (AngleFact)AddFactIfNotFound(new AngleFact(pid1, pid2, pid3, LevelFacts), out bool obsolete, samestep); } } diff --git a/Assets/Scripts/InteractionEngine/FactOrganizer.cs b/Assets/Scripts/InteractionEngine/FactOrganizer.cs index f263b041201b7b460f53dab880f10bdcaee7ebc0..dbe47e92e744019ba9c13199e84237ac3a53feea 100644 --- a/Assets/Scripts/InteractionEngine/FactOrganizer.cs +++ b/Assets/Scripts/InteractionEngine/FactOrganizer.cs @@ -7,12 +7,15 @@ //TODO? hide base dict //TODO: MMT: move some functionality there //TODO: consequent!= samestep != dependent -//TODO! use URI as key -//PERF: avoid string as key (hash -> colission? -> strcmp[!]) +//PERF: avoid string as key (general: allocations & dict: hash -> colission? -> strcmp[!]) +[System.Serializable] public class FactOrganizer: Dictionary<string, Fact> { + // InvokeEvents? + private bool invoke; + private Dictionary<string, meta> MetaInf = new Dictionary<string, meta>(); private List<stepnote> Workflow = new List<stepnote>(); // notes position in Workflow for un-/redo; the pointed to element is non-acitve @@ -21,7 +24,7 @@ public class FactOrganizer: Dictionary<string, Fact> private int worksteps = 0; private int backlog = 0; // set if recently been resetted - private bool resetted = false; + private bool soft_resetted = false; private struct stepnote { @@ -71,36 +74,33 @@ public meta(int workflow_id, bool active = true) } } - public FactOrganizer() : base() { } - - public FactOrganizer(IDictionary<string, Fact> dictionary) : base(dictionary) { } - - - //TODO: PERF: better way than string search? -> use string as key! - public bool searchURI(string uri, out string found) + public FactOrganizer(bool invoke = false) : base() { - foreach(var element in this) - if (element.Value.URI.Equals(uri)) - { - found = element.Key; - return true; - } + this.invoke = invoke; + } - found = null; - return false; + public FactOrganizer(IDictionary<string, Fact> dictionary, bool invoke = false) : base(dictionary) + { + this.invoke = invoke; } + //TODO? MMT? PERF: O(n), every Fact-insertion - private bool FindEquivalent(Fact search, out Fact found) + private bool FindEquivalent(Fact search, out string found, out bool exact) // Looks for existent facts (found) which are very similar to prposed fact (search) // does not check active state { + if (exact = this.ContainsKey(search.URI)) + { + found = search.URI; + return true; + } + foreach (var entry in this) { - if (entry.Value.GetType() == search.GetType() && - entry.Value.Equivalent(search)) + if (entry.Value.Equivalent(search)) { - found = entry.Value; + found = entry.Key; return true; } } @@ -110,7 +110,7 @@ private bool FindEquivalent(Fact search, out Fact found) } private void WorkflowAdd(stepnote note) - // prunes & adds Workflow; updates meta struct; Invokes Events + // prunes & adds Workflow; Invokes Events { PruneWorkflow(); @@ -127,18 +127,16 @@ private void WorkflowAdd(stepnote note) Workflow.Add(note); marker = Workflow.Count; - // update active info - meta info = MetaInf[note.Id]; - info.active = note.creation; - MetaInf[note.Id] = info; - InvokeFactEvent(note.creation, note.Id); } private void PruneWorkflow() // set current (displayed) state in stone; resets un-redo parameters { - if (backlog > 0) + if (soft_resetted) + this.hardreset(false); + + else if (backlog > 0) { worksteps -= backlog; backlog = 0; @@ -155,13 +153,6 @@ private void PruneWorkflow() base.Remove(last.Id); MetaInf.Remove(last.Id); } - else - // update active status - { - meta inf = MetaInf[last.Id]; - inf.active = !last.creation; - MetaInf[last.Id] = inf; - } } // prune Worklfow down to marker @@ -172,29 +163,35 @@ private void PruneWorkflow() public new void Add(string key, Fact value) // hide { - this.Add(value, out bool obsolete); + this.Add(value, out _); } public string Add(Fact value, out bool exists, bool samestep = false) // also checks for duplicates and active state // returns key of actual Fact { - if (resetted) - this.hardreset(false); - string key; - if (exists = FindEquivalent(value, out Fact found)) - { - //TODO: MMT: del 'fact' (value) in MMT (alt.: s.TODO in addFact) - key = found.URI; - if (MetaInf[key].active) + if (exists = FindEquivalent(value, out key, out bool exact)) + { + if (!exact) + // no longer needed + value.delete(); + + if (MetaInf[key].workflow_id >= marker) + // check for zombie-status + // protect zombie from beeing pruned + MetaInf[key] = new meta(marker, true); + + // zombies are undead! + else if (MetaInf[key].active) + // desired outcome already achieved return key; + } else + // brand new Fact { - //TODO: MMT: alt: insert in MMT if needed here/ on Invoke() (see WorkflowAdd) - key = value.URI; base.Add(key, value); MetaInf.Add(key, new meta(marker, true)); @@ -212,11 +209,7 @@ public string Add(Fact value, out bool exists, bool samestep = false) public bool Remove(Fact value, bool samestep = false) { - if (!this.ContainsKey(value.URI)) - return false; - - this.Remove(value.URI, samestep); - return true; + return this.Remove(value.URI, samestep); } public bool Remove(string key, bool samestep = false) @@ -250,20 +243,10 @@ public bool safe_dependencies(string key, out List<string> dependencies) int pos = MetaInf[key].workflow_id; dependencies.Add(key); - /* consequent != samestep != dependent - // get steproot - if (Workflow[pos].samestep) - pos = Workflow[pos].steplink; - - // add entire step - for (int i = pos; i < Workflow[pos].steplink; i++) - dependencies.Add(Workflow[i].Id); - pos = Workflow[pos].steplink; - */ - // accumulate facts that are dependent of dependencies for (int i = pos; i < marker; i++) { + // TODO: consequent != samestep != dependent (want !consequent) if (!Workflow[i].creation) { // just try @@ -295,20 +278,23 @@ private void reversestep(int pos, bool samestep = false) { pos--; - // check for valid step (implicit reset check) if (pos >= marker) + // check for valid step (implicit reset check) return; for (int i = pos, stop = Workflow[pos].samestep ? Workflow[pos].steplink : pos; i >= stop; i--, samestep = true) { - WorkflowAdd(new stepnote(Workflow[i].Id, samestep, !Workflow[i].creation, this)); + if (Workflow[i].creation) + Remove(Workflow[i].Id, samestep); + else + WorkflowAdd(new stepnote(Workflow[i].Id, samestep, true, this)); } } public void undo() { - if (resetted) + if (soft_resetted) fastforward(); // revert softreset else if (backlog < worksteps) { @@ -328,7 +314,7 @@ public void undo() public void redo() { - resetted = false; + soft_resetted = false; if (backlog > 0) { @@ -350,18 +336,19 @@ public void redo() // Does not Invoke RemoveFactEvent(s)! { base.Clear(); + MetaInf.Clear(); Workflow.Clear(); marker = 0; worksteps = 0; backlog = 0; - resetted = false; + soft_resetted = false; } public void hardreset(bool invoke_event = true) { foreach(var entry in this) { - if (invoke_event) //TODO? check if removed + if (invoke_event && invoke && MetaInf[entry.Key].active) CommunicationEvents.RemoveFactEvent.Invoke(entry.Value); entry.Value.delete(); } @@ -370,7 +357,7 @@ public void hardreset(bool invoke_event = true) public void softreset() { - if (resetted) + if (soft_resetted) { fastforward(); return; @@ -381,7 +368,7 @@ public void softreset() while (marker > 0) undo(); - resetted = true; + soft_resetted = true; } public void fastforward() @@ -394,19 +381,65 @@ public void fastforward() public void store() { // TODO: save state of all of this? + // probably nothing: + // safe class instance somewhere } - public void load() + public void load(bool draw_all = true) + // call this after assigning a stored instance in an empty world { // TODO: see issue #58 + + foreach (var mett in MetaInf) + { + // update active info if needed + if (mett.Value.active) + { + meta info = mett.Value; + info.active = false; + MetaInf[mett.Key] = info; + } + } + + marker = 0; + var stop = backlog; + backlog = worksteps; + + if(draw_all) + while(backlog > stop) + redo(); } private void InvokeFactEvent(bool creation, string Id) { - if (creation) - CommunicationEvents.AddFactEvent.Invoke(this[Id]); - else - CommunicationEvents.RemoveFactEvent.Invoke(this[Id]); + // update meta struct + meta info = MetaInf[Id]; + info.active = creation; + MetaInf[Id] = info; + + if (invoke) + if (creation) + CommunicationEvents.AddFactEvent.Invoke(this[Id]); + else + CommunicationEvents.RemoveFactEvent.Invoke(this[Id]); + } + + public bool StaticlySovled(List<Fact> StaticSolution, out List<Fact> MissingElements) + // QoL for simple Levels + { + return DynamiclySolved(StaticSolution, out MissingElements, out _, new FactEquivalentsComparer()); + } + + //TODO: PERF: see CommunicationEvents.Solution + public bool DynamiclySolved(List<Fact> MinimalSolution, out List<Fact> MissingElements, out List<Fact> Solutions, FactComparer FactComparer) + { + Solutions = this.Values.Where(f => MetaInf[f.URI].active) + .Where(active => MinimalSolution.Contains(active, FactComparer.SetSearchRight())) + .ToList(); + + MissingElements = MinimalSolution.Except(Solutions, FactComparer.SetSearchLeft()).ToList(); + + return MissingElements.Count == 0; } } \ No newline at end of file diff --git a/Assets/Scripts/InteractionEngine/FactSpawner.cs b/Assets/Scripts/InteractionEngine/FactSpawner.cs index 9874aef3b20413fab3d5183935851e976ff156b5..0500cac89b3599026e8b6b36448ff86171c30f49 100644 --- a/Assets/Scripts/InteractionEngine/FactSpawner.cs +++ b/Assets/Scripts/InteractionEngine/FactSpawner.cs @@ -65,8 +65,8 @@ public Fact SpawnLine(Fact fact) { LineFact lineFact = ((LineFact)fact); - PointFact pointFact1 = (Facts[lineFact.Pid1] as PointFact); - PointFact pointFact2 = (Facts[lineFact.Pid2] as PointFact); + PointFact pointFact1 = (LevelFacts[lineFact.Pid1] as PointFact); + PointFact pointFact2 = (LevelFacts[lineFact.Pid2] as PointFact); Vector3 point1 = pointFact1.Point; Vector3 point2 = pointFact2.Point; //Change FactRepresentation to Line @@ -102,8 +102,8 @@ public Fact SpawnRay(Fact fact) { RayFact rayFact = ((RayFact)fact); - PointFact pointFact1 = (Facts[rayFact.Pid1] as PointFact); - PointFact pointFact2 = (Facts[rayFact.Pid2] as PointFact); + PointFact pointFact1 = (LevelFacts[rayFact.Pid1] as PointFact); + PointFact pointFact2 = (LevelFacts[rayFact.Pid2] as PointFact); Vector3 point1 = pointFact1.Point; @@ -145,9 +145,9 @@ public Fact SpawnAngle(Fact fact) { AngleFact angleFact = (AngleFact)fact; - Vector3 point1 = (Facts[angleFact.Pid1] as PointFact).Point; - Vector3 point2 = (Facts[angleFact.Pid2] as PointFact).Point; - Vector3 point3 = (Facts[angleFact.Pid3] as PointFact).Point; + Vector3 point1 = (LevelFacts[angleFact.Pid1] as PointFact).Point; + Vector3 point2 = (LevelFacts[angleFact.Pid2] as PointFact).Point; + Vector3 point3 = (LevelFacts[angleFact.Pid3] as PointFact).Point; //Length of the Angle relative to the Length of the shortest of the two lines (point2->point1) and (point2->point3) float lengthFactor = 0.3f; diff --git a/Assets/Scripts/InteractionEngine/Gadgets/AngleTool.cs b/Assets/Scripts/InteractionEngine/Gadgets/AngleTool.cs index ce595794e6f78ba13ee4dd80c70195a496deb323..be18d2d330253b1ce1d4dff14b853fb0c5bbae94 100644 --- a/Assets/Scripts/InteractionEngine/Gadgets/AngleTool.cs +++ b/Assets/Scripts/InteractionEngine/Gadgets/AngleTool.cs @@ -49,7 +49,7 @@ public override void OnHit(RaycastHit hit) if (!this.isActiveAndEnabled) return; if (hit.transform.gameObject.layer == LayerMask.NameToLayer("Point")) { - PointFact tempFact = (PointFact)Facts[hit.transform.GetComponent<FactObject>().URI]; + PointFact tempFact = (PointFact)LevelFacts[hit.transform.GetComponent<FactObject>().URI]; //If two points were already selected and now the third point got selected if (this.angleModeIsFirstPointSelected && this.angleModeIsSecondPointSelected) @@ -138,7 +138,7 @@ public void UpdateCurveDrawing(Vector3 currentPosition) //TODO! PERF O(n) //Find the nearest of all potential third points PointFact nearestPoint = null; - foreach (var entry in Facts) + foreach (var entry in LevelFacts) { Fact fact = entry.Value; if (fact is PointFact && fact.URI != angleModeFirstPointSelected.URI && fact.URI != angleModeSecondPointSelected.URI && nearestPoint == null) diff --git a/Assets/Scripts/InteractionEngine/Gadgets/LineTool.cs b/Assets/Scripts/InteractionEngine/Gadgets/LineTool.cs index f125fbb601540006179b91ab31a1ba303531bc50..e3449d9347a8f28472c3822c6bbda7cebf21adec 100644 --- a/Assets/Scripts/InteractionEngine/Gadgets/LineTool.cs +++ b/Assets/Scripts/InteractionEngine/Gadgets/LineTool.cs @@ -40,7 +40,7 @@ public override void OnHit(RaycastHit hit) if (!this.isActiveAndEnabled) return; if (hit.transform.gameObject.layer == LayerMask.NameToLayer("Point")) { - Fact tempFact = Facts[hit.transform.GetComponent<FactObject>().URI]; + Fact tempFact = LevelFacts[hit.transform.GetComponent<FactObject>().URI]; //If first point was already selected AND second point != first point if (this.LineModeIsFirstPointSelected && this.LineModeFirstPointSelected.URI != tempFact.URI) diff --git a/Assets/Scripts/InteractionEngine/Gadgets/LotTool.cs b/Assets/Scripts/InteractionEngine/Gadgets/LotTool.cs index 8b8095d84aa6f0cba0e5b830d84794eb9ddaa7ae..b77f0e6f455cc0db04547b5a6f7f8c8f68d578c2 100644 --- a/Assets/Scripts/InteractionEngine/Gadgets/LotTool.cs +++ b/Assets/Scripts/InteractionEngine/Gadgets/LotTool.cs @@ -72,7 +72,7 @@ void CreateRayAndAngles(string pidIntersectionPoint, string pidLotPoint, bool sa //If baseline already selected and point selected else if (this.LotModeIsLineSelected && !this.LotModeIsPointSelected && hit.transform.gameObject.layer == LayerMask.NameToLayer("Point")) { - PointFact tempFact = Facts[hit.transform.GetComponent<FactObject>().URI] as PointFact; + PointFact tempFact = LevelFacts[hit.transform.GetComponent<FactObject>().URI] as PointFact; Vector3 intersectionPoint = Math3d.ProjectPointOnLine(this.LotModeLinePointA.Point, this.LotModeLineSelected.Dir, tempFact.Point); @@ -99,12 +99,12 @@ void CreateRayAndAngles(string pidIntersectionPoint, string pidLotPoint, bool sa && (hit.transform.gameObject.layer == LayerMask.NameToLayer("Ray") || hit.transform.gameObject.layer == LayerMask.NameToLayer("Line"))) { - Fact tempFact = Facts[hit.transform.GetComponent<FactObject>().URI]; + Fact tempFact = LevelFacts[hit.transform.GetComponent<FactObject>().URI]; //Activate LineDrawing for preview this.LotModeIsLineSelected = true; this.LotModeLineSelected = tempFact as AbstractLineFact; - this.LotModeLinePointA = (PointFact) Facts[this.LotModeLineSelected.Pid1]; + this.LotModeLinePointA = (PointFact) LevelFacts[this.LotModeLineSelected.Pid1]; this.LotModeLineHit = hit; this.ActivateLineDrawing(); } diff --git a/Assets/Scripts/InteractionEngine/Gadgets/Pendulum.cs b/Assets/Scripts/InteractionEngine/Gadgets/Pendulum.cs index 7be05aed12822de0315a733b3d38386303124b4b..135f598c4ea82e1e9efea788d583deb9e4e27514 100644 --- a/Assets/Scripts/InteractionEngine/Gadgets/Pendulum.cs +++ b/Assets/Scripts/InteractionEngine/Gadgets/Pendulum.cs @@ -45,7 +45,7 @@ public override void OnHit(RaycastHit hit) if (hit.transform.gameObject.layer == LayerMask.NameToLayer("Point")) { - PointFact tempFact = Facts[hit.transform.GetComponent<FactObject>().URI] as PointFact; + PointFact tempFact = LevelFacts[hit.transform.GetComponent<FactObject>().URI] as PointFact; //Raycast downwoard RaycastHit ground; diff --git a/Assets/Scripts/InteractionEngine/Gadgets/Remover.cs b/Assets/Scripts/InteractionEngine/Gadgets/Remover.cs index 7b626909dbe94321708242d84ba950719246d07a..6b64d8bcada8ccc008717affeee73b4186c84769 100644 --- a/Assets/Scripts/InteractionEngine/Gadgets/Remover.cs +++ b/Assets/Scripts/InteractionEngine/Gadgets/Remover.cs @@ -32,7 +32,7 @@ public override void OnHit(RaycastHit hit) // TODO: ask/warn user to cascade var hid = hit.transform.GetComponent<FactObject>().URI; - Facts.Remove(hid); + LevelFacts.Remove(hid); } } diff --git a/Assets/Scripts/InteractionEngine/Gadgets/Tape.cs b/Assets/Scripts/InteractionEngine/Gadgets/Tape.cs index c31d81e9811e2802ed5ad78eaa69c2530460e284..6b24581e5d61fcc53581705aae177a1f86626b1a 100644 --- a/Assets/Scripts/InteractionEngine/Gadgets/Tape.cs +++ b/Assets/Scripts/InteractionEngine/Gadgets/Tape.cs @@ -5,6 +5,8 @@ public class Tape : Gadget { + public float maxHeight = 2.5f; + //Variables for TapeMode distinction private bool TapeModeIsFirstPointSelected = false; private Fact TapeModeFirstPointSelected = null; @@ -40,10 +42,10 @@ public override void OnHit(RaycastHit hit) if (!this.isActiveAndEnabled) return; if (hit.transform.gameObject.layer == LayerMask.NameToLayer("Point")) { - Fact tempFact = Facts[hit.transform.GetComponent<FactObject>().URI]; + Fact tempFact = LevelFacts[hit.transform.GetComponent<FactObject>().URI]; //we can only reach points that are lower than that with the measuring tape - if (/*ActiveToolMode == ToolMode.CreateLineMode && */tempFact.Representation.transform.position.y > 2.5f) + if (/*ActiveToolMode == ToolMode.CreateLineMode && */tempFact.Representation.transform.position.y > maxHeight) return; //If first point was already selected AND second point != first point diff --git a/Assets/Scripts/InteractionEngine/ShinyThings.cs b/Assets/Scripts/InteractionEngine/ShinyThings.cs index e9eeaf64a7d41e959e9e5fc41e134db6e2cac38b..0ff9960a4866477ed21cfd0681ed7ba8bee77d42 100644 --- a/Assets/Scripts/InteractionEngine/ShinyThings.cs +++ b/Assets/Scripts/InteractionEngine/ShinyThings.cs @@ -38,10 +38,16 @@ public class ShinyThings : MonoBehaviour // Start is called before the first frame update public void Start() { - if (Cursor == null) Cursor = GetComponent<WorldCursor>(); - if (directionalLight == null) directionalLight = FindObjectOfType<Light>().gameObject; - CommunicationEvents.PushoutFactEvent.AddListener(StartPushoutFactHighlighting); + if (Cursor == null) + Cursor = GetComponent<WorldCursor>(); + + if (directionalLight == null) + directionalLight = FindObjectOfType<Light>().gameObject; + + CommunicationEvents.PushoutFactEvent.AddListener(HighlightFact); CommunicationEvents.PushoutFactFailEvent.AddListener(StartPushoutFactFailHighlighting); + CommunicationEvents.AnimateExistingFactEvent.AddListener(HighlightWithFireworks); + speedSlowDown = timerDurationEnd * 10; lightColor = directionalLight.GetComponent<Light>().color; @@ -181,9 +187,18 @@ public void OnMouseOverFactEnd(Transform selection) } } - public void StartPushoutFactHighlighting(Fact startFact) { - + public void HighlightWithFireworks(Fact fact) + { GameObject fireworksRepresentation = (GameObject)Resources.Load("Prefabs/Fireworks_Animation", typeof(GameObject)); + + this.extraHighlight = GameObject.Instantiate(fireworksRepresentation); + this.extraHighlight.transform.position = fact.Representation.transform.position; + + HighlightFact(fact); + } + + public void HighlightFact(Fact startFact) { + highlightedPushoutFact = startFact; if (typeof(PointFact).IsInstanceOfType(highlightedPushoutFact)) @@ -191,23 +206,17 @@ public void StartPushoutFactHighlighting(Fact startFact) { PointFact fact = (PointFact)highlightedPushoutFact; tempMaterial = fact.Representation.transform.GetChild(0).GetComponent<MeshRenderer>().material; fact.Representation.transform.GetChild(0).GetComponent<MeshRenderer>().material = pushoutMaterial; - this.extraHighlight = GameObject.Instantiate(fireworksRepresentation); - this.extraHighlight.transform.position = fact.Representation.transform.position; } else if (typeof(LineFact).IsInstanceOfType(highlightedPushoutFact)) { LineFact fact = (LineFact)highlightedPushoutFact; tempMaterial = fact.Representation.transform.GetChild(0).GetChild(1).GetComponent<MeshRenderer>().material; fact.Representation.transform.GetChild(0).GetChild(1).GetComponent<MeshRenderer>().material = pushoutMaterial; - this.extraHighlight = GameObject.Instantiate(fireworksRepresentation); - this.extraHighlight.transform.position = fact.Representation.transform.position; } else if (typeof(AngleFact).IsInstanceOfType(highlightedPushoutFact)) { AngleFact fact = (AngleFact)highlightedPushoutFact; tempMaterial = fact.Representation.transform.GetChild(0).GetComponent<MeshRenderer>().material; fact.Representation.transform.GetChild(0).GetComponent<MeshRenderer>().material = pushoutMaterial; - this.extraHighlight = GameObject.Instantiate(fireworksRepresentation); - this.extraHighlight.transform.position = fact.Representation.transform.position; } //Activate Timer @@ -216,7 +225,7 @@ public void StartPushoutFactHighlighting(Fact startFact) { this.timerActive = true; } - public void StopPushoutFactHighlighting() { + public void StopHighlighting() { if (typeof(PointFact).IsInstanceOfType(highlightedPushoutFact)) { @@ -234,8 +243,11 @@ public void StopPushoutFactHighlighting() { fact.Representation.transform.GetChild(0).GetComponent<MeshRenderer>().material = tempMaterial; } - GameObject.Destroy(this.extraHighlight); - this.extraHighlight = null; + if (this.extraHighlight != null) + { + GameObject.Destroy(this.extraHighlight); + this.extraHighlight = null; + } //Event for the happy Task-Charakter CommunicationEvents.PushoutFactEndEvent.Invoke(null); @@ -261,7 +273,7 @@ public void CheckPushoutHighlighting() { { this.timerActive = false; this.timer = 0; - StopPushoutFactHighlighting(); + StopHighlighting(); } //After this.timerDuration: Slow Down Fireworks else diff --git a/Assets/Scripts/InteractionEngine/SmartMenu.cs b/Assets/Scripts/InteractionEngine/SmartMenu.cs index 42a882c6c2fdf16f99b210fb769c9cc3bfec3074..da13a5667f850c37574768e340e4dbdbc3333a1c 100644 --- a/Assets/Scripts/InteractionEngine/SmartMenu.cs +++ b/Assets/Scripts/InteractionEngine/SmartMenu.cs @@ -7,7 +7,7 @@ public class SmartMenu : MonoBehaviour public void DestroyObject() { - CommunicationEvents.Facts.Remove(CommunicationEvents.Facts[transform.parent.GetComponent<FactObject>().URI]); + CommunicationEvents.LevelFacts.Remove(CommunicationEvents.LevelFacts[transform.parent.GetComponent<FactObject>().URI]); } diff --git a/Assets/Scripts/InteractionEngine/WorldCursor.cs b/Assets/Scripts/InteractionEngine/WorldCursor.cs index 3109f3f061f2a59cd65c0771ab8c026a644ba6fa..b69ae6bf11985ccce1a3181927d481c907d271d9 100644 --- a/Assets/Scripts/InteractionEngine/WorldCursor.cs +++ b/Assets/Scripts/InteractionEngine/WorldCursor.cs @@ -89,8 +89,8 @@ void Update() || Hit.collider.gameObject.layer == LayerMask.NameToLayer("Line")) { var id = Hit.collider.gameObject.GetComponent<FactObject>().URI; - AbstractLineFact lineFact = CommunicationEvents.Facts[id] as AbstractLineFact; - PointFact p1 = CommunicationEvents.Facts[lineFact.Pid1] as PointFact; + AbstractLineFact lineFact = CommunicationEvents.LevelFacts[id] as AbstractLineFact; + PointFact p1 = CommunicationEvents.LevelFacts[lineFact.Pid1] as PointFact; Hit.point = Math3d.ProjectPointOnLine(p1.Point, lineFact.Dir, Hit.point); CheckMouseButtons(true,true); diff --git a/Assets/Scripts/InventoryStuff/DisplayFacts.cs b/Assets/Scripts/InventoryStuff/DisplayFacts.cs index 2141e6e56bf22d2df97c4b174f0af936f58ba539..926b2fb85b92693b6bb97edb3430e18500237570 100644 --- a/Assets/Scripts/InventoryStuff/DisplayFacts.cs +++ b/Assets/Scripts/InventoryStuff/DisplayFacts.cs @@ -55,6 +55,14 @@ public void RemoveFact(Fact fact) { GameObject.Destroy(displayedFacts[fact.URI]); displayedFacts.Remove(fact.URI); + UpdatePositions(); + } + + public void UpdatePositions() + { + int i = 0; + foreach (var element in displayedFacts) + element.Value.GetComponent<RectTransform>().localPosition = GetPosition(i++); } public void AnimateFact(Fact fact) { @@ -62,10 +70,6 @@ public void AnimateFact(Fact fact) { factIcon.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger(); } - string getLetter(int Id) { - return ((Char)(64 + Id + 1)).ToString(); - } - private GameObject CreateDisplay(Transform transform, Fact fact) { return fact.instantiateDisplay(prefabDictionary[fact.GetType()], transform); diff --git a/Assets/Scripts/InventoryStuff/ScrollDetails.cs b/Assets/Scripts/InventoryStuff/ScrollDetails.cs index ba0fb8d3bbf60dcfc0be8a34389df2ca652d90c9..b3b44d81ef6c8dded826d86e64f370c6c6040331 100644 --- a/Assets/Scripts/InventoryStuff/ScrollDetails.cs +++ b/Assets/Scripts/InventoryStuff/ScrollDetails.cs @@ -32,7 +32,6 @@ void Start() { if (cursor == null) cursor = GameObject.FindObjectOfType<WorldCursor>(); - parameterDisplayHint.AddListener(animateScrollParameter); ScrollFactHintEvent.AddListener(animateHint); NewAssignmentEvent.AddListener(newAssignmentTrigger); } @@ -168,9 +167,7 @@ private void readPushout(List<Scroll.ScrollFact> pushoutFacts) Fact newFact = ParsingDictionary.parseFactDictionary[pushoutFacts[i].getType()].Invoke(pushoutFacts[i]); if (newFact != null) { - FactManager.AddFactIfNotFound(newFact, out bool exists, samestep); - if(!exists) - PushoutFactEvent.Invoke(newFact); + PushoutFactEvent.Invoke(FactManager.AddFactIfNotFound(newFact, out bool exists, samestep)); } else { Debug.Log("Parsing on pushout-fact returned null -> One of the dependent facts does not exist"); @@ -236,9 +233,9 @@ public void animateHint(GameObject scrollParameter, string scrollParameterUri) { if (suitableCompletion != null) { - if (Facts.ContainsKey(suitableCompletion.assignment.uri)) + if (LevelFacts.ContainsKey(suitableCompletion.assignment.uri)) { - fact = Facts[suitableCompletion.assignment.uri]; + fact = LevelFacts[suitableCompletion.assignment.uri]; //Animate ScrollParameter scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger(); //Animate Fact in FactPanel @@ -253,9 +250,9 @@ public void animateHint(GameObject scrollParameter, string scrollParameterUri) { var factId = fact.URI; //If there is an equal existing fact -> Animate that fact AND ScrollParameter - if (Facts.ContainsKey(factId)) + if (LevelFacts.ContainsKey(factId)) { - Fact existingFact = Facts[factId]; + Fact existingFact = LevelFacts[factId]; //Animate ScrollParameter scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger(); diff --git a/Assets/Scripts/Level.cs b/Assets/Scripts/Level.cs index a65344b1702760760a9b101b71d5699bcd4660ce..8832fabc94fa1aad5d49df804ad492b5732f2256 100644 --- a/Assets/Scripts/Level.cs +++ b/Assets/Scripts/Level.cs @@ -1,4 +1,5 @@ -using UnityEngine; +using System.Collections.Generic; +using UnityEngine; using static CommunicationEvents; //TODO: think about having one Level class and then different subclasses like TreeLevel, Tangenslevel? @@ -6,46 +7,35 @@ public class Level : MonoBehaviour { //Solving game parameters - public GameObject snapZoneTop; - public GameObject snapZoneBottom; - public static Vector3 solutionVector; + public int minimalSolutionHight; + public static bool solved = false; - // Start is called before the first frame update + + void Start() + // Start is called before the first frame update { - solutionVector = snapZoneTop.transform.position - snapZoneBottom.transform.position; - } + PointFact + buttom = new PointFact(Vector3.zero, Vector3.up, SolutionManager), + top = new PointFact(Vector3.zero + Vector3.up * minimalSolutionHight, Vector3.up, SolutionManager); + + SolutionManager.Add(buttom, out _); + SolutionManager.Add(top, out _, true); + LineFact target = new LineFact(buttom.URI, top.URI, SolutionManager); + Solution.Add(SolutionManager[SolutionManager.Add(target, out _, true)]); + } public static bool gameSolved() { + solved = + LevelFacts.DynamiclySolved(Solution, out _, out List<Fact> hits, new LineFactHightDirectionComparer()); - Vector3 tempDir1 = new Vector3(0, 0, 0); - Vector3 tempDir2 = new Vector3(0, 0, 0); - - if (solved == true) - return true; - else - { - //Look for solutionFact in global factList - foreach (var entry in Facts) - { - Fact fact = entry.Value; - if (typeof(LineFact).IsInstanceOfType(fact)) - { - tempDir1 = ((PointFact) Facts[((LineFact) fact).Pid1]).Point - - ((PointFact) Facts[((LineFact) fact).Pid2]).Point; - tempDir2 = ((PointFact) Facts[((LineFact) fact).Pid2]).Point - - ((PointFact) Facts[((LineFact) fact).Pid1]).Point; - - if (solutionVector == tempDir1 || solutionVector == tempDir2) - { - solved = true; - return true; - } - } - } - return false; - } + if (solved) + foreach (var hit in hits) + AnimateExistingFactEvent.Invoke(hit); + + return solved; } + } diff --git a/Assets/Scripts/Restart.cs b/Assets/Scripts/Restart.cs index cf20ce143c751cca4393404951f573c515e88fd2..47e919b45b077349bb4d2836a84856621f9dcfaa 100644 --- a/Assets/Scripts/Restart.cs +++ b/Assets/Scripts/Restart.cs @@ -1,19 +1,24 @@ using UnityEngine; -using static StartServer; +using UnityEngine.SceneManagement; public class Restart : MonoBehaviour { + public void LevelReset() + { + CommunicationEvents.LevelReset.Invoke(); // currently unused + Level.solved = false; // needed? + CommunicationEvents.LevelFacts.hardreset(false); // delete Facts at Server + SceneManager.LoadSceneAsync(SceneManager.GetActiveScene().buildIndex); + } + public void LoadStartScreen() { - process.Kill(); - Level.solved = false; - //TODO: CommunicationEvents.Facts.Clear(); - CommunicationEvents.Facts.hardreset(); - UnityEngine.SceneManagement.SceneManager.LoadScene(0); + StartServer.process.Kill(); // null reference exception if Server started manually + SceneManager.LoadScene(0); } public void OnApplicationQuit() { - process.Kill(); + StartServer.process.Kill(); } }