parametercurvesformunit.pas 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. unit parametercurvesformunit;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, ComCtrls,
  6. StdCtrls, Spin, ButtonPanel, fpjson, BGRABitmap, BGRABitmapTypes,
  7. parametercurvegeneratorformunit, database, LCLTranslator;
  8. type
  9. { TParameterCurvesForm }
  10. TParameterCurvesForm = class(TForm)
  11. SetValuesWithMouseCheckBox: TCheckBox;
  12. ResultButtonPanel: TButtonPanel;
  13. GenerateButton: TButton;
  14. ManualSettingsGroupBox: TGroupBox;
  15. AdvancedGenerationGroupBox: TGroupBox;
  16. GraphPaintBox: TPaintBox;
  17. ParamSpinEdit: TSpinEdit;
  18. ValueLabel: TLabel;
  19. LevelLabel: TLabel;
  20. PresetAButton: TButton;
  21. PresetBButton: TButton;
  22. PresetCButton: TButton;
  23. PresetDButton: TButton;
  24. PresetEButton: TButton;
  25. QuickGenerationGroupBox: TGroupBox;
  26. MainPanel: TPanel;
  27. ParamTabControl: TTabControl;
  28. LevelSpinEdit: TSpinEdit;
  29. procedure CancelButtonClick(Sender: TObject);
  30. procedure FormCreate(Sender: TObject);
  31. procedure GenerateButtonClick(Sender: TObject);
  32. procedure GraphPaintBoxMouseDown(Sender: TObject; Button: TMouseButton;
  33. Shift: TShiftState; X, Y: Integer);
  34. procedure GraphPaintBoxMouseMove(Sender: TObject; Shift: TShiftState; X,
  35. Y: Integer);
  36. procedure GraphPaintBoxMouseUp(Sender: TObject; Button: TMouseButton;
  37. Shift: TShiftState; X, Y: Integer);
  38. procedure GraphPaintBoxPaint(Sender: TObject);
  39. procedure LevelSpinEditChange(Sender: TObject);
  40. procedure OKButtonClick(Sender: TObject);
  41. procedure ParamSpinEditChange(Sender: TObject);
  42. procedure ParamTabControlChange(Sender: TObject);
  43. procedure PresetButtonClick(Sender: TObject);
  44. procedure SetParamByMouse(X, Y: Integer);
  45. procedure UpdateParamNames(Db: TDatabase);
  46. private
  47. ResultWasAccepted: Boolean;
  48. IsSettingCurveByMouse: Boolean;
  49. EditedParams: TJSONArray;
  50. procedure PresetValues;
  51. procedure GetGraphData(var OffsetLeft: Integer; var BarWidth: Integer);
  52. { Generates a param as a curve from StartVal to EndVal. Steepness is a
  53. number from -10 to 10, -10 is the fastest growth, 10 is the slowest,
  54. 0 is a straight line. }
  55. procedure GenerateParamCurve(StartVal, EndVal, Steepness: Integer);
  56. public
  57. procedure EditParams(Db: TDatabase; ClassObj: TJSONObject; StartingParamId: Integer);
  58. end;
  59. var
  60. ParameterCurvesForm: TParameterCurvesForm;
  61. implementation
  62. uses
  63. constants, globals, Math;
  64. {$R *.lfm}
  65. { TParameterCurvesForm }
  66. procedure TParameterCurvesForm.PresetButtonClick(Sender: TObject);
  67. var
  68. ParamId: Integer;
  69. FromVal, ToVal: Integer;
  70. Quality: Integer;
  71. begin
  72. ParamId := ParamTabControl.TabIndex;
  73. Quality := (Sender as TButton).Tag;
  74. if ParamId < 2 then begin
  75. FromVal := 200 + Quality*100 + Random(100);
  76. ToVal := 4000 + Quality*1000 + Random(1000);
  77. end else begin
  78. FromVal := 20 + Quality*10 + Random(10);
  79. ToVal := 400 + Quality*100 + Random(100);
  80. end;
  81. GenerateParamCurve(FromVal, ToVal, 0);
  82. GraphPaintBox.Refresh
  83. end;
  84. procedure TParameterCurvesForm.ParamTabControlChange(Sender: TObject);
  85. begin
  86. PresetValues;
  87. GraphPaintBox.Refresh
  88. end;
  89. procedure TParameterCurvesForm.GraphPaintBoxPaint(Sender: TObject);
  90. var
  91. BarWidth: Integer = 0;
  92. OffsetLeft: Integer = 0;
  93. GraphHeight: Integer;
  94. Graph: TBGRABitmap;
  95. ParamId: Integer;
  96. I: Integer;
  97. Param: TJSONArray;
  98. ParamValue, BarHeight: Integer;
  99. MaxParamValue: Integer;
  100. begin
  101. GetGraphData(OffsetLeft, BarWidth);
  102. GraphHeight := GraphPaintBox.Height;
  103. Graph := TBGRABitmap.Create(BarWidth * 99, GraphHeight, clWhite);
  104. ParamId := ParamTabControl.TabIndex;
  105. Param := EditedParams.Arrays[ParamId];
  106. MaxParamValue := GetMaxParamValue(ParamId);
  107. Graph.CanvasBGRA.Brush.Color := ColorToBGRA(ParameterColours[ParamId]);
  108. for I := 0 to 98 do begin
  109. ParamValue := Param.Integers[I + 1];
  110. BarHeight := GraphHeight * ParamValue div MaxParamValue;
  111. Graph.CanvasBGRA.FillRect(BarWidth * I, GraphHeight, BarWidth * (I+1), GraphHeight - BarHeight);
  112. end;
  113. Graph.Draw(GraphPaintBox.Canvas, OffsetLeft, 0);
  114. Graph.Free;
  115. end;
  116. procedure TParameterCurvesForm.CancelButtonClick(Sender: TObject);
  117. begin
  118. ResultWasAccepted := False;
  119. Close
  120. end;
  121. procedure TParameterCurvesForm.FormCreate(Sender: TObject);
  122. begin
  123. {In WinXP, if the top bar is too large, the rest is filled with black (in
  124. Win10 it's form colour so that works somehow). But in GTK+, if the top bar
  125. is too small, an exception is triggered.
  126. So, we use GTK+ size but change the size in Windows}
  127. {$IF Defined(LCLWin32)}
  128. ParamTabControl.Height := 20;
  129. {$ENDIF}
  130. end;
  131. procedure TParameterCurvesForm.GenerateButtonClick(Sender: TObject);
  132. var
  133. ParamId: Integer;
  134. Param: TJSONArray;
  135. begin
  136. ParamId := ParamTabControl.TabIndex;
  137. Param := EditedParams.Arrays[ParamId];
  138. if ParameterCurveGeneratorForm.ShowChoice(Param.Integers[0+1],
  139. Param.Integers[98 + 1], 0, GetMaxParamValue(ParamId)) then
  140. with ParameterCurveGeneratorForm do begin
  141. GenerateParamCurve(Level1Value, Level99Value, Smoothness);
  142. GraphPaintBox.Refresh
  143. end;
  144. end;
  145. procedure TParameterCurvesForm.GraphPaintBoxMouseDown(Sender: TObject;
  146. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  147. begin
  148. IsSettingCurveByMouse := True;
  149. SetParamByMouse(X, Y);
  150. GraphPaintBox.Refresh
  151. end;
  152. procedure TParameterCurvesForm.GraphPaintBoxMouseMove(Sender: TObject;
  153. Shift: TShiftState; X, Y: Integer);
  154. begin
  155. if IsSettingCurveByMouse then begin
  156. SetParamByMouse(X, Y);
  157. GraphPaintBox.Refresh
  158. end;
  159. end;
  160. procedure TParameterCurvesForm.GraphPaintBoxMouseUp(Sender: TObject;
  161. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  162. begin
  163. IsSettingCurveByMouse := False
  164. end;
  165. procedure TParameterCurvesForm.SetParamByMouse(X, Y: Integer);
  166. var
  167. ParamId: Integer;
  168. Param: TJSONArray;
  169. BarWidth: Integer = 0;
  170. OffsetLeft: Integer = 0;
  171. ParamLevel, ParamValue: Integer;
  172. begin
  173. ParamId := ParamTabControl.TabIndex;
  174. GetGraphData(OffsetLeft, BarWidth);
  175. ParamLevel := (X - OffsetLeft) div BarWidth + 1;
  176. if SetValuesWithMouseCheckBox.Checked then begin
  177. Param := EditedParams.Arrays[ParamId];
  178. if (ParamLevel >= 1) and (ParamLevel <= 99) then begin
  179. ParamValue := (GraphPaintBox.Height - Y) * GetMaxParamValue(ParamId) div GraphPaintBox.Height;
  180. if ParamValue > GetMaxParamValue(ParamId) then
  181. ParamValue := GetMaxParamValue(ParamId);
  182. if ParamValue < 1 then
  183. ParamValue := 1;
  184. Param.Integers[ParamLevel] := ParamValue
  185. end;
  186. end;
  187. if (ParamLevel >= 1) and (ParamLevel <= 99) then
  188. LevelSpinEdit.Value := ParamLevel;
  189. end;
  190. procedure TParameterCurvesForm.LevelSpinEditChange(Sender: TObject);
  191. var
  192. ParamId: Integer;
  193. Param: TJSONArray;
  194. begin
  195. ParamId := ParamTabControl.TabIndex;
  196. Param := EditedParams.Arrays[ParamId];
  197. ParamSpinEdit.Value := Param.Integers[LevelSpinEdit.Value];
  198. end;
  199. procedure TParameterCurvesForm.OKButtonClick(Sender: TObject);
  200. begin
  201. ResultWasAccepted := True;
  202. Close
  203. end;
  204. procedure TParameterCurvesForm.ParamSpinEditChange(Sender: TObject);
  205. var
  206. ParamId: Integer;
  207. Param: TJSONArray;
  208. begin
  209. ParamId := ParamTabControl.TabIndex;
  210. Param := EditedParams.Arrays[ParamId];
  211. Param.Integers[LevelSpinEdit.Value] := ParamSpinEdit.Value;
  212. GraphPaintBox.Refresh;
  213. end;
  214. procedure TParameterCurvesForm.EditParams(Db: TDatabase; ClassObj: TJSONObject;
  215. StartingParamId: Integer);
  216. begin
  217. ResultWasAccepted := False;
  218. UpdateParamNames(Db);
  219. EditedParams := ClassObj.Arrays['params'].Clone as TJSONArray;
  220. ParamTabControl.TabIndex := StartingParamId;
  221. PresetValues;
  222. ShowModal;
  223. if ResultWasAccepted then begin
  224. ClassObj.Delete('params');
  225. ClassObj.Add('params', EditedParams);
  226. end else
  227. EditedParams.Free;
  228. end;
  229. procedure TParameterCurvesForm.PresetValues;
  230. var
  231. ParamId: Integer;
  232. Param: TJSONArray;
  233. begin
  234. ParamId := ParamTabControl.TabIndex;
  235. Param := EditedParams.Arrays[ParamId];
  236. if ParamId < 2 then
  237. ParamSpinEdit.MaxValue := 9999
  238. else
  239. ParamSpinEdit.MaxValue := 999;
  240. LevelSpinEdit.Value := 1;
  241. ParamSpinEdit.Value := Param.Integers[1];
  242. //TODO
  243. end;
  244. procedure TParameterCurvesForm.GetGraphData(var OffsetLeft: Integer;
  245. var BarWidth: Integer);
  246. var
  247. GraphWidth: Integer;
  248. begin
  249. BarWidth := GraphPaintBox.Width div 99;
  250. GraphWidth := BarWidth * 99;
  251. OffsetLeft := (GraphPaintBox.Width - GraphWidth) div 2;
  252. end;
  253. procedure TParameterCurvesForm.GenerateParamCurve(StartVal, EndVal, Steepness: Integer);
  254. var
  255. ParamId: Integer;
  256. Param: TJSONArray;
  257. I, Value: Integer;
  258. PowerVal, Divisor: Double;
  259. begin
  260. ParamId := ParamTabControl.TabIndex;
  261. Param := EditedParams.Arrays[ParamId];
  262. if Steepness <> 0 then begin
  263. if Steepness > 0 then
  264. PowerVal := 1 + 1 * Steepness / 10
  265. else
  266. PowerVal := 1 + 1/2 * Steepness / 10;
  267. Divisor := Power(99, PowerVal);
  268. end;
  269. for I := 1 to 99 do begin
  270. if Steepness = 0 then
  271. Value := StartVal + (EndVal - StartVal) * (I) div 99
  272. else
  273. Value := Round(
  274. StartVal +
  275. (Power((I), PowerVal) / Divisor) * (EndVal - StartVal)
  276. );
  277. Param.Integers[I] := Value;
  278. end;
  279. (* Hack: the function above is sometimes generating numbers where startval and
  280. endval are not the expected ones. This is a bug, but the function doesn't
  281. require precision so I'll just set the start and end value to
  282. to StartVal and EndVal for now. More mathematically-inclined people are
  283. welcome to fix the function above. (Or maybe it's just a rounding issue?) *)
  284. Param.Integers[1] := StartVal;
  285. Param.Integers[99] := EndVal;
  286. end;
  287. procedure TParameterCurvesForm.UpdateParamNames(Db: TDatabase);
  288. var
  289. I: Integer;
  290. begin
  291. //TODO: set param names from vocabulary
  292. ParamTabControl.Tabs.BeginUpdate;
  293. for I := 0 to 7 do begin
  294. ParamTabControl.Tabs[I] := Db.GetParamName(I);
  295. end;
  296. ParamTabControl.Tabs.EndUpdate;
  297. end;
  298. end.