Closed microaaron closed 2 years ago
Yes, I think that should work. Can you find a similar example test in https://github.com/x3dom/x3dom/tree/master/test/functional/protos ?
https://jsitor.com/FPSiL8lF9 has a potential fix. Since proto handling is quite involved, it will be necessary to test against all proto examples. An additional fieldWatcher for the proto wrapper node now forwards events in to IS nodes. Since there is also a similar forwarder from inside the Proto out to the proto wrapper, there is a loop. So that outForwarder is disabled when the inForwarder is invoked. That was the most challenging to determine.
Could you please test with your setup ? Thanks.
Thanks, It works now. But what about routing from ProtoInstance like this: https://jsitor.com/zJwD5eNRs Died loop problem really makes things complex.
HTML:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1,IE=edge" />
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript" src="https://x3dom.org/download/1.8.2/x3dom-full.debug.js"></script>
<link rel='stylesheet' type='text/css' href='https://www.x3dom.org/release/x3dom.css'>
</link>
</head>
<body>
<X3D showLog="true" profile="Immersive" version="3.2">
<Scene id="rootScene">
<ExternProtoDeclare name="testbox"
url="https://raw.githubusercontent.com/microaaron/ProtoExample/main/routeInProtoBody2.x3d">
</ExternProtoDeclare>
<ProtoInstance name="testbox" DEF="testbox">
<fieldValue name="translation" value="0 0 0" />
</ProtoInstance>
<Transform translation="2.5 0 0">
<Transform DEF="box2">
<Shape>
<Box size="1 1 1"></Box>
<Appearance>
<Material diffuseColor="0 0 1"></Material>
</Appearance>
</Shape>
</Transform>
</Transform>
<ROUTE fromNode="testbox" fromField="translatione_changed" toNode="box2" toField="set_translation"></ROUTE> <!--routing from ProtoInstance doesn't work-->
</Scene>
</X3D>
</body>
</html>
routeInProtoBody2.x3d:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.2//EN" "http://www.web3d.org/specifications/x3d-3.2.dtd">
<X3D profile="Immersive" version="3.2">
<Scene>
<ProtoDeclare name='testbox'>
<ProtoInterface>
<field name='translation' type='SFVec3f' accessType='inputOutput'></field>
</ProtoInterface>
<ProtoBody>
<Group>
<Transform DEF="box1">
<IS>
<connect nodeField="translation" protoField="translation"></connect>
</IS>
<Shape>
<Box size="1 1 1"></Box>
<Appearance>
<Material diffuseColor="0 1 0"></Material>
</Appearance>
</Shape>
</Transform>
<TimeSensor DEF="Timer" cycleInterval="5" loop="true"></TimeSensor>
<PositionInterpolator DEF="PI" key="0 0.25 0.5 0.75 1" keyValue="0 0 0, 0.5 0 0, 0 0 0, -0.5 0 0, 0 0 0">
</PositionInterpolator>
<ROUTE fromNode="Timer" fromField="fraction_changed" toNode="PI" toField="set_fraction"></ROUTE>
<ROUTE fromNode="PI" fromField="value_changed" toNode="box1" toField="set_translation"></ROUTE>
</Group>
</ProtoBody>
</ProtoDeclare>
</Scene>
</X3D>
I think there was a typo: 'translatione'
---on the phone---
On Wed, Nov 24, 2021, 1:37 AM microaaron @.***> wrote:
Thanks, It works now. But what about routing from ProtoInstance like this: https://jsitor.com/zJwD5eNRs Died loop problem really make things complex.
HTML:
routeInProtoBody2.x3d:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.2//EN" "http://www.web3d.org/specifications/x3d-3.2.dtd">
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/x3dom/x3dom/issues/1177#issuecomment-977575764, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABPCT22UOZPSX3LSMXD7IWTUNSB3VANCNFSM5ITI7BCA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
It works. Thanks very much.
Here the revised method for ProtoDeclaration
_setupFieldWatchers: function (field) {
this.declaration._protoBody._ISRoutes[field].forEach(function (ISNode) {
var instanceNode = this.innerNameSpace.defMap[ISNode.nodeDEF];
if (instanceNode == undefined) {
var ISparent = this.protoBodyClone.querySelector("[DEF=" + ISNode.nodeDEF + "]");
if (ISparent.tagName.toLowerCase() == "protoinstance") {
if (this._externTries++ < this._maxTries) {
x3dom.debug.logWarning(" retrying ExternProto: " + this._externTries);
//try again
var timer = setTimeout(this._setupFieldWatchers.bind(this), 1000, field);
}
}
return;
}
var nodeField = this._normalizeName(ISNode.nodeField, instanceNode);
if (!instanceNode._fieldWatchers[nodeField]) {
instanceNode._fieldWatchers[nodeField] = [];
}
var outForwarder = this.postMessage.bind(this, field);
var _watchers = instanceNode._fieldWatchers[nodeField];
_watchers.push(outForwarder); // forward out
// remember outForwardex index for below
var outForwarder_index = _watchers.length - 1;
// AP: added event in forwarding from proto node to instance node so routes can pick it up
if (!this._fieldWatchers[field]) {
this._fieldWatchers[field] = [];
}
var inForwarder = (function (msg)
// avoid cycle
{ // remove above fieldwatcher
_watchers.splice(outForwarder_index, 1);
instanceNode.postMessage(nodeField, msg);
// add back above fieldwatcher
_watchers.push(outForwarder);
outForwarder_index = _watchers.length - 1; // update
}).bind(instanceNode);
this._fieldWatchers[field].push(inForwarder); // forward in
//instanceNode.postMessage.bind( instanceNode, nodeField ) ); // forward in
}, this);
},
Here is the example: https://jsitor.com/MBwavo1Vg