aboutsummaryrefslogtreecommitdiffstats
path: root/src/base
diff options
context:
space:
mode:
Diffstat (limited to 'src/base')
-rw-r--r--src/base/UCommon.pas25
-rw-r--r--src/base/UIni.pas85
-rw-r--r--src/base/UMain.pas12
-rw-r--r--src/base/USkins.pas70
-rw-r--r--src/base/UThemes.pas118
5 files changed, 192 insertions, 118 deletions
diff --git a/src/base/UCommon.pas b/src/base/UCommon.pas
index fa0faf3c..18022337 100644
--- a/src/base/UCommon.pas
+++ b/src/base/UCommon.pas
@@ -45,6 +45,7 @@ uses
type
TStringDynArray = array of string;
+ TUTF8StringDynArray = array of UTF8String;
const
SepWhitespace = [#9, #10, #13, ' ']; // tab, lf, cr, space
@@ -88,6 +89,8 @@ procedure MergeSort(List: TList; CompareFunc: TListSortCompare);
function GetAlignedMem(Size: cardinal; Alignment: integer): pointer;
procedure FreeAlignedMem(P: pointer);
+function GetArrayIndex(const SearchArray: array of UTF8String; Value: string; CaseInsensitiv: boolean = false): integer;
+
implementation
@@ -514,6 +517,28 @@ begin
TempList.Free;
end;
+(**
+ * Returns the index of Value in SearchArray
+ * or -1 if Value is not in SearchArray.
+ *)
+function GetArrayIndex(const SearchArray: array of UTF8String; Value: string;
+ CaseInsensitiv: boolean = false): integer;
+var
+ i: integer;
+begin
+ Result := -1;
+
+ for i := 0 to High(SearchArray) do
+ begin
+ if (SearchArray[i] = Value) or
+ (CaseInsensitiv and (CompareText(SearchArray[i], Value) = 0)) then
+ begin
+ Result := i;
+ Break;
+ end;
+ end;
+end;
+
type
// stores the unaligned pointer of data allocated by GetAlignedMem()
diff --git a/src/base/UIni.pas b/src/base/UIni.pas
index 6e86c558..36c3cce0 100644
--- a/src/base/UIni.pas
+++ b/src/base/UIni.pas
@@ -37,6 +37,7 @@ uses
Classes,
IniFiles,
SysUtils,
+ UCommon,
ULog,
UTextEncoding,
UFilesystem,
@@ -75,7 +76,6 @@ type
private
function ExtractKeyIndex(const Key, Prefix, Suffix: string): integer;
function GetMaxKeyIndex(Keys: TStringList; const Prefix, Suffix: string): integer;
- function GetArrayIndex(const SearchArray: array of UTF8String; Value: string; CaseInsensitiv: boolean = false): integer;
function ReadArrayIndex(const SearchArray: array of UTF8String; IniFile: TCustomIniFile;
IniSection: string; IniProperty: string; Default: integer): integer;
@@ -166,10 +166,10 @@ type
var
Ini: TIni;
- IResolution: array of UTF8String;
- ILanguage: array of UTF8String;
- ITheme: array of UTF8String;
- ISkin: array of UTF8String;
+ IResolution: TUTF8StringDynArray;
+ ILanguage: TUTF8StringDynArray;
+ ITheme: TUTF8StringDynArray;
+ ISkin: TUTF8StringDynArray;
const
IPlayers: array[0..4] of UTF8String = ('1', '2', '3', '4', '6');
@@ -327,6 +327,7 @@ uses
UMain,
URecord,
USkins,
+ UThemes,
UPathUtils,
UUnicodeUtils;
@@ -567,28 +568,6 @@ begin
end;
(**
- * Returns the index of Value in SearchArray
- * or -1 if Value is not in SearchArray.
- *)
-function TIni.GetArrayIndex(const SearchArray: array of UTF8String; Value: string;
- CaseInsensitiv: boolean = false): integer;
-var
- i: integer;
-begin
- Result := -1;
-
- for i := 0 to High(SearchArray) do
- begin
- if (SearchArray[i] = Value) or
- (CaseInsensitiv and (UpperCase(SearchArray[i]) = UpperCase(Value))) then
- begin
- Result := i;
- Break;
- end;
- end;
-end;
-
-(**
* Reads the property IniSeaction:IniProperty from IniFile and
* finds its corresponding index in SearchArray.
* If SearchArray does not contain the property value, the default value is
@@ -717,51 +696,7 @@ begin
end;
procedure TIni.LoadThemes(IniFile: TCustomIniFile);
-var
- SearchResult: TSearchRec;
- ThemeIni: TMemIniFile;
- ThemeName: string;
- ThemeVersion: string;
- I: integer;
- Iter: IFileIterator;
- FileInfo: TFileInfo;
begin
- // Theme
- SetLength(ITheme, 0);
- Log.LogStatus('Searching for Theme : ' + ThemePath.ToNative + '*.ini', 'Theme');
-
-
- Iter := FileSystem.FileFind(ThemePath.Append('*.ini'), 0);
- while (Iter.HasNext) do
- begin
- FileInfo := Iter.Next;
- Log.LogStatus('Found Theme: ' + FileInfo.Name.ToNative, 'Theme');
-
- //Read Themename from Theme
- ThemeIni := TMemIniFile.Create(ThemePath.Append(FileInfo.Name).ToNative);
- ThemeName := UpperCase(ThemeIni.ReadString('Theme','Name', FileInfo.Name.SetExtension('').ToNative));
- ThemeVersion := Trim(UpperCase(ThemeIni.ReadString('Theme','US_Version', 'no version tag')));
- ThemeIni.Free;
-
- // don't load theme with wrong version tag
- if ThemeVersion <> 'USD 110' then
- begin
- Log.LogWarn('Wrong Version (' + ThemeVersion + ') in Theme : ' + ThemeName, 'Theme');
- Continue;
- end;
-
- //Search for Skins for this Theme
- for I := Low(Skin.Skin) to High(Skin.Skin) do
- begin
- if UpperCase(Skin.Skin[I].Theme) = ThemeName then
- begin
- SetLength(ITheme, Length(ITheme)+1);
- ITheme[High(ITheme)] := FileInfo.Name.SetExtension('').ToNative;
- break;
- end;
- end;
- end;
-
// No Theme Found
if (Length(ITheme) = 0) then
begin
@@ -775,13 +710,16 @@ begin
// Skin
Skin.onThemeChange;
- SkinNo := GetArrayIndex(ISkin, IniFile.ReadString('Themes', 'Skin', ISkin[0]));
+ SkinNo := GetArrayIndex(ISkin, IniFile.ReadString('Themes', 'Skin', ISkin[UThemes.Theme.Themes[Theme].DefaultSkin]));
{ there may be a not existing skin in the ini file
e.g. due to manual edit or corrupted file.
in this case we load the first Skin }
if SkinNo = -1 then
SkinNo := 0;
+
+ // Color
+ Color := GetArrayIndex(IColor, IniFile.ReadString('Themes', 'Color', IColor[Skin.GetDefaultColor(SkinNo)]));
end;
procedure TIni.LoadScreenModes(IniFile: TCustomIniFile);
@@ -995,9 +933,6 @@ begin
LoadThemes(IniFile);
- // Color
- Color := GetArrayIndex(IColor, IniFile.ReadString('Themes', 'Color', IColor[0]));
-
LoadInputDeviceCfg(IniFile);
// LoadAnimation
diff --git a/src/base/UMain.pas b/src/base/UMain.pas
index 0de8ddeb..550fe9cd 100644
--- a/src/base/UMain.pas
+++ b/src/base/UMain.pas
@@ -171,6 +171,12 @@ begin
Log.BenchmarkEnd(1);
Log.LogBenchmark('Loading Skin List', 1);
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Loading Theme List', 'Initialization');
+ Theme := TTheme.Create;
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Theme List', 1);
+
// Ini + Paths
Log.BenchmarkStart(1);
Log.LogStatus('Load Ini', 'Initialization');
@@ -196,10 +202,10 @@ begin
// Theme
Log.BenchmarkStart(1);
- Log.LogStatus('Load Themes', 'Initialization');
- Theme := TTheme.Create(ThemePath.Append(ITheme[Ini.Theme] + '.ini'), Ini.Color);
+ Log.LogStatus('Load Theme', 'Initialization');
+ Theme.LoadTheme(Ini.Theme, Ini.Color);
Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Themes', 1);
+ Log.LogBenchmark('Loading Theme', 1);
// Covers Cache
Log.BenchmarkStart(1);
diff --git a/src/base/USkins.pas b/src/base/USkins.pas
index 6ef5c596..a909b081 100644
--- a/src/base/USkins.pas
+++ b/src/base/USkins.pas
@@ -34,7 +34,8 @@ interface
{$I switches.inc}
uses
- UPath;
+ UPath,
+ UCommon;
type
TSkinTexture = record
@@ -47,6 +48,8 @@ type
Name: string;
Path: IPath;
FileName: IPath;
+
+ DefaultColor: integer;
Creator: string; // not used yet
end;
@@ -62,6 +65,10 @@ type
procedure LoadSkin(Name: string);
function GetTextureFileName(TextureName: string): IPath;
function GetSkinNumber(Name: string): integer;
+ function GetDefaultColor(SkinNo: integer): integer;
+
+ procedure GetSkinsByTheme(Theme: string; out Skins: TUTF8StringDynArray);
+
procedure onThemeChange;
end;
@@ -74,6 +81,7 @@ uses
IniFiles,
Classes,
SysUtils,
+ Math,
UIni,
ULog,
UMain,
@@ -130,6 +138,7 @@ begin
Skin[S].Theme := SkinIni.ReadString('Skin', 'Theme', '');
Skin[S].Name := SkinIni.ReadString('Skin', 'Name', '');
Skin[S].Creator := SkinIni.ReadString('Skin', 'Creator', '');
+ Skin[S].DefaultColor := Max(0, GetArrayIndex(IColor, SkinIni.ReadString('Skin', 'Color', ''), true));
SkinIni.Free;
end;
@@ -180,14 +189,6 @@ begin
//Log.LogError('', '-----------------------------------------');
//Log.LogError(TextureName+' - '+ Result, 'TSkin.GetTextureFileName');
end;
-
-{ Result := SkinPath + 'Bar.jpg';
- if TextureName = 'Ball' then
- Result := SkinPath + 'Ball.bmp';
- if Copy(TextureName, 1, 4) = 'Gray' then
- Result := SkinPath + 'Ball.bmp';
- if Copy(TextureName, 1, 6) = 'NoteBG' then
- Result := SkinPath + 'Ball.bmp';}
end;
function TSkin.GetSkinNumber(Name: string): integer;
@@ -196,25 +197,52 @@ var
begin
Result := 0; // set default to the first available skin
for S := 0 to High(Skin) do
- if Skin[S].Name = Name then
+ if CompareText(Skin[S].Name, Name) = 0 then
Result := S;
end;
-procedure TSkin.onThemeChange;
-var
- S: integer;
- Name: String;
+procedure TSkin.GetSkinsByTheme(Theme: string; out Skins: TUTF8StringDynArray);
+ var
+ I: Integer;
+ Len: integer;
begin
- Ini.SkinNo:=0;
- SetLength(ISkin, 0);
- Name := Uppercase(ITheme[Ini.Theme]);
- for S := 0 to High(Skin) do
- if Name = Uppercase(Skin[S].Theme) then
+ SetLength(Skins, 0);
+ Len := 0;
+
+ for I := 0 to High(Skin) do
+ if CompareText(Theme, Skin[I].Theme) = 0 then
begin
- SetLength(ISkin, Length(ISkin)+1);
- ISkin[High(ISkin)] := Skin[S].Name;
+ SetLength(Skins, Len + 1);
+ Skins[Len] := Skin[I].Name;
+ Inc(Len);
end;
+end;
+{ returns number of default color for skin with
+ index SkinNo in ISkin (not in the actual skin array) }
+function TSkin.GetDefaultColor(SkinNo: integer): integer;
+ var
+ I: Integer;
+begin
+ Result := 0;
+
+ for I := 0 to High(Skin) do
+ if CompareText(ITheme[Ini.Theme], Skin[I].Theme) = 0 then
+ begin
+ if SkinNo > 0 then
+ Dec(SkinNo)
+ else
+ begin
+ Result := Skin[I].DefaultColor;
+ Break;
+ end;
+ end;
+end;
+
+procedure TSkin.onThemeChange;
+begin
+ Ini.SkinNo:=0;
+ GetSkinsByTheme(ITheme[Ini.Theme], ISkin);
end;
end.
diff --git a/src/base/UThemes.pas b/src/base/UThemes.pas
index aa89af43..f8b2d8fd 100644
--- a/src/base/UThemes.pas
+++ b/src/base/UThemes.pas
@@ -721,6 +721,13 @@ type
CatText: UTF8String;
end;
+ TThemeEntry = record
+ Name: string;
+ Filename: IPath;
+ DefaultSkin: integer;
+ Creator: string;
+ end;
+
TTheme = class
private
{$IFDEF THEMESAVE}
@@ -731,8 +738,9 @@ type
LastThemeBasic: TThemeBasic;
procedure CreateThemeObjects();
-
+ procedure LoadHeader(FileName: IPath);
public
+ Themes: array of TThemeEntry;
Loading: TThemeLoading;
Main: TThemeMain;
Name: TThemeName;
@@ -774,9 +782,11 @@ type
ILevel: array[0..2] of UTF8String;
- constructor Create(const FileName: IPath); overload; // Initialize theme system
- constructor Create(const FileName: IPath; Color: integer); overload; // Initialize theme system with color
- function LoadTheme(const FileName: IPath; sColor: integer): boolean; // Load some theme settings from file
+ constructor Create;
+
+ procedure LoadList;
+
+ function LoadTheme(ThemeNum: integer; sColor: integer): boolean; // Load some theme settings from file
procedure LoadColors;
@@ -829,9 +839,12 @@ uses
ULanguage,
USkins,
UIni,
+ UPathUtils,
+ UFileSystem,
gl,
glext,
- math;
+ math,
+ StrUtils;
//-----------
//Helper procs to use TRGB in Opengl ...maybe this should be somewhere else
@@ -856,12 +869,7 @@ begin
glColor4f(Color.R, Color.G, Color.B, Min(Color.A, Alpha));
end;
-constructor TTheme.Create(const FileName: IPath);
-begin
- Create(FileName, 0);
-end;
-
-constructor TTheme.Create(const FileName: IPath; Color: integer);
+constructor TTheme.Create;
begin
inherited Create();
@@ -901,11 +909,83 @@ begin
StatMain := TThemeStatMain.Create;
StatDetail := TThemeStatDetail.Create;
- LoadTheme(FileName, Color);
+ //LoadTheme(FileName, Color);
+ LoadList;
+end;
+
+procedure TTheme.LoadHeader(FileName: IPath);
+ var
+ Entry: TThemeEntry;
+ Ini: TMemIniFile;
+ SkinName: string;
+ SkinsFound: boolean;
+ ThemeVersion: string;
+ I: integer;
+ Len: integer;
+ Skins: TUTF8StringDynArray;
+begin
+ Entry.Filename := ThemePath.Append(FileName);
+ //read info from theme header
+ Ini := TMemIniFile.Create(Entry.Filename.ToNative);
+
+ Entry.Name := Ini.ReadString('Theme', 'Name', FileName.SetExtension('').ToNative);
+ ThemeVersion := Trim(UpperCase(Ini.ReadString('Theme', 'US_Version', 'no version tag')));
+ Entry.Creator := Ini.ReadString('Theme', 'Creator', 'Unknown');
+ SkinName := Ini.ReadString('Theme', 'DefaultSkin', FileName.SetExtension('').ToNative);
+
+ Ini.Free;
+
+ // don't load theme with wrong version tag
+ if ThemeVersion <> 'USD 110' then
+ begin
+ Log.LogWarn('Wrong Version (' + ThemeVersion + ') in Theme : ' + Entry.Name, 'Theme.LoadHeader');
+ end
+ else
+ begin
+ //Search for Skins for this Theme
+ SkinsFound := false;
+ for I := Low(Skin.Skin) to High(Skin.Skin) do
+ begin
+ if (CompareText(Skin.Skin[I].Theme, Entry.Name) = 0) then
+ begin
+ SkinsFound := true;
+ break;
+ end;
+ end;
+
+ if SkinsFound then
+ begin
+ { found a valid Theme }
+ // set correct default skin
+ Skin.GetSkinsByTheme(Entry.Name, Skins);
+ Entry.DefaultSkin := max(0, GetArrayIndex(Skins, SkinName, true));
+
+ Len := Length(Themes);
+ SetLength(Themes, Len + 1);
+ SetLength(ITheme, Len + 1);
+ Themes[Len] := Entry;
+ ITheme[Len] := Entry.Name;
+ end;
+ end;
+end;
+procedure TTheme.LoadList;
+ var
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
+begin
+ Log.LogStatus('Searching for Theme : ' + ThemePath.ToNative + '*.ini', 'Theme.LoadList');
+
+ Iter := FileSystem.FileFind(ThemePath.Append('*.ini'), 0);
+ while (Iter.HasNext) do
+ begin
+ FileInfo := Iter.Next;
+ Log.LogStatus('Found Theme: ' + FileInfo.Name.ToNative, 'Theme.LoadList');
+ LoadHeader(Fileinfo.Name);
+ end;
end;
-function TTheme.LoadTheme(const FileName: IPath; sColor: integer): boolean;
+function TTheme.LoadTheme(ThemeNum: integer; sColor: integer): boolean;
var
I: integer;
begin
@@ -913,21 +993,21 @@ begin
CreateThemeObjects();
- Log.LogStatus('Loading: '+ FileName.ToNative, 'TTheme.LoadTheme');
+ Log.LogStatus('Loading: '+ Themes[ThemeNum].FileName.ToNative, 'TTheme.LoadTheme');
- if not FileName.IsFile() then
+ if not Themes[ThemeNum].FileName.IsFile() then
begin
- Log.LogError('Theme does not exist ('+ FileName.ToNative +')', 'TTheme.LoadTheme');
+ Log.LogError('Theme does not exist ('+ Themes[ThemeNum].FileName.ToNative +')', 'TTheme.LoadTheme');
end;
- if FileName.IsFile() then
+ if Themes[ThemeNum].FileName.IsFile() then
begin
Result := true;
{$IFDEF THEMESAVE}
- ThemeIni := TIniFile.Create(FileName.ToNative);
+ ThemeIni := TIniFile.Create(Themes[ThemeNum].FileName.ToNative);
{$ELSE}
- ThemeIni := TMemIniFile.Create(FileName.ToNative);
+ ThemeIni := TMemIniFile.Create(Themes[ThemeNum].FileName.ToNative);
{$ENDIF}
if ThemeIni.ReadString('Theme', 'Name', '') <> '' then