ADMIN: migration complete

git-svn-id: https://svn.code.sf.net/p/apophysis7x/svn/trunk@1 a5d1c0f9-a0e9-45c6-87dd-9d276e40c949
This commit is contained in:
xyrus02
2013-07-28 08:58:33 +00:00
commit 95a2f54683
258 changed files with 175238 additions and 0 deletions

210
Core/BaseVariation.pas Normal file
View File

@ -0,0 +1,210 @@
{
Apophysis Copyright (C) 2001-2004 Mark Townsend
Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov
Apophysis Copyright (C) 2007-2008 Piotr Borys, Peter Sdobnov
Apophysis "3D hack" Copyright (C) 2007-2008 Peter Sdobnov
Apophysis "7X" Copyright (C) 2009-2010 Georg Kiehne
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; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
}
unit BaseVariation;
interface
type
TCalcFunction = procedure of object;
type
TBaseVariation = class
protected
procedure CalcFunction; virtual; abstract;
public
vvar: double;
FTx, FTy: ^double;
FPx, FPy: ^double;
FTz, FPz: ^double;
// more params :)
color : ^double;
a, b, c, d, e, f : double;
class function GetName: string; virtual; abstract;
class function GetInstance: TBaseVariation; virtual; abstract;
function GetNrVariables: integer; virtual;
function GetVariableNameAt(const Index: integer): string; virtual;
function GetVariable(const Name: string; var Value: double): boolean; virtual;
function SetVariable(const Name: string; var Value: double): boolean; virtual;
function ResetVariable(const Name: string): boolean; virtual;
function GetVariableStr(const Name: string): string; virtual;
function SetVariableStr(const Name: string; var strValue: string): boolean; virtual;
procedure Prepare; virtual;
procedure GetCalcFunction(var Delphi_Suxx: TCalcFunction); virtual;
end;
TBaseVariationClass = class of TBaseVariation;
type
TVariationLoader = class
public
Supports3D, SupportsDC : boolean;
function GetName: string; virtual; abstract;
function GetInstance: TBaseVariation; virtual; abstract;
function GetNrVariables: integer; virtual; abstract;
function GetVariableNameAt(const Index: integer): string; virtual; abstract;
end;
type
TVariationClassLoader = class (TVariationLoader)
public
constructor Create(varClass : TBaseVariationClass);
function GetName: string; override;
function GetInstance: TBaseVariation; override;
function GetNrVariables: integer; override;
function GetVariableNameAt(const Index: integer): string; override;
private
VariationClass : TBaseVariationClass;
end;
function fmod(x, y: double) : double;
implementation
uses SysUtils;
function fmod(x, y: double) : double;
begin
Result := frac(x / y) * y;
end;
{ TBaseVariation }
///////////////////////////////////////////////////////////////////////////////
function TBaseVariation.GetNrVariables: integer;
begin
Result := 0;
end;
///////////////////////////////////////////////////////////////////////////////
function TBaseVariation.GetVariable(const Name: string; var value: double): boolean;
begin
Result := False;
end;
function TBaseVariation.SetVariable(const Name: string; var value: double): boolean;
begin
Result := False;
end;
function TBaseVariation.ResetVariable(const Name: string): boolean;
var
zero: double;
begin
zero := 0;
Result := SetVariable(Name, zero);
end;
///////////////////////////////////////////////////////////////////////////////
function TBaseVariation.GetVariableStr(const Name: string): string;
var
value: double;
begin
if GetVariable(Name, value) then
Result := Format('%.6g', [value])
else
Result := '';
end;
function TBaseVariation.SetVariableStr(const Name: string; var strValue: string): boolean;
var
v, oldv: double;
begin
if GetVariable(Name, oldv) then begin
try
v := StrToFloat(strValue);
SetVariable(Name, v);
except
v := oldv;
end;
strValue := Format('%.6g', [v]);
Result := true;
end
else Result := false;
end;
///////////////////////////////////////////////////////////////////////////////
function TBaseVariation.GetVariableNameAt(const Index: integer): string;
begin
Result := ''
end;
///////////////////////////////////////////////////////////////////////////////
procedure TBaseVariation.Prepare;
begin
end;
///////////////////////////////////////////////////////////////////////////////
procedure TBaseVariation.GetCalcFunction(var Delphi_Suxx: TCalcFunction);
begin
Delphi_Suxx := CalcFunction; // -X- lol
end;
///////////////////////////////////////////////////////////////////////////////
{ TVariationClassLoader }
constructor TVariationClassLoader.Create(varClass : TBaseVariationClass);
begin
VariationClass := varClass;
end;
function TVariationClassLoader.GetName: string;
begin
Result := VariationClass.GetName();
end;
function TVariationClassLoader.GetInstance: TBaseVariation;
begin
Result := VariationClass.GetInstance();
end;
function TVariationClassLoader.GetNrVariables: integer;
var
hack : TBaseVariation;
begin
hack := GetInstance();
Result := hack.GetNrVariables();
hack.Free();
end;
function TVariationClassLoader.GetVariableNameAt(const Index: integer): string;
var
hack : TBaseVariation;
begin
hack := GetInstance();
Result := hack.GetVariableNameAt(Index);
hack.Free();
end;
end.

94
Core/Bezier.pas Normal file
View File

@ -0,0 +1,94 @@
unit Bezier;
interface
uses Math;
type
BezierPoint = record
x, y: double;
end;
BezierRect = record
x0, y0, x1, y1: double;
end;
BezierPoints = array [0..3] of BezierPoint;
BezierWeights = array [0..3] of double;
procedure BezierCopy(src: BezierPoints; var tgt: BezierPoints);
procedure BezierSetRect(var points: BezierPoints; flip: boolean; rect: BezierRect);
procedure BezierUnsetRect(var points: BezierPoints; flip: boolean; rect: BezierRect);
procedure BezierSolve(t: double; src: BezierPoints; w: BezierWeights; var solution: BezierPoint);
function BezierFunc(t: double; src: BezierPoints; w: BezierWeights): double;
implementation
procedure BezierCopy(src: BezierPoints; var tgt: BezierPoints);
var
i, n: integer;
begin
n := Length(src);
for i := 0 to n - 1 do
tgt[i] := src[i];
end;
procedure BezierSetRect(var points: BezierPoints; flip: boolean; rect: BezierRect);
var
i, n: integer;
f: double;
begin
n := Length(points);
for i := 0 to n - 1 do
begin
if (flip) then f := 1 - points[i].y
else f := points[i].y;
points[i].x := points[i].x * (rect.x1 - rect.x0) + rect.x0;
points[i].y := f * (rect.y1 - rect.y0) + rect.y0;
end;
end;
procedure BezierUnsetRect(var points: BezierPoints; flip: boolean; rect: BezierRect);
var
i, n: integer;
f: double;
begin
if ((rect.x1 - rect.x0) = 0) or ((rect.y1 - rect.y0) = 0) then Exit;
n := Length(points);
for i := 0 to n - 1 do
begin
points[i].x := (points[i].x - rect.x0) / (rect.x1 - rect.x0);
points[i].y := (points[i].y - rect.y0) / (rect.y1 - rect.y0);
if (flip) then points[i].y := 1 - points[i].y;
end;
end;
procedure BezierSolve(t: double; src: BezierPoints; w: BezierWeights; var solution: BezierPoint);
var
s, s2, s3, t2, t3, nom_x, nom_y, denom: double;
begin
s := 1 - t;
s2 := s * s; s3 := s * s * s;
t2 := t * t; t3 := t * t * t;
nom_x := w[0] * s3 * src[0].x + w[1] * s2 * 3 * t * src[1].x +
w[2] * s * 3 * t2 * src[2].x + w[3] * t3 * src[3].x;
nom_y := w[0] * s3 * src[0].y + w[1] * s2 * 3 * t * src[1].y +
w[2] * s * 3 * t2 * src[2].y + w[3] * t3 * src[3].y;
denom := w[0] * s3 + w[1] * s2 * 3 * t + w[2] * s * 3 * t2 + w[3] * t3;
if (IsNaN(nom_x)) or (IsNaN(nom_y)) or (IsNaN(denom)) then Exit;
if denom = 0 then Exit;
solution.x := nom_x / denom;
solution.y := nom_y / denom;
end;
function BezierFunc(t: double; src: BezierPoints; w: BezierWeights): double;
var
p: BezierPoint;
begin
BezierSolve(t, src, w, p);
Result := p.y;
end;
end.

268
Core/Chaotica.pas Normal file
View File

@ -0,0 +1,268 @@
unit Chaotica;
interface
uses Global, RegularExpressionsCore, RegexHelper, Classes, SysUtils, XFormMan, Windows,
ShellAPI, Forms, ControlPoint, Translation;
function C_GetPathOf(filename: string; usex64: boolean): string;
function C_SupportsDllPlugins(usex64: boolean): boolean;
function C_IsDllPluginBlacklisted(filename: string; usex64: boolean): boolean;
function C_IsVariationNative(name: string; usex64: boolean): boolean;
function C_IsDllPluginInstalled(filename: string): boolean;
procedure C_SyncDllPlugins;
procedure C_InstallVariation(name: string);
procedure C_ExecuteChaotica(flamexml: string; plugins: TStringList; usex64: boolean);
implementation
uses Main;
function CheckX64: Boolean;
var
SEInfo: TShellExecuteInfo;
ExitCode: DWORD;
ExecuteFile, ParamString, StartInString: string;
begin
{$ifdef Apo7X64}
Result := true;
exit;
{$endif}
ExecuteFile:=ExtractFilePath(Application.ExeName)+'chk64.exe';
FillChar(SEInfo, SizeOf(SEInfo), 0);
SEInfo.cbSize := SizeOf(TShellExecuteInfo);
with SEInfo do begin
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := Application.Handle;
lpFile := PChar(ExecuteFile) ;
nShow := SW_SHOWNORMAL;
end;
if ShellExecuteEx(@SEInfo) then
begin
repeat
Application.ProcessMessages;
GetExitCodeProcess(SEInfo.hProcess, ExitCode);
until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
Result := (ExitCode = 0);
end else begin
Result := false;
end;
end;
function C_GetPathOf(filename: string; usex64: boolean): string;
var
subf: string;
begin
if usex64 then subf := '64bit'
else subf := '32bit';
Result := ChaoticaPath + '\' + subf + '\' + filename;
end;
function C_SupportsDllPlugins(usex64: boolean): boolean;
const
re_root : string = '<variation_compatibility\s+(.*?)>.*?</variation_compatibility>';
re_attrib : string = 'supports_dll_plugins="(.*?)"';
var
xml_file : TStringList;
xml_text, attrib, value : string;
begin
if usex64 then begin
Result := false;
Exit;
end;
xml_file := TStringList.Create;
xml_file.LoadFromFile(C_GetPathOf('variation_compatibility.xml', false));
xml_text := xml_file.Text;
xml_file.Destroy;
attrib := GetStringPart(xml_text, re_root, 1, 'supports_dll_plugins="false"');
value := GetStringPart(attrib, re_attrib, 1, 'false');
Result := (value = 'true');
end;
function C_IsDllPluginBlacklisted(filename: string; usex64: boolean): boolean;
var
i: integer;
blacklist: TStringList;
begin
blacklist := TStringList.Create;
blacklist.LoadFromFile(C_GetPathOf('plugin_dll_blacklist.txt', usex64));
for i := 0 to blacklist.Count - 1 do begin
if LowerCase(filename) = LowerCase(blacklist.Strings[i]) then begin
Result := true;
blacklist.Destroy;
Exit;
end;
end;
blacklist.Destroy;
Result := false;
end;
function C_IsVariationNative(name: string; usex64: boolean): boolean;
const
re_root : string = '<variation_compatibility.*?>(.*?)</variation_compatibility>';
re_var : string = '<variation name="(.*?)".*?/>';
var
xml, var_name : string;
xml_file : TStringList;
find_var : TPerlRegEx;
found_var : boolean;
begin
xml_file := TStringList.Create;
xml_file.LoadFromFile(C_GetPathOf('variation_compatibility.xml', false));
xml := xml_file.Text;
xml_file.Destroy;
find_var := TPerlRegEx.Create;
find_var.RegEx := Utf8String(re_var);
find_var.Options := [preSingleLine, preCaseless];
find_var.Subject := Utf8String(GetStringPart(xml, re_root, 1, ''));
found_var := find_var.Match;
while found_var do begin
var_name := String(find_var.Groups[1]);
found_var := find_var.MatchAgain;
if LowerCase(name) = var_name then begin
find_var.Destroy;
Result := true;
Exit;
end;
end;
find_var.Destroy;
Result := false;
end;
function C_IsDllPluginInstalled(filename: string): boolean;
var
path : string;
begin
path := C_GetPathOf('plugins\' + filename, false);
Result := FileExists(path);
end;
////////////////////////////////////////////////////////////////////
procedure C_InstallVariation(name: string);
var
filename: string;
begin
filename := GetFileNameOfVariation(name);
if (filename = '') then Exit;
if C_IsDllPluginInstalled(filename) then Exit;
CopyFile(PCHAR(filename), PCHAR(C_GetPathOf('plugins\' +
ExtractFileName(filename), false)), false);
end;
procedure C_SyncDllPlugins;
var
src_dir: string;
tgt_dir: string;
searchResult: TSearchRec;
begin
src_dir := PluginPath;
tgt_dir := C_GetPathOf('Plugins', false);
if (not DirectoryExists(src_dir)) then Exit;
if (not DirectoryExists(tgt_dir)) then Exit;
// First clear all plugins on Chaotica side
if FindFirst(tgt_dir + '\*.dll', faAnyFile, searchResult) = 0 then
begin
repeat
DeleteFile(PCHAR(tgt_dir + '\' + searchResult.Name)) ;
until (FindNext(searchResult) <> 0);
SysUtils.FindClose(searchResult);
end;
// Then copy all plugins from Apophysis to Chaotica
if FindFirst(src_dir + '*.dll', faAnyFile, searchResult) = 0 then
begin
repeat
if not C_IsDllPluginBlacklisted(searchResult.Name, false)
then CopyFile(
PCHAR(src_dir + '\' + searchResult.Name),
PCHAR(tgt_dir + '\' + searchResult.Name),
false);
until (FindNext(searchResult) <> 0);
SysUtils.FindClose(searchResult);
end;
end;
procedure C_ExecuteChaotica(flamexml: string; plugins: TStringList; usex64: boolean);
var
i: integer;
name, fname: string;
fails: TStringList;
txt: TStringList;
fin_usex64: boolean;
begin
fails := TStringList.Create;
{$ifdef Apo7X64}
fin_usex64 := true;
{$else}
fin_usex64 := usex64 and CheckX64;
for i := 0 to plugins.Count - 1 do begin
name := GetFileNameOfVariation(plugins.Strings[i]);
if (name = '') then name := plugins.Strings[i];
fin_usex64 := fin_usex64 and C_IsVariationNative(name, usex64);
end;
for i := 0 to plugins.Count - 1 do begin
name := GetFileNameOfVariation(plugins.Strings[i]);
if (name = '') then name := plugins.Strings[i]; // assume built-in
if not C_IsVariationNative(name, fin_usex64) then begin // not native -> try install
if C_SupportsDllPlugins(fin_usex64) then // dll unsupported -> fail
fails.Add(plugins.Strings[i])
else if C_IsDllPluginBlacklisted(name, fin_usex64) then // dll supported and blacklisted -> fail
fails.Add(plugins.Strings[i])
;//else C_InstallVariation(plugins.Strings[i]); // dll supported and not blacklisted -> install
// ^^^ this is done on Apophysis startup now!
end;
end;
{$endif}
name := C_GetPathOf('chaotica.exe', fin_usex64);
if (not FileExists(name)) then begin
messagebox(0, PCHAR(TextByKey('main-status-nochaotica')),
PCHAR('Apophysis 7X'), MB_ICONHAND);
Exit;
end;
if (fails.Count > 0) then begin
messagebox(0, PCHAR(TextByKey('main-status-oldchaotica')),
PCHAR('Apophysis 7X'), MB_ICONHAND or MB_OK);
end;
fname := GetEnvironmentVariable('TEMP') + '\chaotica_export.flame';
txt := TStringList.Create;
txt.Text := flamexml;
txt.SaveToFile(fname);
txt.Destroy;
fails.Destroy;
//if fin_usex64 then MessageBox(0, PCHAR('DBG:x64'), PCHAR(''), MB_OK)
//else MessageBox(0, PCHAR('DBG:x86'), PCHAR(''), MB_OK) ;
ShellExecute(application.handle, PChar('open'), pchar(name),
PChar('"' + fname + '"'), PChar(ExtractFilePath(name)), SW_SHOWNORMAL);
end;
end.

689
Core/Global.pas Normal file
View File

@ -0,0 +1,689 @@
{
Apophysis Copyright (C) 2001-2004 Mark Townsend
Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov
Apophysis Copyright (C) 2007-2008 Piotr Borys, Peter Sdobnov
Apophysis "3D hack" Copyright (C) 2007-2008 Peter Sdobnov
Apophysis "7X" Copyright (C) 2009-2010 Georg Kiehne
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; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
}
unit Global;
interface
uses
Windows, SysUtils, Classes, SyncObjs, Controls, Graphics, Math,
cmap, ControlPoint, Xform, CommDlg;
type
EFormatInvalid = class(Exception);
{ Weight manipulation }
{ Triangle transformations }
function triangle_area(t: TTriangle): double;
function transform_affine(const t: TTriangle; const Triangles: TTriangles): boolean;
function line_dist(x, y, x1, y1, x2, y2: double): double;
function dist(x1, y1, x2, y2: double): double;
{ Parsing functions }
function GetVal(token: string): string;
function ReplaceTabs(str: string): string;
{ Palette and gradient functions }
//function GetGradient(FileName, Entry: string): string;
{ Misc }
function det(a, b, c, d: double): double;
function solve3(x1, x2, x1h, y1, y2, y1h, z1, z2, z1h: double;
var a, b, e: double): double;
function OpenSaveFileDialog(Parent: TWinControl;
const DefExt,
Filter,
InitialDir,
Title: string;
var FileName: string;
MustExist,
OverwritePrompt,
NoChangeDir,
DoOpen: Boolean): Boolean;
procedure LoadThumbnailPlaceholder(ThumbnailSize : integer);
function GetEnvVarValue(const VarName: string): string;
const
APP_NAME: string = 'Apophysis 7x';
{$ifdef Apo7X64}
APP_BUILD: string = '64 bit';
{$else}
APP_BUILD: string = '32 bit';
{$endif}
MAX_TRANSFORMS: integer = 100;
prefilter_white: integer = 1024;
eps: double = 1E-10;
White_level = 200;
clyellow1 = TColor($17FCFF);
clplum2 = TColor($ECA9E6);
clSlateGray = TColor($837365);
FT_BMP = 1; FT_PNG = 2; FT_JPG = 3;
const
crEditArrow = 20;
crEditMove = 21;
crEditRotate = 22;
crEditScale = 23;
const
SingleBuffer : boolean =
{$ifdef Apo7X64}
false
{$else}
true
{$endif};
var
MainSeed: integer;
MainTriangles: TTriangles;
Transforms: integer; // Count of Tranforms
EnableFinalXform: boolean;
AppPath: string; // Path of applicatio file
OpenFile: string; // Name of currently open file
CanDrawOnResize: boolean;
PreserveWeights: boolean;
AlwaysCreateBlankFlame : boolean;
StartupCheckForUpdates : boolean;
TBWidth1 : integer;
TBWidth2 : integer;
TBWidth3 : integer;
TBWidth4 : integer;
TBWidth5 : integer;
ThumbnailPlaceholder : TBitmap;
WarnOnMissingPlugin : boolean;
EmbedThumbnails : boolean;
LanguageFile : string;
AvailableLanguages : TStringList;
PluginPath : string;
{ UPR Options }
UPRSampleDensity: integer;
UPRFilterRadius: double;
UPROversample: integer;
UPRAdjustDensity: boolean;
UPRColoringIdent: string;
UPRColoringFile: string;
UPRFormulaIdent: string;
UPRFormulaFile: string;
UPRWidth: Integer;
UPRHeight: Integer;
ImageFolder: string;
UPRPath: string; // Name and folder of last UPR file
cmap_index: integer; // Index to current gradient
Variation: TVariation; // Current variation
NumTries, TryLength: integer; // Settings for smooth palette
SmoothPaletteFile: string;
{ Editor }
UseFlameBackground, UseTransformColors: boolean;
HelpersEnabled: boolean;
EditorBkgColor, ReferenceTriangleColor: integer;
GridColor1, GridColor2, HelpersColor: integer;
ExtEditEnabled, TransformAxisLock, RebuildXaosLinks: boolean;
ShowAllXforms: boolean;
EditorPreviewTransparency: integer;
EnableEditorPreview: boolean;
{ Display }
defSampleDensity, defPreviewDensity: Double;
defGamma, defBrightness, defVibrancy,
defFilterRadius, defGammaThreshold: Double;
defOversample: integer;
{ Render }
renderDensity, renderFilterRadius: double;
renderOversample, renderWidth, renderHeight: integer;
renderBitsPerSample: integer;
renderPath: string;
JPEGQuality: integer;
renderFileFormat: integer;
InternalBitsPerSample: integer;
NrTreads: Integer;
UseNrThreads: integer;
PNGTransparency: integer;
ShowTransparency: boolean;
MainPreviewScale: double;
ExtendMainPreview: boolean;
StoreEXIF : boolean;
StoreParamsEXIF : boolean;
ExifAuthor : string;
{ Defaults }
LastOpenFile: string;
LastOpenFileEntry: integer;
RememberLastOpenFile: boolean;
UseSmallThumbnails: boolean;
ClassicListMode: boolean;
ConfirmDelete: boolean; // Flag confirmation of entry deletion
OldPaletteFormat: boolean;
ConfirmExit: boolean;
ConfirmStopRender: boolean;
SavePath, SmoothPalettePath: string;
RandomPrefix, RandomDate: string;
RandomIndex: integer;
FlameFile, GradientFile, GradientEntry, FlameEntry: string;
ParamFolder: string;
prevLowQuality, prevMediumQuality, prevHighQuality: double;
defSmoothPaletteFile: string;
BrowserPath: string; // Stored path of browser open dialog
EditPrevQual, MutatePrevQual, AdjustPrevQual: Integer;
randMinTransforms, randMaxTransforms: integer;
mutantMinTransforms, mutantMaxTransforms: integer;
KeepBackground: boolean;
randGradient: Integer;
randGradientFile: string;
defFlameFile: string;
PlaySoundOnRenderComplete: boolean;
RenderCompleteSoundFile: string;
SaveIncompleteRenders: boolean;
ShowRenderStats: boolean;
LowerRenderPriority: boolean;
SymmetryType: integer;
SymmetryOrder: integer;
SymmetryNVars: integer;
Variations: array of boolean;
//VariationOptions: int64;
MainForm_RotationMode: integer;
PreserveQuality: boolean;
{ For random gradients }
MinNodes, MaxNodes, MinHue, MaxHue, MinSat, MaxSat, MinLum, MaxLum: integer;
//ReferenceMode: integer;
BatchSize: Integer;
Compatibility: integer; //0 = original, 1 = Drave's
Favorites: TStringList;
Script: string;
ScriptPath: string;
SheepServer, SheepNick, SheepURL, SheepPW, flam3Path, helpPath: string;
ExportBatches, ExportOversample, ExportWidth, ExportHeight, ExportFileFormat: Integer;
ExportFilter, ExportDensity: Double;
ExportEstimator, ExportEstimatorMin, ExportEstimatorCurve: double;
ExportJitters: integer;
ExportGammaTreshold: double;
OpenFileType: TFileType;
// ResizeOnLoad: Boolean;
ShowProgress: Boolean;
defLibrary: string;
LimitVibrancy: Boolean;
DefaultPalette: TColorMap;
AutoOpenLog: Boolean;
AutoSaveEnabled: Boolean;
AutoSaveFreq: integer;
AutoSavePath: string;
LineCenterColor : integer;
LineThirdsColor : integer;
LineGRColor : integer;
EnableGuides : boolean;
function Round6(x: double): double;
implementation
function GetEnvVarValue(const VarName: string): string;
var
BufSize: Integer; // buffer size required for value
begin
// Get required buffer size (inc. terminal #0)
BufSize := GetEnvironmentVariable(
PChar(VarName), nil, 0);
if BufSize > 0 then
begin
// Read env var value into result string
SetLength(Result, BufSize - 1);
GetEnvironmentVariable(PChar(VarName),
PChar(Result), BufSize);
end
else
// No such environment variable
Result := '';
end;
procedure LoadThumbnailPlaceholder(ThumbnailSize : integer);
var
placeholder: TBitmap;
placeholderIcon: TBitmap;
const
pi_width = 48;
pi_height = 48;
begin
placeholder := TBitmap.Create;
placeholderIcon := TBitmap.Create;
placeholderIcon.Handle := LoadBitmap(hInstance, 'THUMB_PLACEHOLDER');
placeholder.PixelFormat := pf32bit;
placeholder.HandleType := bmDIB;
placeholder.Width := ThumbnailSize;
placeholder.Height := ThumbnailSize;
with placeholder.Canvas do begin
Brush.Color := $000000;
FillRect(Rect(0, 0, placeholder.Width, placeholder.Height));
Draw(round(ThumbnailSize / 2 - pi_width / 2), round(ThumbnailSize / 2 - pi_height / 2), placeholderIcon);
end;
placeholderIcon.Free;
ThumbnailPlaceholder := placeholder;
end;
{ IFS }
function det(a, b, c, d: double): double;
begin
Result := (a * d - b * c);
end;
function Round6(x: double): double;
// Really ugly, but it works
begin
// --Z-- this is ridiculous:
// Result := StrToFloat(Format('%.6f', [x]));
// and yes, this is REALLY ugly :-\
Result := RoundTo(x, -6);
end;
function solve3(x1, x2, x1h, y1, y2, y1h, z1, z2, z1h: double;
var a, b, e: double): double;
var
det1: double;
begin
det1 := x1 * det(y2, 1.0, z2, 1.0) - x2 * det(y1, 1.0, z1, 1.0)
+ 1 * det(y1, y2, z1, z2);
if (det1 = 0.0) then
begin
Result := det1;
EXIT;
end
else
begin
a := (x1h * det(y2, 1.0, z2, 1.0) - x2 * det(y1h, 1.0, z1h, 1.0)
+ 1 * det(y1h, y2, z1h, z2)) / det1;
b := (x1 * det(y1h, 1.0, z1h, 1.0) - x1h * det(y1, 1.0, z1, 1.0)
+ 1 * det(y1, y1h, z1, z1h)) / det1;
e := (x1 * det(y2, y1h, z2, z1h) - x2 * det(y1, y1h, z1, z1h)
+ x1h * det(y1, y2, z1, z2)) / det1;
a := Round6(a);
b := Round6(b);
e := Round6(e);
Result := det1;
end;
end;
function dist(x1, y1, x2, y2: double): double;
//var
// d2: double;
begin
(*
{ From FDesign source
{ float pt_pt_distance(float x1, float y1, float x2, float y2) }
d2 := (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
if (d2 = 0.0) then
begin
Result := 0.0;
exit;
end
else
Result := sqrt(d2);
*)
// --Z-- This is just amazing... :-\
// Someone needed an 'FDesign source' - to compute distance between two points??!?
Result := Hypot(x2-x1, y2-y1);
end;
function line_dist(x, y, x1, y1, x2, y2: double): double;
var
a, b, e, c: double;
begin
if ((x = x1) and (y = y1)) then
a := 0.0
else
a := sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
if ((x = x2) and (y = y2)) then
b := 0.0
else
b := sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
if ((x1 = x2) and (y1 = y2)) then
e := 0.0
else
e := sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
if ((a * a + e * e) < (b * b)) then
Result := a
else if ((b * b + e * e) < (a * a)) then
Result := b
else if (e <> 0.0) then
begin
c := (b * b - a * a - e * e) / (-2 * e);
if ((a * a - c * c) < 0.0) then
Result := 0.0
else
Result := sqrt(a * a - c * c);
end
else
Result := a;
end;
function transform_affine(const t: TTriangle; const Triangles: TTriangles): boolean;
var
ra, rb, rc, a, b, c: double;
begin
Result := True;
ra := dist(Triangles[-1].y[0], Triangles[-1].x[0],
Triangles[-1].y[1], Triangles[-1].x[1]);
rb := dist(Triangles[-1].y[1], Triangles[-1].x[1],
Triangles[-1].y[2], Triangles[-1].x[2]);
rc := dist(Triangles[-1].y[2], Triangles[-1].x[2],
Triangles[-1].y[0], Triangles[-1].x[0]);
a := dist(t.y[0], t.x[0], t.y[1], t.x[1]);
b := dist(t.y[1], t.x[1], t.y[2], t.x[2]);
c := dist(t.y[2], t.x[2], t.y[0], t.x[0]);
if (a > ra) then
Result := False
else if (b > rb) then
Result := False
else if (c > rc) then
Result := False
else if ((a = ra) and (b = rb) and (c = rc)) then
Result := False;
end;
function triangle_area(t: TTriangle): double;
var
base, height: double;
begin
try
base := dist(t.x[0], t.y[0], t.x[1], t.y[1]);
height := line_dist(t.x[2], t.y[2], t.x[1], t.y[1],
t.x[0], t.y[0]);
if (base < 1.0) then
Result := height
else if (height < 1.0) then
Result := base
else
Result := 0.5 * base * height;
except on E: EMathError do
Result := 0;
end;
end;
{ Parse }
function GetVal(token: string): string;
var
p: integer;
begin
p := Pos('=', token);
Delete(Token, 1, p);
Result := Token;
end;
function ReplaceTabs(str: string): string;
{Changes tab characters in a string to spaces}
var
i: integer;
begin
for i := 1 to Length(str) do
begin
if str[i] = #9 then
begin
Delete(str, i, 1);
Insert(#32, str, i);
end;
end;
Result := str;
end;
(*
{ Palette and gradient functions }
function RGBToColor(Pal: TMapPalette; index: integer): Tcolor;
begin
{ Converts the RGB values from a palette index to the TColor type ...
could maybe change it to SHLs }
Result := (Pal.Blue[index] * 65536) + (Pal.Green[index] * 256)
+ Pal.Red[index];
end;
procedure rgb2hsv(const rgb: array of double; out hsv: array of double);
var
maxval, minval: double;
del: double;
begin
Maxval := Max(rgb[0], Max(rgb[1], rgb[2]));
Minval := Min(rgb[0], Min(rgb[1], rgb[2]));
hsv[2] := maxval; // v
if (Maxval > 0) and (maxval <> minval) then begin
del := maxval - minval;
hsv[1] := del / Maxval; //s
hsv[0] := 0;
if (rgb[0] > rgb[1]) and (rgb[0] > rgb[2]) then begin
hsv[0] := (rgb[1] - rgb[2]) / del;
end else if (rgb[1] > rgb[2]) then begin
hsv[0] := 2 + (rgb[2] - rgb[0]) / del;
end else begin
hsv[0] := 4 + (rgb[0] - rgb[1]) / del;
end;
if hsv[0] < 0 then
hsv[0] := hsv[0] + 6;
end else begin
hsv[0] := 0;
hsv[1] := 0;
end;
end;
procedure hsv2rgb(const hsv: array of double; out rgb: array of double);
var
j: integer;
f, p, q, t, v: double;
begin
j := floor(hsv[0]);
f := hsv[0] - j;
v := hsv[2];
p := hsv[2] * (1 - hsv[1]);
q := hsv[2] * (1 - hsv[1] * f);
t := hsv[2] * (1 - hsv[1] * (1 - f));
case j of
0: begin rgb[0] := v; rgb[1] := t; rgb[2] := p; end;
1: begin rgb[0] := q; rgb[1] := v; rgb[2] := p; end;
2: begin rgb[0] := p; rgb[1] := v; rgb[2] := t; end;
3: begin rgb[0] := p; rgb[1] := q; rgb[2] := v; end;
4: begin rgb[0] := t; rgb[1] := p; rgb[2] := v; end;
5: begin rgb[0] := v; rgb[1] := p; rgb[2] := t; end;
end;
end;
function GetGradient(FileName, Entry: string): string;
var
FileStrings: TStringList;
GradStrings: TStringList;
i: integer;
begin
FileStrings := TStringList.Create;
GradStrings := TStringList.Create;
try
try
FileStrings.LoadFromFile(FileName);
for i := 0 to FileStrings.count - 1 do
if Pos(Entry + ' ', Trim(FileStrings[i])) = 1 then break;
GradStrings.Add(FileStrings[i]);
repeat
inc(i);
GradStrings.Add(FileStrings[i]);
until Pos('}', FileStrings[i]) <> 0;
GetGradient := GradStrings.Text;
except on exception do
Result := '';
end;
finally
GradStrings.Free;
FileStrings.Free;
end;
end;
*)
function ReplaceStr(Str, SearchStr, ReplaceStr: string): string;
begin
while Pos(SearchStr, Str) <> 0 do
begin
Insert(ReplaceStr, Str, Pos(SearchStr, Str));
system.Delete(Str, Pos(SearchStr, Str), Length(SearchStr));
end;
Result := Str;
end;
function SplitFilter(const fText: String; const fSep: Char; fTrim: Boolean=false; fQuotes: Boolean=false):TStringList;
var vI: Integer;
vBuffer: String;
vOn: Boolean;
begin
Result:=TStringList.Create;
vBuffer:='';
vOn:=true;
for vI:=1 to Length(fText) do
begin
if (fQuotes and(fText[vI]=fSep)and vOn)or(Not(fQuotes) and (fText[vI]=fSep)) then
begin
if fTrim then vBuffer:=Trim(vBuffer);
if vBuffer='' then vBuffer:=fSep; // !!! e.g. split(',**',',')...
if vBuffer[1]=fSep then
vBuffer:=Copy(vBuffer,2,Length(vBuffer));
Result.Add(vBuffer);
vBuffer:='';
end;
if fQuotes then
begin
if fText[vI]='"' then
begin
vOn:=Not(vOn);
Continue;
end;
if (fText[vI]<>fSep)or((fText[vI]=fSep)and(vOn=false)) then
vBuffer:=vBuffer+fText[vI];
end else
if fText[vI]<>fSep then
vBuffer:=vBuffer+fText[vI];
end;
if vBuffer<>'' then
begin
if fTrim then vBuffer:=Trim(vBuffer);
Result.Add(vBuffer);
end;
end;
function OpenSaveFileDialog(Parent: TWinControl;
const DefExt,
Filter,
InitialDir,
Title: string;
var FileName: string;
MustExist,
OverwritePrompt,
NoChangeDir,
DoOpen: Boolean): Boolean;
// uses commdlg
var
ofn: TOpenFileName;
szFile: array[0..260] of Char;
fa, fa2: TStringList;
h,i,j,k,c : integer;
cs, s : string;
begin
Result := False;
FillChar(ofn, SizeOf(TOpenFileName), 0);
with ofn do
begin
lStructSize := SizeOf(TOpenFileName);
hwndOwner := Parent.Handle;
lpstrFile := szFile;
nMaxFile := SizeOf(szFile);
if (Title <> '') then
lpstrTitle := PChar(Title);
if (InitialDir <> '') then
lpstrInitialDir := PChar(InitialDir);
StrPCopy(lpstrFile, FileName);
lpstrFilter := PChar(ReplaceStr(Filter, '|', #0)+#0#0);
fa := splitFilter(Filter, '|');
k := 0;
c := (fa.Count div 2);
for i := 0 to c - 1 do begin
j := 2 * i + 1;
cs := LowerCase(fa.Strings[j]);
fa2 := splitFilter(cs, ';');
for h := 0 to fa2.Count - 1 do begin
cs := fa2.Strings[h];
s := '*.' + LowerCase(DefExt);
if (cs = s) then k := i;
end;
end;
nFilterIndex := k + 1;
if DefExt <> '' then
lpstrDefExt := PChar(DefExt);
end;
if MustExist then ofn.Flags := ofn.Flags or OFN_FILEMUSTEXIST;
if OverwritePrompt then ofn.Flags := ofn.Flags or OFN_OVERWRITEPROMPT;
if NoChangeDir then ofn.Flags := ofn.Flags or OFN_NOCHANGEDIR;
if DoOpen then
begin
if GetOpenFileName(ofn) then
begin
Result := True;
FileName := StrPas(szFile);
end;
end
else
begin
if GetSaveFileName(ofn) then
begin
Result := True;
FileName := StrPas(szFile);
end;
end
end; // function OpenSaveFileDialog
end.

754
Core/Translation.pas Normal file
View File

@ -0,0 +1,754 @@
unit Translation;
interface
uses Global, Classes, Forms, LibXmlParser, LibXmlComps, SysUtils, RegexHelper;
procedure ListLanguages;
procedure LanguageInfo(path: string; var name, localName: string);
function LanguageAuthor(path: string): string;
procedure Add(key, value: string);
procedure LoadLanguage(path:string);
procedure LoadEnglish();
function TextByKey(key:string):string;
type
TParser = class
public
constructor Create;
procedure ListXmlScannerStartTag(Sender: TObject; TagName: string; Attributes: TAttrList);
procedure ListXmlScannerEndTag(Sender: TObject; TagName: string);
procedure ListXmlScannerEmptyTag(Sender: TObject; TagName: string; Attributes: TAttrList);
procedure ListXmlScannerContent(Sender: TObject; Content: string);
private
currentTagname: string;
parentTagnames: TStringList;
end;
TKeyValuePair = class
public
key: string;
value: string;
end;
TDictionary = array of TKeyValuePair;
var
language: TDictionary;
defaultlanguage: TDictionary;
tokenCount: integer;
ListXmlScanner: TEasyXmlScanner;
parser: TParser;
implementation
procedure ListLanguages;
var
searchResult: TSearchRec;
begin
if FindFirst(ExtractFilePath(Application.ExeName) + 'Languages\*.xml', faAnyFile, searchResult) = 0 then
begin
repeat
AvailableLanguages.Add(ExtractFilePath(Application.ExeName) + 'Languages\' + searchResult.Name);
until (FindNext(searchResult) <> 0);
SysUtils.FindClose(searchResult);
end;
end;
procedure LanguageInfo(path: string; var name, localName: string);
const
exp1 = '\stitle="([^"]*)"';
exp2 = '\slocalized-title="([^"]*)"';
var
langxml : string;
sl: TStringList;
begin
sl := TStringList.Create;
sl.LoadFromFile(path);
langxml := sl.Text;
sl.Destroy;
name := GetStringPart(langxml, exp1, 1, '');
localname := GetStringPart(langxml, exp2, 1, '');
end;
function LanguageAuthor(path: string): string;
const
exp = '\sauthor="([^"]*)"';
var
langxml : string;
sl: TStringList;
begin
sl := TStringList.Create;
sl.LoadFromFile(path);
langxml := sl.Text;
sl.Destroy;
Result := GetStringPart(langxml, exp, 1, '');
end;
procedure LoadEnglish();
begin
//TODO:
//render-status-renderhibernated
Add('common-ok', 'OK');
Add('common-cancel', 'Cancel');
Add('common-apply', 'Apply');
Add('common-yes', 'Yes');
Add('common-no', 'No');
Add('common-lowquality', 'Low Quality');
Add('common-mediumquality', 'Medium Quality');
Add('common-highquality', 'High Quality');
Add('common-copy', 'Copy');
Add('common-paste', 'Paste');
Add('common-delete', 'Delete');
Add('common-rename', 'Rename');
Add('common-undo', 'Undo');
Add('common-redo', 'Redo');
Add('common-width', 'Width');
Add('common-height', 'Height');
Add('common-size', 'Size');
Add('common-pixels', 'Pixels');
Add('common-keepaspect', 'Maintain aspect ratio');
Add('common-destination', 'Destination');
Add('common-filename', 'File name');
Add('common-browse', 'Browse...');
Add('common-quality', 'Quality');
Add('common-filterradius', 'Filter Radius');
Add('common-density', 'Density');
Add('common-oversample', 'Oversample');
Add('common-gamma', 'Gamma');
Add('common-brightness', 'Brightness');
Add('common-contrast', 'Contrast');
Add('common-vibrancy', 'Vibrancy');
Add('common-background', 'Background');
Add('common-gammathreshold', 'Gamma Threshold');
Add('common-start', 'Start');
Add('common-pause', 'Pause');
Add('common-resume', 'Resume');
Add('common-close', 'Close');
Add('common-clear', 'Clear');
Add('common-enabled', 'Enabled');
Add('common-disabled', 'Disabled');
Add('common-minimum', 'Minimum');
Add('common-maximum', 'Maximum');
Add('common-resetlocation', 'Reset location');
Add('common-genericopenfailure', 'Unable to open "%s".');
Add('common-genericsavefailure', 'Unable to save "%s".');
Add('common-invalidformat', 'Invalid format.');
Add('common-confirmexit', 'Do you really want to exit? All unsaved data will be lost!');
Add('common-confirmdelete', 'Are you sure you want to permanently delete "%s"?');
Add('common-dragpanelhint', 'Click and drag to change value');
Add('common-trace-pausing', 'Pausing render');
Add('common-trace-resuming', 'Resuming render');
Add('common-trace-terminating', 'Terminating render');
Add('common-trace-stopping', 'Stopping render');
Add('common-trace-saving', 'Saving image...');
Add('common-trace-creating-simple', 'Creating image...');
Add('common-trace-creating-detailed', 'Creating image with quality: %f...');
Add('common-trace-rendering-oneslice', 'Rendering...');
Add('common-trace-rendering-multipleslices', 'Rendering slice %d of %d...');
Add('common-trace-allocating', 'Allocating %n Mb of memory...');
Add('common-trace-notenoughmemory', 'ERROR: Not enough memory for this render!');
Add('common-statistics-title-oneslice', 'Render Statistics:');
Add('common-statistics-title-multipleslices', 'Render Statistics for the last slice:');
Add('common-statistics-maxpossiblebits', 'Max possible bits: %2.3f');
Add('common-statistics-maxred', 'Max Red: %2.3f bits');
Add('common-statistics-maxgreen', 'Max Green: %2.3f bits');
Add('common-statistics-maxblue', 'Max Blue: %2.3f bits');
Add('common-statistics-maxcounter', 'Max Count: %2.3f bits');
Add('common-statistics-pointhitratio', 'Point hit ratio: %2.2f%%');
Add('common-statistics-averagespeed', 'Average speed: %n iterations per second');
Add('common-statistics-purerenderingtime', 'Pure rendering time:');
Add('common-seconds', 'second(s)');
Add('common-minutes', 'minute(s)');
Add('common-hours', 'hour(s)');
Add('common-days', 'day(s)');
Add('common-suspendtodisk', 'Suspend to disk');
Add('common-resumefromdisk', 'Resume from disk');
Add('common-filter-flamefiles', 'Apophysis Flame Library (*.flame;*.xml)');
Add('common-filter-gradientfiles', 'Gradient files (*.gradient;*.ugr)');
Add('common-filter-fractintfiles', 'Fractint maps (*.map)');
Add('common-filter-uprfiles', 'UltraFractal parameters (*.upr)');
Add('common-filter-script', 'Apophysis Script (*.aposcript;*.asc)');
Add('common-filter-allimages', 'All images (*.bmp;*.dib;*.jpg;*.jpeg)');
Add('common-filter-bitmap', 'Windows Bitmap (*.bmp;*.dib)');
Add('common-filter-jpeg', 'JPEG (*.jpg;*.jpeg)');
Add('common-filter-png', 'Portable Network Graphics (*.png)');
Add('common-filter-allfiles', 'All files (*.*)');
Add('splash-loadingui', 'Loading user interface...');
Add('splash-loadingsettings', 'Loading settings...');
Add('splash-loadingplugins', 'Loading plugins...');
Add('splash-initrenderer', 'Initializing renderer...');
Add('splash-initcolormap', 'Initializing gradients...');
Add('splash-initbatch', 'Creating random batch...');
Add('splash-execstartupscript', 'Executing "autoexec.asc"...');
Add('adjustment-title', 'Adjustment');
Add('adjustment-common-depthblur', 'Depth Blur');
Add('adjustment-common-pitch', 'Pitch');
Add('adjustment-common-yaw', 'Yaw');
Add('adjustment-common-height', 'Height');
Add('adjustment-common-perspective', 'Perspective');
Add('adjustment-common-scale', 'Scale');
Add('adjustment-tab-camera-title', 'Camera');
Add('adjustment-tab-camera-zoom', 'Zoom');
Add('adjustment-tab-camera-xpos', 'X-Position');
Add('adjustment-tab-camera-ypos', 'Y-Position');
Add('adjustment-tab-camera-rotation', 'Rotation');
Add('adjustment-tab-rendering-title', 'Rendering');
Add('adjustment-tab-rendering-istransparent', 'Transparent');
Add('adjustment-tab-gradient-title', 'Gradient');
Add('adjustment-tab-gradient-moderotate', 'Rotate');
Add('adjustment-tab-gradient-modehue', 'Hue');
Add('adjustment-tab-gradient-modesaturation', 'Saturation');
Add('adjustment-tab-gradient-modebrightness', 'Brightness');
Add('adjustment-tab-gradient-modecontrast', 'Contrast');
Add('adjustment-tab-gradient-modeblur', 'Blur');
Add('adjustment-tab-gradient-modefrequency', 'Frequency');
Add('adjustment-tab-gradient-preset', 'Preset');
Add('adjustment-tab-gradient-reset', 'Reset');
Add('adjustment-tab-gradient-modehint', 'Click for menu');
Add('adjustment-tab-gradient-presethint', 'Click to choose random preset');
Add('adjustment-tab-size-title', 'Image size');
Add('adjustment-tab-size-preset', 'Empty preset');
Add('adjustment-tab-size-resizemain', 'Resize main window');
Add('adjustment-tab-curves-title', 'Curves');
Add('adjustment-tab-curves-reset', 'Reset');
Add('adjustment-tab-curves-selected', 'Selected curve:');
Add('adjustment-tab-curves-overall', 'Overall');
Add('adjustment-tab-curves-red', 'Red');
Add('adjustment-tab-curves-green', 'Green');
Add('adjustment-tab-curves-blue', 'Blue');
Add('adjustment-popup-quality-instantpreview', 'Instant preview');
Add('adjustment-popup-gradient-randomize', 'Randomize');
Add('adjustment-popup-gradient-invert', 'Invert');
Add('adjustment-popup-gradient-reverse', 'Reverse');
Add('adjustment-popup-gradient-smooth', 'Smooth Palette...');
Add('adjustment-popup-gradient-browser', 'Gradient Browser...');
Add('adjustment-popup-gradient-saveasugr', 'Save Gradient...');
Add('adjustment-popup-gradient-saveasmap', 'Save as Map File...');
Add('adjustment-popup-gradient-saveasdefault', 'Save as default');
Add('editor-title', 'Editor');
Add('editor-common-transform', 'Transform:');
Add('editor-common-name', 'Name:');
Add('editor-common-weight', 'Weight:');
Add('editor-common-finalxformlistitem', 'Final');
Add('editor-common-fromprefix', 'from %d');
Add('editor-common-toprefix', 'to %d');
Add('editor-tab-variations-title', 'Variations');
Add('editor-tab-variations-name', 'Name');
Add('editor-tab-variations-value', 'Value');
Add('editor-tab-variations-togglehideunused', 'Hide unused variations');
Add('editor-tab-variables-title', 'Variables');
Add('editor-tab-variables-name', 'Name');
Add('editor-tab-variables-value', 'Value');
Add('editor-tab-variables-toggleshowall', 'Show all variables');
Add('editor-tab-chaos-title', 'Xaos');
Add('editor-tab-chaos-path', 'Path');
Add('editor-tab-chaos-modifier', 'Weight modifier');
Add('editor-tab-chaos-viewasto', 'View as "to"');
Add('editor-tab-chaos-viewasfrom', 'View as "from"');
Add('editor-tab-triangle-title', 'Triangle');
Add('editor-tab-triangle-pivot', 'Pivot');
Add('editor-tab-triangle-modelocal', 'Local');
Add('editor-tab-triangle-modeworld', 'World');
Add('editor-tab-triangle-resetpivot', 'Reset pivot point');
Add('editor-tab-triangle-pickpivot', 'Pick pivot point');
Add('editor-tab-triangle-rotateleft', 'Rotate triangle counter-clockwise');
Add('editor-tab-triangle-rotateright', 'Rotate triangle clockwise');
Add('editor-tab-triangle-moveup', 'Move triangle up');
Add('editor-tab-triangle-movedown', 'Move triangle down');
Add('editor-tab-triangle-moveleft', 'Move triangle left');
Add('editor-tab-triangle-moveright', 'Move triangle right');
Add('editor-tab-triangle-scaledown', 'Scale triangle down');
Add('editor-tab-triangle-scaleup', 'Scale triangle up');
Add('editor-tab-triangle-autoweight', 'Auto-balance weights');
Add('editor-tab-transform-title', 'Transform');
Add('editor-tab-transform-reset', 'Reset transform');
Add('editor-tab-transform-resethint', 'Reset all vectors to default position');
Add('editor-tab-transform-rectangular', 'Rectangular');
Add('editor-tab-transform-rectangularhint', 'Show vectors in rectangular (cartesian) corrdinates');
Add('editor-tab-transform-polar', 'Polar (deg)');
Add('editor-tab-transform-polarhint', 'Show vector in polar coordinates');
Add('editor-tab-transform-resetpost', 'Reset post transform');
Add('editor-tab-transform-resetposthint', 'Reset all post-transform vectors to default position');
Add('editor-tab-transform-autozscale', 'Auto-calculate pre_zscale');
Add('editor-tab-transform-resetxhint', 'Reset vector X');
Add('editor-tab-transform-resetyhint', 'Reset vector Y');
Add('editor-tab-transform-resetohint', 'Reset vector O');
Add('editor-tab-color-title', 'Colors');
Add('editor-tab-color-transformcolor', 'Transform color');
Add('editor-tab-color-colorspeed', 'Color speed');
Add('editor-tab-color-opacity', 'Opacity');
Add('editor-tab-color-directcolor', 'Direct color');
Add('editor-tab-color-togglesolo', 'Solo');
Add('editor-tab-color-togglesoloformat', 'Solo transform #%d');
Add('editor-tab-color-varpreview', 'Variation preview');
Add('editor-tab-color-previewrange', 'Range');
Add('editor-tab-color-previewdepth', 'Depth');
Add('editor-tab-color-previewdensity', 'Density');
Add('editor-tab-color-preview', 'Preview');
Add('editor-toolbar-newflame', 'New flame');
Add('editor-toolbar-newtransform', 'New transform');
Add('editor-toolbar-addlinkedtransform', 'Add linked transform');
Add('editor-toolbar-duplicatetransform', 'Duplicate transform');
Add('editor-toolbar-removetransform', 'Remove transform');
Add('editor-toolbar-modeselect', 'Selection mode');
Add('editor-toolbar-modemove', 'Movement mode');
Add('editor-toolbar-moderotate', 'Rotation mode');
Add('editor-toolbar-modescale', 'Scale mode');
Add('editor-toolbar-toggleworldpivot', 'Toggle world pivot');
Add('editor-toolbar-rotate90ccw', 'Rotate 90° counter-clockwise');
Add('editor-toolbar-rotate90cw', 'Rotate 90° clockwise');
Add('editor-toolbar-fliph', 'Flip horizontal');
Add('editor-toolbar-flipv', 'Flip vertical');
Add('editor-toolbar-togglevarpreview', 'Show variation preview');
Add('editor-toolbar-toggleposttransform', 'Enable/edit post-transform');
Add('editor-toolbar-togglefinaltransform', 'Enable final transform');
Add('editor-popup-panel-autozoom', 'Zoom automatically');
Add('editor-popup-panel-toggleextendededit', 'Toggle extended edit mode');
Add('editor-popup-panel-locktransformaxes', 'Lock transform axes');
Add('editor-popup-panel-allfliph', 'Flip all horizontally');
Add('editor-popup-panel-allflipv', 'Flip all vertically');
Add('editor-popup-quality-autoreset', 'Auto-reset location');
Add('editor-popup-transform-resetposition', 'Reset position');
Add('editor-popup-transform-resetrotation', 'Reset rotation');
Add('editor-popup-transform-resetscale', 'Reset scale');
Add('editor-popup-transform-copycoords', 'Copy triangle coordinates');
Add('editor-popup-transform-pastecoords', 'Paste triangle coordinates');
Add('editor-popup-transform-resetentiretriangle', 'Reset triangle');
Add('editor-popup-chaos-rebuildlinks', 'Rebuild links');
Add('editor-popup-chaos-clearall', 'Clear all');
Add('editor-popup-chaos-setall', 'Set all');
Add('editor-status-zoomformat', 'Zoom: %f');
Add('editor-status-xformat', 'X: %f');
Add('editor-status-yformat', 'Y: %f');
Add('editor-status-rotateformat', 'Rotate: %3.2f° Inner angle: %3.2f°');
Add('editor-status-rotateformat2', 'Rotate: %3.2f° Local axis: %3.2f°');
Add('editor-status-rotateformat3', 'Rotate: %3.2f°');
Add('editor-status-scaleformat', 'Distance: %3.3f Scale: %3.2f%%');
Add('editor-status-scaleformat2', 'Scale: %3.2f%%');
Add('editor-status-moveformat', 'Move: %3.3f ; %3.3f');
Add('editor-status-moveformat2', 'Move: %3.3f ; %3.3f');
Add('editor-status-transformformat', 'Transform #%d');
Add('editor-status-zoomformat', 'Zoom: %f');
Add('editor-status-selecton', 'Select ON');
Add('editor-status-selectoff', 'Select OFF');
Add('export-title', 'Export to flam3');
Add('export-paramoptions-title', 'Parameter options');
Add('export-paramoptions-bufferdepth', 'Buffer depth');
Add('export-paramoptions-strips', 'Strips');
Add('export-paramoptions-estimatorradius', 'DE radius');
Add('export-paramoptions-estimatorcurve', 'DE curve');
Add('export-paramoptions-estimatormin', 'DE minimum');
Add('export-paramoptions-dorender', 'Render');
Add('export-paramoptions-warningtitle', 'WARNING');
Add('export-paramoptions-warningtext', 'Fractals created with this version of Apophysis are not supported by flam3! To render 2D-only fractals, download the latest version of flam3 from http://www.flam3.com');
Add('favscripts-title', 'Favorite scripts');
Add('favscripts-add', 'Add');
Add('favscripts-remove', 'Remove');
Add('favscripts-moveup', 'Move up');
Add('favscripts-movedown', 'Move down');
Add('fullscreen-popup-rendermore', 'Render more');
Add('fullscreen-popup-stoprender', 'Stop render');
Add('gradientbrowser-title', 'Gradient Browser');
Add('postprocess-title', 'Post-process render');
Add('postprocess-save', 'Save');
Add('postprocess-fittowindow', 'Fit to window');
Add('render-title', 'Render flame');
Add('render-common-gotofolder', 'Open target folder...');
Add('render-tab-settings-title', 'Settings');
Add('render-tab-output-title', 'Output');
Add('render-resourceusage-title', 'Resource usage');
Add('render-resourceusage-infotext', 'The render process will use %u MB of %u MB available physical memory');
Add('render-resourceusage-infotext2', 'Apophysis will try to use %u processor cores (%u available) - change this in the options');
Add('render-resourceusage-limit', 'Memory limit');
Add('render-resourceusage-nolimit', 'No limit');
Add('render-resourceusage-bufferdepth', 'Buffer depth');
Add('render-output-title', 'Output options');
Add('render-output-saveparams', 'Save parameters');
Add('render-completion-title', 'Completion options');
Add('render-completion-postprocess', 'Post-process after rendering');
Add('render-completion-shutdown', 'Shut down after rendering');
Add('render-completion-saveincomplete', 'Save incomplete renders');
Add('render-status-rendererror-log', 'Rendering failed!');
Add('render-status-rendererror-message', 'Error while rendering!');
Add('render-status-saveerror-log', 'Error saving image!');
Add('render-status-saveerror-message1', 'An error occured while saving the image:');
Add('render-status-saveerror-message2', 'Check your free disk space and try again.');
Add('render-status-totaltime', 'Total time:');
Add('render-status-renderterminated', 'Rendering terminated!');
Add('render-status-renderhibernated', 'Rendering paused and progress saved!');
Add('render-status-elapsed', 'Elapsed');
Add('render-status-remaining', 'Remaining');
Add('render-status-slicestatus', 'Slice %d of %d');
Add('render-status-notenoughmemory1', 'You do not have enough memory for this render. Do you want to continue anyway?');
Add('render-status-notenoughmemory2', 'You do not have enough memory for this render. Please use a lower Maximum memory setting. Do you want to ignore this problem and continue?');
Add('render-status-nofilename', 'Please enter a file name.');
Add('render-status-fileexists-message1', '"%s" already exists');
Add('render-status-fileexists-message2', 'Do you want to replace it?');
Add('render-status-pathdoesnotexist', 'The directory does not exist.');
Add('render-status-invaliddensity', 'Invalid Sample Density value');
Add('render-status-invalidfilterradius', 'Invalid Filter Radius value');
Add('render-status-invalidoversample', 'Invalid Oversample value');
Add('render-status-invalidwidth', 'Invalid image width');
Add('render-status-invalidheight', 'Invalid image height');
Add('render-status-maxmemorytoosmall', 'Maximum memory value is too small. Do you want to continue anyway?');
Add('render-status-shuttingdownrender', 'Shutting down previous render...');
Add('render-status-log-title', 'Rendering "%s"');
Add('render-status-log-size', 'Size: %dx%d');
Add('render-status-log-quality', 'Quality: %g');
Add('render-status-log-oversampling', 'Oversample: %d, Filter: %g');
Add('render-status-log-bufferdepth', 'Buffer depth: %s');
Add('render-status-log-memorylimit', 'Memory limit: %d MB');
Add('render-status-log-largepng-message1', '*** WARNING *** You have selected PNG format and an image size which exceeds 20 megapixels');
Add('render-status-log-largepng-message2', 'PNG format with extreme high-resolution images is not recommended!');
Add('render-status-log-largepng-message3', 'To avoid slowdown (and possible memory problems) use BMP file format instead.');
Add('render-status-confirmstop', 'Do you want to stop the current render?');
Add('imagecoloring-title', 'Image coloring');
Add('imagecoloring-enable', 'Enable');
Add('imagecoloring-firstpalette', 'First palette');
Add('imagecoloring-secondpalette', 'Second palette');
Add('imagecoloring-preset', 'Preset');
Add('imagecoloring-image', 'Image');
Add('messages-title', 'Messages');
Add('messages-openautomatically', 'Automatically open this window');
Add('mutation-title', 'Mutation');
Add('mutation-directions', 'Directions');
Add('mutation-speed', 'Speed');
Add('mutation-trend', 'Trend');
Add('mutation-keepnumberoftransforms', 'Keep transform count');
Add('mutation-randomtrend', 'Random');
Add('mutation-maintainsymmetry', 'Maintain symmetry');
Add('mutation-previous', 'Previous');
Add('options-title', 'Settings ');
Add('options-restartnotice', 'You must restart Apophysis 7x to make your changes have effect');
Add('options-tab-general-title', 'General ');
Add('options-tab-general-language', 'Language file');
Add('options-tab-general-multithreading', 'Multithreading ');
Add('options-tab-general-multithreading-off', 'Off ');
Add('options-tab-general-bufferdepth', 'Buffer depth ');
Add('options-tab-general-jpegquality', 'JPEG quality ');
Add('options-tab-general-pngtransparency', 'PNG transparency ');
Add('options-tab-general-showextendedstatistics', 'Show extended render statistics ');
Add('options-tab-general-confirmdelete', 'Confirm delete ');
Add('options-tab-general-confirmexit', 'Confirm exit ');
Add('options-tab-general-confirmrenderstop', 'Confirm stop rendering ');
Add('options-tab-general-oldgradientformat', 'Use old gradient format ');
Add('options-tab-general-alwaysblankflame', 'Disable templates ');
Add('options-tab-general-enablemissingpluginswarning', 'Warn on missing plugins ');
Add('options-tab-general-enablethumbnailembedding', 'Enable thumbnail embedding ');
Add('options-tab-general-rotatemode', 'Rotate mode ');
Add('options-tab-general-rotateimage', 'Rotate image ');
Add('options-tab-general-rotateframe', 'Rotate frame ');
Add('options-tab-general-zoommode', 'Zoom mode ');
Add('options-tab-general-preservequality', 'Preserve quality ');
Add('options-tab-general-preservespeed', 'Preserve speed ');
Add('options-tab-general-guides', 'Guidelines ');
Add('options-tab-general-enableguides', 'Enable guides ');
Add('options-tab-general-guidecentercolor', 'Center ');
Add('options-tab-general-guidethirdscolor', 'Thirds ');
Add('options-tab-general-guidegoldenratiocolor', 'Golden ratio ');
Add('options-tab-general-singleprecision', 'Use single-precision buffers ');
Add('options-tab-general-pluginpath', 'Plugin folder ');
Add('options-tab-editor-title', 'Editor ');
Add('options-tab-editor-editorgraph', 'Graph ');
Add('options-tab-editor-editordefaults', 'Defaults ');
Add('options-tab-editor-referencetriangle', 'Reference triangle ');
Add('options-tab-editor-usetransformcolor', 'Use transform color ');
Add('options-tab-editor-helperlines', 'Show helper lines ');
Add('options-tab-editor-alwaysshowbothtransformtypes', 'Always show both transform types ');
Add('options-tab-editor-backgroundcolor', 'Background ');
Add('options-tab-editor-gridcolors', 'Grid ');
Add('options-tab-editor-referencecolor', 'Reference ');
Add('options-tab-editor-helpercolors', 'Helpers ');
Add('options-tab-editor-extendededit', 'Extended edit mode ');
Add('options-tab-editor-locktransformaxes', 'Lock transform axes ');
Add('options-tab-editor-rebuildxaoslinks', 'Rebuild links ');
Add('options-tab-editor-normalreference', 'Normal ');
Add('options-tab-editor-proportionalreference', 'Proportional ');
Add('options-tab-editor-wanderingreference', 'Wandering (old style) ');
Add('options-tab-editor-enablepreview', 'Enable editor preview');
Add('options-tab-editor-previewtransparency', 'Transparency');
Add('options-tab-display-title', 'Display ');
Add('options-tab-display-rendering', 'Rendering ');
Add('options-tab-display-previewdensity', 'Preview density ');
Add('options-tab-display-mainpreview', 'Main window preview ');
Add('options-tab-display-extendpreviewbuffer', 'Extend preview buffer ');
Add('options-tab-display-extenspreviewbufferlabel', 'Buffer extension ');
Add('options-tab-display-showtransparency', 'Show transparency ');
Add('options-tab-display-usesmallthumbs', 'Use small thumbnails (like Apophysis 2.09) ');
Add('options-tab-random-title', 'Random ');
Add('options-tab-random-numberoftransforms', 'Number of transforms ');
Add('options-tab-random-mutationtransforms', 'Mutation transforms ');
Add('options-tab-random-randombatch', 'Random batch ');
Add('options-tab-random-forcedsymmetry', 'Forced symmetry ');
Add('options-tab-random-batchsize', 'Batch size ');
Add('options-tab-random-titleprefix', 'Title prefix ');
Add('options-tab-random-keepbackground', 'Keep background color ');
Add('options-tab-random-symtype', 'Type ');
Add('options-tab-random-symorder', 'Order ');
Add('options-tab-random-symlimit', 'Limit ');
Add('options-tab-random-type-none', 'None ');
Add('options-tab-random-type-bilateral', 'Bilateral ');
Add('options-tab-random-type-rotational', 'Rotational ');
Add('options-tab-random-type-dihedral', 'Dihedral ');
Add('options-tab-random-onrandom', 'On random flame use... ');
Add('options-tab-random-userandom', 'Random preset ');
Add('options-tab-random-usedefault', 'Default gradient ');
Add('options-tab-random-usecurrent', 'Current gradient ');
Add('options-tab-random-randomcalculated', 'Random gradient ');
Add('options-tab-random-randomfromfile', 'Random from file ');
Add('options-tab-random-filetouse', 'Random file to use ');
Add('options-tab-variations-title', 'Variations ');
Add('options-tab-variations-setall', 'Set all ');
Add('options-tab-variations-clearall', 'Clear all ');
Add('options-tab-gradient-title', 'Gradient ');
Add('options-tab-gradient-numberofnodes', 'Number of nodes ');
Add('options-tab-gradient-smoothpalette', 'Smooth palette ');
Add('options-tab-gradient-huebetween', 'Hue range ');
Add('options-tab-gradient-satbetween', 'Saturation range ');
Add('options-tab-gradient-lumbetween', 'Luminance range ');
Add('options-tab-gradient-numtries', 'Number of tries ');
Add('options-tab-gradient-trylength', 'Try length ');
Add('options-tab-upr-title', 'UltraFractal ');
Add('options-tab-upr-paramdefaults', 'Parameter defaults ');
Add('options-tab-upr-coloralgorithm', 'Coloring algorithm ');
Add('options-tab-upr-uprsize', 'Image size ');
Add('options-tab-upr-formula', 'Formula ');
Add('options-tab-upr-identifier', 'Identifier ');
Add('options-tab-upr-adjustdensity', 'Adjust sample density ');
Add('options-tab-environment-title', 'Environment');
Add('options-tab-environment-defaultparams', 'Default parameters ');
Add('options-tab-environment-smoothpalette', 'Smooth palette ');
Add('options-tab-environment-functionlib', 'Scripting function library ');
Add('options-tab-environment-exportrenderer', 'Export renderer ');
Add('options-tab-environment-helpfile', 'Help file ');
Add('options-tab-environment-rememberlastopen', 'Remember last open parameters ');
Add('options-tab-environment-autosave', 'Enable autosave ');
Add('options-tab-environment-savefrequency', 'Save frequency ');
Add('preview-title', 'Preview');
Add('save-title', 'Save');
Add('save-name', 'Name');
Add('save-oldformat', 'Use old format');
Add('save-newformat', 'Use new format');
Add('save-type-parameters', 'Save Parameters');
Add('save-type-allparameters', 'Save All Parameters');
Add('save-type-gradient', 'Save Gradient');
Add('save-type-exportupr', 'Export UPR');
Add('save-status-notitle', 'No item name given.');
Add('save-status-invalidfilename', 'Invalid file name.');
Add('save-status-alreadyexists', '"%s" in "%s" already exists. Do you want to replace it?');
Add('save-status-alreadyexists2', '"%s" already exists. Do you want to replace it?');
Add('savepreset-title', 'Save preset');
Add('savepreset-name', 'Name');
Add('savepreset-notitle', 'No preset name given.');
Add('script-title', 'Script');
Add('script-rendering', 'Rendering...');
Add('script-break', 'Break');
Add('script-new', 'New');
Add('script-open', 'Open');
Add('script-save', 'Save');
Add('script-run', 'Run');
Add('script-stop', 'Stop');
Add('splash-loadingtext', 'Loading');
Add('template-title', 'Templates');
Add('main-common-title-lite', 'Lite Version');
Add('main-common-title-t500', 'High-Memory Version');
Add('main-common-randombatch', 'Random Batch');
Add('main-menu-file-title', 'File');
Add('main-menu-file-new', 'New');
Add('main-menu-file-open', 'Open...');
Add('main-menu-file-restoreautosave', 'Restore last autosave');
Add('main-menu-file-saveparams', 'Save parameters...');
Add('main-menu-file-saveallparams', 'Save all parameters...');
Add('main-menu-file-smoothpalette', 'Smooth palette...');
Add('main-menu-file-gradientbrowser', 'Gradient browser...');
Add('main-menu-file-exportupr', 'Export UPR...');
Add('main-menu-file-exportflame', 'Export to flam3...');
Add('main-menu-file-importgimp', 'Import GIMP parameters...');
Add('main-menu-file-submitsheep', 'Submit sheep');
Add('main-menu-file-randombatch', 'Random batch');
Add('main-menu-file-exit', 'Exit');
Add('main-menu-edit-title', 'Edit');
Add('main-menu-edit-saveundo', 'Save undo stack...');
Add('main-menu-edit-copyasupr', 'Copy as UPR');
Add('main-menu-view-title', 'View');
Add('main-menu-view-fullscreen', 'Full screen');
Add('main-menu-view-editor', 'Editor');
Add('main-menu-view-adjustment', 'Adjustment');
Add('main-menu-view-gradient', 'Gradient');
Add('main-menu-view-mutation', 'Mutation');
Add('main-menu-view-imagesize', 'Image size');
Add('main-menu-view-messages', 'Messages');
Add('main-menu-view-curves', 'Curves');
Add('main-menu-flame-title', 'Flame');
Add('main-menu-flame-reset', 'Reset location');
Add('main-menu-flame-randomize', 'Randomize');
Add('main-menu-flame-randomweights', 'Randomize weights');
Add('main-menu-flame-equalweights', 'Equalize weights');
Add('main-menu-flame-computeweights', 'Normalize weights');
Add('main-menu-flame-calculatecolors', 'Calculate colors');
Add('main-menu-flame-randomizecolors', 'Randomize colors');
Add('main-menu-flame-rendertodisk', 'Render flame...');
Add('main-menu-flame-renderallflames', 'Render all flames...');
Add('main-menu-flame-resumeunfinished', 'Resume unfinished render process...');
Add('main-menu-flame-generatereport', 'Summarize flame...');
Add('main-menu-variation-title', 'Variation');
Add('main-menu-variation-random', 'Random');
Add('main-menu-variation-builtin', 'Built-in');
Add('main-menu-variation-plugins', 'Plugins');
Add('main-menu-script-title', 'Script');
Add('main-menu-script-run', 'Run script');
Add('main-menu-script-run2', 'Run "%s"');
Add('main-menu-script-directory', 'Directory');
Add('main-menu-script-more', 'More');
Add('main-menu-script-stop', 'Stop script');
Add('main-menu-script-open', 'Open...');
Add('main-menu-script-edit', 'Edit script');
Add('main-menu-script-managefaves', 'Manage favorites...');
Add('main-menu-script-flametoscript', 'Generate script from flame');
Add('main-menu-options-title', 'Tools');
Add('main-menu-options-togglemaintoolbar', 'Show toolbar');
Add('main-menu-options-togglestatusbar', 'Show status bar');
Add('main-menu-options-togglefilelist', 'Show parameter list');
Add('main-menu-options-resetfilelistwidth', 'Reset layout');
Add('main-menu-options-showoptions', 'Settings...');
Add('main-menu-help-title', '?');
Add('main-menu-help-contents', 'Contents');
Add('main-menu-help-aboutalgorithm', 'About fractal flames...');
Add('main-menu-help-aboutapophysis', 'About Apophysis 7x...');
Add('main-toolbar-listviewmode-classic', 'Classic view');
Add('main-toolbar-listviewmode-icons', 'Thumbnail view');
Add('main-toolbar-togglealpha', 'Show transparency');
Add('main-toolbar-toggleguides', 'Show guidelines');
Add('main-toolbar-modemove', 'Pan camera');
Add('main-toolbar-moderotate', 'Rotate camera');
Add('main-toolbar-modezoomin', 'Zoom in');
Add('main-toolbar-modezoomout', 'Zoom out');
Add('main-status-batchgenerate', 'Generating %d of %s...');
Add('main-status-batcherror', 'Error creating batch.');
Add('main-status-calculatingpalette', 'Calculating palette (%d%)...');
Add('main-status-noflam3', 'Unable to find flam3 executable. Please verify your settings.');
Add('main-status-nohelpfile', 'Please specify a help file path in the options dialog first.');
Add('main-status-variationsorvariables', 'variations or variables');
Add('main-status-plugins', 'plugins');
Add('main-status-pluginpath-ioerror', 'Failed to write the setting for the plugin directory. Apophysis will use the default setting.');
Add('main-status-noloadingerrors', 'Flame loaded without errors');
Add('main-status-loadingerrorcount', '%d errors in flame');
Add('main-status-morepluginsneeded', 'The flame "%s" requires the following additional %s:');
Add('main-status-noautosave', 'No autosave present.');
Add('main-report-transformcount', 'Transform count: %d');
Add('main-report-finaltransform', 'Has final transform: %s');
Add('main-report-usedplugins', 'Used plugins:');
Add('main-report-noplugins', '(none)');
end;
procedure Add(key, value: string);
var entry : TKeyValuePair;
begin
Inc(tokenCount);
SetLength(language, tokenCount);
SetLength(defaultlanguage, tokenCount);
entry := TKeyValuePair.Create;
entry.key := key;
entry.value := value;
language[tokenCount - 1] := entry;
defaultlanguage[tokenCount - 1] := entry;
end;
procedure AddNoDefault(key, value: string);
var entry : TKeyValuePair;
begin
Inc(tokenCount);
SetLength(language, tokenCount);
entry := TKeyValuePair.Create;
entry.key := key;
entry.value := value;
language[tokenCount - 1] := entry;
end;
procedure LoadLanguage(path:string);
begin
if (path = '') or (not FileExists(path)) then LoadEnglish()
else begin
tokenCount := 0;
if true then begin
parser := TParser.Create;
ListXmlScanner := TEasyXmlScanner.Create(nil);
ListXmlScanner.OnStartTag := parser.ListXmlScannerStartTag;
ListXmlScanner.OnEndTag := parser.ListXmlScannerEndTag;
ListXmlScanner.OnEmptyTag := parser.ListXmlScannerEmptyTag;
ListXmlScanner.OnContent := parser.ListXmlScannerContent;
ListXmlScanner.Filename := path;
ListXmlScanner.Execute;
ListXmlScanner.Destroy;
parser.Destroy;
end;
end;
end;
function TextByKey(key:string):string;
var i: integer;
begin
Result := '#ERR_NO_TEXT#';
for i:=0 to tokenCount - 1 do begin
if LowerCase(language[i].key) = LowerCase(key) then begin
Result := language[i].value;
exit;
end;
end;
// maybe try default language?
for i:=0 to tokenCount - 1 do begin
if LowerCase(defaultlanguage[i].key) = LowerCase(key) then begin
Result := defaultlanguage[i].value;
exit;
end;
end;
end;
constructor TParser.Create;
begin
self.parentTagnames := TStringList.Create;
end;
procedure TParser.ListXmlScannerStartTag(Sender: TObject; TagName: string; Attributes: TAttrList);
begin
self.parentTagnames.Add(self.currentTagname);
self.currentTagname := TagName;
end;
procedure TParser.ListXmlScannerEndTag(Sender: TObject; TagName: string);
var lastIndex : integer;
begin
lastIndex := self.parentTagnames.Count - 1;
self.currentTagname := self.parentTagnames.Strings[lastIndex];
self.parentTagnames.Delete(lastIndex);
end;
procedure TParser.ListXmlScannerEmptyTag(Sender: TObject; TagName: string; Attributes: TAttrList);
var lastIndex : integer;
begin
self.parentTagnames.Add(self.currentTagname);
self.currentTagname := TagName;
self.ListXmlScannerContent(Sender, '');
lastIndex := self.parentTagnames.Count - 1;
self.currentTagname := self.parentTagnames.Strings[lastIndex];
self.parentTagnames.Delete(lastIndex);
end;
procedure TParser.ListXmlScannerContent(Sender: TObject; Content: string);
const root: string = 'stringtable';
var key, tn: string; i: integer;
begin
for i:=0 to self.parentTagnames.Count - 1 do begin
tn := self.parentTagnames.Strings[i];
if not (tn = '') and not (tn = root) then key := key + tn + '-';
end;
key := key + self.currentTagname;
Add(key, Content);
end;
end.

340
Core/XFormMan.pas Normal file
View File

@ -0,0 +1,340 @@
{
Apophysis Copyright (C) 2001-2004 Mark Townsend
Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov
Apophysis Copyright (C) 2007-2008 Piotr Borys, Peter Sdobnov
Apophysis "3D hack" Copyright (C) 2007-2008 Peter Sdobnov
Apophysis "7X" Copyright (C) 2009-2010 Georg Kiehne
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; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
}
unit XFormMan;
interface
uses
BaseVariation, SysUtils, Forms, Windows;
const
NRLOCVAR = 29;
var
NumBuiltinVars: integer;
type
TFNToVN = record
FileName: string;
VarName: string;
end;
function NrVar: integer;
function Varnames(const index: integer): String;
procedure RegisterVariation(Variation: TVariationLoader; supports3D, supportsDC : boolean);
function GetNrRegisteredVariations: integer;
function GetRegisteredVariation(const Index: integer): TVariationLoader;
function GetNrVariableNames: integer;
function GetVariableNameAt(const Index: integer): string;
function GetVariationIndex(const str: string): integer;
function GetVariationIndexFromVariableNameIndex(const Index: integer): integer;
procedure VarSupports(index : integer; var supports3D : boolean; var supportsDC : boolean);
procedure InitializeXFormMan;
procedure DestroyXFormMan;
procedure RegisterVariationFile(filename, name: string);
function GetFileNameOfVariation(name: string): string;
implementation
uses
Classes;
var
VariationList: TList;
VariableNames: TStringlist;
loaderNum : integer;
Variable2VariationIndex : array of integer;
FNToVNList : array of TFNToVN;
FNToVNCount: integer;
procedure InitializeXFormMan;
begin
VariationList := TList.Create;
VariableNames := TStringlist.create;
SetLength(Variable2VariationIndex,0);
SetLength(FNToVNList, 0);
FNToVNCount := 0;
end;
procedure VarSupports(index : integer; var supports3D : boolean; var supportsDC : boolean);
const
supports3D_arr: array[0..NRLOCVAR-1] of boolean = (
true, //'linear',
true, //'flatten',
true, //'sinusoidal',
true, //'spherical',
true, //'swirl',
true, //'horseshoe',
true, //'polar',
true, //'disc',
true, //'spiral',
true, //'hyperbolic',
true, //'diamond',
true, //'eyefish',
true, //'bubble',
true, //'cylinder',
true, //'noise',
true, //'blur',
true, //'gaussian_blur',
true, //'zblur',
true, //'blur3D',
true, //'pre_blur',
true, //'pre_zscale',
true, //'pre_ztranslate',
true, //'pre_rotate_x',
true, //'pre_rotate_y',
true, //'zscale',
true, //'ztranslate',
true, //'zcone',
true, //'post_rotate_x',
true //'post_rotate_y',
);
supportsDC_arr: array[0..NRLOCVAR-1] of boolean = (
false, //'linear3D',
false, //'linear',
false, //'sinusoidal',
false, //'spherical',
false, //'swirl',
false, //'horseshoe',
false, //'polar',
// false, // 'handkerchief',
// false, // 'heart',
false, //'disc',
false, //'spiral',
false, //'hyperbolic',
false, //'diamond',
// false, // 'ex',
// false, // 'julia',
// false, // 'bent',
// false, // 'waves',
// false, // 'fisheye',
// false, // 'popcorn',
// false, // 'exponential',
// false, // 'power',
// false, // 'cosine',
// false, // 'rings',
// false, // 'fan',
false, //'eyefish',
false, //'bubble',
false, //'cylinder',
false, //'noise',
false, //'blur',
false, //'gaussian_blur',
false, //'zblur',
false, //'blur3D',
false, //'pre_blur',
false, //'pre_zscale',
false, //'pre_ztranslate',
false, //'pre_rotate_x',
false, //'pre_rotate_y',
false, //'zscale',
false, //'ztranslate',
false, //'zcone',
false, //'post_rotate_x',
false //'post_rotate_y'
);
var
varl : TVariationLoader;
begin
if (index >= NRLOCVAR) then begin
supports3D := TVariationLoader(VariationList.Items[index - NRLOCVAR]).supports3D;
supportsDC := TVariationLoader(VariationList.Items[index - NRLOCVAR]).supportsDC;
end else begin
supports3D := supports3D_arr[index];
supportsDC := supportsDC_arr[index];
end;
end;
procedure DestroyXFormMan;
var i: integer;
begin
VariableNames.Free;
// The registered variation loaders are owned here, so we must free them.
for i := 0 to VariationList.Count-1 do
TVariationLoader(VariationList[i]).Free;
VariationList.Free;
Finalize(Variable2VariationIndex);
Finalize(FNToVNList);
end;
///////////////////////////////////////////////////////////////////////////////
function NrVar: integer;
begin
Result := NRLOCVAR + VariationList.Count;
end;
///////////////////////////////////////////////////////////////////////////////
function GetVariationIndexFromVariableNameIndex(const Index: integer): integer;
begin
if (Index<0) or (Index > High(Variable2VariationIndex)) then
Result := -1
else
Result := Variable2VariationIndex[Index];
end;
function Varnames(const index: integer): String;
const
cvarnames: array[0..NRLOCVAR-1] of string = (
'linear',
'flatten',
'sinusoidal',
'spherical',
'swirl',
'horseshoe',
'polar',
// 'handkerchief',
// 'heart',
'disc',
'spiral',
'hyperbolic',
'diamond',
// 'ex',
// 'julia',
// 'bent',
// 'waves',
// 'fisheye',
// 'popcorn',
// 'exponential',
// 'power',
// 'cosine',
// 'rings',
// 'fan',
'eyefish',
'bubble',
'cylinder',
'noise',
'blur',
'gaussian_blur',
'zblur',
'blur3D',
'pre_blur',
'pre_zscale',
'pre_ztranslate',
'pre_rotate_x',
'pre_rotate_y',
'zscale',
'ztranslate',
'zcone',
'post_rotate_x',
'post_rotate_y'
);
begin
if Index < NRLOCVAR then
Result := cvarnames[Index]
else
Result := TVariationLoader(VariationList[Index - NRLOCVAR]).GetName;
end;
///////////////////////////////////////////////////////////////////////////////
function GetVariationIndex(const str: string): integer;
var
i: integer;
begin
i := NRVAR-1;
while (i >= 0) and (Varnames(i) <> str) do Dec(i);
Result := i;
end;
///////////////////////////////////////////////////////////////////////////////
procedure RegisterVariationFile(filename, name: string);
begin
FNToVNCount := FNToVNCount + 1;
SetLength(FNToVNList, FNToVNCount);
FNToVNList[FNToVNCount - 1].FileName := filename;
FNToVNList[FNToVNCount - 1].VarName := name;
end;
function GetFileNameOfVariation(name: string): string;
var i: integer;
begin
for i := 0 to FNToVNCount - 1 do begin
if FNToVNList[i].VarName = name then begin
Result := FNToVNList[i].FileName;
Exit;
end;
end;
Result := '';
end;
procedure RegisterVariation(Variation: TVariationLoader; supports3D, supportsDC : boolean);
var
i: integer;
prevNumVariables:integer;
begin
OutputDebugString(PChar(Variation.GetName));
VariationList.Add(Variation);
Variation.Supports3D := supports3D;
Variation.SupportsDC := supportsDC;
prevNumVariables := GetNrVariableNames;
setLength(Variable2VariationIndex, prevNumVariables + Variation.GetNrVariables);
for i := 0 to Variation.GetNrVariables - 1 do begin
VariableNames.Add(Variation.GetVariableNameAt(i));
Variable2VariationIndex[prevNumVariables + i] := NrVar-1;
end;
end;
///////////////////////////////////////////////////////////////////////////////
function GetNrRegisteredVariations: integer;
begin
Result := VariationList.count;
end;
///////////////////////////////////////////////////////////////////////////////
function GetRegisteredVariation(const Index: integer): TVariationLoader;
begin
Result := TVariationLoader(VariationList[Index]);
end;
///////////////////////////////////////////////////////////////////////////////
function GetNrVariableNames: integer;
begin
Result := VariableNames.Count;
end;
///////////////////////////////////////////////////////////////////////////////
function GetVariableNameAt(const Index: integer): string;
begin
Result := VariableNames[Index];
end;
///////////////////////////////////////////////////////////////////////////////
initialization
InitializeXFormMan;
finalization
DestroyXFormMan;
end.