6b8c455c52
Number of variant dependant code change so all changes can be done only in xform Test mode for new variant added
1901 lines
54 KiB
ObjectPascal
1901 lines
54 KiB
ObjectPascal
{
|
|
Apophysis Copyright (C) 2001-2004 Mark Townsend
|
|
|
|
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.
|
|
}
|
|
//{$D-,L-,O+,Q-,R-,Y-,S-}
|
|
unit Editor;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
|
ExtCtrls, StdCtrls, ComCtrls, Math, Menus, ToolWin, Registry, MyTypes,
|
|
ControlPoint, Render, cmap, Grids, ValEdit;
|
|
|
|
const
|
|
// PixelCountMax = 32768;
|
|
WM_PTHREAD_COMPLETE = WM_APP + 5438;
|
|
|
|
type
|
|
TEditForm = class(TForm)
|
|
GrphPnl: TPanel;
|
|
GraphImage: TImage;
|
|
StatusBar: TStatusBar;
|
|
ControlPanel: TPanel;
|
|
lblTransform: TLabel;
|
|
PrevPnl: TPanel;
|
|
PreviewImage: TImage;
|
|
EditPopup: TPopupMenu;
|
|
mnuLockSel: TMenuItem;
|
|
MenuItem1: TMenuItem;
|
|
mnuDelete: TMenuItem;
|
|
mnuDuplicate: TMenuItem;
|
|
MenuItem2: TMenuItem;
|
|
mnuAdd: TMenuItem;
|
|
mnuAutoZoom: TMenuItem;
|
|
N1: TMenuItem;
|
|
mnuUndo: TMenuItem;
|
|
mnuRedo: TMenuItem;
|
|
QualityPopup: TPopupMenu;
|
|
mnuLowQuality: TMenuItem;
|
|
mnuMediumQuality: TMenuItem;
|
|
mnuHighQuality: TMenuItem;
|
|
N3: TMenuItem;
|
|
mnuResetLocation: TMenuItem;
|
|
mnuVerticalFlipAll: TMenuItem;
|
|
N4: TMenuItem;
|
|
mnuHorizintalFlipAll: TMenuItem;
|
|
N5: TMenuItem;
|
|
mnuFlipVertical: TMenuItem;
|
|
mnuFlipHorizontal: TMenuItem;
|
|
cbTransforms: TComboBox;
|
|
N6: TMenuItem;
|
|
PageControl: TPageControl;
|
|
TabSheet1: TTabSheet;
|
|
Label7: TLabel;
|
|
Label8: TLabel;
|
|
Label9: TLabel;
|
|
Label10: TLabel;
|
|
Label11: TLabel;
|
|
Label12: TLabel;
|
|
txtAx: TEdit;
|
|
txtAy: TEdit;
|
|
txtBx: TEdit;
|
|
txtBy: TEdit;
|
|
txtCx: TEdit;
|
|
txtCy: TEdit;
|
|
chkPreserve: TCheckBox;
|
|
XForm: TTabSheet;
|
|
lbla: TLabel;
|
|
Label1: TLabel;
|
|
Label2: TLabel;
|
|
Label3: TLabel;
|
|
Label4: TLabel;
|
|
Label5: TLabel;
|
|
Label6: TLabel;
|
|
Label29: TLabel;
|
|
txtA: TEdit;
|
|
txtB: TEdit;
|
|
txtC: TEdit;
|
|
txtD: TEdit;
|
|
txtE: TEdit;
|
|
txtF: TEdit;
|
|
txtP: TEdit;
|
|
txtSymmetry: TEdit;
|
|
TabSheet3: TTabSheet;
|
|
VEVars: TValueListEditor;
|
|
TabSheet2: TTabSheet;
|
|
GroupBox1: TGroupBox;
|
|
scrlXFormColor: TScrollBar;
|
|
pnlXFormColor: TPanel;
|
|
txtXFormColor: TEdit;
|
|
GroupBox2: TGroupBox;
|
|
Label20: TLabel;
|
|
Label21: TLabel;
|
|
pnlBackColor: TPanel;
|
|
chkUseXFormColor: TCheckBox;
|
|
chkFlameBack: TCheckBox;
|
|
pnlReference: TPanel;
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure GraphImageMouseMove(Sender: TObject; Shift: TShiftState; X,
|
|
Y: integer);
|
|
procedure GraphImageMouseDown(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: integer);
|
|
procedure GraphImageMouseUp(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: integer);
|
|
procedure FormShow(Sender: TObject);
|
|
procedure mnuDeleteClick(Sender: TObject);
|
|
procedure mnuAddClick(Sender: TObject);
|
|
procedure mnuDupClick(Sender: TObject);
|
|
procedure mnuAutoZoomClick(Sender: TObject);
|
|
procedure mnuLockClick(Sender: TObject);
|
|
procedure mnuXFlipClick(Sender: TObject);
|
|
procedure mnuYFlipClick(Sender: TObject);
|
|
procedure btnCloseClick(Sender: TObject);
|
|
procedure FormResize(Sender: TObject);
|
|
procedure txtPKeyPress(Sender: TObject; var Key: Char);
|
|
procedure CornerEditKeyPress(Sender: TObject; var Key: Char);
|
|
procedure CornerEditExit(Sender: TObject);
|
|
procedure txtPExit(Sender: TObject);
|
|
procedure DrawPreview;
|
|
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
|
procedure mnuUndoClick(Sender: TObject);
|
|
procedure mnuRedoClick(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure mnuLowQualityClick(Sender: TObject);
|
|
procedure mnuHighQualityClick(Sender: TObject);
|
|
procedure mnuMediumQualityClick(Sender: TObject);
|
|
procedure mnuResetLocationClick(Sender: TObject);
|
|
procedure mnuVerticalFlipAllClick(Sender: TObject);
|
|
procedure mnuHorizintalFlipAllClick(Sender: TObject);
|
|
procedure mnuFlipVerticalClick(Sender: TObject);
|
|
procedure mnuFlipHorizontalClick(Sender: TObject);
|
|
procedure GraphImageDblClick(Sender: TObject);
|
|
procedure cbTransformsChange(Sender: TObject);
|
|
procedure CoefKeyPress(Sender: TObject; var Key: Char);
|
|
procedure CoefExit(Sender: TObject);
|
|
procedure scrlXFormColorScroll(Sender: TObject;
|
|
ScrollCode: TScrollCode; var ScrollPos: Integer);
|
|
procedure scrlXFormColorChange(Sender: TObject);
|
|
procedure chkUseXFormColorClick(Sender: TObject);
|
|
procedure chkFlameBackClick(Sender: TObject);
|
|
procedure pnlBackColorClick(Sender: TObject);
|
|
procedure pnlReferenceClick(Sender: TObject);
|
|
procedure txtXFormColorExit(Sender: TObject);
|
|
procedure txtXFormColorKeyPress(Sender: TObject; var Key: Char);
|
|
procedure txtSymmetryExit(Sender: TObject);
|
|
procedure txtSymmetryKeyPress(Sender: TObject; var Key: Char);
|
|
procedure VEVarsKeyPress(Sender: TObject; var Key: Char);
|
|
procedure VEVarsExit(Sender: TObject);
|
|
procedure VEVarsValidate(Sender: TObject; ACol, ARow: Integer;
|
|
const KeyName, KeyValue: String);
|
|
private
|
|
bm: TBitmap;
|
|
cmap: TColorMap;
|
|
// cp1: TControlPoint;
|
|
PreviewDensity: double;
|
|
procedure UpdateFlame(DrawMain: boolean);
|
|
procedure DeleteTriangle(t: integer);
|
|
procedure UpdateFlameX;
|
|
public
|
|
cp: TControlPoint;
|
|
Render: TRenderer;
|
|
{ Options}
|
|
UseFlameBackground, UseTransformColors: boolean;
|
|
BackGroundColor, ReferenceTrianglecolor: integer;
|
|
procedure UpdateDisplay;
|
|
procedure AutoZoom;
|
|
procedure DrawGraph;
|
|
end;
|
|
|
|
var
|
|
EditForm: TEditForm;
|
|
GraphZoom: double;
|
|
CornerCaught: boolean;
|
|
TriangleCaught: boolean;
|
|
SelectedTriangle: integer;
|
|
SelectedCorner: integer;
|
|
SelLocked: boolean;
|
|
Drawing: boolean;
|
|
HasChanged: boolean;
|
|
oldx, oldy: double;
|
|
intoldx, intoldy: integer;
|
|
clr: array[-1..11] of TColor;
|
|
EditedVariation: integer;
|
|
pcenterx, pcentery, pscale: double;
|
|
|
|
procedure ShowSelectedInfo;
|
|
function ColorValToColor(c: TColorMap; index: double): TColor;
|
|
function FlipTriangleVertical(t: TTriangle): TTriangle;
|
|
function FlipTriangleHorizontal(t: TTriangle): TTriangle;
|
|
function RotateTriangle(t: TTriangle; rad: double): TTriangle;
|
|
function OffsetTriangle(t: TTriangle; range: double): TTriangle;
|
|
function ScaleTriangle(t: TTriangle; scale: double): TTriangle;
|
|
function RotateTriangleCenter(t: TTriangle; rad: double): TTriangle;
|
|
function RotateTrianglePoint(t: TTriangle; x, y, rad: double): TTriangle;
|
|
function Centroid(t: TTriangle): TSPoint;
|
|
function OffsetTriangleRandom(t: TTriangle): TTriangle;
|
|
function ScaleTriangleCenter(t: TTriangle; scale: double): TTriangle;
|
|
procedure ScaleAll;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Main, Global, Adjust, Mutate, Xform;
|
|
|
|
const
|
|
SUB_BATCH_SIZE = 1000;
|
|
SC_MyMenuItem1 = WM_USER + 1;
|
|
|
|
var
|
|
oldTriangle: TTriangle;
|
|
gCenterX: double;
|
|
gCentery: double;
|
|
gxlength: double;
|
|
gylength: double;
|
|
|
|
{$R *.DFM}
|
|
|
|
{ Triangle transformations }
|
|
|
|
function OffsetTriangleRandom(t: TTriangle): TTriangle;
|
|
var
|
|
r: integer;
|
|
begin
|
|
r := random(3);
|
|
Result.x[r] := t.x[r] + random - 0.5;
|
|
Result.y[r] := t.y[r] + random - 0.5;
|
|
end;
|
|
|
|
function FlipTriangleVertical(t: TTriangle): TTriangle;
|
|
begin
|
|
Result := t;
|
|
Result.y[0] := -t.y[0];
|
|
Result.y[1] := -t.y[1];
|
|
Result.y[2] := -t.y[2];
|
|
end;
|
|
|
|
function FlipTriangleHorizontal(t: TTriangle): TTriangle;
|
|
begin
|
|
Result := t;
|
|
Result.x[0] := -t.x[0];
|
|
Result.x[1] := -t.x[1];
|
|
Result.x[2] := -t.x[2];
|
|
end;
|
|
|
|
function ScaleTriangle(t: TTriangle; scale: double): TTriangle;
|
|
begin
|
|
Result.y[0] := scale * t.y[0];
|
|
Result.y[1] := scale * t.y[1];
|
|
Result.y[2] := scale * t.y[2];
|
|
Result.x[0] := scale * t.x[0];
|
|
Result.x[1] := scale * t.x[1];
|
|
Result.x[2] := scale * t.x[2];
|
|
end;
|
|
|
|
function Centroid(t: TTriangle): TSPoint;
|
|
begin
|
|
Result.x := (t.x[0] + t.x[1] + t.x[2]) / 3;
|
|
Result.y := (t.y[0] + t.y[1] + t.y[2]) / 3;
|
|
end;
|
|
|
|
function ScaleTriangleCenter(t: TTriangle; scale: double): TTriangle;
|
|
var
|
|
xr, yr: double;
|
|
z: TSPoint;
|
|
begin
|
|
z := Centroid(t);
|
|
xr := z.x;
|
|
yr := z.y;
|
|
Result.y[0] := scale * (t.y[0] - yr) + yr;
|
|
Result.y[1] := scale * (t.y[1] - yr) + yr;
|
|
Result.y[2] := scale * (t.y[2] - yr) + yr;
|
|
Result.x[0] := scale * (t.x[0] - xr) + xr;
|
|
Result.x[1] := scale * (t.x[1] - xr) + xr;
|
|
Result.x[2] := scale * (t.x[2] - xr) + xr;
|
|
end;
|
|
|
|
function RotateTriangle(t: TTriangle; rad: double): TTriangle; //rad in Radians
|
|
var
|
|
i: integer;
|
|
begin
|
|
for i := 0 to 2 do
|
|
begin
|
|
Result.x[i] := t.x[i] * cos(rad) - t.y[i] * sin(rad);
|
|
Result.y[i] := t.x[i] * sin(rad) + t.y[i] * cos(rad);
|
|
end;
|
|
end;
|
|
|
|
function OffsetTriangle(t: TTriangle; range: double): TTriangle;
|
|
var
|
|
i: integer;
|
|
r: double;
|
|
begin
|
|
r := (random * 2 * range) - range;
|
|
for i := 0 to 2 do
|
|
begin
|
|
Result.x[i] := t.x[i] + r;
|
|
Result.y[i] := t.y[i] + r;
|
|
end;
|
|
end;
|
|
|
|
procedure ScaleAll;
|
|
var
|
|
i, j: integer;
|
|
begin
|
|
for i := 0 to 2 do
|
|
begin
|
|
MainTriangles[-1].y[i] := MainTriangles[-1].y[i] * 0.2;
|
|
MainTriangles[-1].x[i] := MainTriangles[-1].x[i] * 0.2;
|
|
end;
|
|
for j := 0 to Transforms - 1 do
|
|
for i := 0 to 2 do
|
|
begin
|
|
MainTriangles[j].y[i] := MainTriangles[j].y[i] * 0.2;
|
|
MainTriangles[j].x[i] := MainTriangles[j].x[i] * 0.2;
|
|
end;
|
|
end;
|
|
|
|
function RotateTriangleCenter(t: TTriangle; rad: double): TTriangle;
|
|
var
|
|
i: integer;
|
|
xr, yr: double;
|
|
z: TSPoint;
|
|
begin
|
|
z := Centroid(t);
|
|
xr := z.x;
|
|
yr := z.y;
|
|
for i := 0 to 2 do
|
|
begin
|
|
Result.x[i] := xr + (t.x[i] - xr) * cos(rad) -
|
|
(t.y[i] - yr) * sin(rad);
|
|
Result.y[i] := yr + (t.x[i] - xr) * sin(rad) +
|
|
(t.y[i] - yr) * cos(rad);
|
|
end;
|
|
end;
|
|
|
|
function RotateTrianglePoint(t: TTriangle; x, y, rad: double): TTriangle;
|
|
var
|
|
i: integer;
|
|
xr, yr: double;
|
|
begin
|
|
xr := x;
|
|
yr := y;
|
|
for i := 0 to 2 do
|
|
begin
|
|
Result.x[i] := xr + (t.x[i] - xr) * cos(rad) -
|
|
(t.y[i] - yr) * sin(rad);
|
|
Result.y[i] := yr + (t.x[i] - xr) * sin(rad) +
|
|
(t.y[i] - yr) * cos(rad);
|
|
end;
|
|
end;
|
|
|
|
|
|
function ColorValToColor(c: TColorMap; index: double): TColor;
|
|
var
|
|
i: integer;
|
|
begin
|
|
i := Trunc(Index * 255);
|
|
result := c[i][2] shl 16 + c[i][1] shl 8 + c[i][0];
|
|
end;
|
|
|
|
procedure TEditForm.UpdateDisplay;
|
|
var
|
|
i: integer;
|
|
begin
|
|
cp.copy(MainCp);
|
|
AdjustScale(cp, PreviewImage.Width, PreviewImage.Height);
|
|
cp.cmap := MainCp.cmap;
|
|
cmap := MainCp.cmap;
|
|
cbTransforms.Clear;
|
|
for i := 0 to Transforms - 1 do
|
|
cbTransforms.Items.Add(IntToStr(i + 1));
|
|
AutoZoom;
|
|
ShowSelectedInfo;
|
|
DrawGraph;
|
|
DrawPreview;
|
|
end;
|
|
|
|
procedure TEditForm.DrawPreview;
|
|
begin
|
|
//Render.Stop;
|
|
cp.sample_density := PreviewDensity;
|
|
cp.spatial_oversample := defOversample;
|
|
cp.spatial_filter_radius := defFilterRadius;
|
|
if mnuResetLocation.checked then
|
|
begin
|
|
cp.zoom := 0;
|
|
cp.CalcBoundbox;
|
|
end
|
|
else
|
|
begin
|
|
cp.zoom := MainCp.zoom;
|
|
cp.center[0] := MainCp.Center[0];
|
|
cp.center[1] := MainCp.Center[1];
|
|
end;
|
|
cp.cmap := MainCp.cmap;
|
|
Render.Compatibility := compatibility;
|
|
Render.SetCP(cp);
|
|
Render.Render;
|
|
PreviewImage.Picture.Bitmap.Assign(Render.GetImage);
|
|
PreviewImage.refresh;
|
|
end;
|
|
|
|
procedure ReadjustWeights(var cp: TControlPoint);
|
|
{ Thanks to Rudy...code from Chaos}
|
|
var
|
|
total, othertotals, excess: double;
|
|
t, i: integer;
|
|
begin
|
|
t := NumXForms(cp);
|
|
{ /* First determine the excess. */ }
|
|
total := 0.0;
|
|
othertotals := 0.0;
|
|
for i := 0 to T - 1 do
|
|
if cp.xform[i].density <> 0.0 then
|
|
begin
|
|
total := total + cp.xform[i].density;
|
|
if (i <> SelectedTriangle) then
|
|
othertotals := othertotals + cp.xform[i].density;
|
|
end;
|
|
excess := total - 1.0;
|
|
{ /* Now we need to fix'em */ }
|
|
for i := 0 to T - 1 do
|
|
if (i <> SelectedTriangle) and (cp.xform[i].density <> 0) then
|
|
cp.xform[i].density := cp.xform[i].density -
|
|
cp.xform[i].density / othertotals * excess;
|
|
end;
|
|
|
|
procedure ShowSelectedInfo;
|
|
var
|
|
t: integer;
|
|
i: integer;
|
|
a, b, c, d, e, f: double;
|
|
begin
|
|
t := SelectedTriangle;
|
|
if (t >= Transforms) then t := Transforms - 1;
|
|
//if EditForm.cbTransforms.ItemIndex <> t then EditForm.cbTransforms.ItemIndex := t;
|
|
EditForm.cbTransforms.ItemIndex := t;
|
|
//select combobox item
|
|
EditForm.txtAx.text := Format('%.6g', [MainTriangles[t].x[0]]);
|
|
EditForm.txtAy.text := Format('%.6g', [MainTriangles[t].y[0]]);
|
|
EditForm.txtBx.text := Format('%.6g', [MainTriangles[t].x[1]]);
|
|
EditForm.txtBy.text := Format('%.6g', [MainTriangles[t].y[1]]);
|
|
EditForm.txtCx.text := Format('%.6g', [MainTriangles[t].x[2]]);
|
|
EditForm.txtCy.text := Format('%.6g', [MainTriangles[t].y[2]]);
|
|
EditForm.lblTransform.Refresh;
|
|
EditForm.txtAx.Refresh;
|
|
EditForm.txtAy.Refresh;
|
|
EditForm.txtBx.Refresh;
|
|
EditForm.txtBy.Refresh;
|
|
EditForm.txtCx.Refresh;
|
|
EditForm.txtCy.Refresh;
|
|
a := EditForm.cp.xform[t].c[0][0];
|
|
b := EditForm.cp.xform[t].c[1][0];
|
|
c := EditForm.cp.xform[t].c[0][1];
|
|
d := EditForm.cp.xform[t].c[1][1];
|
|
e := EditForm.cp.xform[t].c[2][0];
|
|
f := EditForm.cp.xform[t].c[2][1];
|
|
|
|
EditForm.txtA.text := Format('%.6g', [a]);
|
|
EditForm.txtB.text := Format('%.6g', [b]);
|
|
EditForm.txtC.text := Format('%.6g', [c]);
|
|
EditForm.txtD.text := Format('%.6g', [d]);
|
|
EditForm.txtE.text := Format('%.6g', [e]);
|
|
EditForm.txtF.text := Format('%.6g', [f]);
|
|
|
|
EditForm.txtP.text := Format('%.6g', [EditForm.cp.xform[t].density]);
|
|
EditForm.txtSymmetry.text := Format('%.6g', [EditForm.cp.xform[t].symmetry]);
|
|
EditForm.txtA.Refresh;
|
|
EditForm.txtB.Refresh;
|
|
EditForm.txtC.Refresh;
|
|
EditForm.txtD.Refresh;
|
|
EditForm.txtE.Refresh;
|
|
EditForm.txtF.Refresh;
|
|
EditForm.txtP.Refresh;
|
|
EditForm.pnlXFormColor.Color := ColorValToColor(EditForm.cp.cmap, EditForm.cp.xform[t].color);
|
|
EditForm.txtXFormColor.Text := FloatToStr(EditForm.cp.xform[t].color);
|
|
EditForm.scrlXFormcolor.Position := Trunc(EditForm.cp.xform[t].color * 100);
|
|
|
|
for i := 0 to NVars-1 do begin
|
|
EditForm.VEVars.Values[VarNames[i]] := Format('%.6g', [EditForm.cp.xform[SelectedTriangle].vars[i]]);
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure Scale(var fx, fy: double; x, y, Width, Height: integer);
|
|
var
|
|
sc: double;
|
|
begin
|
|
sc := 50 * GraphZoom;
|
|
fx := (x - (Width / 2)) / sc + gCenterX;
|
|
fy := -((y - (Height / 2)) / sc - gCentery);
|
|
end;
|
|
|
|
procedure TEditForm.AutoZoom;
|
|
var
|
|
i, j: integer;
|
|
xminz, yminz, xmaxz, ymaxz: double;
|
|
begin
|
|
xminz := 0;
|
|
yminz := 0;
|
|
xmaxz := 0;
|
|
ymaxz := 0;
|
|
for i := -1 to Transforms - 1 do
|
|
begin
|
|
for j := 0 to 2 do
|
|
begin
|
|
if MainTriangles[i].x[j] < xminz then xminz := MainTriangles[i].x[j];
|
|
if MainTriangles[i].y[j] < yminz then yminz := MainTriangles[i].y[j];
|
|
if MainTriangles[i].x[j] > xmaxz then xmaxz := MainTriangles[i].x[j];
|
|
if MainTriangles[i].y[j] > ymaxz then ymaxz := MainTriangles[i].y[j];
|
|
end;
|
|
end;
|
|
gxlength := xmaxz - xminz;
|
|
gylength := ymaxz - yminz;
|
|
gCenterX := xminz + gxlength / 2;
|
|
gCentery := yminz + gylength / 2;
|
|
if gxlength >= gylength then
|
|
begin
|
|
GraphZoom := EditForm.GraphImage.Width / 60 / gxlength;
|
|
end
|
|
else
|
|
begin
|
|
GraphZoom := EditForm.GraphImage.Height / 60 / gylength;
|
|
end;
|
|
EditForm.StatusBar.Panels[2].Text := Format('Zoom: %f', [GraphZoom]);
|
|
end;
|
|
|
|
procedure TEditForm.UpdateFlameX;
|
|
var
|
|
i: integer;
|
|
begin
|
|
for i := 0 to transforms - 1 do
|
|
begin
|
|
// CP_compute(cp1, Triangles[i], Triangles[-1], i);
|
|
solve3(MainTriangles[-1].x[0], MainTriangles[-1].y[0], MainTriangles[i].x[0],
|
|
MainTriangles[-1].x[1], MainTriangles[-1].y[1], MainTriangles[i].x[1],
|
|
MainTriangles[-1].x[2], MainTriangles[-1].y[2], MainTriangles[i].x[2],
|
|
cp.xform[i].c[0][0], cp.xform[i].c[1][0], cp.xform[i].c[2][0]);
|
|
|
|
solve3(MainTriangles[-1].x[0], MainTriangles[-1].y[0], MainTriangles[i].y[0],
|
|
MainTriangles[-1].x[1], MainTriangles[-1].y[1], MainTriangles[i].y[1],
|
|
MainTriangles[-1].x[2], MainTriangles[-1].y[2], MainTriangles[i].y[2],
|
|
cp.xform[i].c[0][1], cp.xform[i].c[1][1], cp.xform[i].c[2][1]);
|
|
end;
|
|
|
|
GetXForms(cp, MainTriangles, transforms);
|
|
if not chkPreserve.checked then ComputeWeights(cp, MainTriangles, transforms);
|
|
DrawPreview;
|
|
ShowSelectedInfo;
|
|
DrawGraph;
|
|
end;
|
|
|
|
procedure TEditForm.UpdateFlame(DrawMain: boolean);
|
|
begin
|
|
//; MainForm.StopThread;
|
|
StatusBar.Panels[2].Text := Format('Zoom: %f', [GraphZoom]);
|
|
GetXForms(cp, MainTriangles, transforms);
|
|
if not chkPreserve.Checked then ComputeWeights(cp, MainTriangles, transforms);
|
|
DrawPreview;
|
|
ShowSelectedInfo;
|
|
DrawGraph;
|
|
if DrawMain then begin
|
|
MainForm.StopThread;
|
|
MainCp.Copy(cp);
|
|
MainCp.cmap := cmap;
|
|
if mnuResetLocation.checked then begin
|
|
MainCp.zoom := 0;
|
|
MainForm.center[0] := cp.center[0];
|
|
MainForm.center[1] := cp.center[1];
|
|
end;
|
|
// if AdjustForm.Visible then AdjustForm.UpdateDisplay;
|
|
if MutateForm.Visible then MutateForm.UpdateDisplay;
|
|
MainForm.RedrawTimer.enabled := true;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.DeleteTriangle(t: integer);
|
|
var
|
|
i, j: integer;
|
|
begin
|
|
if Transforms > 2 then
|
|
{ Can't have less than 2 transofms}
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
if t = (Transforms - 1) then
|
|
{ Last triangle...just reduce number}
|
|
begin
|
|
Transforms := Transforms - 1;
|
|
SelectedTriangle := Transforms - 1;
|
|
cp.xform[transforms].density := 0;
|
|
cbTransforms.Clear;
|
|
UpdateFlame(True);
|
|
end
|
|
else
|
|
begin
|
|
for i := t to Transforms - 2 do
|
|
begin
|
|
{ copy higher transforms down }
|
|
MainTriangles[i] := MainTriangles[i + 1];
|
|
cp.xform[i].density := cp.xform[i + 1].density;
|
|
cp.xform[i].color := cp.xform[i + 1].color;
|
|
cp.xform[i].symmetry := cp.xform[i + 1].symmetry;
|
|
for j := 0 to NVARS - 1 do
|
|
cp.xform[i].vars[j] := cp.xform[i + 1].vars[j];
|
|
end;
|
|
Transforms := Transforms - 1;
|
|
cp.xform[transforms].density := 0;
|
|
UpdateFlame(True);
|
|
end;
|
|
cbTransforms.clear;
|
|
for i := 0 to Transforms - 1 do
|
|
cbTransforms.Items.Add(IntToStr(i + 1));
|
|
cbTransforms.ItemIndex := SelectedTriangle;
|
|
end;
|
|
end;
|
|
|
|
function InsideTriangle(x, y: double): integer;
|
|
var
|
|
i, j, k: integer;
|
|
inside: boolean;
|
|
begin
|
|
{ is x, y inside a triangle }
|
|
Result := -1;
|
|
inside := False;
|
|
j := 2;
|
|
for k := 0 to Transforms - 1 do
|
|
begin
|
|
for i := 0 to 2 do
|
|
begin
|
|
if (((MainTriangles[k].y[i] <= y) and
|
|
(y < MainTriangles[k].y[j])) or
|
|
((MainTriangles[k].y[j] <= y) and
|
|
(y < MainTriangles[k].y[i]))) and
|
|
(x < (MainTriangles[k].x[j] - MainTriangles[k].x[i]) *
|
|
(y - MainTriangles[k].y[i]) /
|
|
(MainTriangles[k].y[j] - MainTriangles[k].y[i]) +
|
|
MainTriangles[k].x[i]) then
|
|
Inside := not Inside;
|
|
j := i
|
|
end;
|
|
if inside then break;
|
|
end;
|
|
if inside then Result := k;
|
|
end;
|
|
|
|
function InTriangle(fx, fy: double): integer;
|
|
var
|
|
i, j: integer;
|
|
d: double;
|
|
begin
|
|
Result := -2;
|
|
i := InsideTriangle(fx, fy);
|
|
if i > -1 then
|
|
Result := i
|
|
else
|
|
for i := 0 to Transforms - 1 do
|
|
for j := 0 to 2 do
|
|
begin
|
|
d := dist(fx, fy, MainTriangles[i].x[j], MainTriangles[i].y[j]);
|
|
if (d * GraphZoom * 50) < 4 then
|
|
Result := i
|
|
end;
|
|
end;
|
|
|
|
function InsideSelected(x, y: double): boolean;
|
|
var
|
|
i, j, k: integer;
|
|
inside: boolean;
|
|
begin
|
|
inside := False;
|
|
j := 2;
|
|
k := SelectedTriangle;
|
|
for i := 0 to 2 do
|
|
begin
|
|
if (((MainTriangles[k].y[i] <= y) and
|
|
(y < MainTriangles[k].y[j])) or
|
|
((MainTriangles[k].y[j] <= y) and
|
|
(y < MainTriangles[k].y[i]))) and
|
|
(x < (MainTriangles[k].x[j] - MainTriangles[k].x[i]) *
|
|
(y - MainTriangles[k].y[i]) /
|
|
(MainTriangles[k].y[j] - MainTriangles[k].y[i]) +
|
|
MainTriangles[k].x[i]) then inside := not inside;
|
|
j := i
|
|
end;
|
|
InsideSelected := inside;
|
|
end;
|
|
|
|
procedure TEditForm.DrawGraph;
|
|
var
|
|
i: integer;
|
|
ix, iy, sc: double;
|
|
ax, ay, bx, by, cx, cy: integer;
|
|
Width, Height: integer;
|
|
BitMap: TBitMap;
|
|
begin
|
|
if SelectedTriangle >= Transforms then
|
|
begin
|
|
Dec(SelectedTriangle);
|
|
SelLocked := False;
|
|
EditForm.mnuLockSel.Checked := False;
|
|
end;
|
|
BitMap := TBitMap.Create;
|
|
try
|
|
Width := EditForm.GraphImage.Width;
|
|
Height := EditForm.GraphImage.Height;
|
|
BitMap.Width := Width;
|
|
BitMap.Height := Height;
|
|
ix := Width / 2;
|
|
iy := Height / 2;
|
|
sc := 50 * GraphZoom;
|
|
with Bitmap.canvas do
|
|
begin
|
|
if chkFlameBack.checked then
|
|
brush.Color := cp.background[2] shl 16 + cp.background[1] shl 8 + cp.background[0]
|
|
else
|
|
brush.Color := pnlBackColor.Color;
|
|
FillRect(rect(0, 0, Width, Height));
|
|
{Reference Triangle}
|
|
Pen.Width := 1;
|
|
Pen.Style := psDot;
|
|
Pen.color := pnlReference.Color;
|
|
MoveTo(integer(round(ix + MainTriangles[-1].x[0] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[0]) * sc)));
|
|
LineTo(integer(round(ix + MainTriangles[-1].x[1] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[1]) * sc)));
|
|
LineTo(integer(round(ix + MainTriangles[-1].x[2] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[2]) * sc)));
|
|
LineTo(integer(round(ix + MainTriangles[-1].x[0] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[0]) * sc)));
|
|
font.Color := pnlReference.Color;
|
|
TextOut(integer(round(ix + MainTriangles[-1].x[0] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[0]) * sc)), 'A');
|
|
TextOut(integer(round(ix + MainTriangles[-1].x[1] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[1]) * sc)), 'B');
|
|
TextOut(integer(round(ix + MainTriangles[-1].x[2] * sc - gCenterX * sc)), integer(round(iy + (gCentery + -MainTriangles[-1].y[2]) * sc)), 'C');
|
|
{Transforms}
|
|
for i := 0 to Transforms - 1 do
|
|
begin
|
|
ax := integer(round(ix + MainTriangles[i].x[0] * sc - gCenterX * sc));
|
|
ay := integer(round(iy + (gCentery + -MainTriangles[i].y[0]) * sc));
|
|
bx := integer(round(ix + MainTriangles[i].x[1] * sc - gCenterX * sc));
|
|
by := integer(round(iy + (gCentery + -MainTriangles[i].y[1]) * sc));
|
|
cx := integer(round(ix + MainTriangles[i].x[2] * sc - gCenterX * sc));
|
|
cy := integer(round(iy + (gCentery + -MainTriangles[i].y[2]) * sc));
|
|
if chkUseXFormColor.checked then
|
|
pen.color := ColorValToColor(MainCp.cmap, cp.xform[i].color)
|
|
else Pen.color := clr[i mod 12];
|
|
if i = SelectedTriangle then
|
|
Pen.Style := psSolid
|
|
else
|
|
Pen.Style := psDot;
|
|
MoveTo(ax, ay);
|
|
LineTo(bx, by);
|
|
LineTo(cx, cy);
|
|
LineTo(ax, ay);
|
|
Pen.Style := psSolid;
|
|
Ellipse(ax - 4, ay - 4, ax + 4, ay + 4);
|
|
Ellipse(bx - 4, by - 4, bx + 4, by + 4);
|
|
Ellipse(cx - 4, cy - 4, cx + 4, cy + 4);
|
|
Font.color := Pen.color;
|
|
TextOut(ax, ay, 'A');
|
|
TextOut(bx, by, 'B');
|
|
TextOut(cx, cy, 'C');
|
|
end;
|
|
end;
|
|
EditForm.GraphImage.Picture.Graphic := Bitmap;
|
|
EditForm.GraphImage.Refresh;
|
|
finally
|
|
BitMap.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.FormCreate(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
for i:= 0 to NVars-1 do begin
|
|
VEVars.InsertRow(Varnames[i], '0', True);
|
|
end;
|
|
|
|
bm := TBitmap.Create;
|
|
GraphZoom := 1;
|
|
clr[-1] := clGray;
|
|
clr[0] := clYellow1;
|
|
clr[1] := clPlum2;
|
|
clr[2] := clRed;
|
|
clr[3] := clLime;
|
|
clr[4] := clAqua;
|
|
clr[11] := clBlue;
|
|
clr[6] := clMaroon;
|
|
clr[7] := clNavy;
|
|
clr[8] := clOlive;
|
|
clr[9] := clPurple;
|
|
clr[10] := clTeal;
|
|
clr[5] := clGreen;
|
|
case EditPrevQual of
|
|
0: begin
|
|
mnuLowQuality.Checked := true;
|
|
PreviewDensity := prevLowQuality;
|
|
end;
|
|
1: begin
|
|
mnuMediumQuality.Checked := true;
|
|
PreviewDensity := prevMediumQuality;
|
|
end;
|
|
2: begin
|
|
mnuHighQuality.Checked := true;
|
|
PreviewDensity := prevHighQuality;
|
|
end;
|
|
end;
|
|
cp := TControlPoint.Create;
|
|
Render := TRenderer.Create;
|
|
end;
|
|
|
|
procedure TEditForm.GraphImageMouseMove(Sender: TObject; Shift: TShiftState; X,
|
|
Y: integer);
|
|
var
|
|
vx, vy, fx, fy: double;
|
|
begin
|
|
Scale(fx, fy, x, y, EditForm.GraphImage.Width, EditForm.GraphImage.Height);
|
|
if inTriangle(fx, fy) >= 0 then
|
|
GraphImage.Cursor := crHandPoint
|
|
else
|
|
GraphImage.Cursor := crArrow;
|
|
StatusBar.Panels[0].Text := Format('X: %f', [fx]);
|
|
StatusBar.Panels[1].Text := Format('Y: %f', [fy]);
|
|
if CornerCaught then
|
|
begin
|
|
{ Drag a corner }
|
|
MainTriangles[SelectedTriangle].x[SelectedCorner] := fx;
|
|
MainTriangles[SelectedTriangle].y[SelectedCorner] := fy;
|
|
HasChanged := True;
|
|
UpdateFlameX;
|
|
// UpdateFlame(False);
|
|
end
|
|
else if TriangleCaught then
|
|
begin
|
|
{ Drag a whole triangle }
|
|
vx := oldx - fx;
|
|
vy := oldy - fy;
|
|
MainTriangles[SelectedTriangle].x[0] := OldTriangle.x[0] - vx;
|
|
MainTriangles[SelectedTriangle].y[0] := OldTriangle.y[0] - vy;
|
|
MainTriangles[SelectedTriangle].x[1] := OldTriangle.x[1] - vx;
|
|
MainTriangles[SelectedTriangle].y[1] := OldTriangle.y[1] - vy;
|
|
MainTriangles[SelectedTriangle].x[2] := OldTriangle.x[2] - vx;
|
|
MainTriangles[SelectedTriangle].y[2] := OldTriangle.y[2] - vy;
|
|
HasChanged := True;
|
|
UpdateFlameX;
|
|
|
|
// UpdateFlame(False);
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.GraphImageMouseDown(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: integer);
|
|
var
|
|
d, fx, fy: double;
|
|
i, j: integer;
|
|
begin
|
|
intoldx := x;
|
|
intoldy := y;
|
|
CornerCaught := False;
|
|
TriangleCaught := False;
|
|
Scale(fx, fy, x, y, EditForm.GraphImage.Width, EditForm.GraphImage.Height);
|
|
{Has user grabbed a corner?}
|
|
if Button = mbLeft then
|
|
begin
|
|
if SelLocked then
|
|
{ Only change the locked triangle}
|
|
begin
|
|
for j := 0 to 2 do
|
|
begin
|
|
d := dist(fx, fy, MainTriangles[SelectedTriangle].x[j], MainTriangles[SelectedTriangle].y[j]);
|
|
if (d * GraphZoom * 50) < 4 then
|
|
begin
|
|
SelectedCorner := j;
|
|
MainForm.UpdateUndo;
|
|
CornerCaught := True;
|
|
oldx := fx;
|
|
oldy := fy;
|
|
Break;
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
{ Find a corner and select triangle }
|
|
for i := 0 to Transforms - 1 do
|
|
for j := 0 to 2 do
|
|
begin
|
|
d := dist(fx, fy, MainTriangles[i].x[j], MainTriangles[i].y[j]);
|
|
if (d * GraphZoom * 50) < 4 then
|
|
begin
|
|
SelectedTriangle := i;
|
|
SelectedCorner := j;
|
|
MainForm.UpdateUndo;
|
|
CornerCaught := True;
|
|
oldx := fx;
|
|
oldy := fy;
|
|
Break;
|
|
end;
|
|
end;
|
|
if CornerCaught then
|
|
begin
|
|
DrawPreview;
|
|
ShowSelectedInfo;
|
|
DrawGraph;
|
|
end
|
|
else
|
|
begin
|
|
if SelLocked then
|
|
begin
|
|
{ Only move locked triangle }
|
|
if InsideSelected(fx, fy) then
|
|
begin
|
|
OldTriangle := MainTriangles[SelectedTriangle];
|
|
MainForm.UpdateUndo;
|
|
TriangleCaught := True;
|
|
oldx := fx;
|
|
oldy := fy;
|
|
DrawPreview;
|
|
ShowSelectedInfo;
|
|
DrawGraph;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
{ Mouse inside a triangle?}
|
|
i := InsideTriangle(fx, fy);
|
|
if i > -1 then
|
|
begin
|
|
SelectedTriangle := i;
|
|
OldTriangle := MainTriangles[i];
|
|
MainForm.UpdateUndo;
|
|
TriangleCaught := True;
|
|
oldx := fx;
|
|
oldy := fy;
|
|
DrawPreview;
|
|
ShowSelectedInfo;
|
|
DrawGraph;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.GraphImageMouseUp(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: integer);
|
|
var
|
|
fx, fy: double;
|
|
i: integer;
|
|
begin
|
|
Scale(fx, fy, x, y, EditForm.GraphImage.Width, EditForm.GraphImage.Height);
|
|
{ Mouse inside a triangle?}
|
|
i := InsideTriangle(fx, fy);
|
|
if i = -1 then
|
|
begin
|
|
if Button = mbLeft then
|
|
if Shift = [ssCtrl] then
|
|
begin
|
|
AutoZoom;
|
|
ShowSelectedInfo;
|
|
DrawGraph;
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
if SelLocked and (i <> SelectedTriangle) then
|
|
begin
|
|
end
|
|
else if Button = mbLeft then
|
|
if Shift = [ssAlt] then
|
|
begin
|
|
MainTriangles[i] := RotateTriangleCenter(MainTriangles[i], -(PI / 20));
|
|
HasChanged := True;
|
|
UpdateFlame(False);
|
|
end
|
|
else if Shift = [ssCtrl, ssAlt] then
|
|
begin
|
|
MainTriangles[i] := RotateTriangleCenter(MainTriangles[i], PI / 20);
|
|
HasChanged := True;
|
|
UpdateFlame(False);
|
|
end
|
|
else if Shift = [ssShift] then
|
|
begin
|
|
MainTriangles[i] := ScaleTriangleCenter(MainTriangles[i], 1.1);
|
|
HasChanged := True;
|
|
UpdateFlame(False);
|
|
end
|
|
else if Shift = [ssCtrl, ssShift] then
|
|
begin
|
|
MainTriangles[i] := ScaleTriangleCenter(MainTriangles[i], 0.9);
|
|
HasChanged := True;
|
|
UpdateFlame(False);
|
|
end;
|
|
end;
|
|
CornerCaught := False;
|
|
TriangleCaught := False;
|
|
if HasChanged then
|
|
begin
|
|
UpdateFlame(true);
|
|
end;
|
|
HasChanged := False;
|
|
end;
|
|
|
|
procedure TEditForm.FormShow(Sender: TObject);
|
|
var
|
|
Registry: TRegistry;
|
|
begin
|
|
Registry := TRegistry.Create;
|
|
try
|
|
Registry.RootKey := HKEY_CURRENT_USER;
|
|
if Registry.OpenKey('Software\' + APP_NAME + '\Forms\Editor', False) then
|
|
begin
|
|
{ Size and position }
|
|
if Registry.ValueExists('Left') then
|
|
EditForm.Left := Registry.ReadInteger('Left');
|
|
if Registry.ValueExists('Top') then
|
|
EditForm.Top := Registry.ReadInteger('Top');
|
|
if Registry.ValueExists('Width') then
|
|
EditForm.Width := Registry.ReadInteger('Width');
|
|
if Registry.ValueExists('Height') then
|
|
EditForm.Height := Registry.ReadInteger('Height');
|
|
{ Options }
|
|
if Registry.ValueExists('UseTransformColors') then
|
|
begin
|
|
UseTransformColors := Registry.ReadBool('UseTransformColors');
|
|
end
|
|
else
|
|
begin
|
|
UseTransformColors := False;
|
|
end;
|
|
if Registry.ValueExists('UseFlameBackground') then
|
|
begin
|
|
UseFlameBackground := Registry.ReadBool('UseFlameBackground');
|
|
end
|
|
else
|
|
begin
|
|
UseFlameBackground := False;
|
|
end;
|
|
if Registry.ValueExists('BackgroundColor') then
|
|
begin
|
|
BackgroundColor := Registry.ReadInteger('BackgroundColor');
|
|
end
|
|
else
|
|
begin
|
|
BackgroundColor := integer(clBlack);
|
|
end;
|
|
if Registry.ValueExists('ReferenceTriangleColor') then
|
|
begin
|
|
ReferenceTriangleColor := Registry.ReadInteger('ReferenceTriangleColor');
|
|
end
|
|
else
|
|
begin
|
|
ReferenceTriangleColor := integer(clGray);
|
|
end;
|
|
end
|
|
else begin
|
|
UseTransformColors := False;
|
|
UseFlameBackground := False;
|
|
BackgroundColor := integer(clBlack);
|
|
ReferenceTriangleColor := integer(clGray);
|
|
end;
|
|
Registry.CloseKey;
|
|
finally
|
|
Registry.Free;
|
|
end;
|
|
chkUseXFormColor.checked := UseTransformColors;
|
|
chkFlameBack.checked := UseFlameBackground;
|
|
pnlBackColor.Color := TColor(BackgroundColor);
|
|
GrphPnl.Color := TColor(BackgroundColor);
|
|
pnlReference.color := TColor(ReferenceTriangleColor);
|
|
UpdateDisplay;
|
|
end;
|
|
|
|
procedure TEditForm.mnuDeleteClick(Sender: TObject);
|
|
begin
|
|
if SelectedTriangle > -1 then DeleteTriangle(SelectedTriangle);
|
|
end;
|
|
|
|
procedure TEditForm.mnuAddClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
if Transforms < NXFORMS then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
Transforms := Transforms + 1;
|
|
MainTriangles[Transforms - 1] := MainTriangles[-1];
|
|
SelectedTriangle := Transforms - 1;
|
|
ComputeWeights(cp, MainTriangles, transforms);
|
|
cp.xform[Transforms - 1].vars[0] := 1;
|
|
for i := 1 to NVARS - 1 do
|
|
cp.xform[Transforms - 1].vars[i] := 0;
|
|
cbTransforms.clear;
|
|
for i := 0 to Transforms - 1 do
|
|
cbTransforms.Items.Add(IntToStr(i + 1));
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.mnuDupClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
if Transforms < NXFORMS then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
Transforms := Transforms + 1;
|
|
MainTriangles[Transforms - 1] := MainTriangles[SelectedTriangle];
|
|
ComputeWeights(cp, MainTriangles, transforms);
|
|
for i := 0 to NVARS - 1 do
|
|
cp.xform[Transforms - 1].vars[i] := cp.xform[SelectedTriangle].vars[i];
|
|
SelectedTriangle := Transforms - 1;
|
|
cbTransforms.clear;
|
|
for i := 0 to Transforms - 1 do
|
|
cbTransforms.Items.Add(IntToStr(i + 1));
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.mnuAutoZoomClick(Sender: TObject);
|
|
begin
|
|
AutoZoom;
|
|
DrawGraph;
|
|
end;
|
|
|
|
procedure TEditForm.mnuLockClick(Sender: TObject);
|
|
begin
|
|
EditForm.mnuLockSel.Checked := not EditForm.mnuLockSel.Checked;
|
|
SelLocked := EditForm.mnuLockSel.Checked;
|
|
end;
|
|
|
|
procedure TEditForm.mnuXFlipClick(Sender: TObject);
|
|
begin
|
|
MainTriangles[SelectedTriangle] := FlipTriangleHorizontal(MainTriangles[SelectedTriangle]);
|
|
UpdateFlame(True);
|
|
end;
|
|
|
|
procedure TEditForm.mnuYFlipClick(Sender: TObject);
|
|
begin
|
|
MainTriangles[SelectedTriangle] := FlipTriangleVertical(MainTriangles[SelectedTriangle]);
|
|
UpdateFlame(True);
|
|
end;
|
|
|
|
procedure TEditForm.btnCloseClick(Sender: TObject);
|
|
begin
|
|
EditForm.Close;
|
|
end;
|
|
|
|
procedure TEditForm.FormResize(Sender: TObject);
|
|
begin
|
|
Autozoom;
|
|
DrawGraph;
|
|
end;
|
|
|
|
procedure TEditForm.CornerEditExit(Sender: TObject);
|
|
var
|
|
Allow: boolean;
|
|
OldText: string;
|
|
Val: string;
|
|
begin
|
|
Allow := True;
|
|
if Sender = txtAx then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[0]])
|
|
else if Sender = txtAy then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[0]])
|
|
else if Sender = txtBx then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[1]])
|
|
else if Sender = txtBy then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[1]])
|
|
else if Sender = txtCx then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[2]])
|
|
else if Sender = txtCy then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[2]])
|
|
else if Sender = txtP then ;
|
|
val := Format('%.6f', [cp.xform[SelectedTriangle].density]);
|
|
OldText := Val;
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(TEdit(Sender).Text);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
TEdit(Sender).Text := OldText;
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
{ If it's not the same as the old value and it was valid }
|
|
if (val <> TEdit(Sender).Text) and Allow then
|
|
begin
|
|
if Sender = txtAx then
|
|
MainTriangles[SelectedTriangle].x[0] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtAy then
|
|
MainTriangles[SelectedTriangle].y[0] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtBx then
|
|
MainTriangles[SelectedTriangle].x[1] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtBy then
|
|
MainTriangles[SelectedTriangle].y[1] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtCx then
|
|
MainTriangles[SelectedTriangle].x[2] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtCy then
|
|
MainTriangles[SelectedTriangle].y[2] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtP then
|
|
begin
|
|
cp.xform[SelectedTriangle].density := StrToFloat(TEdit(Sender).Text);
|
|
ReadjustWeights(cp);
|
|
TEdit(Sender).Text := Format('%.6g', [cp.xform[SelectedTriangle].density]);
|
|
end;
|
|
MainForm.UpdateUndo;
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.CornerEditKeyPress(Sender: TObject; var Key: Char);
|
|
var
|
|
Allow: boolean;
|
|
OldText: string;
|
|
Val: string;
|
|
begin
|
|
if key = #13 then
|
|
begin
|
|
Allow := True;
|
|
if Sender = txtAx then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[0]])
|
|
else if Sender = txtAy then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[0]])
|
|
else if Sender = txtBx then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[1]])
|
|
else if Sender = txtBy then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[1]])
|
|
else if Sender = txtCx then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].x[2]])
|
|
else if Sender = txtCy then
|
|
Val := Format('%.6f', [MainTriangles[SelectedTriangle].y[2]])
|
|
else if Sender = txtP then ;
|
|
val := Format('%.6f', [cp.xform[SelectedTriangle].density]);
|
|
OldText := Val;
|
|
{ Stop the beep }
|
|
Key := #0;
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(TEdit(Sender).Text);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
TEdit(Sender).Text := OldText;
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
{ If it's not the same as the old value and it was valid }
|
|
if (val <> TEdit(Sender).Text) and Allow then
|
|
begin
|
|
if Sender = txtAx then
|
|
MainTriangles[SelectedTriangle].x[0] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtAy then
|
|
MainTriangles[SelectedTriangle].y[0] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtBx then
|
|
MainTriangles[SelectedTriangle].x[1] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtBy then
|
|
MainTriangles[SelectedTriangle].y[1] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtCx then
|
|
MainTriangles[SelectedTriangle].x[2] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtCy then
|
|
MainTriangles[SelectedTriangle].y[2] := StrToFloat(TEdit(Sender).Text)
|
|
else if Sender = txtP then
|
|
begin
|
|
cp.xform[SelectedTriangle].density := StrToFloat(TEdit(Sender).Text);
|
|
ReadjustWeights(cp);
|
|
TEdit(Sender).Text := Format('%.6g', [cp.xform[SelectedTriangle].density]);
|
|
end;
|
|
MainForm.UpdateUndo;
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ ************************* Probability input ******************************** }
|
|
|
|
procedure TEditForm.txtPKeyPress(Sender: TObject; var Key: Char);
|
|
var
|
|
Allow: boolean;
|
|
NewVal, OldVal: double;
|
|
begin
|
|
if key = #13 then
|
|
begin
|
|
{ Stop the beep }
|
|
Key := #0;
|
|
Allow := True;
|
|
OldVal := Round6(cp.xform[SelectedTriangle].density);
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(TEdit(Sender).Text);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
TEdit(Sender).Text := Format('%.6g', [OldVal]);
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
NewVal := Round6(StrToFloat(TEdit(Sender).Text));
|
|
if NewVal < 0 then NewVal := 0;
|
|
if NewVal > 0.99 then NewVal := 0.99;
|
|
{ If it's not the same as the old value and it was valid }
|
|
TEdit(Sender).Text := Format('%.6g', [NewVal]);
|
|
if (OldVal <> NewVal) and Allow then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
cp.xform[SelectedTriangle].density := NewVal;
|
|
ReadjustWeights(cp);
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.txtPExit(Sender: TObject);
|
|
var
|
|
Allow: boolean;
|
|
NewVal, OldVal: double;
|
|
begin
|
|
Allow := True;
|
|
OldVal := Round6(cp.xform[SelectedTriangle].density);
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(TEdit(Sender).Text);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
TEdit(Sender).Text := Format('%.6g', [OldVal]);
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
NewVal := Round6(StrToFloat(TEdit(Sender).Text));
|
|
if NewVal < 0 then NewVal := 0;
|
|
if NewVal > 0.99 then NewVal := 0.99;
|
|
{ If it's not the same as the old value and it was valid }
|
|
TEdit(Sender).Text := Format('%.6g', [NewVal]);
|
|
if (OldVal <> NewVal) and Allow then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
cp.xform[SelectedTriangle].density := NewVal;
|
|
ReadjustWeights(cp);
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
|
|
{ **************************************************************************** }
|
|
|
|
procedure TEditForm.FormClose(Sender: TObject; var Action: TCloseAction);
|
|
var
|
|
Registry: TRegistry;
|
|
begin
|
|
{ Write position to registry }
|
|
Registry := TRegistry.Create;
|
|
try
|
|
Registry.RootKey := HKEY_CURRENT_USER;
|
|
{ Defaults }
|
|
if Registry.OpenKey('\Software\' + APP_NAME + '\Forms\Editor', True) then
|
|
begin
|
|
{ Options }
|
|
Registry.WriteBool('UseTransformColors', UseTransformColors);
|
|
Registry.WriteBool('UseFlameBackground', UseFlameBackground);
|
|
Registry.WriteInteger('BackgroundColor', BackgroundColor);
|
|
Registry.WriteInteger('ReferenceTriangleColor', ReferenceTriangleColor);
|
|
{ Size and position }
|
|
if EditForm.WindowState <> wsMaximized then begin
|
|
Registry.WriteInteger('Top', EditForm.Top);
|
|
Registry.WriteInteger('Left', EditForm.Left);
|
|
Registry.WriteInteger('Width', EditForm.Width);
|
|
Registry.WriteInteger('Height', EditForm.Height);
|
|
end;
|
|
end;
|
|
finally
|
|
Registry.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.mnuUndoClick(Sender: TObject);
|
|
begin
|
|
MainForm.Undo;
|
|
end;
|
|
|
|
procedure TEditForm.mnuRedoClick(Sender: TObject);
|
|
begin
|
|
MainForm.Redo;
|
|
end;
|
|
|
|
procedure TEditForm.FormDestroy(Sender: TObject);
|
|
begin
|
|
bm.free;
|
|
cp.free;
|
|
Render.free;
|
|
end;
|
|
|
|
procedure TEditForm.mnuLowQualityClick(Sender: TObject);
|
|
begin
|
|
mnuLowQuality.Checked := True;
|
|
PreviewDensity := prevLowQuality;
|
|
EditPrevQual := 0;
|
|
DrawPreview;
|
|
end;
|
|
|
|
procedure TEditForm.mnuHighQualityClick(Sender: TObject);
|
|
begin
|
|
mnuHighQuality.Checked := True;
|
|
PreviewDensity := prevHighQuality;
|
|
EditPrevQual := 2;
|
|
DrawPreview;
|
|
end;
|
|
|
|
procedure TEditForm.mnuMediumQualityClick(Sender: TObject);
|
|
begin
|
|
mnuMediumQuality.Checked := True;
|
|
PreviewDensity := prevMediumQuality;
|
|
EditPrevQual := 1;
|
|
DrawPreview;
|
|
end;
|
|
|
|
procedure TEditForm.mnuResetLocationClick(Sender: TObject);
|
|
begin
|
|
mnuResetLocation.Checked := not mnuResetLocation.Checked;
|
|
if not mnuResetLocation.checked then
|
|
begin
|
|
cp.width := MainCp.width;
|
|
cp.height := MainCp.height;
|
|
cp.pixels_per_unit := MainCp.pixels_per_unit;
|
|
AdjustScale(cp, PreviewImage.width, PreviewImage.Height);
|
|
cp.zoom := MainCp.zoom;
|
|
cp.center[0] := MainCp.center[0];
|
|
cp.center[1] := MainCp.center[1];
|
|
end;
|
|
DrawPreview;
|
|
end;
|
|
|
|
procedure TEditForm.mnuVerticalFlipAllClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
for i := -1 to Transforms - 1 do
|
|
begin
|
|
MainTriangles[i] := FlipTriangleVertical(MainTriangles[i]);
|
|
end;
|
|
AutoZoom;
|
|
UpdateFlame(True);
|
|
end;
|
|
|
|
procedure TEditForm.mnuHorizintalFlipAllClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
for i := -1 to Transforms - 1 do
|
|
begin
|
|
MainTriangles[i] := FlipTriangleHorizontal(MainTriangles[i]);
|
|
end;
|
|
AutoZoom;
|
|
UpdateFlame(True);
|
|
end;
|
|
|
|
procedure TEditForm.mnuFlipVerticalClick(Sender: TObject);
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
MainTriangles[SelectedTriangle] := FlipTriangleVertical(MainTriangles[SelectedTriangle]);
|
|
AutoZoom;
|
|
UpdateFlame(True);
|
|
end;
|
|
|
|
procedure TEditForm.mnuFlipHorizontalClick(Sender: TObject);
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
MainTriangles[SelectedTriangle] := FlipTriangleHorizontal(MainTriangles[SelectedTriangle]);
|
|
AutoZoom;
|
|
UpdateFlame(True);
|
|
end;
|
|
|
|
procedure TEditForm.GraphImageDblClick(Sender: TObject);
|
|
begin
|
|
AutoZoom;
|
|
DrawGraph;
|
|
end;
|
|
|
|
procedure TEditForm.cbTransformsChange(Sender: TObject);
|
|
begin
|
|
if SelectedTriangle <> cbTransforms.ItemIndex then SelectedTriangle := cbTransforms.ItemIndex;
|
|
ShowSelectedInfo;
|
|
DrawGraph;
|
|
end;
|
|
|
|
procedure TEditForm.CoefKeyPress(Sender: TObject; var Key: Char);
|
|
var
|
|
Allow: boolean;
|
|
i: integer;
|
|
OldVal, NewVal: double;
|
|
begin
|
|
i := 0; OldVal := 0;
|
|
if key = #13 then
|
|
begin
|
|
key := #0;
|
|
Allow := True;
|
|
if Sender = txtA then
|
|
i := 0
|
|
else if Sender = txtB then
|
|
i := 1
|
|
else if Sender = txtC then
|
|
i := 2
|
|
else if Sender = txtD then
|
|
i := 3
|
|
else if Sender = txtE then
|
|
i := 4
|
|
else if Sender = txtF then
|
|
i := 5;
|
|
case i of
|
|
0: OldVal := Round6(cp.xform[SelectedTriangle].c[0][0]); //a
|
|
1: OldVal := Round6(cp.xform[SelectedTriangle].c[1][0]); //b
|
|
2: OldVal := Round6(cp.xform[SelectedTriangle].c[0][1]); //c
|
|
3: OldVal := Round6(cp.xform[SelectedTriangle].c[1][1]); //d
|
|
4: OldVal := Round6(cp.xform[SelectedTriangle].c[2][0]); //e
|
|
5: OldVal := Round6(cp.xform[SelectedTriangle].c[2][1]); //f
|
|
end;
|
|
// OldText := Val;
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(TEdit(Sender).Text);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
TEdit(Sender).Text := Format('%.6g', [OldVal]);
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
NewVal := Round6(StrToFloat(TEdit(Sender).Text));
|
|
TEdit(Sender).Text := Format('%.6g', [NewVal]);
|
|
|
|
{ If it's not the same as the old value and it was valid }
|
|
if (NewVal <> OldVal) and Allow then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
case i of
|
|
0: cp.xform[SelectedTriangle].c[0][0] := NewVal; //a
|
|
1: cp.xform[SelectedTriangle].c[1][0] := NewVal; //b
|
|
2: cp.xform[SelectedTriangle].c[0][1] := NewVal; //c
|
|
3: cp.xform[SelectedTriangle].c[1][1] := NewVal; //d
|
|
4: cp.xform[SelectedTriangle].c[2][0] := NewVal; //e
|
|
5: cp.xform[SelectedTriangle].c[2][1] := NewVal; //f
|
|
end;
|
|
MainForm.TrianglesFromCP(cp, MainTriangles);
|
|
ShowSelectedInfo;
|
|
UpdateFlame(true);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.CoefExit(Sender: TObject);
|
|
var
|
|
Allow: boolean;
|
|
i: integer;
|
|
NewVal, OldVal: double;
|
|
begin
|
|
i := 0; OldVal := 0;
|
|
Allow := True;
|
|
if Sender = txtA then
|
|
i := 0
|
|
else if Sender = txtB then
|
|
i := 1
|
|
else if Sender = txtC then
|
|
i := 2
|
|
else if Sender = txtD then
|
|
i := 3
|
|
else if Sender = txtE then
|
|
i := 4
|
|
else if Sender = txtF then
|
|
i := 5;
|
|
case i of
|
|
0: OldVal := Round6(cp.xform[SelectedTriangle].c[0][0]); //a
|
|
1: OldVal := Round6(cp.xform[SelectedTriangle].c[1][0]); //b
|
|
2: OldVal := Round6(cp.xform[SelectedTriangle].c[0][1]); //c
|
|
3: OldVal := Round6(cp.xform[SelectedTriangle].c[1][1]); //d
|
|
4: OldVal := Round6(cp.xform[SelectedTriangle].c[2][0]); //e
|
|
5: OldVal := Round6(cp.xform[SelectedTriangle].c[2][1]); //f
|
|
end;
|
|
// OldText := Val;
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(TEdit(Sender).Text);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
TEdit(Sender).Text := Format('%.6g', [OldVal]);
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
NewVal := Round6(StrToFloat(TEdit(Sender).Text));
|
|
TEdit(Sender).Text := Format('%.6g', [NewVal]);
|
|
|
|
{ If it's not the same as the old value and it was valid }
|
|
if (NewVal <> OldVal) and Allow then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
case i of
|
|
0: cp.xform[SelectedTriangle].c[0][0] := NewVal; //a
|
|
1: cp.xform[SelectedTriangle].c[1][0] := NewVal; //b
|
|
2: cp.xform[SelectedTriangle].c[0][1] := NewVal; //c
|
|
3: cp.xform[SelectedTriangle].c[1][1] := NewVal; //d
|
|
4: cp.xform[SelectedTriangle].c[2][0] := NewVal; //e
|
|
5: cp.xform[SelectedTriangle].c[2][1] := NewVal; //f
|
|
end;
|
|
MainForm.TrianglesFromCP(cp, MainTriangles);
|
|
ShowSelectedInfo;
|
|
UpdateFlame(true);
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.scrlXFormColorScroll(Sender: TObject;
|
|
ScrollCode: TScrollCode; var ScrollPos: Integer);
|
|
begin
|
|
if ScrollCode = scEndScroll then UpdateFlame(True);
|
|
end;
|
|
|
|
procedure TEditForm.scrlXFormColorChange(Sender: TObject);
|
|
begin
|
|
cp.xform[SelectedTriangle].color := (scrlXFormColor.Position) / 100;
|
|
txtXFormColor.Text := FloatToStr(cp.xform[SelectedTriangle].color);
|
|
pnlXFormColor.color := ColorValToColor(MainCp.cmap, cp.xform[SelectedTriangle].color);
|
|
DrawGraph;
|
|
DrawPreview;
|
|
end;
|
|
|
|
procedure TEditForm.chkUseXFormColorClick(Sender: TObject);
|
|
begin
|
|
UseTransformColors := chkUseXFormColor.checked;
|
|
DrawGraph;
|
|
end;
|
|
|
|
procedure TEditForm.chkFlameBackClick(Sender: TObject);
|
|
begin
|
|
UseFlameBackground := chkFlameBack.checked;
|
|
DrawGraph;
|
|
end;
|
|
|
|
procedure TEditForm.pnlBackColorClick(Sender: TObject);
|
|
begin
|
|
AdjustForm.ColorDialog.Color := pnlBackColor.Color;
|
|
if AdjustForm.ColorDialog.Execute then
|
|
begin
|
|
pnlBackColor.Color := AdjustForm.ColorDialog.Color;
|
|
BackgroundColor := Integer(pnlBackColor.color);
|
|
GrphPnl.Color := BackgroundColor;
|
|
DrawGraph;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.pnlReferenceClick(Sender: TObject);
|
|
begin
|
|
AdjustForm.ColorDialog.Color := pnlReference.Color;
|
|
if AdjustForm.ColorDialog.Execute then
|
|
begin
|
|
pnlReference.Color := AdjustForm.ColorDialog.Color;
|
|
ReferenceTriangleColor := Integer(pnlReference.color);
|
|
DrawGraph;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.txtXFormColorExit(Sender: TObject);
|
|
var
|
|
v: double;
|
|
begin
|
|
try
|
|
v := StrToFloat(txtXFormColor.Text);
|
|
except on EConvertError do
|
|
begin
|
|
txtXformColor.text := FLoattoStr(cp.xform[SelectedTriangle].color);
|
|
exit;
|
|
end;
|
|
end;
|
|
if v > 1 then v := 1;
|
|
if v < 0 then v := 0;
|
|
if v <> cp.xform[SelectedTriangle].color then
|
|
begin
|
|
scrlXFormColor.Position := round(v * 100);
|
|
UpdateFlame(true);
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.txtXFormColorKeyPress(Sender: TObject; var Key: Char);
|
|
var
|
|
v: double;
|
|
begin
|
|
if key = #13 then
|
|
begin
|
|
key := #0;
|
|
try
|
|
v := StrToFloat(txtXFormColor.Text);
|
|
except on EConvertError do
|
|
begin
|
|
txtXformColor.text := FLoattoStr(cp.xform[SelectedTriangle].color);
|
|
exit;
|
|
end;
|
|
end;
|
|
if v > 1 then v := 1;
|
|
if v < 0 then v := 0;
|
|
if v <> cp.xform[SelectedTriangle].color then
|
|
begin
|
|
scrlXFormColor.Position := round(v * 100);
|
|
UpdateFlame(true);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.txtSymmetryExit(Sender: TObject);
|
|
var
|
|
Allow: boolean;
|
|
NewVal, OldVal: double;
|
|
begin
|
|
Allow := True;
|
|
OldVal := Round6(cp.xform[SelectedTriangle].symmetry);
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(TEdit(Sender).Text);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
TEdit(Sender).Text := Format('%.6g', [OldVal]);
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
NewVal := Round6(StrToFloat(TEdit(Sender).Text));
|
|
if NewVal < 0 then NewVal := 0;
|
|
if NewVal > 1 then NewVal := 1;
|
|
{ If it's not the same as the old value and it was valid }
|
|
TEdit(Sender).Text := Format('%.6g', [NewVal]);
|
|
if (OldVal <> NewVal) and Allow then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
cp.xform[SelectedTriangle].symmetry := NewVal;
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.txtSymmetryKeyPress(Sender: TObject; var Key: Char);
|
|
var
|
|
Allow: boolean;
|
|
NewVal, OldVal: double;
|
|
begin
|
|
if key = #13 then
|
|
begin
|
|
{ Stop the beep }
|
|
Key := #0;
|
|
Allow := True;
|
|
OldVal := Round6(cp.xform[SelectedTriangle].symmetry);
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(TEdit(Sender).Text);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
TEdit(Sender).Text := Format('%.6g', [OldVal]);
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
NewVal := Round6(StrToFloat(TEdit(Sender).Text));
|
|
if NewVal < 0 then NewVal := 0;
|
|
if NewVal > 1 then NewVal := 1;
|
|
{ If it's not the same as the old value and it was valid }
|
|
TEdit(Sender).Text := Format('%.6g', [NewVal]);
|
|
if (OldVal <> NewVal) and Allow then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
cp.xform[SelectedTriangle].symmetry := NewVal;
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.VEVarsKeyPress(Sender: TObject; var Key: Char);
|
|
var
|
|
Allow: boolean;
|
|
i: integer;
|
|
NewVal, OldVal: double;
|
|
begin
|
|
if key = #13 then
|
|
begin
|
|
key := #0;
|
|
Allow := True;
|
|
|
|
i := EditForm.VEVars.Row - 1;
|
|
|
|
OldVal := Round6(cp.xform[SelectedTriangle].vars[i]);
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(VEVars.Values[VarNames[i]]);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
VEVars.Values[VarNames[i]] := Format('%.6g', [OldVal]);
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
NewVal := Round6(StrToFloat(VEVars.Values[VarNames[i]]));
|
|
// if NewVal < 0 then NewVal := 0;
|
|
VEVars.Values[VarNames[i]] := Format('%.6g', [NewVal]);
|
|
|
|
{ If it's not the same as the old value and it was valid }
|
|
if (NewVal <> OldVal) and Allow then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
EditedVariation := i;
|
|
cp.xform[SelectedTriangle].vars[i] := NewVal;
|
|
// VarNormalize(cp);
|
|
VEVars.Values[VarNames[i]] := Format('%.6g', [cp.xform[SelectedTriangle].vars[i]]);
|
|
ShowSelectedInfo;
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.VEVarsExit(Sender: TObject);
|
|
var
|
|
Allow: boolean;
|
|
i: integer;
|
|
NewVal, OldVal: double;
|
|
begin
|
|
Allow := True;
|
|
|
|
i := EditForm.VEVars.Row - 1;
|
|
|
|
OldVal := Round6(cp.xform[SelectedTriangle].vars[i]);
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(VEVars.Values[VarNames[i]]);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
VEVars.Values[VarNames[i]] := Format('%.6g', [OldVal]);
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
NewVal := Round6(StrToFloat(VEVars.Values[VarNames[i]]));
|
|
// if NewVal < 0 then NewVal := 0;
|
|
VEVars.Values[VarNames[i]] := Format('%.6g', [NewVal]);
|
|
|
|
{ If it's not the same as the old value and it was valid }
|
|
if (NewVal <> OldVal) and Allow then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
EditedVariation := i;
|
|
cp.xform[SelectedTriangle].vars[i] := NewVal;
|
|
// VarNormalize(cp);
|
|
VEVars.Values[VarNames[i]] := Format('%.6g', [cp.xform[SelectedTriangle].vars[i]]);
|
|
ShowSelectedInfo;
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TEditForm.VEVarsValidate(Sender: TObject; ACol, ARow: Integer; const KeyName, KeyValue: String);
|
|
var
|
|
Allow: boolean;
|
|
i: integer;
|
|
NewVal, OldVal: double;
|
|
begin
|
|
Allow := True;
|
|
|
|
i := EditForm.VEVars.Row - 1;
|
|
|
|
OldVal := Round6(cp.xform[SelectedTriangle].vars[i]);
|
|
{ Test that it's a valid floating point number }
|
|
try
|
|
StrToFloat(VEVars.Values[VarNames[i]]);
|
|
except on Exception do
|
|
begin
|
|
{ It's not, so we restore the old value }
|
|
VEVars.Values[VarNames[i]] := Format('%.6g', [OldVal]);
|
|
Allow := False;
|
|
end;
|
|
end;
|
|
NewVal := Round6(StrToFloat(VEVars.Values[VarNames[i]]));
|
|
// if NewVal < 0 then NewVal := 0;
|
|
VEVars.Values[VarNames[i]] := Format('%.6g', [NewVal]);
|
|
|
|
{ If it's not the same as the old value and it was valid }
|
|
if (NewVal <> OldVal) and Allow then
|
|
begin
|
|
MainForm.UpdateUndo;
|
|
EditedVariation := i;
|
|
cp.xform[SelectedTriangle].vars[i] := NewVal;
|
|
// VarNormalize(cp);
|
|
VEVars.Values[VarNames[i]] := Format('%.6g', [cp.xform[SelectedTriangle].vars[i]]);
|
|
ShowSelectedInfo;
|
|
UpdateFlame(True);
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|