@@ -8,19 +8,27 @@ uses |
| 8 |
Classes, SysUtils, Controls, Graphics, Constants, LCLType, math, |
8 |
Classes, SysUtils, Controls, Graphics, Constants, LCLType, math, |
| 9 |
LCLIntf, LMessages, ClipboardUtils, HugeDatatypes; |
9 |
LCLIntf, LMessages, ClipboardUtils, HugeDatatypes; |
| 10 |
|
10 |
|
|
|
11 |
// TODO: Maybe read these from a config file |
| 11 |
const |
12 |
const |
| 12 |
clMisc = clMaroon; |
13 |
clNote = TColor($7F4A00); |
| 13 |
clPitch = clYellow; |
14 |
clInstrument = TColor($7F7F00); |
| 14 |
clVolume = clGreen; |
15 |
clVolume = TColor($99FFB7); |
| 15 |
clPan = clTeal; |
16 |
|
| 16 |
clSong = clRed; |
17 |
clFxMisc = TColor($3F3F7C); |
|
|
18 |
clFxPitch = TColor($006262); |
|
|
19 |
clFxVolume = TColor($007F26); |
|
|
20 |
clFxPan = clInstrument; |
|
|
21 |
clFxSong = TColor($00007F); |
|
|
22 |
|
|
|
23 |
NumColumns = 4; |
|
|
24 |
NumRows = 64; |
| 17 |
|
25 |
|
| 18 |
type |
26 |
type |
| 19 |
TCellPart = (cpNote, cpInstrument, cpVolume, cpEffect); |
27 |
TCellPart = (cpNote = 0, cpInstrument = 1, cpVolume = 2, cpEffect = 3); |
| 20 |
|
28 |
|
| 21 |
TSelectionPos = record |
29 |
TSelectionPos = record |
| 22 |
X, Y: Integer; |
30 |
X, Y: Integer; |
| 23 |
SelectedPart: set of TCellPart |
31 |
SelectedPart: TCellPart |
| 24 |
end; |
32 |
end; |
| 25 |
|
33 |
|
| 26 |
{ TTrackerGrid } |
34 |
{ TTrackerGrid } |
@@ -58,18 +66,13 @@ type |
| 58 |
|
66 |
|
| 59 |
function GetEffectColor(EffectCode: Integer): TColor; |
67 |
function GetEffectColor(EffectCode: Integer): TColor; |
| 60 |
function SelectionsToRect(S1, S2: TSelectionPos): TRect; |
68 |
function SelectionsToRect(S1, S2: TSelectionPos): TRect; |
|
|
69 |
function SelectionToRect(Selection: TSelectionPos): TRect; |
|
|
70 |
function MousePosToSelection(X, Y: Integer): TSelectionPos; |
| 61 |
|
71 |
|
| 62 |
public |
72 |
public |
| 63 |
Cursor, Other: TSelectionPos; |
73 |
Cursor, Other: TSelectionPos; |
| 64 |
SelectedRow: Integer; |
|
|
| 65 |
end; |
74 |
end; |
| 66 |
|
75 |
|
| 67 |
const |
|
|
| 68 |
NotePosition = 0; |
|
|
| 69 |
InstrumentPosition = 3; |
|
|
| 70 |
VolumePosition = 5; |
|
|
| 71 |
EffectPosition = 8; |
|
|
| 72 |
|
|
|
| 73 |
implementation |
76 |
implementation |
| 74 |
|
77 |
|
| 75 |
{ TTrackerGrid } |
78 |
{ TTrackerGrid } |
@@ -80,16 +83,15 @@ var |
| 80 |
begin |
83 |
begin |
| 81 |
inherited Create(AOwner); |
84 |
inherited Create(AOwner); |
| 82 |
|
85 |
|
| 83 |
ControlStyle := ControlStyle + [csCaptureMouse, csClickEvents, |
86 |
ControlStyle := ControlStyle + [csCaptureMouse, csClickEvents, csDoubleClicks]; |
| 84 |
csDoubleClicks]; |
|
|
| 85 |
Self.Parent := Parent; |
87 |
Self.Parent := Parent; |
| 86 |
|
88 |
|
| 87 |
// Kind of a hack |
89 |
// Kind of a hack |
| 88 |
with Canvas.Font do begin |
90 |
with Canvas.Font do begin |
| 89 |
Name := 'Pixelite'; |
91 |
Name := 'Pixelite'; |
| 90 |
Size := 12; |
92 |
Size := 12; |
| 91 |
ColumnWidth := GetTextWidth('C-501v64C01'); |
93 |
ColumnWidth := GetTextWidth('C-5 01v64C01 '); |
| 92 |
RowHeight := GetTextHeight('C-501v64C01'); |
94 |
RowHeight := GetTextHeight('C-5 01v64C01 '); |
| 93 |
|
95 |
|
| 94 |
CharHeight := RowHeight; |
96 |
CharHeight := RowHeight; |
| 95 |
CharWidth := GetTextWidth('C'); |
97 |
CharWidth := GetTextWidth('C'); |
@@ -123,7 +125,7 @@ begin |
| 123 |
Brush.Color := RGBToColor(206, 197, 181); |
125 |
Brush.Color := RGBToColor(206, 197, 181); |
| 124 |
FillRect(0, I*RowHeight, Width, (I+1)*RowHeight); |
126 |
FillRect(0, I*RowHeight, Width, (I+1)*RowHeight); |
| 125 |
end; |
127 |
end; |
| 126 |
if I = SelectedRow then begin |
128 |
if I = Cursor.Y then begin |
| 127 |
Brush.Color := RGBToColor(169, 153, 122); |
129 |
Brush.Color := RGBToColor(169, 153, 122); |
| 128 |
FillRect(0, I*RowHeight, Width, (I+1)*RowHeight); |
130 |
FillRect(0, I*RowHeight, Width, (I+1)*RowHeight); |
| 129 |
end; |
131 |
end; |
@@ -133,7 +135,7 @@ begin |
| 133 |
end; |
135 |
end; |
| 134 |
end; |
136 |
end; |
| 135 |
|
137 |
|
| 136 |
{Canvas.Pen.Color := RGBToColor(169, 153, 122); |
138 |
Canvas.Pen.Color := TColor($ABB7BC); |
| 137 |
Canvas.Pen.Width := 2; |
139 |
Canvas.Pen.Width := 2; |
| 138 |
R := TRect.Create(0, 0, ColumnWidth+1, Height); |
140 |
R := TRect.Create(0, 0, ColumnWidth+1, Height); |
| 139 |
Canvas.Rectangle(R); |
141 |
Canvas.Rectangle(R); |
@@ -144,15 +146,13 @@ begin |
| 144 |
R := TRect.Create(ColumnWidth*3, 0, ColumnWidth, Height); |
146 |
R := TRect.Create(ColumnWidth*3, 0, ColumnWidth, Height); |
| 145 |
Canvas.Rectangle(R); |
147 |
Canvas.Rectangle(R); |
| 146 |
R := TRect.Create(ColumnWidth*4, 0, ColumnWidth, Height); |
148 |
R := TRect.Create(ColumnWidth*4, 0, ColumnWidth, Height); |
| 147 |
Canvas.Rectangle(R);} |
149 |
Canvas.Rectangle(R); |
| 148 |
|
150 |
|
| 149 |
RenderSelectedArea; |
151 |
RenderSelectedArea; |
| 150 |
end; |
152 |
end; |
| 151 |
|
153 |
|
| 152 |
procedure TTrackerGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, |
154 |
procedure TTrackerGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, |
| 153 |
Y: Integer); |
155 |
Y: Integer); |
| 154 |
var |
|
|
| 155 |
SelectedColumn: Integer; |
|
|
| 156 |
begin |
156 |
begin |
| 157 |
inherited MouseDown(Button, Shift, X, Y); |
157 |
inherited MouseDown(Button, Shift, X, Y); |
| 158 |
|
158 |
|
@@ -162,13 +162,7 @@ begin |
| 162 |
if not (csDesigning in ComponentState) and CanFocus then |
162 |
if not (csDesigning in ComponentState) and CanFocus then |
| 163 |
SetFocus; |
163 |
SetFocus; |
| 164 |
|
164 |
|
| 165 |
SelectedRow := Round((Y/Height)*63); |
165 |
Cursor := MousePosToSelection(X, Y); |
| 166 |
SelectedColumn := Round((X/Width)*4); |
|
|
| 167 |
with Cursor do begin |
|
|
| 168 |
X := SelectedColumn; |
|
|
| 169 |
Y := SelectedRow; |
|
|
| 170 |
SelectedPart := []; |
|
|
| 171 |
end; |
|
|
| 172 |
|
166 |
|
| 173 |
ClampCursors; |
167 |
ClampCursors; |
| 174 |
Other := Cursor; |
168 |
Other := Cursor; |
@@ -177,20 +171,12 @@ begin |
| 177 |
end; |
171 |
end; |
| 178 |
|
172 |
|
| 179 |
procedure TTrackerGrid.MouseMove(Shift: TShiftState; X, Y: Integer); |
173 |
procedure TTrackerGrid.MouseMove(Shift: TShiftState; X, Y: Integer); |
| 180 |
var |
|
|
| 181 |
SelectedRow, SelectedColumn: Integer; |
|
|
| 182 |
begin |
174 |
begin |
| 183 |
inherited MouseMove(Shift, X, Y); |
175 |
inherited MouseMove(Shift, X, Y); |
| 184 |
|
176 |
|
| 185 |
if MouseButtonDown then begin |
177 |
if MouseButtonDown then begin |
| 186 |
Selecting := True; |
178 |
Selecting := True; |
| 187 |
SelectedRow := Round((Y/Height)*63); |
179 |
Other := MousePosToSelection(X, Y); |
| 188 |
SelectedColumn := Round((X/Width)*4); |
|
|
| 189 |
with Other do begin |
|
|
| 190 |
X := SelectedColumn; |
|
|
| 191 |
Y := SelectedRow; |
|
|
| 192 |
SelectedPart := []; |
|
|
| 193 |
end; |
|
|
| 194 |
|
180 |
|
| 195 |
ClampCursors; |
181 |
ClampCursors; |
| 196 |
|
182 |
|
@@ -210,13 +196,24 @@ procedure TTrackerGrid.KeyDown(var Key: Word; Shift: TShiftState); |
| 210 |
begin |
196 |
begin |
| 211 |
inherited KeyDown(Key, Shift); |
197 |
inherited KeyDown(Key, Shift); |
| 212 |
|
198 |
|
| 213 |
Selecting := False; |
199 |
Writeln(Cursor.SelectedPart, ' ', High(TCellPart), ' ', Low(TCellPart)); |
| 214 |
|
|
|
| 215 |
case Key of |
200 |
case Key of |
| 216 |
VK_UP: Cursor.Y -= 1; |
201 |
VK_UP: Cursor.Y -= 1; |
| 217 |
VK_DOWN: Cursor.Y += 1; |
202 |
VK_DOWN: Cursor.Y += 1; |
| 218 |
VK_LEFT: Cursor.X -= 1; |
203 |
VK_LEFT: begin |
| 219 |
VK_RIGHT: Cursor.X += 1; |
204 |
if ssCtrl in Shift then |
|
|
205 |
Cursor.X -= 1 |
|
|
206 |
else if Cursor.SelectedPart > Low(TCellPart) then begin |
|
|
207 |
Cursor.SelectedPart := Pred(Cursor.SelectedPart); |
|
|
208 |
end; |
|
|
209 |
end; |
|
|
210 |
VK_RIGHT: begin |
|
|
211 |
if ssCtrl in Shift then |
|
|
212 |
Cursor.X += 1 |
|
|
213 |
else if Cursor.SelectedPart < High(TCellPart) then begin |
|
|
214 |
Cursor.SelectedPart := Succ(Cursor.SelectedPart); |
|
|
215 |
end; |
|
|
216 |
end; |
| 220 |
else begin |
217 |
else begin |
| 221 |
with Cells[Cursor.X, Cursor.Y] do begin |
218 |
with Cells[Cursor.X, Cursor.Y] do begin |
| 222 |
Instrument := Random(20); |
219 |
Instrument := Random(20); |
@@ -227,8 +224,11 @@ begin |
| 227 |
end; |
224 |
end; |
| 228 |
end; |
225 |
end; |
| 229 |
|
226 |
|
|
|
227 |
if not (ssShift in Shift) then |
|
|
228 |
Other := Cursor; |
|
|
229 |
Selecting := ssShift in Shift; |
|
|
230 |
|
| 230 |
ClampCursors; |
231 |
ClampCursors; |
| 231 |
SelectedRow := Cursor.Y; |
|
|
| 232 |
|
232 |
|
| 233 |
Invalidate |
233 |
Invalidate |
| 234 |
end; |
234 |
end; |
@@ -249,7 +249,6 @@ procedure TTrackerGrid.RenderSelectedArea; |
| 249 |
var |
249 |
var |
| 250 |
R: TRect; |
250 |
R: TRect; |
| 251 |
begin |
251 |
begin |
| 252 |
if Selecting then begin |
|
|
| 253 |
R := SelectionsToRect(Cursor, Other); |
252 |
R := SelectionsToRect(Cursor, Other); |
| 254 |
|
253 |
|
| 255 |
with Cursor do begin; |
254 |
with Cursor do begin; |
@@ -264,19 +263,6 @@ begin |
| 264 |
R.Top, |
263 |
R.Top, |
| 265 |
DSTINVERT); |
264 |
DSTINVERT); |
| 266 |
end; |
265 |
end; |
| 267 |
end |
|
|
| 268 |
else |
|
|
| 269 |
with Cursor do |
|
|
| 270 |
BitBlt( |
|
|
| 271 |
Canvas.Handle, |
|
|
| 272 |
Cursor.X*ColumnWidth, |
|
|
| 273 |
Cursor.Y*RowHeight, |
|
|
| 274 |
ColumnWidth, |
|
|
| 275 |
RowHeight, |
|
|
| 276 |
Canvas.Handle, |
|
|
| 277 |
Cursor.X*ColumnWidth, |
|
|
| 278 |
Cursor.Y*RowHeight, |
|
|
| 279 |
DSTINVERT); |
|
|
| 280 |
end; |
266 |
end; |
| 281 |
|
267 |
|
| 282 |
procedure TTrackerGrid.ClampCursors; |
268 |
procedure TTrackerGrid.ClampCursors; |
@@ -306,7 +292,7 @@ var |
| 306 |
begin |
292 |
begin |
| 307 |
with Canvas do begin |
293 |
with Canvas do begin |
| 308 |
if NoteMap.TryGetData(Cell.Note, NoteString) then begin |
294 |
if NoteMap.TryGetData(Cell.Note, NoteString) then begin |
| 309 |
Font.Color := clBlue; |
295 |
Font.Color := clNote; |
| 310 |
TextOut(PenPos.X, PenPos.Y, NoteString); |
296 |
TextOut(PenPos.X, PenPos.Y, NoteString); |
| 311 |
end |
297 |
end |
| 312 |
else begin |
298 |
else begin |
@@ -314,8 +300,10 @@ begin |
| 314 |
TextOut(PenPos.X, PenPos.Y, '...'); |
300 |
TextOut(PenPos.X, PenPos.Y, '...'); |
| 315 |
end; |
301 |
end; |
| 316 |
|
302 |
|
|
|
303 |
TextOut(PenPos.X, PenPos.Y, ' '); |
|
|
304 |
|
| 317 |
if Cell.Instrument <> 0 then begin |
305 |
if Cell.Instrument <> 0 then begin |
| 318 |
Font.Color := clTeal; |
306 |
Font.Color := clInstrument; |
| 319 |
TextOut(PenPos.X, PenPos.Y, FormatFloat('00', Cell.Instrument)); |
307 |
TextOut(PenPos.X, PenPos.Y, FormatFloat('00', Cell.Instrument)); |
| 320 |
end |
308 |
end |
| 321 |
else begin |
309 |
else begin |
@@ -339,6 +327,8 @@ begin |
| 339 |
Font.Color := clGray; |
327 |
Font.Color := clGray; |
| 340 |
TextOut(PenPos.X, PenPos.Y, '...'); |
328 |
TextOut(PenPos.X, PenPos.Y, '...'); |
| 341 |
end; |
329 |
end; |
|
|
330 |
|
|
|
331 |
TextOut(PenPos.X, PenPos.Y, ' '); |
| 342 |
end; |
332 |
end; |
| 343 |
end; |
333 |
end; |
| 344 |
|
334 |
|
@@ -346,29 +336,73 @@ function TTrackerGrid.GetEffectColor(EffectCode: Integer): TColor; |
| 346 |
begin |
336 |
begin |
| 347 |
Result := clBlack; |
337 |
Result := clBlack; |
| 348 |
case EffectCode of |
338 |
case EffectCode of |
| 349 |
$0: Result := clMisc; |
339 |
$0: Result := clFxMisc; |
| 350 |
$1: Result := clPitch; |
340 |
$1: Result := clFxPitch; |
| 351 |
$2: Result := clPitch; |
341 |
$2: Result := clFxPitch; |
| 352 |
$3: Result := clPitch; |
342 |
$3: Result := clFxPitch; |
| 353 |
$4: Result := clPitch; |
343 |
$4: Result := clFxPitch; |
| 354 |
$5: Result := clSong; |
344 |
$5: Result := clFxSong; |
| 355 |
$6: Result := clMisc; |
345 |
$6: Result := clFxMisc; |
| 356 |
$7: Result := clMisc; |
346 |
$7: Result := clFxMisc; |
| 357 |
$8: Result := clPan; |
347 |
$8: Result := clFxPan; |
| 358 |
$9: Result := clSong; |
348 |
$9: Result := clFxSong; |
| 359 |
$A: Result := clVolume; |
349 |
$A: Result := clFxVolume; |
| 360 |
$B: Result := clSong; |
350 |
$B: Result := clFxSong; |
| 361 |
$C: Result := clVolume; |
351 |
$C: Result := clFxVolume; |
| 362 |
$D: Result := clSong; |
352 |
$D: Result := clFxSong; |
| 363 |
$E: Result := clMisc; |
353 |
$E: Result := clFxMisc; |
| 364 |
$F: Result := clSong; |
354 |
$F: Result := clFxSong; |
| 365 |
end; |
355 |
end; |
| 366 |
end; |
356 |
end; |
| 367 |
|
357 |
|
| 368 |
function TTrackerGrid.SelectionsToRect(S1, S2: TSelectionPos): TRect; |
358 |
function TTrackerGrid.SelectionsToRect(S1, S2: TSelectionPos): TRect; |
| 369 |
begin |
359 |
begin |
| 370 |
Result := TRect.Create(S1.X*ColumnWidth, S1.Y*RowHeight, S1.X*ColumnWidth + ColumnWidth, S1.Y*RowHeight + RowHeight); |
360 |
Result := SelectionToRect(S1); |
| 371 |
Result.Union(TRect.Create(S2.X*ColumnWidth, S2.Y*RowHeight, S2.X*ColumnWidth + ColumnWidth, S2.Y*RowHeight + RowHeight)); |
361 |
Result.Union(SelectionToRect(S2)); |
|
|
362 |
end; |
|
|
363 |
|
|
|
364 |
function TTrackerGrid.SelectionToRect(Selection: TSelectionPos): TRect; |
|
|
365 |
var |
|
|
366 |
CharLeft, CharRight: Integer; |
|
|
367 |
begin |
|
|
368 |
case Selection.SelectedPart of |
|
|
369 |
cpNote: begin |
|
|
370 |
CharLeft := 0; |
|
|
371 |
CharRight := 3; |
|
|
372 |
end; |
|
|
373 |
cpInstrument: begin |
|
|
374 |
CharLeft := 4; |
|
|
375 |
CharRight := 6 |
|
|
376 |
end; |
|
|
377 |
cpVolume: begin |
|
|
378 |
CharLeft := 6; |
|
|
379 |
CharRight := 9; |
|
|
380 |
end; |
|
|
381 |
cpEffect: begin |
|
|
382 |
CharLeft := 9; |
|
|
383 |
CharRight := 12; |
|
|
384 |
end; |
|
|
385 |
end; |
|
|
386 |
|
|
|
387 |
Result.Left := (Selection.X*ColumnWidth) + (CharLeft*CharWidth); |
|
|
388 |
Result.Right := (Selection.X*ColumnWidth) + (CharRight*CharWidth); |
|
|
389 |
Result.Top := (Selection.Y*RowHeight); |
|
|
390 |
Result.Bottom := (Selection.Y*RowHeight) + RowHeight; |
|
|
391 |
end; |
|
|
392 |
|
|
|
393 |
function TTrackerGrid.MousePosToSelection(X, Y: Integer): TSelectionPos; |
|
|
394 |
begin |
|
|
395 |
Result.X := Trunc((X/Width)*NumColumns); |
|
|
396 |
Result.Y := Trunc((Y/Height)*NumRows); |
|
|
397 |
|
|
|
398 |
X := (min(X, width-1) mod ColumnWidth); |
|
|
399 |
X := Trunc((X/ColumnWidth)*13); |
|
|
400 |
case X of |
|
|
401 |
0..3: Result.SelectedPart := cpNote; |
|
|
402 |
4..6: Result.SelectedPart := cpInstrument; |
|
|
403 |
7..9: Result.SelectedPart := cpVolume; |
|
|
404 |
10..12: Result.SelectedPart := cpEffect; |
|
|
405 |
end; |
| 372 |
end; |
406 |
end; |
| 373 |
|
407 |
|
| 374 |
end. |
408 |
end. |