@@ -2,54 +2,70 @@ import * as React from 'react';
22import 'react-app-polyfill/ie11' ;
33import * as ReactDOM from 'react-dom' ;
44import { animated } from 'react-spring' ;
5- import { a } from 'react-spring/three' ;
6- import { Canvas } from 'react-three-fiber' ;
5+ import { a } from '@ react-spring/three' ;
6+ import { Canvas , useLoader } from 'react-three-fiber' ;
77import * as THREE from 'three' ;
8- import { Controls , useControl } from '../src' ;
8+ import { Controls , ControlsProvider , useControl , BaseControl } from '../src' ;
99import fontFile from './resources/unknown' ;
10+ import { useEffect } from 'react' ;
1011
1112function Text ( { children, size = 1 , letterSpacing = 0.01 , color = '#000000' } ) {
12- const [ font ] = React . useState ( ( ) => new THREE . FontLoader ( ) . parse ( fontFile ) )
13+ const [ font ] = React . useState ( ( ) => new THREE . FontLoader ( ) . parse ( fontFile ) ) ;
1314 const [ shapes , [ x , y ] ] = React . useMemo ( ( ) => {
1415 let x = 0 ,
15- y = 0
16- let letters = [ ...children ]
17- let mat = new THREE . MeshBasicMaterial ( { color, opacity : 1 , transparent : true } )
16+ y = 0 ;
17+ let letters = [ ...children ] ;
18+ let mat = new THREE . MeshBasicMaterial ( {
19+ color,
20+ opacity : 1 ,
21+ transparent : true ,
22+ } ) ;
1823 return [
1924 letters . map ( letter => {
20- const geom = new THREE . ShapeGeometry ( font . generateShapes ( letter , size , 1 ) )
21- geom . computeBoundingBox ( )
22- const mesh = new THREE . Mesh ( geom , mat )
23- mesh . position . x = x
24- x += geom . boundingBox . max . x + letterSpacing
25- y = Math . max ( y , geom . boundingBox . max . y )
26- return mesh
25+ const geom = new THREE . ShapeGeometry ( font . generateShapes ( letter , size ) ) ;
26+ geom . computeBoundingBox ( ) ;
27+ const mesh = new THREE . Mesh ( geom , mat ) ;
28+ mesh . position . x = x ;
29+ x += geom . boundingBox ? .max ?. x ! + letterSpacing ;
30+ y = Math . max ( y , geom . boundingBox ? .max ?. y ! ) ;
31+ return mesh ;
2732 } ) ,
2833 [ x , y ] ,
29- ]
30- } , [ children ] )
34+ ] ;
35+ } , [ children ] ) ;
3136
3237 return (
3338 < group position = { [ - x / 2 , - y / 2 , 0 ] } >
3439 { shapes . map ( ( shape , index ) => (
3540 < primitive key = { index } object = { shape } />
3641 ) ) }
3742 </ group >
38- )
43+ ) ;
3944}
4045
4146const Next = ( ) => {
42- const rotationX = useControl ( 'Mega' , { group : 'Test' , type : 'number' , spring : true } ) ;
47+ const rotationX = useControl ( 'Mega' , {
48+ group : 'Test' ,
49+ type : 'number' ,
50+ spring : true ,
51+ } ) ;
4352 return (
4453 < a . mesh position = { [ 1.5 , 0 , 0 ] } rotation-x = { rotationX } >
4554 < boxGeometry attach = "geometry" args = { [ 1 , 1 , 1 ] } />
4655 < meshStandardMaterial attach = "material" />
4756 </ a . mesh >
48- )
57+ ) ;
4958} ;
5059
5160const Box = ( ) => {
52- const rotationX = useControl ( 'Rotate X' , { group : 'Basic' , type : 'number' , spring : true } ) ;
61+ const ref = React . useRef < THREE . Mesh > ( ) ;
62+
63+ const rotationX = useControl ( 'Rotate X' , {
64+ group : 'Basic' ,
65+ type : 'number' ,
66+ spring : true ,
67+ } ) ;
68+
5369 const rotationY = useControl ( 'Rotate Y' , {
5470 type : 'number' ,
5571 group : 'Basic' ,
@@ -62,6 +78,11 @@ const Box = () => {
6278 mass : 2 ,
6379 } ,
6480 } ) ;
81+ const bool = useControl ( 'Boolean' , {
82+ group : 'More' ,
83+ type : 'boolean' ,
84+ } ) ;
85+
6586 const color = useControl ( 'Material color' , {
6687 type : 'color' ,
6788 group : 'Basic' ,
@@ -72,14 +93,10 @@ const Box = () => {
7293 value : { x : 0 , y : 0 } ,
7394 distance : Math . PI ,
7495 } ) ;
75- const bool = useControl ( 'Allowed' , {
76- group : 'More' ,
77- type : 'boolean' ,
78- } ) ;
7996 const dropdown = useControl ( 'Pick one' , {
8097 group : 'More' ,
8198 type : 'select' ,
82- items : [ 'foo' , 'bar' , 'baz' ]
99+ items : [ 'foo' , 'bar' , 'baz' ] ,
83100 } ) ;
84101 const str = useControl ( 'Text' , {
85102 group : 'More' ,
@@ -91,27 +108,22 @@ const Box = () => {
91108 type : 'button' ,
92109 onClick ( ) {
93110 alert ( 'Hello world' ) ;
94- }
111+ } ,
95112 } ) ;
96113
97- const MyControl = ( { control, value } ) => (
98- < label > Test:
99- < input
100- type = "number"
101- onChange = { e => control . set ( e . currentTarget . value ) }
102- value = { value }
103- />
104- </ label >
105- ) ;
106-
107- const size = useControl ( 'Test' , {
114+ const texture = useControl ( 'Texture' , {
108115 group : 'More' ,
109- type : 'custom ' ,
110- value : 1 ,
111- component : MyControl
116+ type : 'file ' ,
117+ value : undefined ,
118+ loader : new THREE . TextureLoader ( ) ,
112119 } ) ;
113120
114- const ref = React . useRef < THREE . Mesh > ( ) ;
121+ useEffect ( ( ) => {
122+ if ( ref . current ) {
123+ ( ref . current . material as THREE . Material ) . needsUpdate = true ;
124+ }
125+ } , [ texture ] ) ;
126+
115127 return (
116128 < >
117129 < a . mesh
@@ -120,38 +132,48 @@ const Box = () => {
120132 rotation-x = { rotationX }
121133 rotation-y = { rotationY }
122134 >
123- < boxGeometry attach = "geometry" args = { [ size , size , size ] } />
124- < a . meshStandardMaterial attach = "material"
125- color = { color }
126- />
135+ < boxGeometry attach = "geometry" args = { [ 1 , 1 , 1 ] } />
136+ < a . meshPhongMaterial attach = "material" map = { texture } color = { color } />
127137 </ a . mesh >
128138 < Text > { str } </ Text >
129139 { dropdown === 'bar' && < Next /> }
130140 </ >
131- )
132- }
141+ ) ;
142+ } ;
133143
134144const Hello = ( ) => {
135- useControl ( '1' , { type : 'number' } ) ;
136- useControl ( '2' , { type : 'number' , max : 10 } ) ;
137- useControl ( '3' , { type : 'number' , min : - 5 , max : 5 , value : - 2.5 } ) ;
138- useControl ( '4' , { type : 'number' , min : 0 , max : 200 , value : 100 } ) ;
139- useControl ( '5' , { type : 'number' , scrub : true } ) ;
140- useControl ( '5' , { type : 'number' , scrub : true , distance : 1000 } ) ;
141- return ( < animated . div style = { { width : 100 , height : 100 , background : 'red' } } /> )
145+ const a1 = useControl ( '1' , { type : 'number' } ) ;
146+ const a2 = useControl ( '2' , { type : 'number' , max : 10 } ) ;
147+ const a3 = useControl ( '3' , { type : 'number' , min : - 5 , max : 5 , value : - 2.5 } ) ;
148+ const a4 = useControl ( '4' , { type : 'number' , min : 0 , max : 200 , value : 100 } ) ;
149+ const a5 = useControl ( '5' , { type : 'number' , scrub : true } ) ;
150+ const a6 = useControl ( '6' , { type : 'number' , scrub : true , distance : 1000 } ) ;
151+ return (
152+ < animated . div style = { { width : 180 , background : 'orange' , padding : 20 } } >
153+ < p > This is a div</ p >
154+ < div > 1: { a1 } </ div >
155+ < div > 2: { a2 } </ div >
156+ < div > 3: { a3 } </ div >
157+ < div > 4: { a4 } </ div >
158+ < div > 5: { a5 } </ div >
159+ < div > 6: { a6 } </ div >
160+ </ animated . div >
161+ ) ;
142162} ;
143163
144164const App = ( ) => {
145165 return (
146- < div >
166+ < ControlsProvider >
147167 < Canvas style = { { width : 800 , height : 600 } } >
148168 < ambientLight intensity = { 1 } />
149169 < pointLight position = { [ 0 , 2 , 2 ] } />
150- < Box />
170+ < React . Suspense fallback = { null } >
171+ < Box />
172+ </ React . Suspense >
151173 </ Canvas >
152- < Controls />
153174 < Hello />
154- </ div >
175+ < Controls />
176+ </ ControlsProvider >
155177 ) ;
156178} ;
157179
0 commit comments