Skip to content
Snippets Groups Projects
Verified Commit 080838f0 authored by Björn Eßwein's avatar Björn Eßwein
Browse files

Attached the WebView scroll UI to the ActiveScroll.

parent 2be856ef
No related branches found
No related tags found
No related merge requests found
...@@ -406,12 +406,12 @@ PrefabInstance: ...@@ -406,12 +406,12 @@ PrefabInstance:
- target: {fileID: 8553388048532215990, guid: 884ac57de337c364391b247761071fb1, - target: {fileID: 8553388048532215990, guid: 884ac57de337c364391b247761071fb1,
type: 3} type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8553388048532215990, guid: 884ac57de337c364391b247761071fb1, - target: {fileID: 8553388048532215990, guid: 884ac57de337c364391b247761071fb1,
type: 3} type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8553388048532215990, guid: 884ac57de337c364391b247761071fb1, - target: {fileID: 8553388048532215990, guid: 884ac57de337c364391b247761071fb1,
type: 3} type: 3}
...@@ -561,7 +561,7 @@ PrefabInstance: ...@@ -561,7 +561,7 @@ PrefabInstance:
- target: {fileID: 6500467619489830996, guid: 292834880e6f0e54186b873acc62d3f2, - target: {fileID: 6500467619489830996, guid: 292834880e6f0e54186b873acc62d3f2,
type: 3} type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 604800 value: 605880
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7849991042685492731, guid: 292834880e6f0e54186b873acc62d3f2, - target: {fileID: 7849991042685492731, guid: 292834880e6f0e54186b873acc62d3f2,
type: 3} type: 3}
...@@ -611,7 +611,7 @@ PrefabInstance: ...@@ -611,7 +611,7 @@ PrefabInstance:
- target: {fileID: 7989559431199338490, guid: 292834880e6f0e54186b873acc62d3f2, - target: {fileID: 7989559431199338490, guid: 292834880e6f0e54186b873acc62d3f2,
type: 3} type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: -33600 value: -33660
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8004702056544321748, guid: 292834880e6f0e54186b873acc62d3f2, - target: {fileID: 8004702056544321748, guid: 292834880e6f0e54186b873acc62d3f2,
type: 3} type: 3}
......
...@@ -2950,6 +2950,36 @@ MonoBehaviour: ...@@ -2950,6 +2950,36 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: ae310511ad607a64e891bcb46517277b, type: 3} m_Script: {fileID: 11500000, guid: ae310511ad607a64e891bcb46517277b, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
OnButtonClick:
m_PersistentCalls:
m_Calls: []
HintAvailableEvent:
m_PersistentCalls:
m_Calls: []
OnFactAssignmentUpdated:
m_PersistentCalls:
m_Calls: []
OnMMTServerComunicationError:
m_PersistentCalls:
m_Calls: []
OnScrollDynamicInfoError:
m_PersistentCalls:
m_Calls: []
OnScrollApplicationError:
m_PersistentCalls:
m_Calls: []
OnCancelErrorState:
m_PersistentCalls:
m_Calls: []
OnScrollSolved:
m_PersistentCalls:
m_Calls: []
OnScrollChanged:
m_PersistentCalls:
m_Calls: []
OnScrollDynamicInfoUpdated:
m_PersistentCalls:
m_Calls: []
DynamicScrollDescriptionsActive: 1 DynamicScrollDescriptionsActive: 1
AutomaticHintGenerationActive: 1 AutomaticHintGenerationActive: 1
--- !u!1 &8004702058016740896 --- !u!1 &8004702058016740896
...@@ -3475,12 +3505,12 @@ PrefabInstance: ...@@ -3475,12 +3505,12 @@ PrefabInstance:
- target: {fileID: 2974656142881083530, guid: 1e9d514b702f5784791a4df8d22e1866, - target: {fileID: 2974656142881083530, guid: 1e9d514b702f5784791a4df8d22e1866,
type: 3} type: 3}
propertyPath: m_SizeDelta.x propertyPath: m_SizeDelta.x
value: 600 value: 32
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 2974656142881083530, guid: 1e9d514b702f5784791a4df8d22e1866, - target: {fileID: 2974656142881083530, guid: 1e9d514b702f5784791a4df8d22e1866,
type: 3} type: 3}
propertyPath: m_SizeDelta.y propertyPath: m_SizeDelta.y
value: 600 value: 32
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 2974656142881083530, guid: 1e9d514b702f5784791a4df8d22e1866, - target: {fileID: 2974656142881083530, guid: 1e9d514b702f5784791a4df8d22e1866,
type: 3} type: 3}
...@@ -3573,9 +3603,6 @@ MonoBehaviour: ...@@ -3573,9 +3603,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 534d25977ad35154781c29672ce2bb13, type: 3} m_Script: {fileID: 11500000, guid: 534d25977ad35154781c29672ce2bb13, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
onFactAssignment:
m_PersistentCalls:
m_Calls: []
onHintRequested: onHintRequested:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
......
using REST_JSON_API; using REST_JSON_API;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions;
using TMPro; using TMPro;
using UnityEngine; using UnityEngine;
...@@ -67,7 +68,13 @@ private void ShowScroll(Scroll newScroll) ...@@ -67,7 +68,13 @@ private void ShowScroll(Scroll newScroll)
//Clear all current ScrollFacts //Clear all current ScrollFacts
originalViewport.GetChild(0).gameObject.DestroyAllChildren(); originalViewport.GetChild(0).gameObject.DestroyAllChildren();
originalScroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = newScroll.description; var description = newScroll.description;
// if description is a html description, extract the alternative text representation
if (newScroll.description.StartsWith("<scroll-description"))
{
description = Regex.Match(newScroll.description, "<scroll-description [^>]* alt=([\"']?)(.*)\\1 [^>]*>").Groups[2].Value;
}
originalScroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = description;
//ParameterDisplays.ForEach(gameObj => Destroy(gameObj)); //ParameterDisplays.ForEach(gameObj => Destroy(gameObj));
ParameterDisplays = new(); ParameterDisplays = new();
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
using MoreLinq; using MoreLinq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using REST_JSON_API;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
...@@ -14,14 +15,6 @@ ...@@ -14,14 +15,6 @@
public class WebViewController : ScrollView public class WebViewController : ScrollView
{ {
// TODO: onFactAssignment event shoud hav a dropzone id and a fact id as parameters
public UnityEvent<DomNodeWrapper, string> onFactAssignment;
// TODO: implement onHintRequested event
public UnityEvent<DomNodeWrapper, string> onHintRequested;
// TODO: click events (option for custom buttons for a scroll)
public UnityEvent<DomNodeWrapper> onClick;
private WebViewComponent webViewComponent; private WebViewComponent webViewComponent;
private DomNodeWrapper[] dropzones; private DomNodeWrapper[] dropzones;
...@@ -31,40 +24,121 @@ private void Awake() ...@@ -31,40 +24,121 @@ private void Awake()
webViewComponent = GetComponent<WebViewComponent>(); webViewComponent = GetComponent<WebViewComponent>();
WebViewComponent.serializerSettings.Converters.Add(new FactObjectUIConverter()); WebViewComponent.serializerSettings.Converters.Add(new FactObjectUIConverter());
webViewComponent.targetUrl = Path.Join(CommunicationEvents.Get_DataPath(), "scrollView.html"); webViewComponent.targetUrl = Path.Join(CommunicationEvents.Get_DataPath(), "scrollView.html");
webViewComponent.OnWebViewComponentReady += OnWebViewComponentReady;
// TODO: handle webViewComponent.onDomDocumentUpdated // TODO: handle webViewComponent.onDomDocumentUpdated
}
private void OnWebViewComponentReady()
{
webViewComponent.onDomDocumentUpdated += DocumentUpdatedHandler;
SwitchScrollUI.activeScrollData.OnScrollChanged.AddListener(SetScrollContent);
SwitchScrollUI.activeScrollData.OnScrollDynamicInfoUpdated.AddListener(SetScrollContent);
webViewComponent.tab.AddJSBinding("applyScroll", ApplyScrollHandler);
webViewComponent.tab.AddJSBinding("getHint", GetHintHandler);
RegisterBrowserEventhandlers();
}
private void OnDisable()
{
webViewComponent.onDomDocumentUpdated -= DocumentUpdatedHandler;
SwitchScrollUI.activeScrollData.OnScrollChanged.RemoveListener(SetScrollContent);
SwitchScrollUI.activeScrollData.OnScrollDynamicInfoUpdated.RemoveListener(SetScrollContent);
webViewComponent.tab.RemoveJSBinding("applyScroll");
webViewComponent.tab.RemoveJSBinding("getHint");
DeRegisterBrowserEventhandlers();
}
// TODO: remove this debug code private void DocumentUpdatedHandler(documentUpdatedEvent _)
onFactAssignment.AddListener((DomNodeWrapper node, string factId) => { {
Debug.LogWarning($"onFactAssignment: '{string.Join(", ", GetFactAssignments())}'"); // all old DomNodeWrapper objects are invalid, because the whole document has been updated
}); dropzones = null;
RegisterBrowserEventhandlers();
}
private async void RegisterBrowserEventhandlers()
{
// register js event handlers in the browser
_ = webViewComponent.tab.Evaluate("dropZones = document.querySelectorAll('[dropzone=\"copy\"]'); dropZones.forEach( dropZone => dropZone.addEventListener(\"drop\", ev => dropHandler(ev, \"DropEvent\")) )");
// register c# event handlers
// get the dropzones from the scroll and add the event handler to track when something is dropped
DomNodeWrapper document = await webViewComponent.tab.GetDocument();
dropzones = await document.querySelectorAllAsync("[dropzone='copy']");
dropzones.ForEach(dropzone => dropzone.OnAttributeModified += DropzoneAttributeModifiedHandler);
}
private void DeRegisterBrowserEventhandlers()
{
dropzones?.ForEach(dropzone => dropzone.OnAttributeModified -= DropzoneAttributeModifiedHandler);
} }
/// <summary> /// <summary>
/// sets or updates the content of the scroll container dom element /// sets or updates the content of the scroll container dom element
/// </summary> /// </summary>
/// <param name="scrollHTML"></param> /// <param name="scrollHTML"></param>
public async void SetScrollContent(string scrollHTML) private async void SetScrollContent(Scroll scroll)
{ {
// update scroll container content // update scroll container content
DomNodeWrapper scrollContainer = await DomNodeWrapper.requestNodeAsync(webViewComponent.tab, "scrollContainer"); DomNodeWrapper document = await webViewComponent.tab.GetDocument();
await scrollContainer.setNodeValueAsync(scrollHTML); DomNodeWrapper scrollContainer = await document.querySelectorAsync("#scrollContainer");
// get the dropzones from the scroll and add the event handler to track when something is dropped var description = scroll.description;
dropzones = await scrollContainer.querySelectorAllAsync("[dropzone='copy']"); // if scroll is a lagacy plain text scroll, generate html with slots for the required facts
dropzones.ForEach(dropzone => dropzone.OnAttributeModified += DropzoneAttributeModifiedHandler); if (!scroll.description.StartsWith("<scroll-description"))
{
// generate slots for a plane text scroll description
var factSlots = SwitchScrollUI.activeScrollData.Assignments
.Where(pair => pair.Value.IsVisible)
.Select(pair =>
@$"<span class='lagacySlot' dropzone='copy' data-slot-id='{pair.Key}' {(pair.Value.IsSet ? $"data-fact-id='{pair.Value.fact.Id}'" : "")}>
{(pair.Value.IsSet ?
pair.Value.fact.GetLabel(StageStatic.stage.factState) :
scroll.requiredFacts.Find(fact => fact.@ref.uri == pair.Key).label )}
</span>");
description = $"<scroll-description><p>{scroll.description}</p><div id='lagacySlots'>{String.Join("", factSlots)}</div></scroll-description>";
}
// display the scroll description
await scrollContainer.setOuterHtmlAsync($"<div id='scrollContainer'>{description}</div>");
RegisterBrowserEventhandlers();
} }
private void DropzoneAttributeModifiedHandler(attributeModifiedEvent attributeModifiedEvent) private async void DropzoneAttributeModifiedHandler(attributeModifiedEvent attributeModifiedEvent)
{ {
Debug.LogWarning($"dropzoneAtrributeModifiedHandler: '{attributeModifiedEvent.name}'"); Debug.LogWarning($"dropzoneAtrributeModifiedHandler: '{attributeModifiedEvent.name}'");
// call the onFactAssignment event if the data-fact-id attribute was modified // call the onFactAssignment event if the data-fact-id attribute was modified
if (attributeModifiedEvent.name == "data-fact-id") if (attributeModifiedEvent.name == "data-fact-id")
{ {
var node = webViewComponent.tab.domNodes.GetValueOrDefault(attributeModifiedEvent.nodeId); // get the slot id
onFactAssignment.Invoke(node, attributeModifiedEvent.value); var node = await webViewComponent.tab.GetNode(attributeModifiedEvent.nodeId);
if (! (node.Node.attributes.TryGetValue("data-slot-id", out string slot)
|| (await node.getAttributesAsync()).TryGetValue("data-slot-id", out slot)))
{
Debug.LogError($"dropzoneAtrributeModifiedHandler: data-slot-id attribute not found on dropzone");
throw new Exception("data-slot-id attribute not found on dropzone");
}
// get the fact from the fact id
if (!FactRecorder.AllFacts.TryGetValue(attributeModifiedEvent.value, out Fact fact))
{
Debug.LogError($"dropzoneAtrributeModifiedHandler: fact with id '{attributeModifiedEvent.value}' not found");
throw new Exception($"fact with id '{attributeModifiedEvent.value}' not found");
} }
// assign fact to slot
SwitchScrollUI.activeScrollData.AssignFact(slot, fact);
}
}
private void ApplyScrollHandler(string button)
{
SwitchScrollUI.activeScrollData.ButtonClicked(new MagicScrollButton());
}
private void GetHintHandler(string url)
{
SwitchScrollUI.activeScrollData.ButtonClicked(new HintScrollButton(url));
} }
public string[] GetFactAssignments() public string[] GetFactAssignments()
...@@ -72,6 +146,7 @@ public string[] GetFactAssignments() ...@@ -72,6 +146,7 @@ public string[] GetFactAssignments()
return dropzones.Select(dropzone => dropzone.Node.attributes.GetValueOrDefault("data-fact-id", null)).ToArray(); return dropzones.Select(dropzone => dropzone.Node.attributes.GetValueOrDefault("data-fact-id", null)).ToArray();
} }
[Obsolete()]
private async void GetDropzoneStateAsync() private async void GetDropzoneStateAsync()
{ {
// alternative way to get the dropzone state // alternative way to get the dropzone state
......
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Scroll View</title> <title>Scroll View</title>
...@@ -9,7 +8,13 @@ ...@@ -9,7 +8,13 @@
font-size: 100px; font-size: 100px;
} }
[dropzone] { [dropzone] {
background-color: yellow; background-color: grey;
}
.lagacySlot {
width: 100px;
height: 100px;
margin: 50px;
border-width: 1px;
} }
#rectangle { #rectangle {
width: 10px; width: 10px;
...@@ -24,6 +29,8 @@ ...@@ -24,6 +29,8 @@
</style> </style>
</head> </head>
<body> <body>
<div id="scrollContainer">
<div>Default Scroll</div>
<math> <math>
<mi>E</mi> <mi>E</mi>
<mo>=</mo> <mo>=</mo>
...@@ -64,46 +71,9 @@ ...@@ -64,46 +71,9 @@
</mtr> </mtr>
</mtable> </mtable>
</math> </math>
<div class="demoFact">{ </div>
"s_type": "PointFact", <button type="button" title="Apply the scroll" onclick="applyScroll()">Magic</button><br>
"label": "A", <button type="button" title="Hint" onclick="getHint('http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC')">Hint</button>
"_CustomLabel": null,
"hasCustomLabel": false,
"labelId": 0,
"point": {"x": -1.66086578, "y": -0.00494432449, "z": -2.17682648},
"normal": {"x": 0.1, "y": 1.2, "z": 0.3}
}</div>
<div class="demoFact">{
"pid1": "http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact252",
"pid2": "http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact254",
"pid3": "http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact256",
"s_type": "AngleFact",
"label": "∠BDF",
"_CustomLabel": null,
"is_right_angle": false,
"hasCustomLabel": false,
"labelId": 0
}</div>
<div class="demoFact">{
"s_type": "LineFact",
"pid1": "http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact255",
"pid2": "http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact256",
"dir": {"x": 0.1, "y": 1.2, "z": 0.3},
"label": "[EF]",
"_CustomLabel": null,
"hasCustomLabel": false,
"labelId": 0
}</div>
<div class="demoFact">{
"s_type": "RayFact",
"pid1": "http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact256",
"pid2": "http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact252",
"dir": {"x": 0.1, "y": 1.2, "z": 0.3},
"label": "FB",
"_CustomLabel": null,
"hasCustomLabel": false,
"labelId": 0
}</div>
</body> </body>
<script> <script>
/** /**
......
Subproject commit c49f768b41a3caf0541fcdbfa0d65b74c7e63a4f Subproject commit 32bbc9be2e099918d10d0e54e8993cae6e54799a
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment