Skip to content

Commit fb13eda

Browse files
committed
create-aframe-components is a singleton
1 parent 223b825 commit fb13eda

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

a-toolkit/create-aframe-components.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { getUIWidgets } from './dreem-imports';
2+
3+
const requireDreem = path => window.defineDreem.requireDreem(path);
4+
5+
const dreemAppendChild = function(parent, child){
6+
var Render = requireDreem('$system/base/render');
7+
8+
child.parent = parent
9+
child.rpc = parent.rpc
10+
child.screen = parent.screen
11+
if (!child.screen.initialized) {
12+
throw new Error("INVALID SCREEN FOUND ON ", parent, parent.screen);
13+
}
14+
child.parent_viewport = parent._viewport?parent:parent.parent_viewport
15+
16+
parent.children.push(child);
17+
18+
// render it
19+
Render.process(child, undefined, undefined, false)
20+
21+
22+
parent.relayout();
23+
}
24+
25+
26+
let attrBlacklist = new Set(["position", "scale", "rotation", "visible"]);
27+
let attrNames = aComponent => Array.from(aComponent.attributes).filter(x => !attrBlacklist.has(x.name));
28+
29+
function strMapToObj(strMap) {
30+
let obj = {};
31+
for (let [k,v] of strMap) {
32+
// We don’t escape the key '__proto__'
33+
// which can cause problems on older engines
34+
obj[k] = v;
35+
}
36+
return obj;
37+
}
38+
39+
let props = aComponent => strMapToObj(new Map(
40+
attrNames(aComponent).map(attr => [attr.name, aComponent.getAttribute(attr.name)])
41+
));
42+
43+
// Maps A-Frame elements to corresponding Dreem instances
44+
const elToDreemInstance = new Map();
45+
46+
// Sometimes we add a dreem before its parents are processed
47+
// we need to wait to process them at this point
48+
const waitingForParents = new Set();
49+
const processIfParentsAppeared = () => {
50+
// Try to append elements, see if their parents appeared yet
51+
const parentsFoundFor = Array.from(waitingForParents).filter(
52+
({ dreemObj, el }) => appendToParentEl(dreemObj, el, false)
53+
);
54+
55+
56+
// recurse if we found anyone's parents, maybe somebody was waiting for THEM
57+
if (parentsFoundFor.length > 0) {
58+
// If anyone's parents appeared, remove them from the waitlist
59+
parentsFoundFor.forEach(item => waitingForParents.delete(item));
60+
processIfParentsAppeared();
61+
}
62+
};
63+
64+
window.waitingForParents = waitingForParents;
65+
window.processIfParentsAppeared = processIfParentsAppeared;
66+
67+
68+
const appendToParentEl = (dreemObj, el, notInWaitQueue=true) => {
69+
// first lets register outselves...
70+
elToDreemInstance.set(el, dreemObj);
71+
72+
const parentDreem = elToDreemInstance.get(el.parentEl);
73+
74+
if (parentDreem) {
75+
dreemAppendChild(parentDreem, dreemObj);
76+
77+
if (notInWaitQueue) processIfParentsAppeared();
78+
79+
return true;
80+
} else {
81+
// uhoh, we don't have parents yet, lets wait for them to appear
82+
if (notInWaitQueue) waitingForParents.add({ dreemObj, el });
83+
return false;
84+
}
85+
};
86+
87+
88+
89+
90+
91+
let initialized = false;
92+
function createAFrameComponents() {
93+
if (initialized) return;
94+
initialized = true;
95+
96+
const uiWidgets = getUIWidgets();
97+
const widgetNameToPath = new Map(
98+
uiWidgets.map(path => [path.split('/').slice(1).join('-'), path])
99+
);
100+
widgetNameToPath.set('ui-entity', false);
101+
102+
// Go through all the dreem classes marked as UI and register A-Frame components for them
103+
Array.from(widgetNameToPath.entries()).forEach(([widgetName, dreemPath]) => {
104+
// console.log("registering " + widgetName);
105+
AFRAME.registerComponent(widgetName, {
106+
schema: {
107+
dreem: {type: 'string', default: ''}
108+
},
109+
init() {
110+
// If they set <ui-entity dreemClass="$ui/some-dreem-class"> manually, use it
111+
dreemPath = this.data.dreem.length > 0 ? this.data.dreem : dreemPath;
112+
const DreemClass = requireDreem(dreemPath);
113+
const dreemInstance = new DreemClass(props(this.el));
114+
115+
appendToParentEl(dreemInstance, this.el);
116+
this.dreem = dreemInstance;
117+
}
118+
});
119+
const defaultComponents = {};
120+
defaultComponents[widgetName] = {};
121+
AFRAME.registerPrimitive('a-' + widgetName, {
122+
defaultComponents,
123+
mappings: {
124+
dreem: widgetName + '.dreem'
125+
}
126+
});
127+
});
128+
};
129+
130+
131+
export {createAFrameComponents, elToDreemInstance};

0 commit comments

Comments
 (0)