@fmsim/machine 2.0.0-beta.10 → 2.0.0-beta.100

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.
Files changed (152) hide show
  1. package/dist/agv.js +6 -2
  2. package/dist/agv.js.map +1 -1
  3. package/dist/carrier-manager.js +183 -0
  4. package/dist/carrier-manager.js.map +1 -0
  5. package/dist/carrier.js +99 -9
  6. package/dist/carrier.js.map +1 -1
  7. package/dist/conveyor-join.js +8 -2
  8. package/dist/conveyor-join.js.map +1 -1
  9. package/dist/conveyor.js +8 -0
  10. package/dist/conveyor.js.map +1 -1
  11. package/dist/crane.js +144 -1
  12. package/dist/crane.js.map +1 -1
  13. package/dist/factories/agv-3d.js +8 -9
  14. package/dist/factories/agv-3d.js.map +1 -1
  15. package/dist/factories/conveyor-3d.js +168 -81
  16. package/dist/factories/conveyor-3d.js.map +1 -1
  17. package/dist/factories/crane-3d.js +48 -12
  18. package/dist/factories/crane-3d.js.map +1 -1
  19. package/dist/factories/crane-rail-3d.js +6 -6
  20. package/dist/factories/crane-rail-3d.js.map +1 -1
  21. package/dist/factories/machine-3d.js +527 -181
  22. package/dist/factories/machine-3d.js.map +1 -1
  23. package/dist/factories/oht-3d.js +20 -20
  24. package/dist/factories/oht-3d.js.map +1 -1
  25. package/dist/factories/shuttle-3d.js +2 -5
  26. package/dist/factories/shuttle-3d.js.map +1 -1
  27. package/dist/factories/z-priority-defaults.js +33 -0
  28. package/dist/factories/z-priority-defaults.js.map +1 -0
  29. package/dist/factories/z-priority.js +54 -0
  30. package/dist/factories/z-priority.js.map +1 -0
  31. package/dist/features/conveyor-mixin.js.map +1 -1
  32. package/dist/features/mcs-status-default.js +15 -1
  33. package/dist/features/mcs-status-default.js.map +1 -1
  34. package/dist/features/mcs-status-mixin.js +22 -0
  35. package/dist/features/mcs-status-mixin.js.map +1 -1
  36. package/dist/features/mcs-zone-mixin.js.map +1 -1
  37. package/dist/features/parent-object-mixin.js +15 -7
  38. package/dist/features/parent-object-mixin.js.map +1 -1
  39. package/dist/floating-container.js +5 -0
  40. package/dist/floating-container.js.map +1 -1
  41. package/dist/index.js +52 -34
  42. package/dist/index.js.map +1 -1
  43. package/dist/mcs-carrier-holder.js +56 -22
  44. package/dist/mcs-carrier-holder.js.map +1 -1
  45. package/dist/mcs-machine.js +39 -0
  46. package/dist/mcs-machine.js.map +1 -1
  47. package/dist/mcs-unit.js +20 -0
  48. package/dist/mcs-unit.js.map +1 -1
  49. package/dist/mcs-vehicle.js +8 -3
  50. package/dist/mcs-vehicle.js.map +1 -1
  51. package/dist/node.js +10 -3
  52. package/dist/node.js.map +1 -1
  53. package/dist/oht.js +4 -0
  54. package/dist/oht.js.map +1 -1
  55. package/dist/port-flow.js +4 -0
  56. package/dist/port-flow.js.map +1 -1
  57. package/dist/port.js +4 -0
  58. package/dist/port.js.map +1 -1
  59. package/dist/scanner.js +30 -0
  60. package/dist/scanner.js.map +1 -0
  61. package/dist/scene/root-container-override.js +160 -96
  62. package/dist/scene/root-container-override.js.map +1 -1
  63. package/dist/shelf.js +4 -0
  64. package/dist/shelf.js.map +1 -1
  65. package/dist/static-container.js +5 -0
  66. package/dist/static-container.js.map +1 -1
  67. package/dist/stocker-abnormal-bar.js +5 -1
  68. package/dist/stocker-abnormal-bar.js.map +1 -1
  69. package/dist/stocker-capacity-bar.js +253 -6
  70. package/dist/stocker-capacity-bar.js.map +1 -1
  71. package/dist/stocker-carrier-bar.js +5 -1
  72. package/dist/stocker-carrier-bar.js.map +1 -1
  73. package/dist/stocker.js +6 -0
  74. package/dist/stocker.js.map +1 -1
  75. package/dist/templates/backdrop.js +30 -0
  76. package/dist/templates/backdrop.js.map +1 -0
  77. package/dist/templates/decal.js +21 -0
  78. package/dist/templates/decal.js.map +1 -0
  79. package/dist/templates/index.js +7 -1
  80. package/dist/templates/index.js.map +1 -1
  81. package/dist/templates/scanner.js +20 -0
  82. package/dist/templates/scanner.js.map +1 -0
  83. package/dist/tsconfig.tsbuildinfo +1 -1
  84. package/dist/utils/crane-position.js +83 -0
  85. package/dist/utils/crane-position.js.map +1 -0
  86. package/dist/utils/data-value.js +21 -0
  87. package/dist/utils/data-value.js.map +1 -0
  88. package/dist/utils/fit-gauge-scale.js +28 -0
  89. package/dist/utils/fit-gauge-scale.js.map +1 -0
  90. package/dist/utils/get-value-on-ranges.js +2 -4
  91. package/dist/utils/get-value-on-ranges.js.map +1 -1
  92. package/dist/utils/stocker-gauge.js +78 -0
  93. package/dist/utils/stocker-gauge.js.map +1 -0
  94. package/dist/zone-capacity-bar.js +3 -3
  95. package/dist/zone-capacity-bar.js.map +1 -1
  96. package/icons/backdrop.png +0 -0
  97. package/icons/decal.png +0 -0
  98. package/jest.config.js +10 -0
  99. package/package.json +4 -3
  100. package/src/agv.ts +7 -2
  101. package/src/carrier-manager.ts +223 -0
  102. package/src/carrier.ts +103 -10
  103. package/src/conveyor-join.ts +5 -2
  104. package/src/conveyor.ts +8 -0
  105. package/src/crane.ts +181 -1
  106. package/src/factories/agv-3d.ts +9 -10
  107. package/src/factories/conveyor-3d.ts +171 -84
  108. package/src/factories/crane-3d.ts +53 -12
  109. package/src/factories/crane-rail-3d.ts +8 -7
  110. package/src/factories/machine-3d.ts +616 -191
  111. package/src/factories/oht-3d.ts +20 -20
  112. package/src/factories/shuttle-3d.ts +2 -6
  113. package/src/factories/z-priority-defaults.ts +38 -0
  114. package/src/factories/z-priority.ts +60 -0
  115. package/src/features/conveyor-mixin.ts +1 -1
  116. package/src/features/mcs-status-default.ts +15 -1
  117. package/src/features/mcs-status-mixin.ts +26 -4
  118. package/src/features/mcs-zone-mixin.ts +1 -1
  119. package/src/features/parent-object-mixin.ts +17 -8
  120. package/src/floating-container.ts +5 -0
  121. package/src/index.ts +58 -34
  122. package/src/mcs-carrier-holder.ts +57 -34
  123. package/src/mcs-machine.ts +42 -0
  124. package/src/mcs-unit.ts +24 -1
  125. package/src/mcs-vehicle.ts +9 -6
  126. package/src/node.ts +9 -3
  127. package/src/oht.ts +6 -1
  128. package/src/port-flow.ts +5 -0
  129. package/src/port.ts +5 -0
  130. package/src/scanner.ts +29 -0
  131. package/src/scene/root-container-override.ts +154 -103
  132. package/src/shelf.ts +5 -0
  133. package/src/static-container.ts +5 -0
  134. package/src/stocker-abnormal-bar.ts +6 -1
  135. package/src/stocker-capacity-bar.ts +298 -7
  136. package/src/stocker-carrier-bar.ts +6 -1
  137. package/src/stocker.ts +7 -0
  138. package/src/templates/backdrop.ts +30 -0
  139. package/src/templates/decal.ts +21 -0
  140. package/src/templates/index.ts +7 -1
  141. package/src/templates/scanner.ts +20 -0
  142. package/src/utils/crane-position.ts +105 -0
  143. package/src/utils/data-value.ts +19 -0
  144. package/src/utils/fit-gauge-scale.ts +35 -0
  145. package/src/utils/get-value-on-ranges.ts +2 -4
  146. package/src/utils/stocker-gauge.ts +111 -0
  147. package/src/zone-capacity-bar.ts +3 -3
  148. package/translations/en.json +26 -1
  149. package/translations/ja.json +26 -1
  150. package/translations/ko.json +26 -1
  151. package/translations/ms.json +26 -1
  152. package/translations/zh.json +26 -1
@@ -0,0 +1,111 @@
1
+ /*
2
+ * 스토커 게이지 세그먼트 계산 (2D/3D 공통 단일 소스).
3
+ *
4
+ * 2D(StockerCapacityBar) 와 3D(machine-3d buildGauge) 가 각자 세그먼트 비율/색상을
5
+ * 중복 계산하면 필드/색상 drift 가 발생한다(실제로 carrier 필드명이 어긋난 전례).
6
+ * 이 모듈이 carrier/abnormal 세그먼트 계산의 단일 소스이며 순수 함수라 단위 테스트가
7
+ * 용이하다. 표현(라벨 포맷·watermark·테두리색)은 렌더러별로 다르므로 여기서 다루지 않는다.
8
+ *
9
+ * canonical 데이터 필드(2D 기준):
10
+ * - carrier : CARRIER_FULL / CARRIER_EMPTY / CARRIER_EMPTY_EMPTY
11
+ * - abnormal : CARRIER_NORMAL / CARRIER_ABNORMAL
12
+ */
13
+
14
+ import { Legend } from '../features/mcs-status-default'
15
+
16
+ export type StockerGaugeMode = 'capacity' | 'carrier' | 'abnormal'
17
+
18
+ export interface GaugeSegment {
19
+ /** 세그먼트 라벨(2D per-segment 표시용, '\n' 은 줄바꿈). */
20
+ label: string
21
+ /** 카운트 원본값. */
22
+ count: number
23
+ /** 전체 대비 비율 (0~1). total 이 0 이면 0. */
24
+ ratio: number
25
+ /** 채움 색상. */
26
+ color: string
27
+ }
28
+
29
+ /** carrier 세그먼트 색상 (2D/3D 공통). LEGEND_CARRIER 기본값과 동일 — 테마 미지정 시 폴백. */
30
+ export const CARRIER_COLORS = {
31
+ full: '#4AA7FE',
32
+ empty: '#8BDA5B',
33
+ emptyEmpty: '#019D59'
34
+ }
35
+
36
+ export interface CarrierColors {
37
+ full: string
38
+ empty: string
39
+ emptyEmpty: string
40
+ }
41
+
42
+ /**
43
+ * carrier legend(테마)에서 full/empty/emptyEmpty 색상 추출.
44
+ * carrier 컴포넌트의 색 취득 로직(statusColor = legend[status] || legend.default)과 동일하게,
45
+ * status 키(FULL/EMPTY/EMPTYEMPTY)로 직접 조회한다. 키/default 모두 없으면 CARRIER_COLORS 로 폴백.
46
+ */
47
+ export function carrierColorsFromLegend(legend?: Legend): CarrierColors {
48
+ const pick = (key: string, fallback: string) => (legend && (legend[key] || legend.default)) || fallback
49
+ return {
50
+ full: pick('FULL', CARRIER_COLORS.full),
51
+ empty: pick('EMPTY', CARRIER_COLORS.empty),
52
+ emptyEmpty: pick('EMPTYEMPTY', CARRIER_COLORS.emptyEmpty)
53
+ }
54
+ }
55
+
56
+ /** abnormal 세그먼트 색상 (2D/3D 공통). */
57
+ export const ABNORMAL_COLORS = {
58
+ normal: '#8BDA5B',
59
+ abnormal: '#F4B4B4'
60
+ }
61
+
62
+ function num(v: unknown): number {
63
+ const n = Number(v)
64
+ return Number.isFinite(n) && n > 0 ? n : 0
65
+ }
66
+
67
+ /**
68
+ * 캐리어 상태 세그먼트 (Full / Empty / EmptyEmpty). total 0 이면 모든 ratio 0.
69
+ * colors 미지정 시 CARRIER_COLORS(기본). 테마 색은 carrierColorsFromLegend 로 만들어 전달.
70
+ */
71
+ export function carrierSegments(
72
+ full: unknown,
73
+ empty: unknown,
74
+ emptyEmpty: unknown,
75
+ colors: CarrierColors = CARRIER_COLORS
76
+ ): GaugeSegment[] {
77
+ const f = num(full)
78
+ const e = num(empty)
79
+ const ee = num(emptyEmpty)
80
+ const total = f + e + ee
81
+ const r = (c: number) => (total > 0 ? c / total : 0)
82
+ return [
83
+ { label: 'Full', count: f, ratio: r(f), color: colors.full },
84
+ { label: 'Empty', count: e, ratio: r(e), color: colors.empty },
85
+ { label: 'Empty\nEmpty', count: ee, ratio: r(ee), color: colors.emptyEmpty }
86
+ ]
87
+ }
88
+
89
+ /** 캐리어 정상/비정상 세그먼트 (Normal / Abnormal). total 0 이면 모든 ratio 0. */
90
+ export function abnormalSegments(normal: unknown, abnormal: unknown): GaugeSegment[] {
91
+ const n = num(normal)
92
+ const a = num(abnormal)
93
+ const total = n + a
94
+ const r = (c: number) => (total > 0 ? c / total : 0)
95
+ return [
96
+ { label: 'Normal', count: n, ratio: r(n), color: ABNORMAL_COLORS.normal },
97
+ { label: 'Abnormal', count: a, ratio: r(a), color: ABNORMAL_COLORS.abnormal }
98
+ ]
99
+ }
100
+
101
+ /** 캐리어 세그먼트 — canonical raw data(CARRIER_*) 에서 직접. 3D 처럼 raw data 소스용. */
102
+ export function carrierSegmentsFromData(data: any, colors?: CarrierColors): GaugeSegment[] {
103
+ const d = data && typeof data === 'object' ? data : {}
104
+ return carrierSegments(d.CARRIER_FULL, d.CARRIER_EMPTY, d.CARRIER_EMPTY_EMPTY, colors)
105
+ }
106
+
107
+ /** 비정상 세그먼트 — canonical raw data(CARRIER_*) 에서 직접. */
108
+ export function abnormalSegmentsFromData(data: any): GaugeSegment[] {
109
+ const d = data && typeof data === 'object' ? data : {}
110
+ return abnormalSegments(d.CARRIER_NORMAL, d.CARRIER_ABNORMAL)
111
+ }
@@ -2,7 +2,7 @@ import { Component, ComponentNature, POSITION, Properties, sceneComponent } from
2
2
  import { themesColorRange } from '@fmsim/api'
3
3
  import { LEGEND_CAPACITY } from './features/mcs-status-default'
4
4
  import { safeRound } from './utils/safe-round'
5
- import { getVaueOnRanges } from './utils/get-value-on-ranges'
5
+ import { getValueOnRanges } from './utils/get-value-on-ranges'
6
6
  import { MCSZoneMixin, MCSZoneMixinProperties } from './features/mcs-zone-mixin'
7
7
  import { ParentObjectMixinProperties } from './features/parent-object-mixin'
8
8
  import MCSUnit from './mcs-unit'
@@ -104,7 +104,7 @@ export default class ZoneCapacityBar extends MCSZoneMixin(MCSUnit) {
104
104
 
105
105
  get statusColor() {
106
106
  const { fullup } = this.state
107
- return fullup ? 'red' : getVaueOnRanges(this.usage, this.legend)
107
+ return fullup ? 'red' : getValueOnRanges(this.usage, this.legend)
108
108
  }
109
109
 
110
110
  get text() {
@@ -282,7 +282,7 @@ export default class ZoneCapacityBar extends MCSZoneMixin(MCSUnit) {
282
282
  HIGHWATERMARK = 100,
283
283
  LOWWATERMARK = 0,
284
284
  FULLUP = 'F'
285
- } = typeof this.data == 'object' ? this.data : {}
285
+ } = this.data && typeof this.data == 'object' ? this.data : {}
286
286
 
287
287
  const currentUsage = Number(CURRENTCAPACITY) || 0
288
288
  const maxCapacity = Number(MAXCAPACITY) || 100
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "label.current-usage": "current usage",
3
3
  "label.fullup": "fullup",
4
+ "label.carrier-full": "carrier full",
5
+ "label.carrier-empty": "carrier empty",
6
+ "label.carrier-empty-empty": "carrier empty empty",
7
+ "label.carrier-normal": "carrier normal",
8
+ "label.carrier-abnormal": "carrier abnormal",
4
9
  "label.high-watermark": "high watermark",
5
10
  "label.legend-name": "legend",
6
11
  "label.max-capacity": "max capacity",
@@ -46,5 +51,25 @@
46
51
  "label.node-machine": "node machine",
47
52
  "label.nodes": "nodes",
48
53
  "label.vehicle-animation": "vehicle animation",
49
- "label.battery-rate-legend-name": "battery rate"
54
+ "label.battery-rate-legend-name": "battery rate",
55
+ "label.conveyor-orientation": "Transfer Direction",
56
+ "component.backdrop": "backdrop",
57
+ "label.fit-to-board": "Fit to Board",
58
+ "label.see-through": "see-through",
59
+ "label.east": "East",
60
+ "label.west": "West",
61
+ "label.north": "North",
62
+ "label.south": "South",
63
+ "label.floor": "Floor",
64
+ "label.ceiling": "Ceiling",
65
+ "label.visible": "Visible",
66
+ "label.alpha": "Alpha",
67
+ "label.rotation": "Rotation",
68
+ "label.mirror": "Mirror",
69
+ "label.copy-to-opposite": "Copy to opposite",
70
+ "label.copy-to-walls": "Copy to all walls",
71
+ "label.light-preset": "light preset",
72
+ "label.dark": "dark",
73
+ "label.medium": "medium",
74
+ "label.bright": "bright"
50
75
  }
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "label.current-usage": "current usage",
3
3
  "label.fullup": "fullup",
4
+ "label.carrier-full": "carrier full",
5
+ "label.carrier-empty": "carrier empty",
6
+ "label.carrier-empty-empty": "carrier empty empty",
7
+ "label.carrier-normal": "carrier normal",
8
+ "label.carrier-abnormal": "carrier abnormal",
4
9
  "label.high-watermark": "high watermark",
5
10
  "label.low-watermark": "low watermark",
6
11
  "label.legend-name": "legend",
@@ -48,5 +53,25 @@
48
53
  "label.node-machine": "node machine",
49
54
  "label.nodes": "nodes",
50
55
  "label.vehicle-animation": "vehicle animation",
51
- "label.battery-rate-legend-name": "battery rate"
56
+ "label.battery-rate-legend-name": "battery rate",
57
+ "label.conveyor-orientation": "搬送方向",
58
+ "component.backdrop": "バックドロップ",
59
+ "label.fit-to-board": "ボードに合わせる",
60
+ "label.see-through": "透過",
61
+ "label.east": "東壁",
62
+ "label.west": "西壁",
63
+ "label.north": "北壁",
64
+ "label.south": "南壁",
65
+ "label.floor": "床",
66
+ "label.ceiling": "天井",
67
+ "label.visible": "表示",
68
+ "label.alpha": "透明度",
69
+ "label.rotation": "回転",
70
+ "label.mirror": "鏡像",
71
+ "label.copy-to-opposite": "反対側にコピー",
72
+ "label.copy-to-walls": "壁4面にコピー",
73
+ "label.light-preset": "照明プリセット",
74
+ "label.dark": "暗",
75
+ "label.medium": "中",
76
+ "label.bright": "明"
52
77
  }
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "label.current-usage": "현재 사용량",
3
3
  "label.fullup": "만재",
4
+ "label.carrier-full": "적재 캐리어",
5
+ "label.carrier-empty": "공 캐리어",
6
+ "label.carrier-empty-empty": "이중 공 캐리어",
7
+ "label.carrier-normal": "정상 캐리어",
8
+ "label.carrier-abnormal": "비정상 캐리어",
4
9
  "label.high-watermark": "고수위워터마크",
5
10
  "label.low-watermark": "저수위워터마크",
6
11
  "label.legend-name": "레전드",
@@ -49,5 +54,25 @@
49
54
  "label.node-machine": "node machine",
50
55
  "label.nodes": "nodes",
51
56
  "label.vehicle-animation": "vehicle animation",
52
- "label.battery-rate-legend-name": "배터리 잔량"
57
+ "label.battery-rate-legend-name": "배터리 잔량",
58
+ "label.conveyor-orientation": "이송방향",
59
+ "component.backdrop": "배경",
60
+ "label.fit-to-board": "보드에 맞춤",
61
+ "label.see-through": "투과",
62
+ "label.east": "동측 벽",
63
+ "label.west": "서측 벽",
64
+ "label.north": "북측 벽",
65
+ "label.south": "남측 벽",
66
+ "label.floor": "바닥",
67
+ "label.ceiling": "천장",
68
+ "label.visible": "표시",
69
+ "label.alpha": "투명도",
70
+ "label.rotation": "회전",
71
+ "label.mirror": "거울상",
72
+ "label.copy-to-opposite": "반대편에 복사",
73
+ "label.copy-to-walls": "벽 4면에 복사",
74
+ "label.light-preset": "조명 프리셋",
75
+ "label.dark": "어두움",
76
+ "label.medium": "중간",
77
+ "label.bright": "밝음"
53
78
  }
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "label.current-usage": "current usage",
3
3
  "label.fullup": "fullup",
4
+ "label.carrier-full": "carrier full",
5
+ "label.carrier-empty": "carrier empty",
6
+ "label.carrier-empty-empty": "carrier empty empty",
7
+ "label.carrier-normal": "carrier normal",
8
+ "label.carrier-abnormal": "carrier abnormal",
4
9
  "label.high-watermark": "high watermark",
5
10
  "label.low-watermark": "low watermark",
6
11
  "label.legend-name": "legend",
@@ -48,5 +53,25 @@
48
53
  "label.node-machine": "node machine",
49
54
  "label.nodes": "nodes",
50
55
  "label.vehicle-animation": "vehicle animation",
51
- "label.battery-rate-legend-name": "battery rate"
56
+ "label.battery-rate-legend-name": "battery rate",
57
+ "label.conveyor-orientation": "Transfer Direction",
58
+ "component.backdrop": "Backdrop",
59
+ "label.fit-to-board": "Muat Papan",
60
+ "label.see-through": "tembus pandang",
61
+ "label.east": "Timur",
62
+ "label.west": "Barat",
63
+ "label.north": "Utara",
64
+ "label.south": "Selatan",
65
+ "label.floor": "Lantai",
66
+ "label.ceiling": "Siling",
67
+ "label.visible": "Kelihatan",
68
+ "label.alpha": "Alfa",
69
+ "label.rotation": "Putaran",
70
+ "label.mirror": "Cermin",
71
+ "label.copy-to-opposite": "Salin ke bertentangan",
72
+ "label.copy-to-walls": "Salin ke semua dinding",
73
+ "label.light-preset": "pratetapan cahaya",
74
+ "label.dark": "gelap",
75
+ "label.medium": "sederhana",
76
+ "label.bright": "cerah"
52
77
  }
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "label.current-usage": "current usage",
3
3
  "label.fullup": "fullup",
4
+ "label.carrier-full": "carrier full",
5
+ "label.carrier-empty": "carrier empty",
6
+ "label.carrier-empty-empty": "carrier empty empty",
7
+ "label.carrier-normal": "carrier normal",
8
+ "label.carrier-abnormal": "carrier abnormal",
4
9
  "label.high-watermark": "high watermark",
5
10
  "label.low-watermark": "low watermark",
6
11
  "label.legend-name": "legend",
@@ -48,5 +53,25 @@
48
53
  "label.node-machine": "node machine",
49
54
  "label.nodes": "nodes",
50
55
  "label.vehicle-animation": "vehicle animation",
51
- "label.battery-rate-legend-name": "battery rate"
56
+ "label.battery-rate-legend-name": "battery rate",
57
+ "label.conveyor-orientation": "输送方向",
58
+ "component.backdrop": "背景",
59
+ "label.fit-to-board": "适配画板",
60
+ "label.see-through": "透视",
61
+ "label.east": "东墙",
62
+ "label.west": "西墙",
63
+ "label.north": "北墙",
64
+ "label.south": "南墙",
65
+ "label.floor": "地板",
66
+ "label.ceiling": "天花板",
67
+ "label.visible": "显示",
68
+ "label.alpha": "透明度",
69
+ "label.rotation": "旋转",
70
+ "label.mirror": "镜像",
71
+ "label.copy-to-opposite": "复制到对面",
72
+ "label.copy-to-walls": "复制到4面墙",
73
+ "label.light-preset": "灯光预设",
74
+ "label.dark": "昏暗",
75
+ "label.medium": "适中",
76
+ "label.bright": "明亮"
52
77
  }