diff --git a/Assets/Scenes/RiverWorld.unity b/Assets/Scenes/RiverWorld.unity index fb99d299995018226244620e368b317c4cb0e37d..03b6980f59b42a9c69fd89d2c93bed48659a9a5d 100644 --- a/Assets/Scenes/RiverWorld.unity +++ b/Assets/Scenes/RiverWorld.unity @@ -18018,6 +18018,12 @@ Transform: type: 3} m_PrefabInstance: {fileID: 800121727} m_PrefabAsset: {fileID: 0} +--- !u!1 &802019337 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 4661435515762455780, guid: e289bf5debb17f6459818c207d781953, + type: 3} + m_PrefabInstance: {fileID: 224606875} + m_PrefabAsset: {fileID: 0} --- !u!1 &804378691 GameObject: m_ObjectHideFlags: 0 @@ -23482,7 +23488,7 @@ PrefabInstance: - target: {fileID: 2222111361404534124, guid: 88f2fd29f58b9734683512546acec310, type: 3} propertyPath: m_Name - value: WalkAroundTree + value: DonTWalkAroundThisTree objectReference: {fileID: 0} - target: {fileID: 2222111361405018444, guid: 88f2fd29f58b9734683512546acec310, type: 3} @@ -37123,12 +37129,6 @@ Transform: type: 3} m_PrefabInstance: {fileID: 1738591202} m_PrefabAsset: {fileID: 0} ---- !u!1 &1747050947 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 2222111361404534124, guid: 88f2fd29f58b9734683512546acec310, - type: 3} - m_PrefabInstance: {fileID: 1038096501} - m_PrefabAsset: {fileID: 0} --- !u!1001 &1749781951 PrefabInstance: m_ObjectHideFlags: 0 @@ -59592,11 +59592,21 @@ PrefabInstance: propertyPath: m_IsActive value: 0 objectReference: {fileID: 0} + - target: {fileID: 293934905664952486, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: modload + value: mod+load + objectReference: {fileID: 0} - target: {fileID: 293934905664952486, guid: b996060e27da25c498842defc1996d84, type: 3} propertyPath: modredo value: mod+redo objectReference: {fileID: 0} + - target: {fileID: 293934905664952486, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: modsave + value: mod+save + objectReference: {fileID: 0} - target: {fileID: 293934905664952486, guid: b996060e27da25c498842defc1996d84, type: 3} propertyPath: modundo @@ -61544,7 +61554,7 @@ PrefabInstance: type: 3} propertyPath: walkAroundObject value: - objectReference: {fileID: 1747050947} + objectReference: {fileID: 802019337} - target: {fileID: 6999573641170124239, guid: 8590393c51194934a95cdc2075fc4dec, type: 3} propertyPath: radiusAroundObject diff --git a/Assets/Scenes/TreeWorld.unity b/Assets/Scenes/TreeWorld.unity index fcd487af2d2081448ea00588ff98ef5a3c3fe1c5..7e14a816e0e0db12d575a3959d695a15f570e269 100644 --- a/Assets/Scenes/TreeWorld.unity +++ b/Assets/Scenes/TreeWorld.unity @@ -38,12 +38,12 @@ RenderSettings: m_ReflectionIntensity: 1 m_CustomReflection: {fileID: 0} m_Sun: {fileID: 138245306} - m_IndirectSpecularColor: {r: 0.44108614, g: 0.4898401, b: 0.5699199, a: 1} + m_IndirectSpecularColor: {r: 0.4410863, g: 0.4898401, b: 0.5699197, a: 1} m_UseRadianceAmbientProbe: 0 --- !u!157 &3 LightmapSettings: m_ObjectHideFlags: 0 - serializedVersion: 11 + serializedVersion: 12 m_GIWorkflowMode: 1 m_GISettings: serializedVersion: 2 @@ -98,7 +98,8 @@ LightmapSettings: m_TrainingDataDestination: TrainingData m_LightProbeSampleCountMultiplier: 4 m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 + m_LightingSettings: {fileID: 4890085278179872738, guid: 14e5ba440f2fdd14bb575936dddde1b0, + type: 2} --- !u!196 &4 NavMeshSettings: serializedVersion: 2 @@ -118,6 +119,8 @@ NavMeshSettings: manualTileSize: 0 tileSize: 256 accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 debug: m_Flags: 0 m_NavMeshData: {fileID: 0} @@ -3014,6 +3017,7 @@ Light: m_UseColorTemperature: 0 m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 m_ShadowRadius: 0 m_ShadowAngle: 0 --- !u!4 &138245307 @@ -6654,6 +6658,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -6678,6 +6683,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &318619250 MeshFilter: m_ObjectHideFlags: 0 @@ -8791,6 +8797,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -8815,6 +8822,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &422404980 MeshFilter: m_ObjectHideFlags: 0 @@ -9512,6 +9520,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -9536,6 +9545,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &444871398 MeshFilter: m_ObjectHideFlags: 0 @@ -10600,6 +10610,7 @@ LineRenderer: m_LightProbeUsage: 0 m_ReflectionProbeUsage: 0 m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -11703,6 +11714,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -11727,6 +11739,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &535944727 MeshFilter: m_ObjectHideFlags: 0 @@ -22048,6 +22061,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -22072,6 +22086,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &1009368152 MeshFilter: m_ObjectHideFlags: 0 @@ -34054,6 +34069,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -34078,6 +34094,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &1563243736 MeshFilter: m_ObjectHideFlags: 0 @@ -36434,6 +36451,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -36458,6 +36476,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &1675643437 MeshFilter: m_ObjectHideFlags: 0 @@ -43177,6 +43196,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -43201,6 +43221,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &2019831182 MeshFilter: m_ObjectHideFlags: 0 @@ -47252,6 +47273,7 @@ Light: m_UseColorTemperature: 0 m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 m_ShadowRadius: 0 m_ShadowAngle: 0 --- !u!4 &685153537209802452 @@ -47509,6 +47531,16 @@ PrefabInstance: propertyPath: m_SizeDelta.y value: 0 objectReference: {fileID: 0} + - target: {fileID: 1274450867600639853, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: automaticHintGenerationActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1274450867600639853, guid: b996060e27da25c498842defc1996d84, + type: 3} + propertyPath: dynamicScrollDescriptionsActive + value: 1 + objectReference: {fileID: 0} - target: {fileID: 5237843606108538431, guid: b996060e27da25c498842defc1996d84, type: 3} propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.size @@ -47569,6 +47601,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -47594,6 +47627,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &1017499588648496289 GameObject: m_ObjectHideFlags: 0 @@ -47633,6 +47667,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -47657,6 +47692,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!23 &1099843466031652983 MeshRenderer: m_ObjectHideFlags: 0 @@ -47672,6 +47708,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -47696,6 +47733,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &1316124618987194725 GameObject: m_ObjectHideFlags: 0 @@ -47815,6 +47853,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -47839,6 +47878,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &1745987128933336103 MeshFilter: m_ObjectHideFlags: 0 @@ -48413,6 +48453,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -48438,6 +48479,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!23 &2600518979547571749 MeshRenderer: m_ObjectHideFlags: 0 @@ -48453,6 +48495,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -48477,6 +48520,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!4 &2609522164336802835 Transform: m_ObjectHideFlags: 0 @@ -48631,6 +48675,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -48655,6 +48700,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &4170768673617977780 GameObject: m_ObjectHideFlags: 0 @@ -48750,6 +48796,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -48774,6 +48821,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!4 &4565031082369432565 Transform: m_ObjectHideFlags: 0 @@ -48820,6 +48868,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -48844,6 +48893,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &5064968614624445547 MeshFilter: m_ObjectHideFlags: 0 @@ -48911,6 +48961,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -48935,6 +48986,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!4 &5537943171067704051 Transform: m_ObjectHideFlags: 0 @@ -48992,6 +49044,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49016,6 +49069,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &5951941432316338672 MeshFilter: m_ObjectHideFlags: 0 @@ -49057,6 +49111,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49082,6 +49137,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &6256956892669881441 GameObject: m_ObjectHideFlags: 0 @@ -49151,6 +49207,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49175,6 +49232,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1001 &6999573641241424516 PrefabInstance: m_ObjectHideFlags: 0 @@ -49332,7 +49390,9 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} - m_RemovedComponents: [] + m_RemovedComponents: + - {fileID: 6999573642288568606, guid: 8590393c51194934a95cdc2075fc4dec, type: 3} + - {fileID: 6999573640440716766, guid: 8590393c51194934a95cdc2075fc4dec, type: 3} m_SourcePrefab: {fileID: 100100000, guid: 8590393c51194934a95cdc2075fc4dec, type: 3} --- !u!4 &6999573641241424517 stripped Transform: @@ -49405,6 +49465,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49429,6 +49490,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!23 &7643328943036952926 MeshRenderer: m_ObjectHideFlags: 0 @@ -49444,6 +49506,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49470,6 +49533,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &7649001581117388135 MeshFilter: m_ObjectHideFlags: 0 @@ -49493,6 +49557,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49517,6 +49582,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &8037038874798551250 GameObject: m_ObjectHideFlags: 0 @@ -49564,6 +49630,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49588,6 +49655,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!23 &8284392456268054784 MeshRenderer: m_ObjectHideFlags: 0 @@ -49603,6 +49671,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49627,6 +49696,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!23 &8379924837567921489 MeshRenderer: m_ObjectHideFlags: 0 @@ -49642,6 +49712,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49666,6 +49737,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &8393955356175092067 MeshFilter: m_ObjectHideFlags: 0 @@ -49711,6 +49783,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49735,6 +49808,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!23 &8509506421963195749 MeshRenderer: m_ObjectHideFlags: 0 @@ -49750,6 +49824,7 @@ MeshRenderer: m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -49774,6 +49849,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &8656279830196498237 MeshFilter: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/HideUI.cs b/Assets/Scripts/HideUI.cs index 3b3c4dfb4ce56d744a8cb1d12982a2b11715afda..7dac4c2b819ecbf9b34c38284c6a1d944d4bb030 100644 --- a/Assets/Scripts/HideUI.cs +++ b/Assets/Scripts/HideUI.cs @@ -1,4 +1,5 @@ using UnityEngine; +using UnityEngine.SceneManagement; using static CommunicationEvents; public class HideUI : MonoBehaviour @@ -11,7 +12,9 @@ public string modifier, modundo, modredo, - modreset; + modreset, + modsave, + modload; public UnityStandardAssets.Characters.FirstPerson.FirstPersonController CamControl; public bool LockOnly = true; @@ -60,6 +63,13 @@ void Update() LevelFacts.redo(); else if (Input.GetButtonDown(modreset)) LevelFacts.softreset(); + else if (Input.GetButtonDown(modsave)) + LevelFacts.store(SceneManager.GetActiveScene().name); + else if (Input.GetButtonDown(modload)) + { + LevelFacts.hardreset(); + FactOrganizer.load(ref LevelFacts, true, SceneManager.GetActiveScene().name); + } } /* diff --git a/Assets/Scripts/InteractionEngine/CommunicationEvents.cs b/Assets/Scripts/InteractionEngine/CommunicationEvents.cs index 2904c10b51e33b20cab1ba6c64d0a0b5bc40e540..ddbb4f527b3b5e8805311c87443a080d414f328b 100644 --- a/Assets/Scripts/InteractionEngine/CommunicationEvents.cs +++ b/Assets/Scripts/InteractionEngine/CommunicationEvents.cs @@ -59,4 +59,35 @@ public class AnimationEventWithUris : UnityEvent<List<string>> { } // Configs public static bool VerboseURI = false; + + // TODO! avoid tree traversel with name + public static string CreatePathToFile(out bool file_exists, string name, string format = null, Type type = null) + { + string ending = ".dat"; + if(!string.IsNullOrEmpty(format)) + switch (format) + { + case "JSON": + ending = ".JSON"; + break; + default: + break; + } + + string path = Application.persistentDataPath; + if (type != null) + { + if (typeof(FactOrganizer).IsAssignableFrom(type)) + path = System.IO.Path.Combine(path, "FactStateMachines"); + else + { } + + System.IO.Directory.CreateDirectory(path); + } + + path = System.IO.Path.Combine(path, name + ending); + file_exists = System.IO.File.Exists(path); + + return path; + } } diff --git a/Assets/Scripts/InteractionEngine/Fact.cs b/Assets/Scripts/InteractionEngine/Fact.cs index d279dd9a00cf4ae38b1538e02ac8f35abbedd36f..3432465952c8f0ac10c9d9b5d55d1b1d4316964c 100644 --- a/Assets/Scripts/InteractionEngine/Fact.cs +++ b/Assets/Scripts/InteractionEngine/Fact.cs @@ -3,6 +3,7 @@ using UnityEngine; using UnityEngine.Networking; using TMPro; +using Newtonsoft.Json; using static JSONManager; using static CommunicationEvents; @@ -77,20 +78,30 @@ public static bool sendAdd(string path, string body, out string uri) } } -[Serializable] +//[Serializable] public abstract class Fact { + [JsonIgnore] public GameObject Representation; - public string Id { get { return _URI; } } + public string Id { + get { return _URI; } + set { if (_URI == null) _URI = value; } + } protected string _URI; + // should be called once a constructor call public string Label { get { // in case of renamed dependables - return string.IsNullOrEmpty(_CustomLabel) ? - generateLabel() : - _CustomLabel; + return hasCustomLabel ? + _CustomLabel : + generateLabel(); } + set { rename(value); } + } + public bool hasCustomLabel { + get; + private set; } protected string _CustomLabel = null; private int LabelId = 0; @@ -100,19 +111,53 @@ public string Label { private static int MaxLabelId = 0; private static SortedSet<int> UnusedLabelIds = new SortedSet<int>(); + protected Fact() + // 0 parameter constructor for Json + { + this._Facts = new FactOrganizer(); + hasCustomLabel = false; + } + protected Fact(FactOrganizer organizer) { this._Facts = organizer; + hasCustomLabel = false; } - //TODO: notify about updated dependable Labelnames - public void rename(string newLabel) + protected Fact(Fact fact, FactOrganizer organizer) { - if (_Facts.ContainsLabel(newLabel)) - return; + this._Facts = organizer; + hasCustomLabel = fact.hasCustomLabel; + + if (hasCustomLabel) + _CustomLabel = fact.Label; + } + + //TODO: notify about updated dependable Labelnames for UI + //TODO: check for colissions with not yet generated names + public bool rename(string newLabel) + // returns true if succeded + { + if (string.IsNullOrEmpty(newLabel)) + // switch back to autogenerated + { + generateLabel(); + _CustomLabel = null; + hasCustomLabel = false; + return true; + } + else + // set CustomLabel if available + { + if (_Facts.ContainsLabel(newLabel)) + return false; + + freeAutoLabel(); + _CustomLabel = newLabel; + hasCustomLabel = true; - freeLabel(); - _CustomLabel = newLabel; + return true; + } } //If FactType depends on other Facts, e.g. AngleFacts depend on 3 PointFacts @@ -122,12 +167,18 @@ public void rename(string newLabel) public abstract GameObject instantiateDisplay(GameObject prefab, Transform transform); + public static void Clear() + { + MaxLabelId = 0; + UnusedLabelIds.Clear(); + } + public virtual void delete(bool keep_clean = true) { //TODO: MMT: delete over there if (keep_clean) - freeLabel(); + freeAutoLabel(); if (VerboseURI) Debug.Log("Server removed Fact:\n" + this.Id); @@ -139,20 +190,6 @@ public virtual void delete(bool keep_clean = true) public abstract override int GetHashCode(); - // TODO? only get _Fact to freeLabel/ - public void freeLabel() - { - if (LabelId > 0) - { - UnusedLabelIds.Add(LabelId); - // store Label for name-persistance - LabelId = -LabelId; - } - - if (!string.IsNullOrEmpty(_CustomLabel)) - _CustomLabel = null; - } - protected virtual string generateLabel() { if (LabelId == 0) @@ -166,19 +203,31 @@ protected virtual string generateLabel() else if (LabelId < 0) // reload Label if possible + LabelId = UnusedLabelIds.Remove(-LabelId) ? -LabelId : 0; + + return ((char)(64 + LabelId)).ToString(); + } + + // TODO? only get _Fact to freeLabel/ + public /*protected internal*/ void freeAutoLabel() + { + if (LabelId > 0) { + UnusedLabelIds.Add(LabelId); + // store Label for name-persistance LabelId = -LabelId; - UnusedLabelIds.Remove(LabelId); } - - return ((char)(64 + LabelId)).ToString(); } } public abstract class FactWrappedCRTP<T>: Fact where T: FactWrappedCRTP<T> { + protected FactWrappedCRTP() : base() { } + protected FactWrappedCRTP(FactOrganizer organizer) : base(organizer) { } + protected FactWrappedCRTP(FactWrappedCRTP<T> fact, FactOrganizer organizer) : base(fact, organizer) { } + public override bool Equivalent(Fact f2) { return Equivalent(this, f2); @@ -203,12 +252,24 @@ public abstract class AbstractLineFact: FactWrappedCRTP<AbstractLineFact> //only for temporary Use of LineFacts. //public AbstractLineFact() { } - public AbstractLineFact(string pid1, string pid2, FactOrganizer organizer): base(organizer) + protected AbstractLineFact() : base() + { + Pid1 = null; + Pid2 = null; + Dir = Vector3.zero; + } + + protected AbstractLineFact(AbstractLineFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer) + { + set_public_members(old_to_new[fact.Pid1], old_to_new[fact.Pid2]); + } + + protected AbstractLineFact(string pid1, string pid2, FactOrganizer organizer): base(organizer) { set_public_members(pid1, pid2); } - public AbstractLineFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(organizer) + protected AbstractLineFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(organizer) { set_public_members(pid1, pid2); this._URI = backendURI; @@ -241,12 +302,13 @@ public override int GetHashCode() public abstract class AbstractLineFactWrappedCRTP<T>: AbstractLineFact where T: AbstractLineFactWrappedCRTP<T> { - //only for temporary Use of LineFacts. - //public AbstractLineFactWrappedCRTP() { } + protected AbstractLineFactWrappedCRTP () : base() { } - public AbstractLineFactWrappedCRTP (string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer) { } + protected AbstractLineFactWrappedCRTP (AbstractLineFactWrappedCRTP<T> fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, old_to_new, organizer) { } - public AbstractLineFactWrappedCRTP (string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer) { } + protected AbstractLineFactWrappedCRTP (string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer) { } + + protected AbstractLineFactWrappedCRTP (string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer) { } protected override bool EquivalentWrapped(AbstractLineFact f1, AbstractLineFact f2) { @@ -256,15 +318,29 @@ protected override bool EquivalentWrapped(AbstractLineFact f1, AbstractLineFact protected abstract bool EquivalentWrapped(T f1, T f2); } - -//I am not sure if we ever need to attach these to an object, so one script for all for now... public class PointFact : FactWrappedCRTP<PointFact> { public Vector3 Point; public Vector3 Normal; + public PointFact() : base() + { + this.Point = Vector3.zero; + this.Normal = Vector3.zero; + } + + public PointFact(PointFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer) + { + init(fact.Point, fact.Normal); + } + public PointFact(Vector3 P, Vector3 N, FactOrganizer organizer) : base(organizer) + { + init(P, N); + } + + private void init(Vector3 P, Vector3 N) { this.Point = P; this.Normal = N; @@ -280,7 +356,6 @@ public PointFact(Vector3 P, Vector3 N, FactOrganizer organizer) : base(organizer MMTTerm tp = new OMS(MMTURIs.Point); MMTTerm df = new OMA(new OMS(MMTURIs.Tuple), arguments); - //TODO: rework fact list + labeling MMTSymbolDeclaration mmtDecl = new MMTSymbolDeclaration(this.Label, tp, df); AddFactResponse.sendAdd(mmtDecl, out this._URI); } @@ -290,6 +365,7 @@ public PointFact(float a, float b, float c, string uri, FactOrganizer organizer) this.Point = new Vector3(a, b, c); this.Normal = new Vector3(0, 1, 0); this._URI = uri; + _ = this.Label; } public static PointFact parseFact(Scroll.ScrollFact fact) { @@ -338,12 +414,28 @@ public class LineFact : AbstractLineFactWrappedCRTP<LineFact> { public float Distance; + public LineFact() : base() + { + Distance = 0; + } + + public LineFact(LineFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, old_to_new, organizer) + { + init(old_to_new[fact.Pid1], old_to_new[fact.Pid2]); + } + public LineFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer) { SetDistance(); + _ = this.Label; } public LineFact(string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer) + { + init(pid1, pid2); + } + + private void init(string pid1, string pid2) { SetDistance(); @@ -423,9 +515,24 @@ private void SetDistance() public class RayFact : AbstractLineFactWrappedCRTP<RayFact> { - public RayFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer) { } + public RayFact() : base() { } + + public RayFact(RayFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, old_to_new, organizer) + { + init(old_to_new[fact.Pid1], old_to_new[fact.Pid2]); + } + + public RayFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer) + { + _ = this.Label; + } public RayFact(string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer) + { + init(pid1, pid2); + } + + private void init(string pid1, string pid2) { PointFact pf1 = _Facts[pid1] as PointFact; PointFact pf2 = _Facts[pid2] as PointFact; @@ -443,7 +550,6 @@ public RayFact(string pid1, string pid2, FactOrganizer organizer) : base(pid1, p MMTTerm tp = new OMS(MMTURIs.LineType); MMTTerm df = new OMA(new OMS(MMTURIs.LineOf), arguments); - //TODO: rework fact list + labeling MMTSymbolDeclaration mmtDecl = new MMTSymbolDeclaration(this.Label, tp, df); AddFactResponse.sendAdd(mmtDecl, out this._URI); } @@ -496,7 +602,23 @@ public class OnLineFact : FactWrappedCRTP<OnLineFact> //Id's of the Point and the Line it's on public string Pid, Rid; + public OnLineFact() : base() + { + this.Pid = null; + this.Rid = null; + } + + public OnLineFact(OnLineFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer) + { + init(old_to_new[fact.Pid], old_to_new[fact.Rid]); + } + public OnLineFact(string pid, string rid, FactOrganizer organizer) : base(organizer) + { + init(pid, rid); + } + + private void init(string pid, string rid) { this.Pid = pid; this.Rid = rid; @@ -521,7 +643,6 @@ public OnLineFact(string pid, string rid, FactOrganizer organizer) : base(organi MMTTerm tp = new OMA(new OMS(MMTURIs.Ded), outerArguments); MMTTerm df = null; - //TODO: rework fact list + labeling MMTSymbolDeclaration mmtDecl = new MMTSymbolDeclaration(this.Label, tp, df); AddFactResponse.sendAdd(mmtDecl, out this._URI); } @@ -531,6 +652,7 @@ public OnLineFact(string pid, string rid, string uri, FactOrganizer organizer) : this.Pid = pid; this.Rid = rid; this._URI = uri; + _ = this.Label; } public static OnLineFact parseFact(Scroll.ScrollFact fact) @@ -596,7 +718,25 @@ public class AngleFact : FactWrappedCRTP<AngleFact> public string Pid1, Pid2, Pid3; public bool is_right_angle; + public AngleFact() : base() + { + this.Pid1 = null; + this.Pid2 = null; + this.Pid3 = null; + this.is_right_angle = false; + } + + public AngleFact(AngleFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer) + { + init(old_to_new[fact.Pid1], old_to_new[fact.Pid2], old_to_new[fact.Pid3]); + } + public AngleFact(string pid1, string pid2, string pid3, FactOrganizer organizer) : base(organizer) + { + init(pid1, pid2, pid3); + } + + private void init(string pid1, string pid2, string pid3) { this.Pid1 = pid1; this.Pid2 = pid2; @@ -629,6 +769,7 @@ public AngleFact(string Pid1, string Pid2, string Pid3, string backendURI, FactO GetAngle(); this._URI = backendURI; + _ = this.Label; } public static AngleFact parseFact(Scroll.ScrollFact fact) @@ -762,6 +903,4 @@ protected override bool EquivalentWrapped(AngleFact f1, AngleFact f2) return (p1f1.Equivalent(p1f2) && p2f1.Equivalent(p2f2) && p3f1.Equivalent(p3f2)) ;//|| (p1f1.Equivalent(p3f2) && p2f1.Equivalent(p2f2) && p1f1.Equivalent(p3f2)); } -} - - +} \ No newline at end of file diff --git a/Assets/Scripts/InteractionEngine/FactManager.cs b/Assets/Scripts/InteractionEngine/FactManager.cs index 2a7cdbed53e5bc2c5d80cfccec05da23c4c85112..503a08936e32b258d48de3fa026c8960b635e9fd 100644 --- a/Assets/Scripts/InteractionEngine/FactManager.cs +++ b/Assets/Scripts/InteractionEngine/FactManager.cs @@ -15,22 +15,22 @@ public static Fact AddFactIfNotFound(Fact fact, out bool exists, bool samestep) public PointFact AddPointFact(RaycastHit hit, bool samestep = false) { - return (PointFact) AddFactIfNotFound(new PointFact(hit.point, hit.normal, LevelFacts), out bool obsolete, samestep); + return (PointFact) AddFactIfNotFound(new PointFact(hit.point, hit.normal, LevelFacts), out _, samestep); } public PointFact AddPointFact(Vector3 point, Vector3 normal, bool samestep = false) { - return (PointFact) AddFactIfNotFound(new PointFact(point, normal, LevelFacts), out bool obsolete, samestep); + return (PointFact) AddFactIfNotFound(new PointFact(point, normal, LevelFacts), out _, samestep); } public OnLineFact AddOnLineFact(string pid, string lid, bool samestep = false) { - return (OnLineFact)AddFactIfNotFound(new OnLineFact(pid, lid, LevelFacts), out bool obsolete, samestep); + return (OnLineFact)AddFactIfNotFound(new OnLineFact(pid, lid, LevelFacts), out _, samestep); } public LineFact AddLineFact(string pid1, string pid2, bool samestep = false) { - return (LineFact)AddFactIfNotFound(new LineFact(pid1, pid2, LevelFacts), out bool obsolete, samestep); + return (LineFact)AddFactIfNotFound(new LineFact(pid1, pid2, LevelFacts), out _, samestep); } public RayFact AddRayFact(string pid1, string pid2, bool samestep = false) @@ -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, LevelFacts), out bool obsolete, samestep); + return (AngleFact)AddFactIfNotFound(new AngleFact(pid1, pid2, pid3, LevelFacts), out _, samestep); } } diff --git a/Assets/Scripts/InteractionEngine/FactOrganizer.cs b/Assets/Scripts/InteractionEngine/FactOrganizer.cs index e627e936f2cf23cc4453b92b99a876f870d6e6a2..76ad5c7fb489e5ce5a5c9ec15ec33dbf87dd6984 100644 --- a/Assets/Scripts/InteractionEngine/FactOrganizer.cs +++ b/Assets/Scripts/InteractionEngine/FactOrganizer.cs @@ -1,31 +1,33 @@ -using System.Collections; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using Newtonsoft.Json; +using System.Collections; using UnityEngine; using System.Linq; +using System; //TODO? PERF? (often inserts) SortedDict <-> Dict (often reads) //TODO: MMT: move some functionality there //TODO: consequent!= samestep != dependent //PERF: avoid string as key (general: allocations & dict: hash -> colission? -> strcmp[!]) - -[System.Serializable] public class FactOrganizer { - private Dictionary<string, Fact> FactDict; - private Dictionary<string, meta> MetaInf = new Dictionary<string, meta>(); - private List<stepnote> Workflow = new List<stepnote>(); + protected internal Dictionary<string, Fact> FactDict; + protected internal Dictionary<string, meta> MetaInf = new Dictionary<string, meta>(); + protected internal List<stepnote> Workflow = new List<stepnote>(); // notes position in Workflow for un-/redo; the pointed to element is non-acitve - private int marker = 0; + protected internal int marker = 0; // backlock logic for convinience - private int worksteps = 0; - private int backlog = 0; + protected internal int worksteps = 0; + protected internal int backlog = 0; // set if recently been resetted - private bool soft_resetted = false; + protected internal bool soft_resetted = false; // InvokeEvents? - private bool invoke; + public bool invoke; - private struct stepnote + protected internal struct stepnote { // Fact.Id public string Id; @@ -57,7 +59,7 @@ public stepnote(string Id, bool samestep, bool creation, FactOrganizer that) } } - private struct meta + protected internal struct meta { // TODO? -> public int last_occurence for safe_dependencies @@ -79,15 +81,86 @@ public FactOrganizer(bool invoke = false) this.invoke = invoke; } - public FactOrganizer(IDictionary<string, Fact> dictionary, bool invoke = false) + private FactOrganizer(ref FactOrganizer set, PublicFactOrganizer exposed, bool invoke) { - FactDict = new Dictionary<string, Fact>(dictionary); + // TODO: other strategy needed when MMT save/load supported + // map old URIs to new ones + Dictionary<string, string> old_to_new = new Dictionary<string, string>(); + // combine T:Fact to Fact + Dictionary<string, Fact> old_FactDict = new Dictionary<string, Fact>(); + + /* + FieldInfo[] finfos = typeof(PublicFactOrganizer).GetFields(); + foreach(string type in PublicFactOrganizer.WatchedFacts) + AddListToDict( + finfos.First(x => x.Name.Remove(x.Name.Length-1) == type) + .GetValue(exposed) + as List<Fact>); + */ + + AddListToDict(exposed.PointFacts); + AddListToDict(exposed.LineFacts); + AddListToDict(exposed.RayFacts); + AddListToDict(exposed.AngleFacts); + AddListToDict(exposed.OnLineFacts); + + + // initiate this.invoke = invoke; + FactDict = new Dictionary<string, Fact>(); + set = this; + + // work Workflow + foreach (var sn in exposed.Workflow) + { + if (sn.creation) + // Add + { + Fact add; + if (old_to_new.ContainsKey(sn.Id)) + add = FactDict[old_to_new[sn.Id]]; + else + { + Fact old_Fact = old_FactDict[sn.Id]; + + // TODO! false customLabel + add = old_Fact.GetType() + .GetConstructor(new Type[] { old_Fact.GetType(), old_to_new.GetType(), typeof(FactOrganizer) }) + .Invoke(new object[] { old_Fact, old_to_new, this }) + as Fact; + + old_to_new.Add(sn.Id, add.Id); + } + + Add(add, out _, sn.samestep); + } + else if(old_to_new.ContainsKey(sn.Id)) + // Remove + { + Fact remove = FactDict[old_to_new[sn.Id]]; + Remove(remove, sn.samestep); + } + } + + // set un-redo state + while (this.backlog < exposed.backlog) + undo(); + + this.soft_resetted = exposed.soft_resetted; + + + // === local functions === + + void AddListToDict<T>(List<T> list) where T:Fact + { + foreach (T ft in list) + old_FactDict.Add(ft.Id, ft); + } } public Fact this[string id] { - get{ return FactDict[id]; } + get { return FactDict[id]; } } public bool ContainsKey(string id) @@ -165,7 +238,8 @@ private void PruneWorkflow() { stepnote last = Workflow[i]; - if (MetaInf[last.Id].workflow_id == i) + if (last.creation // may be zombie + && MetaInf[last.Id].workflow_id == i) // remove for good, if original creation gets pruned { this[last.Id].delete(); @@ -193,9 +267,14 @@ public string Add(Fact value, out bool exists, bool samestep = false) if (MetaInf[key].workflow_id >= marker) // check for zombie-status + { // protect zombie from beeing pruned + var zombie = Workflow[MetaInf[key].workflow_id]; + zombie.creation = false; + Workflow[MetaInf[key].workflow_id] = zombie; + // set new init location MetaInf[key] = new meta(marker, true); - + } // zombies are undead! else if (MetaInf[key].active) // desired outcome already achieved @@ -385,15 +464,27 @@ public void fastforward() redo(); } - public void store() + public void store(string name, bool use_type_subfolder = true) { - // TODO: save state of all of this? - // probably nothing: - // safe class instance somewhere + string path = CommunicationEvents.CreatePathToFile(out _, name, "JSON", use_type_subfolder ? typeof(FactOrganizer) : null); + + // note: max depth for "this" is 2, since Fact has non-serilazible member, that is not yet ignored (see Fact.[JasonIgnore] and JSONManager.WriteToJsonFile) + // using public dummy class to circumvent deserialiation JsonInheritanceProblem (see todos @PublicFactOrganizer) + JSONManager.WriteToJsonFile(path, new PublicFactOrganizer(this), 0); + } + + public static void load(ref FactOrganizer set, bool draw, string name, bool use_type_subfolder = true, bool reset_Fact = false) + { + string path = CommunicationEvents.CreatePathToFile(out _, name, "JSON", use_type_subfolder ? typeof(FactOrganizer) : null); + PublicFactOrganizer de_json = JSONManager.ReadFromJsonFile<PublicFactOrganizer>(path); + new FactOrganizer(ref set, de_json, draw); + + if (reset_Fact) + Fact.Clear(); } public void load(bool draw_all = true) - // call this after assigning a stored instance in an empty world + // call this after assigning a stored instance in an empty world, that was not drawn { // TODO: see issue #58 // TODO: communication with MMT @@ -431,8 +522,11 @@ private void InvokeFactEvent(bool creation, string Id) else CommunicationEvents.RemoveFactEvent.Invoke(this[Id]); - if (!creation) - FactDict[Id].freeLabel(); + if (creation) + // undo freeLabel() + _ = FactDict[Id].Label; + else + FactDict[Id].freeAutoLabel(); } public bool StaticlySovled(List<Fact> StaticSolution, out List<Fact> MissingElements, out List<Fact> Solutions) @@ -453,4 +547,140 @@ public bool DynamiclySolved(List<Fact> MinimalSolution, out List<Fact> MissingEl return MissingElements.Count == 0; } +} + + +// TODO? PERF? SE? JsonInheritanceProblem: scrap this hardwired class and implement dynamic approach with JsonConverter (see: JSONManager.JsonInheritenceConverter) +public class PublicFactOrganizer : FactOrganizer +// public class exposing all protected members of FactOrganizer for JSON conversion +{ + // TODO? check once if those are all with reflection + protected internal static List<string> WatchedFacts = new List<string>(new string[] { + "PointFact", + "LineFact", + "RayFact", + "OnLineFact", + "AngleFact" + }); + + public List<PointFact> PointFacts = new List<PointFact>(); + public List<LineFact> LineFacts = new List<LineFact>(); + public List<RayFact> RayFacts = new List<RayFact>(); + public List<OnLineFact> OnLineFacts = new List<OnLineFact>(); + public List<AngleFact> AngleFacts = new List<AngleFact>(); + + public new Dictionary<string, meta> MetaInf = new Dictionary<string, meta>(); + public new List<stepnote> Workflow = new List<stepnote>(); + // notes position in Workflow for un-/redo; the pointed to element is non-acitve + public new int marker = 0; + // backlock logic for convinience + public new int worksteps = 0; + public new int backlog = 0; + // set if recently been resetted + public new bool soft_resetted = false; + // InvokeEvents? + public new bool invoke; + + public new struct stepnote + { + // Fact.Id + public string Id; + // true if this Fact has been created in the same step as the last one + // steproot[false] (=> steptail[true])* + public bool samestep; + // reference to steproot/ after steptail-end + public int steplink; + // distincts creation and deletion + public bool creation; + + public stepnote(string Id, bool samestep, int steplink, bool creation) + { + this.Id = Id; + this.samestep = samestep; + this.steplink = steplink; + this.creation = creation; + } + + /*public stepnote(string Id, bool samestep, bool creation, PublicFactOrganizer that) + { + this.Id = Id; + this.samestep = samestep; + this.creation = creation; + + if (samestep) + // steplink = !first_steptail ? previous.steplink : steproot + { + stepnote prev = that.Workflow[that.marker - 1]; + this.steplink = prev.samestep ? prev.steplink : that.marker - 1; + } + else + // steproot sets steplink after itself (end of steptail) + this.steplink = that.marker + 1; + + }*/ + } + + public new struct meta + { + // TODO? -> public int last_occurence for safe_dependencies + + // reference to first occurrence in Workflow + public int workflow_id; + // keeps track wether Fact is currently in Scene + public bool active; + + public meta(int workflow_id, bool active) + { + this.workflow_id = workflow_id; + this.active = active; + } + } + + public PublicFactOrganizer() + { + FactDict = new Dictionary<string, Fact>(); + this.invoke = false; + } + + protected internal PublicFactOrganizer(FactOrganizer expose) + { + // expose all non-abstract members + marker = expose.marker; + worksteps = expose.worksteps; + backlog = expose.backlog; + soft_resetted = expose.soft_resetted; + invoke = expose.invoke; + + foreach (var sn in expose.Workflow) + Workflow.Add(new stepnote(sn.Id, sn.samestep, sn.steplink, sn.creation)); + + foreach (var mt in expose.MetaInf) + MetaInf.Add(mt.Key, new meta(mt.Value.workflow_id, mt.Value.active)); + + // expose and deserialize all abstract members + foreach (var fc in expose.FactDict.Values) + // keys are Fact.Id + { + switch (fc.GetType().Name) + { + case "PointFact": + PointFacts.Add(fc as PointFact); + break; + case "LineFact": + LineFacts.Add(fc as LineFact); + break; + case "RayFact": + RayFacts.Add(fc as RayFact); + break; + case "OnLineFact": + OnLineFacts.Add(fc as OnLineFact); + break; + case "AngleFact": + AngleFacts.Add(fc as AngleFact); + break; + default: + throw new System.NotImplementedException(); + } + } + } } \ No newline at end of file diff --git a/Assets/Scripts/InventoryStuff/ScrollDetails.cs b/Assets/Scripts/InventoryStuff/ScrollDetails.cs index 92af7732477ecc9ae0e79a5b9c35633e3c2b6b2d..c062b0b50ffcc8f2ff3c6fa03af9b3f243ea26ca 100644 --- a/Assets/Scripts/InventoryStuff/ScrollDetails.cs +++ b/Assets/Scripts/InventoryStuff/ScrollDetails.cs @@ -22,6 +22,9 @@ public class ScrollDetails : MonoBehaviour public string currentMmtAnswer; + public bool dynamicScrollDescriptionsActive = true; + public bool automaticHintGenerationActive = true; + public Vector3 GetPosition(int i) { return new Vector3(x_Start, y_Start + i * (-y_Paece_Between_Items), 0f); @@ -87,7 +90,8 @@ IEnumerator magicButton() } public void newAssignmentTrigger() { - StartCoroutine(newAssignment()); + if(this.automaticHintGenerationActive || this.dynamicScrollDescriptionsActive) + StartCoroutine(newAssignment()); } IEnumerator newAssignment() @@ -192,27 +196,40 @@ public void processScrollDynamicInfo(Scroll.ScrollDynamicInfo scrollDynamicInfo) //Update Scroll, process data for later hints and update Uri-List for which hints are available hintUris = processRenderedScroll(scrollDynamicInfo.rendered, hintUris); - //Show that Hint is available for ScrollParameter - HintAvailableEvent.Invoke(hintUris); + if (this.automaticHintGenerationActive) + { + //Show that Hint is available for ScrollParameter + HintAvailableEvent.Invoke(hintUris); + } } public List<string> processRenderedScroll(Scroll rendered, List<string> hintUris) { Transform scroll = gameObject.transform.GetChild(1).transform; - //Update scroll-description - scroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = rendered.description; + if (this.dynamicScrollDescriptionsActive) + { + //Update scroll-description + scroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = rendered.description; + } for (int i = 0; i < rendered.requiredFacts.Count; i++) { - //Update ScrollParameter label var obj = ParameterDisplays.Find(x => x.transform.GetChild(0).GetComponent<RenderedScrollFact>().factUri.Equals(rendered.requiredFacts[i].@ref.uri)); - obj.transform.GetChild(0).GetComponent<RenderedScrollFact>().Label = rendered.requiredFacts[i].label; + + if (this.dynamicScrollDescriptionsActive) + { + //Update ScrollParameter label + obj.transform.GetChild(0).GetComponent<RenderedScrollFact>().Label = rendered.requiredFacts[i].label; + } //Check Hint Informations //If ScrollFact is assigned -> No Hint if (obj.transform.GetChild(0).GetComponent<DropHandling>().currentFact == null) { Fact currentFact = ParsingDictionary.parseFactDictionary[rendered.requiredFacts[i].getType()].Invoke(rendered.requiredFacts[i]); + //If currentFact could be parsed: this fact maybe not yet exists in the global fact-list but there must be a fact + // of the same type and the same dependent facts in the fact-list, otherwise currentFact could not have been parsed + //If the fact could not be parsed -> Therefore not all dependent Facts exist -> No Hint //AND if fact has no dependent facts -> No Hint if (currentFact != null && currentFact.hasDependentFacts()) @@ -240,8 +257,9 @@ public void animateHint(GameObject scrollParameter, string scrollParameterUri) { scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger(); //Animate Fact in FactPanel AnimateExistingFactEvent.Invoke(fact); - //Animate factRepresentation in game - fact.Representation.GetComponentInChildren<MeshRendererHintAnimation>().AnimationTrigger(); + //Animate factRepresentation in game, if fact has a Representation (e.g. OnLineFact has no Representation) + if(fact.Representation != null) + fact.Representation.GetComponentInChildren<MeshRendererHintAnimation>().AnimationTrigger(); } } else if (LatestRenderedHints.Exists(x => x.Id.Equals(scrollParameterUri))) @@ -258,8 +276,8 @@ public void animateHint(GameObject scrollParameter, string scrollParameterUri) { scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger(); //Animate Fact in FactPanel AnimateExistingFactEvent.Invoke(existingFact); - //Animate factRepresentation in game if Fact has a Representation - if(existingFact.Representation != null) + //Animate factRepresentation in game if Fact has a Representation (e.g. OnLineFact has no Representation) + if (existingFact.Representation != null) existingFact.Representation.GetComponentInChildren<MeshRendererHintAnimation>().AnimationTrigger(); } //If not -> Generate a Fact-Representation with such dependent facts diff --git a/Assets/Scripts/JSONManager.cs b/Assets/Scripts/JSONManager.cs index 9b0c619cb7794e60ada4149db0452e9c9832a200..098f17f68a4c6dc1398fcd54a6104e89263a58e4 100644 --- a/Assets/Scripts/JSONManager.cs +++ b/Assets/Scripts/JSONManager.cs @@ -1,10 +1,13 @@ -using System; -using JsonSubTypes; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using System; +using System.Linq; using Newtonsoft.Json; +using JsonSubTypes; using System.Collections; -using System.Collections.Generic; using UnityEngine; - +using Newtonsoft.Json.Linq; public class MMTURICollection { @@ -77,7 +80,6 @@ public OMSTR(string s) } } - public class OMF : MMTTerm { [JsonProperty("float")] @@ -148,4 +150,168 @@ public MMTValueDeclaration(string label, MMTTerm lhs, MMTTerm valueTp, MMTTerm v } } + + // TODO? /// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [JsonIgnore] attribute.</para> + + /// <summary> + /// Writes the given object instance to a Json file, recursively to set depth, including all members. + /// <para>Object type must have a parameterless constructor.</para> + /// <para>Only All properties and variables will be written to the file. These can be any type though, even other non-abstract classes.</para> + /// </summary> + /// <param name="filePath">The file path to write the object instance to.</param> + /// <param name="objectToWrite">The object instance to write to the file.</param> + /// <param name="max_depth">The depth recursion will occur. Default = 0.</param> + public static void WriteToJsonFile(string filePath, object objectToWrite, int max_depth = 0) + { + int current_depth = 0; + + // This tells your serializer that multiple references are okay. + var settings = new JsonSerializerSettings(); + settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + + BindingFlags bindFlags = + BindingFlags.Instance | + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Static; + + TextWriter writer = null; + try + { + string payload = RecursiveStep(objectToWrite); + writer = new StreamWriter(filePath); + writer.Write(payload); + } + finally + { + if (writer != null) + writer.Close(); + } + + + // ======= local methods ======= + // TODO? more stable depths (see next todo) + // TODO? respect IgnoreJson tags + + string RecursiveStep<S>(S objectToWrite) where S : new() + { + string json; + + if (current_depth >= max_depth + || Type.GetTypeCode(objectToWrite.GetType()) != TypeCode.Object + || objectToWrite == null) + json = JsonConvert.SerializeObject(objectToWrite, settings/*, new JsonInheritenceConverter<object>()*/); + else + { + current_depth++; + json = IntrusiveRecursiveJsonGenerator(objectToWrite); + current_depth--; + } + + return json; + } + + string IntrusiveRecursiveJsonGenerator<S>(S objectToWrite) where S : new() + // private convention? more like private suggestion! + { + bool is_enum = IsEnumerableType(objectToWrite.GetType()); + + string json = is_enum ? "[" : "{"; + foreach (object field in is_enum ? (objectToWrite as IEnumerable) : objectToWrite.GetType().GetFields(bindFlags)) + { + object not_so_private; + if (is_enum) + { + not_so_private = field; + } + else + { + not_so_private = ((FieldInfo)field).GetValue(objectToWrite); + json += ((FieldInfo)field).Name + ":"; + } + + json += RecursiveStep(not_so_private); + + json += ","; + } + json = json.TrimEnd(',') + (is_enum ? "]" : "}"); + + return json; + + + // ======= local methods ======= + + bool IsEnumerableType(Type type) + { + if (type.IsInterface && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) + return true; + + foreach (Type intType in type.GetInterfaces()) + { + if (intType.IsGenericType + && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) + { + return true; + } + } + return false; + } + } + } + + /// <summary> + /// Reads an object instance from an Json file. + /// <para>Object type must have a parameterless constructor.</para> + /// </summary> + /// <typeparam name="T">The type of object to read from the file.</typeparam> + /// <param name="filePath">The file path to read the object instance from.</param> + /// <returns>Returns a new instance of the object read from the Json file.</returns> + public static T ReadFromJsonFile<T>(string filePath) where T : new() + { + TextReader reader = null; + try + { + reader = new StreamReader(filePath); + var fileContents = reader.ReadToEnd(); + return JsonConvert.DeserializeObject<T>(fileContents/*, new JsonInheritenceConverter<object>()*/); + } + finally + { + if (reader != null) + reader.Close(); + } + } + + // tutorial @https://www.codeproject.com/Articles/1201466/Working-with-JSON-in-Csharp-VB#data_structure_types + // unused + // TODO: check for actual type in ReadJson + // TODO: avoid self-referencing-loop-error in WriteJson + public sealed class JsonInheritenceConverter<T> : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return typeof(T).IsAssignableFrom(objectType); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + JObject jo = JObject.Load(reader); + var element = jo.Properties().First(); + return element.Value.ToObject(Type.GetType(element.Name)); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value == null) + { + serializer.Serialize(writer, null); + return; + } + + writer.WriteStartObject(); + writer.WritePropertyName(value.GetType().FullName); + serializer.Serialize(writer, value); + writer.WriteEndObject(); + } + } } diff --git a/Assets/Scripts/Level.cs b/Assets/Scripts/Level.cs index 4dcd75000ebbe0b385cbcbce91125458a4f3c445..49eadeef8cc6dd77782df6f18409fd3e0e6edae2 100644 --- a/Assets/Scripts/Level.cs +++ b/Assets/Scripts/Level.cs @@ -9,8 +9,6 @@ public class Level : MonoBehaviour //Solving game parameters public int minimalSolutionHight; - public static bool solved = false; - void Start() // Start is called before the first frame update @@ -25,11 +23,12 @@ void Start() LineFact target = new LineFact(buttom.Id, top.Id, SolutionManager); Solution.Add(SolutionManager[SolutionManager.Add(target, out _, true)]); + Fact.Clear(); } public static bool gameSolved() { - solved = + bool solved = LevelFacts.DynamiclySolved(Solution, out _, out List<Fact> hits, FactComparer: new LineFactHightDirectionComparer()); if (solved) diff --git a/Assets/Scripts/Restart.cs b/Assets/Scripts/Restart.cs index 613be963d6b3480d8f5a9541b592dd846f39c445..eea905469957fc745855804933e9c64e8d47076c 100644 --- a/Assets/Scripts/Restart.cs +++ b/Assets/Scripts/Restart.cs @@ -12,6 +12,8 @@ public void LevelReset() // only when generated! (in Level.cs) CommunicationEvents.SolutionManager.hardreset(false); + Fact.Clear(); + SceneManager.LoadSceneAsync(SceneManager.GetActiveScene().buildIndex); }