@@ -3,8 +3,44 @@ import { adjustFromAndToForInflateAndStretch } from "../outliner/types/cube";
33import { compileJSON } from "../util/json" ;
44import { toSnakeCase } from "../util/util" ;
55
6+ export interface PreviewSceneOptions {
7+ name ?: string
8+ description ?: string
9+ category ?: string
10+ web_config ?: string
11+ require_minecraft_eula ?: boolean
12+ light_color ?: { r : number , g : number , b : number }
13+ light_side ?: number
14+ condition ?: ConditionResolvable
15+ cubemap ?: string [ ]
16+ fog ?: {
17+ type : 'linear' | 'exponential'
18+ color
19+ near ?: number
20+ far ?: number
21+ density ?: number
22+ }
23+ fov ?: number
24+ preview_models ?: ( string | PreviewModel | PreviewModelOptions ) [ ]
25+ }
26+
627export class PreviewScene {
7- constructor ( id , data = 0 ) {
28+ id : string
29+ loaded : boolean = false ;
30+ require_minecraft_eula : boolean = false ;
31+ name : string ;
32+ description ?: string ;
33+ category : string ;
34+ light_color : { r : number , g : number , b : number } = { r : 1 , g : 1 , b : 1 } ;
35+ light_side : number = 0 ;
36+ condition : ConditionResolvable ;
37+ fov : number = null ;
38+ web_config_path ?: string
39+ fog ?: THREE . Fog | THREE . FogExp2
40+ cubemap ?: THREE . CubeTexture
41+ preview_models = [ ] ;
42+
43+ constructor ( id : string , data : PreviewSceneOptions = { } ) {
844 PreviewScene . scenes [ id ] = this ;
945 this . id = id ;
1046 this . loaded = false ;
@@ -24,7 +60,7 @@ export class PreviewScene {
2460
2561 PreviewScene . menu_categories [ this . category ] [ id ] = this . name ;
2662 }
27- extend ( data ) {
63+ extend ( data : PreviewSceneOptions ) {
2864 this . loaded = data . web_config ? false : true ;
2965 this . web_config_path = data . web_config ;
3066 if ( data . require_minecraft_eula ) this . require_minecraft_eula = true ;
@@ -47,6 +83,7 @@ export class PreviewScene {
4783 Canvas . updateShading ( ) ;
4884 }
4985 } ) ;
86+ // @ts -expect-error
5087 texture_cube . colorSpace = THREE . SRGBColorSpace ;
5188 texture_cube . mapping = THREE . CubeRefractionMapping ;
5289 this . cubemap = texture_cube ;
@@ -99,6 +136,9 @@ export class PreviewScene {
99136 }
100137 this . extend ( json ) ;
101138 }
139+ /**
140+ * Selects this preview scene
141+ */
102142 async select ( ) {
103143 if ( this . require_minecraft_eula ) {
104144 let accepted = await MinecraftEULA . promptUser ( 'preview_scenes' ) ;
@@ -109,7 +149,7 @@ export class PreviewScene {
109149 }
110150 if ( PreviewScene . active ) PreviewScene . active . unselect ( ) ;
111151
112- Canvas . global_light_color . copy ( this . light_color ) ;
152+ Canvas . global_light_color . copy ( this . light_color as THREE . Color ) ;
113153 Canvas . global_light_side = this . light_side ;
114154 Canvas . scene . background = this . cubemap ;
115155 Canvas . scene . fog = this . fog ;
@@ -128,6 +168,9 @@ export class PreviewScene {
128168 Blockbench . dispatchEvent ( 'select_preview_scene' , { scene : this } ) ;
129169 Canvas . updateShading ( ) ;
130170 }
171+ /**
172+ * Unselects this preview scene
173+ */
131174 unselect ( ) {
132175 this . preview_models . forEach ( model => {
133176 model . disable ( ) ;
@@ -138,7 +181,7 @@ export class PreviewScene {
138181 if ( this . cubemap ) scene . background = null ;
139182 if ( this . fog ) scene . fog = null ;
140183 if ( this . fov && ! ( Modes . display && DisplayMode . display_slot . startsWith ( 'firstperson' ) ) ) {
141- Preview . all . forEach ( preview => preview . setFOV ( settings . fov . value ) ) ;
184+ Preview . all . forEach ( preview => preview . setFOV ( settings . fov . value as number ) ) ;
142185 }
143186 Blockbench . dispatchEvent ( 'unselect_preview_scene' , { scene : this } ) ;
144187 Canvas . updateShading ( ) ;
@@ -148,28 +191,109 @@ export class PreviewScene {
148191 delete PreviewScene . scenes [ this . id ] ;
149192 delete PreviewScene . menu_categories [ this . category ] [ this . id ] ;
150193 }
194+
195+ /**
196+ * All preview scenes, listed by ID
197+ */
198+ static scenes : Record < string , PreviewScene > = { } ;
199+ /**
200+ * The currently active scene
201+ */
202+ static active : PreviewScene | null = null ;
203+ static select_options = { } ;
204+ /**
205+ * The URL to the source repository that scenes are pulled from
206+ */
207+ static source_repository = 'https://cdn.jsdelivr.net/gh/JannisX11/blockbench-scenes' ;
208+ static menu_categories : {
209+ [ category_id : string ] : {
210+ [ id : string ] : string
211+ }
212+ } = {
213+ main : {
214+ none : tl ( 'generic.none' )
215+ } ,
216+ generic : {
217+ _label : 'Generic'
218+ } ,
219+ realistic : {
220+ _label : 'Realistic'
221+ } ,
222+ minecraft : {
223+ _label : 'Minecraft'
224+ } ,
225+ } ;
226+
151227}
152- PreviewScene . scenes = { } ;
153- PreviewScene . active = null ;
154- PreviewScene . select_options = { } ;
155- PreviewScene . source_repository = 'https://cdn.jsdelivr.net/gh/JannisX11/blockbench-scenes' ;
156- PreviewScene . menu_categories = {
157- main : {
158- none : tl ( 'generic.none' )
159- } ,
160- generic : {
161- _label : 'Generic'
162- } ,
163- realistic : {
164- _label : 'Realistic'
165- } ,
166- minecraft : {
167- _label : 'Minecraft'
168- } ,
169- } ;
170228
171- export class PreviewModel {
172- constructor ( id , data ) {
229+ interface PreviewModelCubeTemplate {
230+ prefab ?: string
231+ offset ?: ArrayVector3
232+ offset_space ?: 'block' | 'pixel'
233+ position ?: ArrayVector3
234+ size ?: ArrayVector3
235+ origin ?: ArrayVector3
236+ rotation ?: ArrayVector3
237+ faces ?: {
238+ north ?: { uv : ArrayVector4 }
239+ east ?: { uv : ArrayVector4 }
240+ west ?: { uv : ArrayVector4 }
241+ south ?: { uv : ArrayVector4 }
242+ up ?: { uv : ArrayVector4 }
243+ down ?: { uv : ArrayVector4 }
244+ }
245+ }
246+ type PrefabTemplate = PreviewModelCubeTemplate
247+ export interface PreviewModelOptions {
248+ id ?: string
249+ condition ?: ConditionResolvable
250+ cubes ?: PreviewModelCubeTemplate [ ]
251+ prefabs ?: Record < string , PrefabTemplate >
252+ /**
253+ * Source of the model's texture
254+ */
255+ texture ?: string
256+ /**
257+ * Model tint color
258+ */
259+ color ?: string
260+ /**
261+ * Enable shading on the material
262+ */
263+ shading ?: boolean
264+ /**
265+ * THREE.JS material render side
266+ */
267+ render_side ?: number
268+ texture_size ?: [ number , number ]
269+ position ?: ArrayVector3
270+ rotation ?: ArrayVector3
271+ scale ?: ArrayVector3
272+ onUpdate ?( ) : void
273+ }
274+ export class PreviewModel implements Deletable {
275+ id : string
276+ condition : ConditionResolvable
277+ model_3d : THREE . Object3D
278+ onUpdate ?: ( ) => void
279+ enabled : boolean = false ;
280+ build_data : {
281+ prefabs ?: Record < string , PrefabTemplate > ,
282+ cubes ?: PreviewModelCubeTemplate [ ] ,
283+ texture ?: string
284+ position ?: ArrayVector3
285+ rotation ?: ArrayVector3
286+ scale ?: ArrayVector3
287+ }
288+ color : string
289+ shading : boolean
290+ render_side : THREE . Side
291+ texture_size : ArrayVector2
292+ cubes : PreviewModelCubeTemplate [ ]
293+ texture ?: string
294+ [ idkey : string ] : any
295+
296+ constructor ( id : string , data : PreviewModelOptions ) {
173297 PreviewModel . models [ id ] = this ;
174298 this . id = id ;
175299 this . condition = data . condition ;
@@ -192,15 +316,24 @@ export class PreviewModel {
192316
193317 this . buildModel ( ) ;
194318 }
319+ /**
320+ * Enables the model in the preview
321+ */
195322 enable ( ) {
196323 Canvas . scene . add ( this . model_3d ) ;
197324 this . enabled = true ;
198325 this . update ( ) ;
199326 }
327+ /**
328+ * Disables the model in the preview
329+ */
200330 disable ( ) {
201331 Canvas . scene . remove ( this . model_3d ) ;
202332 this . enabled = false ;
203333 }
334+ /**
335+ * Update the appearance and visibility of the model
336+ */
204337 update ( ) {
205338 if ( typeof this . onUpdate == 'function' ) {
206339 this . onUpdate ( ) ;
@@ -217,7 +350,7 @@ export class PreviewModel {
217350 this . model_3d . visible = ! ! Condition ( this . condition ) ;
218351 }
219352 buildModel ( ) {
220- let tex ;
353+ let tex : THREE . Texture = undefined ;
221354 if ( this . build_data . texture ) {
222355 let img = new Image ( ) ;
223356 img . src = this . build_data . texture ;
@@ -262,6 +395,7 @@ export class PreviewModel {
262395 }
263396 mesh . geometry . translate ( cube . position [ 0 ] + cube . size [ 0 ] / 2 , cube . position [ 1 ] + cube . size [ 1 ] / 2 , cube . position [ 2 ] + cube . size [ 2 ] / 2 )
264397 if ( cube . rotation ) {
398+ // @ts -expect-error
265399 mesh . rotation . setFromDegreeArray ( cube . rotation )
266400 }
267401
@@ -285,11 +419,13 @@ export class PreviewModel {
285419 }
286420
287421 let indices = [ ] ;
422+ // @ts -expect-error
288423 mesh . geometry . faces = [ ] ;
289424 mesh . geometry . clearGroups ( ) ;
290425 Canvas . face_order . forEach ( ( fkey , i ) => {
291426 if ( cube . faces [ fkey ] ) {
292427 indices . push ( 0 + i * 4 , 2 + i * 4 , 1 + i * 4 , 2 + i * 4 , 3 + i * 4 , 1 + i * 4 ) ;
428+ // @ts -expect-error
293429 mesh . geometry . faces . push ( fkey )
294430 }
295431 } )
@@ -306,11 +442,12 @@ export class PreviewModel {
306442 case 'up' : fIndex = 4 ; break ;
307443 case 'down' : fIndex = 6 ; break ;
308444 }
309- mesh . geometry . attributes . uv . array . set ( uv_array [ 0 ] , fIndex * 4 + 0 ) ; //0,1
310- mesh . geometry . attributes . uv . array . set ( uv_array [ 1 ] , fIndex * 4 + 2 ) ; //1,1
311- mesh . geometry . attributes . uv . array . set ( uv_array [ 2 ] , fIndex * 4 + 4 ) ; //0,0
312- mesh . geometry . attributes . uv . array . set ( uv_array [ 3 ] , fIndex * 4 + 6 ) ; //1,0
313- mesh . geometry . attributes . uv . needsUpdate = true ;
445+ let uv_attr = mesh . geometry . attributes . uv ;
446+ ( uv_attr . array as any ) . set ( uv_array [ 0 ] , fIndex * 4 + 0 ) ; //0,1
447+ ( uv_attr . array as any ) . set ( uv_array [ 1 ] , fIndex * 4 + 2 ) ; //1,1
448+ ( uv_attr . array as any ) . set ( uv_array [ 2 ] , fIndex * 4 + 4 ) ; //0,0
449+ ( uv_attr . array as any ) . set ( uv_array [ 3 ] , fIndex * 4 + 6 ) ; //1,0
450+ uv_attr . needsUpdate = true ;
314451 }
315452
316453 this . model_3d . add ( mesh ) ;
@@ -323,8 +460,8 @@ export class PreviewModel {
323460
324461 static generateModelFromProject ( ) {
325462 let cubes = Cube . all . map ( cube => {
326- let from = cube . from . slice ( ) ;
327- let to = cube . to . slice ( ) ;
463+ let from = cube . from . slice ( ) as ArrayVector3 ;
464+ let to = cube . to . slice ( ) as ArrayVector3 ;
328465 adjustFromAndToForInflateAndStretch ( from , to , cube ) ;
329466 let data = {
330467 "position" : from ,
@@ -356,17 +493,17 @@ export class PreviewModel {
356493 cubes
357494 } ) ;
358495 }
359- }
360- PreviewModel . models = { } ;
361- PreviewModel . getActiveModels = function ( ) {
362- let list = [ ] ;
363- for ( let id in PreviewModel . models ) {
364- let model = PreviewModel . models [ id ] ;
365- if ( model . enabled ) {
366- list . push ( model ) ;
496+ static models : Record < string , PreviewModel > = { } ;
497+ static getActiveModels = function ( ) : PreviewModel [ ] {
498+ let list = [ ] ;
499+ for ( let id in PreviewModel . models ) {
500+ let model = PreviewModel . models [ id ] ;
501+ if ( model . enabled ) {
502+ list . push ( model ) ;
503+ }
367504 }
505+ return list ;
368506 }
369- return list ;
370507}
371508
372509new PreviewModel ( 'studio' , {
@@ -767,10 +904,10 @@ player_preview_model.updateArmVariant = function(slim) {
767904
768905StateMemory . init ( 'minecraft_eula_accepted' , 'object' ) ;
769906export const MinecraftEULA = {
770- isAccepted ( key ) {
907+ isAccepted ( key : string ) {
771908 return StateMemory . minecraft_eula_accepted [ key ] ;
772909 } ,
773- async promptUser ( key ) {
910+ async promptUser ( key : string ) {
774911 if ( MinecraftEULA . isAccepted ( key ) ) {
775912 return true ;
776913 }
@@ -802,7 +939,7 @@ BARS.defineActions(function() {
802939 category : 'view' ,
803940 icon : 'nature_people' ,
804941 click ( event ) {
805- new Menu ( this . children ) . show ( event . target ) ;
942+ new Menu ( this . children ) . show ( event . target as HTMLElement ) ;
806943 } ,
807944 children : ( ) => {
808945 let list = [ ] ;
@@ -846,9 +983,18 @@ BARS.defineActions(function() {
846983 } )
847984} )
848985
849- Object . assign ( window , {
986+ const global = {
850987 PreviewScene,
851988 PreviewModel,
852989 MinecraftEULA,
853990 player_preview_model
854- } )
991+ } ;
992+ declare global {
993+ type PreviewScene = import ( './preview_scenes' ) . PreviewScene
994+ const PreviewScene : typeof global . PreviewScene
995+ type PreviewModel = import ( './preview_scenes' ) . PreviewModel
996+ const PreviewModel : typeof global . PreviewModel
997+ const MinecraftEULA : typeof global . MinecraftEULA
998+ const player_preview_model : PreviewModel
999+ }
1000+ Object . assign ( window , global ) ;
0 commit comments