@lightningjs/blits 1.48.0 → 2.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,6 +32,47 @@ export default () =>
32
32
  code: {
33
33
  render: function anonymous(parent, component, context, components, effect, getRaw, Log) {
34
34
  const elms = []
35
+ const validAttributes = [
36
+ 'parent',
37
+ 'rotation',
38
+ 'w',
39
+ 'width',
40
+ 'h',
41
+ 'height',
42
+ 'x',
43
+ 'y',
44
+ 'z',
45
+ 'zIndex',
46
+ 'color',
47
+ 'src',
48
+ 'texture',
49
+ 'fit',
50
+ 'rtt',
51
+ 'mount',
52
+ 'pivot',
53
+ 'scale',
54
+ 'show',
55
+ 'alpha',
56
+ 'rounded',
57
+ 'border',
58
+ 'shadow',
59
+ 'shader',
60
+ 'clipping',
61
+ 'overflow',
62
+ 'font',
63
+ 'size',
64
+ 'maxwidth',
65
+ 'maxheight',
66
+ 'maxlines',
67
+ 'textoverflow',
68
+ 'letterspacing',
69
+ 'lineheight',
70
+ 'contain',
71
+ 'align',
72
+ 'content',
73
+ 'placement',
74
+ 'inspector-data',
75
+ ]
35
76
  const elementConfigs = []
36
77
  const forloops = []
37
78
  const props = []
@@ -53,8 +94,8 @@ export default () =>
53
94
  inSlot === true ? slotComponent : component
54
95
  )
55
96
 
56
- elementConfigs[0]['w'] = parent.node.width * (100 / 100)
57
- elementConfigs[0]['height'] = parent.node.height * (100 / 100)
97
+ elementConfigs[0]['w'] = parent.node.w * (100 / 100)
98
+ elementConfigs[0]['height'] = parent.node.h * (100 / 100)
58
99
  elms[0].populate(elementConfigs[0])
59
100
 
60
101
  if (inSlot === true) {
@@ -77,6 +118,7 @@ export default () =>
77
118
  props.length = 0
78
119
  skips.length = 0
79
120
  },
121
+ skips,
80
122
  }
81
123
  },
82
124
  effects: [],
@@ -89,9 +131,11 @@ export default () =>
89
131
  },
90
132
  hooks: {
91
133
  async ready() {
92
- if (this.parent[symbols.routerHooks] && this.parent[symbols.routerHooks].init) {
93
- await this.parent[symbols.routerHooks].init.apply(this.parent)
134
+ const parent = this[symbols.parent]
135
+ if (parent && parent[symbols.routerHooks] && parent[symbols.routerHooks].init) {
136
+ await parent[symbols.routerHooks].init.apply(parent)
94
137
  }
138
+
95
139
  hashchangeHandler = () => Router.navigate.apply(this)
96
140
  Router.navigate.apply(this)
97
141
  window.addEventListener('hashchange', hashchangeHandler)
@@ -107,13 +151,20 @@ export default () =>
107
151
  },
108
152
  input: {
109
153
  back(e) {
154
+ const parent = this[symbols.parent]
155
+
110
156
  if (routerState.backNavigation === false) {
111
- this.parent.$input(e)
157
+ if (parent && parent.$input) {
158
+ parent.$input(e)
159
+ }
112
160
  return
113
161
  }
162
+
114
163
  const navigating = Router.back.call(this)
115
164
  if (navigating === false) {
116
- this.parent.$focus(e)
165
+ if (parent && parent.$focus) {
166
+ parent.$focus(e)
167
+ }
117
168
  }
118
169
  },
119
170
  },
@@ -25,6 +25,47 @@ export default () =>
25
25
  code: {
26
26
  render: function anonymous(parent, component, context, components, effect, getRaw, Log) {
27
27
  const elms = []
28
+ const validAttributes = [
29
+ 'parent',
30
+ 'rotation',
31
+ 'w',
32
+ 'width',
33
+ 'h',
34
+ 'height',
35
+ 'x',
36
+ 'y',
37
+ 'z',
38
+ 'zIndex',
39
+ 'color',
40
+ 'src',
41
+ 'texture',
42
+ 'fit',
43
+ 'rtt',
44
+ 'mount',
45
+ 'pivot',
46
+ 'scale',
47
+ 'show',
48
+ 'alpha',
49
+ 'rounded',
50
+ 'border',
51
+ 'shadow',
52
+ 'shader',
53
+ 'clipping',
54
+ 'overflow',
55
+ 'font',
56
+ 'size',
57
+ 'maxwidth',
58
+ 'maxheight',
59
+ 'maxlines',
60
+ 'textoverflow',
61
+ 'letterspacing',
62
+ 'lineheight',
63
+ 'contain',
64
+ 'align',
65
+ 'content',
66
+ 'placement',
67
+ 'inspector-data',
68
+ ]
28
69
  const elementConfigs = []
29
70
  const forloops = []
30
71
  const props = []
@@ -46,8 +87,8 @@ export default () =>
46
87
  inSlot === true ? slotComponent : component
47
88
  )
48
89
 
49
- elementConfigs[0]['w'] = parent.node.width * (100 / 100)
50
- elementConfigs[0]['h'] = parent.node.height * (100 / 100)
90
+ elementConfigs[0]['w'] = parent.node.w * (100 / 100)
91
+ elementConfigs[0]['h'] = parent.node.h * (100 / 100)
51
92
  elementConfigs[0]['texture'] = component.texture
52
93
  elementConfigs[0]['color'] = component.color
53
94
  elementConfigs[0]['effects'] = component.effects
@@ -73,20 +114,25 @@ export default () =>
73
114
  props.length = 0
74
115
  skips.length = 0
75
116
  },
117
+ skips,
76
118
  }
77
119
  },
78
120
  effects: [
79
- function anonymous(component, elms, context, components, rootComponent, effect) {
121
+ function anonymous(component, elms, context, components, rootComponent, skips, effect) {
80
122
  elms[0].set('texture', component.texture)
81
123
  },
82
- function anonymous(component, elms, context, components, rootComponent, effect) {
124
+ function anonymous(component, elms, context, components, rootComponent, skips, effect) {
83
125
  elms[0].set('color', component.color)
84
126
  },
85
127
  ],
86
128
  context: {},
87
129
  },
88
- props: ['image', 'map', 'frame', 'color', 'effects'],
89
-
130
+ props: {
131
+ image: undefined,
132
+ map: undefined,
133
+ frame: undefined,
134
+ color: undefined,
135
+ },
90
136
  state() {
91
137
  return {
92
138
  spriteTexture: null,
@@ -149,8 +195,8 @@ export default () =>
149
195
  texture: this.spriteTexture,
150
196
  x: options.x,
151
197
  y: options.y,
152
- width: options.w,
153
- height: options.h,
198
+ w: options.w,
199
+ h: options.h,
154
200
  })
155
201
  }
156
202
 
@@ -16,11 +16,13 @@
16
16
  */
17
17
 
18
18
  import { renderer } from './launch.js'
19
+ import { parseToObject, isObjectString, isArrayString, isTransition } from '../../lib/utils.js'
19
20
  import colors from '../../lib/colors/colors.js'
20
21
 
21
22
  import { Log } from '../../lib/log.js'
22
23
  import symbols from '../../lib/symbols.js'
23
24
  import Settings from '../../settings.js'
25
+ import shaders from '../../lib/shaders/shaders.js'
24
26
 
25
27
  /**
26
28
  * Creates a padding object from a value and direction.
@@ -79,8 +81,8 @@ const layoutFn = function (config) {
79
81
  const position = config.direction === 'vertical' ? 'y' : 'x'
80
82
  const oppositePosition = config.direction === 'vertical' ? 'x' : 'y'
81
83
  const oppositeMount = config.direction === 'vertical' ? 'mountX' : 'mountY'
82
- const dimension = config.direction === 'vertical' ? 'height' : 'width'
83
- const oppositeDimension = config.direction === 'vertical' ? 'width' : 'height'
84
+ const dimension = config.direction === 'vertical' ? 'h' : 'w'
85
+ const oppositeDimension = config.direction === 'vertical' ? 'w' : 'h'
84
86
  const padding = createPaddingObject(config.padding, config.direction)
85
87
 
86
88
  let offset = padding.start
@@ -98,17 +100,10 @@ const layoutFn = function (config) {
98
100
  node[position] = offset
99
101
  node[oppositePosition] = padding.oppositeStart
100
102
  // todo: temporary text check, due to 1px width of empty text node
101
- if (dimension === 'width') {
102
- offset += node.width + (node.width !== ('text' in node ? 1 : 0) ? gap : 0)
103
+ if (dimension === 'w') {
104
+ offset += node.w + (node.w !== ('text' in node ? 1 : 0) ? gap : 0)
103
105
  } else {
104
- offset +=
105
- 'text' in node
106
- ? node.width > 1
107
- ? node.height + gap
108
- : 0
109
- : node.height !== 0
110
- ? node.height + gap
111
- : 0
106
+ offset += 'text' in node ? (node.w > 1 ? node.h + gap : 0) : node.h !== 0 ? node.h + gap : 0
112
107
  }
113
108
  otherDimension = Math.max(
114
109
  otherDimension,
@@ -135,7 +130,7 @@ const layoutFn = function (config) {
135
130
 
136
131
  // emit an updated event
137
132
  if (config['@updated'] !== undefined) {
138
- config['@updated']({ w: this.node.width, h: this.node.height }, this)
133
+ config['@updated']({ w: this.node.w, h: this.node.h }, this)
139
134
  }
140
135
 
141
136
  // trigger layout on parent if parent is a layout
@@ -144,33 +139,6 @@ const layoutFn = function (config) {
144
139
  }
145
140
  }
146
141
 
147
- /**
148
- * Checks if a value is a transition object.
149
- * @param {any} value - The value to check.
150
- * @returns {boolean} True if the value is a transition object, false otherwise.
151
- */
152
- const isTransition = (value) => {
153
- return value !== null && typeof value === 'object' && 'transition' in value === true
154
- }
155
-
156
- /**
157
- * Checks if a string is an object string (starts and ends with curly braces).
158
- * @param {string} str - The string to check.
159
- * @returns {boolean} True if the string is an object string, false otherwise.
160
- */
161
- const isObjectString = (str) => {
162
- return typeof str === 'string' && str.startsWith('{') && str.endsWith('}')
163
- }
164
-
165
- /**
166
- * Parses a string into an object, converting single quotes to double and adding quotes to keys.
167
- * @param {string} str - The string to parse.
168
- * @returns {object} The parsed object.
169
- */
170
- const parseToObject = (str) => {
171
- return JSON.parse(str.replace(/'/g, '"').replace(/([{,]\s*)([\w-_]+)(\s*:)/g, '$1"$2"$3'))
172
- }
173
-
174
142
  /**
175
143
  * Parses a percentage string or returns the value as-is.
176
144
  * @param {string|number} v - The value to parse (may be a percentage string).
@@ -242,36 +210,38 @@ const propsTransformer = {
242
210
  this.props['rotation'] = v * (Math.PI / 180)
243
211
  },
244
212
  set w(v) {
245
- this.props['width'] = parsePercentage.call(this, v, 'width')
213
+ const parsed = parsePercentage.call(this, v, 'w')
214
+ this.props['w'] = parsed
246
215
  if (
247
216
  this.___wrapper === true &&
248
217
  this.element.component.eol !== true &&
249
218
  this.element.component[symbols.holder] !== undefined
250
219
  ) {
251
- this.element.component[symbols.holder].set('w', this.props['width'])
220
+ this.element.component[symbols.holder].set('w', parsed)
252
221
  }
253
222
  },
254
223
  set width(v) {
255
224
  this.w = v
256
225
  },
257
226
  set h(v) {
258
- this.props['height'] = parsePercentage.call(this, v, 'height')
227
+ const parsed = parsePercentage.call(this, v, 'h')
228
+ this.props['h'] = parsed
259
229
  if (
260
230
  this.___wrapper === true &&
261
231
  this.element.component.eol !== true &&
262
232
  this.element.component[symbols.holder] !== undefined
263
233
  ) {
264
- this.element.component[symbols.holder].set('h', this.props['height'])
234
+ this.element.component[symbols.holder].set('h', parsed)
265
235
  }
266
236
  },
267
237
  set height(v) {
268
238
  this.h = v
269
239
  },
270
240
  set x(v) {
271
- this.props['x'] = parsePercentage.call(this, v, 'width')
241
+ this.props['x'] = parsePercentage.call(this, v, 'w')
272
242
  },
273
243
  set y(v) {
274
- this.props['y'] = parsePercentage.call(this, v, 'height')
244
+ this.props['y'] = parsePercentage.call(this, v, 'h')
275
245
  },
276
246
  set z(v) {
277
247
  this.props['zIndex'] = v
@@ -301,7 +271,7 @@ const propsTransformer = {
301
271
  this.props['color'] = this.props['src'] ? 0xffffffff : 0x00000000
302
272
  }
303
273
  // apply auto sizing when no width or height specified
304
- if (!('w' in this.raw) && !('w' in this.raw) && !('h' in this.raw) && !('height' in this.raw)) {
274
+ if (!('w' in this.raw) && !('h' in this.raw)) {
305
275
  this.props['autosize'] = true
306
276
  }
307
277
  },
@@ -393,37 +363,68 @@ const propsTransformer = {
393
363
  this.props['alpha'] = v
394
364
  }
395
365
  },
366
+ set rounded(v) {
367
+ this.props['rounded'] = v
368
+ if (this.element.node !== undefined && this.elementShader === true) {
369
+ if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
370
+ this.element.node.props['shader'].props = v
371
+ } else {
372
+ if (isArrayString(v) === true) {
373
+ v = JSON.parse(v)
374
+ }
375
+ this.element.node.props['shader'].props.radius = v
376
+ }
377
+ }
378
+ },
379
+ set border(v) {
380
+ this.props['border'] = v
381
+ if (
382
+ this.element.node !== undefined &&
383
+ this.elementShader === true &&
384
+ (typeof v === 'object' || isObjectString(v) === true)
385
+ ) {
386
+ v = shaders.parseProps(v)
387
+ for (const key in v) {
388
+ this.element.node.props['shader'].props[`border-${key}`] = v[key]
389
+ }
390
+ }
391
+ },
392
+ set shadow(v) {
393
+ this.props['shadow'] = v
394
+ if (
395
+ this.element.node !== undefined &&
396
+ this.elementShader === true &&
397
+ (typeof v === 'object' || isObjectString(v) === true)
398
+ ) {
399
+ v = shaders.parseProps(v)
400
+ for (const key in v) {
401
+ this.element.node.props['shader'].props[`shadow-${key}`] = v[key]
402
+ }
403
+ }
404
+ },
396
405
  set shader(v) {
406
+ let type = v
407
+ if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
408
+ type = v.type
409
+ v = shaders.parseProps(v)
410
+ }
397
411
  const target = this.element.node !== undefined ? this.element.node : this.props
398
-
399
- if (v === null) {
400
- target['shader'] = null
412
+ //if v remains a string we can change shader types
413
+ if (typeof v === 'string') {
414
+ target['shader'] = renderer.createShader(type)
401
415
  return
402
416
  }
403
417
 
404
- if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
405
- if (target.shader !== undefined && target.shader.type === v.type) {
406
- for (const prop in v.props) {
407
- target.shader.props[prop] = v.props[prop]
408
- }
418
+ //check again if v is an object since it could have been an object string
419
+ if (typeof v === 'object') {
420
+ if (target.shader !== undefined && type === target.shader.shaderKey) {
421
+ target['shader'].props = v
409
422
  return
410
423
  }
411
- target['shader'] = renderer.createShader(v.type, v.props)
412
- }
413
- },
414
- set effects(v) {
415
- for (let i = 0; i < v.length; i++) {
416
- if (v[i].props && v[i].props.color) {
417
- v[i].props.color = colors.normalize(v[i].props.color)
418
- }
419
- }
420
- if (this.element.node === undefined) {
421
- this.props['shader'] = renderer.createShader('DynamicShader', {
422
- effects: v.map((effect) => {
423
- return renderer.createEffect(effect.type, effect.props)
424
- }),
425
- })
424
+ target['shader'] = renderer.createShader(type, v)
425
+ return
426
426
  }
427
+ target['shader'] = renderer.createShader('DefaultShader')
427
428
  },
428
429
  set clipping(v) {
429
430
  this.props['clipping'] = v
@@ -437,21 +438,27 @@ const propsTransformer = {
437
438
  set size(v) {
438
439
  this.props['fontSize'] = v
439
440
  },
440
- set wordwrap(v) {
441
- Log.warn('The wordwrap attribute is deprecated, use maxwidth instead')
442
- this.props['width'] = v
443
- this.props['contain'] = 'width'
444
- },
445
441
  set maxwidth(v) {
446
- this.props['width'] = v
442
+ this.props['maxWidth'] = v
443
+ if (this.manualTextContain === true) {
444
+ return
445
+ }
446
+ if (this.props['contain'] === 'height') {
447
+ this.props['contain'] = 'both'
448
+ return
449
+ }
447
450
  this.props['contain'] = 'width'
448
451
  },
449
452
  set maxheight(v) {
450
- this.props['height'] = v
451
- this.props['contain'] = 'both'
452
- },
453
- set contain(v) {
454
- this.props['contain'] = v
453
+ this.props['maxHeight'] = v
454
+ if (this.manualTextContain === true) {
455
+ return
456
+ }
457
+ if (this.props['contain'] === 'width') {
458
+ this.props['contain'] = 'both'
459
+ return
460
+ }
461
+ this.props['contain'] = 'height'
455
462
  },
456
463
  set maxlines(v) {
457
464
  this.props['maxLines'] = v
@@ -465,6 +472,10 @@ const propsTransformer = {
465
472
  set lineheight(v) {
466
473
  this.props['lineHeight'] = v
467
474
  },
475
+ set contain(v) {
476
+ this.props['contain'] = v
477
+ this.manualTextContain = true
478
+ },
468
479
  set align(v) {
469
480
  this.props['textAlign'] = v
470
481
  },
@@ -514,13 +525,14 @@ const propsTransformer = {
514
525
  },
515
526
  }
516
527
 
528
+ export const elementAttributes = Object.keys(propsTransformer)
529
+
517
530
  const Element = {
518
531
  /**
519
532
  * Populates the element with data
520
- * @param {import('../../component.js').BlitsElementProps} data
533
+ * @param {import('../../component.js').BlitsElementProps} props
521
534
  */
522
- populate(data) {
523
- const props = data
535
+ populate(props) {
524
536
  props['node'] = this.config.node
525
537
 
526
538
  if (props[symbols.isSlot] === true) {
@@ -533,11 +545,22 @@ const Element = {
533
545
  //@ts-ignore This might be a left over from the old code?
534
546
  delete props.parent
535
547
 
536
- this.props.raw = data
548
+ this.props.raw = props
549
+ this.props.elementShader = false
537
550
 
538
551
  const propKeys = Object.keys(props)
539
552
  const length = propKeys.length
540
553
 
554
+ if (
555
+ props['shader'] === undefined &&
556
+ (props['rounded'] !== undefined ||
557
+ props['border'] !== undefined ||
558
+ props['shadow'] !== undefined)
559
+ ) {
560
+ this.props.elementShader = true
561
+ this.props.props['shader'] = shaders.createElementShader(props)
562
+ }
563
+
541
564
  for (let i = 0; i < length; i++) {
542
565
  const key = propKeys[i]
543
566
  const value = props[key]
@@ -557,7 +580,7 @@ const Element = {
557
580
 
558
581
  if (props['@loaded'] !== undefined && typeof props['@loaded'] === 'function') {
559
582
  this.node.on('loaded', (el, { type, dimensions }) => {
560
- props['@loaded']({ w: dimensions.width, h: dimensions.height, type }, this)
583
+ props['@loaded']({ w: dimensions.w, h: dimensions.h, type }, this)
561
584
  })
562
585
  }
563
586
 
@@ -1,38 +1,33 @@
1
- import { SdfTrFontFace, WebTrFontFace } from '@lightningjs/renderer'
2
1
  import Settings from '../../settings.js'
3
2
  import { renderer } from './launch.js'
4
3
 
4
+ const fontTypeMapping = {
5
+ sdf: 'sdf',
6
+ msdf: 'sdf',
7
+ canvas: 'canvas',
8
+ web: 'canvas',
9
+ }
10
+
5
11
  export default () => {
6
12
  const stage = renderer.stage
7
- Settings.get('fonts', []).forEach((font) => {
8
- if (font.type === 'sdf' || font.type === 'msdf') {
9
- // automatically map png key to file name
10
- if (!font.png && font.file) {
11
- font.png = font.file.replace(/\.[^.]+$/, `.${font.type}.png`)
12
- }
13
- // automatically map json to file name
14
- if (!font.json && font.file) {
15
- font.json = font.file.replace(/\.[^.]+$/, `.${font.type}.json`)
16
- }
17
- stage.fontManager.addFontFace(
18
- new SdfTrFontFace(font.type, {
19
- fontFamily: font.family,
20
- descriptors: {},
21
- atlasUrl: font.png,
22
- atlasDataUrl: font.json,
23
- stage,
24
- metrics: font.metrics,
25
- })
26
- )
27
- } else if (font.type === 'web') {
28
- stage.fontManager.addFontFace(
29
- new WebTrFontFace({
30
- fontFamily: font.family,
31
- fontUrl: font.file,
32
- descriptors: {},
33
- metrics: font.metrics,
34
- })
35
- )
13
+
14
+ const fonts = Settings.get('fonts', [])
15
+ for (let i = 0; i < fonts.length; i++) {
16
+ const font = fonts[i]
17
+ const type = fontTypeMapping[font.type] || 'sdf'
18
+
19
+ if (type === 'sdf') {
20
+ stage.loadFont('sdf', {
21
+ fontFamily: font.family,
22
+ atlasUrl: font.json || (font.file && font.file.replace(/\.[^.]+$/, `.${font.type}.png`)),
23
+ atlasDataUrl:
24
+ font.json || (font.file && font.file.replace(/\.[^.]+$/, `.${font.type}.json`)),
25
+ })
26
+ } else {
27
+ stage.loadFont('canvas', {
28
+ fontFamily: font.family,
29
+ fontUrl: font.file,
30
+ })
36
31
  }
37
- })
32
+ }
38
33
  }
@@ -1,12 +1,62 @@
1
1
  import Settings from '../../settings.js'
2
2
  import { renderer } from './launch.js'
3
+ import * as webglShaders from '@lightningjs/renderer/webgl/shaders'
4
+ import * as canvasShaders from '@lightningjs/renderer/canvas/shaders'
5
+
6
+ function registerBlitsDefaultShaders(
7
+ shManager,
8
+ Rounded,
9
+ Border,
10
+ Shadow,
11
+ RoundedWithBorder,
12
+ RoundedWithShadow,
13
+ RoundedWithBorderAndShadow,
14
+ HolePunch,
15
+ RadialGradient,
16
+ LinearGradient
17
+ ) {
18
+ shManager.registerShaderType('rounded', Rounded)
19
+ shManager.registerShaderType('border', Border)
20
+ shManager.registerShaderType('shadow', Shadow)
21
+ shManager.registerShaderType('roundedWithBorder', RoundedWithBorder)
22
+ shManager.registerShaderType('roundedWithShadow', RoundedWithShadow)
23
+ shManager.registerShaderType('roundedWithBorderAndShadow', RoundedWithBorderAndShadow)
24
+ shManager.registerShaderType('holePunch', HolePunch)
25
+ shManager.registerShaderType('radialGradient', RadialGradient)
26
+ shManager.registerShaderType('linearGradient', LinearGradient)
27
+ }
3
28
 
4
29
  export default () => {
5
30
  const stage = renderer.stage
6
- Settings.get('shaders', []).forEach((shader) => {
7
- stage.shManager.registerShaderType(shader.name, shader.type)
8
- })
9
- Settings.get('effects', []).forEach((effect) => {
10
- stage.shManager.registerShaderType(effect.name, effect.type)
11
- })
31
+
32
+ const {
33
+ Rounded,
34
+ Border,
35
+ Shadow,
36
+ RoundedWithBorder,
37
+ RoundedWithShadow,
38
+ RoundedWithBorderAndShadow,
39
+ HolePunch,
40
+ RadialGradient,
41
+ LinearGradient,
42
+ } = Settings.get('renderMode', 'webgl') === 'webgl' ? webglShaders : canvasShaders
43
+
44
+ registerBlitsDefaultShaders(
45
+ stage.shManager,
46
+ Rounded,
47
+ Border,
48
+ Shadow,
49
+ RoundedWithBorder,
50
+ RoundedWithShadow,
51
+ RoundedWithBorderAndShadow,
52
+ HolePunch,
53
+ RadialGradient,
54
+ LinearGradient
55
+ )
56
+
57
+ const shaders = Settings.get('shaders', [])
58
+ const len = shaders.length
59
+ for (let i = 0; i < len; i++) {
60
+ stage.shManager.registerShaderType(shaders[i].name, shaders[i].type)
61
+ }
12
62
  }