8 void putChar(unsigned char character
,int x
,int y
,int red
,int blue
) {
9 unsigned short *ptr
= ((unsigned short *)output
) + x
+ y
*outWidth
;
10 unsigned short put
= (blue
<<8)+red
;
12 for(i
=0;i
<8;i
++,ptr
+= outWidth
-8)
13 for(j
=0;j
<8;j
++,ptr
++)
14 if (font
[character
*8+i
] & (128>>j
))
18 void putString(char *string
,int x
,int y
,int red
,int blue
) {
19 if (x
< 0 || y
< 0 || y
>= outHeight
-8)
21 for(;*string
&& x
<= outWidth
-8;string
++,x
+=8)
22 putChar((unsigned char)(*string
),x
,y
,red
,blue
);
28 int visibleMask
, activeMask
;
29 double x
,y
,width
,height
;
32 virtual int go(bool mouseDown
,bool mouseClick
,bool mouseOver
,
33 double x
, double y
, double scale
, char &hotKey
, int &action
)
36 virtual void handleKey(char key
, int &action
) = 0;
39 struct Button
: public UIObject
{
45 Button(int _am
,int _vm
,double _x
,double _y
,
46 double _size
,int _icon
,char _key
= 0,
47 bool _passive
= false, bool _bright
= false) {
48 activeMask
= _am
; visibleMask
= _vm
;
49 x
= _x
; y
= _y
; width
= height
= _size
;
50 icon
= _icon
; hotKey
= _key
; passive
= _passive
; bright
= _bright
;
53 int go(bool mouseDown
,bool mouseClick
,bool mouseOver
,
54 double _x
, double _y
, double scale
, char &_hotKey
, int &action
) {
57 (bright
? 0x0404 : 0x0200),
58 x
*scale
,y
*scale
,width
*scale
,height
*scale
);
60 if (mouseOver
&& !passive
)
64 (x
-IconWidths
[icon
]*width
/2)*scale
,
65 (y
-height
/2)*scale
,width
*scale
*2,height
*scale
*2);
67 if (mouseOver
&& mouseClick
&& !passive
)
70 if (mouseOver
&& !passive
&& hotKey
)
76 void handleKey(char key
, int &action
) {
77 if (key
== hotKey
&& !passive
)
82 struct PopperUpper
: public UIObject
{
85 PopperUpper(int _am
,int _vm
,double _x
,double _y
,
86 double _width
,double _height
, int _maskAdd
) {
87 activeMask
= _am
; visibleMask
= _vm
;
88 x
= _x
; y
= _y
; width
= _width
; height
= _height
;
92 int go(bool mouseDown
,bool mouseClick
,bool mouseOver
,
93 double _x
, double _y
, double scale
, char &_hotKey
, int &action
) {
97 x
*scale
,y
*scale
,width
*scale
,height
*scale
);
99 return mouseOver
? maskAdd
: 0;
102 void handleKey(char key
, int &action
) { }
106 struct SliderBar
: public UIObject
{
108 char leftKey
, rightKey
;
110 typedef void (*Callback
)(double v
);
113 SliderBar(int _am
,int _vm
,double _x
,double _y
,
114 double _width
,double _height
, double *_value
,
115 Callback _callback
, char _leftKey
, char _rightKey
) {
116 activeMask
= _am
; visibleMask
= _vm
;
117 x
= _x
; y
= _y
; width
= _width
; height
= _height
;
118 value
= _value
; callback
= _callback
;
119 leftKey
= _leftKey
; rightKey
= _rightKey
;
122 int go(bool mouseDown
,bool mouseClick
,bool mouseOver
,
123 double _x
, double _y
, double scale
, char &_hotKey
, int &action
) {
127 x
*scale
,y
*scale
,width
*scale
,height
*scale
);
131 (x
+*value
*width
-IconWidths
[Slider
]*height
/2)*scale
,
132 y
*scale
,height
*scale
,height
*scale
);
135 double newValue
= (_x
)/(width
);
136 if (newValue
< 0.0) newValue
= 0.0;
137 if (newValue
> 1.0) newValue
= 1.0;
142 (x
+newValue
*width
-IconWidths
[Selector
]*height
/2)*scale
,
143 y
*scale
,height
*scale
,height
*scale
);
153 _hotKey
= (newValue
< *value
? leftKey
: rightKey
);
159 void handleKey(char key
, int &action
) {
160 if (key
== leftKey
|| key
== rightKey
) {
161 if (key
== leftKey
) {
162 if (*value
== 0.0) return;
164 if (*value
< 0.0) *value
= 0.0;
166 if (*value
== 1.0) return;
168 if (*value
> 1.0) *value
= 1.0;
177 //Dodgy, uses some globals
178 struct TrackSelector
: public UIObject
{
181 TrackSelector(int _am
,int _vm
,double _x
,double _y
,
182 double _width
,double _height
) {
183 activeMask
= _am
; visibleMask
= _vm
;
184 x
= _x
; y
= _y
; width
= _width
; height
= _height
;
187 int go(bool mouseDown
,bool mouseClick
,bool mouseOver
,
188 double _x
, double _y
, double scale
, char &_hotKey
, int &action
) {
189 int count
= cdGetTrackCount();
190 if (count
== 0) return 0;
194 position
= int(_x
/width
*count
)+1;
200 _hotKey
= '0' + position
;
201 else if (position
== 10)
205 for(int i
=0;i
<count
;i
++)
208 (i
+1==position
?0x0003:(i
+1==track
?0x0202:0x0100)),
209 x
*scale
+i
*width
*scale
/count
,
211 width
*scale
/count
/IconWidths
[TrackSelect
],
217 void handleKey(char key
, int &action
) {
218 if (key
>= '1' && key
<= '9')
225 static UIObject
*uiObjects
;
226 static Button
*stateButton
, *starsButton
, *waveButton
, *flameButton
,
227 *starButton
, *diamondButton
;
228 static TrackSelector
*trackSelector
;
229 static int mouseButtons
;
231 void setupPalette(double dummy
=0.0) {
232 #define BOUND(x) ((x) > 255 ? 255 : (x))
233 #define PEAKIFY(x) int(BOUND((x) - (x)*(255-(x))/255/2))
234 #define MAX(x,y) ((x) > (y) ? (x) : (y))
236 unsigned char palette
[768];
238 double scale
, fgRed
, fgGreen
, fgBlue
, bgRed
, bgGreen
, bgBlue
;
240 fgGreen
= fgGreenSlider
;
241 fgBlue
= 1.0 - MAX(fgRedSlider
,fgGreenSlider
);
242 //scale = MAX(MAX(fgRed,fgGreen),fgBlue);
243 scale
= (fgRed
+fgGreen
+fgBlue
)/2.0;
249 bgGreen
= bgGreenSlider
;
250 bgBlue
= 1.0 - MAX(bgRedSlider
,bgGreenSlider
);
251 //scale = MAX(MAX(bgRed,bgGreen),bgBlue);
252 scale
= (bgRed
+bgGreen
+bgBlue
)/2.0;
258 int f
= i
&15, b
= i
/16;
259 //palette[i*3+0] = PEAKIFY(b*bgRed*16+f*fgRed*16);
260 //palette[i*3+1] = PEAKIFY(b*bgGreen*16+f*fgGreen*16);
261 //palette[i*3+2] = PEAKIFY(b*bgBlue*16+f*fgBlue*16);
263 double red
= b
*bgRed
*16+f
*fgRed
*16;
264 double green
= b
*bgGreen
*16+f
*fgGreen
*16;
265 double blue
= b
*bgBlue
*16+f
*fgBlue
*16;
268 for(int j
=0;j
<5;j
++) {
273 if (red
> 255) { excess
+= red
-255; red
= 255; }
274 if (green
> 255) { excess
+= green
-255; green
= 255; }
275 if (blue
> 255) { excess
+= blue
-255; blue
= 255; }
278 double scale
= (0.5 + (red
+green
+blue
)/768.0) / 1.5;
283 palette
[i
*3+0] = BOUND(int(red
));
284 palette
[i
*3+1] = BOUND(int(green
));
285 palette
[i
*3+2] = BOUND(int(blue
));
287 screen
->setPalette(palette
);
290 void setTrackProgress(double progress
) {
291 int interval
= cdGetTrackFrame(track
+1)-cdGetTrackFrame(track
);
292 if (interval
<= 0) return;
293 cdPlay(cdGetTrackFrame(track
)+int(interval
*progress
));
311 static int visibleMask
, cdCheckCountDown
;
312 static int mouseX
, mouseY
, lastX
, lastY
, countDown
;
314 void addUI(UIObject
*obj
) {
315 obj
->next
= uiObjects
;
320 #define SliderSize 0.125
321 void interfaceInit() {
324 //addUI(new Button(ALL,0.025,0.525,IconSize, 0, 'x'));
325 addUI(new PopperUpper(ALL
,ALL
,0,0,0.25,0.25, BUTTONBAR
));
326 addUI(stateButton
= new Button(ALL
,ALL
,0.05,0.025,IconSize
, 0, 0, true, false));
328 addUI(new PopperUpper(ALL
,BUTTONBAR
,x
=0.25,y
=0,1.375,0.25, BUTTONBAR
));
329 x
+= 0.1; y
+= 0.025;
330 addUI(new Button(PLAYING
|PAUSED
,BUTTONBAR
,x
,y
,IconSize
, SkipBack
, '['));
331 addUI(new Button(PAUSED
|STOPPED
|OPEN
,BUTTONBAR
,x
+= IconSize
,y
,IconSize
, Play
, 'p'));
332 addUI(new Button(PLAYING
,BUTTONBAR
,x
,y
,IconSize
, Pause
, 'p'));
333 addUI(new Button(PLAYING
|PAUSED
|OPEN
,BUTTONBAR
,x
+= IconSize
,y
,IconSize
, Stop
, 's'));
334 addUI(new Button(PLAYING
|PAUSED
,BUTTONBAR
,x
+= IconSize
,y
,IconSize
, SkipFwd
, ']'));
335 addUI(new Button(PLAYING
|PAUSED
|STOPPED
|NOCD
, BUTTONBAR
,
336 x
+= IconSize
,y
,IconSize
, Open
, 'e'));
337 addUI(new Button(ALL
, BUTTONBAR
,x
+= IconSize
,y
,IconSize
, Exit
, 'q'));
339 addUI(new PopperUpper(PLAYING
|PAUSED
|STOPPED
, ALL
,0,0.25,0.25,0.25, TRACKBAR
));
340 addUI(new PopperUpper(PLAYING
|PAUSED
|STOPPED
, TRACKBAR
,x
=0.25,y
=0.25,1.0,0.625, TRACKBAR
));
342 addUI(trackSelector
= new TrackSelector(PLAYING
|PAUSED
|STOPPED
, TRACKBAR
,x
,y
,0.75,0.25));
343 addUI(new SliderBar(PLAYING
|PAUSED
, TRACKBAR
,x
,y
+=0.25,0.75,0.25,
344 &trackProgress
,setTrackProgress
,'{','}'));
346 addUI(new PopperUpper(ALL
,ALL
,0,0.5,0.25,0.25, DIALBAR
));
347 addUI(new Button(ALL
,ALL
,0.05,0.525,IconSize
, Bulb
, 0, true, false));
349 addUI(new PopperUpper(ALL
,DIALBAR
,x
=0.25,y
=0.0,1.25,1.0, DIALBAR
));
350 x
+= 0.05; y
+= 0.025;
352 addUI(starsButton
= new Button(ALL
,DIALBAR
,x
,y
,IconSize
, Stars
, 'd'));
353 addUI(waveButton
= new Button(ALL
,DIALBAR
,x
+IconSize
,y
,IconSize
, Wave
, 'f'));
354 addUI(flameButton
= new Button(ALL
,DIALBAR
,x
+IconSize
*2.5,y
,IconSize
, Flame
, 'g'));
356 addUI(starButton
= new Button(ALL
,DIALBAR
,x
+IconSize
*3.5,y
,IconSize
, Star
, 'h'));
357 addUI(diamondButton
= new Button(ALL
,DIALBAR
,x
+IconSize
*4.5,y
,IconSize
, Diamond
, 'j'));
359 addUI(new Button(ALL
,DIALBAR
,x
+0.4,y
+0.8,IconSize
, Save
, '?'));
360 addUI(new Button(ALL
,DIALBAR
,x
+0.65,y
+0.8,IconSize
, Reset
, '/'));
364 addUI(new Button(ALL
,DIALBAR
,x
,y
-0.05,IconSize
, Bulb
, 0, true));
365 addUI(new SliderBar(ALL
,DIALBAR
,
366 x
+IconSize
,y
, 0.75, SliderSize
, &brightnessTwiddler
, 0, 'z', 'x'));
368 addUI(new Button(ALL
,DIALBAR
,x
,y
+SliderSize
*1,IconSize
, Size
, 'x', true));
369 addUI(new SliderBar(ALL
,DIALBAR
,
370 x
+IconSize
,y
+SliderSize
, 0.75, SliderSize
, &starSize
, setStarSize
, 'c','v'));
372 addUI(new Button(ALL
,DIALBAR
,x
+0.5,y
+SliderSize
*2-0.025,IconSize
, FgColor
, 0, true));
373 addUI(new SliderBar(ALL
,DIALBAR
,
374 x
,y
+SliderSize
*2, 0.45, SliderSize
, &fgRedSlider
, setupPalette
, 'b','n'));
375 addUI(new SliderBar(ALL
,DIALBAR
,
376 x
+0.5+SliderSize
,y
+SliderSize
*2, 0.45, SliderSize
, &fgGreenSlider
, setupPalette
, 'm',','));
379 addUI(new Button(ALL
,DIALBAR
,x
+0.5,y
+SliderSize
*3,IconSize
, BgColor
, 0, true));
380 addUI(new SliderBar(ALL
,DIALBAR
,
381 x
,y
+SliderSize
*3, 0.45, SliderSize
, &bgRedSlider
, setupPalette
, 'B','N'));
382 addUI(new SliderBar(ALL
,DIALBAR
,
383 x
+0.5+SliderSize
,y
+SliderSize
*3, 0.45, SliderSize
, &bgGreenSlider
, setupPalette
, 'M','<'));
385 addUI(new PopperUpper(ALL
,ALL
,0,0.75,0.25,0.25, VOLUMEBAR
));
386 addUI(new Button(ALL
,ALL
,0.05,0.775,IconSize
, Speaker
, 0, true, false));
388 addUI(new PopperUpper(ALL
,VOLUMEBAR
,x
=0.25,y
=0.75,1.0,0.25, VOLUMEBAR
));
389 x
+= 0.1;// y += 0.0625;
390 addUI(new SliderBar(ALL
,VOLUMEBAR
,x
,y
, 0.75, 0.25, &volume
, setVolume
, '-','+'));
391 //static double value = 0.5;
392 //addUI(new SliderBar(ALL,0,0.75,1.0,0.25,&value));
394 //addUI(new Button(BUTTONBAR,x,y,IconSize, 1, 'x'));
395 //addUI(new Button(BUTTONBAR,x += IconSize,y,IconSize, 2, 'x'));
396 //addUI(new Button(BUTTONBAR,x += IconSize,y,IconSize, 3, 'x'));
399 cdCheckCountDown
= 0;
407 interfaceSyncToState();
410 void interfaceSyncToState() {
411 starsButton
->bright
= (fadeMode
== Stars
);
412 flameButton
->bright
= (fadeMode
== Flame
);
413 waveButton
->bright
= (fadeMode
== Wave
);
415 starButton
->bright
= !pointsAreDiamonds
;
416 diamondButton
->bright
= pointsAreDiamonds
;
421 int changeState(int transitionSymbol
) {
422 if (transitionSymbol
< 0) {
423 cdPlay(cdGetTrackFrame(-transitionSymbol
));
428 switch(transitionSymbol
) {
433 cdGetStatus(track
, frames
, state
);
435 if (state
== Pause
) cdResume(); else cdPlay(cdGetTrackFrame(1));
451 cdPlay(cdGetTrackFrame(track
-1));
454 cdPlay(cdGetTrackFrame(track
+1));
458 starsButton
->bright
= false;
459 flameButton
->bright
= true;
460 waveButton
->bright
= false;
462 setStarSize(starSize
);
465 starsButton
->bright
= false;
466 flameButton
->bright
= false;
467 waveButton
->bright
= true;
469 setStarSize(starSize
);
472 starsButton
->bright
= true;
473 flameButton
->bright
= false;
474 waveButton
->bright
= false;
476 setStarSize(starSize
);
480 pointsAreDiamonds
= false;
481 starButton
->bright
= true;
482 diamondButton
->bright
= false;
485 pointsAreDiamonds
= true;
486 starButton
->bright
= false;
487 diamondButton
->bright
= true;
494 setStateToDefaults();
495 interfaceSyncToState();
496 setStarSize(starSize
);
506 int newVisibleMask
= ALL
;
509 int action
= NotASymbol
;
510 int oldButtons
= mouseButtons
;
512 screen
->inputUpdate(mouseX
,mouseY
,mouseButtons
,keyHit
); //may also resize output
514 bool mouseClick
= (mouseButtons
&& !oldButtons
);
516 if ((mouseX
!= lastX
|| mouseY
!= lastY
) &&
517 lastX
> 0 && lastY
> 0 &&
518 lastX
< outWidth
&& lastY
< outHeight
)
521 int activeMask
= ALL
;
523 case Play
: activeMask
|= PLAYING
; break;
524 case Pause
: activeMask
|= PAUSED
; break;
525 case Stop
: activeMask
|= STOPPED
; break;
526 case NoCD
: activeMask
|= NOCD
; break;
527 case Open
: activeMask
|= OPEN
; break;
535 (outWidth
*0.625 < outHeight
? outWidth
*0.625 : outHeight
);
536 double scaledX
= mouseX
/ scale
;
537 double scaledY
= mouseY
/ scale
;
541 polygonEngine
.clear();
543 stateButton
->icon
= state
;
546 for(UIObject
*i
=uiObjects
;i
;i
= i
->next
) {
547 if ((i
->visibleMask
& visibleMask
) && (i
->activeMask
& activeMask
))
548 newVisibleMask
|= i
->go(mouseButtons
,mouseClick
,
551 scaledX
< i
->x
+i
->width
&&
552 scaledY
< i
->y
+i
->height
),
560 if (activeMask
& (PLAYING
|PAUSED
|STOPPED
)) {
561 int trackNumber
= (activeMask
&(PLAYING
|PAUSED
) ? track
: -1);
562 unsigned short trackColor
= 0x0100;
563 if ((visibleMask
&TRACKBAR
) && trackSelector
->position
!= -1) {
564 trackNumber
= trackSelector
->position
;
568 if (trackNumber
!= -1) {
570 polygonEngine
.icon(Icons
[Zero
+trackNumber
/10%10],trackColor
,
571 scale
*0.03125,scale
*0.25,scale
*0.25,scale
*0.25);
573 polygonEngine
.icon(Icons
[Zero
+trackNumber
%10],trackColor
,
574 scale
*0.125,scale
*0.25,scale
*0.25,scale
*0.25);
578 visibleMask
= newVisibleMask
;
579 if (visibleMask
!= 1)
582 polygonEngine
.icon(Icons
[Pointer
],0x0303,mouseX
,mouseY
,50,50);
584 polygonEngine
.apply(outputBmp
.data
);
588 putString(hint
,mouseX
+6,mouseY
+7,0,0);
592 for(UIObject
*i
=uiObjects
;i
;i
= i
->next
)
593 if (i
->activeMask
& activeMask
)
594 i
->handleKey(keyHit
,action
);
600 if (action
!= NotASymbol
)
601 quit
= quit
|| changeState(action
);
603 if (state
!= Plug
&& (action
!= NotASymbol
|| cdCheckCountDown
< 0)) {
604 SymbolID oldState
= state
;
605 cdGetStatus(track
, frames
, state
);
606 if (action
== NotASymbol
&&
607 (oldState
== Play
|| oldState
== Open
|| oldState
== NoCD
) &&
609 if (playListLength
== 0)
610 cdPlay(cdGetTrackFrame(1));
612 int track
= atoi(playList
[playListPosition
]);
613 playListPosition
= (playListPosition
+1) % playListLength
;
614 cdPlay(cdGetTrackFrame(track
),cdGetTrackFrame(track
+1));
618 int interval
= cdGetTrackFrame(track
+1)-cdGetTrackFrame(track
);
620 trackProgress
= double(frames
)/interval
;
624 cdCheckCountDown
= 100;
626 cdCheckCountDown
-= (countDown
? 10 : 1);
628 if (mouseClick
&& action
== NotASymbol
&& !(visibleMask
&~ALL
)) {
629 screen
->toggleFullScreen();
630 screen
->inputUpdate(mouseX
,mouseY
,mouseButtons
,keyHit
);
638 void interfaceEnd() {
640 UIObject
*next
= uiObjects
->next
;