1 //------------------------------------------------------------------------------
2 // emNetwalkPanel.cpp
3 //
4 // Copyright (C) 2010-2012,2014,2016,2019-2020 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 <emCore/emRes.h>
22 #include <emNetwalk/emNetwalkPanel.h>
23 #include <emNetwalk/emNetwalkControlPanel.h>
24 
25 
emNetwalkPanel(ParentArg parent,const emString & name,emNetwalkModel * fileModel)26 emNetwalkPanel::emNetwalkPanel(
27 	ParentArg parent, const emString & name, emNetwalkModel * fileModel
28 )
29 	: emFilePanel(parent,name,fileModel,true)
30 {
31 	Mdl=fileModel;
32 	HaveControlPanel=IsVFSGood();
33 	Scrolling=false;
34 	PrepareTransformation();
35 	AddWakeUpSignal(Mdl->GetChangeSignal());
36 	AddWakeUpSignal(GetVirFileStateSignal());
37 }
38 
39 
~emNetwalkPanel()40 emNetwalkPanel::~emNetwalkPanel()
41 {
42 }
43 
44 
GetTitle() const45 emString emNetwalkPanel::GetTitle() const
46 {
47 	return "Netwalk";
48 }
49 
50 
GetIconFileName() const51 emString emNetwalkPanel::GetIconFileName() const
52 {
53 	return "netwalk.tga";
54 }
55 
56 
GetEssenceRect(double * pX,double * pY,double * pW,double * pH) const57 void emNetwalkPanel::GetEssenceRect(
58 	double * pX, double * pY, double * pW, double * pH
59 ) const
60 {
61 	*pX=EssenceX;
62 	*pY=EssenceY;
63 	*pW=EssenceW;
64 	*pH=EssenceH;
65 }
66 
67 
Cycle()68 bool emNetwalkPanel::Cycle()
69 {
70 	bool vfsGood;
71 
72 	if (IsSignaled(GetVirFileStateSignal())) {
73 		vfsGood=IsVFSGood();
74 		if (HaveControlPanel!=vfsGood) {
75 			HaveControlPanel=vfsGood;
76 			InvalidateControlPanel();
77 		}
78 		if (!vfsGood && Scrolling) {
79 			Scrolling=false;
80 			InvalidateCursor();
81 		}
82 		if (vfsGood && ImgSymbols.IsEmpty()) {
83 			try {
84 				ImgBackground=emTryGetInsResImage(GetRootContext(),"emNetwalk","Background.tga");
85 				ImgBorder    =emTryGetInsResImage(GetRootContext(),"emNetwalk","Border.tga");
86 				ImgLights    =emTryGetInsResImage(GetRootContext(),"emNetwalk","Lights.tga");
87 				ImgMarks     =emTryGetInsResImage(GetRootContext(),"emNetwalk","Marks.tga");
88 				ImgNoBorder  =emTryGetInsResImage(GetRootContext(),"emNetwalk","NoBorder.tga");
89 				ImgPipes     =emTryGetInsResImage(GetRootContext(),"emNetwalk","Pipes.tga");
90 				ImgSymbols   =emTryGetInsResImage(GetRootContext(),"emNetwalk","Symbols.tga");
91 				InvalidatePainting();
92 			}
93 			catch (const emException & exception) {
94 				SetCustomError(exception.GetText());
95 			}
96 		}
97 	}
98 
99 	if (
100 		IsSignaled(GetVirFileStateSignal()) ||
101 		IsSignaled(Mdl->GetChangeSignal())
102 	) {
103 		PrepareTransformation();
104 		InvalidatePainting();
105 	}
106 
107 	return emFilePanel::Cycle();
108 }
109 
110 
Notice(NoticeFlags flags)111 void emNetwalkPanel::Notice(NoticeFlags flags)
112 {
113 	emFilePanel::Notice(flags);
114 	if (flags&NF_LAYOUT_CHANGED) {
115 		PrepareTransformation();
116 		InvalidatePainting();
117 	}
118 }
119 
120 
Input(emInputEvent & event,const emInputState & state,double mx,double my)121 void emNetwalkPanel::Input(
122 	emInputEvent & event, const emInputState & state, double mx, double my
123 )
124 {
125 	int x,y;
126 
127 	if (!IsViewed() || !IsVFSGood()) {
128 		emFilePanel::Input(event,state,mx,my);
129 		return;
130 	}
131 
132 	if (Scrolling) {
133 		if (!state.Get(EM_KEY_LEFT_BUTTON) || !Mdl->IsBorderless()) {
134 			Scrolling=false;
135 			InvalidateCursor();
136 		}
137 		else {
138 			x=(int)floor((mx-ScrollX0)/DX+0.5);
139 			y=(int)floor((my-ScrollY0)/DY+0.5);
140 			if (x || y) {
141 				Mdl->Scroll(x,y);
142 				ScrollX0+=x*DX;
143 				ScrollY0+=y*DY;
144 			}
145 		}
146 	}
147 	else if (event.IsLeftButton() && state.IsCtrlMod() && Mdl->IsBorderless()) {
148 		Scrolling=true;
149 		ScrollX0=mx;
150 		ScrollY0=my;
151 		InvalidateCursor();
152 	}
153 
154 	if (!event.IsEmpty()) {
155 		x=(int)floor((mx-X0)/DX);
156 		y=(int)floor((my-Y0)/DY);
157 		if (Mdl->IsBorderless()) {
158 			if (x==-1) x=Mdl->GetWidth()-1;
159 			if (y==-1) y=Mdl->GetHeight()-1;
160 			if (x==Mdl->GetWidth()) x=0;
161 			if (y==Mdl->GetHeight()) y=0;
162 		}
163 		if (x>=0 && y>=0 && x<Mdl->GetWidth() && y<Mdl->GetHeight()) {
164 			if (event.IsLeftButton() && !Scrolling) {
165 				if (state.IsNoMod()) Mdl->RotateLeft(x,y);
166 				else if (state.IsShiftMod()) Mdl->RotateRight(x,y);
167 			}
168 			if (event.IsRightButton() && state.IsNoMod()) {
169 				Mdl->MarkOrUnmark(x,y);
170 			}
171 		}
172 	}
173 
174 	if (event.IsKey(EM_KEY_N) && state.IsCtrlMod()) {
175 		try {
176 			Mdl->TrySetup(
177 				Mdl->GetWidth(),Mdl->GetHeight(),Mdl->IsBorderless(),
178 				Mdl->IsNoFourWayJunctions(),Mdl->GetComplexity(),
179 				Mdl->IsDigMode(),Mdl->IsAutoMark()
180 			);
181 		}
182 		catch (const emException & exception) {
183 			emDialog::ShowMessage(GetViewContext(),"Error",exception.GetText());
184 		}
185 		event.Eat();
186 	}
187 
188 	if (event.IsKey(EM_KEY_U) && state.IsCtrlMod()) {
189 		Mdl->UnmarkAll();
190 		event.Eat();
191 	}
192 
193 	emFilePanel::Input(event,state,mx,my);
194 }
195 
196 
GetCursor() const197 emCursor emNetwalkPanel::GetCursor() const
198 {
199 	if (Scrolling) return emCursor::LEFT_RIGHT_UP_DOWN_ARROW;
200 	else return emFilePanel::GetCursor();
201 }
202 
203 
IsOpaque() const204 bool emNetwalkPanel::IsOpaque() const
205 {
206 	if (IsVFSGood()) return true;
207 	else return emFilePanel::IsOpaque();
208 }
209 
210 
Paint(const emPainter & painter,emColor canvasColor) const211 void emNetwalkPanel::Paint(const emPainter & painter, emColor canvasColor) const
212 {
213 	int x,y,x1,y1,x2,y2,w,h,d;
214 	double fx1,fy1,fx2,fy2,gx1,gy1,gx2,gy2,bx,by;
215 	emString str;
216 	double t;
217 
218 	if (!IsVFSGood() || ImgSymbols.IsEmpty()) {
219 		emFilePanel::Paint(painter,canvasColor);
220 		return;
221 	}
222 
223 	painter.Clear(BgColor,canvasColor);
224 	canvasColor=BgColor;
225 
226 	w=Mdl->GetWidth();
227 	h=Mdl->GetHeight();
228 
229 	x1=0; y1=0; x2=w; y2=h;
230 	if (Mdl->IsBorderless()) { x1--; y1--; x2++; y2++; }
231 	for (y=y1; y<y2; y++) {
232 		for (x=x1; x<x2; x++) {
233 			PaintPieceBackground(painter,X0+x*DX,Y0+y*DY,DX,DY,x,y,canvasColor);
234 		}
235 	}
236 	for (y=y1; y<y2; y++) {
237 		for (x=x1; x<x2; x++) {
238 			PaintPiecePipe(painter,X0+x*DX,Y0+y*DY,DX,DY,x,y);
239 		}
240 	}
241 
242 	if (Mdl->IsBorderless()) {
243 		fx1=X0-DX;
244 		fy1=Y0-DY;
245 		fx2=X0+DX*(w+1);
246 		fy2=Y0+DY*(h+1);
247 		d=(ImgNoBorder.GetWidth()-1)/2;
248 		painter.PaintBorderImage(
249 			fx1,fy1,fx2-fx1,fy2-fy1,
250 			DX,DY,DX,DY,
251 			ImgNoBorder,
252 			d,d,d,d,
253 			255,0,0757
254 		);
255 		gx1=painter.RoundUpX(fx1);
256 		gy1=painter.RoundUpY(fy1);
257 		gx2=painter.RoundDownX(fx2);
258 		gy2=painter.RoundDownY(fy2);
259 		fx1=painter.RoundDownX(fx1);
260 		fy1=painter.RoundDownY(fy1);
261 		fx2=painter.RoundUpX(fx2);
262 		fy2=painter.RoundUpY(fy2);
263 		painter.PaintRect(fx1,fy1,fx2-fx1,gy1-fy1,BgColor);
264 		painter.PaintRect(fx1,gy1,gx1-fx1,gy2-gy1,BgColor);
265 		painter.PaintRect(gx2,gy1,fx2-gx2,gy2-gy1,BgColor);
266 		painter.PaintRect(fx1,gy2,fx2-fx1,fy2-gy2,BgColor);
267 	}
268 	else {
269 		d=(ImgBorder.GetWidth()-1)/2;
270 		bx=DX*BorderSize;
271 		by=DY*BorderSize;
272 		painter.PaintBorderImage(
273 			X0-bx,Y0-by,DX*w+2*bx,DY*h+2*by,
274 			bx,by,bx,by,
275 			ImgBorder,
276 			d,d,d,d,
277 			255,0,0757
278 		);
279 	}
280 
281 	if (Mdl->IsFinished()) {
282 		str=emString::Format(
283 			"Net complete!\n"
284 			"Penalty: %d",
285 			Mdl->GetPenaltyPoints()
286 		);
287 		t=EssenceW*0.003;
288 		painter.PaintTextBoxed(
289 			EssenceX+t,EssenceY+t,EssenceW,EssenceH,
290 			str,
291 			EssenceW/12,
292 			0x444400FF,0,EM_ALIGN_CENTER,EM_ALIGN_CENTER
293 		);
294 		painter.PaintTextBoxed(
295 			EssenceX,EssenceY,EssenceW,EssenceH,
296 			str,
297 			EssenceW/12,
298 			0xFFFF88FF,0,EM_ALIGN_CENTER,EM_ALIGN_CENTER
299 		);
300 	}
301 }
302 
303 
CreateControlPanel(ParentArg parent,const emString & name)304 emPanel * emNetwalkPanel::CreateControlPanel(
305 	ParentArg parent, const emString & name
306 )
307 {
308 	if (HaveControlPanel) {
309 		return new emNetwalkControlPanel(parent,name,GetView(),Mdl);
310 	}
311 	else {
312 		return emFilePanel::CreateControlPanel(parent,name);
313 	}
314 }
315 
316 
PaintPieceBackground(const emPainter & painter,double x,double y,double w,double h,int px,int py,emColor canvasColor) const317 void emNetwalkPanel::PaintPieceBackground(
318 	const emPainter & painter, double x, double y, double w, double h,
319 	int px, int py, emColor canvasColor
320 ) const
321 {
322 	int piece,west,north,northwest,tileSize,tx,ty;
323 	double w2,h2;
324 
325 	piece=Mdl->GetPiece(px,py);
326 	west=Mdl->GetPiece(px-1,py);
327 	north=Mdl->GetPiece(px,py-1);
328 	northwest=Mdl->GetPiece(px-1,py-1);
329 
330 	tileSize=ImgBackground.GetWidth()/8;
331 
332 	if (piece&PF_BLOCKED) {
333 		tileSize*=2;
334 		if (west&PF_EAST) {
335 			if (north&PF_SOUTH) { tx=3; ty=0; }
336 			else { tx=2; ty=0; }
337 		}
338 		else {
339 			if (north&PF_SOUTH) { tx=1; ty=0; }
340 			else { tx=0; ty=0; }
341 		}
342 		painter.PaintImage(
343 			x,y,w,h,
344 			ImgBackground,
345 			tx*tileSize,ty*tileSize,tileSize,tileSize,
346 			255,canvasColor
347 		);
348 		return;
349 	}
350 
351 	w2=w*0.5;
352 	h2=h*0.5;
353 
354 	if (north&PF_BLOCKED) {
355 		if (west&PF_BLOCKED) { tx=6; ty=2; }
356 		else if (northwest&PF_BLOCKED) { tx=4; ty=2; }
357 		else { tx=2; ty=2; }
358 	}
359 	else if (northwest&PF_BLOCKED) {
360 		if (west&PF_BLOCKED) { tx=5; ty=2; }
361 		else { tx=1; ty=2; }
362 	}
363 	else {
364 		if (west&PF_BLOCKED) { tx=3; ty=2; }
365 		else { tx=0; ty=2; }
366 	}
367 	painter.PaintImage(
368 		x,y,w2,h2,
369 		ImgBackground,
370 		tx*tileSize,ty*tileSize,tileSize,tileSize,
371 		255,canvasColor
372 	);
373 
374 	if (piece&PF_NORTH) {
375 		if ((piece&PF_CONMASK)==(PF_NORTH|PF_EAST)) {
376 			if (north&PF_BLOCKED) { tx=3; ty=4; }
377 			else if (north&PF_SOUTH) { tx=7; ty=3; }
378 			else { tx=3; ty=3; }
379 		}
380 		else if ((piece&PF_CONMASK)==(PF_NORTH|PF_WEST)) {
381 			if (north&PF_BLOCKED) { tx=2; ty=4; }
382 			else if (north&PF_SOUTH) { tx=6; ty=3; }
383 			else { tx=2; ty=3; }
384 		}
385 		else {
386 			if (north&PF_BLOCKED) { tx=1; ty=4; }
387 			else if (north&PF_SOUTH) { tx=5; ty=3; }
388 			else { tx=1; ty=3; }
389 		}
390 	}
391 	else {
392 		if (north&PF_BLOCKED) { tx=0; ty=4; }
393 		else if (north&PF_SOUTH) { tx=4; ty=3; }
394 		else { tx=0; ty=3; }
395 	}
396 	painter.PaintImage(
397 		x+w2,y,w2,h2,
398 		ImgBackground,
399 		tx*tileSize,ty*tileSize,tileSize,tileSize,
400 		255,canvasColor
401 	);
402 
403 	if (piece&PF_WEST) {
404 		if ((piece&PF_CONMASK)==(PF_WEST|PF_SOUTH)) {
405 			if (west&PF_BLOCKED) { tx=3; ty=6; }
406 			else if (west&PF_EAST) { tx=7; ty=5; }
407 			else { tx=3; ty=5; }
408 		}
409 		else if ((piece&PF_CONMASK)==(PF_WEST|PF_NORTH)) {
410 			if (west&PF_BLOCKED) { tx=2; ty=6; }
411 			else if (west&PF_EAST) { tx=6; ty=5; }
412 			else { tx=2; ty=5; }
413 		}
414 		else {
415 			if (west&PF_BLOCKED) { tx=1; ty=6; }
416 			else if (west&PF_EAST) { tx=5; ty=5; }
417 			else { tx=1; ty=5; }
418 		}
419 	}
420 	else {
421 		if (west&PF_BLOCKED) { tx=0; ty=6; }
422 		else if (west&PF_EAST) { tx=4; ty=5; }
423 		else { tx=0; ty=5; }
424 	}
425 	painter.PaintImage(
426 		x,y+h2,w2,h2,
427 		ImgBackground,
428 		tx*tileSize,ty*tileSize,tileSize,tileSize,
429 		255,canvasColor
430 	);
431 
432 	if (piece&PF_NORTH) {
433 		if (piece&PF_WEST) {
434 			if (piece&PF_SOUTH) {
435 				if (piece&PF_EAST) { tx=7; ty=8; } else { tx=6; ty=8; }
436 			}
437 			else {
438 				if (piece&PF_EAST) { tx=5; ty=8; } else { tx=4; ty=8; }
439 			}
440 		}
441 		else {
442 			if (piece&PF_SOUTH) {
443 				if (piece&PF_EAST) { tx=3; ty=8; } else { tx=2; ty=8; }
444 			}
445 			else {
446 				if (piece&PF_EAST) { tx=1; ty=8; } else { tx=0; ty=8; }
447 			}
448 		}
449 	}
450 	else {
451 		if (piece&PF_WEST) {
452 			if (piece&PF_SOUTH) {
453 				if (piece&PF_EAST) { tx=7; ty=7; } else { tx=6; ty=7; }
454 			}
455 			else {
456 				if (piece&PF_EAST) { tx=5; ty=7; } else { tx=4; ty=7; }
457 			}
458 		}
459 		else {
460 			if (piece&PF_SOUTH) {
461 				if (piece&PF_EAST) { tx=3; ty=7; } else { tx=2; ty=7; }
462 			}
463 			else {
464 				if (piece&PF_EAST) { tx=1; ty=7; } else { tx=0; ty=7; }
465 			}
466 		}
467 	}
468 	painter.PaintImage(
469 		x+w2,y+h2,w2,h2,
470 		ImgBackground,
471 		tx*tileSize,ty*tileSize,tileSize,tileSize,
472 		255,canvasColor
473 	);
474 
475 	if (!(piece&PF_BLOCKED) && (piece&(PF_SOURCE|PF_TARGET))) {
476 		if (piece&PF_SOURCE) tx=0;
477 		else if (!(piece&PF_FILLED)) tx=1;
478 		else tx=2;
479 		tileSize=ImgSymbols.GetWidth()/3;
480 		painter.PaintImage(
481 			x,y,w,h,
482 			ImgSymbols,
483 			tx*tileSize,tileSize,tileSize,tileSize
484 		);
485 	}
486 }
487 
488 
PaintPiecePipe(const emPainter & painter,double x,double y,double w,double h,int px,int py) const489 void emNetwalkPanel::PaintPiecePipe(
490 	const emPainter & painter, double x, double y, double w, double h,
491 	int px, int py
492 ) const
493 {
494 	int piece,east,west,south,north,tileSize,tx,ty;
495 
496 	piece=Mdl->GetPiece(px,py);
497 	east=Mdl->GetPiece(px+1,py);
498 	west=Mdl->GetPiece(px-1,py);
499 	south=Mdl->GetPiece(px,py+1);
500 	north=Mdl->GetPiece(px,py-1);
501 
502 	tileSize=ImgLights.GetWidth()/4;
503 	if ((piece&PF_EAST)==0 && (east&PF_WEST)!=0 && (east&PF_FILLED)!=0) {
504 		PaintImageColoredWithRoundedEdges(
505 			painter,x,y,w,h,ImgLights,
506 			0*tileSize,4*tileSize,tileSize,tileSize,0,LightColor
507 		);
508 	}
509 	if ((piece&PF_SOUTH)==0 && (south&PF_NORTH)!=0 && (south&PF_FILLED)!=0) {
510 		PaintImageColoredWithRoundedEdges(
511 			painter,x,y,w,h,ImgLights,
512 			3*tileSize,3*tileSize,tileSize,tileSize,0,LightColor
513 		);
514 	}
515 	if ((piece&PF_WEST)==0 && (west&PF_EAST)!=0 && (west&PF_FILLED)!=0) {
516 		PaintImageColoredWithRoundedEdges(
517 			painter,x,y,w,h,ImgLights,
518 			1*tileSize,4*tileSize,tileSize,tileSize,0,LightColor
519 		);
520 	}
521 	if ((piece&PF_NORTH)==0 && (north&PF_SOUTH)!=0 && (north&PF_FILLED)!=0) {
522 		PaintImageColoredWithRoundedEdges(
523 			painter,x,y,w,h,ImgLights,
524 			3*tileSize,4*tileSize,tileSize,tileSize,0,LightColor
525 		);
526 	}
527 
528 	if (piece&PF_NORTH) {
529 		if (piece&PF_WEST) {
530 			if (piece&PF_SOUTH) {
531 				if (piece&PF_EAST) { tx=1; ty=1; } else { tx=2; ty=1; }
532 			}
533 			else {
534 				if (piece&PF_EAST) { tx=1; ty=2; } else { tx=2; ty=2; }
535 			}
536 		}
537 		else {
538 			if (piece&PF_SOUTH) {
539 				if (piece&PF_EAST) { tx=0; ty=1; } else { tx=3; ty=1; }
540 			}
541 			else {
542 				if (piece&PF_EAST) { tx=0; ty=2; } else { tx=3; ty=2; }
543 			}
544 		}
545 	}
546 	else {
547 		if (piece&PF_WEST) {
548 			if (piece&PF_SOUTH) {
549 				if (piece&PF_EAST) { tx=1; ty=0; } else { tx=2; ty=0; }
550 			}
551 			else {
552 				if (piece&PF_EAST) { tx=1; ty=3; } else { tx=2; ty=3; }
553 			}
554 		}
555 		else {
556 			if (piece&PF_SOUTH) {
557 				if (piece&PF_EAST) { tx=0; ty=0; } else { tx=3; ty=0; }
558 			}
559 			else {
560 				if (piece&PF_EAST) { tx=0; ty=3; } else { tx=3; ty=3; }
561 			}
562 		}
563 	}
564 
565 	if ((piece&PF_FILLED)==0 || !LightColor.IsOpaque()) {
566 		tileSize=ImgPipes.GetWidth()/4;
567 		PaintImageWithRoundedEdges(
568 			painter,x,y,w,h,ImgPipes,
569 			tx*tileSize,ty*tileSize,tileSize,tileSize
570 		);
571 	}
572 	if (piece&PF_FILLED) {
573 		tileSize=ImgLights.GetWidth()/4;
574 		PaintImageColoredWithRoundedEdges(
575 			painter,x,y,w,h,ImgLights,
576 			tx*tileSize,ty*tileSize,tileSize,tileSize,0,LightColor
577 		);
578 	}
579 
580 	if (piece&PF_MARKED) {
581 		tileSize=ImgMarks.GetWidth()/4;
582 		PaintImageColoredWithRoundedEdges(
583 			painter,x,y,w,h,ImgMarks,
584 			tx*tileSize,ty*tileSize,tileSize,tileSize,0,MarkColor
585 		);
586 	}
587 
588 	if (piece&(PF_SOURCE|PF_TARGET)) {
589 		if (piece&PF_SOURCE) tx=0;
590 		else if (!(piece&PF_FILLED)) tx=1;
591 		else tx=2;
592 		tileSize=ImgSymbols.GetWidth()/3;
593 		painter.PaintImage(
594 			x,y,w,h,
595 			ImgSymbols,
596 			tx*tileSize,0,tileSize,tileSize
597 		);
598 	}
599 }
600 
601 
PaintImageColoredWithRoundedEdges(const emPainter & painter,double x,double y,double w,double h,const emImage & img,int srcX,int srcY,int srcW,int srcH,emColor color1,emColor color2,emColor canvasColor)602 void emNetwalkPanel::PaintImageColoredWithRoundedEdges(
603 	const emPainter & painter, double x, double y, double w, double h,
604 	const emImage & img, int srcX, int srcY, int srcW, int srcH,
605 	emColor color1, emColor color2, emColor canvasColor
606 )
607 {
608 	double rx,ry,rw,rh;
609 
610 	rx=painter.RoundX(x);
611 	ry=painter.RoundY(y);
612 	rw=painter.RoundX(x+w)-rx;
613 	rh=painter.RoundY(y+h)-ry;
614 	painter.PaintImageColored(
615 		rx,ry,rw,rh,
616 		img,
617 		srcX,srcY,srcW,srcH,
618 		color1,color2,canvasColor,emTexture::EXTEND_EDGE
619 	);
620 }
621 
622 
PaintImageWithRoundedEdges(const emPainter & painter,double x,double y,double w,double h,const emImage & img,int srcX,int srcY,int srcW,int srcH,int alpha,emColor canvasColor)623 void emNetwalkPanel::PaintImageWithRoundedEdges(
624 	const emPainter & painter, double x, double y, double w, double h,
625 	const emImage & img, int srcX, int srcY, int srcW, int srcH,
626 	int alpha, emColor canvasColor
627 )
628 {
629 	double rx,ry,rw,rh;
630 
631 	rx=painter.RoundX(x);
632 	ry=painter.RoundY(y);
633 	rw=painter.RoundX(x+w)-rx;
634 	rh=painter.RoundY(y+h)-ry;
635 	painter.PaintImage(
636 		rx,ry,rw,rh,
637 		img,
638 		srcX,srcY,srcW,srcH,
639 		alpha,canvasColor,emTexture::EXTEND_EDGE
640 	);
641 }
642 
643 
PrepareTransformation()644 void emNetwalkPanel::PrepareTransformation()
645 {
646 	double h,bs,tw,th;
647 
648 	if (!IsViewed() || !IsVFSGood()) {
649 		EssenceX=0.0;
650 		EssenceY=0.0;
651 		EssenceW=1.0;
652 		EssenceH=GetHeight();
653 		X0=0.0;
654 		Y0=0.0;
655 		DX=1.0;
656 		DY=1.0;
657 	}
658 	else {
659 		h=GetHeight();
660 		bs=Mdl->IsBorderless() ? 1.0 : BorderSize;
661 		tw=Mdl->GetWidth()+2*bs;
662 		th=Mdl->GetHeight()+2*bs;
663 		DX=emMin(1.0/tw,h/th)*0.85;
664 		DY=DX;
665 		EssenceW=tw*DX;
666 		EssenceH=th*DY;
667 		EssenceX=(1.0-EssenceW)*0.5;
668 		EssenceY=(h-EssenceH)*0.5;
669 		X0=EssenceX+bs*DX;
670 		Y0=EssenceY+bs*DY;
671 	}
672 }
673 
674 
675 const double emNetwalkPanel::BorderSize=0.333333;
676 const emColor emNetwalkPanel::BgColor=0x000000FF;
677 const emColor emNetwalkPanel::LightColor=0x00FFCCBB;
678 const emColor emNetwalkPanel::MarkColor=0xDDDDDD55;
679