aboutsummaryrefslogtreecommitdiffstats
path: root/src/menu/UMenuText.pas
diff options
context:
space:
mode:
Diffstat (limited to 'src/menu/UMenuText.pas')
-rw-r--r--src/menu/UMenuText.pas379
1 files changed, 379 insertions, 0 deletions
diff --git a/src/menu/UMenuText.pas b/src/menu/UMenuText.pas
new file mode 100644
index 00000000..ab180b77
--- /dev/null
+++ b/src/menu/UMenuText.pas
@@ -0,0 +1,379 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuText;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ math,
+ SysUtils,
+ gl,
+ SDL,
+ TextGL,
+ UTexture;
+
+type
+ TText = class
+ private
+ SelectBool: boolean;
+ TextString: UTF8String;
+ TextTiles: array of UTF8String;
+
+ STicks: cardinal;
+ SelectBlink: boolean;
+ public
+ X: real;
+ Y: real;
+ Z: real;
+ MoveX: real; // some modifier for x - position that don't affect the real Y
+ MoveY: real; // some modifier for y - position that don't affect the real Y
+ W: real; // text wider than W is broken
+// H: real;
+ Size: real;
+ ColR: real;
+ ColG: real;
+ ColB: real;
+ Alpha: real;
+ Int: real;
+ Style: integer;
+ Visible: boolean;
+ Align: integer; // 0 = left, 1 = center, 2 = right
+
+ // reflection
+ Reflection: boolean;
+ ReflectionSpacing: real;
+
+ procedure SetSelect(Value: boolean);
+ property Selected: boolean read SelectBool write SetSelect;
+
+ procedure SetText(Value: UTF8String);
+ property Text: UTF8String read TextString write SetText;
+
+ procedure DeleteLastLetter; //< Deletes the rightmost letter
+
+ procedure Draw;
+ constructor Create; overload;
+ constructor Create(X, Y: real; const Text: UTF8String); overload;
+ constructor Create(ParX, ParY, ParW: real; ParStyle: integer; ParSize, ParColR, ParColG, ParColB: real; ParAlign: integer; const ParText: UTF8String; ParReflection: boolean; ParReflectionSpacing: real; ParZ: real); overload;
+ end;
+
+implementation
+
+uses
+ UGraphic,
+ UUnicodeUtils,
+ StrUtils;
+
+procedure TText.SetSelect(Value: boolean);
+begin
+ SelectBool := Value;
+
+ // set cursor visible
+ SelectBlink := true;
+ STicks := SDL_GetTicks() div 550;
+end;
+
+procedure TText.SetText(Value: UTF8String);
+var
+ NextPos: cardinal; // next pos of a space etc.
+ LastPos: cardinal; // last pos "
+ LastBreak: cardinal; // last break
+ isBreak: boolean; // true if the break is not caused because the text is out of the area
+ FirstWord: word; // is first word after break?
+ Len: word; // length of the tiles array
+
+ function GetNextPos: boolean;
+ var
+ T1, {T2,} T3: cardinal;
+ begin
+ LastPos := NextPos;
+
+ // next space (if width is given)
+ if (W > 0) then
+ T1 := PosEx(' ', Value, LastPos + 1)
+ else
+ T1 := Length(Value);
+
+ {// next -
+ T2 := PosEx('-', Value, LastPos + 1);}
+
+ // next break
+ T3 := PosEx('\n', Value, LastPos + 1);
+
+ if T1 = 0 then
+ T1 := Length(Value);
+ {if T2 = 0 then
+ T2 := Length(Value); }
+ if T3 = 0 then
+ T3 := Length(Value);
+
+ // get nearest pos
+ NextPos := min(T1, T3{min(T2, T3)});
+
+ if (LastPos = cardinal(Length(Value))) then
+ NextPos := 0;
+
+ isBreak := (NextPos = T3) and (NextPos <> cardinal(Length(Value)));
+ Result := (NextPos <> 0);
+ end;
+
+ procedure AddBreak(const From, bTo: cardinal);
+ begin
+ if (isBreak) or (bTo - From >= 1) then
+ begin
+ Inc(Len);
+ SetLength (TextTiles, Len);
+ TextTiles[Len-1] := Trim(Copy(Value, From, bTo - From));
+
+ if isBreak then
+ LastBreak := bTo + 2
+ else
+ LastBreak := bTo + 1;
+ FirstWord := 0;
+ end;
+ end;
+
+begin
+ // set TextString
+ TextString := Value;
+
+ // set cursor visible
+ SelectBlink := true;
+ STicks := SDL_GetTicks() div 550;
+
+ // exit if there is no need to create tiles
+ if (W <= 0) and (Pos('\n', Value) = 0) then
+ begin
+ SetLength (TextTiles, 1);
+ TextTiles[0] := Value;
+ Exit;
+ end;
+
+ // create tiles
+ // reset text array
+ SetLength (TextTiles, 0);
+ Len := 0;
+
+ // reset counter vars
+ LastPos := 1;
+ NextPos := 1;
+ LastBreak := 1;
+ FirstWord := 1;
+
+ if (W > 0) then
+ begin
+ // set font properties
+ SetFontStyle(Style);
+ SetFontSize(Size);
+ end;
+
+ // go through text
+ while (GetNextPos) do
+ begin
+ // break in text
+ if isBreak then
+ begin
+ // look for break before the break
+ if (glTextWidth(Copy(Value, LastBreak, NextPos - LastBreak + 1)) > W) AND (NextPos-LastPos > 1) then
+ begin
+ isBreak := false;
+ // not the first word after break, so we don't have to break within a word
+ if (FirstWord > 1) then
+ begin
+ // add break before actual position, because there the text fits the area
+ AddBreak(LastBreak, LastPos);
+ end
+ else // first word after break break within the word
+ begin
+ // to do
+ // AddBreak(LastBreak, LastBreak + 155);
+ end;
+ end;
+
+ isBreak := true;
+ // add break from text
+ AddBreak(LastBreak, NextPos);
+ end
+ // text comes out of the text area -> createbreak
+ else if (glTextWidth(Copy(Value, LastBreak, NextPos - LastBreak + 1)) > W) then
+ begin
+ // not the first word after break, so we don't have to break within a word
+ if (FirstWord > 1) then
+ begin
+ // add break before actual position, because there the text fits the area
+ AddBreak(LastBreak, LastPos);
+ end
+ else // first word after break -> break within the word
+ begin
+ // to do
+ // AddBreak(LastBreak, LastBreak + 155);
+ end;
+ end;
+ //end;
+ Inc(FirstWord)
+ end;
+ // add ending
+ AddBreak(LastBreak, Length(Value)+1);
+end;
+
+procedure TText.DeleteLastLetter;
+begin
+ SetText(UTF8Copy(TextString, 1, LengthUTF8(TextString)-1));
+end;
+
+procedure TText.Draw;
+var
+ X2, Y2: real;
+ Text2: UTF8String;
+ I: integer;
+ Ticks: cardinal;
+begin
+ if Visible then
+ begin
+ SetFontStyle(Style);
+ SetFontSize(Size);
+ SetFontItalic(false);
+
+ glColor4f(ColR*Int, ColG*Int, ColB*Int, Alpha);
+
+ // reflection
+ if Reflection then
+ SetFontReflection(true, ReflectionSpacing)
+ else
+ SetFontReflection(false,0);
+
+ // if selected set blink...
+ if SelectBool then
+ begin
+ Ticks := SDL_GetTicks() div 550;
+ if Ticks <> STicks then
+ begin // change visability
+ STicks := Ticks;
+ SelectBlink := Not SelectBlink;
+ end;
+ end;
+
+ {if (false) then // no width set draw as one long string
+ begin
+ if not (SelectBool AND SelectBlink) then
+ Text2 := Text
+ else
+ Text2 := Text + '|';
+
+ case Align of
+ 0: X2 := X;
+ 1: X2 := X - glTextWidth(Text2)/2;
+ 2: X2 := X - glTextWidth(Text2);
+ end;
+
+ SetFontPos(X2, Y);
+ glPrint(Text2);
+ SetFontStyle(ftNormal); // reset to default
+ end
+ else
+ begin}
+ // now use always:
+ // draw text as many strings
+ Y2 := Y + MoveY;
+ for I := 0 to High(TextTiles) do
+ begin
+ if (not (SelectBool and SelectBlink)) or (I <> High(TextTiles)) then
+ Text2 := TextTiles[I]
+ else
+ Text2 := TextTiles[I] + '|';
+
+ case Align of
+ 1: X2 := X + MoveX - glTextWidth(Text2)/2; { centered }
+ 2: X2 := X + MoveX - glTextWidth(Text2); { right aligned }
+ else X2 := X + MoveX; { left aligned (default) }
+ end;
+
+ SetFontPos(X2, Y2);
+
+ SetFontZ(Z);
+
+ glPrint(Text2);
+
+ {if Size >= 10 then
+ Y2 := Y2 + Size * 0.93
+ else}
+ if (Style = ftBold) then
+ Y2 := Y2 + Size * 0.93
+ else
+ Y2 := Y2 + Size * 0.72;
+ end;
+ SetFontStyle(ftNormal); // reset to default
+
+ //end;
+ end;
+end;
+
+constructor TText.Create;
+begin
+ Create(0, 0, '');
+end;
+
+constructor TText.Create(X, Y: real; const Text: UTF8String);
+begin
+ Create(X, Y, 0, ftNormal, 30, 0, 0, 0, 0, Text, false, 0, 0);
+end;
+
+constructor TText.Create(ParX, ParY, ParW: real;
+ ParStyle: integer;
+ ParSize, ParColR, ParColG, ParColB: real;
+ ParAlign: integer;
+ const ParText: UTF8String;
+ ParReflection: boolean;
+ ParReflectionSpacing: real;
+ ParZ: real);
+begin
+ inherited Create;
+ Alpha := 1;
+ X := ParX;
+ Y := ParY;
+ W := ParW;
+ Z := ParZ;
+ Style := ParStyle;
+ Size := ParSize;
+ Text := ParText;
+ ColR := ParColR;
+ ColG := ParColG;
+ ColB := ParColB;
+ Int := 1;
+ Align := ParAlign;
+ SelectBool := false;
+ Visible := true;
+ Reflection := ParReflection;
+ ReflectionSpacing := ParReflectionSpacing;
+end;
+
+end.