update and enable photon profiles, stub creality, elegoo
This commit is contained in:
parent
682f2b0a48
commit
db37c13100
23 changed files with 425 additions and 81 deletions
15
src/kiri/dev/sla/Anycubic.Photon.D2.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.D2.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 130.56,
|
||||||
|
"bed_depth": 73.44,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 165,
|
||||||
|
"resolution_x": 2560,
|
||||||
|
"resolution_y": 1440,
|
||||||
|
"sla_format": "dl2p",
|
||||||
|
"sla_file_ext": "dl2p",
|
||||||
|
"sla_format_version": 517
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.M3.Max.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.M3.Max.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 298.08,
|
||||||
|
"bed_depth": 165.6,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 300,
|
||||||
|
"resolution_x": 6480,
|
||||||
|
"resolution_y": 3600,
|
||||||
|
"sla_format": "pm3m",
|
||||||
|
"sla_file_ext": "pm3m",
|
||||||
|
"sla_format_version": 516
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.M3.Plus.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.M3.Plus.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 198.15,
|
||||||
|
"bed_depth": 123.84,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 245,
|
||||||
|
"resolution_x": 5760,
|
||||||
|
"resolution_y": 3600,
|
||||||
|
"sla_format": "pwmb",
|
||||||
|
"sla_file_ext": "pwmb",
|
||||||
|
"sla_format_version": 517
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.M3.Premium.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.M3.Premium.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 218.88,
|
||||||
|
"bed_depth": 123.12,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 250,
|
||||||
|
"resolution_x": 7680,
|
||||||
|
"resolution_y": 4320,
|
||||||
|
"sla_format": "pm3r",
|
||||||
|
"sla_file_ext": "pm3r",
|
||||||
|
"sla_format_version": 517
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.M3.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.M3.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 163.84,
|
||||||
|
"bed_depth": 102.4,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 180,
|
||||||
|
"resolution_x": 4096,
|
||||||
|
"resolution_y": 2560,
|
||||||
|
"sla_format": "pm3",
|
||||||
|
"sla_file_ext": "pm3",
|
||||||
|
"sla_format_version": 516
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,6 @@
|
||||||
"resolution_y": 2560,
|
"resolution_y": 2560,
|
||||||
"sla_format": "pm3n",
|
"sla_format": "pm3n",
|
||||||
"sla_file_ext": "pm3n",
|
"sla_file_ext": "pm3n",
|
||||||
"sla_format_version": 1
|
"sla_format_version": 517
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
"no_clone": true,
|
"no_clone": true,
|
||||||
"cmd": {},
|
"cmd": {},
|
||||||
"settings": {
|
"settings": {
|
||||||
"bed_width": 132,
|
"bed_width": 134.4,
|
||||||
"bed_depth": 80,
|
"bed_depth": 84,
|
||||||
"bed_height": 1,
|
"bed_height": 1,
|
||||||
"max_height": 165,
|
"max_height": 165,
|
||||||
"resolution_x": 3840,
|
"resolution_x": 3840,
|
||||||
"resolution_y": 2400,
|
"resolution_y": 2400,
|
||||||
"sla_format": "pwma",
|
"sla_format": "pwma",
|
||||||
"sla_file_ext": "pwma",
|
"sla_file_ext": "pwma",
|
||||||
"sla_format_version": 1
|
"sla_format_version": 516
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.Mono.M5.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.Mono.M5.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 218.88,
|
||||||
|
"bed_depth": 122.88,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 200,
|
||||||
|
"resolution_x": 11520,
|
||||||
|
"resolution_y": 5120,
|
||||||
|
"sla_format": "pm5",
|
||||||
|
"sla_file_ext": "pm5",
|
||||||
|
"sla_format_version": 517
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.Mono.M5s.Pro.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.Mono.M5s.Pro.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 223.642,
|
||||||
|
"bed_depth": 126.976,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 200,
|
||||||
|
"resolution_x": 13312,
|
||||||
|
"resolution_y": 5120,
|
||||||
|
"sla_format": "m5sp",
|
||||||
|
"sla_file_ext": "m5sp",
|
||||||
|
"sla_format_version": 518
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,6 @@
|
||||||
"resolution_y": 5120,
|
"resolution_y": 5120,
|
||||||
"sla_format": "pm5s",
|
"sla_format": "pm5s",
|
||||||
"sla_file_ext": "pm5s",
|
"sla_file_ext": "pm5s",
|
||||||
"sla_format_version": 1
|
"sla_format_version": 518
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.Mono.SE.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.Mono.SE.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 82.62,
|
||||||
|
"bed_depth": 130.56,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 160,
|
||||||
|
"resolution_x": 1620,
|
||||||
|
"resolution_y": 2560,
|
||||||
|
"sla_format": "pwms",
|
||||||
|
"sla_file_ext": "pwms",
|
||||||
|
"sla_format_version": 516
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.Mono.SQ.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.Mono.SQ.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 120,
|
||||||
|
"bed_depth": 128,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 200,
|
||||||
|
"resolution_x": 2400,
|
||||||
|
"resolution_y": 2560,
|
||||||
|
"sla_format": "pmsq",
|
||||||
|
"sla_file_ext": "pmsq",
|
||||||
|
"sla_format_version": 516
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.Mono.X.2.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.Mono.X.2.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 196.61,
|
||||||
|
"bed_depth": 122.88,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 200,
|
||||||
|
"resolution_x": 4096,
|
||||||
|
"resolution_y": 2560,
|
||||||
|
"sla_format": "pmx2",
|
||||||
|
"sla_file_ext": "pmx2",
|
||||||
|
"sla_format_version": 517
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.Mono.X.6K.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.Mono.X.6K.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 198.15,
|
||||||
|
"bed_depth": 123.84,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 245,
|
||||||
|
"resolution_x": 5760,
|
||||||
|
"resolution_y": 3600,
|
||||||
|
"sla_format": "pwmb",
|
||||||
|
"sla_file_ext": "pwmb",
|
||||||
|
"sla_format_version": 516
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
"max_height": 200,
|
"max_height": 200,
|
||||||
"resolution_x": 5760,
|
"resolution_x": 5760,
|
||||||
"resolution_y": 3600,
|
"resolution_y": 3600,
|
||||||
"sla_format": "pwmb",
|
"sla_format": "px6s",
|
||||||
"sla_file_ext": "pwmb",
|
"sla_file_ext": "px6s",
|
||||||
"sla_format_version": 1
|
"sla_format_version": 517
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,6 @@
|
||||||
"resolution_y": 2400,
|
"resolution_y": 2400,
|
||||||
"sla_format": "pwmx",
|
"sla_format": "pwmx",
|
||||||
"sla_file_ext": "pwmx",
|
"sla_file_ext": "pwmx",
|
||||||
"sla_format_version": 1
|
"sla_format_version": 516
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
"no_clone": true,
|
"no_clone": true,
|
||||||
"cmd": {},
|
"cmd": {},
|
||||||
"settings": {
|
"settings": {
|
||||||
"bed_width": 130,
|
"bed_width": 82.62,
|
||||||
"bed_depth": 80,
|
"bed_depth": 130.56,
|
||||||
"bed_height": 1,
|
"bed_height": 1,
|
||||||
"max_height": 165,
|
"max_height": 165,
|
||||||
"resolution_x": 1620,
|
"resolution_x": 1620,
|
||||||
"resolution_y": 2560,
|
"resolution_y": 2560,
|
||||||
"sla_format": "pwmo",
|
"sla_format": "pwmo",
|
||||||
"sla_file_ext": "pwmo",
|
"sla_file_ext": "pwmo",
|
||||||
"sla_format_version": 1
|
"sla_format_version": 516
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
src/kiri/dev/sla/Anycubic.Photon.Ultra.json
Normal file
15
src/kiri/dev/sla/Anycubic.Photon.Ultra.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 102.4,
|
||||||
|
"bed_depth": 57.6,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 165,
|
||||||
|
"resolution_x": 1280,
|
||||||
|
"resolution_y": 720,
|
||||||
|
"sla_format": "dlp",
|
||||||
|
"sla_file_ext": "dlp",
|
||||||
|
"sla_format_version": 516
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/kiri/dev/sla/Creality.CT-005.Pro.json
Normal file
14
src/kiri/dev/sla/Creality.CT-005.Pro.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 192,
|
||||||
|
"bed_depth": 120,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 250,
|
||||||
|
"resolution_x": 3840,
|
||||||
|
"resolution_y": 2400,
|
||||||
|
"sla_format": "cxdlp",
|
||||||
|
"sla_file_ext": "cxdlp"
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/kiri/dev/sla/Creality.Halot.Lite.json
Normal file
14
src/kiri/dev/sla/Creality.Halot.Lite.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 192,
|
||||||
|
"bed_depth": 120,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 200,
|
||||||
|
"resolution_x": 3840,
|
||||||
|
"resolution_y": 2400,
|
||||||
|
"sla_format": "cxdlp",
|
||||||
|
"sla_file_ext": "cxdlp"
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/kiri/dev/sla/Elegoo.Mars.2.CTB.json
Normal file
15
src/kiri/dev/sla/Elegoo.Mars.2.CTB.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"no_clone": true,
|
||||||
|
"cmd": {},
|
||||||
|
"settings": {
|
||||||
|
"bed_width": 82.62,
|
||||||
|
"bed_depth": 130.56,
|
||||||
|
"bed_height": 1,
|
||||||
|
"max_height": 150,
|
||||||
|
"resolution_x": 1620,
|
||||||
|
"resolution_y": 2560,
|
||||||
|
"sla_format": "ctb",
|
||||||
|
"sla_file_ext": "ctb",
|
||||||
|
"sla_format_version": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -64,77 +64,98 @@ export const SLA_FORMATS = {
|
||||||
id: 'pwmo',
|
id: 'pwmo',
|
||||||
ext: 'pwmo',
|
ext: 'pwmo',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pwma: {
|
pwma: {
|
||||||
id: 'pwma',
|
id: 'pwma',
|
||||||
ext: 'pwma',
|
ext: 'pwma',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pwms: {
|
pwms: {
|
||||||
id: 'pwms',
|
id: 'pwms',
|
||||||
ext: 'pwms',
|
ext: 'pwms',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pwmx: {
|
pwmx: {
|
||||||
id: 'pwmx',
|
id: 'pwmx',
|
||||||
ext: 'pwmx',
|
ext: 'pwmx',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pwmb: {
|
pwmb: {
|
||||||
id: 'pwmb',
|
id: 'pwmb',
|
||||||
ext: 'pwmb',
|
ext: 'pwmb',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pwsq: {
|
pmsq: {
|
||||||
id: 'pwsq',
|
id: 'pmsq',
|
||||||
ext: 'pwsq',
|
ext: 'pmsq',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
px6s: {
|
px6s: {
|
||||||
id: 'px6s',
|
id: 'px6s',
|
||||||
ext: 'px6s',
|
ext: 'px6s',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pm3: {
|
pm3: {
|
||||||
id: 'pm3',
|
id: 'pm3',
|
||||||
ext: 'pm3',
|
ext: 'pm3',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pm3n: {
|
pm3n: {
|
||||||
id: 'pm3n',
|
id: 'pm3n',
|
||||||
ext: 'pm3n',
|
ext: 'pm3n',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pm3m: {
|
pm3m: {
|
||||||
id: 'pm3m',
|
id: 'pm3m',
|
||||||
ext: 'pm3m',
|
ext: 'pm3m',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pm3r: {
|
pm3r: {
|
||||||
id: 'pm3r',
|
id: 'pm3r',
|
||||||
ext: 'pm3r',
|
ext: 'pm3r',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
|
family: 'photon-workshop'
|
||||||
|
},
|
||||||
|
dl2p: {
|
||||||
|
id: 'dl2p',
|
||||||
|
ext: 'dl2p',
|
||||||
|
proprietary: true,
|
||||||
|
available: true,
|
||||||
|
family: 'photon-workshop'
|
||||||
|
},
|
||||||
|
pmx2: {
|
||||||
|
id: 'pmx2',
|
||||||
|
ext: 'pmx2',
|
||||||
|
proprietary: true,
|
||||||
|
available: true,
|
||||||
|
family: 'photon-workshop'
|
||||||
|
},
|
||||||
|
dlp: {
|
||||||
|
id: 'dlp',
|
||||||
|
ext: 'dlp',
|
||||||
|
proprietary: true,
|
||||||
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pm4m: {
|
pm4m: {
|
||||||
|
|
@ -162,14 +183,21 @@ export const SLA_FORMATS = {
|
||||||
id: 'pm5',
|
id: 'pm5',
|
||||||
ext: 'pm5',
|
ext: 'pm5',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pm5s: {
|
pm5s: {
|
||||||
id: 'pm5s',
|
id: 'pm5s',
|
||||||
ext: 'pm5s',
|
ext: 'pm5s',
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
available: false,
|
available: true,
|
||||||
|
family: 'photon-workshop'
|
||||||
|
},
|
||||||
|
m5sp: {
|
||||||
|
id: 'm5sp',
|
||||||
|
ext: 'm5sp',
|
||||||
|
proprietary: true,
|
||||||
|
available: true,
|
||||||
family: 'photon-workshop'
|
family: 'photon-workshop'
|
||||||
},
|
},
|
||||||
pm7: {
|
pm7: {
|
||||||
|
|
|
||||||
|
|
@ -4,43 +4,51 @@ import { imageToRowMajor, renderRasterLayers, round } from './raster.js';
|
||||||
|
|
||||||
const FAMILY = "Photon Workshop";
|
const FAMILY = "Photon Workshop";
|
||||||
const MARK_SIZE = 12;
|
const MARK_SIZE = 12;
|
||||||
|
const VERSION_516 = 516;
|
||||||
const VERSION_517 = 517;
|
const VERSION_517 = 517;
|
||||||
|
const VERSION_518 = 518;
|
||||||
const RLE4_ENCODING_LIMIT = 0xfff;
|
const RLE4_ENCODING_LIMIT = 0xfff;
|
||||||
const FORMAT_RECORDS = {
|
const FORMAT_RECORDS = {
|
||||||
pw0: { ext: "pw0", generation: "pw", notes: "Photon Zero" },
|
pw0: { ext: "pw0", generation: "pw", notes: "Photon Zero" },
|
||||||
pwx: { ext: "pwx", generation: "pw", notes: "Photon X" },
|
pwx: { ext: "pwx", generation: "pw", notes: "Photon X" },
|
||||||
pwmo: { ext: "pwmo", generation: "mono", notes: "Photon Mono" },
|
dlp: { ext: "dlp", generation: "mono", version: VERSION_516, machine: "Photon Ultra", notes: "Photon Ultra" },
|
||||||
pwma: { ext: "pwma", generation: "mono", notes: "Photon Mono 4K class" },
|
dl2p: { ext: "dl2p", generation: "m3", version: VERSION_517, machine: "Photon D2", notes: "Photon D2" },
|
||||||
pwms: { ext: "pwms", generation: "mono", notes: "Photon Mono SE class" },
|
pwmo: { ext: "pwmo", generation: "mono", version: VERSION_516, machine: "Photon Mono", notes: "Photon Mono" },
|
||||||
pwmx: { ext: "pwmx", generation: "mono-x", notes: "Photon Mono X class" },
|
pwma: { ext: "pwma", generation: "mono", version: VERSION_516, machine: "Photon Mono 4K", notes: "Photon Mono 4K class" },
|
||||||
pwmb: { ext: "pwmb", generation: "m3", notes: "Photon M3 / Mono X 6K class" },
|
pwms: { ext: "pwms", generation: "mono", version: VERSION_516, machine: "Photon Mono SE", notes: "Photon Mono SE class" },
|
||||||
pwsq: { ext: "pwsq", generation: "m3", notes: "Photon M3 Premium class" },
|
pwmx: { ext: "pwmx", generation: "mono-x", version: VERSION_516, machine: "Photon Mono X", notes: "Photon Mono X class" },
|
||||||
px6s: { ext: "px6s", generation: "m3", notes: "Photon X 6Ks class" },
|
pmx2: { ext: "pmx2", generation: "mono-x", version: VERSION_517, machine: "Photon Mono X2", notes: "Photon Mono X2" },
|
||||||
pm3: { ext: "pm3", generation: "m3", notes: "Photon M3" },
|
pwmb: { ext: "pwmb", generation: "m3", version: VERSION_517, machine: "Photon Mono X 6K", notes: "Photon M3 Plus / Mono X 6K class" },
|
||||||
pm3n: { ext: "pm3n", generation: "m3", notes: "Photon Mono 2" },
|
pmsq: { ext: "pmsq", generation: "m3", version: VERSION_516, machine: "Photon Mono SQ", notes: "Photon Mono SQ" },
|
||||||
pm3m: { ext: "pm3m", generation: "m3", notes: "Photon M3 Max / Plus class" },
|
px6s: { ext: "px6s", generation: "m3", version: VERSION_517, machine: "Photon Mono X 6Ks", notes: "Photon X 6Ks class" },
|
||||||
pm3r: { ext: "pm3r", generation: "m3", notes: "Photon M3 resolver variant" },
|
pm3: { ext: "pm3", generation: "m3", version: VERSION_516, machine: "Photon M3", notes: "Photon M3" },
|
||||||
|
pm3n: { ext: "pm3n", generation: "m3", version: VERSION_517, machine: "Photon Mono 2", notes: "Photon Mono 2" },
|
||||||
|
pm3m: { ext: "pm3m", generation: "m3", version: VERSION_516, machine: "Photon M3 Max", notes: "Photon M3 Max / Plus class" },
|
||||||
|
pm3r: { ext: "pm3r", generation: "m3", version: VERSION_517, machine: "Photon M3 Premium", notes: "Photon M3 Premium" },
|
||||||
pm4m: { ext: "pm4m", generation: "m4", notes: "Photon Mono M4 class" },
|
pm4m: { ext: "pm4m", generation: "m4", notes: "Photon Mono M4 class" },
|
||||||
pm4u: { ext: "pm4u", generation: "m4", notes: "Photon Mono 4 Ultra class" },
|
pm4u: { ext: "pm4u", generation: "m4", notes: "Photon Mono 4 Ultra class" },
|
||||||
pm4n: { ext: "pm4n", generation: "m4", notes: "Photon Mono 4" },
|
pm4n: { ext: "pm4n", generation: "m4", version: VERSION_517, machine: "Photon Mono 4", notes: "Photon Mono 4" },
|
||||||
pm5: { ext: "pm5", generation: "m5", notes: "Photon Mono M5" },
|
pm5: { ext: "pm5", generation: "m5", version: VERSION_517, machine: "Photon Mono M5", notes: "Photon Mono M5" },
|
||||||
pm5s: { ext: "pm5s", generation: "m5", notes: "Photon Mono M5s" },
|
pm5s: { ext: "pm5s", generation: "m5", version: VERSION_518, machine: "Photon Mono M5s", notes: "Photon Mono M5s" },
|
||||||
|
m5sp: { ext: "m5sp", generation: "m5", version: VERSION_518, machine: "Photon Mono M5s Pro", notes: "Photon Mono M5s Pro" },
|
||||||
pm7: { ext: "pm7", generation: "m7", notes: "Photon Mono M7 class" },
|
pm7: { ext: "pm7", generation: "m7", notes: "Photon Mono M7 class" },
|
||||||
pm7m: { ext: "pm7m", generation: "m7", notes: "Photon Mono M7 Pro class" },
|
pm7m: { ext: "pm7m", generation: "m7", notes: "Photon Mono M7 Pro class" },
|
||||||
pwsz: { ext: "pwsz", generation: "v3-zip", notes: "Photon Workshop v3 zip container" }
|
pwsz: { ext: "pwsz", generation: "v3-zip", notes: "Photon Workshop v3 zip container" }
|
||||||
};
|
};
|
||||||
const ENCODE_FORMATS = new Set(["pm4n"]);
|
const ENCODE_FORMATS = new Set(Object.entries(FORMAT_RECORDS)
|
||||||
|
.filter(([, rec]) => rec.version >= VERSION_516)
|
||||||
|
.map(([format]) => format));
|
||||||
|
|
||||||
function encode(print, progress, renderer) {
|
function encode(print, progress, renderer) {
|
||||||
let format = print.settings.device.slaFormat || "pm4n";
|
let format = print.settings.device.slaFormat || "pm4n";
|
||||||
let rec = FORMAT_RECORDS[format];
|
let rec = FORMAT_RECORDS[format];
|
||||||
|
|
||||||
if (format === "pm4n") {
|
if (canEncode(format)) {
|
||||||
if (renderer) {
|
if (renderer) {
|
||||||
return Promise.resolve(encodePM4N(print, progress, renderer));
|
return Promise.resolve(encodeAnycubic(print, progress, renderer, rec));
|
||||||
}
|
}
|
||||||
return import('./x_photon.js').then(({ photon }) =>
|
return import('./x_photon.js').then(({ photon }) =>
|
||||||
encodePM4N(print, progress, photon));
|
encodeAnycubic(print, progress, photon, rec));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(new Error([
|
return Promise.reject(new Error([
|
||||||
|
|
@ -50,9 +58,11 @@ function encode(print, progress, renderer) {
|
||||||
].join(" ")));
|
].join(" ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodePM4N(print, progress, photon) {
|
function encodeAnycubic(print, progress, photon, rec) {
|
||||||
let layers = [];
|
let layers = [];
|
||||||
let preview = createPreview(224, 168);
|
let preview = createPreview(224, 168);
|
||||||
|
let preview2 = rec.version >= VERSION_518 ? createPreview(330, 190) : null;
|
||||||
|
let format = rec.ext;
|
||||||
|
|
||||||
let { ctx, volume } = renderRasterLayers(print, photon, params => {
|
let { ctx, volume } = renderRasterLayers(print, photon, params => {
|
||||||
let { index, rendered, bottom, z, ctx } = params;
|
let { index, rendered, bottom, z, ctx } = params;
|
||||||
|
|
@ -61,6 +71,9 @@ function encodePM4N(print, progress, photon) {
|
||||||
let encoded = encodePW0(raster);
|
let encoded = encodePW0(raster);
|
||||||
|
|
||||||
accumulatePreview(preview, rendered.image, width, height);
|
accumulatePreview(preview, rendered.image, width, height);
|
||||||
|
if (preview2) {
|
||||||
|
accumulatePreview(preview2, rendered.image, width, height);
|
||||||
|
}
|
||||||
layers.push({
|
layers.push({
|
||||||
index,
|
index,
|
||||||
data: encoded,
|
data: encoded,
|
||||||
|
|
@ -70,10 +83,10 @@ function encodePM4N(print, progress, photon) {
|
||||||
exposure: bottom ? process.slaBaseOn : process.slaLayerOn,
|
exposure: bottom ? process.slaBaseOn : process.slaLayerOn,
|
||||||
z
|
z
|
||||||
});
|
});
|
||||||
}, progress ? (value) => progress(value * 0.85, "pm4n_encode") : null);
|
}, progress ? (value) => progress(value * 0.85, `${format}_encode`) : null);
|
||||||
|
|
||||||
let file = writeAnycubic({ ctx, layers, volume, preview });
|
let file = writeAnycubic({ ctx, layers, volume, preview, preview2, rec });
|
||||||
if (progress) progress(1, "pm4n_write");
|
if (progress) progress(1, `${format}_write`);
|
||||||
|
|
||||||
return { file, layers: layers.length, volume };
|
return { file, layers: layers.length, volume };
|
||||||
}
|
}
|
||||||
|
|
@ -85,9 +98,10 @@ function read(input) {
|
||||||
throw new Error(`invalid Anycubic mark ${mark}`);
|
throw new Error(`invalid Anycubic mark ${mark}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let version = view.getUint32(12, true);
|
||||||
let file = {
|
let file = {
|
||||||
mark,
|
mark,
|
||||||
version: view.getUint32(12, true),
|
version,
|
||||||
tableCount: view.getUint32(16, true),
|
tableCount: view.getUint32(16, true),
|
||||||
headerOffset: view.getUint32(20, true),
|
headerOffset: view.getUint32(20, true),
|
||||||
softwareOffset: view.getUint32(24, true),
|
softwareOffset: view.getUint32(24, true),
|
||||||
|
|
@ -97,7 +111,9 @@ function read(input) {
|
||||||
extraOffset: view.getUint32(40, true),
|
extraOffset: view.getUint32(40, true),
|
||||||
machineOffset: view.getUint32(44, true),
|
machineOffset: view.getUint32(44, true),
|
||||||
layerImageOffset: view.getUint32(48, true),
|
layerImageOffset: view.getUint32(48, true),
|
||||||
modelOffset: view.getUint32(52, true)
|
modelOffset: version >= VERSION_517 ? view.getUint32(52, true) : 0,
|
||||||
|
subLayerOffset: version >= VERSION_518 ? view.getUint32(56, true) : 0,
|
||||||
|
preview2Offset: version >= VERSION_518 ? view.getUint32(60, true) : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -119,11 +135,21 @@ function decodeLayer(view, layer, pixelCount) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeAnycubic(params) {
|
function writeAnycubic(params) {
|
||||||
let { ctx, layers, volume, preview } = params;
|
let { ctx, layers, volume, preview, preview2, rec } = params;
|
||||||
let { device, process, width, height } = ctx;
|
let { device, process, width, height } = ctx;
|
||||||
let fileMarkSize = MARK_SIZE + 11 * 4;
|
let version = Number(device.slaFormatVersion || rec.version || VERSION_517);
|
||||||
|
if (version < VERSION_516 || version > VERSION_518) {
|
||||||
|
throw new Error(`Anycubic .${rec.ext} encoder requires version 516-518 (got ${version})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let fileMarkSize = MARK_SIZE + ({
|
||||||
|
[VERSION_516]: 10,
|
||||||
|
[VERSION_517]: 11,
|
||||||
|
[VERSION_518]: 13
|
||||||
|
}[version] || 11) * 4;
|
||||||
let headerOffset = fileMarkSize;
|
let headerOffset = fileMarkSize;
|
||||||
let headerSize = 16 + 92;
|
let headerLength = version >= VERSION_518 ? 96 : version >= VERSION_517 ? 92 : 84;
|
||||||
|
let headerSize = 16 + headerLength;
|
||||||
let previewOffset = headerOffset + headerSize;
|
let previewOffset = headerOffset + headerSize;
|
||||||
let previewData = encodePreview(preview);
|
let previewData = encodePreview(preview);
|
||||||
let previewSize = 28 + previewData.length;
|
let previewSize = 28 + previewData.length;
|
||||||
|
|
@ -134,12 +160,21 @@ function writeAnycubic(params) {
|
||||||
let extraOffset = layerDefOffset + layerDefSize;
|
let extraOffset = layerDefOffset + layerDefSize;
|
||||||
let extraSize = 16 + 56;
|
let extraSize = 16 + 56;
|
||||||
let machineOffset = extraOffset + extraSize;
|
let machineOffset = extraOffset + extraSize;
|
||||||
let machineSize = 156;
|
let machineSize = version >= VERSION_518 ? 224 : 156;
|
||||||
let softwareOffset = machineOffset + machineSize;
|
let softwareOffset = version >= VERSION_517 ? machineOffset + machineSize : 0;
|
||||||
let softwareSize = 164;
|
let softwareSize = version >= VERSION_517 ? 164 : 0;
|
||||||
let modelOffset = softwareOffset + softwareSize;
|
let modelOffset = version >= VERSION_517 ? softwareOffset + softwareSize : 0;
|
||||||
let modelSize = 48;
|
let modelSize = version >= VERSION_517 ? 48 : 0;
|
||||||
let layerImageOffset = modelOffset + modelSize;
|
let subLayerOffset = version >= VERSION_518 ? modelOffset + modelSize : 0;
|
||||||
|
let subLayerSize = version >= VERSION_518 ? 24 + layers.length * 44 : 0;
|
||||||
|
let preview2Offset = version >= VERSION_518 ? subLayerOffset + subLayerSize : 0;
|
||||||
|
let preview2Data = preview2 ? encodePreview(preview2) : null;
|
||||||
|
let preview2Size = preview2 ? 28 + preview2Data.length : 0;
|
||||||
|
let layerImageOffset = version >= VERSION_518
|
||||||
|
? preview2Offset + preview2Size
|
||||||
|
: version >= VERSION_517
|
||||||
|
? modelOffset + modelSize
|
||||||
|
: machineOffset + machineSize;
|
||||||
let total = layerImageOffset;
|
let total = layerImageOffset;
|
||||||
|
|
||||||
layers.forEach(layer => {
|
layers.forEach(layer => {
|
||||||
|
|
@ -150,8 +185,8 @@ function writeAnycubic(params) {
|
||||||
|
|
||||||
let writer = new BinaryWriter(new ArrayBuffer(total));
|
let writer = new BinaryWriter(new ArrayBuffer(total));
|
||||||
writeFileMark(writer, {
|
writeFileMark(writer, {
|
||||||
version: VERSION_517,
|
version,
|
||||||
tableCount: 9,
|
tableCount: version >= VERSION_518 ? 11 : version >= VERSION_517 ? 9 : 8,
|
||||||
headerOffset,
|
headerOffset,
|
||||||
softwareOffset,
|
softwareOffset,
|
||||||
previewOffset,
|
previewOffset,
|
||||||
|
|
@ -160,10 +195,12 @@ function writeAnycubic(params) {
|
||||||
extraOffset,
|
extraOffset,
|
||||||
machineOffset,
|
machineOffset,
|
||||||
layerImageOffset,
|
layerImageOffset,
|
||||||
modelOffset
|
modelOffset,
|
||||||
|
subLayerOffset,
|
||||||
|
preview2Offset
|
||||||
});
|
});
|
||||||
writer.seek(headerOffset);
|
writer.seek(headerOffset);
|
||||||
writeHeader(writer, { device, process, width, height, layers, volume });
|
writeHeader(writer, { device, process, width, height, layers, volume, version, headerLength });
|
||||||
writer.seek(previewOffset);
|
writer.seek(previewOffset);
|
||||||
writePreview(writer, preview, previewData);
|
writePreview(writer, preview, previewData);
|
||||||
writer.seek(colorTableOffset);
|
writer.seek(colorTableOffset);
|
||||||
|
|
@ -173,16 +210,28 @@ function writeAnycubic(params) {
|
||||||
writer.seek(extraOffset);
|
writer.seek(extraOffset);
|
||||||
writeExtra(writer, process);
|
writeExtra(writer, process);
|
||||||
writer.seek(machineOffset);
|
writer.seek(machineOffset);
|
||||||
writeMachine(writer, { device, width, height });
|
writeMachine(writer, { device, width, height, version, rec });
|
||||||
writer.seek(softwareOffset);
|
if (version >= VERSION_517) {
|
||||||
writeSoftware(writer);
|
writer.seek(softwareOffset);
|
||||||
writer.seek(modelOffset);
|
writeSoftware(writer);
|
||||||
writeModel(writer, { device, process, layers });
|
writer.seek(modelOffset);
|
||||||
|
writeModel(writer, { device, process, layers });
|
||||||
|
}
|
||||||
|
if (version >= VERSION_518) {
|
||||||
|
writer.seek(subLayerOffset);
|
||||||
|
writeSubLayerDefinitions(writer, layers);
|
||||||
|
writer.seek(preview2Offset);
|
||||||
|
writePreview2(writer, preview2, preview2Data);
|
||||||
|
}
|
||||||
layers.forEach(layer => {
|
layers.forEach(layer => {
|
||||||
writer.seek(layer.dataOffset);
|
writer.seek(layer.dataOffset);
|
||||||
writer.writeBytes(layer.data);
|
writer.writeBytes(layer.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (writer.pos !== total) {
|
||||||
|
throw new Error(`Anycubic writer size mismatch (${writer.pos} !== ${total})`);
|
||||||
|
}
|
||||||
|
|
||||||
return writer.buffer;
|
return writer.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,15 +247,21 @@ function writeFileMark(writer, mark) {
|
||||||
writer.writeU32(mark.extraOffset);
|
writer.writeU32(mark.extraOffset);
|
||||||
writer.writeU32(mark.machineOffset);
|
writer.writeU32(mark.machineOffset);
|
||||||
writer.writeU32(mark.layerImageOffset);
|
writer.writeU32(mark.layerImageOffset);
|
||||||
writer.writeU32(mark.modelOffset);
|
if (mark.version >= VERSION_517) {
|
||||||
|
writer.writeU32(mark.modelOffset);
|
||||||
|
}
|
||||||
|
if (mark.version >= VERSION_518) {
|
||||||
|
writer.writeU32(mark.subLayerOffset);
|
||||||
|
writer.writeU32(mark.preview2Offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeHeader(writer, params) {
|
function writeHeader(writer, params) {
|
||||||
let { device, process, width, height, layers, volume } = params;
|
let { device, process, width, height, layers, volume, version, headerLength } = params;
|
||||||
let printTime = Math.round((process.slaBaseLayers * process.slaBaseOn) +
|
let printTime = Math.round((process.slaBaseLayers * process.slaBaseOn) +
|
||||||
Math.max(0, layers.length - process.slaBaseLayers) * process.slaLayerOn);
|
Math.max(0, layers.length - process.slaBaseLayers) * process.slaLayerOn);
|
||||||
|
|
||||||
writer.writeTable("HEADER", 92);
|
writer.writeTable("HEADER", headerLength);
|
||||||
writer.writeF32(pixelSizeMicrons(device.bedWidth, width));
|
writer.writeF32(pixelSizeMicrons(device.bedWidth, width));
|
||||||
writer.writeF32(process.slaSlice);
|
writer.writeF32(process.slaSlice);
|
||||||
writer.writeF32(process.slaLayerOn);
|
writer.writeF32(process.slaLayerOn);
|
||||||
|
|
@ -228,9 +283,14 @@ function writeHeader(writer, params) {
|
||||||
writer.writeU32(0);
|
writer.writeU32(0);
|
||||||
writer.writeU32(0);
|
writer.writeU32(0);
|
||||||
writer.writeU32(0);
|
writer.writeU32(0);
|
||||||
writer.writeU16(0);
|
if (version >= VERSION_517) {
|
||||||
writer.writeU16(0);
|
writer.writeU16(0);
|
||||||
writer.writeU32(0);
|
writer.writeU16(0);
|
||||||
|
writer.writeU32(0);
|
||||||
|
}
|
||||||
|
if (version >= VERSION_518) {
|
||||||
|
writer.writeU32(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function writePreview(writer, preview, data) {
|
function writePreview(writer, preview, data) {
|
||||||
|
|
@ -241,6 +301,15 @@ function writePreview(writer, preview, data) {
|
||||||
writer.writeBytes(data);
|
writer.writeBytes(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function writePreview2(writer, preview, data) {
|
||||||
|
writer.writeTable("PREVIEW2", 28 + data.length);
|
||||||
|
writer.writeU32(preview.width);
|
||||||
|
writer.writeU16(4293);
|
||||||
|
writer.writeU16(0);
|
||||||
|
writer.writeU32(preview.height);
|
||||||
|
writer.writeBytes(data);
|
||||||
|
}
|
||||||
|
|
||||||
function writeColorTable(writer) {
|
function writeColorTable(writer) {
|
||||||
writer.writeU32(0);
|
writer.writeU32(0);
|
||||||
writer.writeU32(16);
|
writer.writeU32(16);
|
||||||
|
|
@ -284,18 +353,30 @@ function writeExtra(writer, process) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeMachine(writer, params) {
|
function writeMachine(writer, params) {
|
||||||
let { device, width, height } = params;
|
let { device, width, height, version, rec } = params;
|
||||||
|
let tableLength = version >= VERSION_518 ? 224 : 156;
|
||||||
|
let propertyFields = version >= VERSION_518 ? 15 : version >= VERSION_517 ? 7 : 1;
|
||||||
|
|
||||||
writer.writeTable("MACHINE", 156);
|
writer.writeTable("MACHINE", tableLength);
|
||||||
writer.writeString("Photon Mono 4", 96);
|
writer.writeString(rec.machine || device.deviceName || "Anycubic Photon", 96);
|
||||||
writer.writeString("pw0Img", 16);
|
writer.writeString("pw0Img", 16);
|
||||||
writer.writeU32(16);
|
writer.writeU32(16);
|
||||||
writer.writeU32(7);
|
writer.writeU32(propertyFields);
|
||||||
writer.writeF32(device.bedWidth);
|
writer.writeF32(device.bedWidth);
|
||||||
writer.writeF32(device.bedDepth);
|
writer.writeF32(device.bedDepth);
|
||||||
writer.writeF32(device.maxHeight || device.bedHeight);
|
writer.writeF32(device.maxHeight || device.bedHeight);
|
||||||
writer.writeU32(VERSION_517);
|
writer.writeU32(version);
|
||||||
writer.writeU32(6506241);
|
writer.writeU32(6506241);
|
||||||
|
if (version >= VERSION_518) {
|
||||||
|
writer.writeF32(pixelSizeMicrons(device.bedWidth, width));
|
||||||
|
writer.writeF32(pixelSizeMicrons(device.bedDepth, height));
|
||||||
|
for (let i=0; i<8; i++) writer.writeU32(0);
|
||||||
|
writer.writeU32(1);
|
||||||
|
writer.writeU32(0);
|
||||||
|
writer.writeU16(width);
|
||||||
|
writer.writeU16(height);
|
||||||
|
for (let i=0; i<4; i++) writer.writeU32(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeSoftware(writer) {
|
function writeSoftware(writer) {
|
||||||
|
|
@ -321,6 +402,18 @@ function writeModel(writer, params) {
|
||||||
writer.writeF32(0);
|
writer.writeF32(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function writeSubLayerDefinitions(writer, layers) {
|
||||||
|
writer.writeTable("SUBIMGS", 24 + layers.length * 44);
|
||||||
|
writer.writeU32(layers.length);
|
||||||
|
writer.writeU32(1);
|
||||||
|
layers.forEach(layer => {
|
||||||
|
writer.writeU32(layer.dataOffset);
|
||||||
|
writer.writeU32(layer.dataLength);
|
||||||
|
writer.writeU32(layer.nonzero);
|
||||||
|
for (let i=0; i<8; i++) writer.writeF32(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createPreview(width, height) {
|
function createPreview(width, height) {
|
||||||
return {
|
return {
|
||||||
width,
|
width,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue