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