Skip to content

Commit d99ed1c

Browse files
committed
Add image list window
1 parent 91b1cbd commit d99ed1c

File tree

2 files changed

+222
-1
lines changed

2 files changed

+222
-1
lines changed

src/imageList.ts

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
2+
namespace ImageList {
3+
4+
const WINDOW_CLASS = 'devtools.window.imagelist';
5+
6+
export function register() {
7+
ui.registerMenuItem('Image List', () => {
8+
getOrOpen();
9+
});
10+
}
11+
12+
export function getOrOpen() {
13+
const w = ui.getWindow(WINDOW_CLASS);
14+
if (w) {
15+
w.bringToFront();
16+
} else {
17+
open();
18+
}
19+
}
20+
21+
function open() {
22+
let startId = 14222;
23+
let nextId = 0;
24+
let showImageBorders = false;
25+
let primaryChecked = false;
26+
let secondaryChecked = false;
27+
let primaryColour = 4;
28+
let secondaryColour = 18;
29+
let ternaryColour = 30;
30+
31+
const width = ui.width - 64;
32+
const height = ui.height - 96;
33+
const window = ui.openWindow({
34+
classification: WINDOW_CLASS,
35+
title: 'Image List',
36+
x: (ui.width - width) / 2,
37+
y: (ui.height - height) / 2,
38+
width: width,
39+
height: height,
40+
minWidth: width,
41+
minHeight: height,
42+
maxWidth: 1500,
43+
maxHeight: 1200,
44+
widgets: [
45+
{ type: 'groupbox', x: 8, y: 16, width: 286, height: 100 },
46+
{ type: 'colourpicker', name: 'clrPrimary', onChange: c => onPrimaryColourChange(c), x: 16, y: 28, width: 12, height: 12 },
47+
{ type: 'checkbox', name: 'chkPrimary', x: 32, y: 28, width: 100, height: 14, isChecked: true, text: 'Primary' },
48+
{ type: 'colourpicker', name: 'clrSecondary', onChange: c => onSecondaryColourChange(c), x: 16, y: 42, width: 12, height: 12 },
49+
{ type: 'checkbox', name: 'chkSecondary', x: 32, y: 42, width: 100, height: 14, isChecked: true, text: 'Secondary' },
50+
{ type: 'colourpicker', name: 'clrTernary', onChange: c => onTernaryColourChange(c), x: 16, y: 56, width: 12, height: 12 },
51+
{ type: 'checkbox', x: 32, y: 56, width: 100, height: 14, text: 'Blend' },
52+
{ type: 'label', x: 16, y: 74, width: 50, height: 14, text: 'Palette:' },
53+
{ type: 'spinner', name: 'spnPalette', x: 68, y: 72, width: 100, height: 14, text: '0', onDecrement: () => onDecrementPalette(), onIncrement: () => onIncrementPalette() },
54+
{ type: 'label', x: 16, y: 92, width: 50, height: 14, text: 'Start ID:' },
55+
{ type: 'spinner', name: 'spnStartId', x: 68, y: 90, width: 100, height: 14, text: startId.toString(), onDecrement: () => onDecrementId(), onIncrement: () => onIncrementId() },
56+
{ type: 'button', x: 178, y: 90, width: 50, height: 14, text: 'Select', onClick: () => onSelectId() },
57+
{ type: 'custom', name: 'imageList', x: 8, y: 122, width: 200, height: 100, onDraw: function (g) { onDrawImages(this, g); } }
58+
],
59+
onUpdate: () => onUpdate()
60+
});
61+
62+
function onSelectId() {
63+
ui.showTextInput({
64+
title: 'Start ID',
65+
description: 'Type in the image ID to move to:',
66+
initialValue: startId.toString(),
67+
maxLength: 8,
68+
callback: text => {
69+
startId = parseInt(text) || 0
70+
}
71+
});
72+
}
73+
74+
function onPrimaryColourChange(c: number) {
75+
primaryColour = c;
76+
}
77+
78+
function onSecondaryColourChange(c: number) {
79+
secondaryColour = c;
80+
}
81+
82+
function onTernaryColourChange(c: number) {
83+
ternaryColour = c;
84+
}
85+
86+
function onDecrementPalette() {
87+
const paletteSpinner = window.findWidget<SpinnerWidget>('spnPalette');
88+
if (paletteSpinner) {
89+
if (primaryColour === undefined) {
90+
primaryColour = 0;
91+
}
92+
if (primaryColour > 0) {
93+
primaryColour--;
94+
}
95+
paletteSpinner.text = primaryColour.toString();
96+
}
97+
}
98+
99+
function onIncrementPalette() {
100+
const paletteSpinner = window.findWidget<SpinnerWidget>('spnPalette');
101+
if (paletteSpinner) {
102+
if (primaryColour === undefined) {
103+
primaryColour = 0;
104+
}
105+
if (primaryColour < 255) {
106+
primaryColour++;
107+
}
108+
paletteSpinner.text = primaryColour.toString();
109+
}
110+
}
111+
112+
function onDecrementId() {
113+
const startIdSpinner = window.findWidget<SpinnerWidget>('spnStartId');
114+
if (startIdSpinner && startId > 0) {
115+
startId = Math.max(0, startId - 32);
116+
startIdSpinner.text = startId.toString();
117+
}
118+
}
119+
120+
function onIncrementId() {
121+
const startIdSpinner = window.findWidget<SpinnerWidget>('spnStartId');
122+
if (startIdSpinner) {
123+
startId = nextId;
124+
startIdSpinner.text = startId.toString();
125+
}
126+
}
127+
128+
function onUpdate() {
129+
const imageList = window.findWidget<CustomWidget>('imageList');
130+
if (imageList) {
131+
imageList.width = window.width - (imageList.x * 2);
132+
imageList.height = window.height - imageList.y - 16;
133+
}
134+
135+
primaryChecked = window.findWidget<CheckboxWidget>('chkPrimary').isChecked || false;
136+
const primaryColourWidget = window.findWidget<ColourPickerWidget>('clrPrimary');
137+
if (primaryColourWidget) {
138+
primaryColourWidget.colour = primaryColour;
139+
}
140+
141+
secondaryChecked = window.findWidget<CheckboxWidget>('chkSecondary').isChecked || false;
142+
const secondaryColourWidget = window.findWidget<ColourPickerWidget>('clrSecondary');
143+
if (secondaryColourWidget) {
144+
secondaryColourWidget.colour = secondaryColour;
145+
}
146+
147+
const ternaryColourWidget = window.findWidget<ColourPickerWidget>('clrTernary');
148+
if (ternaryColourWidget) {
149+
ternaryColourWidget.colour = ternaryColour;
150+
}
151+
152+
const paletteSpinner = window.findWidget<SpinnerWidget>('spnPalette');
153+
if (primaryColour !== undefined) {
154+
paletteSpinner.text = primaryColour.toString();
155+
}
156+
}
157+
158+
function onDrawImages(widget: CustomWidget, g: GraphicsContext) {
159+
const margin = 2;
160+
const clipWidth = widget.width - 2 - margin;
161+
const clipHeight = widget.height - 2 - margin;
162+
163+
g.colour = 1;
164+
g.well(0, 0, widget.width, widget.height);
165+
g.clip(1 + margin, 1 + margin, clipWidth, clipHeight);
166+
167+
let id = startId;
168+
let x = 0;
169+
let y = 0;
170+
let width = clipWidth;
171+
let lineHeight = 0;
172+
let secondLineId: number | undefined = undefined;
173+
const output = { width: 0, height: 0 };
174+
while (y < clipHeight) {
175+
const img = g.getImage(id);
176+
if (img) {
177+
const remWidth = width - x;
178+
if (img.width > remWidth) {
179+
x = 0;
180+
y += lineHeight;
181+
lineHeight = 0;
182+
if (secondLineId === undefined) {
183+
secondLineId = id;
184+
}
185+
}
186+
187+
drawImage(g, img, x, y, output);
188+
189+
x += output.width;
190+
lineHeight = Math.max(lineHeight, output.height);
191+
}
192+
id++;
193+
}
194+
nextId = secondLineId || startId + 1;
195+
}
196+
197+
function drawImage(g: GraphicsContext, img: ImageInfo, x: number, y: number, output: { width: number, height: number }) {
198+
const sz = '{TINYFONT}' + img.id;
199+
g.colour = 2;
200+
g.text(sz, x, y)
201+
const textWidth = g.measureText(sz).width;
202+
y += 8;
203+
204+
if (showImageBorders) {
205+
g.stroke = 1;
206+
g.rect(x, y, img.width + 2, img.height + 2);
207+
}
208+
209+
g.colour = primaryChecked && secondaryChecked ? primaryColour : undefined;
210+
g.secondaryColour = secondaryChecked ? secondaryColour : undefined;
211+
g.paletteId = primaryChecked && !secondaryChecked ? primaryColour : undefined;
212+
g.ternaryColour = ternaryColour;
213+
g.image(img.id, x - img.offset.x + 1, y - img.offset.y + 1);
214+
215+
output.width = Math.max(textWidth + 4, img.width + 6);
216+
output.height = Math.max(8, img.height + 12);
217+
}
218+
}
219+
}

src/main.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ const main = () => {
77
}
88

99
EntityViewer.register();
10+
ImageList.register();
1011
NetworkMonitor.register();
1112

1213
if (DEBUG) {
1314
ui.closeAllWindows();
14-
NetworkMonitor.getOrOpen();
15+
// NetworkMonitor.getOrOpen();
16+
ImageList.getOrOpen();
1517
}
1618
};
1719

0 commit comments

Comments
 (0)