1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: ui_widget.cpp 4339 2010-12-14 12:07:27Z dj_jl $
11 //**
12 //**	Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 
26 // HEADER FILES ------------------------------------------------------------
27 
28 #include "gamedefs.h"
29 #include "cl_local.h"
30 #include "drawer.h"
31 #include "ui.h"
32 
33 // MACROS ------------------------------------------------------------------
34 
35 // TYPES -------------------------------------------------------------------
36 
37 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
38 
39 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
40 
41 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
42 
43 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
44 
45 // PUBLIC DATA DEFINITIONS -------------------------------------------------
46 
47 IMPLEMENT_CLASS(V, Widget);
48 
49 // PRIVATE DATA DEFINITIONS ------------------------------------------------
50 
51 // CODE --------------------------------------------------------------------
52 
53 //==========================================================================
54 //
55 //	VWidget::CreateNewWidget
56 //
57 //==========================================================================
58 
CreateNewWidget(VClass * AClass,VWidget * AParent)59 VWidget* VWidget::CreateNewWidget(VClass* AClass, VWidget* AParent)
60 {
61 	guard(VWidget::CreateNewWidget);
62 	VWidget* W = (VWidget*)StaticSpawnObject(AClass);
63 	W->Init(AParent);
64 	return W;
65 	unguardf(("(%s)", AClass->GetName()));
66 }
67 
68 //==========================================================================
69 //
70 //	VWidget::Init
71 //
72 //==========================================================================
73 
Init(VWidget * AParent)74 void VWidget::Init(VWidget* AParent)
75 {
76 	guard(VWidget::Init);
77 	// Set default values
78 	SetFont(SmallFont);
79 	SetTextAlign(hleft, vtop);
80 
81 	ParentWidget = AParent;
82 	if (ParentWidget)
83 	{
84 		ParentWidget->AddChild(this);
85 	}
86 	ClipTree();
87 	OnCreate();
88 	unguard;
89 }
90 
91 //==========================================================================
92 //
93 //	VWidget::Destroy
94 //
95 //==========================================================================
96 
Destroy()97 void VWidget::Destroy()
98 {
99 	guard(VWidget::Destroy);
100 	OnDestroy();
101 	DestroyAllChildren();
102 	if (ParentWidget)
103 	{
104 		ParentWidget->RemoveChild(this);
105 	}
106 	Super::Destroy();
107 	unguard;
108 }
109 
110 //==========================================================================
111 //
112 //	VWidget::AddChild
113 //
114 //==========================================================================
115 
AddChild(VWidget * NewChild)116 void VWidget::AddChild(VWidget* NewChild)
117 {
118 	guard(VWidget::AddChild);
119 	NewChild->PrevWidget = LastChildWidget;
120 	NewChild->NextWidget = NULL;
121 	if (LastChildWidget)
122 	{
123 		LastChildWidget->NextWidget = NewChild;
124 	}
125 	else
126 	{
127 		FirstChildWidget = NewChild;
128 	}
129 	LastChildWidget = NewChild;
130 	OnChildAdded(NewChild);
131 	if (!CurrentFocusChild)
132 	{
133 		SetCurrentFocusChild(NewChild);
134 	}
135 	unguard;
136 }
137 
138 //==========================================================================
139 //
140 //	VWidget::RemoveChild
141 //
142 //==========================================================================
143 
RemoveChild(VWidget * InChild)144 void VWidget::RemoveChild(VWidget* InChild)
145 {
146 	guard(VWidget::RemoveChild);
147 	if (InChild->PrevWidget)
148 	{
149 		InChild->PrevWidget->NextWidget = InChild->NextWidget;
150 	}
151 	else
152 	{
153 		FirstChildWidget = InChild->NextWidget;
154 	}
155 	if (InChild->NextWidget)
156 	{
157 		InChild->NextWidget->PrevWidget = InChild->PrevWidget;
158 	}
159 	else
160 	{
161 		LastChildWidget = InChild->PrevWidget;
162 	}
163 	InChild->PrevWidget = NULL;
164 	InChild->NextWidget = NULL;
165 	InChild->ParentWidget = NULL;
166 	OnChildRemoved(InChild);
167 	if (CurrentFocusChild == InChild)
168 	{
169 		FindNewFocus();
170 	}
171 	unguard;
172 }
173 
174 //==========================================================================
175 //
176 //	VWidget::DestroyAllChildren
177 //
178 //==========================================================================
179 
DestroyAllChildren()180 void VWidget::DestroyAllChildren()
181 {
182 	guard(VWidget::DestroyAllChildren);
183 	while (FirstChildWidget)
184 	{
185 		FirstChildWidget->ConditionalDestroy();
186 	}
187 	unguard;
188 }
189 
190 //==========================================================================
191 //
192 //	VWidget::GetRootWidget
193 //
194 //==========================================================================
195 
GetRootWidget()196 VRootWidget* VWidget::GetRootWidget()
197 {
198 	guard(VWidget::GetRootWidget);
199 	VWidget* W = this;
200 	while (W->ParentWidget)
201 	{
202 		W = W->ParentWidget;
203 	}
204 	return (VRootWidget*)W;
205 	unguard;
206 }
207 
208 //==========================================================================
209 //
210 //	VWidget::Lower
211 //
212 //==========================================================================
213 
Lower()214 void VWidget::Lower()
215 {
216 	guard(VWidget::Lower);
217 	if (!ParentWidget)
218 	{
219 		Sys_Error("Can't lower root window");
220 	}
221 
222 	if (ParentWidget->FirstChildWidget == this)
223 	{
224 		//	Already there
225 		return;
226 	}
227 
228 	//	Unlink from current location
229 	PrevWidget->NextWidget = NextWidget;
230 	if (NextWidget)
231 	{
232 		NextWidget->PrevWidget = PrevWidget;
233 	}
234 	else
235 	{
236 		ParentWidget->LastChildWidget = PrevWidget;
237 	}
238 
239 	//	Link on bottom
240 	PrevWidget = NULL;
241 	NextWidget = ParentWidget->FirstChildWidget;
242 	ParentWidget->FirstChildWidget->PrevWidget = this;
243 	ParentWidget->FirstChildWidget = this;
244 	unguard;
245 }
246 
247 //==========================================================================
248 //
249 //	VWidget::Raise
250 //
251 //==========================================================================
252 
Raise()253 void VWidget::Raise()
254 {
255 	guard(VWidget::Raise);
256 	if (!ParentWidget)
257 	{
258 		Sys_Error("Can't raise root window");
259 	}
260 
261 	if (ParentWidget->LastChildWidget == this)
262 	{
263 		//	Already there
264 		return;
265 	}
266 
267 	//	Unlink from current location
268 	NextWidget->PrevWidget = PrevWidget;
269 	if (PrevWidget)
270 	{
271 		PrevWidget->NextWidget = NextWidget;
272 	}
273 	else
274 	{
275 		ParentWidget->FirstChildWidget = NextWidget;
276 	}
277 
278 	//	Link on top
279 	PrevWidget = ParentWidget->LastChildWidget;
280 	NextWidget = NULL;
281 	ParentWidget->LastChildWidget->NextWidget = this;
282 	ParentWidget->LastChildWidget = this;
283 	unguard;
284 }
285 
286 //==========================================================================
287 //
288 //	VWidget::MoveBefore
289 //
290 //==========================================================================
291 
MoveBefore(VWidget * Other)292 void VWidget::MoveBefore(VWidget* Other)
293 {
294 	guard(VWidget::MoveBefore);
295 	if (ParentWidget != Other->ParentWidget)
296 	{
297 		Sys_Error("Must have the same parent widget");
298 	}
299 	if (Other == this)
300 	{
301 		Sys_Error("Can't move before self");
302 	}
303 
304 	if (Other->PrevWidget == this)
305 	{
306 		//	Already there
307 		return;
308 	}
309 
310 	//	Unlink from current location
311 	if (PrevWidget)
312 	{
313 		PrevWidget->NextWidget = NextWidget;
314 	}
315 	else
316 	{
317 		ParentWidget->FirstChildWidget = NextWidget;
318 	}
319 	if (NextWidget)
320 	{
321 		NextWidget->PrevWidget = PrevWidget;
322 	}
323 	else
324 	{
325 		ParentWidget->LastChildWidget = PrevWidget;
326 	}
327 
328 	//	Link in new position
329 	PrevWidget = Other->PrevWidget;
330 	NextWidget = Other;
331 	Other->PrevWidget = this;
332 	if (PrevWidget)
333 	{
334 		PrevWidget->NextWidget = this;
335 	}
336 	else
337 	{
338 		ParentWidget->FirstChildWidget = this;
339 	}
340 	unguard;
341 }
342 
343 //==========================================================================
344 //
345 //	VWidget::MoveAfter
346 //
347 //==========================================================================
348 
MoveAfter(VWidget * Other)349 void VWidget::MoveAfter(VWidget* Other)
350 {
351 	guard(VWidget::MoveAfter);
352 	if (ParentWidget != Other->ParentWidget)
353 	{
354 		Sys_Error("Must have the same parent widget");
355 	}
356 	if (Other == this)
357 	{
358 		Sys_Error("Can't move after self");
359 	}
360 
361 	if (Other->NextWidget == this)
362 	{
363 		//	Already there
364 		return;
365 	}
366 
367 	//	Unlink from current location
368 	if (PrevWidget)
369 	{
370 		PrevWidget->NextWidget = NextWidget;
371 	}
372 	else
373 	{
374 		ParentWidget->FirstChildWidget = NextWidget;
375 	}
376 	if (NextWidget)
377 	{
378 		NextWidget->PrevWidget = PrevWidget;
379 	}
380 	else
381 	{
382 		ParentWidget->LastChildWidget = PrevWidget;
383 	}
384 
385 	//	Link in new position
386 	NextWidget = Other->NextWidget;
387 	PrevWidget = Other;
388 	Other->NextWidget = this;
389 	if (NextWidget)
390 	{
391 		NextWidget->PrevWidget = this;
392 	}
393 	else
394 	{
395 		ParentWidget->LastChildWidget = this;
396 	}
397 	unguard;
398 }
399 
400 //==========================================================================
401 //
402 //	VWidget::ClipTree
403 //
404 //==========================================================================
405 
ClipTree()406 void VWidget::ClipTree()
407 {
408 	guard(VWidget::ClipTree);
409 	//	Set up clipping rectangle.
410 	if (ParentWidget)
411 	{
412 		//	Clipping rectangle is relative to the parent widget.
413 		ClipRect.OriginX = ParentWidget->ClipRect.OriginX +
414 			ParentWidget->ClipRect.ScaleX * PosX;
415 		ClipRect.OriginY = ParentWidget->ClipRect.OriginY +
416 			ParentWidget->ClipRect.ScaleY * PosY;
417 		ClipRect.ScaleX = ParentWidget->ClipRect.ScaleX * SizeScaleX;
418 		ClipRect.ScaleY = ParentWidget->ClipRect.ScaleY * SizeScaleY;
419 		ClipRect.ClipX1 = ClipRect.OriginX;
420 		ClipRect.ClipY1 = ClipRect.OriginY;
421 		ClipRect.ClipX2 = ClipRect.OriginX + ClipRect.ScaleX * SizeWidth;
422 		ClipRect.ClipY2 = ClipRect.OriginY + ClipRect.ScaleY * SizeHeight;
423 
424 		//	Clip against the parent widget's clipping rectangle.
425 		if (ClipRect.ClipX1 < ParentWidget->ClipRect.ClipX1)
426 		{
427 			ClipRect.ClipX1 = ParentWidget->ClipRect.ClipX1;
428 		}
429 		if (ClipRect.ClipY1 < ParentWidget->ClipRect.ClipY1)
430 		{
431 			ClipRect.ClipY1 = ParentWidget->ClipRect.ClipY1;
432 		}
433 		if (ClipRect.ClipX2 > ParentWidget->ClipRect.ClipX2)
434 		{
435 			ClipRect.ClipX2 = ParentWidget->ClipRect.ClipX2;
436 		}
437 		if (ClipRect.ClipY2 > ParentWidget->ClipRect.ClipY2)
438 		{
439 			ClipRect.ClipY2 = ParentWidget->ClipRect.ClipY2;
440 		}
441 	}
442 	else
443 	{
444 		//	This is the root widget.
445 		ClipRect.OriginX = PosX;
446 		ClipRect.OriginY = PosY;
447 		ClipRect.ScaleX = SizeScaleX;
448 		ClipRect.ScaleY = SizeScaleY;
449 		ClipRect.ClipX1 = ClipRect.OriginX;
450 		ClipRect.ClipY1 = ClipRect.OriginY;
451 		ClipRect.ClipX2 = ClipRect.OriginX + ClipRect.ScaleX * SizeWidth;
452 		ClipRect.ClipY2 = ClipRect.OriginY + ClipRect.ScaleY * SizeHeight;
453 	}
454 
455 	//	Set up clipping rectangles in child widgets.
456 	for (VWidget* W = FirstChildWidget; W; W = W->NextWidget)
457 	{
458 		W->ClipTree();
459 	}
460 	unguard;
461 }
462 
463 //==========================================================================
464 //
465 //	VWidget::SetConfiguration
466 //
467 //==========================================================================
468 
SetConfiguration(int NewX,int NewY,int NewWidth,int HewHeight,float NewScaleX,float NewScaleY)469 void VWidget::SetConfiguration(int NewX, int NewY, int NewWidth,
470 	int HewHeight, float NewScaleX, float NewScaleY)
471 {
472 	guard(VWidget::SetConfiguration);
473 	PosX = NewX;
474 	PosY = NewY;
475 	SizeWidth = NewWidth;
476 	SizeHeight = HewHeight;
477 	SizeScaleX = NewScaleX;
478 	SizeScaleY = NewScaleY;
479 	ClipTree();
480 	OnConfigurationChanged();
481 	unguard;
482 }
483 
484 //==========================================================================
485 //
486 //	VWidget::SetVisibility
487 //
488 //==========================================================================
489 
SetVisibility(bool NewVisibility)490 void VWidget::SetVisibility(bool NewVisibility)
491 {
492 	guard(VWidget::SetVisibility);
493 	if (!!(WidgetFlags & WF_IsVisible) != NewVisibility)
494 	{
495 		if (NewVisibility)
496 		{
497 			WidgetFlags |= WF_IsVisible;
498 			if (ParentWidget && !ParentWidget->CurrentFocusChild)
499 			{
500 				ParentWidget->SetCurrentFocusChild(this);
501 			}
502 		}
503 		else
504 		{
505 			WidgetFlags &= ~WF_IsVisible;
506 			if (ParentWidget && ParentWidget->CurrentFocusChild == this)
507 			{
508 				ParentWidget->FindNewFocus();
509 			}
510 		}
511 		OnVisibilityChanged(NewVisibility);
512 	}
513 	unguard;
514 }
515 
516 //==========================================================================
517 //
518 //	VWidget::SetEnabled
519 //
520 //==========================================================================
521 
SetEnabled(bool NewEnabled)522 void VWidget::SetEnabled(bool NewEnabled)
523 {
524 	guard(VWidget::SetEnabled);
525 	if (!!(WidgetFlags & WF_IsEnabled) != NewEnabled)
526 	{
527 		if (NewEnabled)
528 		{
529 			WidgetFlags |= WF_IsEnabled;
530 			if (ParentWidget && !ParentWidget->CurrentFocusChild)
531 			{
532 				ParentWidget->SetCurrentFocusChild(this);
533 			}
534 		}
535 		else
536 		{
537 			WidgetFlags &= ~WF_IsEnabled;
538 			if (ParentWidget && ParentWidget->CurrentFocusChild == this)
539 			{
540 				ParentWidget->FindNewFocus();
541 			}
542 		}
543 		OnEnableChanged(NewEnabled);
544 	}
545 	unguard;
546 }
547 
548 //==========================================================================
549 //
550 //	VWidget::SetFocusable
551 //
552 //==========================================================================
553 
SetFocusable(bool NewFocusable)554 void VWidget::SetFocusable(bool NewFocusable)
555 {
556 	guard(VWidget::SetFocusable);
557 	if (!!(WidgetFlags & WF_IsFocusable) != NewFocusable)
558 	{
559 		if (NewFocusable)
560 		{
561 			WidgetFlags |= WF_IsFocusable;
562 			if (ParentWidget && !ParentWidget->CurrentFocusChild)
563 			{
564 				ParentWidget->SetCurrentFocusChild(this);
565 			}
566 		}
567 		else
568 		{
569 			WidgetFlags &= ~WF_IsFocusable;
570 			if (ParentWidget && ParentWidget->CurrentFocusChild == this)
571 			{
572 				ParentWidget->FindNewFocus();
573 			}
574 		}
575 		OnFocusableChanged(NewFocusable);
576 	}
577 	unguard;
578 }
579 
580 //==========================================================================
581 //
582 //	VWidget::SetCurrentFocusChild
583 //
584 //==========================================================================
585 
SetCurrentFocusChild(VWidget * NewFocus)586 void VWidget::SetCurrentFocusChild(VWidget* NewFocus)
587 {
588 	guard(VWidget::SetCurrentFocusChild);
589 	//	Check f it's already focused.
590 	if (CurrentFocusChild == NewFocus)
591 	{
592 		return;
593 	}
594 
595 	//	Make sure it's visible, enabled and focusable.
596 	if (NewFocus && (!(NewFocus->WidgetFlags & WF_IsVisible) ||
597 		!(NewFocus->WidgetFlags & WF_IsEnabled) ||
598 		!(NewFocus->WidgetFlags & WF_IsFocusable)))
599 	{
600 		return;
601 	}
602 
603 	//	If we have a focused child, send focus lost event.
604 	if (CurrentFocusChild)
605 	{
606 		CurrentFocusChild->OnFocusLost();
607 	}
608 
609 	//	Make it the current focus.
610 	CurrentFocusChild = NewFocus;
611 	if (CurrentFocusChild)
612 	{
613 		CurrentFocusChild->OnFocusReceived();
614 	}
615 	unguard;
616 }
617 
618 //==========================================================================
619 //
620 //	VWidget::IsFocus
621 //
622 //==========================================================================
623 
IsFocus(bool Recurse) const624 bool VWidget::IsFocus(bool Recurse) const
625 {
626 	guard(VWidget::IsFocus);
627 	//	Root is always focused.
628 	if (!ParentWidget)
629 	{
630 		return true;
631 	}
632 	if (Recurse)
633 	{
634 		const VWidget* W = this;
635 		while (W->ParentWidget && W->ParentWidget->CurrentFocusChild == W)
636 		{
637 			W = W->ParentWidget;
638 		}
639 		return !W->ParentWidget;
640 	}
641 	else
642 	{
643 		return ParentWidget->CurrentFocusChild == this;
644 	}
645 	unguard;
646 }
647 
648 //==========================================================================
649 //
650 //	VWidget::SetFocus
651 //
652 //==========================================================================
653 
SetFocus()654 void VWidget::SetFocus()
655 {
656 	guard(VWidget::SetFocus);
657 	if (ParentWidget)
658 	{
659 		ParentWidget->SetCurrentFocusChild(this);
660 	}
661 	unguard;
662 }
663 
664 //==========================================================================
665 //
666 //	VWidget::FindNewFocus
667 //
668 //==========================================================================
669 
FindNewFocus()670 void VWidget::FindNewFocus()
671 {
672 	guard(VWidget::FindNewFocus);
673 	for (VWidget* W = CurrentFocusChild->NextWidget; W; W = W->NextWidget)
674 	{
675 		if ((W->WidgetFlags & WF_IsFocusable) &&
676 			(W->WidgetFlags & WF_IsVisible) &&
677 			(W->WidgetFlags & WF_IsEnabled))
678 		{
679 			SetCurrentFocusChild(W);
680 			return;
681 		}
682 	}
683 
684 	for (VWidget* W = CurrentFocusChild->PrevWidget; W; W = W->PrevWidget)
685 	{
686 		if ((W->WidgetFlags & WF_IsFocusable) &&
687 			(W->WidgetFlags & WF_IsVisible) &&
688 			(W->WidgetFlags & WF_IsEnabled))
689 		{
690 			SetCurrentFocusChild(W);
691 			return;
692 		}
693 	}
694 
695 	SetCurrentFocusChild(NULL);
696 	unguard;
697 }
698 
699 //==========================================================================
700 //
701 //	VWidget::GetWidgetAt
702 //
703 //==========================================================================
704 
GetWidgetAt(float X,float Y)705 VWidget* VWidget::GetWidgetAt(float X, float Y)
706 {
707 	guard(VWidget::GetWidgetAt);
708 	for (VWidget* W = LastChildWidget; W; W = W->PrevWidget)
709 	{
710 		if (!(W->WidgetFlags & WF_IsVisible))
711 		{
712 			continue;
713 		}
714 		if (X >= W->ClipRect.ClipX1 && X < W->ClipRect.ClipX2 &&
715 			Y >= W->ClipRect.ClipY1 && Y < W->ClipRect.ClipY2)
716 		{
717 			return W->GetWidgetAt(X, Y);
718 		}
719 	}
720 	return this;
721 	unguard;
722 }
723 
724 //==========================================================================
725 //
726 //	VWidget::DrawTree
727 //
728 //==========================================================================
729 
DrawTree()730 void VWidget::DrawTree()
731 {
732 	guard(VWidget::DrawTree);
733 	if (!(WidgetFlags & WF_IsVisible) || !ClipRect.HasArea())
734 	{
735 		//	Not visible or clipped away.
736 		return;
737 	}
738 
739 	//	Main draw event for this widget.
740 	OnDraw();
741 
742 	//	Draw chid widgets.
743 	for (VWidget* c = FirstChildWidget; c; c = c->NextWidget)
744 	{
745 		c->DrawTree();
746 	}
747 
748 	//	Do any drawing after child wigets have been drawn.
749 	OnPostDraw();
750 	unguard;
751 }
752 
753 //==========================================================================
754 //
755 //	VWidget::TickTree
756 //
757 //==========================================================================
758 
TickTree(float DeltaTime)759 void VWidget::TickTree(float DeltaTime)
760 {
761 	guard(VWidget::TickTree);
762 	if (WidgetFlags & WF_TickEnabled)
763 	{
764 		Tick(DeltaTime);
765 	}
766 	for (VWidget* c = FirstChildWidget; c; c = c->NextWidget)
767 	{
768 		c->TickTree(DeltaTime);
769 	}
770 	unguard;
771 }
772 
773 //==========================================================================
774 //
775 //	VWidget::TransferAndClipRect
776 //
777 //==========================================================================
778 
TransferAndClipRect(float & X1,float & Y1,float & X2,float & Y2,float & S1,float & T1,float & S2,float & T2) const779 bool VWidget::TransferAndClipRect(float& X1, float& Y1, float& X2, float& Y2,
780 	float& S1, float& T1, float& S2, float& T2) const
781 {
782 	guard(VWidget::TransferAndClipRect);
783 	X1 = ClipRect.ScaleX * X1 + ClipRect.OriginX;
784 	Y1 = ClipRect.ScaleY * Y1 + ClipRect.OriginY;
785 	X2 = ClipRect.ScaleX * X2 + ClipRect.OriginX;
786 	Y2 = ClipRect.ScaleY * Y2 + ClipRect.OriginY;
787 	if (X1 < ClipRect.ClipX1)
788 	{
789 		S1 = S1 + (X1 - ClipRect.ClipX1) / (X1 - X2) * (S2 - S1);
790 		X1 = ClipRect.ClipX1;
791 	}
792 	if (X2 > ClipRect.ClipX2)
793 	{
794 		S2 = S2 + (X2 - ClipRect.ClipX2) / (X1 - X2) * (S2 - S1);
795 		X2 = ClipRect.ClipX2;
796 	}
797 	if (Y1 < ClipRect.ClipY1)
798 	{
799 		T1 = T1 + (Y1 - ClipRect.ClipY1) / (Y1 - Y2) * (T2 - T1);
800 		Y1 = ClipRect.ClipY1;
801 	}
802 	if (Y2 > ClipRect.ClipY2)
803 	{
804 		T2 = T2 + (Y2 - ClipRect.ClipY2) / (Y1 - Y2) * (T2 - T1);
805 		Y2 = ClipRect.ClipY2;
806 	}
807 	return X1 < X2 && Y1 < Y2;
808 	unguard;
809 }
810 
811 //==========================================================================
812 //
813 //	VWidget::DrawPic
814 //
815 //==========================================================================
816 
DrawPic(int X,int Y,int Handle,float Alpha,int Trans)817 void VWidget::DrawPic(int X, int Y, int Handle, float Alpha, int Trans)
818 {
819 	guard(VWidget::DrawPic);
820 	DrawPic(X, Y, GTextureManager(Handle), Alpha, Trans);
821 	unguard;
822 }
823 
824 //==========================================================================
825 //
826 //	VWidget::DrawPic
827 //
828 //==========================================================================
829 
DrawPic(int X,int Y,VTexture * Tex,float Alpha,int Trans)830 void VWidget::DrawPic(int X, int Y, VTexture* Tex, float Alpha, int Trans)
831 {
832 	guard(VWidget::DrawPic);
833 	if (!Tex)
834 	{
835 		return;
836 	}
837 
838 	X -= Tex->GetScaledSOffset();
839 	Y -= Tex->GetScaledTOffset();
840 	float X1 = X;
841 	float Y1 = Y;
842 	float X2 = X + Tex->GetScaledWidth();
843 	float Y2 = Y + Tex->GetScaledHeight();
844 	float S1 = 0;
845 	float T1 = 0;
846 	float S2 = Tex->GetWidth();
847 	float T2 = Tex->GetHeight();
848 	if (TransferAndClipRect(X1, Y1, X2, Y2, S1, T1, S2, T2))
849 	{
850 		Drawer->DrawPic(X1, Y1, X2, Y2, S1, T1, S2, T2, Tex,
851 			R_GetCachedTranslation(Trans, NULL), Alpha);
852 	}
853 	unguard;
854 }
855 
856 //==========================================================================
857 //
858 //	VWidget::DrawShadowedPic
859 //
860 //==========================================================================
861 
DrawShadowedPic(int X,int Y,int Handle)862 void VWidget::DrawShadowedPic(int X, int Y, int Handle)
863 {
864 	guard(VWidget::DrawShadowedPic);
865 	DrawShadowedPic(X, Y, GTextureManager(Handle));
866 	unguard;
867 }
868 
869 //==========================================================================
870 //
871 //	VWidget::DrawShadowedPic
872 //
873 //==========================================================================
874 
DrawShadowedPic(int X,int Y,VTexture * Tex)875 void VWidget::DrawShadowedPic(int X, int Y, VTexture* Tex)
876 {
877 	guard(VWidget::DrawShadowedPic);
878 	if (!Tex)
879 	{
880 		return;
881 	}
882 
883 	float X1 = X - Tex->GetScaledSOffset() + 2;
884 	float Y1 = Y - Tex->GetScaledTOffset() + 2;
885 	float X2 = X - Tex->GetScaledSOffset() + 2 + Tex->GetScaledWidth();
886 	float Y2 = Y - Tex->GetScaledTOffset() + 2 + Tex->GetScaledHeight();
887 	float S1 = 0;
888 	float T1 = 0;
889 	float S2 = Tex->GetWidth();
890 	float T2 = Tex->GetHeight();
891 	if (TransferAndClipRect(X1, Y1, X2, Y2, S1, T1, S2, T2))
892 	{
893 		Drawer->DrawPicShadow(X1, Y1, X2, Y2, S1, T1, S2, T2, Tex, 0.625);
894 	}
895 
896 	DrawPic(X, Y, Tex);
897 	unguard;
898 }
899 
900 //==========================================================================
901 //
902 //	VWidget::FillRectWithFlat
903 //
904 //==========================================================================
905 
FillRectWithFlat(int X,int Y,int Width,int Height,VName Name)906 void VWidget::FillRectWithFlat(int X, int Y, int Width, int Height,
907 	VName Name)
908 {
909 	guard(VWidget::FillRectWithFlat);
910 	float X1 = X;
911 	float Y1 = Y;
912 	float X2 = X + Width;
913 	float Y2 = Y + Height;
914 	float S1 = 0;
915 	float T1 = 0;
916 	float S2 = Width;
917 	float T2 = Height;
918 	if (TransferAndClipRect(X1, Y1, X2, Y2, S1, T1, S2, T2))
919 	{
920 		Drawer->FillRectWithFlat(X1, Y1, X2, Y2, S1, T1, S2, T2,
921 			GTextureManager(GTextureManager.NumForName(Name, TEXTYPE_Flat,
922 			true, true)));
923 	}
924 	unguard;
925 }
926 
927 //==========================================================================
928 //
929 //	VWidget::ShadeRect
930 //
931 //==========================================================================
932 
ShadeRect(int X,int Y,int Width,int Height,float Shade)933 void VWidget::ShadeRect(int X, int Y, int Width, int Height, float Shade)
934 {
935 	guard(VWidget::ShadeRect);
936 	float X1 = X;
937 	float Y1 = Y;
938 	float X2 = X + Width;
939 	float Y2 = Y + Height;
940 	float S1 = 0;
941 	float T1 = 0;
942 	float S2 = 0;
943 	float T2 = 0;
944 	if (TransferAndClipRect(X1, Y1, X2, Y2, S1, T1, S2, T2))
945 	{
946 		Drawer->ShadeRect((int)X1, (int)Y1, (int)X2 - (int)X1, (int)Y2 - (int)Y1, Shade);
947 	}
948 	unguard;
949 }
950 
951 //==========================================================================
952 //
953 //	VWidget::SetFont
954 //
955 //==========================================================================
956 
SetFont(VFont * AFont)957 void VWidget::SetFont(VFont* AFont)
958 {
959 	guard(VWidget::SetFont);
960 	Font = AFont;
961 	unguard;
962 }
963 
964 //==========================================================================
965 //
966 //	VWidget::SetFont
967 //
968 //==========================================================================
969 
SetFont(VName FontName)970 void VWidget::SetFont(VName FontName)
971 {
972 	guard(VWidget::SetFont);
973 	VFont* F = VFont::GetFont(FontName, FontName);
974 	if (F)
975 	{
976 		Font = F;
977 	}
978 	else
979 	{
980 		GCon->Logf("No such font %s", *FontName);
981 	}
982 	unguard;
983 }
984 
985 //==========================================================================
986 //
987 //	VWidget::SetTextAlign
988 //
989 //==========================================================================
990 
SetTextAlign(halign_e NewHAlign,valign_e NewVAlign)991 void VWidget::SetTextAlign(halign_e NewHAlign, valign_e NewVAlign)
992 {
993 	guard(VWidget::SetTextAlign);
994 	HAlign = NewHAlign;
995 	VAlign = NewVAlign;
996 	unguard;
997 }
998 
999 //==========================================================================
1000 //
1001 //	VWidget::SetTextShadow
1002 //
1003 //==========================================================================
1004 
SetTextShadow(bool State)1005 void VWidget::SetTextShadow(bool State)
1006 {
1007 	if (State)
1008 		WidgetFlags |= WF_TextShadowed;
1009 	else
1010 		WidgetFlags &= ~WF_TextShadowed;
1011 }
1012 
1013 //==========================================================================
1014 //
1015 //	VWidget::DrawString
1016 //
1017 //==========================================================================
1018 
DrawString(int x,int y,const VStr & String,int NormalColour,int BoldColour,float Alpha)1019 void VWidget::DrawString(int x, int y, const VStr& String, int NormalColour,
1020 	int BoldColour, float Alpha)
1021 {
1022 	guard(VWidget::DrawNString);
1023 	if (String.IsEmpty())
1024 		return;
1025 
1026 	int cx = x;
1027 	int cy = y;
1028 	int Kerning = Font->GetKerning();
1029 	int Colour = NormalColour;
1030 
1031 	if (HAlign == hcentre)
1032 		cx -= Font->StringWidth(String) / 2;
1033 	if (HAlign == hright)
1034 		cx -= Font->StringWidth(String);
1035 
1036 	for (const char* SPtr = *String; *SPtr;)
1037 	{
1038 		int c = VStr::GetChar(SPtr);
1039 
1040 		//	Check for colour escape.
1041 		if (c == TEXT_COLOUR_ESCAPE)
1042 		{
1043 			Colour = VFont::ParseColourEscape(SPtr, NormalColour, BoldColour);
1044 			continue;
1045 		}
1046 
1047 		int w;
1048 		VTexture* Tex = Font->GetChar(c, &w, Colour);
1049 		if (Tex)
1050 		{
1051 			if (WidgetFlags & WF_TextShadowed)
1052 				DrawShadowedPic(cx, cy, Tex);
1053 			else
1054 				DrawPic(cx, cy, Tex, Alpha);
1055 		}
1056 		cx += w + Kerning;
1057 	}
1058 	LastX = cx;
1059 	LastY = cy;
1060 	unguard;
1061 }
1062 
1063 //==========================================================================
1064 //
1065 //	VWidget::DrawText
1066 //
1067 //==========================================================================
1068 
DrawText(int x,int y,const VStr & String,int NormalColour,int BoldColour,float Alpha)1069 void VWidget::DrawText(int x, int y, const VStr& String, int NormalColour,
1070 	int BoldColour, float Alpha)
1071 {
1072 	guard(VWidget::DrawText);
1073 	int start = 0;
1074 	int cx = x;
1075 	int cy = y;
1076 
1077 	if (VAlign == vcentre)
1078 		cy -= Font->TextHeight(String) / 2;
1079 	if (VAlign == vbottom)
1080 		cy -= Font->TextHeight(String);
1081 
1082 	//	Need this for correct cursor position with empty strings.
1083 	LastX = cx;
1084 	LastY = cy;
1085 
1086 	for (size_t i = 0; i < String.Length(); i++)
1087 	{
1088 		if (String[i] == '\n')
1089 		{
1090 			VStr cs(String, start, i - start);
1091 			DrawString(cx, cy, cs, NormalColour, BoldColour, Alpha);
1092 			cy += Font->GetHeight();
1093 			start = i + 1;
1094 		}
1095 		if (i == String.Length() - 1)
1096 		{
1097 			DrawString(cx, cy, VStr(String, start, String.Length() - start),
1098 				NormalColour, BoldColour, Alpha);
1099 		}
1100 	}
1101 	unguard;
1102 }
1103 
1104 //==========================================================================
1105 //
1106 //	VWidget::DrawCursor
1107 //
1108 //==========================================================================
1109 
DrawCursor()1110 void VWidget::DrawCursor()
1111 {
1112 	DrawCursorAt(LastX, LastY);
1113 }
1114 
1115 //==========================================================================
1116 //
1117 //	VWidget::DrawCursorAt
1118 //
1119 //==========================================================================
1120 
DrawCursorAt(int x,int y)1121 void VWidget::DrawCursorAt(int x, int y)
1122 {
1123 	guard(VWidget::DrawCursorAt);
1124 	if ((int)(host_time * 4) & 1)
1125 	{
1126 		int w;
1127 		DrawPic(x, y, Font->GetChar('_', &w, CR_UNTRANSLATED));
1128 	}
1129 	unguard;
1130 }
1131 
1132 //==========================================================================
1133 //
1134 //	Natives
1135 //
1136 //==========================================================================
1137 
IMPLEMENT_FUNCTION(VWidget,NewChild)1138 IMPLEMENT_FUNCTION(VWidget, NewChild)
1139 {
1140 	P_GET_PTR(VClass, ChildClass);
1141 	P_GET_SELF;
1142 	RET_REF(CreateNewWidget(ChildClass, Self));
1143 }
1144 
IMPLEMENT_FUNCTION(VWidget,Destroy)1145 IMPLEMENT_FUNCTION(VWidget, Destroy)
1146 {
1147 	P_GET_SELF;
1148 	delete Self;
1149 	Self = NULL;
1150 }
1151 
IMPLEMENT_FUNCTION(VWidget,DestroyAllChildren)1152 IMPLEMENT_FUNCTION(VWidget, DestroyAllChildren)
1153 {
1154 	P_GET_SELF;
1155 	Self->DestroyAllChildren();
1156 }
1157 
IMPLEMENT_FUNCTION(VWidget,GetRootWidget)1158 IMPLEMENT_FUNCTION(VWidget, GetRootWidget)
1159 {
1160 	P_GET_SELF;
1161 	RET_REF(Self->GetRootWidget());
1162 }
1163 
IMPLEMENT_FUNCTION(VWidget,Lower)1164 IMPLEMENT_FUNCTION(VWidget, Lower)
1165 {
1166 	P_GET_SELF;
1167 	Self->Lower();
1168 }
1169 
IMPLEMENT_FUNCTION(VWidget,Raise)1170 IMPLEMENT_FUNCTION(VWidget, Raise)
1171 {
1172 	P_GET_SELF;
1173 	Self->Raise();
1174 }
1175 
IMPLEMENT_FUNCTION(VWidget,MoveBefore)1176 IMPLEMENT_FUNCTION(VWidget, MoveBefore)
1177 {
1178 	P_GET_REF(VWidget, Other);
1179 	P_GET_SELF;
1180 	Self->MoveBefore(Other);
1181 }
1182 
IMPLEMENT_FUNCTION(VWidget,MoveAfter)1183 IMPLEMENT_FUNCTION(VWidget, MoveAfter)
1184 {
1185 	P_GET_REF(VWidget, Other);
1186 	P_GET_SELF;
1187 	Self->MoveAfter(Other);
1188 }
1189 
IMPLEMENT_FUNCTION(VWidget,SetPos)1190 IMPLEMENT_FUNCTION(VWidget, SetPos)
1191 {
1192 	P_GET_INT(NewY);
1193 	P_GET_INT(NewX);
1194 	P_GET_SELF;
1195 	Self->SetPos(NewX, NewY);
1196 }
1197 
IMPLEMENT_FUNCTION(VWidget,SetX)1198 IMPLEMENT_FUNCTION(VWidget, SetX)
1199 {
1200 	P_GET_INT(NewX);
1201 	P_GET_SELF;
1202 	Self->SetX(NewX);
1203 }
1204 
IMPLEMENT_FUNCTION(VWidget,SetY)1205 IMPLEMENT_FUNCTION(VWidget, SetY)
1206 {
1207 	P_GET_INT(NewY);
1208 	P_GET_SELF;
1209 	Self->SetY(NewY);
1210 }
1211 
IMPLEMENT_FUNCTION(VWidget,SetSize)1212 IMPLEMENT_FUNCTION(VWidget, SetSize)
1213 {
1214 	P_GET_INT(NewHeight);
1215 	P_GET_INT(NewWidth);
1216 	P_GET_SELF;
1217 	Self->SetSize(NewWidth, NewHeight);
1218 }
1219 
IMPLEMENT_FUNCTION(VWidget,SetWidth)1220 IMPLEMENT_FUNCTION(VWidget, SetWidth)
1221 {
1222 	P_GET_INT(NewWidth);
1223 	P_GET_SELF;
1224 	Self->SetWidth(NewWidth);
1225 }
1226 
IMPLEMENT_FUNCTION(VWidget,SetHeight)1227 IMPLEMENT_FUNCTION(VWidget, SetHeight)
1228 {
1229 	P_GET_INT(NewHeight);
1230 	P_GET_SELF;
1231 	Self->SetHeight(NewHeight);
1232 }
1233 
IMPLEMENT_FUNCTION(VWidget,SetScale)1234 IMPLEMENT_FUNCTION(VWidget, SetScale)
1235 {
1236 	P_GET_FLOAT(NewScaleY);
1237 	P_GET_FLOAT(NewScaleX);
1238 	P_GET_SELF;
1239 	Self->SetScale(NewScaleX, NewScaleY);
1240 }
1241 
IMPLEMENT_FUNCTION(VWidget,SetConfiguration)1242 IMPLEMENT_FUNCTION(VWidget, SetConfiguration)
1243 {
1244 	P_GET_FLOAT_OPT(NewScaleY, 1.0);
1245 	P_GET_FLOAT_OPT(NewScaleX, 1.0);
1246 	P_GET_INT(NewHeight);
1247 	P_GET_INT(NewWidth);
1248 	P_GET_INT(NewY);
1249 	P_GET_INT(NewX);
1250 	P_GET_SELF;
1251 	Self->SetConfiguration(NewX, NewY, NewWidth, NewHeight, NewScaleX,
1252 		NewScaleY);
1253 }
1254 
IMPLEMENT_FUNCTION(VWidget,SetVisibility)1255 IMPLEMENT_FUNCTION(VWidget, SetVisibility)
1256 {
1257 	P_GET_BOOL(bNewVisibility);
1258 	P_GET_SELF;
1259 	Self->SetVisibility(bNewVisibility);
1260 }
1261 
IMPLEMENT_FUNCTION(VWidget,Show)1262 IMPLEMENT_FUNCTION(VWidget, Show)
1263 {
1264 	P_GET_SELF;
1265 	Self->Show();
1266 }
1267 
IMPLEMENT_FUNCTION(VWidget,Hide)1268 IMPLEMENT_FUNCTION(VWidget, Hide)
1269 {
1270 	P_GET_SELF;
1271 	Self->Hide();
1272 }
1273 
IMPLEMENT_FUNCTION(VWidget,IsVisible)1274 IMPLEMENT_FUNCTION(VWidget, IsVisible)
1275 {
1276 	P_GET_BOOL_OPT(Recurse, true);
1277 	P_GET_SELF;
1278 	RET_BOOL(Self->IsVisible(Recurse));
1279 }
1280 
IMPLEMENT_FUNCTION(VWidget,SetEnabled)1281 IMPLEMENT_FUNCTION(VWidget, SetEnabled)
1282 {
1283 	P_GET_BOOL(bNewEnabled);
1284 	P_GET_SELF;
1285 	Self->SetEnabled(bNewEnabled);
1286 }
1287 
IMPLEMENT_FUNCTION(VWidget,Enable)1288 IMPLEMENT_FUNCTION(VWidget, Enable)
1289 {
1290 	P_GET_SELF;
1291 	Self->Enable();
1292 }
1293 
IMPLEMENT_FUNCTION(VWidget,Disable)1294 IMPLEMENT_FUNCTION(VWidget, Disable)
1295 {
1296 	P_GET_SELF;
1297 	Self->Disable();
1298 }
1299 
IMPLEMENT_FUNCTION(VWidget,IsEnabled)1300 IMPLEMENT_FUNCTION(VWidget, IsEnabled)
1301 {
1302 	P_GET_BOOL_OPT(Recurse, true);
1303 	P_GET_SELF;
1304 	RET_BOOL(Self->IsEnabled(Recurse));
1305 }
1306 
IMPLEMENT_FUNCTION(VWidget,SetFocusable)1307 IMPLEMENT_FUNCTION(VWidget, SetFocusable)
1308 {
1309 	P_GET_BOOL(bNewFocusable);
1310 	P_GET_SELF;
1311 	Self->SetFocusable(bNewFocusable);
1312 }
1313 
IMPLEMENT_FUNCTION(VWidget,IsFocusable)1314 IMPLEMENT_FUNCTION(VWidget, IsFocusable)
1315 {
1316 	P_GET_SELF;
1317 	RET_BOOL(Self->IsFocusable());
1318 }
1319 
IMPLEMENT_FUNCTION(VWidget,SetCurrentFocusChild)1320 IMPLEMENT_FUNCTION(VWidget, SetCurrentFocusChild)
1321 {
1322 	P_GET_REF(VWidget, NewFocus);
1323 	P_GET_SELF;
1324 	Self->SetCurrentFocusChild(NewFocus);
1325 }
1326 
IMPLEMENT_FUNCTION(VWidget,GetCurrentFocus)1327 IMPLEMENT_FUNCTION(VWidget, GetCurrentFocus)
1328 {
1329 	P_GET_SELF;
1330 	RET_REF(Self->GetCurrentFocus());
1331 }
1332 
IMPLEMENT_FUNCTION(VWidget,IsFocus)1333 IMPLEMENT_FUNCTION(VWidget, IsFocus)
1334 {
1335 	P_GET_BOOL_OPT(Recurse, true);
1336 	P_GET_SELF;
1337 	RET_BOOL(Self->IsFocus(Recurse));
1338 }
1339 
IMPLEMENT_FUNCTION(VWidget,SetFocus)1340 IMPLEMENT_FUNCTION(VWidget, SetFocus)
1341 {
1342 	P_GET_SELF;
1343 	Self->SetFocus();
1344 }
1345 
IMPLEMENT_FUNCTION(VWidget,DrawPic)1346 IMPLEMENT_FUNCTION(VWidget, DrawPic)
1347 {
1348 	P_GET_INT_OPT(Translation, 0);
1349 	P_GET_FLOAT_OPT(Alpha, 1.0);
1350 	P_GET_INT(Handle);
1351 	P_GET_INT(Y);
1352 	P_GET_INT(X);
1353 	P_GET_SELF;
1354 	Self->DrawPic(X, Y, Handle, Alpha, Translation);
1355 }
1356 
IMPLEMENT_FUNCTION(VWidget,DrawShadowedPic)1357 IMPLEMENT_FUNCTION(VWidget, DrawShadowedPic)
1358 {
1359 	P_GET_INT(Handle);
1360 	P_GET_INT(Y);
1361 	P_GET_INT(X);
1362 	P_GET_SELF;
1363 	Self->DrawShadowedPic(X, Y, Handle);
1364 }
1365 
IMPLEMENT_FUNCTION(VWidget,FillRectWithFlat)1366 IMPLEMENT_FUNCTION(VWidget, FillRectWithFlat)
1367 {
1368 	P_GET_NAME(Name);
1369 	P_GET_INT(Height);
1370 	P_GET_INT(Width);
1371 	P_GET_INT(Y);
1372 	P_GET_INT(X);
1373 	P_GET_SELF;
1374 	Self->FillRectWithFlat(X, Y, Width, Height, Name);
1375 }
1376 
IMPLEMENT_FUNCTION(VWidget,ShadeRect)1377 IMPLEMENT_FUNCTION(VWidget, ShadeRect)
1378 {
1379 	P_GET_FLOAT(Shade);
1380 	P_GET_INT(Height);
1381 	P_GET_INT(Width);
1382 	P_GET_INT(Y);
1383 	P_GET_INT(X);
1384 	P_GET_SELF;
1385 	Self->ShadeRect(X, Y, Width, Height, Shade);
1386 }
1387 
IMPLEMENT_FUNCTION(VWidget,SetFont)1388 IMPLEMENT_FUNCTION(VWidget, SetFont)
1389 {
1390 	P_GET_NAME(FontName);
1391 	P_GET_SELF;
1392 	Self->SetFont(FontName);
1393 }
1394 
IMPLEMENT_FUNCTION(VWidget,SetTextAlign)1395 IMPLEMENT_FUNCTION(VWidget, SetTextAlign)
1396 {
1397 	P_GET_INT(valign);
1398 	P_GET_INT(halign);
1399 	P_GET_SELF;
1400 	Self->SetTextAlign((halign_e)halign, (valign_e)valign);
1401 }
1402 
IMPLEMENT_FUNCTION(VWidget,SetTextShadow)1403 IMPLEMENT_FUNCTION(VWidget, SetTextShadow)
1404 {
1405 	P_GET_BOOL(State);
1406 	P_GET_SELF;
1407 	Self->SetTextShadow(State);
1408 }
1409 
IMPLEMENT_FUNCTION(VWidget,TextWidth)1410 IMPLEMENT_FUNCTION(VWidget, TextWidth)
1411 {
1412 	P_GET_STR(text);
1413 	P_GET_SELF;
1414 	RET_INT(Self->Font->TextWidth(text));
1415 }
1416 
IMPLEMENT_FUNCTION(VWidget,TextHeight)1417 IMPLEMENT_FUNCTION(VWidget, TextHeight)
1418 {
1419 	P_GET_STR(text);
1420 	P_GET_SELF;
1421 	RET_INT(Self->Font->TextHeight(text));
1422 }
1423 
IMPLEMENT_FUNCTION(VWidget,SplitText)1424 IMPLEMENT_FUNCTION(VWidget, SplitText)
1425 {
1426 	P_GET_INT(MaxWidth);
1427 	P_GET_PTR(TArray<VSplitLine>, Lines);
1428 	P_GET_STR(Text);
1429 	P_GET_SELF;
1430 	RET_INT(Self->Font->SplitText(Text, *Lines, MaxWidth));
1431 }
1432 
IMPLEMENT_FUNCTION(VWidget,SplitTextWithNewlines)1433 IMPLEMENT_FUNCTION(VWidget, SplitTextWithNewlines)
1434 {
1435 	P_GET_INT(MaxWidth);
1436 	P_GET_STR(Text);
1437 	P_GET_SELF;
1438 	RET_STR(Self->Font->SplitTextWithNewlines(Text, MaxWidth));
1439 }
1440 
IMPLEMENT_FUNCTION(VWidget,DrawText)1441 IMPLEMENT_FUNCTION(VWidget, DrawText)
1442 {
1443 	P_GET_FLOAT_OPT(Alpha, 1.0);
1444 	P_GET_INT_OPT(BoldColour, CR_UNTRANSLATED);
1445 	P_GET_INT_OPT(Colour, CR_UNTRANSLATED);
1446 	P_GET_STR(String);
1447 	P_GET_INT(Y);
1448 	P_GET_INT(X);
1449 	P_GET_SELF;
1450 	Self->DrawText(X, Y, String, Colour, BoldColour, Alpha);
1451 }
1452 
IMPLEMENT_FUNCTION(VWidget,DrawCursor)1453 IMPLEMENT_FUNCTION(VWidget, DrawCursor)
1454 {
1455 	P_GET_SELF;
1456 	Self->DrawCursor();
1457 }
1458 
IMPLEMENT_FUNCTION(VWidget,FindTextColour)1459 IMPLEMENT_FUNCTION(VWidget, FindTextColour)
1460 {
1461 	P_GET_STR(Name);
1462 	RET_INT(VFont::FindTextColour(*Name.ToLower()));
1463 }
1464