Apophysis-AV/Forms/Editor.pas

8145 lines
244 KiB
ObjectPascal
Raw Normal View History

2022-03-08 12:25:51 -05:00
{
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
Apophysis AV "Phoenix Edition" Copyright (C) 2021-2022 Alice V. Koryagina
2022-03-08 12:25:51 -05:00
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;
//{$define VAR_STR}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, ComCtrls, Math, Menus, ToolWin, Registry,
Grids, ValEdit, Buttons, ImgList, Types, StrUtils,
2022-03-08 12:25:51 -05:00
ControlPoint, XForm, cmap, CustomDrawControl, ClipBrd,
RenderingInterface, RenderThread, System.ImageList,
Vcl.Samples.Spin, Vcl.GraphUtil;
2022-03-08 12:25:51 -05:00
type
TEditForm = class(TForm)
StatusBar: TStatusBar;
EditPopup: TPopupMenu;
mnuAdd: TMenuItem;
mnuAutoZoom: TMenuItem;
N1: TMenuItem;
mnuUndo: TMenuItem;
mnuRedo: TMenuItem;
QualityPopup: TPopupMenu;
mnuLowQuality: TMenuItem;
mnuMediumQuality: TMenuItem;
mnuHighQuality: TMenuItem;
N3: TMenuItem;
mnuResetLoc: TMenuItem;
N4: TMenuItem;
mnuFlipVertical: TMenuItem;
mnuFlipHorizontal: TMenuItem;
mnuFlipAllV: TMenuItem; //AV
mnuFlipAllH: TMenuItem; // AV
EditorToolBar: TToolBar;
tbAdd: TToolButton;
tbDuplicate: TToolButton;
tbDelete: TToolButton;
ToolButton4: TToolButton;
tbMove: TToolButton;
tbRotate: TToolButton;
ToolButton1: TToolButton;
tbUndo: TToolButton;
tbRedo: TToolButton;
tbScale: TToolButton;
tbFlipHorz: TToolButton;
tbFlipVert: TToolButton;
tbSelect: TToolButton;
EditorTB: TImageList;
tbResetAll: TToolButton;
ToolButton2: TToolButton;
tbVarPreview: TToolButton;
tbEnableFinalXform: TToolButton;
ToolButton3: TToolButton;
TrianglePopup: TPopupMenu;
mnuDuplicate: TMenuItem;
mnuDelete: TMenuItem;
mnuAdd1: TMenuItem;
N2: TMenuItem;
mnuShowVarPreview: TMenuItem;
mnuReset: TMenuItem;
N6: TMenuItem;
Rotatetriangle90CCW1: TMenuItem;
Rotatetriangle90CCW2: TMenuItem;
mnuResetTrgRotation: TMenuItem;
mnuResetTrgPosition: TMenuItem;
mnuResetTrgScale: TMenuItem;
N7: TMenuItem;
mnuExtendedEdit: TMenuItem;
N8: TMenuItem;
mnuAxisLock: TMenuItem;
mnuSelectmode: TMenuItem;
ToolButton6: TToolButton;
tbPivotMode: TToolButton;
tbRotate90CCW: TToolButton;
tbRotate90CW: TToolButton;
tbPostXswap: TToolButton;
oggleposttriangleediting1: TMenuItem;
mnuCopyTriangle: TMenuItem;
mnuPasteTriangle: TMenuItem;
ChaosPopup: TPopupMenu;
mnuChaosViewTo: TMenuItem;
mnuChaosViewFrom: TMenuItem;
N9: TMenuItem;
mnuChaosClearAll: TMenuItem;
mnuChaosSetAll: TMenuItem;
N10: TMenuItem;
mnuLinkPostxform: TMenuItem;
mnuLinkPrexform: TMenuItem;
mnuChaosRebuild: TMenuItem;
tbPostLink: TToolButton;
ToolButton8: TToolButton;
tbCopy: TToolButton;
tbPaste: TToolButton;
ToolButton11: TToolButton;
EditPnl: TPanel;
Splitter1: TSplitter;
GrphPnl: TPanel;
RightPanel: TPanel;
Splitter2: TSplitter;
ControlPanel: TPanel;
cbTransforms: TComboBox;
PageControl: TPageControl;
TriangleTab: TTabSheet;
TriangleScrollBox: TScrollBox;
TrianglePanel: TPanel;
TriangleToolBar: TToolBar;
tbCopyTriangle: TToolButton;
tbPasteTriangle: TToolButton;
tbExtendedEdit: TToolButton;
tbAxisLock: TToolButton;
tbAutoWeights: TToolButton;
tb2PostXswap: TToolButton;
tabXForm: TTabSheet;
tabColors: TTabSheet;
tabVariations: TTabSheet;
VEVars: TValueListEditor;
bClear: TBitBtn;
TabVariables: TTabSheet;
vleVariables: TValueListEditor;
chkCollapseVariables: TCheckBox;
TabChaos: TTabSheet;
vleChaos: TValueListEditor;
optFrom: TRadioButton;
optTo: TRadioButton;
txtP: TEdit;
pnlWeight: TPanel;
Panel1: TPanel;
txtName: TEdit;
Panel2: TPanel;
PrevPnl: TPanel;
PreviewImage: TImage;
gbTrgOperations: TGroupBox;
2022-03-08 12:25:51 -05:00
btTrgRotateLeft90: TSpeedButton;
btTrgRotateRight90: TSpeedButton;
btTrgScaleDown: TSpeedButton;
btTrgScaleUp: TSpeedButton;
btTrgMoveDown: TSpeedButton;
btTrgMoveLeft: TSpeedButton;
btTrgMoveRight: TSpeedButton;
btTrgMoveUp: TSpeedButton;
btTrgRotateLeft: TSpeedButton;
btTrgRotateRight: TSpeedButton;
txtTrgScaleValue: TComboBox;
txtTrgRotateValue: TComboBox;
txtTrgMoveValue: TComboBox;
gbCoordinates: TGroupBox;
2022-03-08 12:25:51 -05:00
LabelC: TLabel;
LabelA: TLabel;
LabelB: TLabel;
txtAx: TEdit;
txtAy: TEdit;
txtBx: TEdit;
txtBy: TEdit;
txtCx: TEdit;
txtCy: TEdit;
ScrollBox1: TScrollBox;
GroupBox9: TGroupBox;
btnXcoefs: TSpeedButton;
btnYcoefs: TSpeedButton;
btnOcoefs: TSpeedButton;
btnResetCoefs: TSpeedButton;
txtA: TEdit;
txtB: TEdit;
txtC: TEdit;
txtD: TEdit;
txtE: TEdit;
txtF: TEdit;
spinA: TSpinButton;
spinB: TSpinButton;
spinC: TSpinButton;
spinD: TSpinButton;
spinE: TSpinButton;
spinF: TSpinButton;
GroupBox7: TGroupBox;
btnCoefsPolar: TSpeedButton;
btnCoefsRect: TSpeedButton;
GroupBox8: TGroupBox;
btnXpost: TSpeedButton;
btnYpost: TSpeedButton;
btnOpost: TSpeedButton;
btnResetPostCoefs: TSpeedButton;
txtPost00: TEdit;
txtPost01: TEdit;
txtPost10: TEdit;
txtPost11: TEdit;
txtPost20: TEdit;
txtPost21: TEdit;
spinPost00: TSpinButton;
spinPost01: TSpinButton;
spinPost10: TSpinButton;
spinPost11: TSpinButton;
spinPost20: TSpinButton;
spinPost21: TSpinButton;
chkAutoZscale: TCheckBox;
ScrollBox2: TScrollBox;
GroupBox1: TGroupBox;
pnlSymmetry: TPanel;
pnlXFormColor: TPanel;
shColor: TShape;
txtXFormColor: TEdit;
txtSymmetry: TEdit;
ColorBar: TPanel;
ColorBarPicture: TImage;
scrlXFormColor: TScrollBar;
pnlOpacity: TPanel;
txtOpacity: TEdit;
chkXformSolo: TCheckBox;
pnlDC: TPanel;
txtDC: TEdit;
GroupBox2: TGroupBox;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
trkVarPreviewDensity: TTrackBar;
trkVarPreviewRange: TTrackBar;
trkVarPreviewDepth: TTrackBar;
ImgTemp: TImage;
N11: TMenuItem;
mnuEHighQuality: TMenuItem;
mnuEMediumQuality: TMenuItem;
mnuELowQuality: TMenuItem;
lblSearch: TLabel;
2022-03-08 12:25:51 -05:00
txtSearchBox: TEdit;
ToolButton5: TToolButton;
btnMathPopup: TToolButton;
tbPreLink: TToolButton;
btnFullChaos: TToolButton;
btnResetSearch: TSpeedButton;
gbPivot: TGroupBox;
2022-03-08 12:25:51 -05:00
btnResetPivot: TSpeedButton;
btnPickPivot: TSpeedButton;
btnPivotMode: TSpeedButton;
editPivotY: TEdit;
editPivotX: TEdit;
MathPopup: TPopupMenu;
InsertPi1: TMenuItem;
Insert2Pi1: TMenuItem;
InsertPi21: TMenuItem;
InsertPi31: TMenuItem;
InsertGoldenratio1: TMenuItem;
InsertPi41: TMenuItem;
InsertPi61: TMenuItem;
Insertsqrt321: TMenuItem;
Insertsqrt331: TMenuItem;
Pifractions: TMenuItem;
Insert1sqrt21: TMenuItem;
CopyMenu: TPopupMenu;
PasteMenu: TPopupMenu;
CopyTriangleCoordinates: TMenuItem;
CopyTransform: TMenuItem;
PasteTriangleCoordinates: TMenuItem;
PasteTransform: TMenuItem;
2022-03-08 12:25:51 -05:00
Squareroots1: TMenuItem;
Insertsqrt361: TMenuItem;
Insertsqrt31: TMenuItem;
TriangleOperations: TPopupMenu;
InvertMovevalue1: TMenuItem;
ShowModVals: TMenuItem;
tbTriangle: TToolButton;
InvCurrentNum: TMenuItem;
N12: TMenuItem;
ScaleX: TMenuItem;
ScaleY: TMenuItem;
N13: TMenuItem;
ScaleXYO: TMenuItem;
N14: TMenuItem;
RotateXYO: TMenuItem;
RotateX: TMenuItem;
RotateY: TMenuItem;
ScaleO: TMenuItem;
RotateO: TMenuItem;
gbFlip: TGroupBox;
2022-03-08 12:25:51 -05:00
btnShowLine: TSpeedButton;
btnResetFlip: TSpeedButton;
btnFlip: TSpeedButton;
editFlipY: TEdit;
editFlipX: TEdit;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
lblGridType: TLabel;
GridComboBox: TComboBox;
Mul2: TMenuItem;
Div2: TMenuItem;
Squarethenumber1: TMenuItem;
RectGrid: TMenuItem;
TriGrid: TMenuItem;
N15: TMenuItem;
NormChaos: TMenuItem;
SpinPivotX: TSpinButton;
SpinPivotY: TSpinButton;
SpinFlipX: TSpinButton;
SpinFlipY: TSpinButton;
lblFlipAngle: TLabel;
RandomizeMatrix: TMenuItem;
btSwapCoefs: TButton;
CalcArcsinScale: TMenuItem;
N16: TMenuItem;
mnuFlipAllLine: TMenuItem;
btResetChaos: TButton;
ResetChaos: TMenuItem;
btClearChaos: TButton;
RandomizeChaos: TMenuItem;
N17: TMenuItem;
ChaosClearBelow: TMenuItem;
ClearAllAbove: TMenuItem;
btConjugate: TButton;
AddContainer: TMenuItem;
N18: TMenuItem;
CalcCos: TMenuItem;
CalcSin: TMenuItem;
CalcTan: TMenuItem;
UseDegrees: TMenuItem;
InheritWeights: TMenuItem;
InvertXaos: TMenuItem;
SquareRoot: TMenuItem;
btFlipX: TButton;
btFlipY: TButton;
btFlipDiag: TButton;
mnuResetTrgFlip: TMenuItem;
btChaos: TButton;
SpinXx: TSpinButton;
SpinYx: TSpinButton;
SpinOx: TSpinButton;
SpinXy: TSpinButton;
SpinYy: TSpinButton;
SpinOy: TSpinButton;
IconsAV: TImageList;
N19: TMenuItem;
ShowChaosMatrix: TMenuItem;
btnVarOrder: TBitBtn;
cbCollapseVariations: TComboBox;
btResetParams: TButton;
tbSyncTriangles: TToolButton;
mnuSyncTriangles: TPopupMenu;
SynchronizeAll: TMenuItem;
N20: TMenuItem;
CopyVariations: TMenuItem;
PasteVariations: TMenuItem;
ToolButton7: TToolButton;
tbComment: TToolButton;
mnuCalcExpression: TMenuItem;
N22: TMenuItem;
SaveFlameState: TToolButton;
N23: TMenuItem;
mnuCopyChaos: TMenuItem;
mnuPasteChaos: TMenuItem;
CopyChaos: TMenuItem;
PasteChaos: TMenuItem;
2022-03-08 12:25:51 -05:00
procedure btnResetSearchClick(Sender: TObject);
procedure txtSearchBoxKeyPress(Sender: TObject; var Key: Char);
// procedure txtSearchBoxChange(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure ScrollBox1Resize(Sender: TObject);
procedure ScrollBox2Resize(Sender: TObject);
procedure ControlPanelResize(Sender: TObject);
procedure TrianglePanelResize(Sender: TObject);
procedure ValidateVariable;
procedure vleVariablesValidate(Sender: TObject; ACol, ARow: Integer; const KeyName, KeyValue: string);
procedure vleVariablesKeyPress(Sender: TObject; var Key: Char);
procedure vleVariablesExit(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure TriangleViewMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: integer);
procedure TriangleViewMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: integer);
procedure TriangleViewMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: integer);
procedure TriangleViewMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
procedure TriangleViewDblClick(Sender: TObject);
procedure TriangleViewKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure TriangleViewKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure TriangleViewExit(Sender: TObject);
procedure TriangleViewMouseLeave(Sender: TObject);
procedure TriangleViewInvalidate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure mnuDeleteClick(Sender: TObject);
procedure mnuAddClick(Sender: TObject);
procedure mnuDupClick(Sender: TObject);
procedure mnuAutoZoomClick(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 mnuResetLocClick(Sender: TObject);
procedure mnuFlipAllVClick(Sender: TObject);
procedure mnuFlipAllHClick(Sender: TObject);
procedure mnuFlipVerticalClick(Sender: TObject);
procedure mnuFlipHorizontalClick(Sender: TObject);
procedure cbTransformsChange(Sender: TObject);
procedure CoefKeyPress(Sender: TObject; var Key: Char);
procedure CoefValidate(Sender: TObject);
procedure scrlXFormColorScroll(Sender: TObject;
ScrollCode: TScrollCode; var ScrollPos: Integer);
procedure scrlXFormColorChange(Sender: TObject);
procedure txtXFormColorExit(Sender: TObject);
procedure txtXFormColorKeyPress(Sender: TObject; var Key: Char);
procedure txtSymmetrySet(Sender: TObject);
procedure txtSymmetrKeyPress(Sender: TObject; var Key: Char);
procedure txtDCSet(Sender: TObject);
procedure txtDCKeyPress(Sender: TObject; var Key: Char);
procedure txtOpacitySet(Sender: TObject);
procedure txtOpacityKeyPress(Sender: TObject; var Key: Char);
procedure btTrgRotateLeftClick(Sender: TObject);
procedure btTrgRotateRightClick(Sender: TObject);
procedure btTrgRotateLeft90Click(Sender: TObject);
procedure btTrgRotateRight90Click(Sender: TObject);
procedure TrgMove(dx, dy: double);
procedure btTrgMoveLeftClick(Sender: TObject);
procedure btTrgMoveRightClick(Sender: TObject);
procedure btTrgMoveUpClick(Sender: TObject);
procedure btTrgMoveDownClick(Sender: TObject);
procedure btTrgScaleUpClick(Sender: TObject);
procedure btTrgScaleDownClick(Sender: TObject);
procedure splitterMoved(Sender: TObject);
procedure tbSelectClick(Sender: TObject);
procedure EditKeyPress(Sender: TObject; var Key: Char);
procedure tbEditModeClick(Sender: TObject);
procedure ValidateVariation;
procedure VEVarsKeyPress(Sender: TObject; var Key: Char);
procedure VEVarsChange(Sender: TObject);
procedure VEVarsValidate(Sender: TObject; ACol, ARow: Integer;
const KeyName, KeyValue: String);
procedure VEVarsMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure VEVarsMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure VEVarsMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure VEVarsDblClick(Sender: TObject);
procedure cbTransformsDrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
procedure tbFullViewClick(Sender: TObject);
procedure EditKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure txtValidateValue(Sender: TObject);
procedure txtValKeyPress(Sender: TObject; var Key: Char);
procedure mnuResetTriangleClick(Sender: TObject);
procedure mnuResetAllClick(Sender: TObject);
procedure btnXcoefsClick(Sender: TObject);
procedure btnYcoefsClick(Sender: TObject);
procedure btnOcoefsClick(Sender: TObject);
procedure btnCoefsModeClick(Sender: TObject);
procedure tbVarPreviewClick(Sender: TObject);
procedure trkVarPreviewRangeChange(Sender: TObject);
procedure trkVarPreviewDensityChange(Sender: TObject);
procedure trkVarPreviewDepthChange(Sender: TObject);
procedure btnXpostClick(Sender: TObject);
procedure btnYpostClick(Sender: TObject);
procedure btnOpostClick(Sender: TObject);
procedure PostCoefValidate(Sender: TObject);
procedure PostCoefKeypress(Sender: TObject; var Key: Char);
procedure btnResetCoefsClick(Sender: TObject);
procedure btnResetPostCoefsClick(Sender: TObject);
procedure btnPivotModeClick(Sender: TObject);
procedure PivotValidate(Sender: TObject);
procedure PivotKeyPress(Sender: TObject; var Key: Char);
procedure btnResetPivotClick(Sender: TObject);
procedure btnPickPivotClick(Sender: TObject);
procedure VEVarsDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure tbEnableFinalXformClick(Sender: TObject);
procedure DragPanelMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure DragPanelMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure DragPanelMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure DragPanelDblClick(Sender: TObject);
procedure mnuResetTrgRotationClick(Sender: TObject);
procedure mnuResetTrgScaleClick(Sender: TObject);
procedure ResetAxisRotation(n: integer);
procedure ResetAxisScale(n: integer);
procedure tbExtendedEditClick(Sender: TObject);
procedure tbAxisLockClick(Sender: TObject);
procedure tbPostXswapClick(Sender: TObject);
procedure btnCopyTriangleClick(Sender: TObject);
procedure btnPasteTriangleClick(Sender: TObject);
procedure chkAutoZscaleClick(Sender: TObject);
procedure ValidateChaos;
procedure vleChaosExit(Sender: TObject);
procedure vleChaosKeyPress(Sender: TObject; var Key: Char);
procedure vleChaosValidate(Sender: TObject; ACol, ARow: Integer;
const KeyName, KeyValue: String);
procedure VleChaosDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure mnuChaosViewToClick(Sender: TObject);
procedure mnuChaosViewFromClick(Sender: TObject);
procedure mnuChaosClearAllClick(Sender: TObject);
procedure mnuChaosSetAllClick(Sender: TObject);
procedure mnuLinkPostxformClick(Sender: TObject);
procedure mnuLinkPrexformClick(Sender: TObject);
procedure chkXformSoloClick(Sender: TObject);
procedure mnuChaosRebuildClick(Sender: TObject);
procedure chkCollapseVariationsClick(Sender: TObject);
procedure chkCollapseVariablesClick(Sender: TObject);
procedure shColorMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure shColorMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure shColorMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure bClearClick(Sender: TObject);
procedure ColorBarMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure txtNameKeyPress(Sender: TObject; var Key: Char);
procedure txtNameExit(Sender: TObject);
procedure InsertPi1Click(Sender: TObject);
procedure CopyTransformClick(Sender: TObject);
procedure PasteTransformClick(Sender: TObject);
2022-03-08 12:25:51 -05:00
procedure btResetparamsClick(Sender: TObject);
procedure SpinButtonDownClick(Sender: TObject);
procedure SpinButtonUpClick(Sender: TObject);
procedure InvertMovevalue1Click(Sender: TObject);
procedure InvCurrentNumClick(Sender: TObject);
procedure btnFlipClick(Sender: TObject);
procedure btnResetFlipClick(Sender: TObject);
procedure FlipPointKeyPress(Sender: TObject; var Key: Char);
procedure FlipPointValidate(Sender: TObject);
procedure btnShowLineClick(Sender: TObject);
procedure GridComboBoxChange(Sender: TObject);
procedure MulDiv2Click(Sender: TObject);
procedure NormChaosClick(Sender: TObject);
procedure RandomizeMatrixClick(Sender: TObject);
procedure btSwapCoefsClick(Sender: TObject);
procedure CalcArcsinScaleClick(Sender: TObject);
procedure mnuFlipAllLineClick(Sender: TObject);
procedure ResetChaosClick(Sender: TObject);
procedure ChaosClearBelowClick(Sender: TObject);
procedure ClearAllAboveClick(Sender: TObject);
procedure btConjugateClick(Sender: TObject);
procedure AddContainerClick(Sender: TObject);
procedure ResetToolsDblClick(Sender: TObject);
procedure CalcCosClick(Sender: TObject);
procedure InvertXaosClick(Sender: TObject);
procedure btFlipXYClick(Sender: TObject);
procedure AffineCoefsDblClick(Sender: TObject);
procedure mnuResetTrgFlipClick(Sender: TObject);
procedure btChaosClick(Sender: TObject);
procedure mnuChangeGridClick(Sender: TObject);
procedure ExtSysMenu(var Msg: TMessage); message WM_SysCommand;
procedure TriangleOperationsClick(Sender: TObject);
procedure btnFullChaosClick(Sender: TObject);
procedure btnVarOrderClick(Sender: TObject);
procedure FormShortCut(var Msg: TWMKey; var Handled: Boolean);
procedure tbSyncTrianglesClick(Sender: TObject);
procedure SynchronizeAllClick(Sender: TObject);
procedure SyncTrianglesDrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; State: TOwnerDrawState);
procedure CopyVariationsClick(Sender: TObject);
procedure PasteVariationsClick(Sender: TObject);
procedure tbCommentClick(Sender: TObject);
procedure mnuCalcExpressionClick(Sender: TObject); // AV
procedure SaveFlameStateClick(Sender: TObject);
procedure mnuCopyChaosClick(Sender: TObject);
procedure mnuPasteChaosClick(Sender: TObject); // AV
2022-03-08 12:25:51 -05:00
private
TriangleView: TCustomDrawControl;
cmap: TColorMap;
PreviewDensity: double;
viewDragMode, viewDragged: boolean;
editMode, oldMode, widgetMode: (modeNone, modeMove, modeRotate, modeScale, modePick);
modeHack: boolean; // for mouseOverEdge...
modeKey: word;
key_handled: boolean;
updating: boolean;
MousePos: TPoint; // in screen coordinates
mouseOverTriangle, mouseOverEdge, mouseOverCorner, mouseOverWidget: integer;
mouseOverPos: TSPoint;
Widgets: array[0..3] of array [0..2] of TSPoint;
xx, xy, yx, yy: double;
varDragMode: boolean;
varDragIndex: integer;
varDragValue: double;
varDragPos, varDragOld: integer;
varMM: boolean; //hack?
pDragValue: ^double;
SelectMode, ExtendedEdit, AxisLock: boolean;
showVarPreview: boolean;
ShowFlipLine: boolean; // AV
hasLinkX: boolean; // AV
SyncTriangles: set of 0..NXFORMS; // AV: to change several triangles at time
2022-03-08 12:25:51 -05:00
GraphZoom: double;
TriangleCaught, CornerCaught, EdgeCaught: boolean;
LocalAxisLocked: boolean;
oldSelected: integer;
SelectedCorner: integer;
HasChanged: boolean;
oldTriangle: TTriangle;
gCenterX: double;
gCenterY: double;
MemTriangle: TTriangle;
oldx, oldy, olddist: double;
Pivot, FlipPoint, fl: TSPoint;
// hack: to prevent slow valuelist redraw
VarsCache: array of double; // AV: now length is sets dynamically
MemChaos: array of double; // AV
2022-03-08 12:25:51 -05:00
BackgroundBmp : TBitmap;
Renderer : TRenderThread;
pnlDragMode: boolean;
pnlDragPos, pnlDragOld: integer;
pnlDragValue: double;
LastFocus: TEdit;
procedure UpdateFlameX;
procedure UpdateFlame(DrawMain: boolean);
procedure UpdateWidgets;
procedure UpdateXformsList;
procedure UpdateVariationList; // AV
procedure DeleteTriangle(t: integer);
function GetPivot: TSPoint; overload;
function GetPivot(n: integer): TSPoint; overload;
procedure ShowSelectedInfo;
procedure Scale(var fx, fy: double; x, y: integer);
procedure RotateTriangleBy(const angle: double); // AV
2022-03-08 12:25:51 -05:00
procedure TriangleViewPaint(Sender: TObject);
procedure AutoZoom;
procedure KeyInput(str: string);
procedure CalcFlip;
function ValidNumField: boolean; inline; // AV: check active control
// AV: methods to synchronize tranformations of triangles
procedure FillSyncTrianglesMenu;
procedure AdjustSyncTriangles;
procedure SyncTrianglesClick(Sender: TObject);
procedure UpdateSyncTriangles;
2022-03-08 12:25:51 -05:00
public
cp: TControlPoint;
Render: TRenderer;
// Accessible from scripter
SelectedTriangle: integer; // outside only for scripting
PivotMode: (pivotLocal, pivotWorld);
LocalPivot, WorldPivot: TSPoint;
procedure UpdatePreview;
procedure UpdateDisplay(PreviewOnly: boolean = false);
2022-03-08 12:25:51 -05:00
function GetTriangleColor(n: integer): TColor;
function LastTriangle: integer;
function InsideTriangle(x, y: double): integer;
procedure ScriptGetPivot(var px, py: double);
2022-03-08 12:25:51 -05:00
procedure UpdateColorBar;
procedure PaintBackground;
procedure CreateScreenShot;
2022-03-08 12:25:51 -05:00
procedure RedrawButtons;
end;
const
{TrgColors: array[-1..13] of TColor = (clGray,
$0000ff, $00ffff, $00ff00, $ffff00, $ff0000, $ff00ff, $007fff,
$7f00ff, $55ffff, $ccffcc, $ffffaa, $ff7f7f, $ffaaff, $55ccff );}
TrgColors: array[-1..13] of TColor = (clGray,
$0000ff, $00cccc, $00cc00, $cccc00, $ff4040, $cc00cc, $0080cc,
$4f0080, $228080, $608060, $808050, $804f4f, $805080, $226080 );
saved_variations = 'Variations.list';
saved_variables = 'Variables.list';
2022-03-08 12:25:51 -05:00
var
EditForm: TEditForm;
function ColorValToColor(c: TColorMap; index: double): TColor;
2022-03-08 12:25:51 -05:00
function FlipTriangleVertical(t: TTriangle): TTriangle;
function FlipTriangleHorizontal(t: TTriangle): TTriangle;
function RotateTriangle(t: TTriangle; rad: double): TTriangle;
function ScaleTriangle(t: TTriangle; scale: double): TTriangle;
function RotateTrianglePoint(t: TTriangle; xr, yr: double; rad: double): TTriangle;
function ScaleTrianglePoint(t: TTriangle; x, y, scale: double): TTriangle;
{
2022-03-08 12:25:51 -05:00
function Centroid(t: TTriangle): TSPoint;
function RotateTriangleCenter(t: TTriangle; rad: double): TTriangle;
2022-03-08 12:25:51 -05:00
function ScaleTriangleCenter(t: TTriangle; scale: double): TTriangle;
function OffsetTriangle(t: TTriangle; range: double): TTriangle;
function OffsetTriangleRandom(t: TTriangle): TTriangle;
}
2022-03-08 12:25:51 -05:00
// AV: new operations
function ScaleTriangleXY(t: TTriangle; axis: integer; scale: double): TTriangle;
function ScaleTriangleO(t: TTriangle; x, y, scale: double): TTriangle;
function RotateTriangleO(t: TTriangle; x, y, rad: double): TTriangle;
function RotateTriangleXY(t: TTriangle; axis: integer; rad: double): TTriangle;
function FlipTriangleLine(t: TTriangle; x, y, fx, fy: double): TTriangle;
implementation
uses
Main, Global, Adjust, Mutate, XformMan, Translation,
Chaos, VarOrderForm, FlameComment, MathExpressions;
2022-03-08 12:25:51 -05:00
{$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 FlipTriangleLine(t: TTriangle; x, y, fx, fy: double): TTriangle; // AV
var
N: TSpoint;
N2: double;
begin
N.x := fy - y;
N.y := -(fx - x);
N2 := 2 / (N.x * N.x + N.y * N.y);
Result.x[0] := t.x[0] - N2 *((t.x[0] - x) * N.x + (t.y[0] - y) * N.y)* N.x;
Result.y[0] := t.y[0] - N2 *((t.x[0] - x) * N.x + (t.y[0] - y) * N.y)* N.y;
Result.x[1] := t.x[1] - N2 *((t.x[1] - x) * N.x + (t.y[1] - y) * N.y)* N.x;
Result.y[1] := t.y[1] - N2 *((t.x[1] - x) * N.x + (t.y[1] - y) * N.y)* N.y;
Result.x[2] := t.x[2] - N2 *((t.x[2] - x) * N.x + (t.y[2] - y) * N.y)* N.x;
Result.y[2] := t.y[2] - N2 *((t.x[2] - x) * N.x + (t.y[2] - y) * N.y)* N.y;
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 ScaleTriangleXY(t: TTriangle; axis: integer; scale: double): TTriangle; // AV
begin
Result := t;
if scale < 1e-64 then Exit;
Result.x[axis] := scale * (t.x[axis] - t.x[1]) + t.x[1];
Result.y[axis] := scale * (t.y[axis] - t.y[1]) + t.y[1];
end;
function ScaleTriangleO(t: TTriangle; x, y, scale: double): TTriangle; // AV
begin
Result.x[1] := scale * (t.x[1] - x) + x;
Result.y[1] := scale * (t.y[1] - y) + y;
Result.x[0] := t.x[0] - t.x[1] + Result.x[1];
Result.y[0] := t.y[0] - t.y[1] + Result.y[1];
Result.x[2] := t.x[2] - t.x[1] + Result.x[1];
Result.y[2] := t.y[2] - t.y[1] + Result.y[1];
end;
function RotateTriangleO(t: TTriangle; x, y, rad: double): TTriangle;
begin
Result.x[1] := x + (t.x[1] - x) * cos(rad) - (t.y[1] - y) * sin(rad);
Result.y[1] := y + (t.x[1] - x) * sin(rad) + (t.y[1] - y) * cos(rad);
Result.x[0] := t.x[0] - t.x[1] + Result.x[1];
Result.y[0] := t.y[0] - t.y[1] + Result.y[1];
Result.x[2] := t.x[2] - t.x[1] + Result.x[1];
Result.y[2] := t.y[2] - t.y[1] + Result.y[1];
end;
function RotateTriangleXY(t: TTriangle; axis: integer; rad: double): TTriangle; // AV
begin
Result := t;
Result.x[axis] := t.x[1] + (t.x[axis] - t.x[1]) * cos(rad) - (t.y[axis] - t.y[1]) * sin(rad);
Result.y[axis] := t.y[1] + (t.x[axis] - t.x[1]) * sin(rad) + (t.y[axis] - t.y[1]) * cos(rad);
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
assert(scale <> 0);
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 ScaleTrianglePoint(t: TTriangle; x, y, scale: double): TTriangle;
begin
//assert(scale <> 0);
if scale = 0 then scale := 1e-64;
Result.y[0] := scale * (t.y[0] - y) + y;
Result.y[1] := scale * (t.y[1] - y) + y;
Result.y[2] := scale * (t.y[2] - y) + y;
Result.x[0] := scale * (t.x[0] - x) + x;
Result.x[1] := scale * (t.x[1] - x) + x;
Result.x[2] := scale * (t.x[2] - x) + x;
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;
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; xr, yr: double; rad: double): TTriangle;
var
i: integer;
begin
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);
assert(i >= 0);
assert(i < 256);
result := c[i][2] shl 16 + c[i][1] shl 8 + c[i][0];
end;
procedure TEditForm.UpdatePreview;
var
pw, ph: integer;
begin
pw := PrevPnl.Width -2;
ph := PrevPnl.Height -2;
if (cp.width / cp.height) > (pw / ph) then
begin
PreviewImage.Width := pw;
assert(pw <> 0);
PreviewImage.Height := round(cp.height / cp.Width * pw);
PreviewImage.Left := 1;
PreviewImage.Top := (ph - PreviewImage.Height) div 2;
end
else begin
PreviewImage.Height := ph;
assert(ph <> 0);
PreviewImage.Width := round(cp.Width / cp.Height * ph);
PreviewImage.Top := 1;
PreviewImage.Left := (pw - PreviewImage.Width) div 2;
end;
cp.AdjustScale(PreviewImage.Width, PreviewImage.Height);
DrawPreview;
TriangleViewPaint(TriangleView);
end;
procedure TEditForm.UpdateVariationList; // AV: adjust the var_order
var
s: string;
2022-03-08 12:25:51 -05:00
svars: TStringList;
begin
svars := TStringList.Create;
with cp.xform[SelectedTriangle] do
for s in ifs do
svars.AddPair(s, Round6(GetVariation(GetVariationIndex(s))).ToString);
2022-03-08 12:25:51 -05:00
VEVars.Strings.Assign(svars);
svars.Free;
end;
procedure TEditForm.UpdateXformsList;
var
i, n: integer;
prefix: string;
begin
cbTransforms.Clear;
for i := 1 to Transforms do begin
cbTransforms.Items.Add(IntToStr(i));
end;
if EnableFinalXform or cp.HasFinalXForm then
cbTransforms.Items.Add(TextByKey('editor-common-finalxformlistitem'));
cbTransforms.ItemIndex := SelectedTriangle;
if mnuChaosViewTo.Checked then prefix := TextByKey('editor-common-toprefix')
else prefix := TextByKey('editor-common-fromprefix');
n := Transforms + 1;
while vleChaos.RowCount > n do
vleChaos.DeleteRow(vleChaos.RowCount-1);
while vleChaos.RowCount < n do
vleChaos.InsertRow(Format(prefix, [vleChaos.RowCount]), '1', true);
UpdateVariationList; // AV
chkCollapseVariablesClick(nil);
chkCollapseVariationsClick(nil);
FillSyncTrianglesMenu; // AV
if (SelectedTriangle < Transforms) and (SelectedTriangle >= 0) then
begin
mnuSyncTriangles.Items[SelectedTriangle].Checked := True;
SyncTriangles := [SelectedTriangle];
end
else
SyncTriangles := [];
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.UpdateDisplay(PreviewOnly: boolean = false);
begin
// currently EditForm does not really know if we select another
// flame in the Main Window - which is not good...
cp.copy(MainCp);
if SelectedTriangle > LastTriangle{???} then
begin
SelectedTriangle := cp.NumXForms-1;
mouseOverTriangle := -1;
end;
EnableFinalXform := cp.finalXformEnabled;
tbEnableFinalXform.Down := EnableFinalXform;
UpdatePreview;
if PreviewOnly then exit;
cp.cmap := MainCp.cmap;
cmap := MainCp.cmap;
UpdateXformsList;
UpdateColorBar;
UpdateVariationList; // AV
// just in case:
SetCaptureControl(nil);
HasChanged := false;
// viewDragMode := false;
varDragMode := false;
pnlDragMode := false;
CornerCaught := false;
EdgeCaught := false;
TriangleCaught := false;
cp.TrianglesFromCP(MainTriangles);
ShowSelectedInfo;
if MainForm.UndoIndex = 0 then AutoZoom // auto-zoom only on 'new' flame
else TriangleView.Invalidate;
end;
procedure TEditForm.DrawPreview;
begin
if EnableEditorPreview then exit;
//Render.Stop;
cp.sample_density := PreviewDensity;
cp.spatial_oversample := defOversample;
cp.spatial_filter_radius := defFilterRadius;
if mnuResetLoc.checked then
begin
cp.zoom := 0;
cp.CalcBoundbox;
end;
cp.cmap := MainCp.cmap;
Render.SetCP(cp);
Render.Render;
PreviewImage.Picture.Bitmap.Assign(Render.GetImage);
PreviewImage.refresh;
end;
procedure TEditForm.ShowSelectedInfo;
var
i: integer;
v: double;
strval: string;
begin
updating := true;
if (SelectedTriangle > LastTriangle) then
SelectedTriangle := LastTriangle;
for i := 0 to Transforms - 1 do
begin
// AV: it's technically impossible inside this loop
{
if (i >= Transforms) then begin
if (cbTransforms.Items.Count > Transforms) then
cbTransforms.Items[i] := TextByKey('editor-common-finalxformlistitem');
end else begin
n := i + 1;
}
if (cp.xform[i].TransformName <> '') then
cbTransforms.Items[i] := IntToStr(i + 1) + ' - ' + cp.xform[i].TransformName
else
cbTransforms.Items[i] := IntToStr(i + 1);
// end;
end;
cbTransforms.ItemIndex := SelectedTriangle;
cbTransforms.Refresh;
with MainTriangles[SelectedTriangle] do
begin
txtAx.text := Format('%.6g', [x[0]]);
txtAy.text := Format('%.6g', [y[0]]);
txtBx.text := Format('%.6g', [x[1]]);
txtBy.text := Format('%.6g', [y[1]]);
txtCx.text := Format('%.6g', [x[2]]);
txtCy.text := Format('%.6g', [y[2]]);
end;
with cp.xform[SelectedTriangle] do
begin
if btnCoefsRect.Down then begin
txtA.text := Format('%.6g', [ c[0][0]]);
txtB.text := Format('%.6g', [-c[0][1]]);
txtC.text := Format('%.6g', [-c[1][0]]);
txtD.text := Format('%.6g', [ c[1][1]]);
txtE.text := Format('%.6g', [ c[2][0]]);
txtF.text := Format('%.6g', [-c[2][1]]);
txtPost00.text := Format('%.6g', [ p[0][0]]);
txtPost01.text := Format('%.6g', [-p[0][1]]);
txtPost10.text := Format('%.6g', [-p[1][0]]);
txtPost11.text := Format('%.6g', [ p[1][1]]);
txtPost20.text := Format('%.6g', [ p[2][0]]);
txtPost21.text := Format('%.6g', [-p[2][1]]);
end
else begin
txtA.text := Format('%.6g', [Hypot(c[0][0], c[0][1])]);
txtB.text := Format('%.6g', [arctan2(-c[0][1], c[0][0])*180/PI]);
txtC.text := Format('%.6g', [Hypot(c[1][0], c[1][1])]);
txtD.text := Format('%.6g', [arctan2(c[1][1], -c[1][0])*180/PI]);
txtE.text := Format('%.6g', [Hypot(c[2][0], c[2][1])]);
txtF.text := Format('%.6g', [arctan2(-c[2][1], c[2][0])*180/PI]);
txtPost00.text := Format('%.6g', [Hypot(p[0][0], p[0][1])]);
txtPost01.text := Format('%.6g', [arctan2(-p[0][1], p[0][0])*180/PI]);
txtPost10.text := Format('%.6g', [Hypot(p[1][0], p[1][1])]);
txtPost11.text := Format('%.6g', [arctan2(p[1][1], -p[1][0])*180/PI]);
txtPost20.text := Format('%.6g', [Hypot(p[2][0], p[2][1])]);
txtPost21.text := Format('%.6g', [arctan2(-p[2][1], p[2][0])*180/PI]);
end;
tbPostXswap.Down := postXswap;
tb2PostXswap.Down := postXswap;
CalcFlip; // AV
if postXswap then begin // AV: simplified
GroupBox9.Font.Style := [];
GroupBox8.Font.Style := [fsBold];
end
else begin
GroupBox8.Font.Style := [];
GroupBox9.Font.Style := [fsBold];
end;
chkAutoZscale.Checked := autoZscale;
txtName.Text := TransformName;
if (SelectedTriangle >= Transforms) then
begin
txtName.Text := 'n/a';
end;
if SelectedTriangle < Transforms then
begin
txtP.text := Format('%.6g', [density]);
txtP.Enabled := true;
txtName.Enabled := true;
vleChaos.Enabled := true;
optTo.Enabled := True; // AV
optFrom.Enabled := True; // AV
//chkXformInvisible.Enabled := true;
//chkXformInvisible.Checked := (transOpacity = 0);
chkXformSolo.Enabled := true;
txtOpacity.Enabled := true;
txtDC.Enabled := true;
btChaos.Visible := True; // AV
btClearChaos.Visible := True; // AV
btResetChaos.Visible := True; // AV
CopyChaos.Enabled := True; // AV
PasteChaos.Enabled := length(MemChaos) <> 0; // AV
2022-03-08 12:25:51 -05:00
if cp.soloXform >= 0 then begin
chkXformSolo.Checked := true;
chkXformSolo.Caption := Format(TextByKey('editor-tab-color-togglesoloformat'), [cp.soloXform + 1]);
end
else begin
chkXformSolo.Checked := false;
chkXformSolo.Caption := TextByKey('editor-tab-color-togglesolo');
end;
end
else begin // disable controls for FinalXform
txtP.Enabled := false;
txtP.Text := 'n/a';
txtName.Enabled := false;
vleChaos.Enabled := false;
btChaos.Visible := False; // AV
btClearChaos.Visible := False; // AV
btResetChaos.Visible := False; // AV
CopyChaos.Enabled := False; // AV
PasteChaos.Enabled := False; // AV
2022-03-08 12:25:51 -05:00
optTo.Enabled := False; // AV
optFrom.Enabled := False; // AV
//chkXformInvisible.Enabled := false;
//chkXformInvisible.Checked := false;
txtOpacity.Enabled := false;
chkXformSolo.Enabled := false;
end;
tbEnableFinalXform.Down := EnableFinalXform;
txtSymmetry.text := Format('%.6g', [symmetry]);
txtOpacity.text := Format('%.6g', [transOpacity]);
txtDC.Text := Format('%.6g', [pluginColor]);
pnlXFormColor.Color := ColorValToColor(cp.cmap, color);
shColor.Brush.Color := pnlXformColor.Color;
txtXFormColor.Text := Format('%1.3f', [color]);
scrlXFormcolor.Position := Trunc(color * scrlXFormColor.Max);
for i := 0 to NRVAR-1 do begin
v := GetVariation(i);
if v <> VarsCache[i] then
begin
VarsCache[i] := v;
VEVars.Values[VarNames(i)] := Format('%.6g', [v]);
end;
end;
for i:= 0 to GetNrVariableNames - 1 do begin
{$ifndef VAR_STR}
GetVariable(GetVariableNameAt(i), v);
strval := Format('%.6g', [v]);
{$else}
strval := GetVariableStr(GetVariableNameAt(i));
{$endif}
// kinda funny, but it really helped...
if vleVariables.Values[GetVariableNameAt(i)] <> strval then
vleVariables.Values[GetVariableNameAt(i)] := strval;
end;
//Assert(vleChaos.RowCount = Transforms+1);
if SelectedTriangle < Transforms then begin
if mnuChaosViewTo.Checked then
// view as "to" values
for i := 1 to Transforms do begin
strval := Format('%.6g', [modWeights[i - 1]]);
if vleChaos.Cells[1, i] <> strval then
vleChaos.Cells[1, i] := strval;
end
else
// view as "from" values
for i := 1 to Transforms do begin
strval := Format('%.6g', [cp.xform[i - 1].modWeights[SelectedTriangle]]);
if vleChaos.Cells[1, i] <> strval then
vleChaos.Cells[1, i] := strval;
end;
end
else
for i := 1 to vleChaos.RowCount-1 do
vleChaos.Cells[1, i] := 'n/a';
end;
//AV: moved checks here since Apo7X didn't refresh these pages well
// if cbCollapseVariations.ItemIndex = 1 then
2022-03-08 12:25:51 -05:00
chkCollapseVariationsClick(nil);
chkCollapseVariablesClick(nil);
if PivotMode = pivotLocal then begin
editPivotX.Text := Format('%.6g', [LocalPivot.x]);
editPivotY.Text := Format('%.6g', [LocalPivot.y]);
btnPivotMode.Caption := TextByKey('editor-tab-triangle-modelocal');
btnPivotMode.Hint := TextByKey('editor-tab-triangle-toworld');
tbPivotMode.Down := false;
end
else begin
editPivotX.Text := Format('%.6g', [WorldPivot.x]);
editPivotY.Text := Format('%.6g', [WorldPivot.y]);
btnPivotMode.Caption := TextByKey('editor-tab-triangle-modeworld');
btnPivotMode.Hint := TextByKey('editor-tab-triangle-tolocal');
tbPivotMode.Down := true;
end;
PageControl.Refresh;
updating := false;
end;
{/////////////////////////////////////////////////// }
procedure TEditForm.FillSyncTrianglesMenu; // AV
var
i: byte;
t: TMenuItem;
pic: TBitMap;
defStyle: boolean;
begin
mnuSyncTriangles.Items.Clear;
pic := TBitmap.Create;
pic.Width := 16;
pic.Height := 16;
if (CurrentStyle = 'Windows') then
begin
pic.Transparent := True;
pic.TransparentColor := clWhite;
defStyle := True;
end
else
defStyle := False;
for i := 0 to Transforms - 1 do
begin
t := TMenuItem.Create(self);
t.Caption := IntToStr(i + 1);
t.Tag := i;
t.AutoCheck := True;
with pic.Canvas do
begin
brush.Color := clWhite;
FillRect(Rect(0, 0, 16, 16));
pen.Color := TrgColors[i mod 14];
brush.Color := pen.Color shr 1 and $7f7f7f;
Polygon([Point(15, 5), Point(15, 15), Point(5, 15)]);
end;
t.Bitmap.Assign(pic);
t.OnClick := SyncTrianglesClick;
if defStyle then
t.OnAdvancedDrawItem := SyncTrianglesDrawItem
else
// AV: it's better to rely on RTL rather than adjust colors for every theme manually
t.OnAdvancedDrawItem := nil;
mnuSyncTriangles.Items.Add(t);
end;
pic.Free;
i := 0;
while i < mnuSyncTriangles.Items.Count do
begin
mnuSyncTriangles.Items[i].Break := mbBreak;
inc(i, mbHeight);
end;
end;
procedure TEditForm.SynchronizeAllClick(Sender: TObject);
var i: smallint;
begin
for i := 0 to mnuSyncTriangles.Items.Count - 1 do
begin
mnuSyncTriangles.Items[i].Checked := True;
Include(SyncTriangles, i);
end;
end;
procedure TEditForm.SyncTrianglesClick(Sender: TObject); // AV
begin
if (SelectedTriangle < Transforms) and
(Sender = mnuSyncTriangles.Items[SelectedTriangle]) then
TMenuItem(Sender).Checked := True;
if TMenuItem(Sender).Checked then
Include(SyncTriangles, TMenuItem(Sender).Tag)
else
Exclude(SyncTriangles, TMenuItem(Sender).Tag);
end;
procedure TEditForm.SyncTrianglesDrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; State: TOwnerDrawState);
begin
ACanvas.Draw(ARect.Left + 10, ARect.Top, TMenuItem(Sender).Bitmap);
if not (odSelected in State) then
begin
ACanvas.Brush.Color := clMenu;
ACanvas.Font.Color := clMenuText;
end;
if TMenuItem(Sender).Tag = SelectedTriangle then
ACanvas.Font.Style := [fsBold];
ACanvas.TextOut(ARect.Left + 30, ARect.Top + 2, TMenuItem(Sender).Caption);
if (odChecked in State) then
DrawCheck(ACanvas, Point(ARect.Left + 5, ARect.Top + 10), 3);
end;
{/////////////////////////////////////////////////// }
2022-03-08 12:25:51 -05:00
procedure TEditForm.CreateScreenShot;
begin
SaveScreenShot('Apophysis Transform Editor');
end;
procedure TEditForm.ExtSysMenu(var Msg: TMessage);
begin
if Msg.WParam = $C0 then CreateScreenShot;
inherited;
end;
{ /////////////// AV: arrow buttons for all num fields //////////////// }
procedure TEditForm.SpinButtonDownClick(Sender: TObject);
var
step, n: double;
ANumEdit: TEdit;
begin
step := 0.01;
if GetKeyState(VK_MENU) < 0 then step := 0.000001 // Alt
else if GetKeyState(VK_CONTROL) < 0 then step := 0.0001
else if GetKeyState(VK_SHIFT) < 0 then step := 0.1;
try
ANumEdit := TEdit((Sender as TSpinButton).FocusControl);
n := StrToFloat(ANumEdit.Text);
ANumEdit.Text := Format('%.6g', [n - step]);
ANumEdit.OnExit(ANumEdit);
except
// do nothing
end;
end;
procedure TEditForm.SpinButtonUpClick(Sender: TObject);
var
step, n: double;
ANumEdit: TEdit;
begin
step := 0.01;
if GetKeyState(VK_MENU) < 0 then step := 0.000001 // Alt
else if GetKeyState(VK_CONTROL) < 0 then step := 0.0001
else if GetKeyState(VK_SHIFT) < 0 then step := 0.1;
try
ANumEdit := TEdit((Sender as TSpinButton).FocusControl);
n := StrToFloat(ANumEdit.Text);
ANumEdit.Text := Format('%.6g', [n + step]);
ANumEdit.OnExit(ANumEdit);
except
// do nothing
end;
end;
{ ////////////////////////////////////////////////////////////////// }
procedure TEditForm.Scale(var fx, fy: double; x, y: integer);
var
sc: double;
begin
sc := 50 * GraphZoom;
fx := (x - (TriangleView.Width / 2)) / sc + gCenterX;
fy := -((y - (TriangleView.Height / 2)) / sc - gCentery);
end;
procedure TEditForm.AddContainerClick(Sender: TObject);
var
i: integer;
sumw: double;
begin
if (Transforms < NXFORMS) then
begin
MainForm.UpdateUndo;
MainTriangles[Transforms + 1] := MainTriangles[Transforms];
cp.xform[Transforms + 1].Assign(cp.xform[Transforms]);
MainTriangles[Transforms] := MainTriangles[-1];
for i := 0 to Transforms-1 do
cp.xform[i].TransOpacity := 0;
cp.xform[Transforms].Clear;
cp.xform[Transforms].symmetry := 1;
cp.xform[Transforms].SetVariation(0, 1);
cp.xform[Transforms].modWeights[Transforms] := 0;
if InheritWeights.Checked then begin
sumw := 0;
for i := 0 to Transforms-1 do
sumw := sumw + cp.xform[i].density;
cp.xform[Transforms].density := sumw;
end else
cp.xform[Transforms].density := 0.5;
SelectedTriangle := Transforms;
cp.xform[SelectedTriangle].TransformName := 'Container TX';
Inc(Transforms);
UpdateXformsList;
UpdateFlame(True);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
end;
procedure TEditForm.AffineCoefsDblClick(Sender: TObject); // AV
var
num: string;
begin
if not AllowResetCoefs then exit;
with TEdit(Sender) do // restore defaults
begin
if (Parent = gbCoordinates) or btnCoefsRect.Down then
2022-03-08 12:25:51 -05:00
num := IntToStr(Tag)
else // if btnCoefsPolar.Down then
begin
if (Left = 36) and (Top < 65) then // hack...
num := '1'
else if (Tag = 1) then
num := '90'
else num := '0';
end;
if Text <> num then
begin
Text := num;
OnExit(Sender);
end;
end;
end;
procedure TEditForm.AutoZoom;
var
i, j: integer;
xminz, yminz, xmaxz, ymaxz: double;
gxlength, gylength: double;
begin
xminz := 0;
yminz := 0;
xmaxz := 0;
ymaxz := 0;
for i := -1 to LastTriangle 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
GraphZoom := TriangleView.Width / 60 / gxlength
else
GraphZoom := TriangleView.Height / 60 / gylength;
EditForm.StatusBar.Panels[2].Text := Format(TextByKey('editor-status-zoomformat'), [GraphZoom]);
TriangleView.Invalidate;//Refresh;
end;
procedure TEditForm.UpdateFlameX;
begin
cp.GetFromTriangles(MainTriangles, Transforms);
if tbAutoWeights.Down then cp.CalculateWeights; //cp.ComputeWeights(MainTriangles, Transforms);
DrawPreview;
ShowSelectedInfo;
TriangleView.Refresh;
end;
procedure TEditForm.UpdateFlame(DrawMain: boolean);
begin
StatusBar.Panels[2].Text := Format(TextByKey('editor-status-zoomformat'), [GraphZoom]);
cp.GetFromTriangles(MainTriangles, LastTriangle);
DrawPreview;
ShowSelectedInfo;
TriangleView.Refresh;
if DrawMain then begin
MainForm.StopThread;
MainCp.Copy(cp, true);
MainCp.cmap := cmap;
if mnuResetLoc.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;
// AV: following is included into ShowSelectedInfo
//chkCollapseVariablesClick(nil);
//chkCollapseVariationsClick(nil);
end;
procedure TEditForm.UpdateWidgets;
function Point(x, y: double): TSPoint;
begin
Result.x := x;
Result.y := y;
end;
begin
with mainTriangles[Selectedtriangle] do
begin
xx := x[0] - x[1];
xy := y[0] - y[1];
yx := x[2] - x[1];
yy := y[2] - y[1];
Widgets[0][0] := Point(x[1] + 0.8*xx + yx, y[1] + 0.8*xy + yy);
Widgets[0][1] := Point(x[1] + xx + yx, y[1] + xy + yy);
Widgets[0][2] := Point(x[1] + xx + 0.8*yx, y[1] + xy + 0.8*yy);
Widgets[1][0] := Point(x[1] - 0.8*xx + yx, y[1] - 0.8*xy + yy);
Widgets[1][1] := Point(x[1] - xx + yx, y[1] - xy + yy);
Widgets[1][2] := Point(x[1] - xx + 0.8*yx, y[1] - xy + 0.8*yy);
Widgets[2][0] := Point(x[1] - 0.8*xx - yx, y[1] - 0.8*xy - yy);
Widgets[2][1] := Point(x[1] - xx - yx, y[1] - xy - yy);
Widgets[2][2] := Point(x[1] - xx - 0.8*yx, y[1] - xy - 0.8*yy);
Widgets[3][0] := Point(x[1] + 0.8*xx - yx, y[1] + 0.8*xy - yy);
Widgets[3][1] := Point(x[1] + xx - yx, y[1] + xy - yy);
Widgets[3][2] := Point(x[1] + xx - 0.8*yx, y[1] + xy - 0.8*yy);
end;
end;
procedure TEditForm.DeleteTriangle(t: integer);
var
i, j, nmin, nmax: integer;
lx, ps: integer;
txname: string;
begin
if (t = Transforms) then
begin
assert(cp.HasFinalXForm or EnableFinalXform);
MainForm.UpdateUndo;
EnableFinalXform := false;
cp.finalXformEnabled := false;
cp.xform[Transforms].Clear;
cp.xform[Transforms].symmetry := 1;
assert(cp.HasFinalXForm = false);
MainTriangles[Transforms] := MainTriangles[-1];
tbEnableFinalXform.Down := false;
if (SelectedTriangle = Transforms) then Dec(SelectedTriangle);
end
else
if (Transforms <= 1) then exit
else begin
MainForm.UpdateUndo;
for i := 0 to Transforms-1 do
begin
if (pos('link', cp.xform[i].TransformName) > 0) then
begin
// AV: correcting the numbers in linked transforms' names
if i = t then continue;
txname := cp.xform[i].TransformName;
ps := pos('TX ', txname) + 3;
txname := copy(txname, ps, length(txname) - ps + 1);
try // if user didn't change the original name
lx := StrToInt(txname) - 1;
if (lx = t) then cp.xform[i].TransformName := ''
else if (lx > t) then
cp.xform[i].TransformName := copy(cp.xform[i].TransformName, 1, ps - 1) + IntToStr(lx);
except
// leave the name as is
end;
end;
end;
if RebuildXaosLinks then begin
// check for single "to" links
for i := 0 to NXFORMS-1 {Transforms-1} do
with cp.xform[i] do begin
nmin := NXFORMS;
nmax := -1;
for j := 0 to NXFORMS-1 {Transforms-1} do
if modWeights[j] <> 0 then begin
if j < nmin then nmin := j;
if j > nmax then nmax := j;
end;
if (nmin = nmax) and (nmin = t) then begin
for j := 0 to NXFORMS-1 {Transforms-1} do
modWeights[j] := cp.xform[t].modWeights[j];
if (transOpacity = 0) then begin
transOpacity := cp.xform[t].transOpacity;
end;
end;
end;
// check for single "from" links
for i := 0 to NXFORMS-1 {Transforms-1} do
begin
if cp.xform[t].modWeights[i] = 0 then continue;
nmin := NXFORMS;
nmax := -1;
for j := 0 to NXFORMS-1 {Transforms-1} do
if cp.xform[j].modWeights[i] <> 0 then begin
if j < nmin then nmin := j;
if j > nmax then nmax := j;
end;
if (nmin = nmax) and (nmin = t) then begin
for j := 0 to NXFORMS-1 {Transforms-1} do
cp.xform[j].modWeights[i] := cp.xform[t].modWeights[i];
end;
end;
if pos('Container TX', cp.xform[t].TransformName) > 0 then
for i := 0 to t-1 do
if (cp.xform[t].transOpacity = 0) then
cp.xform[t].transOpacity := 1;
end;
// delete xform from all probability tables
for i := 0 to NXFORMS-1 {Transforms-1} do
with cp.xform[i] do begin
for j := t to NXFORMS-1 {Transforms-1} do
modWeights[j] := modWeights[j+1];
modWeights[Transforms-1] := 1;
end;
if t = (Transforms - 1) then
begin
MainTriangles[t] := MainTriangles[Transforms];
cp.xform[t].Assign(cp.xform[Transforms]);
Dec(SelectedTriangle);
end
else begin
for i := t to Transforms-1 do // was: -2
begin
{ copy higher transforms down }
MainTriangles[i] := MainTriangles[i + 1];
cp.xform[i].Assign(cp.xform[i + 1]);
end;
end;
if cp.soloXform > t then Dec(cp.soloXform)
else if cp.soloXform = t then cp.soloXform := -1;
Dec(Transforms);
assert(cp.xform[transforms].density = 0); // cp.xform[transforms].density := 0;
end;
UpdateXformsList;
UpdateFlame(True);
end;
procedure TEditForm.InsertPi1Click(Sender: TObject);
var
num: double;
sn: string;
begin
if (not ValidNumField) then
begin
Application.MessageBox(PChar(TextByKey('editor-status-nonumfield')),
ApophysisSVN, MB_ICONWARNING);
2022-03-08 12:25:51 -05:00
exit;
end
else if (ActiveControl = txtTrgRotateValue) then exit;
case TMenuItem(Sender).Tag of
0: num := 3.14159265358979; // pi;
1: num := 6.28318530717959; // 2 * pi;
2: num := 1.5707963267949; // pi * 0.5;
3: num := 1.0471975511966; // pi/3;
4: num := 0.785398163397448; // pi * 0.25;
5: num := 0.523598775598299; // pi/6;
6: num := 0.288675134594813; // sqrt(3)/6;
7: num := 0.707106781186548; // sqrt(2) * 0.5;
8: num := 0.866025403784439; // sqrt(3) * 0.5;
9: num := 0.577350269189626; // sqrt(3)/3;
10: num := 1.73205080756888; // sqrt(3);
11: num := 0.618033988749895; // (sqrt(5)- 1) * 0.5;
else num := 0;
end;
if (ActiveControl = txtTrgScaleValue) then num := num * 100;
sn := Format('%.6g', [num]);
if (ActiveControl is TEdit) then
begin
TEdit(ActiveControl).Text := sn;
TEdit(ActiveControl).OnExit(ActiveControl);
end else if (ActiveControl is TValueListEditor) then
begin
TValueListEditor(ActiveControl).Cells[1, TValueListEditor(ActiveControl).Row] := sn;
TValueListEditor(ActiveControl).OnExit(ActiveControl);
end
else // if (ActiveControl is TComboBox) then
TComboBox(ActiveControl).Text := sn;
end;
function TEditForm.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 := LastTriangle downto 0 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 TEditForm.GetTriangleColor(n: integer): TColor;
begin
if n = Transforms then Result := clWhite
else
if UseTransformColors then
Result := ColorValToColor(MainCp.cmap, cp.xform[n].color)
else Result := TrgColors[n mod 14];
end;
procedure TEditForm.GridComboBoxChange(Sender: TObject);
begin
if tbVarPreview.Down then
TriangleView.Invalidate;
end;
procedure TEditForm.ResetToolsDblClick(Sender: TObject);
begin
RotateXYO.Checked := True;
ScaleXYO.Checked := True;
ShowModvals.Checked := False;
mnuChangeGridClick(RectGrid);
txtTrgRotateValue.Text := '15';
txtTrgScaleValue.Text := '125';
txtTrgMoveValue.Text := '0.1';
end;
procedure TEditForm.RedrawButtons;
begin
if IsLightMenu then
btnMathPopup.ImageIndex := 42 // white PI
else
btnMathPopup.ImageIndex := 32; // black PI
end;
function TEditForm.LastTriangle: integer;
begin
if EnableFinalXform or cp.HasFinalXForm then Result := Transforms
else Result := Transforms-1;
end;
procedure TEditForm.CalcFlip;
var ang: double;
begin
if (PivotMode = pivotLocal) or (mouseOverEdge >= 0) then
with MainTriangles[SelectedTriangle] do begin
fl.x := (x[0] - x[1]) * (FlipPoint.x - LocalPivot.x) + (x[2] - x[1]) * (FlipPoint.y - LocalPivot.y);
fl.y := (y[0] - y[1]) * (FlipPoint.x - LocalPivot.x) + (y[2] - y[1]) * (FlipPoint.y - LocalPivot.y);
end
else begin
fl.x := FlipPoint.x - WorldPivot.x;
fl.y := FlipPoint.y - WorldPivot.y;
end;
ang := RadToDeg(arctan2(fl.y, fl.x));
if (ang < 0) then ang := ang + 180.0
else if (ang = 180.0) then ang := 0.0;
lblFlipAngle.Caption := lblFlipAngle.Hint + Format(': %1.3g'#176, [ang]);
end;
procedure TEditForm.CalcArcsinScaleClick(Sender: TObject);
var t: double;
begin
try
t := StrToFloat(txtTrgScaleValue.Text) * 0.01;
if (abs(t) <= 1) then begin
t := RadToDeg(arcsin(t));
txtTrgRotateValue.Text := Format('%.6g', [t]);
end else
Application.MessageBox(PChar(TextByKey('editor-status-warnscale')),
ApophysisSVN, MB_ICONWARNING);
2022-03-08 12:25:51 -05:00
except
Beep;
end;
end;
procedure TEditForm.CalcCosClick(Sender: TObject);
var
num, t: double;
sn: string;
begin
if (not ValidNumField) then
begin
Application.MessageBox(PChar(TextByKey('editor-status-nonumfield')),
ApophysisSVN, MB_ICONWARNING);
2022-03-08 12:25:51 -05:00
exit;
end;
try
if (ActiveControl is TEdit) then
sn := TEdit(ActiveControl).Text
else if (ActiveControl is TValueListEditor) then
sn := TValueListEditor(ActiveControl).Cells[1, TValueListEditor(ActiveControl).Row]
else //if (ActiveControl is TComboBox) then
sn := TComboBox(ActiveControl).Text;
num := StrToFloat(sn);
if UseDegrees.Checked then
num := num * pi / 180;
case TMenuItem(Sender).Tag of
0: sn := Format('%.6g', [cos(num)]);
1: sn := Format('%.6g', [sin(num)]);
else begin
t := abs(cos(num));
if (t < 1E-6) then exit;
t := Round6(tan(num));
sn := FloatToStr(t);
end;
end;
if (ActiveControl is TEdit) then
begin
TEdit(ActiveControl).Text := sn;
TEdit(ActiveControl).OnExit(ActiveControl);
end
else if (ActiveControl is TValueListEditor) then
begin
TValueListEditor(ActiveControl).Cells[1, TValueListEditor(ActiveControl).Row] := sn;
TValueListEditor(ActiveControl).OnExit(ActiveControl);
end
else //if (ActiveControl is TComboBox) then
TComboBox(ActiveControl).Text := sn;
except
end;
end;
procedure TEditForm.mnuCalcExpressionClick(Sender: TObject); // AV
var
sn: string;
begin
if (not ValidNumField) then
begin
Application.MessageBox(PChar(TextByKey('editor-status-nonumfield')),
ApophysisSVN, MB_ICONWARNING);
exit;
end;
try
if (ActiveControl is TEdit) then
sn := TEdit(ActiveControl).Text
else if (ActiveControl is TValueListEditor) then
sn := TValueListEditor(ActiveControl).Cells[1,
TValueListEditor(ActiveControl).Row]
else // if (ActiveControl is TComboBox) then
sn := TComboBox(ActiveControl).Text;
if not InputQuery(TextByKey('editor-toolbar-calcexpression'),
TextByKey('editor-status-formula'), sn) then exit;
MathExpressions.InDegrees := UseDegrees.Checked;
sn := MathExpressions.CalculateExpression(LowerCase(sn));
if sn = '' then exit; // expression is not evaluated
if (ActiveControl is TEdit) then
begin
TEdit(ActiveControl).Text := sn;
TEdit(ActiveControl).OnExit(ActiveControl);
end
else if (ActiveControl is TValueListEditor) then
begin
TValueListEditor(ActiveControl).Cells[1,
TValueListEditor(ActiveControl).Row] := sn;
TValueListEditor(ActiveControl).OnExit(ActiveControl);
end
else //if (ActiveControl is TComboBox) then
TComboBox(ActiveControl).Text := sn;
except
Application.MessageBox(PChar(TextByKey('formula-cannotevaluate')),
ApophysisSVN, 16);
end;
end;
2022-03-08 12:25:51 -05:00
procedure TEditForm.TriangleViewPaint(Sender: TObject);
const
foc_ofs = 4;
foc_size = 32;
var
ix, iy, sc: double;
function ToScreen(fx, fy: double): TPoint;
begin
Result.x := integer(round(ix + (fx - gCenterX) * sc));
Result.y := integer(round(iy - (fy - gCenterY) * sc));
end;
procedure ToUnit(p: TPoint; var fx, fy: double);
begin
fx := (p.x - ix) / sc + gCenterX;
fy := (p.y + iy) / sc + gCenterY;
end;
var
dx, dy: double;
Width, Height: integer;
BitMap: TBitMap;
procedure LineDxDy;
var
k: double;
begin
if (dx <> 0) and (dy <> 0) then with Bitmap.Canvas do
begin
k := dy / dx;
if abs(k) < 1 then begin
MoveTo(0, round(iy - sc*(Pivot.y - ( ix/sc-GCenterX+Pivot.x)*k - GCenterY)));
LineTo(Width, round(iy - sc*(Pivot.y - (-ix/sc-GCenterX+Pivot.x)*k - GCenterY)));
end
else begin
MoveTo(round(ix + sc*(Pivot.x - (-iy/sc-GCenterY+Pivot.y)/k - GCenterX)), 0);
LineTo(round(ix + sc*(Pivot.x - ( iy/sc-GCenterY+Pivot.y)/k - GCenterX)), Height);
end;
end;
end;
procedure DrawFlipLine;
var k: double;
begin
with Bitmap.Canvas do
begin
k := fl.y / fl.x;
if abs(k) < 1 then begin
MoveTo(0, round(iy - sc*(GetPivot.y - ( ix/sc-GCenterX+GetPivot.x)*k - GCenterY)));
LineTo(Width, round(iy - sc*(GetPivot.y - (-ix/sc-GCenterX+GetPivot.x)*k - GCenterY)));
end
else begin
MoveTo(round(ix + sc*(GetPivot.x - (-iy/sc-GCenterY+GetPivot.y)/k - GCenterX)), 0);
LineTo(round(ix + sc*(GetPivot.x - ( iy/sc-GCenterY+GetPivot.y)/k - GCenterX)), Height);
end;
end;
end;
var
a, b, c: TPoint;
e, f: TPoint;
procedure DrawWidgets;
var
i: integer;
begin
with Bitmap.Canvas do
with MainTriangles[SelectedTriangle] do
begin
for i := 0 to 3 do
begin
a:=toscreen(Widgets[i][0].x, Widgets[i][0].y);
b:=toscreen(Widgets[i][1].x, Widgets[i][1].y);
c:=toscreen(Widgets[i][2].x, Widgets[i][2].y);
moveto(a.x, a.y);
lineto(b.x, b.y);
lineto(c.x, c.y);
end
end;
end;
var
i, n, tc, tn, lin: integer;
d, d1: double;
tx, ty: double;
tr, ta, den: double; // for (bi)polar grid
ax, ay: integer;
gridX1, gridX2, gridY1, gridY2, gi, gstep: double;
gp: TRoundToRange;
tps: TPenStyle;
tT: TTriangle;
txx, txy, tyx, tyy: double;
str, vvstr: string;
bf: TBlendFunction;
RenderCP : TControlPoint;
Renderer : TRenderer;
bm : TBitmap;
q, p0, p1: integer;
label DrawCorner;
begin
if (SelectedTriangle < 0) then begin
assert(false, 'Selected triangle < 0');
SelectedTriangle := 0;
end;
assert(TCustomDrawControl(Sender) = TriangleView);
if SelectedTriangle > LastTriangle then SelectedTriangle := LastTriangle;
BitMap := TBitMap.Create;
Width := TriangleView.Width;
Height := TriangleView.Height;
Bitmap.Width := Width;
Bitmap.Height := Height;
ix := Width / 2;
iy := Height / 2;
sc := 50 * GraphZoom;
try
with Bitmap.Canvas do
begin
try // who knows... ;)
gp:=round(log10(max(Width, Height)/sc))-1;
gstep:=power(10.0, gp);
except
gp:=0;
gstep:=1.0;
end;
a := ToScreen(MainTriangles[-1].x[0], MainTriangles[-1].y[0]);
b := ToScreen(MainTriangles[-1].x[1], MainTriangles[-1].y[1]);
c := ToScreen(MainTriangles[-1].x[2], MainTriangles[-1].y[2]);
brush.Color := EditorBkgColor;
FillRect(Rect(0, 0, Width, Height));
if EnableEditorPreview then begin
q := 0;
if EditPrevQual = 2 then q := 1;
p0 := TriangleView.Width div (2 - q);
p1 := TriangleView.Height div (2 - q);
RenderCp := cp.Clone;
RenderCp.Width := TriangleView.Width;
Rendercp.Height := TriangleView.Height;
RenderCp.pixels_per_unit := sc;
RenderCp.AdjustScale(p0, p1);
RenderCP.sample_density := PreviewDensity * 0.5;
RenderCP.spatial_oversample := 1;
RenderCP.spatial_filter_radius := 0.001;
RenderCp.center[0] := gCenterX ;
RenderCp.center[1] := -gCenterY ;
RenderCp.background[0] := EditorBkgColor and $ff;
RenderCp.background[1] := (EditorBkgColor and $ff00) shl 8;
RenderCp.background[2] := (EditorBkgColor and $ff0000) shl 16;
Render.SetCP(RenderCp);
Render.Render;
bf.BlendOp := AC_SRC_OVER;
bf.BlendFlags := 0;
bf.SourceConstantAlpha := 255 - EditorPreviewTransparency;
bf.AlphaFormat := 0;
bm := TBitmap.Create;
bm.Width := p0;
bm.Height := p1;
bm.Assign(Render.GetImage);
Windows.AlphaBlend(Handle, 0, 0,
TriangleView.Width, TriangleView.Height,
bm.Canvas.Handle, 0, 0, bm.Width, bm.Height, bf);
2022-03-08 12:25:51 -05:00
RenderCp.Destroy;
try
bm.Dormant;
bm.FreeImage;
finally
bm.Free;
end;
end;
Pen.Style := psSolid;
Pen.Width := 1;
// draw grid
Pen.Color := GridColor2;
gridX1:=gCenterX-ix/sc;
gridX2:=gCenterX+(Width-ix)/sc;
gridY1:=gCenterY-iy/sc;
gridY2:=gCenterY+(Height-iy)/sc;
gi:=RoundTo(gridX1, gp);
while gi <= gridX2 do
begin
ax:=integer(round(ix + (gi - gCenterX)*sc));
MoveTo(ax, 0);
LineTo(ax, Height);
gi:=gi+gstep;
end;
gi:=RoundTo(gridY1, gp);
while gi <= gridY2 do
begin
ay:=integer(round(iy - (gi - gCenterY)*sc));
MoveTo(0, ay);
LineTo(Width, ay);
gi:=gi+gstep;
end;
// draw axis
Pen.Color := GridColor1;
ax := integer(round(ix - gCenterX*sc));
ay := integer(round(iy + gCentery*sc));
MoveTo(ax, 0);
LineTo(ax, Height-1);
MoveTo(0, ay);
LineTo(Width-1, ay);
{Reference Triangle}
Pen.Style := psDot;
Pen.color := ReferenceTriangleColor;
brush.Color := gridColor1 shr 1 and $7f7f7f;
Polyline([a, b, c, a]);
brush.Color := EditorBkgColor;
Font.color := Pen.color;
TextOut(c.x-9, c.y-12, 'Y');
TextOut(a.x+2, a.y+1, 'X');
TextOut(b.x-8, b.y+1, 'O');
Pen.Style := psSolid;
// Draw Triangles
for i := 0 to LastTriangle do
begin
if i <> SelectedTriangle then Pen.Style := psDot;
with cp.xform[i] do // draw post-triangle
if postXswap or
((ShowAllXforms or (i = SelectedTriangle)) and (
(p[0,0]<>1) or (p[0,1]<>0) or
(p[1,0]<>0) or (p[1,1]<>1) or
(p[2,0]<>0) or (p[2,1]<>0) )) then
begin
Pen.Color := GetTriangleColor(i) shr 1 and $7f7f7f;
tps := Pen.Style;
Pen.Style := psDot;
cp.GetPostTriangle(tT, i);
txx := tT.x[0] - tT.x[1];
txy := tT.y[0] - tT.y[1];
tyx := tT.x[2] - tT.x[1];
tyy := tT.y[2] - tT.y[1];
a := ToScreen(tT.x[1] + txx + tyx, tT.y[1] + txy + tyy);
b := ToScreen(tT.x[1] - txx + tyx, tT.y[1] - txy + tyy);
e := ToScreen(tT.x[1] + txx - tyx, tT.y[1] + txy - tyy);
f := ToScreen(tT.x[1] - txx - tyx, tT.y[1] - txy - tyy);
Polyline([a, b, f, e, a]);
pen.Style := psSolid;
a := ToScreen(tT.x[1] - txx, tT.y[1] - txy);
b := ToScreen(tT.x[1] + txx, tT.y[1] + txy);
e := ToScreen(tT.x[1] + tyx, tT.y[1] + tyy);
f := ToScreen(tT.x[1] - tyx, tT.y[1] - tyy);
Polyline([a, b, e, f]);
if postXswap and ((i = SelectedTriangle) or ShowAllXforms) then
begin
Pen.Style := psDot;
cp.GetTriangle(tT, i);
a:=toscreen(tT.x[0], tT.y[0]);
moveto(a.x, a.y);
b:=toscreen(tT.x[2], tT.y[2]);
lineto(b.x, b.y);
pen.Style := psSolid;
b:=toscreen(tT.x[1], tT.y[1]);
lineto(b.x, b.y);
lineto(a.x, a.y);
end;
Pen.Style := tps;
end;
Pen.Color := GetTriangleColor(i);
a := ToScreen(MainTriangles[i].x[0], MainTriangles[i].y[0]);
b := ToScreen(MainTriangles[i].x[1], MainTriangles[i].y[1]);
c := ToScreen(MainTriangles[i].x[2], MainTriangles[i].y[2]);
if pen.Style <> psSolid then
Polyline([a, b, c, a])
else begin
Polyline([a, b, c]);
Pen.Style := psDot;
brush.Color := pen.color shr 1 and $7f7f7f;
Polyline([c, a]);
brush.Color := EditorBkgColor;
end;
Pen.Style := psSolid;
Ellipse(a.x - 4, a.y - 4, a.x + 4, a.y + 4);
Ellipse(b.x - 4, b.y - 4, b.x + 4, b.y + 4);
Ellipse(c.x - 4, c.y - 4, c.x + 4, c.y + 4);
Font.color := Pen.color;
TextOut(c.x+2, c.y+1, 'Y');
TextOut(a.x+2, a.y+1, 'X');
TextOut(b.x+2, b.y+1, 'O');
end;
UpdateWidgets;
if ExtendedEdit then begin
n := GetTriangleColor(SelectedTriangle);// shr 1 and $7f7f7f;
if mouseOverTriangle <> SelectedTriangle then n := n shr 1 and $7f7f7f;
Pen.Color := n;
Pen.Mode := pmMerge;
DrawWidgets;
if mouseOverWidget >= 0 then
begin
pen.Color := pen.Color shr 1 and $7f7f7f;
pen.Width := 4;
DrawWidgets;
pen.Width := 1;
end;
end;
if showVarPreview then
begin
assert(trkVarPreviewRange.position > 0);
assert(trkVarPreviewDensity.position > 0);
cp.xform[SelectedTriangle].Prepare;
n := trkVarPreviewRange.position * trkVarPreviewDensity.position * 5;
d1 := trkVarPreviewDensity.position * 5;
tc := GetTriangleColor(SelectedTriangle);
// AV: draw the variation preview in the selected coordinate system
case GridComboBox.ItemIndex of
0: begin // transform rectangular grid
for ax := -n to n do
for ay := -n to n do
try
tx := ax / d1;
ty := ay / d1;
for i := trkVarPreviewDepth.position downto 1 do
cp.xform[SelectedTriangle].NextPointXY(tx, ty);
a := toscreen(tx, -ty);
Pixels[a.x, a.y] := tc;
except
end;
end;
1: begin // transform polar grid
try
tx := 0; ty := 0; // origin
for i := trkVarPreviewDepth.position downto 1 do
cp.xform[SelectedTriangle].NextPointXY(tx, ty);
a := ToScreen(tx, -ty);
Pixels[a.x, a.y] := tc;
except
end;
for ax := -2*n to 2*n do
for ay := 1 to n do
try
tr := ay/d1;
ta := ax * PI/2/n;
tx := tr * cos(ta);
ty := tr * sin(ta);
for i := trkVarPreviewDepth.position downto 1 do
cp.xform[SelectedTriangle].NextPointXY(tx, ty);
a := ToScreen(tx, -ty);
Pixels[a.x, a.y] := tc;
except
end;
end;
2: begin // transform bipolar grid
for ax := -2*n to 2*n do
for ay := -n to n do
try
tr := ay/d1;
ta := ax * PI/2/n;
den := cosh(tr) - cos(ta);
tx := sinh(tr)/den;
ty := sin(ta)/den;
for i := trkVarPreviewDepth.position downto 1 do
cp.xform[SelectedTriangle].NextPointXY(tx, ty);
a := ToScreen(tx, -ty);
Pixels[a.x, a.y] := tc;
except
end;
end;
else begin // transform elliptic grid
for ax := -2*n to 2*n do
for ay := 0 to n do
try
tr := ay/d1;
ta := ax * PI/2/n;
tx := cosh(tr) * cos(ta);
ty := sinh(tr) * sin(ta);
for i := trkVarPreviewDepth.position downto 1 do
cp.xform[SelectedTriangle].NextPointXY(tx, ty);
a := ToScreen(tx, -ty);
Pixels[a.x, a.y] := tc;
except
end;
end;
end;
end;
// *********** Reflection stuff ****************************
if ShowFlipLine then
begin
pen.Color := FlipColor;
pen.Mode := pmMerge;
pen.Style := psSolid;
CalcFlip;
if (fl.x <> 0) and (fl.y <> 0) then
DrawFlipLine
else if (fl.x = 0) and (fl.y <> 0)then
begin
lin := round(ix + (GetPivot.x - gCenterX) * sc);
MoveTo(lin, 0);
LineTo(lin, Height);
end
else if (fl.y = 0) and (fl.x <> 0) then
begin
lin := round(iy - (GetPivot.y - gCenterY) * sc);
MoveTo(0, lin);
LineTo(Width, lin);
end;
end;
//****************************************************
if (TriangleCaught or CornerCaught) then // if dragging, draw pivot axis
begin
mouseOverTriangle := SelectedTriangle;
if HelpersEnabled then
begin
pen.Color := HelpersColor;
pen.Mode := pmMerge;
pen.Style := psSolid;
a := ToScreen(Pivot.x, Pivot.y);
MoveTo(a.x, 0);
LineTo(a.x, Height);
MoveTo(0, a.y);
LineTo(Width, a.y);
if (editMode = modeRotate) then // draw circle
begin
if CornerCaught then begin
dx := MainTriangles[SelectedTriangle].x[SelectedCorner] - Pivot.x;
dy := MainTriangles[SelectedTriangle].y[SelectedCorner] - Pivot.y;
d := Hypot(dx, dy);
end
else begin
dx := MainTriangles[SelectedTriangle].x[0] - Pivot.x;
dy := MainTriangles[SelectedTriangle].y[0] - Pivot.y;
d := Hypot(dx, dy);
for i := 1 to 2 do
begin
d1 := dist(Pivot.x, Pivot.y, MainTriangles[SelectedTriangle].x[i], MainTriangles[SelectedTriangle].y[i]);
if d1 > d then
begin
if d > 0 then begin
dx := dx/d*d1;
dy := dy/d*d1;
end;
d := d1;
end;
end;
end;
i := integer(round(d * sc));
if i > 4 then
begin
pen.Color := HelpersColor;
brush.Style := bsClear;
Ellipse(a.x - i, a.y - i, a.x + i, a.y + i);
a := ToScreen(Pivot.x - dy, Pivot.y + dx);
b := ToScreen(Pivot.x + dy, Pivot.y - dx);
c := ToScreen(Pivot.x, Pivot.y);
MoveTo(a.x, a.y);
LineTo(c.X, c.y);
LineTo(b.X, b.y);
end;
// rotated axis
LineDxDy;
end
else if (editMode = modeScale) then // draw lines
begin
if CornerCaught then begin
dx := MainTriangles[SelectedTriangle].x[SelectedCorner] - Pivot.x;
dy := MainTriangles[SelectedTriangle].y[SelectedCorner] - Pivot.y;
LineDxDy;
end
else begin // hmmm...
dx := MainTriangles[SelectedTriangle].x[0] - Pivot.x;
dy := MainTriangles[SelectedTriangle].y[0] - Pivot.y;
LineDxDy;
dx := MainTriangles[SelectedTriangle].x[1] - Pivot.x;
dy := MainTriangles[SelectedTriangle].y[1] - Pivot.y;
LineDxDy;
dx := MainTriangles[SelectedTriangle].x[2] - Pivot.x;
dy := MainTriangles[SelectedTriangle].y[2] - Pivot.y;
LineDxDy;
end;
end
else // if editMode = modeMove then // draw target axis
begin
Pen.Color := HelpersColor;
Pen.Mode := pmMerge;//Xor;
brush.Color := 0;
if CornerCaught then
a := ToScreen(MainTriangles[SelectedTriangle].x[SelectedCorner],
MainTriangles[SelectedTriangle].y[SelectedCorner])
else
a := ToScreen(GetPivot.x, GetPivot.y);
MoveTo(a.x, 0);
LineTo(a.x, Height);
MoveTo(0, a.y);
LineTo(Width, a.y);
Pen.Mode := pmCopy;
end;
end; // endif HelpersEnabled
end;
if (mouseOverTriangle >= 0) then // highlight triangle under cursor
begin
with MainTriangles[mouseOverTriangle] do begin
a := ToScreen(x[0], y[0]);
b := ToScreen(x[1], y[1]);
c := ToScreen(x[2], y[2]);
end;
pen.Width:=2;
Pen.Color:=GetTriangleColor(mouseOverTriangle) shr 1 and $7f7f7f;
Pen.Mode:=pmMerge;
brush.Color:=Pen.Color shr 1 and $7f7f7f;
if (SelectMode and (editMode <> modePick)) or (mouseOverTriangle = SelectedTriangle) then
Polygon([a, b, c])
else
PolyLine([a, b, c, a]);
pen.width:=4;
Ellipse(a.x - 3, a.y - 3, a.x + 3, a.y + 3);
Ellipse(b.x - 3, b.y - 3, b.x + 3, b.y + 3);
Ellipse(c.x - 3, c.y - 3, c.x + 3, c.y + 3);
pen.width:=1;
pen.mode:=pmCopy;
if not (CornerCaught or TriangleCaught) then // show used variations
begin
font.Color := GetTriangleColor(mouseOverTriangle);
brush.Style := bsClear;
ay := Height-foc_ofs*2 + font.Height; // font.height < 0
for i:= NRVAR - 1 downto 0 do
if cp.xform[mouseOverTriangle].GetVariation(i) <> 0 then
begin
// AV: hack, inspired by Apo 2.09
if (pos('julian', Varnames(i))> 0) or (pos('julia3D', Varnames(i))> 0)
or (pos('juliascope', Varnames(i))> 0) then
begin
vvstr := Varnames(i) + '_power = ' +
cp.xform[mouseOverTriangle].GetVariableStr(Varnames(i) + '_power');
ax := Width-foc_ofs*2 - TextWidth(vvstr);
TextOut(ax, ay, vvstr);
Inc(ay, font.Height);
end else
if (Varnames(i) = 'affine3D') or (Varnames(i) = 'trianglecrop')
or (Varnames(i) = 'projective') or (Varnames(i) = 'spherecrop') then
begin
vvstr := Varnames(i) + '_mode';
vvstr := vvstr + ' = ' + cp.xform[mouseOverTriangle].GetVariableStr(vvstr);
ax := Width-foc_ofs*2 - TextWidth(vvstr);
TextOut(ax, ay, vvstr);
Inc(ay, font.Height);
end;
vvstr := Varnames(i) + Format(' = %.6g', [cp.xform[mouseOverTriangle].GetVariation(i)]);
ax := Width-foc_ofs*2 - TextWidth(vvstr);
TextOut(ax, ay, vvstr);
Inc(ay, font.Height);
end;
// brush.Style := bsSolid;
end;
end;
pen.color := clWhite;
if CornerCaught then // draw selected corner
begin
brush.Color:=clSilver;
a := ToScreen(MainTriangles[SelectedTriangle].x[SelectedCorner], MainTriangles[SelectedTriangle].y[SelectedCorner]);
Ellipse(a.x - 4, a.y - 4, a.x + 4, a.y + 4);
end
else if (mouseOverTriangle>=0) then
begin
if (mouseOverCorner >= 0) then // highlight corner under cursor
begin
case mouseOverCorner of
0: brush.Color:=clRed;
2: brush.Color:=clBlue;
else brush.Color:=clSilver;
end;
a := ToScreen(MainTriangles[mouseOverTriangle].x[mouseOverCorner], MainTriangles[mouseOverTriangle].y[mouseOverCorner]);
Ellipse(a.x - 4, a.y - 4, a.x + 4, a.y + 4);
// hmm... TODO: optimize
if HelpersEnabled then begin
pen.Color := HelpersColor;
pen.Mode := pmMerge;
pen.Style := psDot;
brush.Style := bsClear;
if (editMode = modeRotate) then
begin
i := integer(round(olddist * sc));
if i > 4 then begin
a := ToScreen(pivot.x, pivot.y);
Ellipse(a.x - i, a.y - i, a.x + i, a.y + i);
end;
end
else if editMode = modeScale then
begin
dx := MainTriangles[mouseOverTriangle].x[mouseOverCorner] - Pivot.x;
dy := MainTriangles[mouseOverTriangle].y[mouseOverCorner] - Pivot.y;
LineDxDy;
end;
end;
end;
if (mouseOverEdge >= 0) then // highlight edge under cursor
begin
i := (mouseOverEdge + 1) mod 3;
a := ToScreen(MainTriangles[mouseOverTriangle].x[mouseOverEdge], MainTriangles[mouseOverTriangle].y[mouseOverEdge]);
b := ToScreen(MainTriangles[mouseOverTriangle].x[i], MainTriangles[mouseOverTriangle].y[i]);
pen.Width:=5;
Pen.Color:=GetTriangleColor(mouseOverTriangle) shr 1 and $7f7f7f;
Pen.Mode:=pmMerge;
MoveTo(a.X, a.Y);
LineTo(b.X, b.Y);
pen.Mode:=pmCopy;
pen.Width:=1;
end;
end;
// draw pivot point
a := ToScreen(GetPivot.x, GetPivot.y);
Pen.Style := psSolid;
pen.Color := clWhite;
brush.Color := clSilver;
if (pivotMode = pivotLocal) or EdgeCaught then i := 2
else i := 3;
Ellipse(a.x - i, a.y - i, a.x + i, a.y + i);
if editMode = modePick then begin // hmm...
a := ToScreen(mouseOverPos.x, mouseOverPos.y);
brush.Style := bsClear;
Ellipse(a.x - i, a.y - i, a.x + i, a.y + i);
end;
if TWinControl(Sender).Focused then
begin
pen.Color := HelpersColor;
pen.Mode := pmXor;
MoveTo(foc_ofs, foc_size);
LineTo(foc_ofs, foc_ofs);
LineTo(foc_size, foc_ofs);
MoveTo(Width-1-foc_ofs, foc_size);
LineTo(Width-1-foc_ofs, foc_ofs);
LineTo(Width-1-foc_size, foc_ofs);
MoveTo(Width-1-foc_ofs, Height-1-foc_size);
LineTo(Width-1-foc_ofs, Height-1-foc_ofs);
LineTo(Width-1-foc_size, Height-1-foc_ofs);
MoveTo(foc_ofs, Height-1-foc_size);
LineTo(foc_ofs, Height-1-foc_ofs);
LineTo(foc_size, Height-1-foc_ofs);
end;
end;
TriangleView.Canvas.Draw(0, 0, Bitmap);
finally
BitMap.Free;
end;
end;
procedure TEditForm.FormCreate(Sender: TObject);
var
i: integer;
vn: string;
ExtSM: HMenu;
begin
mnuELowQuality.Caption := TextByKey('common-lowquality');
mnuEMediumQuality.Caption := TextByKey('common-mediumquality');
mnuEHighQuality.Caption := TextByKey('common-highquality');
mnuLowQuality.Caption := TextByKey('common-lowquality');
mnuMediumQuality.Caption := TextByKey('common-mediumquality');
mnuHighQuality.Caption := TextByKey('common-highquality');
tbCopy.Hint := TextByKey('common-copy');
tbCopyTriangle.Hint := TextByKey('editor-popup-transform-copycoords');
CopyTriangleCoordinates.Caption := TextByKey('editor-popup-transform-copycoords');
CopyTransform.Caption := TextByKey('editor-popup-transform-copywhole');
CopyVariations.Caption := TextByKey('editor-popup-transform-copyvars');
2022-03-08 12:25:51 -05:00
tbPaste.Hint := TextByKey('common-paste');
tbPasteTriangle.Hint := TextByKey('editor-popup-transform-pastecoords');
PasteTriangleCoordinates.Caption := TextByKey('editor-popup-transform-pastecoords');
PasteTransform.Caption := TextByKey('editor-popup-transform-pastewhole');
PasteVariations.Caption := TextByKey('editor-popup-transform-pastevars');
CopyChaos.Caption := TextByKey('editor-popup-chaos-copy');
PasteChaos.Caption := TextByKey('editor-popup-chaos-paste');
mnuCopyChaos.Caption := CopyChaos.Caption;
mnuPasteChaos.Caption := PasteChaos.Caption;
2022-03-08 12:25:51 -05:00
tbUndo.Hint := TextByKey('common-undo');
mnuUndo.Caption := TextByKey('common-undo');
tbRedo.Hint := TextByKey('common-redo');
mnuRedo.Caption := TextByKey('common-redo');
bClear.Caption := TextByKey('common-clear');
pnlSymmetry.Hint := TextByKey('common-dragpanelhint');
pnlOpacity.Hint := TextByKey('common-dragpanelhint');
pnlDC.Hint := TextByKey('common-dragpanelhint');
pnlWeight.Hint := TextByKey('common-dragpanelhint');
pnlXFormColor.Hint := TextByKey('common-dragpanelhint'); // AV
self.Caption := TextByKey('editor-title');
Panel1.Caption := TextByKey('editor-common-transform');
Panel2.Caption := TextByKey('editor-common-name');
pnlWeight.Caption := TextByKey('editor-common-weight');
tbComment.Hint := TextByKey('editor-common-editcomment');
SaveFlameState.Hint := TextByKey('editor-toolbar-savestate');
2022-03-08 12:25:51 -05:00
tabVariations.Caption := TextByKey('editor-tab-variations-title');
VEVars.TitleCaptions[0] := TextByKey('editor-tab-variations-name');
VEVars.TitleCaptions[1] := TextByKey('editor-tab-variations-value');
cbCollapseVariations.Items[0] := TextByKey('editor-tab-variations-toggleshowall');
cbCollapseVariations.Items[1] := TextByKey('editor-tab-variations-togglehideunused');
cbCollapseVariations.Items[2] := TextByKey('editor-tab-variations-togglefavourites');
cbCollapseVariations.Items[3] := TextByKey('editor-tab-variations-toggle3d');
cbCollapseVariations.Items[4] := TextByKey('editor-tab-variations-toggledc');
2022-03-08 12:25:51 -05:00
btnVarOrder.Caption := TextByKey('editor-tab-variations-order');
btnVarOrder.Hint := TextByKey('editor-tab-variations-orderhint');
TabVariables.Caption := TextByKey('editor-tab-variables-title');
vleVariables.TitleCaptions[0] := TextByKey('editor-tab-variables-name');
vleVariables.TitleCaptions[1] := TextByKey('editor-tab-variables-value');
chkCollapseVariables.Caption := TextByKey('editor-tab-variables-toggleshowall');
btResetparams.Caption := TextByKey('editor-tab-variables-reset');
TabChaos.Caption := TextByKey('editor-tab-chaos-title');
vleChaos.TitleCaptions[0] := TextByKey('editor-tab-chaos-path');
vleChaos.TitleCaptions[1] := TextByKey('editor-tab-chaos-modifier');
optTo.Caption := TextByKey('editor-tab-chaos-viewasto');
mnuChaosViewTo.Caption := TextByKey('editor-tab-chaos-viewasto');
optFrom.Caption := TextByKey('editor-tab-chaos-viewasfrom');
mnuChaosViewFrom.Caption := TextByKey('editor-tab-chaos-viewasfrom');
TriangleTab.Caption := TextByKey('editor-tab-triangle-title');
gbPivot.Caption := TextByKey('editor-tab-triangle-pivot');
2022-03-08 12:25:51 -05:00
GroupBox7.Caption := TextByKey('editor-tab-transform-coordsystem');
GroupBox9.Caption := TextByKey('editor-tab-transform-affine');
GroupBox8.Caption := TextByKey('editor-tab-transform-postaffine');
btSwapCoefs.Caption:= TextByKey('editor-tab-transform-swapaffine');
btSwapCoefs.Hint := TextByKey('editor-tab-transform-swapaffinehint');
RotateXYO.Caption := TextByKey('editor-popup-triangle-rotateall');
RotateX.Caption := TextByKey('editor-popup-triangle-rotatex');
RotateY.Caption := TextByKey('editor-popup-triangle-rotatey');
RotateO.Caption := TextByKey('editor-popup-triangle-rotateo');
ScaleXYO.Caption := TextByKey('editor-popup-triangle-scaleall');
ScaleX.Caption := TextByKey('editor-popup-triangle-scalex');
ScaleY.Caption := TextByKey('editor-popup-triangle-scaley');
ScaleO.Caption := TextByKey('editor-popup-triangle-scaleo');
RectGrid.Caption := TextByKey('editor-popup-triangle-squaregrid');
TriGrid.Caption := TextByKey('editor-popup-triangle-hexgrid');
InvertMovevalue1.Caption := TextByKey('editor-popup-triangle-invertstep');
CalcArcsinScale.Caption := TextByKey('editor-popup-triangle-arcsin');
ShowModVals.Caption := TextByKey('editor-popup-triangle-display');
mnuFlipAllLine.Caption := TextByKey('editor-popup-panel-allflipline');
tbTriangle.Hint := TextByKey('editor-tab-triangle-menuhint');
btnResetPivot.Hint := TextByKey('editor-tab-triangle-resetpivot');
btnPickPivot.Hint := TextByKey('editor-tab-triangle-pickpivot');
btTrgRotateLeft.Hint := TextByKey('editor-tab-triangle-rotateleft');
btTrgRotateRight.Hint := TextByKey('editor-tab-triangle-rotateright');
btTrgMoveUp.Hint := TextByKey('editor-tab-triangle-moveup');
btTrgMoveDown.Hint := TextByKey('editor-tab-triangle-movedown');
btTrgMoveLeft.Hint := TextByKey('editor-tab-triangle-moveleft');
btTrgMoveRight.Hint := TextByKey('editor-tab-triangle-moveright');
btTrgScaleDown.Hint := TextByKey('editor-tab-triangle-scaledown');
btTrgScaleUp.Hint := TextByKey('editor-tab-triangle-scaleup');
tbAutoWeights.Hint := TextByKey('editor-tab-triangle-autoweight');
tabXForm.Caption := TextByKey('editor-tab-transform-title');
btnResetCoefs.Caption := TextByKey('editor-tab-transform-reset');
btnResetCoefs.Hint := TextByKey('editor-tab-transform-resethint');
btnCoefsRect.Caption := TextByKey('editor-tab-transform-rectangular');
btnCoefsRect.Hint := TextByKey('editor-tab-transform-rectangularhint');
btnCoefsPolar.Caption := TextByKey('editor-tab-transform-polar');
btnCoefsPolar.Hint := TextByKey('editor-tab-transform-polarhint');
btnResetPostCoefs.Caption := TextByKey('editor-tab-transform-resetpost');
btnResetPostCoefs.Hint := TextByKey('editor-tab-transform-resetposthint');
btConjugate.Caption := 'TVT'#$02C9#$00B9#32#32 + TextByKey('editor-tab-transform-conjugate');
btConjugate.Hint := TextByKey('editor-tab-transform-conjugatehint');
chkAutoZScale.Caption := TextByKey('editor-tab-transform-autozscale');
btnXcoefs.Hint := TextByKey('editor-tab-transform-resetxhint');
btnXpost.Hint := TextByKey('editor-tab-transform-resetxhint');
btnYcoefs.Hint := TextByKey('editor-tab-transform-resetyhint');
btnYpost.Hint := TextByKey('editor-tab-transform-resetyhint');
btnOcoefs.Hint := TextByKey('editor-tab-transform-resetohint');
btnOpost.Hint := TextByKey('editor-tab-transform-resetohint');
tabColors.Caption := TextByKey('editor-tab-color-title');
GroupBox1.Caption := TextByKey('editor-tab-color-transformcolor');
pnlSymmetry.Caption := TextByKey('editor-tab-color-colorspeed');
pnlOpacity.Caption := TextByKey('editor-tab-color-opacity');
pnlDC.Caption := TextByKey('editor-tab-color-directcolor');
chkXFormSolo.Caption := TextByKey('editor-tab-color-togglesolo');
GroupBox2.Caption := TextByKey('editor-tab-color-varpreview');
gbFlip.Caption := TextByKey('editor-tab-triangle-reflection');
gbTrgOperations.Caption := TextByKey('editor-tab-triangle-transforms');
gbCoordinates.Caption := TextByKey('editor-tab-triangle-coordinates');
2022-03-08 12:25:51 -05:00
btnResetFlip.Hint := TextByKey('editor-tab-triangle-resetflip');
Label1.Caption := TextByKey('editor-tab-color-previewrange');
Label2.Caption := TextByKey('editor-tab-color-previewdepth');
Label3.Caption := TextByKey('editor-tab-color-previewdensity');
Label1.Hint := TextByKey('editor-tab-color-previewrangehint');
Label2.Hint := TextByKey('editor-tab-color-previewdepthhint');
Label3.Hint := TextByKey('editor-tab-color-previewdensityhint');
lblSearch.Caption := TextByKey('editor-tab-variations-search'); // AV
txtSearchBox.TextHint := TextByKey('editor-tab-variations-searchhint'); // AV
2022-03-08 12:25:51 -05:00
tbResetAll.Hint := TextByKey('editor-toolbar-newflame');
tbAdd.Hint := TextByKey('editor-toolbar-newtransform');
mnuAdd.Caption := TextByKey('editor-toolbar-newtransform');
mnuAdd1.Caption := TextByKey('editor-toolbar-newtransform');
tbPreLink.Hint := TextByKey('editor-toolbar-addlinkedpretransform');
tbPostLink.Hint := TextByKey('editor-toolbar-addlinkedtransform');
mnuLinkPostxform.Caption := TextByKey('editor-toolbar-addlinkedtransform');
mnuLinkPrexform.Caption := TextByKey('editor-toolbar-addlinkedpretransform');
tbDuplicate.Hint := TextByKey('editor-toolbar-duplicatetransform');
mnuDuplicate.Caption := TextByKey('editor-toolbar-duplicatetransform');
tbDelete.Hint := TextByKey('editor-toolbar-removetransform');
mnuDelete.Caption := TextByKey('editor-toolbar-removetransform');
tbSelect.Hint := TextByKey('editor-toolbar-modeselect');
mnuSelectMode.Caption := TextByKey('editor-toolbar-modeselect');
tbMove.Hint := TextByKey('editor-toolbar-modemove');
tbRotate.Hint := TextByKey('editor-toolbar-moderotate');
tbScale.Hint := TextByKey('editor-toolbar-modescale');
tbPivotMode.Caption := TextByKey('editor-toolbar-toggleworldpivot');
tbPivotMode.Hint := TextByKey('editor-toolbar-toggleworldpivot');
tbRotate90CCW.Caption := TextByKey('editor-toolbar-rotate90ccw');
tbRotate90CCW.Hint := TextByKey('editor-toolbar-rotate90ccw');
btTrgRotateLeft90.Hint := TextByKey('editor-toolbar-rotate90ccw');
RotateTriangle90CCW1.Caption := TextByKey('editor-toolbar-rotate90ccw');
tbRotate90CW.Caption := TextByKey('editor-toolbar-rotate90cw');
tbRotate90CW.Hint := TextByKey('editor-toolbar-rotate90cw');
btTrgRotateRight90.Hint := TextByKey('editor-toolbar-rotate90cw');
RotateTriangle90CCW2.Caption := TextByKey('editor-toolbar-rotate90cw');
tbFlipHorz.Caption := TextByKey('editor-toolbar-fliph');
tbFlipHorz.Hint := TextByKey('editor-toolbar-fliph');
mnuFlipHorizontal.Caption := TextByKey('editor-toolbar-fliph');
tbFlipVert.Caption := TextByKey('editor-toolbar-flipv');
tbFlipVert.Hint := TextByKey('editor-toolbar-flipv');
mnuFlipVertical.Caption := TextByKey('editor-toolbar-flipv');
tbVarPreview.Caption := TextByKey('editor-toolbar-togglevarpreview');
tbVarPreview.Hint := TextByKey('editor-toolbar-togglevarpreview');
mnuShowVarPreview.Caption := TextByKey('editor-toolbar-togglevarpreview');
tbPostXSwap.Caption := TextByKey('editor-toolbar-toggleposttransform');
tbPostXSwap.Hint := TextByKey('editor-toolbar-toggleposttransform');
tb2PostXSwap.Hint := TextByKey('editor-toolbar-toggleposttransform');
oggleposttriangleediting1.Caption := TextByKey('editor-toolbar-toggleposttransform');
tbEnableFinalxform.Caption := TextByKey('editor-toolbar-togglefinaltransform');
tbEnableFinalxform.Hint := TextByKey('editor-toolbar-togglefinaltransform');
mnuAutoZoom.Caption := TextByKey('editor-popup-panel-autozoom');
tbExtendedEdit.Hint := TextByKey('editor-popup-panel-toggleextendededit');
mnuExtendedEdit.Caption := TextByKey('editor-popup-panel-toggleextendededit');
tbAxisLock.Hint := TextByKey('editor-popup-panel-locktransformaxes');
mnuAxisLock.Caption := TextByKey('editor-popup-panel-locktransformaxes');
SynchronizeAll.Caption := TextByKey('editor-tab-triangle-syncall');
2022-03-08 12:25:51 -05:00
btnShowLine.Caption := TextByKey('editor-tab-triangle-showline');
btnShowLine.Hint := TextByKey('editor-tab-triangle-showlinehint');
btnFlip.Caption := TextByKey('editor-tab-triangle-fliptriangle');
btnFlip.Hint := TextByKey('editor-tab-triangle-fliptrianglehint');
btFlipX.Hint := TextByKey('editor-tab-triangle-flipx');
btFlipY.Hint := TextByKey('editor-tab-triangle-flipy');
btFlipDiag.Hint := TextByKey('editor-tab-triangle-flipxy');
lblFlipAngle.Hint := TextByKey('editor-status-angle');
editPivotX.Hint := TextByKey('editor-tab-triangle-pivot1x');
editPivotY.Hint := TextByKey('editor-tab-triangle-pivot1y');
editFlipX.Hint := TextByKey('editor-tab-triangle-pivot2x');
editFlipY.Hint := TextByKey('editor-tab-triangle-pivot2y');
btnFullChaos.Hint := TextByKey('editor-toolbar-showchaos');
ShowChaosMatrix.Caption := btnFullChaos.Hint;
mnuFlipAllH.Caption := TextByKey('editor-popup-panel-allfliph');
mnuFlipAllV.Caption := TextByKey('editor-popup-panel-allflipv');
mnuResetLoc.Caption := TextByKey('editor-popup-quality-autoreset');
mnuResetTrgPosition.Caption := TextByKey('editor-popup-transform-resetposition');
mnuResetTrgRotation.Caption := TextByKey('editor-popup-transform-resetrotation');
mnuResetTrgScale.Caption := TextByKey('editor-popup-transform-resetscale');
mnuResetTrgFlip.Caption := TextByKey('editor-popup-transform-resetflip');
mnuCopyTriangle.Caption := TextByKey('editor-popup-transform-copycoords');
mnuPasteTriangle.Caption := TextByKey('editor-popup-transform-pastecoords');
mnuReset.Caption := TextByKey('editor-popup-transform-resetentiretriangle');
mnuChaosRebuild.Caption := TextByKey('editor-popup-chaos-rebuildlinks');
mnuChaosClearAll.Caption := TextByKey('editor-popup-chaos-clearall');
mnuChaosSetAll.Caption := TextByKey('editor-popup-chaos-setall');
btClearChaos.Hint := TextByKey('editor-popup-chaos-clearall');
btResetChaos.Hint := TextByKey('editor-popup-chaos-setall');
NormChaos.Caption := TextByKey('editor-popup-chaos-normalize');
RandomizeMatrix.Caption := TextByKey('editor-popup-chaos-randomize');
RandomizeChaos.Caption := TextByKey('editor-popup-chaos-random');
ResetChaos.Caption := TextByKey('editor-popup-chaos-reset');
ChaosClearBelow.Caption := TextByKey('editor-popup-chaos-clearbelow');
ClearAllAbove.Caption := TextByKey('editor-popup-chaos-clearabove');
btnPivotMode.Hint := TextByKey('editor-tab-triangle-toworld');
AddContainer.Caption := TextByKey('editor-popup-chaos-container');
InheritWeights.Caption := TextByKey('editor-popup-chaos-keepweight');
InvertXaos.Caption := TextByKey('editor-popup-chaos-invert');
btChaos.Caption := TextByKey('editor-popup-chaos-showmenu');
GridComboBox.Items[0] := TextByKey('editor-grid-rectangular');
GridComboBox.Items[1] := TextByKey('editor-grid-polar');
GridComboBox.Items[2] := TextByKey('editor-grid-bipolar');
GridComboBox.Items[3] := TextByKey('editor-grid-elliptic');
GridComboBox.ItemIndex := 0;
lblGridType.Caption := TextByKey('editor-grid-type');
lblGridType.Hint := TextByKey('editor-grid-typehint');
gbTrgOperations.Hint := StringReplace(TextByKey('editor-tab-triangle-transformshint'),
2022-03-08 12:25:51 -05:00
',', ','#13, [rfReplaceAll]);
// Math constants
RedrawButtons;
btnMathPopup.Hint := TextByKey('editor-toolbar-pihint');
Pifractions.Caption := TextByKey('editor-toolbar-pimenu') + #32#$03C0'...';
InsertPi1.Caption := #$03C0;
Insert2Pi1.Caption := '2'#$03C0;
InsertPi21.Caption := #$03C0'/2';
InsertPi31.Caption := #$03C0'/3';
InsertPi41.Caption := #$03C0'/4';
InsertPi61.Caption := #$03C0'/6';
Insert1sqrt21.Caption := '1/'#$221A#$0305'2';
Insertsqrt321.Caption := #$221A#$0305'3/2';
Insertsqrt331.Caption := #$221A#$0305'3/3';
Insertsqrt361.Caption := #$221A#$0305'3/6';
Insertsqrt31.Caption := #$221A#$0305'3';
SquareRoots1.Caption := TextByKey('editor-toolbar-squareroots');
InsertGoldenratio1.Caption := TextByKey('editor-toolbar-goldenratio');
InvCurrentNum.Caption := TextByKey('editor-toolbar-invert');
Squarethenumber1.Caption := TextByKey('editor-toolbar-square');
SquareRoot.Caption := TextByKey('editor-toolbar-squareroot');
Mul2.Caption := TextByKey('editor-toolbar-multiply');
Div2.Caption := TextByKey('editor-toolbar-divide');
CalcCos.Caption := TextByKey('editor-toolbar-calccos');
CalcSin.Caption := TextByKey('editor-toolbar-calcsin');
CalcTan.Caption := TextByKey('editor-toolbar-calctan');
UseDegrees.Caption := TextByKey('editor-toolbar-usedegrees');
mnuCalcExpression.Caption := TextByKey('editor-toolbar-calcexpression');
2022-03-08 12:25:51 -05:00
ExtSM := GetSystemMenu(Handle, False); // AV
InsertMenu(ExtSM, UINT(5), MF_ByPosition or MF_Separator, 0, nil);
InsertMenu(ExtSM, UINT(6), MF_ByPosition, $C0, PChar(TextByKey('main-menu-screenshot')));
// Custom control setup
TriangleView := TCustomDrawControl.Create(self);
TriangleView.TabStop := True;
TriangleView.TabOrder := 0;
TriangleView.Parent := GrphPnl;
TriangleView.Align := alClient;
TriangleView.Visible := True;
TriangleView.OnPaint := TriangleViewPaint;
TriangleView.OnDblClick := TriangleViewDblClick;
TriangleView.OnMouseDown := TriangleViewMouseDown;
TriangleView.OnMouseMove := TriangleViewMouseMove;
TriangleView.OnMouseUp := TriangleViewMouseUp;
TriangleView.OnMouseWheel := TriangleViewMouseWheel;
TriangleView.OnKeyDown := TriangleViewKeyDown;
TriangleView.OnKeyUp := TriangleViewKeyUp;
TriangleView.OnEnter := TriangleViewInvalidate;
TriangleView.OnExit := TriangleViewExit;
TriangleView.OnMouseLeave := TriangleViewmouseLeave;
SetLength(VarsCache, NRVAR); // AV
for i:= 0 to NRVAR - 1 do begin
vn := Varnames(i);
VEVars.InsertRow(vn, '0', True);
VarsCache[i] := MinDouble; // AV: moved here
end;
for i:= 0 to GetNrVariableNames - 1 do begin
vn := GetVariableNameAt(i);
vleVariables.InsertRow(vn, '0', True);
end;
vleChaos.InsertRow(Format(TextByKey('editor-common-toprefix'), [1]), '1', true);
mnuChaosRebuild.Checked := RebuildXaosLinks;
GraphZoom := 1;
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;
SelectMode := true;
editMode := modeMove;
AxisLock := TransformAxisLock;
tbAxisLock.Down := AxisLock;
ExtendedEdit := ExtEditEnabled;
// tbExtendedEdit.Down := ExtendedEdit;
2022-03-08 12:25:51 -05:00
widgetMode := modeRotate;
ShowFlipLine := False;
hasLinkX := False;
EdgeCaught := false;
CornerCaught := false;
TriangleCaught := false;
mouseOverTriangle := -1;
mouseOverCorner := -1;
mouseOverEdge := -1;
mouseOverWidget := -1;
oldSelected := -1;
MemTriangle.x[0] := 1;
MemTriangle.y[0] := 0;
MemTriangle.x[1] := 0;
MemTriangle.y[1] := 0;
MemTriangle.x[2] := 0;
MemTriangle.y[2] := 1;
// AV: reflection start settings
FlipPoint.x := 0;
FlipPoint.y := 1;
// AV: added some "magic" variation parameters presets :)
with vleVariables do
begin
with ItemProps['fan2_x'] do
begin
EditStyle := esPickList;
PickList.Add('1.41421');
PickList.Add('1');
PickList.Add('0.816497');
PickList.Add('0.707107');
PickList.Add('0.57735');
PickList.Add('0.534522');
PickList.Add('0.5');
PickList.Add('0.471405');
PickList.Add('0.447214');
PickList.Add('0.426401');
PickList.Add('0.408248');
end;
with ItemProps['fan2_y'] do
begin
EditStyle := esPickList;
PickList.Add('6.28319');
PickList.Add('4.71239');
PickList.Add('4.18879');
PickList.Add('3.92699');
PickList.Add('3.66519');
PickList.Add('3.59039');
PickList.Add('3.53429');
PickList.Add('3.49066');
PickList.Add('3.45575');
PickList.Add('3.42719');
PickList.Add('3.40339');
end;
with ItemProps['rings2_val'] do
begin
EditStyle := esPickList;
PickList.Add('1');
PickList.Add('1.22474');
PickList.Add('1.41421'); // degenerate case - circumferences
PickList.Add('2');
end;
ItemProps['trianglecrop_mode'].PickList.CommaText := '"0","1","2"';
ItemProps['projective_mode'].PickList.CommaText := '"0","1","2"';;
ItemProps['affine3D_mode'].PickList.CommaText := '"0","1","2"';;
ItemProps['spherecrop_mode'].PickList.CommaText := '"0","1","2"';;
for i := NrLocVar to NumBuiltInVars - 1 do
begin
vn := VarNames(i);
if pos('hypertile', vn) > 0 then
begin
ItemProps[vn + '_p'].PickList.CommaText := '"3","4","5","7","8"';
ItemProps[vn + '_q'].PickList.CommaText := '"3","4","5","7","8"';
end;
end;
if NumBuiltInVars < NrVar then
begin
i := GetVariationIndex('hexes');
if (i > 0) then
with ItemProps['hexes_rotate'] do
begin
EditStyle := esPickList;
PickList.Add('0.166667');
PickList.Add('0.333333');
PickList.Add('0.5');
PickList.Add('0.666667');
PickList.Add('0.833333');
PickList.Add('1');
end;
end;
end;
// MainForm.Buttons.GetBitmap(9, btnResetPivot.Glyph);
// MainForm.Buttons.GetBitmap(9, btnResetFlip.Glyph);
2022-03-08 12:25:51 -05:00
PageControl.ActivePage := tabVariations; // AV
cbCollapseVariations.ItemIndex := 0; // AV
end;
procedure TEditForm.FormDestroy(Sender: TObject);
begin
cp.free;
Render.free;
if FileExists(APPDATA + saved_variations) then DeleteFile(APPDATA + saved_variations);
if FileExists(APPDATA + saved_variables) then DeleteFile(APPDATA + saved_variables);
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.TriangleViewMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: integer);
var
vx, vy, fx, fy: double;
mt, mc, me: integer;
a, t: double;
i, j: integer;
d: double;
i0, i1: integer;
dx, dy, x1, y1: double;
label FoundCorner, Skip1, Skip2;
begin
Scale(fx, fy, x, y);
StatusBar.Panels[0].Text := Format(TextByKey('editor-status-xformat'), [fx]);
StatusBar.Panels[1].Text := Format(TextByKey('editor-status-yformat'), [fy]);
if viewDragMode then // graph panning
begin
if (fx = oldx) and (fy = oldy) then exit;
viewDragged := true;
GcenterX := GcenterX - (fx - oldx);
GcenterY := GcenterY - (fy - oldy);
TriangleView.Refresh;
exit;
end;
mt:=mouseOverTriangle;
mc:=MouseOverCorner;
me:=mouseOverEdge;
if not (CornerCaught or TriangleCaught) then // look for a point under cursor
begin
mouseOverWidget := -1;
mouseOverEdge := -1;
mouseOverCorner:= -1;
mouseOverPos.x := fx;
mouseOverPos.y := fy;
if SelectMode then
begin
i0:=0;
i1:=LastTriangle;//Transforms-1;
end
else begin
i0:=SelectedTriangle;
i1:=i0;
end;
for i := i1 downto i0 do
begin
for j := 0 to 2 do // -- detect point hit first
begin
d := dist(fx, fy, MainTriangles[i].x[j], MainTriangles[i].y[j]);
if (d * GraphZoom * 50) < 4 then
begin
mouseOverTriangle := i;
mouseOverCorner := j;
// mouseOverEdge := -1;
// -- from MouseDown -- for highlighting:
// TODO: optimize...
if (j = 1) then
begin
if PivotMode = pivotLocal then begin
Pivot.x := 0;
Pivot.y := 0;
end
else Pivot := GetPivot;
LocalAxisLocked := true;
end
else begin
Pivot := GetPivot(mouseOverTriangle);
LocalAxisLocked := false;
end;
oldx := MainTriangles[mouseOverTriangle].x[j] - Pivot.X;
oldy := MainTriangles[mouseOverTriangle].y[j] - Pivot.Y;
olddist := Hypot(oldx, oldy);
// --
// -- for Pick Pivot
if editMode = modePick then
begin
mouseOverPos.x := MainTriangles[mouseOverTriangle].x[mouseOverCorner];
mouseOverPos.y := MainTriangles[mouseOverTriangle].y[mouseOverCorner];
end;
// ---
goto FoundCorner;
end;
end;
end;
if ExtendedEdit then //and (oldMode = modeNone) then
begin
for i := 0 to 3 do // -- detect 'widget' hit
for j := 0 to 1 do begin
if abs(line_dist(fx, fy, Widgets[i][j].x, Widgets[i][j].y,
Widgets[i][j+1].x, Widgets[i][j+1].y)
) * GraphZoom * 50 < 3 then
begin
mouseOverTriangle := SelectedTriangle;
mouseOverWidget := i;
// mouseOverEdge := -1;
// mouseOverCorner:= -1;
mouseOverPos.x := fx;
mouseOverPos.y := fy;
goto FoundCorner;
end;
end;
for i := i1 downto i0 do
begin
for j := 0 to 2 do // -- detect edge hit
begin
if abs(line_dist(fx, fy, MainTriangles[i].x[j], MainTriangles[i].y[j],
MainTriangles[i].x[(j+1) mod 3], MainTriangles[i].y[(j+1) mod 3])
) * GraphZoom * 50 < 3 then
begin
mouseOverTriangle:=i;
mouseOverEdge := j;
// mouseOverCorner:= -1;
mouseOverPos.x := fx;
mouseOverPos.y := fy;
goto FoundCorner;
end;
end;
end;
end;
i := InsideTriangle(fx, fy);
if i >= 0 then mouseOverTriangle:=i
else mouseOverTriangle:=-1;
FoundCorner:
end;
if (mouseOverTriangle >= 0) or (SelectMode = false) or (oldMode <> modeNone) then
begin
if (mouseOverWidget >= 0) and (oldMode = modeNone) then
TriangleView.Cursor := crEditRotate
else
if (mouseOverEdge >= 0) and (oldMode = modeNone) then begin // kinda hack, not good...
if mouseOverEdge = 2 then
TriangleView.Cursor := crEditScale
else
TriangleView.Cursor := crEditRotate;
end
else
case editMode of
modeMove:
TriangleView.Cursor := crEditMove;
modeRotate:
TriangleView.Cursor := crEditRotate;
modeScale:
TriangleView.Cursor := crEditScale;
modePick:
TriangleView.Cursor := crEditArrow;
end
end
else
TriangleView.Cursor := crEditArrow; //crDefault;
Shift := Shift - [ssLeft];
if CornerCaught then // Modify a point ///////////////////////////////////////
begin
if (editMode = modeRotate) then // rotate point
begin // rotate point around pivot
d := dist(Pivot.X, Pivot.Y, fx, fy);
if d<>0 then begin
if ssShift in Shift then // angle snap
begin
try
t := StrToFloat(txtTrgRotateValue.Text)/180*PI;
//assert(t<>0);
except
t := 15.0*PI/180.0;
txtTrgRotateValue.Text := '15';
end;
if t = 0 then goto Skip1; //?
a := Round(arctan2(fy-Pivot.Y, fx-Pivot.X)/t)*t;
vx := olddist*cos(a);
vy := olddist*sin(a);
end
else begin
Skip1:
vx := (fx-Pivot.X)*olddist/d;
vy := (fy-Pivot.Y)*olddist/d;
a := arctan2(vy,vx) - arctan2(oldy,oldx);
end;
if LocalAxisLocked then with MainTriangles[SelectedTriangle] do
begin
assert(SelectedCorner = 1);
x[0] := OldTriangle.x[0] + Pivot.X+vx - OldTriangle.x[1];
y[0] := OldTriangle.y[0] + Pivot.Y+vy - OldTriangle.y[1];
x[2] := OldTriangle.x[2] + Pivot.X+vx - OldTriangle.x[1];
y[2] := OldTriangle.y[2] + Pivot.Y+vy - OldTriangle.y[1];
end;
MainTriangles[SelectedTriangle].x[SelectedCorner] := Pivot.X+vx;
MainTriangles[SelectedTriangle].y[SelectedCorner] := Pivot.Y+vy;
end
else a := 0;
vy := abs(
arctan2(MainTriangles[SelectedTriangle].y[0]-MainTriangles[SelectedTriangle].y[1],
MainTriangles[SelectedTriangle].x[0]-MainTriangles[SelectedTriangle].x[1])
-arctan2(MainTriangles[SelectedTriangle].y[2]-MainTriangles[SelectedTriangle].y[1],
MainTriangles[SelectedTriangle].x[2]-MainTriangles[SelectedTriangle].x[1])
);
if vy > PI then vy := 2*PI - vy;
StatusBar.Panels[2].Text := Format(TextByKey('editor-status-rotateformat'), [a*180/PI, vy*180/PI]);
end
else if (editMode = modeScale) then
begin // move point along vector ("scale")
if olddist<>0 then begin
d := (oldx*(fx-Pivot.X) + oldy*(fy-Pivot.Y))/olddist;
if ssShift in Shift then // 'snapped' scale
begin
try // use move-value for 'scaling' point:
t := abs(StrToFloat(txtTrgMoveValue.Text));
//assert(t<>0);
except
t := 0.1;
txtTrgMoveValue.Text := '0.1';
end;
if t <> 0 then d := Trunc(d/t)*t;
end;
vx := oldx*d/olddist;
vy := oldy*d/olddist;
if LocalAxisLocked then with MainTriangles[SelectedTriangle] do
begin
assert(SelectedCorner = 1);
x[0] := OldTriangle.x[0] + Pivot.X+vx - OldTriangle.x[1];
y[0] := OldTriangle.y[0] + Pivot.Y+vy - OldTriangle.y[1];
x[2] := OldTriangle.x[2] + Pivot.X+vx - OldTriangle.x[1];
y[2] := OldTriangle.y[2] + Pivot.Y+vy - OldTriangle.y[1];
end;
MainTriangles[SelectedTriangle].x[SelectedCorner] := Pivot.X + vx;
MainTriangles[SelectedTriangle].y[SelectedCorner] := Pivot.Y + vy;
StatusBar.Panels[2].Text := Format(TextByKey('editor-status-scaleformat'),
[Hypot(vx, vy), d*100/olddist]);
end
else begin
MainTriangles[SelectedTriangle].x[SelectedCorner] := Pivot.X;
MainTriangles[SelectedTriangle].y[SelectedCorner] := Pivot.Y;
end;
end
else begin // snap/move
if ssShift in Shift then // snap to axis
begin
if abs(fx-Pivot.X) > abs(fy-Pivot.Y) then begin
vx := fx;
vy := Pivot.Y;
end
else begin
vx := Pivot.x;
vy := fy;
end;
end
else begin // just move
vx := fx;
vy := fy;
end;
if (SelectedCorner = 1) and AxisLock then with MainTriangles[SelectedTriangle] do
begin
x[0] := OldTriangle.x[0] + (vx - OldTriangle.x[1]);
y[0] := OldTriangle.y[0] + (vy - OldTriangle.y[1]);
x[2] := OldTriangle.x[2] + (vx - OldTriangle.x[1]);
y[2] := OldTriangle.y[2] + (vy - OldTriangle.y[1]);
end;
MainTriangles[SelectedTriangle].x[SelectedCorner] := vx;
MainTriangles[SelectedTriangle].y[SelectedCorner] := vy;
StatusBar.Panels[2].Text := Format(TextByKey('editor-status-moveformat'), [vx-(Pivot.X+oldx), vy-(Pivot.Y+oldy)]);
end;
// --
HasChanged := True;
UpdateFlameX;
// UpdateFlame(False);
StatusBar.Refresh;
exit;
end
else if TriangleCaught then // Modify a whole triangle ///////////////////////
begin
if (editMode = modeRotate) then // rotate triangle
begin
a := arctan2(fy-Pivot.Y, fx-Pivot.X) - arctan2(oldy, oldx);
if ssShift in Shift then // angle snap
begin
try
t := StrToFloat(txtTrgRotateValue.Text)/180*PI;
//assert(t<>0);
except
t := 15.0*PI/180.0;
txtTrgRotateValue.Text := '15';
end;
if t = 0 then goto Skip2;
a := Round(a/t)*t
end;
Skip2:
MainTriangles[SelectedTriangle] :=
RotateTrianglePoint(OldTriangle, Pivot.X, Pivot.Y, a);
vx := MainTriangles[SelectedTriangle].x[0]-MainTriangles[SelectedTriangle].x[1];
vy := MainTriangles[SelectedTriangle].y[0]-MainTriangles[SelectedTriangle].y[1];
if abs(vx*(MainTriangles[SelectedTriangle].x[2]-MainTriangles[SelectedTriangle].x[1])+
vy*(MainTriangles[SelectedTriangle].y[2]-MainTriangles[SelectedTriangle].y[1])) < 0.001
then
StatusBar.Panels[2].Text := Format(TextByKey('editor-status-rotateformat2'), [a*180/PI, arctan2(vy, vx)*180/PI])
else StatusBar.Panels[2].Text := Format(TextByKey('editor-status-rotateformat3'), [a*180/PI]);
end
else if (editMode = modeScale) then // scale
begin
if olddist<>0 then begin
vy := (oldx*(fx-Pivot.X) + oldy*(fy-Pivot.Y))/sqr(olddist);
if ssShift in Shift then // 'snapped' scale
begin
try
t := abs(StrToFloat(txtTrgScaleValue.Text)/100.0 - 1.0);
//assert(t<>0);
except
t := 0.1;
txtTrgRotateValue.Text := '0.1';
end;
if t <> 0 then vy := Trunc(vy/t)*t;
end;
MainTriangles[SelectedTriangle] :=
ScaleTrianglePoint(OldTriangle, Pivot.X, Pivot.Y, vy);
StatusBar.Panels[2].Text := Format(TextByKey('editor-status-scaleformat2'), [vy*100]);
end
else MainTriangles[SelectedTriangle] := OldTriangle;
end
else begin // snap/move
vx := fx - (Pivot.x + oldx);
vy := fy - (Pivot.y + oldy);
if ssShift in Shift then // snap to axis
begin
if abs(vx) > abs(vy) then vy := 0
else vx := 0;
end;
with MainTriangles[SelectedTriangle] do
begin
x[0] := OldTriangle.x[0] + vx;
y[0] := OldTriangle.y[0] + vy;
x[1] := OldTriangle.x[1] + vx;
y[1] := OldTriangle.y[1] + vy;
x[2] := OldTriangle.x[2] + vx;
y[2] := OldTriangle.y[2] + vy;
end;
StatusBar.Panels[2].Text := Format(TextByKey('editor-status-moveformat2'), [vx, vy]);
end;
HasChanged := True;
UpdateFlameX;
// UpdateFlame(False);
StatusBar.Refresh;
exit;
end;
if ((mt <> mouseOverTriangle) or (mc <> MouseOverCorner) or (me <> MouseOverEdge)) then
begin
if (mouseOverTriangle >= 0) then
StatusBar.Panels[2].Text := Format(TextByKey('editor-status-transformformat'), [mouseOverTriangle+1])
else StatusBar.Panels[2].Text := '';
TriangleView.Refresh;
end
else if editMode = modePick then TriangleView.Refresh; // hmm...
end;
procedure TEditForm.TriangleViewMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: integer);
var
d, fx, fy: double;
i, j: integer;
i0, i1: integer;
label
FoundTriangle;
begin
TWinControl(Sender).SetFocus;
viewDragged := false;
Scale(fx, fy, x, y);
if Button = mbLeft then
begin
if editMode = modePick then
begin
if (mouseOverCorner >= 0) then // snap to point
begin
fx := MainTriangles[mouseOverTriangle].x[mouseOverCorner];
fy := MainTriangles[mouseOverTriangle].y[mouseOverCorner];
end;
if PivotMode = pivotLocal then
with MainTriangles[SelectedTriangle] do begin
// xx := x[0] - x[1];
// xy := y[0] - y[1];
// yx := x[2] - x[1];
// yy := y[2] - y[1];
d := (xx*yy - yx*xy);
if d <> 0 then
begin
LocalPivot.x := ( (fx - x[1]) * yy - (fy - y[1]) * yx) / d;
LocalPivot.y := (-(fx - x[1]) * xy + (fy - y[1]) * xx) / d;
end
end
else begin
WorldPivot.x := fx;
WorldPivot.y := fy;
end;
editMode := oldMode;
oldMode := modeNone;
btnPickPivot.Down := false;
ShowSelectedInfo;
TriangleView.Invalidate;
exit;
end;
Shift := Shift - [ssLeft];
if SelectMode then
begin
i0:=0;
i1:=LastTriangle;
end
else begin // Only check selected triangle
i0:=SelectedTriangle;
i1:=i0;
end;
oldSelected := SelectedTriangle;
for i := i1 downto i0 do
begin
for j := 0 to 2 do // detect corner hit
begin
d := dist(fx, fy, MainTriangles[i].x[j], MainTriangles[i].y[j]);
if (d * GraphZoom * 50) < 4 then
begin
SelectedTriangle := i;
CornerCaught := True;
SelectedCorner := j;
// Pivot := GetPivot;
if (j = 1) then
2022-03-08 12:25:51 -05:00
begin
if PivotMode = pivotLocal then begin
Pivot.x := 0;
Pivot.y := 0;
end
else Pivot := GetPivot;
LocalAxisLocked := true;
end
else begin
Pivot := GetPivot;
LocalAxisLocked := false;
end;
OldTriangle := MainTriangles[SelectedTriangle];
oldx := MainTriangles[SelectedTriangle].x[j] - Pivot.X;
oldy := MainTriangles[SelectedTriangle].y[j] - Pivot.Y;
olddist := sqrt(sqr(oldx) + sqr(oldy));
HasChanged := false;
ShowSelectedInfo;
TriangleView.Invalidate;
UpdateSyncTriangles; // AV
2022-03-08 12:25:51 -05:00
exit;
end;
end;
end;
if ExtendedEdit then //and (oldMode = modeNone) then
begin
for i := 0 to 3 do // -- detect 'widget' hit
for j := 0 to 1 do
begin
if abs(line_dist(fx, fy, Widgets[i][j].x, Widgets[i][j].y,
Widgets[i][j+1].x, Widgets[i][j+1].y)
) * GraphZoom * 50 < 3 then
begin
// modeHack := true;
if (oldMode = modeNone) then
begin
modeHack := true;
oldMode := editMode;
editMode := modeRotate;
end;
goto FoundTriangle;
end;
end;
for i := i1 downto i0 do
begin
for j := 0 to 2 do // -- detect edge hit
begin
if abs(line_dist(fx, fy, MainTriangles[i].x[j], MainTriangles[i].y[j],
MainTriangles[i].x[(j+1) mod 3], MainTriangles[i].y[(j+1) mod 3])
) * GraphZoom * 50 < 3 then
begin
SelectedTriangle := i;
EdgeCaught := true;
// modeHack := true;
if (oldMode = modeNone) then
begin
modeHack := true;
oldMode := editMode;
if j = 2 then
editMode := modeScale
else
if AxisLock then editMode := modeRotate
else
begin
// hacky...
CornerCaught := True;
editMode := modeRotate;
if j = 1 then SelectedCorner := 2
else SelectedCorner := 0;
Pivot := GetPivot;
LocalAxisLocked := false;
OldTriangle := MainTriangles[SelectedTriangle];
oldx := MainTriangles[SelectedTriangle].x[SelectedCorner] - Pivot.X;
oldy := MainTriangles[SelectedTriangle].y[SelectedCorner] - Pivot.Y;
olddist := sqrt(sqr(oldx) + sqr(oldy));
HasChanged := false;
ShowSelectedInfo;
TriangleView.Invalidate;
UpdateSyncTriangles; // AV
exit;
end;
2022-03-08 12:25:51 -05:00
end;
goto FoundTriangle;
end;
end;
end;
end;
// so user hasn't selected any corners,
// let's check for triangles then!
if SelectMode then
begin
i := InsideTriangle(fx, fy);
if i >= 0 then SelectedTriangle := i
else
if (oldMode = modeNone) and not(ssShift in Shift) then exit;
end;
FoundTriangle:
TriangleCaught := True;
OldTriangle := MainTriangles[SelectedTriangle];
//MainForm.UpdateUndo;
HasChanged := false;
Pivot := GetPivot;
oldx := fx-Pivot.X;
oldy := fy-Pivot.Y;
olddist := sqrt(oldx*oldx + oldy*oldy);
UpdateVariationList; // AV
UpdateSyncTriangles; // AV
ShowSelectedInfo;
2022-03-08 12:25:51 -05:00
TriangleView.Invalidate;
exit;
end
else if (Button = mbRight) and
not (TriangleCaught or CornerCaught) then // graph panning
begin
SetCaptureControl(TriangleView);
Screen.Cursor := crSizeAll;
viewDragMode := true;
oldx := fx;
oldY := fy;
end;
end;
procedure TEditForm.TriangleViewMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: integer);
begin
if Button = mbLeft then
begin
if modeHack then begin
assert(oldMode <> modeNone);
editMode := oldMode;
oldMode := modeNone;
modeHack := false;
end;
if HasChanged then
begin
MainForm.UpdateUndo;
UpdateFlame(true);
HasChanged := False;
end;
EdgeCaught := false;
CornerCaught := false;
TriangleCaught := false;
TriangleView.Invalidate;
end
else if (Button = mbRight) and viewDragMode then
begin
viewDragMode := false;
Screen.Cursor := crDefault;
SetCaptureControl(nil);
if viewDragged = false then // haven't dragged - popup menu then
begin
//GetCursorPos(mousepos); // hmmm
mousePos := (Sender as TControl).ClientToScreen(Point(x, y));
if mouseOverTriangle < 0 then
EditPopup.Popup(mousepos.x, mousepos.y)
else begin
SelectedTriangle := mouseOverTriangle;
cbTransforms.ItemIndex := SelectedTriangle;
TriangleView.Refresh;
TrianglePopup.Popup(mousepos.x, mousepos.y)
end;
end
else viewDragged := false;
end
end;
// AV: added standart shotcuts for numeric feilds
procedure TEditForm.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
if GetKeyState(VK_CONTROL) >= 0 then
Exit;
if Msg.CharCode = Ord('W') then begin
CreateScreenShot;
Handled := True;
end;
if (ActiveControl = txtName) or (ActiveControl = txtSearchBox) then Exit;
if not ((ActiveControl is TEdit) or (ActiveControl is TComboBox)) then Exit;
if Msg.CharCode = Ord('C') then begin
SendMessage(ActiveControl.Handle, WM_COPY, 0, 0);
Handled := True;
end
else
if Msg.CharCode = Ord('V') then begin
if not Clipboard.HasFormat(CF_TEXT) then
Handled := False
else begin
if StrToFloatDef(Clipboard.AsText, MaxDouble) <> MaxDouble then // hack
begin
SendMessage(ActiveControl.Handle, WM_PASTE, 0, 0);
Handled := True;
end
else
Handled := False;
end;
end
else
if Msg.CharCode = Ord('X') then begin
SendMessage(ActiveControl.Handle, WM_CUT, 0, 0);
Handled := True;
end
else
if Msg.CharCode = Ord('U') then begin
if (ActiveControl is TEdit) and TEdit(ActiveControl).CanUndo then
begin
TEdit(ActiveControl).Undo;
//SendMessage(ActiveControl.Handle, WM_UNDO, 0, 0);
Handled := True;
end
else
Handled := False;
end;
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');
if Registry.ValueExists('ResetLocation') then
mnuResetLoc.checked := Registry.ReadBool('ResetLocation')
else
mnuResetLoc.checked := false;
if Registry.ValueExists('HelpersEnabled') then
HelpersEnabled := Registry.ReadBool('HelpersEnabled')
else
HelpersEnabled := true;
if Registry.ValueExists('VariationPreview') then
begin
showVarPreview := Registry.ReadBool('VariationPreview');
tbVarPreview.Down := showVarPreview;
end
else begin
showVarPreview := false;
tbVarPreview.Down := false;
end;
if Registry.ValueExists('VariationPreviewRange') then
trkVarPreviewRange.Position := Registry.ReadInteger('VariationPreviewRange');
if Registry.ValueExists('VariationPreviewDensity') then
trkVarPreviewDensity.Position := Registry.ReadInteger('VariationPreviewDensity');
if Registry.ValueExists('VariationPreviewDepth') then
trkVarPreviewDepth.Position := Registry.ReadInteger('VariationPreviewDepth');
if Registry.ValueExists('VariationPreviewGrid') then
GridComboBox.ItemIndex := Registry.ReadInteger('VariationPreviewGrid');
if Registry.ValueExists('VariationFilter') then
cbCollapseVariations.ItemIndex := Registry.ReadInteger('VariationFilter');
end
else begin
UseFlameBackground := False;
mnuResetLoc.checked := false;
end;
Registry.CloseKey;
finally
Registry.Free;
end;
if ExtendedEdit then tbExtendedEdit.Down := true
else tbMove.Down := true;
AdjustSyncTriangles; // AV
2022-03-08 12:25:51 -05:00
UpdateDisplay;
TrianglePanelResize(nil);
ScrollBox1Resize(nil);
end;
procedure TEditForm.mnuDeleteClick(Sender: TObject);
begin
if (SelectedTriangle >= 0) then DeleteTriangle(SelectedTriangle);
end;
procedure TEditForm.mnuAddClick(Sender: TObject);
begin
if Transforms < NXFORMS then
begin
MainForm.UpdateUndo;
MainTriangles[Transforms+1] := MainTriangles[Transforms];
cp.xform[Transforms+1].Assign(cp.xform[Transforms]);
MainTriangles[Transforms] := MainTriangles[-1];
SelectedTriangle := Transforms;
cp.xform[Transforms].Clear(hasLinkX);
cp.xform[Transforms].density := 0.5;
cp.xform[Transforms].SetVariation(0, 1);
Inc(Transforms);
UpdateXformsList;
UpdateFlame(True);
end;
end;
procedure TEditForm.mnuDupClick(Sender: TObject);
var
i: integer;
begin
if Transforms < NXFORMS then
begin
MainForm.UpdateUndo;
MainTriangles[Transforms+1] := MainTriangles[Transforms];
cp.xform[Transforms+1].Assign(cp.xform[Transforms]);
if SelectedTriangle <> Transforms then
begin
MainTriangles[Transforms] := MainTriangles[SelectedTriangle];
cp.xform[Transforms].Assign(cp.xform[SelectedTriangle]);
for i := 0 to Transforms-1 do
cp.xform[i].modWeights[Transforms] := cp.xform[i].modWeights[SelectedTriangle];
cp.xform[Transforms].modWeights[Transforms] := cp.xform[SelectedTriangle].modWeights[SelectedTriangle];
SelectedTriangle := Transforms;
end
else cp.xform[Transforms].density := 0.5;
Inc(Transforms);
UpdateXformsList;
UpdateFlame(True);
end;
end;
procedure TEditForm.mnuAutoZoomClick(Sender: TObject);
begin
AutoZoom;
end;
procedure TEditForm.btChaosClick(Sender: TObject);
begin
vleChaos.SetFocus;
ChaosPopup.Popup(btChaos.ClientOrigin.x, btChaos.ClientOrigin.y + btChaos.Height);
end;
procedure TEditForm.btConjugateClick(Sender: TObject);
var
deta: double;
begin
if not tbPostXSwap.Down then
begin
with cp.xform[SelectedTriangle] do
begin
deta := detC; // pre-affine determinant
2022-03-08 12:25:51 -05:00
if (abs(deta) < 1E-4) then
begin
Application.MessageBox(PChar(TextByKey('editor-status-warninvert')),
ApophysisSVN, MB_ICONWARNING);
2022-03-08 12:25:51 -05:00
exit;
end;
MainForm.UpdateUndo;
p[0,0] := c[1,1] / deta; // d
p[0,1] := -c[0,1] / deta; // -c
p[1,0] := -c[1,0] / deta; // -b
p[1,1] := c[0,0] / deta; // a
p[2,0] := (c[1,0] * c[2,1] - c[1,1] * c[2,0]) / deta; // -d*e + b*f
p[2,1] := (c[0,1] * c[2,0] - c[0,0] * c[2,1]) / deta; // c*e - a*f
end;
cp.GetTriangle(MainTriangles[SelectedTriangle], SelectedTriangle);
end else
begin
with cp.xform[SelectedTriangle] do
begin
deta := detP; // post-affine determinant
2022-03-08 12:25:51 -05:00
if (abs(deta) < 1E-4) then
begin
Application.MessageBox(PChar(TextByKey('editor-status-warninvert')),
ApophysisSVN, MB_ICONWARNING);
2022-03-08 12:25:51 -05:00
exit;
end;
MainForm.UpdateUndo;
c[0,0] := p[1,1] / deta;
c[0,1] := -p[0,1] / deta;
c[1,0] := -p[1,0] / deta;
c[1,1] := p[0,0] / deta;
c[2,0] := (p[1,0] * p[2,1] - p[1,1] * p[2,0]) / deta;
c[2,1] := (p[0,1] * p[2,0] - p[0,0] * p[2,1]) / deta;
end;
cp.GetPostTriangle(MainTriangles[SelectedTriangle], SelectedTriangle);
end;
UpdateFlame(true);
end;
procedure TEditForm.btFlipXYClick(Sender: TObject);
begin
if (editPivotX.Text <> '0') or (editPivotY.Text <> '0') then
btnResetPivot.Click;
if (Sender = btFlipX) then
begin
FlipPoint.x := 1; editFlipX.Text := '1';
FlipPoint.y := 0; editFlipY.Text := '0';
end
else if (Sender = btFlipY) then
begin
FlipPoint.x := 0; editFlipX.Text := '0';
FlipPoint.y := 1; editFlipY.Text := '1';
end else // if Sender = btFlipDiag then
begin
FlipPoint.x := 1; editFlipX.Text := '1';
FlipPoint.y := 1; editFlipY.Text := '1';
end;
if not ShowFlipLine then CalcFlip // refresh current angle
else TriangleView.Invalidate; // refresh angle and image
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.btnCloseClick(Sender: TObject);
begin
EditForm.Close;
end;
procedure TEditForm.FormResize(Sender: TObject);
begin
AutoZoom;
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
if SelectedTriangle < Transforms 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);
TEdit(Sender).Text := Format('%.6g', [cp.xform[SelectedTriangle].density]);
end;
MainForm.UpdateUndo;
UpdateFlame(True);
end;
self.LastFocus := TEdit(sender);
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);
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 = '-') then Key:= #0;
if SelectedTriangle >= Transforms then key := #0;
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.000001 then NewVal := 0.000001;
if NewVal > MAX_WEIGHT then NewVal := MAX_WEIGHT;
{ 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);
if ChaosForm.Visible then // AV
ChaosForm.WeightVector.Invalidate;
end;
end;
end;
procedure TEditForm.txtPExit(Sender: TObject);
var
Allow: boolean;
NewVal, OldVal: double;
begin
if SelectedTriangle >= Transforms then exit;
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.000001 then NewVal := 0.000001;
if NewVal > MAX_WEIGHT then NewVal := MAX_WEIGHT;
{ 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);
if ChaosForm.Visible then // AV
ChaosForm.WeightVector.Invalidate;
end;
self.LastFocus := TEdit(sender);
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('ResetLocation', mnuResetLoc.checked);
Registry.WriteBool('VariationPreview', showVarPreview);
Registry.WriteBool('HelpersEnabled', HelpersEnabled);
Registry.WriteInteger('VariationPreviewRange', trkVarPreviewRange.Position);
Registry.WriteInteger('VariationPreviewDensity', trkVarPreviewDensity.Position);
Registry.WriteInteger('VariationPreviewDepth', trkVarPreviewDepth.Position);
Registry.WriteInteger('VariationPreviewGrid', GridComboBox.ItemIndex);
Registry.WriteInteger('VariationFilter', cbCollapseVariations.ItemIndex);
{ 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;
// AV: free memory
SetLength(MemChaos, 0);
mnuPasteChaos.Enabled := False;
PasteChaos.Enabled := False;
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.mnuUndoClick(Sender: TObject);
begin
MainForm.Undo;
end;
procedure TEditForm.MulDiv2Click(Sender: TObject);
var
num: double;
sn: string;
begin
if (not ValidNumField) then
begin
Application.MessageBox(PChar(TextByKey('editor-status-nonumfield')),
ApophysisSVN, MB_ICONWARNING);
2022-03-08 12:25:51 -05:00
exit;
end;
if (txtTrgRotateValue.Focused) and (TMenuItem(Sender).Tag = 0) then exit;
try
if (ActiveControl is TEdit) then
sn := TEdit(ActiveControl).Text
else if (ActiveControl is TValueListEditor) then
sn := TValueListEditor(ActiveControl).Cells[1, TValueListEditor(ActiveControl).Row]
else // if (ActiveControl is TComboBox) then
sn := TComboBox(ActiveControl).Text;
num := StrToFloat(sn);
if (num <> 0) then
begin
case TMenuItem(Sender).Tag of
0: if (txtTrgScaleValue.Focused) then
sn := Format('%.6g', [num * num * 0.01])
else sn := Format('%.6g', [num * num]);
2022-03-08 12:25:51 -05:00
1: sn := Format('%.6g', [num * 2]);
2: sn := Format('%.6g', [num * 0.5]);
else if (txtTrgScaleValue.Focused) then
sn := Format('%.6g', [sign(num) * sqrt(abs(num * 0.01)) * 100])
else sn := Format('%.6g', [sign(num) * sqrt(abs(num))]);
end;
if (ActiveControl is TEdit) then
begin
TEdit(ActiveControl).Text := sn;
TEdit(ActiveControl).OnExit(ActiveControl);
end
else if (ActiveControl is TValueListEditor) then
begin
TValueListEditor(ActiveControl).Cells[1, TValueListEditor(ActiveControl).Row] := sn;
TValueListEditor(ActiveControl).OnExit(ActiveControl);
end
else //if (ActiveControl is TComboBox) then
TComboBox(ActiveControl).Text := sn;
end;
except
end;
end;
procedure TEditForm.NormChaosClick(Sender: TObject);
var i, j: smallint;
2022-03-08 12:25:51 -05:00
sum: double;
begin
MainForm.UpdateUndo;
for i := 0 to Transforms-1 do
begin
sum := 0;
for j := 0 to Transforms-1 do
sum := sum + cp.xform[i].modWeights[j];
if (sum = 1.0) or (sum = 0.0) then continue;
for j := 0 to Transforms-1 do
cp.xform[i].modWeights[j] := cp.xform[i].modWeights[j] / sum;
2022-03-08 12:25:51 -05:00
end;
UpdateFlame(True);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
procedure TEditForm.mnuRedoClick(Sender: TObject);
begin
MainForm.Redo;
end;
procedure TEditForm.mnuLowQualityClick(Sender: TObject);
begin
mnuLowQuality.Checked := True;
mnuELowQuality.Checked := True;
PreviewDensity := prevLowQuality;
EditPrevQual := 0;
DrawPreview;
TriangleViewPaint(TriangleView);
end;
procedure TEditForm.mnuHighQualityClick(Sender: TObject);
begin
mnuHighQuality.Checked := True;
mnuEHighQuality.Checked := True;
PreviewDensity := prevHighQuality;
EditPrevQual := 2;
DrawPreview;
TriangleViewPaint(TriangleView);
end;
procedure TEditForm.mnuMediumQualityClick(Sender: TObject);
begin
mnuMediumQuality.Checked := True;
mnuEMediumQuality.Checked := True;
PreviewDensity := prevMediumQuality;
EditPrevQual := 1;
DrawPreview;
TriangleViewPaint(TriangleView);
end;
procedure TEditForm.mnuResetLocClick(Sender: TObject);
var
reset: boolean;
begin
reset:= not mnuResetLoc.Checked;
mnuResetLoc.Checked := reset;
if reset then
begin
cp.width := MainCp.width;
cp.height := MainCp.height;
cp.pixels_per_unit := MainCp.pixels_per_unit;
cp.AdjustScale(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.mnuFlipAllVClick(Sender: TObject);
var
i: smallint;
2022-03-08 12:25:51 -05:00
begin
MainForm.UpdateUndo;
for i := -1 to Transforms do
begin
MainTriangles[i] := FlipTriangleVertical(MainTriangles[i]);
end;
cp.GetFromTriangles(MainTriangles, Transforms);
cp.TrianglesFromCP(MainTriangles);
AutoZoom;
UpdateFlame(True);
end;
procedure TEditForm.mnuFlipAllHClick(Sender: TObject);
var
i: smallint;
2022-03-08 12:25:51 -05:00
begin
MainForm.UpdateUndo;
for i := -1 to Transforms do
begin
MainTriangles[i] := FlipTriangleHorizontal(MainTriangles[i]);
end;
cp.GetFromTriangles(MainTriangles, Transforms);
cp.TrianglesFromCP(MainTriangles);
AutoZoom;
UpdateFlame(True);
end;
procedure TEditForm.mnuFlipAllLineClick(Sender: TObject); // AV
var
i: smallint;
2022-03-08 12:25:51 -05:00
begin
if (FlipPoint.x = 0) and (FlipPoint.y = 0) then exit;
if (FlipPoint.x = 0) then mnuFlipAllH.Click
else if (FlipPoint.y = 0) then mnuFlipAllV.Click
else begin
MainForm.UpdateUndo;
for i := -1 to Transforms do
MainTriangles[i] := FlipTriangleLine(MainTriangles[i], 0, 0,
FlipPoint.x, FlipPoint.y);
cp.GetFromTriangles(MainTriangles, Transforms);
cp.TrianglesFromCP(MainTriangles);
AutoZoom;
UpdateFlame(True);
end;
end;
procedure TEditForm.mnuFlipVerticalClick(Sender: TObject);
var
p: double;
i: integer;
2022-03-08 12:25:51 -05:00
begin
MainForm.UpdateUndo;
if (not UseTriangleSync) or (SelectedTriangle = Transforms) then
with MainTriangles[SelectedTriangle] do
begin
p := GetPivot.y * 2;
y[0] := p - y[0];
y[1] := p - y[1];
y[2] := p - y[2];
end
else for i in SyncTriangles do
with MainTriangles[i] do
begin
p := GetPivot(i).y * 2;
y[0] := p - y[0];
y[1] := p - y[1];
y[2] := p - y[2];
end;;
2022-03-08 12:25:51 -05:00
//AutoZoom;
UpdateFlame(True);
end;
procedure TEditForm.mnuFlipHorizontalClick(Sender: TObject);
var
p: double;
i: integer;
2022-03-08 12:25:51 -05:00
begin
MainForm.UpdateUndo;
if (not UseTriangleSync) or (SelectedTriangle = Transforms) then
with MainTriangles[SelectedTriangle] do
begin
p := GetPivot.x * 2;
x[0] := p - x[0];
x[1] := p - x[1];
x[2] := p - x[2];
end
else for i in SyncTriangles do
with MainTriangles[i] do
begin
p := GetPivot(i).x * 2;
x[0] := p - x[0];
x[1] := p - x[1];
x[2] := p - x[2];
end;
2022-03-08 12:25:51 -05:00
//AutoZoom;
UpdateFlame(True);
end;
procedure TEditForm.cbTransformsChange(Sender: TObject);
var
n: smallint;
2022-03-08 12:25:51 -05:00
begin
n := cbTransforms.ItemIndex;
if (n <> SelectedTriangle) and (n >= 0) and (n <= LastTriangle) then
begin
SelectedTriangle := n;
UpdateVariationList; // AV
ShowSelectedInfo;
TriangleView.Invalidate;
end;
UpdateSyncTriangles; // AV
end;
procedure TEditForm.UpdateSyncTriangles;
var n: smallint;
begin
if SelectedTriangle in SyncTriangles then exit;
for n := 0 to Transforms-1 do
if mnuSyncTriangles.Items[n].Checked then
mnuSyncTriangles.Items[n].Click;
if SelectedTriangle < Transforms then
mnuSyncTriangles.Items[SelectedTriangle].Click;
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.cbTransformsDrawItem(Control: TWinControl;
Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
h: integer;
ax,ay,bx,by: integer;
TrgColor: TColor;
begin
assert(Index >= 0);
TrgColor := GetTriangleColor(Index);
with cbTransforms.Canvas do
begin
h := Rect.Bottom - Rect.Top;
brush.Color:=clBlack;
FillRect(Rect);
Font.Color := clWhite;
TextOut(Rect.Left+h+2, Rect.Top, cbTransforms.Items[Index]); //IntToStr(Index+1));
pen.Color := TrgColor;
brush.Color := pen.Color shr 1 and $7f7f7f;
ax:=Rect.Left+h-2;
ay:=Rect.Top+1;
bx:=Rect.Left+2;
by:=Rect.Bottom-3;
Polygon([Point(ax, ay), Point(ax, by), Point(bx, by)]);
end;
end;
procedure TEditForm.ChaosClearBelowClick(Sender: TObject);
var i, n: smallint;
2022-03-08 12:25:51 -05:00
begin
n := vleChaos.Row;
if n = Transforms then exit;
MainForm.UpdateUndo;
if mnuChaosViewTo.Checked then
for i := n to Transforms-1 do
cp.xform[SelectedTriangle].modWeights[i] := 0
else for i := n to Transforms-1 do
cp.xform[i].modWeights[SelectedTriangle] := 0;
UpdateFlame(true);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
procedure TEditForm.ClearAllAboveClick(Sender: TObject);
var i, n: smallint;
2022-03-08 12:25:51 -05:00
begin
n := vleChaos.Row;
if (n < 2) then exit;
MainForm.UpdateUndo;
if mnuChaosViewTo.Checked then
for i := 0 to n-2 do
cp.xform[SelectedTriangle].modWeights[i] := 0
else for i := 0 to n-2 do
cp.xform[i].modWeights[SelectedTriangle] := 0;
UpdateFlame(true);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
procedure TEditForm.CoefKeyPress(Sender: TObject; var Key: Char);
begin
if key <> #13 then exit;
key := #0;
CoefValidate(Sender);
end;
procedure TEditForm.CoefValidate(Sender: TObject);
var
NewVal: double;
x, y, r, a: double; // dumb... must optimize
begin
try
NewVal := Round6(StrToFloat(TEdit(Sender).Text));
except on Exception do
begin
ShowSelectedInfo; //TEdit(Sender).Text := Format('%.6g', [pVal^]);
exit;
end;
end;
//TEdit(Sender).Text := Format('%.6g', [NewVal]);
MainForm.UpdateUndo; // TODO - prevent unnecessary UpdateUndo...
with cp.xform[SelectedTriangle] do
begin
if btnCoefsRect.Down = true then
begin
if Sender = txtA then c[0][0] := NewVal
else if Sender = txtB then c[0][1] := -NewVal
else if Sender = txtC then c[1][0] := -NewVal
else if Sender = txtD then c[1][1] := NewVal
else if Sender = txtE then c[2][0] := NewVal
else if Sender = txtF then c[2][1] := -NewVal;
end
else begin
if (Sender = txtA) or (Sender = txtB) then begin
x := c[0][0];
y := -c[0][1];
end else
if (Sender = txtC) or (Sender = txtD) then begin
x := -c[1][0];
y := c[1][1];
end else
{if (Sender = txtE) or (Sender = txtF) then}
begin
x := c[2][0];
y := -c[2][1];
end;
r := Hypot(x, y);
a := arctan2(y, x);
if (Sender = txtA) or (Sender = txtC) or (Sender = txtE) then
r := NewVal
else
a := NewVal*PI/180;
x := r * cos(a);
y := r * sin(a);
if (Sender = txtA) or (Sender = txtB) then begin
c[0][0] := x;
c[0][1] := -y;
end else
if (Sender = txtC) or (Sender = txtD) then begin
c[1][0] := -x;
c[1][1] := y;
end else
{if (Sender = txtE) or (Sender = txtF) then}
begin
c[2][0] := x;
c[2][1] := -y;
end;
end;
end;
cp.TrianglesFromCP(MainTriangles);
if tbAutoWeights.Down then cp.CalculateWeights; // AV
ShowSelectedInfo;
UpdateFlame(true);
self.LastFocus := TEdit(sender);
end;
procedure TEditForm.scrlXFormColorScroll(Sender: TObject;
ScrollCode: TScrollCode; var ScrollPos: Integer);
begin
if (ScrollCode = scEndScroll) and HasChanged then begin
MainForm.UpdateUndo;
UpdateFlame(True);
end;
end;
procedure TEditForm.scrlXFormColorChange(Sender: TObject);
var
v: double;
begin
if updating then exit;
v := (scrlXFormColor.Position) / scrlXFormColor.Max;
if v <> cp.xform[SelectedTriangle].color then
begin
cp.xform[SelectedTriangle].color := v;
pnlXFormColor.color := ColorValToColor(MainCp.cmap, v);
shColor.Brush.Color := pnlXFormColor.Color;
txtXFormColor.Text := Format('%1.3f', [v]);
txtXFormColor.Refresh;
HasChanged := true;
DrawPreview;
end;
end;
function TEditForm.ValidNumField: boolean;
begin
Result := (ActiveControl is TEdit);
if Result then
if (ActiveControl = txtSearchBox) or (ActiveControl = txtName) then
Exit(False);
Result := Result or (ActiveControl is TValueListEditor) or
((ActiveControl is TComboBox) and (ActiveControl.Parent = gbTrgOperations));
2022-03-08 12:25:51 -05:00
end;
(*
procedure TEditForm.chkUseXFormColorClick(Sender: TObject);
begin
UseTransformColors := chkUseXFormColor.checked;
TriangleView.Invalidate;
end;
procedure TEditForm.chkHelpersClick(Sender: TObject);
begin
HelpersEnabled := chkHelpers.checked;
TriangleView.Invalidate;
end;
*)
procedure TEditForm.txtXFormColorExit(Sender: TObject);
var
v: double;
begin
try
v := StrToFloat(txtXFormColor.Text);
except on EConvertError do
begin
txtXformColor.text := Format('%1.3f', [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
updating := true;
scrlXFormColor.Position := round(v * scrlXFormColor.Max);
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].color := v;
updating := false;
UpdateFlame(true);
end;
end;
procedure TEditForm.txtXFormColorKeyPress(Sender: TObject; var Key: Char);
begin
if (Key = '-') then Key:= #0; // AV
if key = #13 then
begin
key := #0;
txtXFormColorExit(Sender);
end;
end;
procedure TEditForm.txtOpacitySet(Sender: TObject);
var
Allow: boolean;
NewVal, OldVal: double;
begin
Allow := True;
OldVal := Round6(cp.xform[SelectedTriangle].transOpacity);
{ 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].transOpacity := NewVal;
UpdateFlame(True);
end;
end;
procedure TEditForm.txtDCSet(Sender: TObject);
var
Allow: boolean;
NewVal, OldVal: double;
begin
Allow := True;
OldVal := Round6(cp.xform[SelectedTriangle].pluginColor);
{ 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].pluginColor := NewVal;
UpdateFlame(True);
end;
end;
procedure TEditForm.txtSymmetrySet(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 < -1 then NewVal := -1;
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.txtOpacityKeyPress(Sender: TObject; var Key: Char);
var
Allow: boolean;
NewVal, OldVal: double;
begin
if (Key = '-') then Key:= #0; // AV
if key = #13 then
begin
{ Stop the beep }
Key := #0;
Allow := True;
OldVal := Round6(cp.xform[SelectedTriangle].transOpacity);
{ 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].transOpacity := NewVal;
UpdateFlame(True);
end;
end;
end;
procedure TEditForm.txtDCKeyPress(Sender: TObject; var Key: Char);
var
Allow: boolean;
NewVal, OldVal: double;
begin
if (Key = '-') then Key:= #0;
if key = #13 then
begin
{ Stop the beep }
Key := #0;
Allow := True;
OldVal := Round6(cp.xform[SelectedTriangle].pluginColor);
{ 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].pluginColor := NewVal;
UpdateFlame(True);
end;
end;
end;
procedure TEditForm.txtSymmetrKeyPress(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 < -1 then NewVal := -1;
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;
// -- Variation List Editor ----------------------------------------------------
procedure TEditForm.ValidateVariation;
var
i: integer;
NewVal, OldVal: double;
begin
//i := VEVars.Row - 1;
i := GetVariationIndex(VEVars.Keys[VEVars.Row]); // AV
OldVal := Round6(cp.xform[SelectedTriangle].GetVariation(i));
try
NewVal := Round6(StrToFloat(VEVars.Values[VarNames(i)]));
except
VEVars.Values[VarNames(i)] := Format('%.6g', [OldVal]);
exit;
end;
if (NewVal <> OldVal) then
begin
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].SetVariation(i, NewVal);
VEVars.Values[VarNames(i)] := Format('%.6g', [NewVal]);
ShowSelectedInfo;
UpdateFlame(True);
end;
2022-03-08 12:25:51 -05:00
end;
(*
// here's another way to do this -
// we could use it with variables value editor,
// only if we had an *array* of variables
type
TDblArray = array of double;
PDblArray = ^TDblArray;
procedure ValidateValue(Sender: TValueListEditor; values: PDblArray);
var
Allow: boolean;
i: integer;
NewVal, OldVal: double;
begin
Allow := True;
i := Sender.Row - 1;
OldVal := values^[i];
{ Test that it's a valid floating point number }
try
StrToFloat(Sender.Values[VarNames(i)]);
except on Exception do
begin
{ It's not, so we restore the old value }
Sender.Values[VarNames(i)] := Format('%.6g', [OldVal]);
Allow := False;
end;
end;
NewVal := Round6(StrToFloat(Sender.Values[VarNames(i)]));
Sender.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;
values^[i] := NewVal;
Sender.Values[VarNames(i)] := Format('%.6g', [NewVal]);
EditForm.ShowSelectedInfo;
EditForm.UpdateFlame(True);
end;
end;
*)
procedure TEditForm.VEVarsKeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
begin
key := #0;
ValidateVariation;
end;
end;
procedure TEditForm.VEVarsChange(Sender: TObject);
begin
ValidateVariation;
end;
procedure TEditForm.VEVarsValidate(Sender: TObject; ACol, ARow: Integer; const KeyName, KeyValue: String);
begin
ValidateVariation;
end;
// -- ValueList mouse stuff ----------------------------------------------------
procedure TEditForm.VEVarsMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
cell: TGridCoord;
begin
if Button = mbLeft then begin
varDragOld:=x;
cell := TValueListEditor(Sender).MouseCoord(x, y);
varDragIndex := cell.Y-1;
if (cell.y < 1) or (cell.y >= TValueListEditor(Sender).RowCount) or
(cell.x <> 0) then exit;
TValueListEditor(Sender).Row := cell.Y;
Screen.Cursor := crHSplit;
//GetCursorPos(mousepos); // hmmm
mousePos := (Sender as TControl).ClientToScreen(Point(x, y));
varDragMode:=true;
varDragPos:=0;
varMM := false;
SetCaptureControl(TValueListEditor(Sender));
if Sender = VEVars then
begin
varDragIndex := GetVariationIndex(VEVars.Keys[varDragIndex+1]); // AV
varDragValue := cp.xform[SelectedTriangle].GetVariation(varDragIndex);
end
else if Sender = vleVariables then
cp.xform[SelectedTriangle].GetVariable(vleVariables.Keys[varDragIndex+1], varDragValue)
else if Sender = vleChaos then begin
if mnuChaosViewTo.Checked then
pDragValue := @cp.xform[SelectedTriangle].modWeights[varDragIndex]
else
pDragValue := @cp.xform[varDragIndex].modWeights[SelectedTriangle];
varDragValue := pDragValue^;
end
else Assert(false);
HasChanged := False;
end;
end;
procedure TEditForm.VEVarsMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
v: double;
cell: TGridCoord;
begin
cell := TValueListEditor(Sender).MouseCoord(x, y);
if (cell.Y > 0) and (cell.X = 0) then TValueListEditor(Sender).Cursor := crHandPoint
else TValueListEditor(Sender).Cursor := crDefault;
if varMM then // hack: to skip MouseMove event
begin
varMM:=false;
end
else
if varDragMode and (x <> varDragOld) then
begin
Inc(varDragPos, x - varDragOld);
if GetKeyState(VK_MENU) < 0 then v := 100000
else if GetKeyState(VK_CONTROL) < 0 then v := 10000
else if GetKeyState(VK_SHIFT) < 0 then v := 100
else v := 1000;
v := Round6(varDragValue + varDragPos/v);
SetCursorPos(MousePos.x, MousePos.y); // hmmm
// this Delphi is WEIRD!
// why GetCursorPos deals with TPoint,
// and SetCursorPos - with two integers? :)
varMM:=true;
//cp.xform[SelectedTriangle].vars[varDragIndex] := v;
if Sender = VEVars then
begin
cp.xform[SelectedTriangle].SetVariation(varDragIndex, v);
VEVars.Values[VarNames(varDragIndex)] := FloatToStr(v); //Format('%.6g', [v]);
end
else if Sender = vleVariables then begin
cp.xform[SelectedTriangle].SetVariable(vleVariables.Keys[varDragIndex+1], v);
vleVariables.Values[vleVariables.Keys[varDragIndex+1]] := FloatToStr(v);
end
else begin
if v < 0 then v := 0;
//cp.xform[SelectedTriangle].modWeights[varDragIndex] := v;
pDragValue^ := v;
vleChaos.Cells[1, varDragIndex+1] := FloatToStr(v);
end;
HasChanged := True;
UpdateFlameX;
end;
end;
procedure TEditForm.VEVarsMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button <> mbLeft then exit;
SetCaptureControl(nil);
if varDragMode then
begin
varDragMode:=false;
Screen.Cursor := crDefault;
if HasChanged then
begin
MainForm.UpdateUndo;
UpdateFlame(true);
HasChanged := False;
if (Sender = vleChaos) and ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
end;
end;
procedure TEditForm.VEVarsDblClick(Sender: TObject);
var
n, i: integer;
v, v1: double;
changed, allzero: boolean;
varname: string;
begin
n := TValueListEditor(Sender).Row - 1;
assert(n >= 0);
assert(n < TValueListEditor(Sender).rowCount);
//changed := false;
if (SelectedTriangle < 0) or (SelectedTriangle > High(cp.xform)) then
changed := false
else begin
if Sender = VEVars then
begin
if (n < 0) or (n > (cp.xform[SelectedTriangle].NumVariations - 1)) then
changed := false
else begin
i := n; // AV
n := GetVariationIndex(VEVars.Keys[i+1]); // AV
v := cp.xform[SelectedTriangle].GetVariation(n);
if AllowResetLinear then // AV
begin
if v = 0 then
begin
allzero := true;
for i := 1 to NrVar-1 do
allzero := allzero and (cp.xform[SelectedTriangle].GetVariation(i) = 0);
if (cp.xform[SelectedTriangle].GetVariation(0) = 1) and allzero then
cp.xform[SelectedTriangle].SetVariation(0, 0);
cp.xform[SelectedTriangle].SetVariation(n, 1);
end
else cp.xform[SelectedTriangle].SetVariation(n, 0);
end else
cp.xform[SelectedTriangle].SetVariation(n, IfThen(v = 0, 1, 0));
changed := (cp.xform[SelectedTriangle].GetVariation(n) <> v);
end;
end
else if Sender = vleVariables then begin
varname := vleVariables.Keys[n + 1]; // AV
cp.xform[SelectedTriangle].GetVariable(varname, v);
cp.xform[SelectedTriangle].ResetVariable(varname);
cp.xform[SelectedTriangle].GetVariable(varname, v1);
changed := (v1 <> v);
end
else if Sender = vleChaos then begin
if ((varDragIndex) < 0) or ((varDragIndex) > high(cp.xform[SelectedTriangle].modWeights)) then
changed := false
else
begin
if mnuChaosViewTo.Checked then
pDragValue := @cp.xform[SelectedTriangle].modWeights[varDragIndex]
else
pDragValue := @cp.xform[varDragIndex].modWeights[SelectedTriangle];
v := pDragValue^;
v := ifthen(v = 1, 0, 1);
pDragValue^ := v;
vleChaos.Cells[1, n+1] := FloatToStr(v);
changed := true;
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end
//else Assert(false);
end else changed := false;
end;
if changed then MainForm.UpdateUndo;
UpdateFlame(true);
end;
{ **************************************************************************** }
function TEditForm.GetPivot: TSPoint;
begin
Result := GetPivot(SelectedTriangle);
end;
function TEditForm.GetPivot(n: integer): TSPoint;
begin
if (PivotMode = pivotLocal) or {EdgeCaught} (mouseOverEdge >= 0) then // should be always local for edges (hmm...?)
with MainTriangles[n] do begin
Result.x := x[1] + (x[0] - x[1])*LocalPivot.x + (x[2] - x[1])*LocalPivot.y;
Result.y := y[1] + (y[0] - y[1])*LocalPivot.x + (y[2] - y[1])*LocalPivot.y;
end
else begin
Result.x := WorldPivot.x;
Result.y := WorldPivot.y;
end;
end;
procedure TEditForm.ScriptGetPivot(var px, py: double);
begin
// AV: sometimes the scripter swaps pre and post triangles...
if (PivotMode = pivotLocal) then
with MainTriangles[SelectedTriangle] do begin
px := x[1] + (x[0] - x[1])*LocalPivot.x + (x[2] - x[1])*LocalPivot.y;
py := y[1] + (y[0] - y[1])*LocalPivot.x + (y[2] - y[1])*LocalPivot.y;
end
{ with cp.xform[SelectedTriangle] do
begin
if not postXswap then begin
px := c[2,0] + c[0,0]*LocalPivot.x + (-c[0,1])*LocalPivot.y;
py := -c[2,1] + (-c[0,1])*LocalPivot.x + c[1,1]*LocalPivot.y;
end
else begin
px := p[2,0] + p[0,0]*LocalPivot.x + (-p[0,1])*LocalPivot.y;
py := -p[2,1] + (-p[0,1])*LocalPivot.x + p[1,1]*LocalPivot.y;
end;
end }
else begin
px := WorldPivot.x;
py := WorldPivot.y;
end;
end;
procedure TEditForm.InvCurrentNumClick(Sender: TObject);
var
num: double;
sn: string;
isEdit: boolean;
begin
if (ActiveControl = txtTrgMoveValue) then
begin
InvertMovevalue1.Click;
exit;
end
else if (ActiveControl is TComboBox) then exit;
isEdit := (ActiveControl is TEdit);
if isEdit then
if (ActiveControl = txtSearchBox) or (ActiveControl = txtName) then
isEdit := False;
if not (isEdit or (ActiveControl is TValueListEditor)) then
begin
Application.MessageBox(PChar(TextByKey('editor-status-nonumfield')),
ApophysisSVN, MB_ICONWARNING);
2022-03-08 12:25:51 -05:00
exit;
end;
try
if isEdit then
sn := TEdit(ActiveControl).Text
else // if (ActiveControl is TValueListEditor) then
sn := TValueListEditor(ActiveControl).Cells[1, TValueListEditor(ActiveControl).Row];
num := StrToFloat(sn);
if (abs(num) < 1E-5) then exit;
sn := Format('%.6g', [1/num]);
if isEdit then
begin
TEdit(ActiveControl).Text := sn;
TEdit(ActiveControl).OnExit(ActiveControl);
end
else // if (ActiveControl is TValueListEditor) then
begin
TValueListEditor(ActiveControl).Cells[1, TValueListEditor(ActiveControl).Row] := sn;
TValueListEditor(ActiveControl).OnExit(ActiveControl);
end;
except
end;
end;
procedure TEditForm.InvertMovevalue1Click(Sender: TObject);
var step: double;
begin
try
step := StrToFloat(txtTrgMoveValue.Text);
if (abs(step) >= 0.1) then txtTrgMoveValue.Text := Format('%.6g', [1/step]);
except
txtTrgMoveValue.ItemIndex := 1;
end;
end;
procedure TEditForm.InvertXaosClick(Sender: TObject);
var i: smallint;
2022-03-08 12:25:51 -05:00
cmax: double;
begin
MainForm.UpdateUndo;
if mnuChaosViewTo.Checked then
begin
cmax := MaxValue(cp.xform[SelectedTriangle].modWeights);
if (cmax > 0) then
for i := 0 to Transforms-1 do
cp.xform[SelectedTriangle].modWeights[i] :=
IfThen(cp.xform[SelectedTriangle].modWeights[i] = 0, cmax,
cmax - cp.xform[SelectedTriangle].modWeights[i])
else for i := 0 to Transforms-1 do
cp.xform[SelectedTriangle].modWeights[i] := 1;
end else begin
cmax := 0;
for i := 0 to Transforms-1 do
if (cp.xform[i].modWeights[SelectedTriangle] > cmax) then
cmax := cp.xform[i].modWeights[SelectedTriangle];
if (cmax > 0) then
for i := 0 to Transforms-1 do
cp.xform[i].modWeights[SelectedTriangle] :=
IfThen(cp.xform[i].modWeights[SelectedTriangle] = 0, cmax,
cmax - cp.xform[i].modWeights[SelectedTriangle])
else for i := 0 to Transforms-1 do
cp.xform[i].modWeights[SelectedTriangle] := 1;
end;
UpdateFlame(true);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
procedure TEditForm.UpdateColorBar;
var
BitMap: TBitmap;
Row: pRGBTripleArray;
i: smallint;
2022-03-08 12:25:51 -05:00
begin
BitMap := TBitMap.Create;
try
Bitmap.PixelFormat := pf24bit;
BitMap.Width := 256;
BitMap.Height := 1;
Row := Bitmap.Scanline[0];
for i := 0 to 255 do
with Row[i] do
begin
rgbtRed := MainCP.cmap[i][0];
rgbtGreen := MainCP.cmap[i][1];
rgbtBlue := MainCP.cmap[i][2];
end;
EditForm.ColorBarPicture.Picture.Graphic := Bitmap;
EditForm.ColorBarPicture.Refresh;
finally
BitMap.Free;
end;
end;
procedure TEditForm.RotateTriangleBy(const angle: double); // AV
var
i: smallint;
begin
MainForm.UpdateUndo;
if (not UseTriangleSync) or (SelectedTriangle = Transforms) then
begin
if RotateXYO.Checked then
MainTriangles[SelectedTriangle] :=
RotateTrianglePoint(MainTriangles[SelectedTriangle], GetPivot.x, GetPivot.y, angle)
else if RotateX.Checked then begin
MainTriangles[SelectedTriangle] :=
RotateTriangleXY(MainTriangles[SelectedTriangle], 0, angle);
if tbAutoWeights.Down then cp.CalculateWeights; // AV
end else if RotateY.Checked then begin
MainTriangles[SelectedTriangle] :=
RotateTriangleXY(MainTriangles[SelectedTriangle], 2, angle);
if tbAutoWeights.Down then cp.CalculateWeights; // AV
end else //if RotateO.Checked then
MainTriangles[SelectedTriangle] :=
RotateTriangleO(MainTriangles[SelectedTriangle], WorldPivot.x, WorldPivot.y, angle);
end
else begin
if RotateXYO.Checked then
for i in SyncTriangles do
MainTriangles[i] :=
RotateTrianglePoint(MainTriangles[i], GetPivot(i).x, GetPivot(i).y, angle)
else if RotateX.Checked then
for i in SyncTriangles do
MainTriangles[i] := RotateTriangleXY(MainTriangles[i], 0, angle)
else if RotateY.Checked then
for i in SyncTriangles do
MainTriangles[i] := RotateTriangleXY(MainTriangles[i], 2, angle)
else //if RotateO.Checked then
for i in SyncTriangles do
MainTriangles[i] := RotateTriangleO(MainTriangles[i], WorldPivot.x, WorldPivot.y, angle);
end;
HasChanged := True;
UpdateFlame(true);
end;
2022-03-08 12:25:51 -05:00
procedure TEditForm.btTrgRotateLeftClick(Sender: TObject);
var
angle: double;
begin
try
angle := StrToFloat(txtTrgRotateValue.Text);
except
txtTrgRotateValue.ItemIndex := 1;
exit;
end;
assert(angle <> 0);
if GetKeyState(VK_CONTROL) < 0 then angle := angle / 6.0
else if GetKeyState(VK_SHIFT) < 0 then angle := angle * 6.0;
2022-03-08 12:25:51 -05:00
// AV: to show internally modified value
if (ShowModVals.Checked) then txtTrgRotateValue.Text := Format('%.6g', [angle]);
angle := PI/180 * angle; // AV
RotateTriangleBy(angle); // AV
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.btTrgRotateLeft90Click(Sender: TObject);
begin
RotateTriangleBy(PI/2); // AV
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.btTrgRotateRightClick(Sender: TObject);
var
angle: double;
begin
try
angle := StrToFloat(txtTrgRotateValue.Text);
except
txtTrgRotateValue.ItemIndex := 1;
exit;
end;
assert(angle <> 0);
if GetKeyState(VK_CONTROL) < 0 then angle := angle/6.0
else if GetKeyState(VK_SHIFT) < 0 then angle := angle*6.0;
// AV: to show internally modified value
if (ShowModVals.Checked) then txtTrgRotateValue.Text := Format('%.6g', [angle]);
angle := -PI/180 * angle; // AV
RotateTriangleBy(angle); // AV
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.btTrgRotateRight90Click(Sender: TObject);
begin
RotateTriangleBy(-PI/2); // AV
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.PaintBackground;
begin
assert(false);
TriangleViewPaint(TriangleView);
end;
procedure TEditForm.TrgMove(dx, dy: double);
var
i, j: smallint;
2022-03-08 12:25:51 -05:00
offset: double;
begin
try
offset := StrToFloat(txtTrgMoveValue.Text);
assert(offset <> 0);
except
txtTrgMoveValue.ItemIndex := 1;
exit;
end;
if GetKeyState(VK_CONTROL) < 0 then offset := offset/10.0
else if GetKeyState(VK_SHIFT) < 0 then offset := offset*10.0;
// AV: to show internally modified value
if (ShowModVals.Checked) then txtTrgMoveValue.Text := Format('%.6g', [offset]);
MainForm.UpdateUndo;
if (not UseTriangleSync) or (SelectedTriangle = Transforms) then
for i := 0 to 2 do begin
MainTriangles[SelectedTriangle].x[i] :=
2022-03-08 12:25:51 -05:00
MainTriangles[SelectedTriangle].x[i] + dx*offset;
MainTriangles[SelectedTriangle].y[i] :=
2022-03-08 12:25:51 -05:00
MainTriangles[SelectedTriangle].y[i] + dy*offset;
end
else
for j in SyncTriangles do
for i := 0 to 2 do begin
MainTriangles[j].x[i] := MainTriangles[j].x[i] + dx * offset;
MainTriangles[j].y[i] := MainTriangles[j].y[i] + dy * offset;
end;
2022-03-08 12:25:51 -05:00
// HasChanged := True;
UpdateFlame(true);
end;
procedure TEditForm.btTrgMoveLeftClick(Sender: TObject);
begin
TrgMove(-1,0);
end;
procedure TEditForm.btTrgMoveRightClick(Sender: TObject);
begin
TrgMove(1,0);
end;
procedure TEditForm.btTrgMoveUpClick(Sender: TObject);
begin
if RectGrid.Checked then TrgMove(0,1)
else TrgMove(0.5, sqrt(3)*0.5);
end;
procedure TEditForm.btTrgMoveDownClick(Sender: TObject);
begin
if RectGrid.Checked then TrgMove(0,-1)
else TrgMove(-0.5, -sqrt(3)*0.5);
end;
{
procedure TEditForm.btTrgMoveLUClick(Sender: TObject);
begin
TrgMove(-1,1);
end;
procedure TEditForm.btTrgMoveLDClick(Sender: TObject);
begin
TrgMove(-1,-1);
end;
procedure TEditForm.btTrgMoveRUClick(Sender: TObject);
begin
TrgMove(1,1);
end;
procedure TEditForm.btTrgMoveRDClick(Sender: TObject);
begin
TrgMove(1,-1);
end;
}
procedure TEditForm.btTrgScaleUpClick(Sender: TObject);
var
scale: double;
i: smallint;
2022-03-08 12:25:51 -05:00
begin
try
scale := StrToFloat(txtTrgScaleValue.Text) / 100.0;
except
txtTrgScaleValue.ItemIndex := 1;
exit;
end;
if scale = 0 then scale := 1e-6; //assert(scale <> 0);
// AV: fixed - added abs() for negative value
if GetKeyState(VK_CONTROL) < 0 then scale := sqrt(abs(scale))
else if GetKeyState(VK_SHIFT) < 0 then scale := scale*scale;
// AV: to show internally modified value
if (ShowModVals.Checked) then txtTrgScaleValue.Text := Format('%.6g', [scale * 100.0]);
MainForm.UpdateUndo;
if (not UseTriangleSync) or (SelectedTriangle = Transforms) then
begin
if ScaleXYO.Checked then
MainTriangles[SelectedTriangle] :=
ScaleTrianglePoint(MainTriangles[SelectedTriangle], GetPivot.x, GetPivot.y, scale)
2022-03-08 12:25:51 -05:00
else if ScaleX.Checked then
MainTriangles[SelectedTriangle] := ScaleTriangleXY(MainTriangles[SelectedTriangle], 0, scale)
else if ScaleY.Checked then
MainTriangles[SelectedTriangle] := ScaleTriangleXY(MainTriangles[SelectedTriangle], 2, scale)
else //if ScaleO.Checked then
MainTriangles[SelectedTriangle] :=
ScaleTriangleO(MainTriangles[SelectedTriangle], WorldPivot.x, WorldPivot.y, scale);
end
else begin
if ScaleXYO.Checked then
for i in SyncTriangles do
MainTriangles[i] :=
ScaleTrianglePoint(MainTriangles[i], GetPivot(i).x, GetPivot(i).y, scale)
else if ScaleX.Checked then
for i in SyncTriangles do
MainTriangles[i] := ScaleTriangleXY(MainTriangles[i], 0, scale)
else if ScaleY.Checked then
for i in SyncTriangles do
MainTriangles[i] := ScaleTriangleXY(MainTriangles[i], 2, scale)
else //if ScaleO.Checked then begin
for i in SyncTriangles do
MainTriangles[i] :=
ScaleTriangleO(MainTriangles[i], WorldPivot.x, WorldPivot.y, scale);
end;
2022-03-08 12:25:51 -05:00
if tbAutoWeights.Down then cp.CalculateWeights; // AV
HasChanged := True;
UpdateFlame(true);
end;
procedure TEditForm.btTrgScaleDownClick(Sender: TObject);
var
scale: double;
i: smallint;
2022-03-08 12:25:51 -05:00
begin
try
scale := 100.0 / StrToFloat(txtTrgScaleValue.Text);
except
txtTrgScaleValue.ItemIndex := 1;
exit;
end;
if scale = 0 then scale := 1e-6; //assert(scale <> 0);
// AV: fixed for negative value
if GetKeyState(VK_CONTROL) < 0 then scale := sqrt(abs(scale))
else if GetKeyState(VK_SHIFT) < 0 then scale := scale*scale;
// AV: to show modified value
if (ShowModVals.Checked) then txtTrgScaleValue.Text := Format('%.6g', [scale * 100.0]);
MainForm.UpdateUndo;
if (not UseTriangleSync) or (SelectedTriangle = Transforms) then
begin
if ScaleXYO.Checked then
MainTriangles[SelectedTriangle] :=
ScaleTrianglePoint(MainTriangles[SelectedTriangle], GetPivot.x, GetPivot.y, scale)
else if ScaleX.Checked then
MainTriangles[SelectedTriangle] := ScaleTriangleXY(MainTriangles[SelectedTriangle], 0, scale)
else if ScaleY.Checked then
MainTriangles[SelectedTriangle] := ScaleTriangleXY(MainTriangles[SelectedTriangle], 2, scale)
else //if ScaleO.Checked then
MainTriangles[SelectedTriangle] :=
ScaleTriangleO(MainTriangles[SelectedTriangle], WorldPivot.x, WorldPivot.y, scale);
end
else begin
if ScaleXYO.Checked then
for i in SyncTriangles do
MainTriangles[i] :=
ScaleTrianglePoint(MainTriangles[i], GetPivot(i).x, GetPivot(i).y, scale)
2022-03-08 12:25:51 -05:00
else if ScaleX.Checked then
for i in SyncTriangles do
MainTriangles[i] := ScaleTriangleXY(MainTriangles[i], 0, scale)
2022-03-08 12:25:51 -05:00
else if ScaleY.Checked then
for i in SyncTriangles do
MainTriangles[i] := ScaleTriangleXY(MainTriangles[i], 2, scale)
else //if ScaleO.Checked then begin
for i in SyncTriangles do
MainTriangles[i] :=
ScaleTriangleO(MainTriangles[i], WorldPivot.x, WorldPivot.y, scale);
end;
2022-03-08 12:25:51 -05:00
if tbAutoWeights.Down then cp.CalculateWeights; // AV
HasChanged := True;
UpdateFlame(true);
end;
procedure TEditForm.TriangleViewKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (oldMode = modeNone) and
(key in [{VK_SHIFT,} VK_MENU, VK_CONTROL]) then
begin
oldMode := editMode;
modeKey := key;
if key = VK_MENU then
if editMode <> modeRotate then
begin
editMode := modeRotate;
TriangleView.Cursor := crEditRotate;
end
else begin
editMode := modeMove;
TriangleView.Cursor := crEditMove;
end
else {if key = VK_CONTROL then}
begin
if editMode <> modeScale then
begin
editMode := modeScale;
TriangleView.Cursor := crEditScale;
end
else begin
editMode := modeMove;
TriangleView.Cursor := crEditMove;
end
end;
end
else
case key of
VK_LEFT:
if Shift = [ssAlt] then btTrgRotateLeftClick(Sender)
else TrgMove(-1,0);
VK_RIGHT:
if Shift = [ssAlt] then btTrgRotateRightClick(Sender)
else TrgMove(1,0);
VK_UP:
if Shift = [ssAlt] then btTrgScaleUpClick(Sender)
else TrgMove(0,1);
VK_DOWN:
if Shift = [ssAlt] then btTrgScaleDownClick(Sender)
else TrgMove(0,-1);
VK_PRIOR: btTrgRotateLeftClick(Sender);
VK_NEXT: btTrgRotateRightClick(Sender);
VK_HOME: btTrgScaleUpClick(Sender);
VK_END: btTrgScaleDownClick(Sender);
VK_INSERT: mnuDupClick(Sender);
VK_DELETE: mnuDeleteClick(Sender);
// can be changed in the future...
Ord('R'): btnResetPivotClick(Sender);
Ord('P'): btnPickPivotClick(Sender);
Ord('T'): tbPostXswapClick(Sender);
{
Ord('I'): // Invisible <<-- AV: or Invert :-)
chkXformInvisible.Checked := not chkXformInvisible.Checked;
}
Ord('S'): // Solo
begin
chkXformSolo.Checked := not chkXformSolo.Checked;
end;
189: // "-"
begin
GraphZoom := GraphZoom * 0.8;
EditForm.StatusBar.Panels[2].Text := Format(TextByKey('editor-status-zoomformat'), [GraphZoom]);
TriangleView.Invalidate;
end;
187: // "+"
begin
GraphZoom := GraphZoom * 1.25;
EditForm.StatusBar.Panels[2].Text := Format(TextByKey('editor-status-zoomformat'), [GraphZoom]);
TriangleView.Invalidate;
end;
VK_ESCAPE:
begin
if TriangleCaught or CornerCaught or EdgeCaught then begin
if modeHack then begin
assert(oldMode <> modeNone);
editMode := oldMode;
oldMode := modeNone;
modeHack := false;
end;
if HasChanged then
begin
MainTriangles[SelectedTriangle] := OldTriangle;
HasChanged := False;
end;
EdgeCaught := false;
CornerCaught := false;
TriangleCaught := false;
TriangleView.Invalidate;
UpdateFlameX;
end;
end
end;
end;
procedure TEditForm.TriangleViewKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (oldMode <> modeNone) and (key = modeKey) then
begin
assert(key in [VK_MENU, VK_CONTROL]);
editMode := oldMode;
oldMode := modeNone;
// tbMove.Down := (editMode = modeMove);
// tbRotate.Down := (editMode = modeRotate);
// tbScale.Down := (editMode = modeScale);
// hack: to generate MouseMove event
GetCursorPos(MousePos);
SetCursorPos(MousePos.x, MousePos.y);
end;
end;
procedure TEditForm.TriangleViewExit(Sender: TObject);
begin
if oldMode <> modeNone then
begin
editMode := oldMode;
oldMode := modeNone;
// tbMove.Down := (editMode = modeMove);
// tbRotate.Down := (editMode = modeRotate);
// tbScale.Down := (editMode = modeScale);
end;
mouseOverTriangle := -1;
TriangleView.Invalidate;
end;
procedure TEditForm.TriangleViewMouseLeave(Sender: TObject);
begin
if viewDragMode = false then
begin
mouseOverTriangle := -1;
TriangleView.Invalidate;
end;
end;
procedure TEditForm.EditKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var num: double;
begin
2022-03-08 12:25:51 -05:00
case key of
VK_ADD:
if SelectedTriangle < LastTriangle then begin
txtNameExit(Sender); // store name before re-filling name box by changing xform
Inc(SelectedTriangle);
TriangleView.Invalidate;
ShowSelectedInfo;
end;
VK_SUBTRACT:
if SelectedTriangle > 0 then begin
txtNameExit(Sender); // store name before re-filling name box by changing xform
Dec(SelectedTriangle);
TriangleView.Invalidate;
ShowSelectedInfo;
end;
VK_SPACE:
if not txtName.Focused then
btnPivotModeClick(Sender);
Ord('I'):
if (not txtName.Focused) and (not txtSearchBox.Focused) then begin
if txtTrgMoveValue.Focused then InvertMoveValue1.Click
else InvCurrentNum.Click;
end;
Ord('X'):
if (not txtName.Focused) and (not txtSearchBox.Focused) then
begin
ScaleX.Checked := True;
RotateX.Checked := True;
end;
Ord('Y'):
if (not txtName.Focused) and (not txtSearchBox.Focused) then
begin
ScaleY.Checked := True;
RotateY.Checked := True;
end;
Ord('O'):
if (not txtName.Focused) and (not txtSearchBox.Focused) then
begin
ScaleO.Checked := True;
RotateO.Checked := True;
end;
Ord('A'):
if (not txtName.Focused) and (not txtSearchBox.Focused) then
begin
ScaleXYO.Checked := True;
RotateXYO.Checked := True;
end;
Ord('M'):
if (not txtName.Focused) and (not txtSearchBox.Focused) then
begin
mnuCalcExpression.Click;
end;
2022-03-08 12:25:51 -05:00
else
key_handled := false;
exit;
end;
key_handled := true;
key := 0;
end;
procedure TEditForm.EditKeyPress(Sender: TObject; var Key: Char);
begin
if txtName.Focused then begin
{
if (key = '+') or (key='-') then begin
2022-03-08 12:25:51 -05:00
// nvm...code moved to EditKeyDown
key := #0;
end;
if (key='"') then key := #0; // we dont want that in "name" box -> XML mess!
}
// AV: we also don't want XML-tag's brackets here
if CharInSet(Key,['+', '-', '"', '<', '>']) then key := #0;
2022-03-08 12:25:51 -05:00
exit;
end
else if txtSearchBox.Focused then
2022-03-08 12:25:51 -05:00
begin
if (key = #13) then key := #0; // AV: to prevent a beep
exit;
end;
// kill alphanumeric keys generally
// if key_handled or (CharInSet(key,['A'..'z'])) then key := #0; // hmmm...
{ AV: the code above doesn't work properly, so I rewrote it }
{ AV: a lot of users type comma as the decimal separator,
but Apo discard it. It's not normally... }
if (Key = ',') then Key := '.'; // FormatSettings.DecimalSeparator;
if key_handled or not CharInSet(Key,['0'..'9', '-', #8, #13, '.'])
2022-03-08 12:25:51 -05:00
then Key:= #0;
end;
procedure TEditForm.splitterMoved(Sender: TObject);
begin
UpdatePreview;
end;
procedure TEditForm.tbSelectClick(Sender: TObject);
begin
SelectMode := not SelectMode;
tbSelect.Down := SelectMode;
if SelectMode then
begin
StatusBar.Panels[2].Text := TextByKey('editor-status-selecton');
end
else begin
mouseOverTriangle := SelectedTriangle;
StatusBar.Panels[2].Text := TextByKey('editor-status-selectoff');;
end;
// hack: to generate MouseMove event
GetCursorPos(MousePos);
SetCursorPos(MousePos.x, MousePos.y);
end;
procedure TEditForm.tbSyncTrianglesClick(Sender: TObject);
begin
UseTriangleSync := not UseTriangleSync;
AdjustSyncTriangles;
end;
procedure TEditForm.AdjustSyncTriangles;
begin
if UseTriangleSync then begin
tbSyncTriangles.Style := tbsDropDown;
tbSyncTriangles.DropdownMenu := mnuSyncTriangles;
TriangleToolBar.Perform(CM_CONTROLCHANGE, WPARAM(tbSyncTriangles), 36);
tbSyncTriangles.ImageIndex := 44;
tbSyncTriangles.Hint := TextByKey('editor-tab-triangle-enablesync');
end
else begin
tbSyncTriangles.Style := tbsButton;
tbSyncTriangles.DropdownMenu := nil;
TriangleToolBar.Perform(CM_CONTROLCHANGE, WPARAM(tbSyncTriangles), 23);
tbSyncTriangles.ImageIndex := 43;
tbSyncTriangles.Hint := TextByKey('editor-tab-triangle-disablesync');
end;
end;
2022-03-08 12:25:51 -05:00
procedure TEditForm.TriangleViewMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
fx, fy, sc: double;
p: TPoint;
begin
p := TriangleView.ScreenToClient(MousePos);
Scale(fx, fy, p.X, p.Y);
if WheelDelta > 0 then GraphZoom := GraphZoom * 1.25
else GraphZoom := GraphZoom * 0.8;
EditForm.StatusBar.Panels[2].Text := Format(TextByKey('editor-status-zoomformat'), [GraphZoom]);
if viewDragMode then begin
sc := GraphZoom * 50;
gCenterX := fx - (p.X - TriangleView.Width/2) / sc;
gCenterY := fy + (p.Y - TriangleView.Height/2) / sc;
end;
TriangleView.Invalidate;
Handled := true;
end;
procedure TEditForm.TriangleViewDblClick(Sender: TObject);
begin
if mouseOverTriangle >= 0 then
begin
if mouseOverCorner >= 0 then begin
case mouseOverCorner of
0: if editMode = modeRotate then ResetAxisRotation(0) else ResetAxisScale(0);
1: if editMode = modeRotate then ResetAxisRotation(1)
else begin
if editMode = modeScale then
ResetAxisScale(1)
else begin
if cp.xform[SelectedTriangle].postXswap then
btnOpostClick(Sender)
else
btnOcoefsClick(Sender);
end;
end;
2: if editMode = modeRotate then ResetAxisRotation(2) else ResetAxisScale(2);
end;
end
else if mouseOverEdge >= 0 then begin
if AxisLock then begin
if (editMode = modeScale) or (mouseOverEdge = 2)then
mnuResetTrgScaleClick(Sender)
else
mnuResetTrgRotationClick(Sender);
end
else case mouseOverEdge of
0: if editMode = modeScale then ResetAxisScale(0) else ResetAxisRotation(0);
1: if editMode = modeScale then ResetAxisScale(2) else ResetAxisRotation(2);
2: mnuResetTrgScaleClick(Sender);
end;
end
else if mouseOverWidget >= 0 then begin
case editMode of
modeScale: mnuResetTrgScaleClick(Sender);
else mnuResetTrgRotationClick(Sender);
end;
end
else case editMode of
//modeMove: Do Nothing
modeScale: mnuResetTrgScaleClick(Sender);
modeRotate: mnuResetTrgRotationClick(Sender);
end;
end
else AutoZoom;
end;
procedure TEditForm.TriangleViewInvalidate(Sender: TObject);
begin
TriangleView.Invalidate;
end;
procedure TEditForm.tbEditModeClick(Sender: TObject);
begin
// ExtendedEdit := (Sender = tbExtendedEdit);
if Sender = tbRotate then
begin
editMode := modeRotate;
//tbRotate.Down := true;
end
else if Sender = tbScale then
begin
editMode := modeScale;
//tbScale.Down := true;
end
else begin
editMode := modeMove;
//tbMove.Down := true;
end;
TToolButton(Sender).Down := true;
TriangleView.Invalidate;
end;
procedure TEditForm.tbExtendedEditClick(Sender: TObject);
begin
ExtendedEdit := not ExtendedEdit;
tbExtendedEdit.Down := ExtendedEdit;
TriangleView.Invalidate;
end;
procedure TEditForm.tbAxisLockClick(Sender: TObject);
begin
AxisLock := not AxisLock;
tbAxisLock.Down := AxisLock;
end;
procedure TEditForm.tbCommentClick(Sender: TObject);
begin
CommentForm.memComment.Lines.Text := cp.comment;
if CommentForm.ShowModal = mrOK then
begin
cp.comment := Trim(CommentForm.memComment.Lines.Text);
MainCp.comment := cp.comment;
end;
end;
2022-03-08 12:25:51 -05:00
procedure TEditForm.tbFullViewClick(Sender: TObject);
begin
MainForm.mnuFullScreenClick(Sender);
end;
//-- Variables -------------------------------------------------------------
procedure TEditForm.ValidateVariable;
var
i: integer;
NewVal, OldVal: double;
str, oldstr: string;
begin
i := vleVariables.Row;
{$ifndef VAR_STR}
cp.xform[SelectedTriangle].GetVariable(vleVariables.Keys[i], OldVal);
{ Test that it's a valid floating point number }
try
NewVal := Round6(StrToFloat(vleVariables.Values[vleVariables.Keys[i]]));
except
{ It's not, so we restore the old value }
vleVariables.Values[vleVariables.Keys[i]] := Format('%.6g', [OldVal]);
// cp.xform[SelectedTriangle].GetVariableStr(vleVariables.Keys[i]);
exit;
end;
{ If it's not the same as the old value and it was valid }
if (NewVal <> OldVal) then
begin
vleVariables.Cells[1,i];
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].SetVariable(vleVariables.Keys[i], NewVal);
vleVariables.Values[vleVariables.Keys[i]] := Format('%.6g', [NewVal]);
ShowSelectedInfo;
UpdateFlame(True);
end;
{$else}
oldstr := cp.xform[SelectedTriangle].GetVariableStr(vleVariables.Keys[i]);
str := vleVariables.Values[vleVariables.Keys[i]];
cp.xform[SelectedTriangle].SetVariableStr(vleVariables.Keys[i], str);
if str <> oldstr then
begin
MainForm.UpdateUndo;
vleVariables.Values[vleVariables.Keys[i]] := str;
ShowSelectedInfo;
UpdateFlame(True);
end;
{$endif}
end;
procedure TEditForm.vleVariablesExit(Sender: TObject);
begin
ValidateVariable;
end;
procedure TEditForm.vleVariablesKeyPress(Sender: TObject; var Key: Char);
begin
if key <> #13 then Exit;
key := #0;
ValidateVariable;
end;
procedure TEditForm.vleVariablesValidate(Sender: TObject; ACol, ARow: Integer; const KeyName, KeyValue: string);
begin
ValidateVariable;
end;
// -----------------------------------------------------------------------------
procedure TEditForm.txtValidateValue(Sender: TObject);
var
t: double;
begin
try
t := StrToFloat(TComboBox(Sender).Text);
if t <> 0 then exit;
except
TComboBox(Sender).ItemIndex := 1;
end;
end;
procedure TEditForm.txtValKeyPress(Sender: TObject; var Key: Char);
begin
if key <> #13 then exit;
key := #0;
txtValidateValue(Sender);
end;
procedure TEditForm.mnuResetTriangleClick(Sender: TObject);
begin
if (MainTriangles[SelectedTriangle].x[0] = MainTriangles[-1].x[0]) and
(MainTriangles[SelectedTriangle].x[1] = MainTriangles[-1].x[1]) and
(MainTriangles[SelectedTriangle].x[2] = MainTriangles[-1].x[2]) and
(MainTriangles[SelectedTriangle].y[0] = MainTriangles[-1].y[0]) and
(MainTriangles[SelectedTriangle].y[1] = MainTriangles[-1].y[1]) and
(MainTriangles[SelectedTriangle].y[2] = MainTriangles[-1].y[2])
then exit;
MainForm.UpdateUndo;
MainTriangles[SelectedTriangle] := MainTriangles[-1];
UpdateFlame(True);
end;
procedure TEditForm.mnuResetAllClick(Sender: TObject);
var
i: integer;
saved: boolean;
2022-03-08 12:25:51 -05:00
begin
MainForm.UpdateUndo;
for i := 0 to Transforms do cp.xform[i].Clear;
cp.xform[0].SetVariation(0, 1);
cp.xform[0].density := 0.5;
cp.xform[1].symmetry := 1;
cp.center[0] := 0;
cp.center[1] := 0;
cp.zoom := 0;
cp.pixels_per_unit := PreviewImage.Width/4;
cp.FAngle := 0;
// AV: add 3D-camera resetting
cp.cameraPitch := 0;
cp.cameraYaw := 0;
cp.cameraRoll := 0;
cp.cameraPersp := 0;
cp.cameraZPos := 0;
cp.cameraDOF := 0;
Transforms := 1;
SelectedTriangle := 0; // AV: fixed - was 1;
2022-03-08 12:25:51 -05:00
MainTriangles[0] := MainTriangles[-1];
MainTriangles[1] := MainTriangles[-1]; // kinda reset finalxform
EnableFinalXform := false;
assert(cp.HasFinalXForm = false);
UpdateXformsList;
AutoZoom;
UpdateFlame(True);
if AutoSaveXML then // AV: create a flame from scratch if needed
begin
MainCp.name := 'New flame' + FormatDateTime(' (MM-dd-yyyy hh-mm-ss)', Now);
if (OpenFileType = ftXML) then
saved := MainForm.SaveXMLFlame(MainCp, MainCp.name, OpenFile)
else
saved := MainForm.SaveFlame(MainCp, MainCp.name, OpenFile);
if saved then MainForm.AddFlameToList; // AV: show the new item
2022-03-08 12:25:51 -05:00
end;
end;
procedure TEditForm.SaveFlameStateClick(Sender: TObject); // AV
{ Saves current flame into opened file and adds it to list view }
var
n: word;
FItem: TListItem;
Ftitle: string;
saved: boolean;
begin
n := 0; //
for FItem in MainForm.ListView1.Items do
if pos(MainCp.name, FItem.Caption) = 1 then inc(n);
if (n = 0) then
Ftitle := MainCp.name // current flame is not in the list
else begin
Ftitle := MainCp.name + ' (' + IntToStr(n) + ')';
Fitem := MainForm.ListView1.FindCaption(0, FTitle, false, true, false);
if FItem <> nil then // we already have a flame with the same name
Ftitle := MainCp.name + FormatDateTime(' (MM-dd-yyyy hh-mm-ss)', Now);
end;
if (OpenFileType = ftXML) then
saved := MainForm.SaveXMLFlame(MainCp, Ftitle, OpenFile)
else
saved := MainForm.SaveFlame(MainCp, Ftitle, OpenFile);
if saved then
MainForm.AddFlameToList(Ftitle); // show the new item
end;
2022-03-08 12:25:51 -05:00
// -----------------------------------------------------------------------------
procedure TEditForm.btnXcoefsClick(Sender: TObject);
begin
with cp.xform[SelectedTriangle] do
begin
if (c[0][0] = 1) and (c[0][1] = 0) then exit;
MainForm.UpdateUndo;
c[0][0] := 1;
c[0][1] := 0;
end;
cp.TrianglesFromCP(MainTriangles);
UpdateFlame(True);
end;
procedure TEditForm.btnYcoefsClick(Sender: TObject);
begin
if (cp.xform[SelectedTriangle].c[1][0] = 0) and
(cp.xform[SelectedTriangle].c[1][1] = 1) then exit;
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].c[1][0] := 0;
cp.xform[SelectedTriangle].c[1][1] := 1;
cp.TrianglesFromCP(MainTriangles);
UpdateFlame(True);
end;
procedure TEditForm.btnOcoefsClick(Sender: TObject);
begin
if (sender = mnuResetTrgPosition) and cp.xform[SelectedTriangle].postXswap then
begin
btnOpostClick(Sender);
exit;
end;
if (cp.xform[SelectedTriangle].c[2][0] = 0) and
(cp.xform[SelectedTriangle].c[2][1] = 0) then exit;
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].c[2][0] := 0;
cp.xform[SelectedTriangle].c[2][1] := 0;
cp.TrianglesFromCP(MainTriangles);
UpdateFlame(True);
end;
procedure TEditForm.btnCoefsModeClick(Sender: TObject);
begin
ShowSelectedInfo;
end;
procedure TEditForm.tbVarPreviewClick(Sender: TObject);
begin
showVarPreview := not showVarPreview;
tbVarPreview.Down := showVarPreview;
TriangleView.Invalidate;
end;
procedure TEditForm.trkVarPreviewRangeChange(Sender: TObject);
begin
trkVarPreviewRange.Hint := Format(TextByKey('editor-tab-color-previewrange') + ' %d', [trkVarPreviewRange.position]);
TriangleView.Invalidate;
end;
procedure TEditForm.trkVarPreviewDensityChange(Sender: TObject);
begin
trkVarPreviewDensity.Hint := Format(TextByKey('editor-tab-color-previewdensity') + ' %d', [trkVarPreviewDensity.position]);
TriangleView.Invalidate;
end;
procedure TEditForm.trkVarPreviewDepthChange(Sender: TObject);
begin
trkVarPreviewDepth.Hint := Format(TextByKey('editor-tab-color-previewdepth') + ' %d', [trkVarPreviewDepth.position]);
TriangleView.Invalidate;
end;
procedure TEditForm.btnXpostClick(Sender: TObject);
begin
with cp.xform[SelectedTriangle] do
begin
if (p[0][0] = 1) and (p[0][1] = 0) then exit;
MainForm.UpdateUndo;
p[0][0] := 1;
p[0][1] := 0;
end;
cp.TrianglesFromCP(MainTriangles);
UpdateFlame(True);
end;
procedure TEditForm.btnYpostClick(Sender: TObject);
begin
if (cp.xform[SelectedTriangle].p[1][0] = 0) and
(cp.xform[SelectedTriangle].p[1][1] = 1) then exit;
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].p[1][0] := 0;
cp.xform[SelectedTriangle].p[1][1] := 1;
cp.TrianglesFromCP(MainTriangles);
UpdateFlame(True);
end;
procedure TEditForm.btnOpostClick(Sender: TObject);
begin
if (cp.xform[SelectedTriangle].p[2][0] = 0) and
(cp.xform[SelectedTriangle].p[2][1] = 0) then exit;
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].p[2][0] := 0;
cp.xform[SelectedTriangle].p[2][1] := 0;
cp.TrianglesFromCP(MainTriangles);
UpdateFlame(True);
end;
// --Z-- copying functions is dumb... I am so lazy :-(
procedure TEditForm.PostCoefKeypress(Sender: TObject; var Key: Char);
begin
if key <> #13 then exit;
key := #0;
PostCoefValidate(Sender);
end;
procedure TEditForm.PostCoefValidate(Sender: TObject);
var
NewVal: double;
x, y, r, a: double; // dumb... must optimize
begin
try
NewVal := Round6(StrToFloat(TEdit(Sender).Text));
except on Exception do
begin
ShowSelectedInfo;
exit;
end;
end;
MainForm.UpdateUndo; // TODO - prevent unnecessary UpdateUndo...
with cp.xform[SelectedTriangle] do
begin
if btnCoefsRect.Down = true then
begin
if Sender = txtPost00 then p[0][0] := NewVal
else if Sender = txtPost01 then p[0][1] := -NewVal
else if Sender = txtPost10 then p[1][0] := -NewVal
else if Sender = txtPost11 then p[1][1] := NewVal
else if Sender = txtPost20 then p[2][0] := NewVal
else if Sender = txtPost21 then p[2][1] := -NewVal;
end
else begin
if (Sender = txtPost00) or (Sender = txtPost01) then begin
x := p[0][0];
y := -p[0][1];
end else
if (Sender = txtPost10) or (Sender = txtPost11) then begin
x := -p[1][0];
y := p[1][1];
end else
begin
x := p[2][0];
y := -p[2][1];
end;
r := Hypot(x, y);
a := arctan2(y, x);
if (Sender = txtPost00) or (Sender = txtPost10) or (Sender = txtPost20) then
r := NewVal
else
a := NewVal*PI/180;
x := r * cos(a);
y := r * sin(a);
if (Sender = txtPost00) or (Sender = txtPost01) then begin
p[0][0] := x;
p[0][1] := -y;
end else
if (Sender = txtPost10) or (Sender = txtPost11) then begin
p[1][0] := -x;
p[1][1] := y;
end else
begin
p[2][0] := x;
p[2][1] := -y;
end;
end;
end;
cp.TrianglesFromCP(MainTriangles);
//if tbAutoWeights.Down then cp.CalculateWeights;
ShowSelectedInfo;
UpdateFlame(true);
self.LastFocus := TEdit(sender);
end;
procedure TEditForm.btnResetCoefsClick(Sender: TObject);
begin
with cp.xform[SelectedTriangle] do
begin
if (c[0,0]<>1) or (c[0,1]<>0) or(c[1,0]<>0) or (c[1,1]<>1) or (c[2,0]<>0) or (c[2,1]<>0) then
begin
MainForm.UpdateUndo;
c[0, 0] := 1;
c[0, 1] := 0;
c[1, 0] := 0;
c[1, 1] := 1;
c[2, 0] := 0;
c[2, 1] := 0;
ShowSelectedInfo;
cp.TrianglesFromCP(MainTriangles);
if tbAutoWeights.Down then cp.CalculateWeights; // AV
UpdateFlame(True);
end;
end;
end;
procedure TEditForm.btnResetFlipClick(Sender: TObject);
begin
FlipPoint.x := 0;
FlipPoint.y := 0;
editFlipX.Text := '0';
editFlipY.Text := '0';
CalcFlip;
TriangleView.Invalidate;
end;
procedure TEditForm.btnResetPostCoefsClick(Sender: TObject);
begin
with cp.xform[SelectedTriangle] do
begin
if (p[0,0]<>1) or (p[0,1]<>0) or(p[1,0]<>0) or (p[1,1]<>1) or (p[2,0]<>0) or (p[2,1]<>0) then
begin
p[0, 0] := 1;
p[0, 1] := 0;
p[1, 0] := 0;
p[1, 1] := 1;
p[2, 0] := 0;
p[2, 1] := 0;
ShowSelectedInfo;
cp.TrianglesFromCP(MainTriangles);
UpdateFlame(True);
end;
end;
end;
procedure TEditForm.btnPivotModeClick(Sender: TObject);
begin
if PivotMode <> pivotLocal then
// with MainTriangles[SelectedTriangle] do
PivotMode := pivotLocal
else
// with MainTriangles[SelectedTriangle] do
PivotMode := pivotWorld;
TriangleView.Invalidate;
ShowSelectedInfo;
end;
procedure TEditForm.PivotValidate(Sender: TObject);
var
v: double;
begin
try
v := Round6(StrToFloat(TEdit(Sender).Text));
except on Exception do
begin
ShowSelectedInfo;
exit;
end;
end;
if Sender = editPivotX then
if v <> Round6(GetPivot.x) then begin
if PivotMode = pivotLocal then LocalPivot.x := v
else WorldPivot.x := v;
end
else exit
else
if v <> Round6(GetPivot.y) then begin
if PivotMode = pivotLocal then LocalPivot.y := v
else WorldPivot.y := v;
end
else exit;
TriangleView.Invalidate;
ShowSelectedInfo;
self.LastFocus := TEdit(sender);
end;
procedure TEditForm.PivotKeyPress(Sender: TObject; var Key: Char);
begin
if key <> #13 then exit;
key := #0;
PivotValidate(Sender);
end;
procedure TEditForm.btnResetPivotClick(Sender: TObject);
begin
if editMode = modePick then begin
editMode := oldMode;
oldMode := modeNone;
// hack: to generate MouseMove event
GetCursorPos(MousePos);
SetCursorPos(MousePos.x, MousePos.y);
//
end;
if PivotMode = pivotLocal then
begin
LocalPivot.x := 0;
LocalPivot.y := 0;
end
else begin
WorldPivot.x := 0;
WorldPivot.y := 0;
end;
TriangleView.Invalidate;
ShowSelectedInfo;
end;
procedure TEditForm.btnPickPivotClick(Sender: TObject);
begin
if editMode = modePick then begin
editMode := oldMode;
oldMode := modeNone;
TriangleView.Invalidate;
// hack: to generate MouseMove event
GetCursorPos(MousePos);
SetCursorPos(MousePos.x, MousePos.y);
//
exit;
end;
if oldMode <> modeNone then exit;
oldMode := editMode;
editMode := modePick;
TriangleView.Invalidate;
btnPickPivot.Down := true;
end;
procedure TEditForm.VEVarsDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
supports3D, supportsDC : boolean;
col : TColor;
frect : TRect;
i: integer;
begin
if (ARow = 0) then exit; // AV
i := GetVariationIndex(VEVars.Keys[ARow]); // AV
if (i > NRLOCVAR) and not (gdSelected in State) then
begin
if IsDarkTheme then // AV: dark UI design requies another colors
begin
if i > NumBuiltinVars then
col := MidColor
else begin
col := BrightColor;
if (CurrentStyle = 'Auric') then // make the text more visible
VEVars.Canvas.Font.Color := WinColor
end;
end
else begin // classic variant
if i > NumBuiltinVars then
col := $e0ffff // orange
else
col := $ffe0e0; // blue
end;
VEVars.canvas.brush.Color := col;
VEVars.canvas.fillRect(Rect);
VEVars.canvas.TextOut(Rect.Left+2, Rect.Top+2, VEVars.Cells[ACol,ARow]);
end
else col := VEVars.canvas.brush.color;
if (Acol = 0) and (Arow > 0) then
begin
2022-03-08 12:25:51 -05:00
VEVars.Canvas.Font.Name := 'Arial';
VEVars.Canvas.Font.Size := 5;
supports3D := VarSupports3D(i); // i <-- (Arow - 1)
supportsDC := VarSupportsDC(i); // AV: separate methods
2022-03-08 12:25:51 -05:00
if (supports3D or supportsDC) then // AV: optimized calculations
begin
frect.Left := Rect.Right - 12;
frect.Right := Rect.Right;
frect.Top := Rect.Top;
frect.Bottom := Rect.Bottom;
2022-03-08 12:25:51 -05:00
VEVars.canvas.brush.Color := col;
VEVars.canvas.fillRect(frect);
if (supports3D) then begin
VEVars.Canvas.Font.Color := $a00000;
VEVars.Canvas.TextOut(frect.Left, frect.Top + 2, '3D');
end;
if (supportsDC) then begin
VEVars.Canvas.Font.Color := $0000a0;
VEVars.Canvas.TextOut(frect.Left, frect.Top + 9, 'DC');
end;
2022-03-08 12:25:51 -05:00
end;
end;
end;
procedure TEditForm.tbEnableFinalXformClick(Sender: TObject);
begin
MainForm.UpdateUndo;
EnableFinalXform := tbEnableFinalXform.Down;
if (cp.HasFinalXForm = false) then
begin
if (EnableFinalXform = true) then
begin
cbTransforms.Items.Add(TextByKey('editor-common-finalxformlistitem'));
SelectedTriangle := Transforms;
if (mouseOverTriangle > LastTriangle) then mouseOverTriangle := -1;
end
else begin
if cbTransforms.Items.Count = Transforms+1 then
cbTransforms.Items.Delete(Transforms);
if SelectedTriangle >= Transforms then SelectedTriangle := Transforms-1;
end;
end;
cp.finalXformEnabled := EnableFinalXform;
UpdateFlame(True);
TriangleView.Invalidate;
UpdateSyncTriangles; // AV
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.DragPanelMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var dont :boolean;
begin
if Button <> mbLeft then exit;
// -X- why? its impossible!
assert(pnlDragMode = false); //?
if pnlDragMode = true then exit;
dont := false;
if (Sender = pnlWeight) then
if SelectedTriangle < Transforms then
pnlDragValue := cp.xform[SelectedTriangle].density
else exit
else if (Sender = pnlSymmetry) then
pnlDragValue := cp.xform[SelectedTriangle].symmetry
else if (Sender = pnlXformColor) then
pnlDragValue := cp.xform[SelectedTriangle].color
else if (Sender = pnlOpacity) then begin
if (txtOpacity.Enabled) then begin
pnlDragValue := cp.xform[SelectedTriangle].transOpacity;
end else dont := true;
end else if (Sender = pnlDC) then begin
if (txtDC.Enabled) then begin
pnlDragValue := cp.xform[SelectedTriangle].pluginColor;
end else dont := true;
end else assert(false);
if (not dont) then begin
pnlDragMode := true;
pnlDragPos := 0;
pnlDragOld := x;
varMM := false;
//SetCaptureControl(TControl(Sender));
Screen.Cursor := crHSplit;
//GetCursorPos(mousepos); // hmmm
mousePos := (Sender as TControl).ClientToScreen(Point(x, y));
HasChanged := false;
end;
end;
procedure TEditForm.DragPanelMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
var
v: double;
pEdit: ^TEdit;
begin
if varMM then // hack: to skip MouseMove event
begin
varMM:=false;
end
else
if pnlDragMode and (x <> pnlDragOld) then
begin
Inc(pnlDragPos, x - pnlDragOld);
if GetKeyState(VK_MENU) < 0 then v := 100000
else if GetKeyState(VK_CONTROL) < 0 then v := 10000
else if GetKeyState(VK_SHIFT) < 0 then v := 100
else v := 1000;
v := Round6(pnlDragValue + pnlDragPos / v);
SetCursorPos(MousePos.x, MousePos.y); // hmmm
varMM:=true;
if (Sender = pnlWeight) then
begin
if v <= 0.000001 then v := 0.000001
else if v > MAX_WEIGHT then v := MAX_WEIGHT;
cp.xform[SelectedTriangle].density := v;
pEdit := @txtP;
end
else if (Sender = pnlSymmetry) then
begin
if v < -1 then v := -1
else if v > 1 then v := 1;
cp.xform[SelectedTriangle].symmetry := v;
pEdit := @txtSymmetry;
end
else if (Sender = pnlOpacity) then
begin
if (txtOpacity.Enabled) then begin
if v < 0 then v := 0
else if v > 1 then v := 1;
cp.xform[SelectedTriangle].transOpacity := v;
pEdit := @txtOpacity;
end else exit;
end
else if (Sender = pnlDC) then
begin
if (txtDC.Enabled) then begin
if v < 0 then v := 0
else if v > 1 then v := 1;
cp.xform[SelectedTriangle].pluginColor := v;
pEdit := @txtDC;
end else exit;
end
else if (Sender = pnlXformColor) then
begin
if v < 0 then v := 0
else if v > 1 then v := 1;
cp.xform[SelectedTriangle].color := v;
pnlXFormColor.Color := ColorValToColor(cp.cmap, v);
shColor.Brush.Color := pnlXformColor.Color;
updating := true;
scrlXformColor.Position := round(v*1000);
pEdit := @txtXformColor;
updating := false;
end
else begin
assert(false);
exit;
end;
pEdit^.Text := FloatToStr(v);
pEdit.Refresh;
HasChanged := True;
DrawPreview;
end;
end;
procedure TEditForm.DragPanelMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button <> mbLeft then exit;
if pnlDragMode then
begin
//SetCaptureControl(nil);
pnlDragMode := false;
Screen.Cursor := crDefault;
if HasChanged then
begin
MainForm.UpdateUndo;
UpdateFlame(true);
HasChanged := False;
if (Sender = pnlWeight) and ChaosForm.Visible then // AV
ChaosForm.WeightVector.Invalidate;
end;
end;
end;
procedure TEditForm.DragPanelDblClick(Sender: TObject);
var
pValue: ^double;
pEdit: ^TEdit;
begin
if (Sender = pnlWeight) then
begin
if SelectedTriangle >= Transforms then exit; // hmm
pValue := @cp.xform[SelectedTriangle].density;
if pValue^ = 0.5 then exit;
pValue^ := 0.5;
pEdit := @txtP;
if ChaosForm.Visible then // AV
ChaosForm.WeightVector.Invalidate;
end
else if (Sender = pnlSymmetry) then
begin
pValue := @cp.xform[SelectedTriangle].symmetry;
if SelectedTriangle = Transforms then begin
if pValue^ = 1 then exit;
pValue^ := 1;
end
else begin
if pValue^ = 0 then exit;
pValue^ := 0;
end;
pEdit := @txtSymmetry;
end
else if (Sender = pnlXformColor) then
begin
pValue := @cp.xform[SelectedTriangle].color;
if pValue^ = 0 then exit;
pValue^ := 0;
pEdit := @txtXformColor;
end
else if (Sender = pnlOpacity) then
begin
if SelectedTriangle >= Transforms then exit; // hmm
pValue := @cp.xform[SelectedTriangle].transOpacity;
if pValue^ = 1.0 then begin
pValue^ := 0.0;
end else begin
pValue^ := 1.0;
end;
pEdit := @txtOpacity;
end
else if (Sender = pnlDC) then
begin
if SelectedTriangle >= Transforms then exit; // hmm
pValue := @cp.xform[SelectedTriangle].pluginColor;
if pValue^ = 1.0 then begin
pValue^ := 0.0;
end else begin
pValue^ := 1.0;
end;
pEdit := @txtDC;
end
else begin
assert(false);
exit;
end;
MainForm.UpdateUndo;
pEdit^.Text := FloatToStr(pValue^);
UpdateFlame(true);
end;
procedure TEditForm.mnuResetTrgRotationClick(Sender: TObject);
var
dx, dy: double;
ax, ay, da: integer;
nx0, ny0, nx2, ny2: double;
begin
with MainTriangles[SelectedTriangle] do
begin
// xx := x[0] - x[1];
// xy := y[0] - y[1];
// yx := x[2] - x[1];
// yy := y[2] - y[1];
ax := round( arctan2(xy, xx) / (pi/2) );
ay := round( arctan2(yy, yx) / (pi/2) );
dx := Hypot(xx, xy);
dy := Hypot(yx, yy);
if xx*yy - yx*xy >= 0 then da := 1 else da := -1;
if ax = ay then ay := ay + da
else if abs(ax-ay) = 2 then ay := ay - da;
nx0 := x[1] + dx*cos(ax*pi/2);
ny0 := y[1] + dx*sin(ax*pi/2);
nx2 := x[1] + dy*cos(ay*pi/2);
ny2 := y[1] + dy*sin(ay*pi/2);
if (x[0] = nx0) and (y[0] = ny0) and (x[2] = nx2) and (y[2] = ny2) then exit;
MainForm.UpdateUndo;
x[0] := nx0;
y[0] := ny0;
x[2] := nx2;
y[2] := ny2;
UpdateFlame(True);
end;
end;
procedure TEditForm.mnuResetTrgScaleClick(Sender: TObject);
var
dx, dy: double;
nx0, ny0, nx2, ny2: double;
begin
with MainTriangles[SelectedTriangle] do
begin
// xx := x[0] - x[1];
// xy := y[0] - y[1];
// yx := x[2] - x[1];
// yy := y[2] - y[1];
dx := Hypot(xx, xy);
dy := Hypot(yx, yy);
if dx <> 0 then begin
nx0 := x[1] + (x[0] - x[1])/dx;
ny0 := y[1] + (y[0] - y[1])/dx;
end
else begin
nx0 := x[1] + 1;
ny0 := y[1];
end;
if dx <> 0 then begin
nx2 := x[1] + (x[2] - x[1])/dy;
ny2 := y[1] + (y[2] - y[1])/dy;
end
else begin
nx2 := x[1];
ny2 := y[1] + 1;
end;
if (x[0] = nx0) and (y[0] = ny0) and (x[2] = nx2) and (y[2] = ny2) then exit;
MainForm.UpdateUndo;
x[0] := nx0;
y[0] := ny0;
x[2] := nx2;
y[2] := ny2;
UpdateFlame(True);
end;
end;
procedure TEditForm.RandomizeMatrixClick(Sender: TObject);
var i, j: integer;
begin
MainForm.UpdateUndo;
if Sender = RandomizeMatrix then
for i := 0 to Transforms-1 do
for j := 0 to Transforms-1 do
cp.xform[i].modWeights[j] := Round6(random)
else begin
if mnuChaosViewTo.Checked then
for j := 0 to Transforms-1 do
cp.xform[SelectedTriangle].modWeights[j] := Round6(random)
else for j := 0 to Transforms-1 do
cp.xform[j].modWeights[SelectedTriangle] := Round6(random);
end;
UpdateFlame(True);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
procedure TEditForm.ResetAxisRotation(n: integer);
var
dx, dy, d: double;
a: integer;
nx, ny: double;
begin
with MainTriangles[SelectedTriangle] do
begin
if n = 1 then
begin
d := Hypot(x[1], y[1]);
if d = 0 then exit;
a := round( arctan2(y[1], x[1]) / (pi/2) );
nx := d*cos(a*pi/2);
ny := d*sin(a*pi/2);
if (x[1] = nx) and (y[1] = ny) then exit;
MainForm.UpdateUndo;
x[1] := nx;
y[1] := ny;
x[0] := x[1] + xx;
y[0] := y[1] + xy;
x[2] := x[1] + yx;
y[2] := y[1] + yy;
UpdateFlame(True);
end
else begin
dx := x[n] - x[1];
dy := y[n] - y[1];
a := round( arctan2(dy, dx) / (pi/2) );
d := Hypot(dx, dy);
nx := x[1] + d*cos(a*pi/2);
ny := y[1] + d*sin(a*pi/2);
if (x[n] = nx) and (y[n] = ny) then exit;
MainForm.UpdateUndo;
x[n] := nx;
y[n] := ny;
UpdateFlame(True);
end;
end;
end;
procedure TEditForm.ResetAxisScale(n: integer);
var
dx, dy, d: double;
nx, ny: double;
begin
with MainTriangles[SelectedTriangle] do
begin
if n = 1 then
begin
d := Hypot(x[1], y[1]);
if d = 0 then exit;
nx := x[1]/d;
ny := y[1]/d;
if (x[1] = nx) and (y[1] = ny) then exit;
MainForm.UpdateUndo;
x[1] := nx;
y[1] := ny;
x[0] := x[1] + xx;
y[0] := y[1] + xy;
x[2] := x[1] + yx;
y[2] := y[1] + yy;
UpdateFlame(True);
end
else begin
dx := x[n] - x[1];
dy := y[n] - y[1];
d := Hypot(dx, dy);
if d <> 0 then begin
nx := x[1] + dx / d;
ny := y[1] + dy / d;
end
else begin
nx := x[1] + ifthen(n=0, 1, 0);
ny := y[1] + ifthen(n=2, 1, 0);
end;
if (x[n] = nx) and (y[n] = ny) then exit;
MainForm.UpdateUndo;
x[n] := nx;
y[n] := ny;
UpdateFlame(True);
end;
end;
end;
procedure TEditForm.tbPostXswapClick(Sender: TObject);
begin
cp.GetFromTriangles(MainTriangles, cp.NumXForms);
with cp.xform[SelectedTriangle] do begin
{ // AV: it doesn't work then user press hotkey T...
if (sender = tbPostXswap) then tb2PostXswap.down := tbPostXswap.Down;
if (sender = tb2PostXswap) then tbPostXswap.Down := tb2PostXSwap.Down;
postXswap := TToolButton(sender).Down; }
if (sender = tbPostXswap) or (sender = tb2PostXswap) then
postXswap := TToolButton(sender).Down
else
postXswap := not postXswap;
tbPostXswap.Down := postXswap;
tb2PostXswap.Down := postXswap;
ShowSelectedInfo;
end;
cp.TrianglesFromCP(MainTriangles);
TriangleView.Refresh;
end;
procedure TEditForm.btnCopyTriangleClick(Sender: TObject);
begin
MemTriangle := MainTriangles[SelectedTriangle];
tbPasteTriangle.Enabled := True;
PasteTriangleCoordinates.Enabled := True;
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.btnFlipClick(Sender: TObject);
var px, py, fx, fy: double;
begin
px := GetPivot.x;
py := GetPivot.y;
if (PivotMode = pivotLocal) then
with MainTriangles[SelectedTriangle] do begin
fx := x[1] + (x[0] - x[1])* FlipPoint.x + (x[2] - x[1])* FlipPoint.y;
fy := y[1] + (y[0] - y[1])* FlipPoint.x + (y[2] - y[1])* FlipPoint.y;
end
else begin
fx := FlipPoint.x;
fy := FlipPoint.y;
end;
if (px = fx) and (py = fy) then exit;
MainForm.UpdateUndo;
2022-03-08 12:25:51 -05:00
MainTriangles[SelectedTriangle] :=
FlipTriangleLine(MainTriangles[SelectedTriangle], px, py, fx, fy);
UpdateFlame(true);
end;
procedure TEditForm.btnFullChaosClick(Sender: TObject);
begin
ChaosForm.Show;
end;
procedure TEditForm.btnPasteTriangleClick(Sender: TObject);
begin
if (MainTriangles[SelectedTriangle].x[0] <> MemTriangle.x[0]) or
(MainTriangles[SelectedTriangle].x[1] <> MemTriangle.x[1]) or
(MainTriangles[SelectedTriangle].x[2] <> MemTriangle.x[2]) or
(MainTriangles[SelectedTriangle].y[0] <> MemTriangle.y[0]) or
(MainTriangles[SelectedTriangle].y[1] <> MemTriangle.y[1]) or
(MainTriangles[SelectedTriangle].y[2] <> MemTriangle.y[2]) then
begin
MainForm.UpdateUndo;
MainTriangles[SelectedTriangle] := MemTriangle;
UpdateFlame(True);
end;
end;
procedure TEditForm.chkAutoZscaleClick(Sender: TObject);
begin
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].autoZscale := chkAutoZscale.Checked;
UpdateFlame(True);
end;
// --------------------------------------------------------------- Chaos Editor
procedure TEditForm.ValidateChaos;
var
i: integer;
NewVal, OldVal: double;
begin
i := vleChaos.Row - 1;
if mnuChaosViewTo.Checked then
OldVal := Round6(cp.xform[SelectedTriangle].modWeights[i])
else
OldVal := Round6(cp.xform[i].modWeights[SelectedTriangle]);
try
NewVal := Round6(StrToFloat(vleChaos.Cells[1, i+1]));
except
vleChaos.Cells[1, i+1] := Format('%.6g', [OldVal]);
exit;
end;
if (NewVal <> OldVal) then
begin
MainForm.UpdateUndo;
if mnuChaosViewTo.Checked then
cp.xform[SelectedTriangle].modWeights[i] := NewVal
else
cp.xform[i].modWeights[SelectedTriangle] := NewVal;
vleChaos.Cells[1, i+1] := Format('%.6g', [NewVal]);
ShowSelectedInfo;
UpdateFlame(True);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
end;
procedure TEditForm.vleChaosExit(Sender: TObject);
begin
ValidateChaos;
end;
procedure TEditForm.vleChaosKeyPress(Sender: TObject; var Key: Char);
begin
if (Key = '-') then Key:= #0; // AV
if key = #13 then
begin
key := #0;
ValidateChaos;
end;
end;
procedure TEditForm.vleChaosValidate(Sender: TObject; ACol, ARow: Integer;
const KeyName, KeyValue: String);
begin
ValidateChaos;
end;
procedure TEditForm.VleChaosDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
h,ax,ay,bx,by: integer;
trgColor: TColor;
begin
if (ACol > 0) or (ARow = 0) then exit;
trgColor := GetTriangleColor(ARow - 1);
with vleChaos.Canvas do begin
h := Rect.Bottom - Rect.Top - 2;
// TextOut(Rect.Left+h+2, Rect.Top+1, vleChaos.Cells[ACol, ARow]);
ax:=Rect.Right-3;
ay:=Rect.Top+2;
bx:=Rect.Right-h;
by:=Rect.Bottom-3;
pen.Color := clBlack;
Polyline([Point(ax+1, ay-2), Point(ax+1, by+1), Point(bx-2, by+1), Point(ax+1, ay-2)]);
pen.Color := trgColor;
brush.Color := pen.Color shr 1 and $7f7f7f;
Polygon([Point(ax, ay), Point(ax, by), Point(bx, by)]);
end;
end;
procedure TEditForm.mnuChaosViewToClick(Sender: TObject);
var
i: integer;
begin
mnuChaosViewTo.Checked := true;
for i := 1 to vleChaos.RowCount-1 do begin
vleChaos.Cells[0, i] := Format(TextByKey('editor-common-toprefix'), [i]);
vleChaos.Cells[1, i] := FloatToStr(cp.xform[SelectedTriangle].modWeights[i-1]);
end;
//ShowSelectedInfo;
end;
procedure TEditForm.mnuChaosViewFromClick(Sender: TObject);
var
i: integer;
begin
mnuChaosViewFrom.Checked := true;
for i := 1 to vleChaos.RowCount-1 do begin
vleChaos.Cells[0, i] := Format(TextByKey('editor-common-fromprefix'), [i]);
vleChaos.Cells[1, i] := FloatToStr(cp.xform[i-1].modWeights[SelectedTriangle]);
end;
//ShowSelectedInfo;
end;
procedure TEditForm.mnuCopyChaosClick(Sender: TObject);
var i: smallint;
begin
SetLength(MemChaos, NXFORMS);
if mnuChaosViewTo.Checked then
for i := 0 to high(MemChaos) do
MemChaos[i] := cp.xform[SelectedTriangle].modWeights[i]
else
for i := 0 to high(MemChaos) do
MemChaos[i] := cp.xform[i].modWeights[SelectedTriangle];
mnuPasteChaos.Enabled := True;
PasteChaos.Enabled := True;
end;
procedure TEditForm.mnuPasteChaosClick(Sender: TObject);
var i, t: smallint;
begin
MainForm.UpdateUndo;
if mnuChaosViewTo.Checked then
for t in SyncTriangles do
for i := 0 to high(MemChaos) do
cp.xform[t].modWeights[i] := MemChaos[i]
else
for t in SyncTriangles do
for i := 0 to high(MemChaos) do
cp.xform[i].modWeights[t] := MemChaos[i];
UpdateFlame(true);
if ChaosForm.Visible then ChaosForm.ChaosMatrix.Invalidate;
end;
2022-03-08 12:25:51 -05:00
(*
procedure TEditForm.chkPlotModeClick(Sender: TObject);
var newMode: boolean;
begin
if (SelectedTriangle < Transforms) then
begin
newMode := chkXformInvisible.Checked;
if cp.xform[SelectedTriangle].noPlot <> newMode then begin
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].noPlot := newMode;
UpdateFlame(true);
end;
end;
end;
*)
procedure TEditForm.mnuChangeGridClick(Sender: TObject); // AV
begin
if not TMenuItem(Sender).Checked then
begin
TMenuItem(Sender).Checked := True;
try
if Sender = RectGrid then // AV: classic arrows
begin
btTrgMoveUp.Glyph := nil;
IconsAV.GetBitmap(0, btTrgMoveUp.Glyph);
btTrgMoveDown.Glyph := nil;
IconsAV.GetBitmap(1, btTrgMoveDown.Glyph);
end else begin // AV: slope arrows
btTrgMoveUp.Glyph := nil;
IconsAV.GetBitmap(2, btTrgMoveUp.Glyph);
btTrgMoveDown.Glyph := nil;
IconsAV.GetBitmap(3, btTrgMoveDown.Glyph);
end;
finally
end;
end;
end;
procedure TEditForm.mnuChaosClearAllClick(Sender: TObject);
var
i: integer;
noEdit: boolean;
begin
noEdit := true;
for i := 1 to cp.NumXForms do
if mnuChaosViewTo.Checked then begin
if cp.xform[SelectedTriangle].modWeights[i-1] <> 0 then begin
noEdit := false;
break;
end;
end
else begin
if cp.xform[i-1].modWeights[SelectedTriangle] <> 0 then begin
noEdit := false;
break;
end;
end;
if noEdit then exit;
Mainform.UpdateUndo;
for i := 1 to cp.NumXForms do
if mnuChaosViewTo.Checked then
cp.xform[SelectedTriangle].modWeights[i-1] := 0
else
cp.xform[i-1].modWeights[SelectedTriangle] := 0;
UpdateFlame(true);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
procedure TEditForm.mnuChaosSetAllClick(Sender: TObject);
var
i: integer;
noEdit: boolean;
begin
noEdit := true;
for i := 1 to cp.NumXForms do
if mnuChaosViewTo.Checked then begin
if cp.xform[SelectedTriangle].modWeights[i-1] <> 1 then begin
noEdit := false;
break;
end;
end
else begin
if cp.xform[i-1].modWeights[SelectedTriangle] <> 1 then begin
noEdit := false;
break;
end;
end;
if noEdit then exit;
Mainform.UpdateUndo;
for i := 1 to cp.NumXForms do
if mnuChaosViewTo.Checked then
cp.xform[SelectedTriangle].modWeights[i-1] := 1
else
cp.xform[i-1].modWeights[SelectedTriangle] := 1;
UpdateFlame(true);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
procedure TEditForm.mnuLinkPostxformClick(Sender: TObject);
var
i, k: integer;
begin
if (Transforms < NXFORMS) and (SelectedTriangle <> Transforms) then
begin
MainForm.UpdateUndo;
MainTriangles[Transforms+1] := MainTriangles[Transforms];
cp.xform[Transforms+1].Assign(cp.xform[Transforms]);
MainTriangles[Transforms] := MainTriangles[-1];
cp.xform[Transforms].Clear;
if InheritWeights.Checked then
cp.xform[Transforms].density := cp.xform[SelectedTriangle].density
else cp.xform[Transforms].density := 0.5;
cp.xform[Transforms].SetVariation(0, 1);
for i := 0 to NXFORMS-1 do begin
if (i = Transforms) then continue;
cp.xform[Transforms].modWeights[i] := cp.xform[SelectedTriangle].modWeights[i];
cp.xform[SelectedTriangle].modWeights[i] := 0;
end;
for i := 0 to NXFORMS-1 do
cp.xform[i].modWeights[Transforms] := 0;
cp.xform[SelectedTriangle].modWeights[Transforms] := 1;
cp.xform[Transforms].symmetry := 1;
cp.xform[Transforms].transOpacity := cp.xform[SelectedTriangle].transOpacity;
cp.xform[SelectedTriangle].transOpacity := 0;
hasLinkX := True;
k := SelectedTriangle;
SelectedTriangle := Transforms;
cp.xform[SelectedTriangle].TransformName := 'Post-link for TX ' + IntToStr(k + 1);
Inc(Transforms);
UpdateXformsList;
UpdateFlame(True);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
end;
procedure TEditForm.mnuLinkPreXformClick(Sender: TObject);
var
i, k: integer;
begin
if (Transforms < NXFORMS) and (SelectedTriangle <> Transforms) then
begin
MainForm.UpdateUndo;
MainTriangles[Transforms+1] := MainTriangles[Transforms];
cp.xform[Transforms+1].Assign(cp.xform[Transforms]);
MainTriangles[Transforms] := MainTriangles[-1];
cp.xform[Transforms].Clear;
if InheritWeights.Checked then
cp.xform[Transforms].density := cp.xform[SelectedTriangle].density
else cp.xform[Transforms].density := 0.5;
cp.xform[Transforms].SetVariation(0, 1);
for i := 0 to NXFORMS-1 do begin
if (i = Transforms) then continue;
cp.xform[i].modWeights[Transforms] := cp.xform[i].modWeights[SelectedTriangle];
cp.xform[i].modWeights[SelectedTriangle] := 0;
end;
for i := 0 to NXFORMS-1 do
cp.xform[Transforms].modWeights[i] := 0;
cp.xform[Transforms].modWeights[SelectedTriangle] := 1;
cp.xform[Transforms].symmetry := 1;
cp.xform[Transforms].transOpacity := 0;
hasLinkX := True;
k := SelectedTriangle;
SelectedTriangle := Transforms;
cp.xform[SelectedTriangle].TransformName := 'Pre-link for TX ' + IntToStr(k + 1);
Inc(Transforms);
UpdateXformsList;
UpdateFlame(True);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
end;
procedure TEditForm.chkXformSoloClick(Sender: TObject);
begin
if chkXformSolo.Checked <> (cp.soloXform >=0) then begin
if chkXformSolo.Checked then begin
if (SelectedTriangle < Transforms) then begin
cp.soloXform := SelectedTriangle;
UpdateFlame(true);
end;
end
else begin
cp.soloXform := -1;
UpdateFlame(true);
end;
end;
end;
procedure TEditForm.mnuChaosRebuildClick(Sender: TObject);
begin
RebuildXaosLinks := not RebuildXaosLinks;
mnuChaosRebuild.Checked := RebuildXaosLinks;
end;
procedure TEditForm.chkCollapseVariationsClick(Sender: TObject);
var
i: integer;
s: string;
IsSupport: boolean;
2022-03-08 12:25:51 -05:00
begin
s := Trim(txtSearchBox.Text);
for i := 1 to VEVars.RowCount - 1 do
begin
if (Length(s) = 0) or ((Length(s) <= Length(VEVars.Cells[0, i])) and
(Pos(s, VEVars.Cells[0, i]) > 0)) then // AV: search text is not empty
2022-03-08 12:25:51 -05:00
begin
case cbCollapseVariations.ItemIndex of
0: VEVars.RowHeights[i] := VEVars.DefaultRowHeight; // all
1: if Assigned(cp) then
VEVars.RowHeights[i] := // active
IfThen((VEVars.Cells[1,i] = '0'), -1, VEVars.DefaultRowHeight)
else
VEVars.RowHeights[i] := -1;
2: VEVars.RowHeights[i] := // favourites
IfThen(FavouriteVariations[GetVariationIndex(VEVars.Cells[0,i])], // i-1
VEVars.DefaultRowHeight, -1);
3: // 3D
begin
IsSupport := VarSupports3D(GetVariationIndex(VEVars.Cells[0,i]));
VEVars.RowHeights[i] := IfThen(IsSupport, VEVars.DefaultRowHeight, -1);
end;
4: // DC
begin
IsSupport := VarSupportsDC(GetVariationIndex(VEVars.Cells[0,i]));
VEVars.RowHeights[i] := IfThen(IsSupport, VEVars.DefaultRowHeight, -1);
end;
2022-03-08 12:25:51 -05:00
end;
end
else
2022-03-08 12:25:51 -05:00
VEVars.RowHeights[i] := -1;
end;
{
2022-03-08 12:25:51 -05:00
s := Trim(txtSearchBox.Text);
for i:= 1 to VEVars.RowCount - 1 do
begin
if (Length(s) = 0) then
begin
if ((Assigned(cp)) and (VEVars.Cells[1,i]='0')) then
if chkCollapseVariations.Checked then
VEVars.RowHeights[i] := -1
else
VEVars.RowHeights[i] := VEVars.DefaultRowHeight
else
VEVars.RowHeights[i] := VEVars.DefaultRowHeight;
end
else begin
if (Length(s) > Length(VEVars.Cells[0, i])) then
VEVars.RowHeights[i] := -1
else if Pos(s, VEVars.Cells[0, i]) > 0 then
begin
if ((Assigned(cp)) and (VEVars.Cells[1,i]='0')) then
if chkCollapseVariations.Checked then
VEVars.RowHeights[i] := -1
else
VEVars.RowHeights[i] := VEVars.DefaultRowHeight
else
VEVars.RowHeights[i] := VEVars.DefaultRowHeight;
end
else
VEVars.RowHeights[i] := -1;
end;
end;
}
2022-03-08 12:25:51 -05:00
end;
procedure TEditForm.chkCollapseVariablesClick(Sender: TObject);
var
i, vari: integer;
begin
for i := 1 to vleVariables.RowCount - 1 do
begin
if chkCollapseVariables.Checked then
vleVariables.RowHeights[i] := vleVariables.DefaultRowHeight
else
begin
vari := GetVariationIndexFromVariableNameIndex(i-1);
if ( (vari = -1) or
((Assigned(cp)) and (cp.xform[SelectedTriangle].GetVariation(vari) = 0)) ) then
vleVariables.RowHeights[i] := -1
else
vleVariables.RowHeights[i] := vleVariables.DefaultRowHeight;
end;
end;
end;
procedure TEditForm.shColorMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DragPanelMouseDown(pnlXFormColor, Button, Shift, X, Y);
end;
procedure TEditForm.shColorMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
DragPanelMouseMove(pnlXFormColor, Shift, X, Y);
end;
procedure TEditForm.shColorMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DragPanelMouseUp(pnlXFormColor, Button, Shift, X, Y);
end;
procedure TEditForm.bClearClick(Sender: TObject);
var
i:integer;
changed:boolean;
begin
changed := false;
for i := 0 to VEVars.RowCount - 1 do begin
if (cp.xform[SelectedTriangle].GetVariation(i) <> 0) then changed := true;
cp.xform[SelectedTriangle].SetVariation(i, 0);
end;
if changed then MainForm.UpdateUndo;
UpdateFlame(true);
end;
procedure TEditForm.ResetChaosClick(Sender: TObject);
var i, j: integer;
noEdit: boolean;
begin
noEdit := true;
for i := 0 to Transforms-1 do
begin
if not noEdit then break;
for j := 0 to Transforms-1 do
if cp.xform[i].modWeights[j] <> 1 then
begin
noEdit := false;
break;
end;
end;
if noEdit then exit;
MainForm.UpdateUndo;
for i := 0 to NXforms-1 do
for j := 0 to NXforms-1 do
cp.xform[i].modWeights[j] := 1;
UpdateFlame(True);
if ChaosForm.Visible then // AV
ChaosForm.ChaosMatrix.Invalidate;
end;
procedure TEditForm.mnuResetTrgFlipClick(Sender: TObject);
var
x0, y0, x1, y1, detT: double;
begin
with cp.xform[SelectedTriangle] do
if postXswap then
detT := det(p[0,0], p[1,0], p[0,1], p[1,1])
else detT := det(c[0,0], c[1,0], c[0,1], c[1,1]);
if (detT >= 0) then exit;
with MainTriangles[SelectedTriangle] do
begin
x0 := x[1];
y0 := y[1];
x1 := x[0] + x[2] - x0;
y1 := y[0] + y[2] - y0;
end;
MainForm.UpdateUndo;
MainTriangles[SelectedTriangle] :=
FlipTriangleLine(MainTriangles[SelectedTriangle], x0, y0, x1, y1);
UpdateFlame(true);
end;
procedure TEditForm.btResetparamsClick(Sender: TObject);
var
i: integer;
begin
for i:= 0 to GetNrVariableNames - 1 do begin
cp.xform[SelectedTriangle].ResetVariable(GetVariableNameAt(i));
end;
MainForm.UpdateUndo;
UpdateFlame(true);
end;
procedure TEditForm.btSwapCoefsClick(Sender: TObject);
var
i, j: byte;
t: double;
begin
MainForm.UpdateUndo;
with cp.xform[SelectedTriangle] do
for i := 0 to 2 do
for j := 0 to 1 do
begin
t := c[i,j];
c[i,j] := p[i,j];
p[i,j] := t;
end;
if not tbPostXSwap.Down then
cp.GetTriangle(MainTriangles[SelectedTriangle], SelectedTriangle)
else cp.GetPostTriangle(MainTriangles[SelectedTriangle], SelectedTriangle);
UpdateFlame(true);
end;
procedure TEditForm.ColorBarMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
dx: double;
2022-03-08 12:25:51 -05:00
begin
// dx := Round(100 * X / ColorBar.Width) / 100; // <-- AV: it's not correct
2022-03-08 12:25:51 -05:00
dx := X / (ColorBarPicture.Width - 1); // AV: this gives the best results
txtXFormColor.Text := FloatToStrF(dx, ffFixed, 4, 3); // AV: default presision
txtXFormColorExit(nil);
end;
{
procedure TEditForm.btnLoadVVARClick(Sender: TObject);
var
fn:string;
i:integer;
begin
if OpenSaveFileDialog(EditForm, '.dll', 'Dynamic Link Libraries (*.dll)|*.dll', '.\Plugins', 'LoadPlugin...', fn, true, false, false, true) then begin
//if (fn <> '') then begin
LoadPlugin(fn);
VEVars.Strings.Clear;
vleVariables.Strings.Clear;
for i:= 0 to NRVAR - 1 do begin
VEVars.InsertRow(Varnames(i), '0', True);
end;
for i:= 0 to GetNrVariableNames - 1 do begin
vleVariables.InsertRow(GetVariableNameAt(i), '0', True);
end;
for i := 0 to Transforms - 1 do begin
cp.xform[i].InvokeAddRegVariations;
end;
end;
end;
end;
}
procedure TEditForm.txtNameKeyPress(Sender: TObject; var Key: Char);
begin
if SelectedTriangle >= Transforms then key := #0;
if key = #13 then
begin
{ Stop the beep }
Key := #0;
txtNameExit(sender);
end;
end;
procedure TEditForm.txtNameExit(Sender: TObject);
var
n:integer;
oldval,newval:string;
begin
oldval := cp.xform[SelectedTriangle].TransformName;
newval := txtName.Text;
if (oldval <> newval) then begin
MainForm.UpdateUndo;
cp.xform[SelectedTriangle].TransformName := newval;
n := SelectedTriangle + 1;
if (cp.xform[SelectedTriangle].TransformName <> '') then
cbTransforms.Items[SelectedTriangle] := IntToStr(n) + ' - ' + cp.xform[SelectedTriangle].TransformName
else
cbTransforms.Items[SelectedTriangle] := IntToStr(n);
//workaround..
if (SelectedTriangle >= Transforms) then
cbTransforms.Items[SelectedTriangle] := TextByKey('editor-common-finalxformlistitem');
cbTransforms.ItemIndex := SelectedTriangle;
UpdateFlame(True);
end;
end;
procedure TEditForm.TriangleOperationsClick(Sender: TObject);
begin
TMenuItem(Sender).Checked := True;
end;
procedure TEditForm.TrianglePanelResize(Sender: TObject);
begin
gbTrgOperations.Left := (TrianglePanel.CLientWidth - gbTrgOperations.Width) div 2;
gbCoordinates.Left := (TrianglePanel.CLientWidth - gbCoordinates.Width) div 2;
gbPivot.Left := (TrianglePanel.CLientWidth - gbPivot.Width) div 2;
gbFlip.Left := (TrianglePanel.CLientWidth - gbFlip.Width) div 2;
2022-03-08 12:25:51 -05:00
TriangleToolBar.Left := (TrianglePanel.CLientWidth - TriangleToolBar.Width) div 2;
end;
procedure TEditForm.ControlPanelResize(Sender: TObject);
begin
cbTransforms.ItemHeight := Panel1.Height - 6;
cbTransforms.Height := Panel1.Height;
PageControl.Top := Panel1.Height + Panel2.Height + pnlWeight.Height + 12;
PageControl.Height := ControlPanel.Height - PageControl.Top;
end;
procedure TEditForm.CopyTransformClick(Sender: TObject);
var
txt: string;
i, n: byte;
2022-03-08 12:25:51 -05:00
begin
MemCp.Clear;
MemCp.Name := 'Memorized XForm Parameters';
if (not UseTriangleSync) or (SelectedTriangle = Transforms) then
MemCp.xform[0].Assign(cp.xform[SelectedTriangle])
else begin // AV: copy all selected transforms
n := 0;
for i in SyncTriangles do
begin
MemCp.xform[n].Assign(cp.xform[i]);
inc(n);
end;
end;
txt := Trim(FlameToXML(MemCp));
2022-03-08 12:25:51 -05:00
Clipboard.SetTextBuf(PChar(txt));
PasteTransform.Enabled := True;
2022-03-08 12:25:51 -05:00
MainForm.mnuPaste.Enabled := False;
end;
procedure TEditForm.CopyVariationsClick(Sender: TObject);
begin
try
VEVars.Strings.SaveToFile(APPDATA + saved_variations);
VLEVariables.Strings.SaveToFile(APPDATA + saved_variables);
PasteVariations.Enabled := True;
except
// TODO
PasteVariations.Enabled := False;
end;
end;
procedure TEditForm.PasteTransformClick(Sender: TObject);
2022-03-08 12:25:51 -05:00
var
TempTriangles: TTriangles;
i, t: smallint;
2022-03-08 12:25:51 -05:00
begin
t := MemCp.NumXForms - 1;
if (t >= 0) and (Transforms + t < NXFORMS) then
2022-03-08 12:25:51 -05:00
begin
MainForm.UpdateUndo;
MemCp.TrianglesFromCP(TempTriangles);
for i := 0 to t do
2022-03-08 12:25:51 -05:00
begin
MainTriangles[Transforms+1] := MainTriangles[Transforms];
cp.xform[Transforms+1].Assign(cp.xform[Transforms]);
MainTriangles[Transforms] := TempTriangles[i];
cp.xform[Transforms].Assign(MemCp.xform[i]);
SelectedTriangle := Transforms;
Inc(Transforms);
end;
UpdateXformsList;
UpdateFlame(True);
end;
end;
procedure TEditForm.PasteVariationsClick(Sender: TObject);
var
i: integer;
v: double;
s: string;
begin
MainForm.UpdateUndo;
try
VEVars.Strings.LoadFromFile(APPDATA + saved_variations);
for i := 0 to NrVar-1 do
begin
s := VEVars.Strings.Names[i];
cp.xform[SelectedTriangle].SetVariation(GetVariationIndex(s),
StrToFloat(VEVars.Strings.Values[s]));
cp.xform[SelectedTriangle].ifs[i] := s;
end;
VLEVariables.Strings.LoadFromFile(APPDATA + saved_variables);
for i := 0 to GetNrVariableNames - 1 do
begin
v := StrToFloat(VLEVariables.Strings.ValueFromIndex[i]);
cp.xform[SelectedTriangle].SetVariable(VLEVariables.Strings.Names[i], v);
end;
UpdateFlame(true);
except
// restore defaults?
cp.xform[SelectedTriangle].SetVariation(0, 1);
cp.xform[SelectedTriangle].ifs[0] := 'linear';
VEVars.Strings.BeginUpdate;
VEVars.Strings[0] := 'linear=1';
for i := 1 to NrVar-1 do
begin
s := VarNames(i);
cp.xform[SelectedTriangle].SetVariation(i, 0);
cp.xform[SelectedTriangle].ifs[i] := s;
VEVars.Strings[i] := s + '=0';
end;
VEVars.Strings.EndUpdate;
VLEVariables.Strings.BeginUpdate;
for i := 0 to GetNrVariableNames - 1 do
begin
s := GetVariableNameAt(i);
cp.xform[SelectedTriangle].ResetVariable(s);
VLEVariables.Strings[i] := s + '=' + cp.xform[SelectedTriangle].GetVariableStr(s);
end;
VLEVariables.Strings.EndUpdate;
UpdateFlame(true);
end;
end;
2022-03-08 12:25:51 -05:00
procedure TEditForm.ScrollBox2Resize(Sender: TObject);
begin // AV: done
GroupBox1.Left := (ScrollBox2.ClientWidth - GroupBox1.Width) div 2;
GroupBox2.Left := (ScrollBox2.ClientWidth - GroupBox2.Width) div 2;
end;
procedure TEditForm.ScrollBox1Resize(Sender: TObject);
var sbw: integer; // AV: for speed
begin
sbw := (ScrollBox1.ClientWidth - GroupBox9.Width) div 2;
GroupBox7.Left := sbw;
GroupBox8.Left := sbw;
GroupBox9.Left := sbw;
chkAutoZscale.Left := sbw;
btSwapCoefs.Left := sbw;
btConjugate.Left := sbw + 116;
end;
procedure TEditForm.FlipPointKeyPress(Sender: TObject; var Key: Char);
begin
if key <> #13 then exit;
key := #0;
FlipPointValidate(Sender);
end;
procedure TEditForm.FlipPointValidate(Sender: TObject);
var
v: double;
begin
try
v := Round6(StrToFloat(TEdit(Sender).Text));
if Sender = editFlipX then
FlipPoint.x := v
else
FlipPoint.y := v;
except // restore old value
if Sender = editFlipX then v := FlipPoint.x
else v := FlipPoint.y;
end;
TEdit(Sender).Text := Format('%.6g',[v]);
TriangleView.Invalidate;
CalcFlip;
end;
procedure TEditForm.FormActivate(Sender: TObject);
begin
if EnableEditorPreview and PrevPnl.Visible then
begin
Splitter2.Height := 1;
Splitter2.Visible := false;
PrevPnl.Height := 1;
PrevPnl.Visible := false;
end
else if (not EnableEditorPreview) and (not PrevPnl.Visible) then
begin
Splitter2.Height := 8;
Splitter2.Visible := true;
PrevPnl.Height := 177;
PrevPnl.Visible := true;
end;
// AV: check if these parameters were changed in options
tbExtendedEdit.Down := ExtEditEnabled;
tbAxisLock.Down := TransformAxisLock;
mnuChaosRebuild.Checked := RebuildXaosLinks;
AdjustSyncTriangles; // AV
2022-03-08 12:25:51 -05:00
chkCollapseVariationsClick(nil);
end;
(* // AV: exactly the same as chkCollapseVariationsClick
procedure TEditForm.txtSearchBoxChange(Sender: TObject);
var
i: integer;
s: string;
begin
s := Trim(txtSearchBox.Text);
for i:= 1 to VEVars.RowCount - 1 do begin
if (Length(s) = 0) then begin
if ((Assigned(cp)) and (VEVars.Cells[1,i]='0')) then
if chkCollapseVariations.Checked then VEVars.RowHeights[i] := -1
else VEVars.RowHeights[i] := VEVars.DefaultRowHeight
else VEVars.RowHeights[i] := VEVars.DefaultRowHeight;
end else begin
if (Length(s) > Length(VEVars.Cells[0, i])) then
VEVars.RowHeights[i] := -1
else if Pos(s, VEVars.Cells[0, i]) > 0 then begin
if ((Assigned(cp)) and (VEVars.Cells[1,i]='0')) then
if chkCollapseVariations.Checked then VEVars.RowHeights[i] := -1
else VEVars.RowHeights[i] := VEVars.DefaultRowHeight
else VEVars.RowHeights[i] := VEVars.DefaultRowHeight;
end else VEVars.RowHeights[i] := -1;
end;
end;
end;
*)
procedure TEditForm.txtSearchBoxKeyPress(Sender: TObject; var Key: Char);
begin
// AV: exactly the same as chkCollapseVariationsClick
// txtSearchBoxChange(Sender);
chkCollapseVariationsClick(Sender); // AV
end;
procedure TEditForm.btnResetSearchClick(Sender: TObject);
begin
txtSearchBox.Text := '';
end;
procedure TEditForm.btnShowLineClick(Sender: TObject);
begin
ShowFlipLine := not ShowFlipLine;
if ShowFlipLine then btnShowLine.Caption := TextByKey('editor-tab-triangle-hideline')
else btnShowLine.Caption := TextByKey('editor-tab-triangle-showline');
TriangleView.Invalidate;
end;
procedure TEditForm.btnVarOrderClick(Sender: TObject);
var
i: integer;
begin
if (VarOrder.ShowModal = mrOK) then
if VarOrder.Changed then
begin
MainForm.UpdateUndo;
for i := 0 to NrVar - 1 do
cp.xform[SelectedTriangle].ifs[i] := VarOrder.VarListView.Items[i].Caption;
UpdateVariationList;
chkCollapseVariationsClick(Sender);
UpdateFlame(true);
end;
end;
procedure TEditForm.KeyInput(str:string);
var
Inp: TInput;
mapCh: UINT;
sym: byte;
i: Integer;
begin
Application.ProcessMessages;
for i := 1 to Length(Str) do
begin
{
Inp.Itype := INPUT_KEYBOARD;
Inp.ki.wVk := Ord(Str[i]);
Inp.ki.dwFlags := 0;
SendInput(1, Inp, SizeOf(Inp));
Inp.Itype := INPUT_KEYBOARD;
Inp.ki.wVk := Ord(Str[i]);
Inp.ki.dwFlags := KEYEVENTF_KEYUP;
SendInput(1, Inp, SizeOf(Inp));
}
// AV: hack - to "press" Enter when a numeric field is active
if Str[i] = #13 then
sym := VK_RETURN // for faster work
else
sym := VkKeyScan(Str[i]);
mapCh := MapVirtualKey(LOBYTE(sym), 0);
Inp.Itype := INPUT_KEYBOARD;
Inp.ki.dwFlags := KEYEVENTF_SCANCODE;
Inp.ki.wScan := mapCh;
SendInput(1, Inp, SizeOf(Inp));
Inp.Itype := INPUT_KEYBOARD;
Inp.ki.dwFlags := KEYEVENTF_KEYUP;
Inp.ki.wScan := mapCh;
SendInput(1, Inp, SizeOf(Inp));
end;
end;
end.