1 //------------------------------------------------------------------------------
2 // emMinesPanel.cpp
3 //
4 // Copyright (C) 2005-2008,2016 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20
21 #include <emMines/emMinesControlPanel.h>
22 #include <emMines/emMinesPanel.h>
23
24
emMinesPanel(ParentArg parent,const emString & name,emMinesFileModel * fileModel)25 emMinesPanel::emMinesPanel(
26 ParentArg parent, const emString & name, emMinesFileModel * fileModel
27 )
28 : emFilePanel(parent,name,fileModel,true)
29 {
30 Mdl=fileModel;
31 HaveControlPanel=IsVFSGood();
32 CursorX=-1;
33 CursorY=-1;
34 CursorZ=-1;
35 AddWakeUpSignal(Mdl->GetChangeSignal());
36 AddWakeUpSignal(GetVirFileStateSignal());
37 PrepareTransformation();
38 }
39
40
~emMinesPanel()41 emMinesPanel::~emMinesPanel()
42 {
43 }
44
45
GetTitle() const46 emString emMinesPanel::GetTitle() const
47 {
48 return "Mines";
49 }
50
51
GetIconFileName() const52 emString emMinesPanel::GetIconFileName() const
53 {
54 return "mines.tga";
55 }
56
57
GetEssenceRect(double * pX,double * pY,double * pW,double * pH) const58 void emMinesPanel::GetEssenceRect(
59 double * pX, double * pY, double * pW, double * pH
60 ) const
61 {
62 *pX=EssenceX;
63 *pY=EssenceY;
64 *pW=EssenceW;
65 *pH=EssenceH;
66 }
67
68
Cycle()69 bool emMinesPanel::Cycle()
70 {
71 bool vfsGood;
72
73 if (IsSignaled(GetVirFileStateSignal())) {
74 vfsGood=IsVFSGood();
75 if (HaveControlPanel!=vfsGood) {
76 HaveControlPanel=vfsGood;
77 InvalidateControlPanel();
78 }
79 }
80
81 if (
82 IsSignaled(GetVirFileStateSignal()) ||
83 IsSignaled(Mdl->GetChangeSignal())
84 ) {
85 PrepareTransformation();
86 InvalidatePainting();
87 }
88
89 return emFilePanel::Cycle();
90 }
91
92
Notice(NoticeFlags flags)93 void emMinesPanel::Notice(NoticeFlags flags)
94 {
95 emFilePanel::Notice(flags);
96 if ((flags&NF_VIEWING_CHANGED)!=0) {
97 CursorX=-1;
98 CursorY=-1;
99 CursorZ=-1;
100 PrepareTransformation();
101 }
102 }
103
104
Input(emInputEvent & event,const emInputState & state,double mx,double my)105 void emMinesPanel::Input(
106 emInputEvent & event, const emInputState & state, double mx, double my
107 )
108 {
109 int x,y,z,cx,cy,cz;
110 double dx,dy,d,dmin;
111
112 if (!IsViewed() || !IsVFSGood()) {
113 CursorX=-1;
114 CursorY=-1;
115 CursorZ=-1;
116 emFilePanel::Input(event,state,mx,my);
117 return;
118 }
119
120 cx=-1;
121 cy=-1;
122 cz=-1;
123 if (
124 mx>=0 && mx<1.0 && my>=0 && my<GetHeight() &&
125 IsViewed() &&
126 PanelToViewX(mx)>=GetClipX1() && PanelToViewX(mx)<GetClipX2() &&
127 PanelToViewY(my)>=GetClipY1() && PanelToViewY(my)<GetClipY2() &&
128 !Mdl->IsGameWon() && !Mdl->IsGameLost()
129 ) {
130 dmin=(TransX(1,0)-TransX(0,0))*0.5;
131 dmin*=dmin;
132 for (z=Mdl->GetSizeZ()-1; z>=0 && z>CameraZ+0.5; z--) {
133 for (y=Mdl->GetSizeY()-1; y>=0; y--) {
134 for (x=Mdl->GetSizeX()-1; x>=0; x--) {
135 dx=mx-TransX(x,z);
136 dy=my-TransY(y,z);
137 d=dx*dx+dy*dy;
138 if (d<dmin) {
139 dmin=d; cx=x; cy=y; cz=z;
140 }
141 }
142 }
143 }
144 }
145 if (CursorX!=cx || CursorY!=cy || CursorZ!=cz) {
146 CursorX=cx;
147 CursorY=cy;
148 CursorZ=cz;
149 InvalidatePainting();
150 }
151
152 switch (event.GetKey()) {
153 case EM_KEY_LEFT_BUTTON:
154 if (state.IsNoMod()) {
155 if (IsCursorValid() && !Mdl->IsGameWon() && !Mdl->IsGameLost()) {
156 Mdl->OpenField(CursorX,CursorY,CursorZ);
157 }
158 Focus();
159 event.Eat();
160 }
161 break;
162 case EM_KEY_RIGHT_BUTTON:
163 if (state.IsNoMod()) {
164 if (IsCursorValid() && !Mdl->IsGameWon() && !Mdl->IsGameLost()) {
165 Mdl->InvertMark(CursorX,CursorY,CursorZ);
166 }
167 Focus();
168 event.Eat();
169 }
170 break;
171 case EM_KEY_N:
172 if (state.IsCtrlMod()) {
173 Mdl->StartGame(
174 Mdl->GetSizeX(),
175 Mdl->GetSizeY(),
176 Mdl->GetSizeZ(),
177 Mdl->GetMineCount()
178 );
179 event.Eat();
180 }
181 break;
182 case EM_KEY_1:
183 if (state.IsCtrlMod()) {
184 Mdl->StartGame(1);
185 event.Eat();
186 }
187 break;
188 case EM_KEY_2:
189 if (state.IsCtrlMod()) {
190 Mdl->StartGame(2);
191 event.Eat();
192 }
193 break;
194 case EM_KEY_3:
195 if (state.IsCtrlMod()) {
196 Mdl->StartGame(3);
197 event.Eat();
198 }
199 break;
200 case EM_KEY_4:
201 if (state.IsCtrlMod()) {
202 Mdl->StartGame(4);
203 event.Eat();
204 }
205 break;
206 case EM_KEY_5:
207 if (state.IsCtrlMod()) {
208 Mdl->StartGame(5);
209 event.Eat();
210 }
211 break;
212 default:
213 break;
214 }
215
216 emFilePanel::Input(event,state,mx,my);
217 }
218
219
IsOpaque() const220 bool emMinesPanel::IsOpaque() const
221 {
222 if (IsVFSGood()) return true;
223 else return emFilePanel::IsOpaque();
224 }
225
226
Paint(const emPainter & painter,emColor canvasColor) const227 void emMinesPanel::Paint(const emPainter & painter, emColor canvasColor) const
228 {
229 emColor color;
230 double tx,ty,tz,tw,th;
231 int x,y,z,cx,cy,sx,sy,sz;
232
233 if (!IsVFSGood()) {
234 emFilePanel::Paint(painter,canvasColor);
235 return;
236 }
237
238 painter.Clear(
239 Mdl->IsGameWon()?emColor(34,34,102):
240 Mdl->IsGameLost()?emColor(102,17,0):
241 emColor(emColor::BLACK),
242 canvasColor
243 );
244
245 sx=Mdl->GetSizeX();
246 sy=Mdl->GetSizeY();
247 sz=Mdl->GetSizeZ();
248 cx=(int)ceil(CameraX);
249 cy=(int)ceil(CameraY);
250 if (cx<0) cx=0; else if (cx>sx-1) cx=sx-1;
251 if (cy<0) cy=0; else if (cy>sy-1) cy=sy-1;
252
253 for (z=sz-1; z>=0 && z>CameraZ+0.5; z--) {
254 color.SetHSVA(
255 60.0F*(z%6),
256 55.0F,
257 400.0F/(z+4),
258 255
259 );
260 for (y=0; y<cy; y++) {
261 for (x=0; x<cx; x++) {
262 PaintField(painter,x,y,z,color);
263 }
264 }
265 for (y=0; y<cy; y++) {
266 for (x=sx-1; x>=cx; x--) {
267 PaintField(painter,x,y,z,color);
268 }
269 }
270 for (y=sy-1; y>=cy; y--) {
271 for (x=0; x<cx; x++) {
272 PaintField(painter,x,y,z,color);
273 }
274 }
275 for (y=sy-1; y>=cy; y--) {
276 for (x=sx-1; x>=cx; x--) {
277 PaintField(painter,x,y,z,color);
278 }
279 }
280 }
281
282 if (IsCursorValid()) {
283 color=emColor(255,255,255,192);
284 PaintField(painter,CursorX,CursorY,CursorZ,color);
285 }
286
287 if (Mdl->IsGameWon() || Mdl->IsGameLost()) {
288 tz=-1.0;
289 if (tz>CameraZ+0.5) {
290 tx=TransX(0,tz);
291 ty=TransY(0,tz);
292 tw=TransX(Mdl->GetSizeX()-1,tz)-tx;
293 th=TransY(Mdl->GetSizeY()-1,tz)-ty;
294 tx+=0.125*tw;
295 ty+=0.125*th;
296 tw*=0.75;
297 th*=0.75;
298 painter.PaintTextBoxed(
299 tx,
300 ty,
301 tw,
302 th,
303 Mdl->IsGameLost() ? "Game over" : "Success!",
304 th,
305 Mdl->IsGameLost() ? emColor(255,0,0,128) : emColor(0,0,255,128),
306 0,
307 EM_ALIGN_CENTER,
308 EM_ALIGN_CENTER,
309 1.0
310 );
311 }
312 }
313 }
314
315
CreateControlPanel(ParentArg parent,const emString & name)316 emPanel * emMinesPanel::CreateControlPanel(
317 ParentArg parent, const emString & name
318 )
319 {
320 if (HaveControlPanel) {
321 return new emMinesControlPanel(parent,name,Mdl);
322 }
323 else {
324 return emFilePanel::CreateControlPanel(parent,name);
325 }
326 }
327
328
PaintField(const emPainter & painter,int x,int y,int z,emColor color) const329 void emMinesPanel::PaintField(
330 const emPainter & painter, int x, int y, int z, emColor color
331 ) const
332 {
333 static const double br=0.002;
334 static const double fr=0.08;
335 int sizeX,sizeY,sizeZ,surroundings,xybeams;
336 bool isOpen,isMine,isMarked;
337
338 sizeX=Mdl->GetSizeX();
339 sizeY=Mdl->GetSizeY();
340 sizeZ=Mdl->GetSizeZ();
341 surroundings=Mdl->GetSurroundings(x,y,z);
342 isOpen=Mdl->IsOpen(x,y,z);
343 isMine=Mdl->IsMine(x,y,z);
344 isMarked=Mdl->IsMarked(x,y,z);
345
346 painter.LeaveUserSpace();
347
348 if (z+1<sizeZ) PaintZBeam(painter,x,y,z+fr,z+0.5,br,color);
349
350 xybeams=0;
351 if (x>0) {
352 if (x-fr<=CameraX) PaintXBeam(painter,x-0.5,y,z,x-fr,br,color);
353 else xybeams|=1;
354 }
355 if (x+1<sizeX) {
356 if (x+fr>=CameraX) PaintXBeam(painter,x+fr,y,z,x+0.5,br,color);
357 else xybeams|=2;
358 }
359 if (y>0) {
360 if (y-fr<=CameraY) PaintYBeam(painter,x,y-0.5,z,y-fr,br,color);
361 else xybeams|=4;
362 }
363 if (y+1<sizeY) {
364 if (y+fr>=CameraY) PaintYBeam(painter,x,y+fr,z,y+0.5,br,color);
365 else xybeams|=8;
366 }
367
368 if (isOpen) {
369 if (isMine) PaintExplodingField(painter,x,y,z,fr);
370 else PaintOpenField(painter,x,y,z,fr,surroundings,color);
371 }
372 else if (isMarked) PaintMarkedField(painter,x,y,z,fr,color);
373 else PaintClosedField(painter,x,y,z,fr,color);
374
375 if ((xybeams&1)!=0) PaintXBeam(painter,x-0.5,y,z,x-fr,br,color);
376 if ((xybeams&2)!=0) PaintXBeam(painter,x+fr,y,z,x+0.5,br,color);
377 if ((xybeams&4)!=0) PaintYBeam(painter,x,y-0.5,z,y-fr,br,color);
378 if ((xybeams&8)!=0) PaintYBeam(painter,x,y+fr,z,y+0.5,br,color);
379 if (z>0) PaintZBeam(painter,x,y,z-0.5,z-fr,br,color);
380
381 painter.EnterUserSpace();
382 }
383
384
PaintClosedField(const emPainter & painter,double x,double y,double z,double r,emColor color) const385 void emMinesPanel::PaintClosedField(
386 const emPainter & painter, double x, double y, double z, double r,
387 emColor color
388 ) const
389 {
390 double x11,y11,x12,y12,x21,y21,x22,y22;
391 double xy[4*2];
392 emColor cl,cr,ct,cb;
393
394 cl=color.GetLighted(-20.0f);
395 cr=color.GetLighted(-30.0f);
396 ct=color.GetLighted(-10.0f);
397 cb=color.GetLighted(-40.0f);
398
399 x11=TransX(x-r,z-r);
400 y11=TransY(y-r,z-r);
401 x12=TransX(x-r,z+r);
402 y12=TransY(y-r,z+r);
403 x21=TransX(x+r,z-r);
404 y21=TransY(y+r,z-r);
405 x22=TransX(x+r,z+r);
406 y22=TransY(y+r,z+r);
407
408 painter.PaintRect(x11,y11,x21-x11,y21-y11,color);
409 if (x12<x11) {
410 xy[0]=x11; xy[1]=y11;
411 xy[2]=x11; xy[3]=y21;
412 xy[4]=x12; xy[5]=y22;
413 xy[6]=x12; xy[7]=y12;
414 painter.PaintPolygon(xy,4,cl);
415 painter.PaintEdgeCorrection(x11,y11,x11,y21,color,cl);
416 }
417 else if (x22>x21) {
418 xy[0]=x21; xy[1]=y11;
419 xy[2]=x21; xy[3]=y21;
420 xy[4]=x22; xy[5]=y22;
421 xy[6]=x22; xy[7]=y12;
422 painter.PaintPolygon(xy,4,cr);
423 painter.PaintEdgeCorrection(x21,y21,x21,y11,color,cr);
424 }
425 if (y12<y11) {
426 xy[0]=x11; xy[1]=y11;
427 xy[2]=x21; xy[3]=y11;
428 xy[4]=x22; xy[5]=y12;
429 xy[6]=x12; xy[7]=y12;
430 painter.PaintPolygon(xy,4,ct);
431 painter.PaintEdgeCorrection(x21,y11,x11,y11,color,ct);
432 if (x12<x11) painter.PaintEdgeCorrection(x11,y11,x12,y12,cl,ct);
433 else if (x22>x21) painter.PaintEdgeCorrection(x22,y12,x21,y11,cr,ct);
434 }
435 else if (y22>y21) {
436 xy[0]=x11; xy[1]=y21;
437 xy[2]=x21; xy[3]=y21;
438 xy[4]=x22; xy[5]=y22;
439 xy[6]=x12; xy[7]=y22;
440 painter.PaintPolygon(xy,4,cb);
441 painter.PaintEdgeCorrection(x11,y21,x21,y21,color,cb);
442 if (x12<x11) painter.PaintEdgeCorrection(x12,y22,x11,y21,cl,cb);
443 else if (x22>x21) painter.PaintEdgeCorrection(x21,y21,x22,y22,cr,cb);
444 }
445 }
446
447
PaintMarkedField(const emPainter & painter,double x,double y,double z,double r,emColor color) const448 void emMinesPanel::PaintMarkedField(
449 const emPainter & painter, double x, double y, double z, double r,
450 emColor color
451 ) const
452 {
453 static const float light[8]={-45,-40,-30,-20,-5,-10,-20,-30};
454 double x1[8],y1[8],x2[8],y2[8],x3[8],y3[8];
455 double xy[8*2];
456 double nx,ny;
457 int i,k,v1,v2;
458 emColor c1[8],c2[8];
459 emColor cwarn;
460
461 cwarn=color.GetBlended(emColor(255,0,0,color.GetAlpha()),25.0f);
462
463 for (i=0; i<8; i++) {
464 nx=r*cos((i+0.5)*(M_PI*0.25));
465 ny=r*sin((i+0.5)*(M_PI*0.25));
466 x1[i]=TransX(x+nx*0.448,z-r );
467 y1[i]=TransY(y+ny*0.448,z-r );
468 x2[i]=TransX(x+nx*1.082,z-r*0.414);
469 y2[i]=TransY(y+ny*1.082,z-r*0.414);
470 x3[i]=TransX(x+nx*1.082,z+r*0.414);
471 y3[i]=TransY(y+ny*1.082,z+r*0.414);
472 if ((i&1)!=0) {
473 c1[i]=color.GetLighted(light[i]*0.5F);
474 c2[i]=cwarn.GetLighted(light[i]);
475 }
476 else {
477 c1[i]=cwarn.GetLighted(light[i]*0.5F);
478 c2[i]=color.GetLighted(light[i]);
479 }
480 }
481
482 v1=0;
483 v2=0;
484 for (i=0; i<8; i++) {
485 k=(i+1)&7;
486 xy[0]=x2[i]; xy[1]=y2[i];
487 xy[2]=x2[k]; xy[3]=y2[k];
488 xy[4]=x3[k]; xy[5]=y3[k];
489 xy[6]=x3[i]; xy[7]=y3[i];
490 if ((xy[0]-xy[2])*(xy[7]-xy[1])+(xy[3]-xy[1])*(xy[6]-xy[0])>0.0) {
491 painter.PaintPolygon(xy,4,c2[i]);
492 v2|=1<<i;
493 }
494 xy[0]=x1[i]; xy[1]=y1[i];
495 xy[2]=x1[k]; xy[3]=y1[k];
496 xy[4]=x2[k]; xy[5]=y2[k];
497 xy[6]=x2[i]; xy[7]=y2[i];
498 if ((xy[0]-xy[2])*(xy[7]-xy[1])+(xy[3]-xy[1])*(xy[6]-xy[0])>0.0) {
499 painter.PaintPolygon(xy,4,c1[i]);
500 v1|=1<<i;
501 }
502 }
503 for (i=0; i<8; i++) {
504 xy[i*2]=x1[i];
505 xy[i*2+1]=y1[i];
506 }
507 painter.PaintPolygon(xy,8,color);
508
509 for (i=0; i<8; i++) {
510 k=(i+1)&7;
511 if ((v2&(1<<i))!=0 && (v2&(1<<k))!=0) {
512 if (!k) painter.PaintEdgeCorrection(x3[k],y3[k],x2[k],y2[k],c2[k],c2[i]);
513 else painter.PaintEdgeCorrection(x2[k],y2[k],x3[k],y3[k],c2[i],c2[k]);
514 }
515 if ((v1&(1<<i))!=0) {
516 if ((v1&(1<<k))!=0) {
517 if (!k) painter.PaintEdgeCorrection(x2[k],y2[k],x1[k],y1[k],c1[k],c1[i]);
518 else painter.PaintEdgeCorrection(x1[k],y1[k],x2[k],y2[k],c1[i],c1[k]);
519 }
520 painter.PaintEdgeCorrection(x1[i],y1[i],x1[k],y1[k],c1[i],color);
521 if ((v2&(1<<i))!=0) {
522 painter.PaintEdgeCorrection(x2[i],y2[i],x2[k],y2[k],c2[i],c1[i]);
523 }
524 }
525 }
526 }
527
528
PaintOpenField(const emPainter & painter,double x,double y,double z,double r,int number,emColor color) const529 void emMinesPanel::PaintOpenField(
530 const emPainter & painter, double x, double y, double z, double r,
531 int number, emColor color
532 ) const
533 {
534 double x1,y1,x2,y2;
535 char numstr[64];
536
537 x1=TransX(x-r*1.2,z+r*0.1);
538 y1=TransY(y-r*1.2,z+r*0.1);
539 x2=TransX(x+r*1.2,z+r*0.1);
540 y2=TransY(y+r*1.4,z+r*0.1);
541 sprintf(numstr,"%d",number);
542 painter.PaintTextBoxed(
543 x1,y1,x2-x1,y2-y1,
544 numstr,
545 y2-y1,
546 color.GetLighted(-25.0f)
547 );
548
549 x1=TransX(x-r*1.2,z-r*0.1);
550 y1=TransY(y-r*1.2,z-r*0.1);
551 x2=TransX(x+r*1.2,z-r*0.1);
552 y2=TransY(y+r*1.4,z-r*0.1);
553 painter.PaintTextBoxed(
554 x1,y1,x2-x1,y2-y1,
555 numstr,
556 y2-y1,
557 color
558 );
559 }
560
561
PaintExplodingField(const emPainter & painter,double x,double y,double z,double r) const562 void emMinesPanel::PaintExplodingField(
563 const emPainter & painter, double x, double y, double z, double r
564 ) const
565 {
566 static const struct { double x, y, z; } vertex[18]={
567 {1347.62,-575.08,-864.97},
568 {364.42,263.00,-316.07},
569 {129.39,1088.80,-881.94},
570 {-460.32,176.19,-316.07},
571 {-1427.27,-577.16,-896.03},
572 {-257.24,-525.68,-316.07},
573 {-62.15,-1552.24,-896.03},
574 {222.94,-491.38,-316.07},
575 {0.00,0.00,0.00},
576 {2190.00,-734.54,-426.79},
577 {588.33,433.44,-179.60},
578 {284.21,1851.23,-432.53},
579 {-601.94,512.80,-179.60},
580 {-2446.35,-754.52,-459.44},
581 {-493.83,-856.07,-179.60},
582 {-102.35,-2555.93,-459.44},
583 {489.14,-875.85,-179.60},
584 {0.00,0.00,0.00}
585 };
586 static const emColor colors[2]={
587 emColor(255,255,0,192),
588 emColor(255,0,0,255)
589 };
590 static const struct { int vi[3]; int ci; } poly[16]={
591 {{15,16,17},0},
592 {{17,16,9},0},
593 {{17,9,10},0},
594 {{11,17,10},0},
595 {{11,12,17},0},
596 {{13,17,12},0},
597 {{17,13,14},0},
598 {{14,15,17},0},
599 {{6,7,8},1},
600 {{8,7,0},1},
601 {{8,0,1},1},
602 {{2,8,1},1},
603 {{2,3,8},1},
604 {{4,8,3},1},
605 {{8,4,5},1},
606 {{5,6,8},1}
607 };
608 double xy[3*2];
609 int i,j;
610
611 for (i=0; i<16; i++) {
612 for (j=0; j<3; j++) {
613 xy[j*2]=TransX(
614 x+r*vertex[poly[i].vi[j]].x*0.004,
615 z+r*vertex[poly[i].vi[j]].z*0.004
616 );
617 xy[j*2+1]=TransY(
618 y+r*vertex[poly[i].vi[j]].y*0.004,
619 z+r*vertex[poly[i].vi[j]].z*0.004
620 );
621 }
622 painter.PaintPolygon(xy,3,colors[poly[i].ci]);
623 }
624 }
625
626
PaintXBeam(const emPainter & painter,double x,double y,double z,double x2,double r,emColor color) const627 void emMinesPanel::PaintXBeam(
628 const emPainter & painter, double x, double y, double z, double x2,
629 double r, emColor color
630 ) const
631 {
632 double x11,y11,x12,y12,x21,y21,x22,y22;
633 double xy[4*2];
634
635 x11=TransX(x ,z-r);
636 y11=TransY(y-r,z-r);
637 x12=TransX(x ,z+r);
638 y12=TransY(y-r,z+r);
639 x21=TransX(x2 ,z-r);
640 y21=TransY(y+r,z-r);
641 x22=TransX(x2 ,z+r);
642 y22=TransY(y+r,z+r);
643 painter.PaintRect(x11,y11,x21-x11,y21-y11,color);
644 if (y12<y11) {
645 xy[0]=x11; xy[1]=y11;
646 xy[2]=x21; xy[3]=y11;
647 xy[4]=x22; xy[5]=y12;
648 xy[6]=x12; xy[7]=y12;
649 painter.PaintPolygon(xy,4,color.GetLighted(-10.0f));
650 }
651 else if (y22>y21) {
652 xy[0]=x11; xy[1]=y21;
653 xy[2]=x21; xy[3]=y21;
654 xy[4]=x22; xy[5]=y22;
655 xy[6]=x12; xy[7]=y22;
656 painter.PaintPolygon(xy,4,color.GetLighted(-40.0f));
657 }
658 }
659
660
PaintYBeam(const emPainter & painter,double x,double y,double z,double y2,double r,emColor color) const661 void emMinesPanel::PaintYBeam(
662 const emPainter & painter, double x, double y, double z, double y2,
663 double r, emColor color
664 ) const
665 {
666 double x11,y11,x12,y12,x21,y21,x22,y22;
667 double xy[4*2];
668
669 x11=TransX(x-r,z-r);
670 y11=TransY(y ,z-r);
671 x12=TransX(x-r,z+r);
672 y12=TransY(y ,z+r);
673 x21=TransX(x+r,z-r);
674 y21=TransY(y2 ,z-r);
675 x22=TransX(x+r,z+r);
676 y22=TransY(y2 ,z+r);
677 painter.PaintRect(x11,y11,x21-x11,y21-y11,color);
678 if (x12<x11) {
679 xy[0]=x11; xy[1]=y11;
680 xy[2]=x11; xy[3]=y21;
681 xy[4]=x12; xy[5]=y22;
682 xy[6]=x12; xy[7]=y12;
683 painter.PaintPolygon(xy,4,color.GetLighted(-20.0f));
684 }
685 else if (x22>x21) {
686 xy[0]=x21; xy[1]=y11;
687 xy[2]=x21; xy[3]=y21;
688 xy[4]=x22; xy[5]=y22;
689 xy[6]=x22; xy[7]=y12;
690 painter.PaintPolygon(xy,4,color.GetLighted(-30.0f));
691 }
692 }
693
694
PaintZBeam(const emPainter & painter,double x,double y,double z,double z2,double r,emColor color) const695 void emMinesPanel::PaintZBeam(
696 const emPainter & painter, double x, double y, double z, double z2,
697 double r, emColor color
698 ) const
699 {
700 double x11,y11,x12,y12,x21,y21,x22,y22;
701 double xy[4*2];
702
703 x11=TransX(x-r,z );
704 y11=TransY(y-r,z );
705 x12=TransX(x-r,z2);
706 y12=TransY(y-r,z2);
707 x21=TransX(x+r,z );
708 y21=TransY(y+r,z );
709 x22=TransX(x+r,z2);
710 y22=TransY(y+r,z2);
711 if (x12<x11) {
712 xy[0]=x11; xy[1]=y11;
713 xy[2]=x11; xy[3]=y21;
714 xy[4]=x12; xy[5]=y22;
715 xy[6]=x12; xy[7]=y12;
716 painter.PaintPolygon(xy,4,color.GetLighted(-20.0f));
717 }
718 else if (x22>x21) {
719 xy[0]=x21; xy[1]=y11;
720 xy[2]=x21; xy[3]=y21;
721 xy[4]=x22; xy[5]=y22;
722 xy[6]=x22; xy[7]=y12;
723 painter.PaintPolygon(xy,4,color.GetLighted(-30.0f));
724 }
725 if (y12<y11) {
726 xy[0]=x11; xy[1]=y11;
727 xy[2]=x21; xy[3]=y11;
728 xy[4]=x22; xy[5]=y12;
729 xy[6]=x12; xy[7]=y12;
730 painter.PaintPolygon(xy,4,color.GetLighted(-10.0f));
731 }
732 else if (y22>y21) {
733 xy[0]=x11; xy[1]=y21;
734 xy[2]=x21; xy[3]=y21;
735 xy[4]=x22; xy[5]=y22;
736 xy[6]=x12; xy[7]=y22;
737 painter.PaintPolygon(xy,4,color.GetLighted(-40.0f));
738 }
739 }
740
741
IsCursorValid() const742 bool emMinesPanel::IsCursorValid() const
743 {
744 return
745 CursorX>=0 && CursorX<Mdl->GetSizeX() &&
746 CursorY>=0 && CursorY<Mdl->GetSizeY() &&
747 CursorZ>=0 && CursorZ<Mdl->GetSizeZ()
748 ;
749 }
750
751
TransX(double fieldX,double fieldZ) const752 double emMinesPanel::TransX(double fieldX, double fieldZ) const
753 {
754 return (fieldX-CameraX)/(fieldZ-CameraZ)*TrScale+TrX0;
755 }
756
757
TransY(double fieldY,double fieldZ) const758 double emMinesPanel::TransY(double fieldY, double fieldZ) const
759 {
760 return (fieldY-CameraY)/(fieldZ-CameraZ)*TrScale+TrY0;
761 }
762
763
PrepareTransformation()764 void emMinesPanel::PrepareTransformation()
765 {
766 double h,k,s;
767
768 if (!IsViewed() || !IsVFSGood()) {
769 EssenceX=0.0;
770 EssenceY=0.0;
771 EssenceW=1.0;
772 EssenceH=GetHeight();
773 CameraX=0;
774 CameraY=0;
775 CameraZ=1000;
776 TrX0=0;
777 TrY0=0;
778 TrScale=1.0;
779 return;
780 }
781
782 h=GetHeight();
783 s=emMin(h/Mdl->GetSizeY(),1.0/Mdl->GetSizeX())*0.9;
784
785 EssenceW=(Mdl->GetSizeX()-0.6)*s;
786 EssenceH=(Mdl->GetSizeY()-0.6)*s;
787 EssenceX=(1.0-EssenceW)*0.5;
788 EssenceY=(h-EssenceH)*0.5;
789
790 TrX0=ViewToPanelX(GetView().GetCurrentX()+GetView().GetCurrentWidth()*0.5);
791 TrY0=ViewToPanelY(GetView().GetCurrentY()+GetView().GetCurrentHeight()*0.5);
792
793 CameraX=TrX0/s+(Mdl->GetSizeX()-1-1.0/s)*0.5;
794 CameraY=TrY0/s+(Mdl->GetSizeY()-1-h/s)*0.5;
795 k=emMax(
796 PanelToViewDeltaX(EssenceW)/GetView().GetCurrentWidth(),
797 PanelToViewDeltaY(EssenceH)/GetView().GetCurrentHeight()
798 );
799 CameraZ=(Mdl->GetSizeX()*Mdl->GetSizeY())*0.5/k*0.21;
800 TrScale=CameraZ*s;
801 if (k>1.0) {
802 TrScale*=k/(2.0-1.0/k);
803 CameraZ*=1.0-(1.0-1.0/k)*log(k)*0.5;
804 }
805 CameraZ=-CameraZ;
806 }
807