Advertisement
--JawZ--

TES5EDIT - Weather Editor code

Jun 24th, 2014
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.53 KB | None | 0 0
  1. {
  2. Weather Editor v0.1
  3. Supports Oblivion, Skyrim, Fallout 3, Fallout New Vegas
  4.  
  5. Hotkey: Ctrl+W
  6. }
  7.  
  8. unit WeatherEditor;
  9.  
  10. const
  11. sCloudTexturesLocation = 'textures\sky\';
  12. iColorEditorWidth = 170;
  13. iColorEditorHeight = 50;
  14.  
  15. var
  16. Weather: IInterface;
  17. sCloudLayerSignatures, sColorTimes: string;
  18. slCloudTextures, slCloudSignatures, slColorTimes: TStringList;
  19. lstCED, lstCEDElement: TList; // list of Color Editors and respective elements
  20. frm: TForm;
  21. pgcWeather: TPageControl;
  22. tsClouds, tsWeatherColors, tsLightingColors, tsTools: TTabSheet;
  23. lbCloudLayers: TCheckListBox;
  24. pnlCloud, pnlCloudEdit: TPanel;
  25. cmbCloudTexture: TComboBox;
  26. btnShowCloudTexture, btnApplyCloud, btnApplyWeatherColors, btnApplyLightingColors: TButton;
  27. btnCopyClouds, btnCopyWeatherColors, btnCopyLightingColors: TButton;
  28. edCloudXSpeed, edCloudYSpeed, edCloudAlpha1, edCloudAlpha2, edCloudAlpha3, edCloudAlpha4: TLabeledEdit;
  29. imgCloud: TImage;
  30. CountCloudLayers: integer; // a total number of supported cloud layers
  31. CountTimes: integer; // a total number of times (sunrise, day, sunset, night)
  32. CountWeatherColors: integer; // a total number of weather colors
  33. CountLightingColors: integer; // a total number of lighting colors
  34.  
  35. //============================================================================
  36. function CheckEditable(e: IInterface): Boolean;
  37. begin
  38. Result := IsEditable(e);
  39. if not Result then
  40. MessageDlg(Format('%s \ %s is not editable', [GetFileName(e), Name(e)]), mtError, [mbOk], 0);
  41. end;
  42.  
  43. //============================================================================
  44. // copy element elName from RecSrc record to RecDst record
  45. procedure CopyElement(RecSrc, RecDst: IInterface; elName: string);
  46. var
  47. el: IInterface;
  48. begin
  49. el := ElementByPath(recsrc, elName);
  50. if not Assigned(el) then begin
  51. RemoveElement(recdst, elName);
  52. Exit;
  53. end;
  54. if not ElementExists(recdst, elName) then
  55. Add(recdst, elName, True);
  56. ElementAssign(ElementByPath(recdst, elName), LowInteger, el, False);
  57. end;
  58.  
  59. //============================================================================
  60. // record selector
  61. function SelectRecord(aSignatures: string; aWithOverrides: Boolean): IInterface;
  62. var
  63. sl, slRec: TStringList;
  64. i, j, k: integer;
  65. f, g, r: IInterface;
  66. clb: TCheckListBox;
  67. frm: TForm;
  68. begin
  69. sl := TStringList.Create;
  70. sl.Delimiter := ',';
  71. sl.StrictDelimiter := True;
  72. sl.DelimitedText := aSignatures;
  73. slRec := TStringList.Create;
  74.  
  75. for i := 0 to Pred(FileCount) do begin
  76. f := FileByIndex(i);
  77. for j := 0 to Pred(sl.Count) do begin
  78. g := GroupBySignature(f, sl[j]);
  79. for k := 0 to Pred(ElementCount(g)) do begin
  80. r := ElementByIndex(g, k);
  81. if aWithOverrides then
  82. slRec.AddObject(GetFileName(r) + ' \ '+ Name(r), r)
  83. else
  84. if IsMaster(r) then begin
  85. r := WinningOverride(r);
  86. slRec.AddObject(Name(r), r);
  87. end;
  88. end;
  89. end;
  90. end;
  91.  
  92. frm := frmFileSelect;
  93. frm.Width := 600;
  94. try
  95. frm.Caption := 'Select a record';
  96. clb := TCheckListBox(frm.FindComponent('CheckListBox1'));
  97. clb.Items.Assign(slRec);
  98. if frm.ShowModal <> mrOk then Exit;
  99. for i := 0 to Pred(clb.Items.Count) do
  100. if clb.Checked[i] then begin
  101. Result := ObjectToElement(clb.Items.Objects[i]);
  102. Exit;
  103. end;
  104. finally
  105. frm.Free;
  106. sl.Free;
  107. slRec.Free;
  108. end;
  109. end;
  110.  
  111. //============================================================================
  112. // convert a color element in plugin to TColor
  113. function ColorElementToColor(elColor: IInterface): LongWord;
  114. begin
  115. Result := Result or GetElementNativeValues(elColor, 'Blue') shl 16;
  116. Result := Result or GetElementNativeValues(elColor, 'Green') shl 8;
  117. Result := Result or GetElementNativeValues(elColor, 'Red');
  118. end;
  119.  
  120. //============================================================================
  121. // load colors from weather record into color editors with index idxFrom..idxTo
  122. procedure ColorEditorReadColor(idxFrom, idxTo: integer);
  123. var
  124. i: integer;
  125. begin
  126. for i := idxFrom to idxTo do
  127. TPanel(lstCED[i]).Color := ColorElementToColor(ObjectToElement(lstCEDElement[i]));
  128. end;
  129.  
  130. //============================================================================
  131. // save colors to weather record for color editors with index idxFrom..idxTo
  132. procedure ColorEditorWriteColor(idxFrom, idxTo: integer);
  133. var
  134. i: integer;
  135. c: LongWord;
  136. e: IInterface;
  137. begin
  138. for i := idxFrom to idxTo do begin
  139. c := TPanel(lstCED[i]).Color;
  140. e := ObjectToElement(lstCEDElement[i]);
  141. SetElementNativeValues(e, 'Red', c and $FF);
  142. SetElementNativeValues(e, 'Green', (c shr 8) and $FF);
  143. SetElementNativeValues(e, 'Blue', (c shr 16) and $FF);
  144. end;
  145. end;
  146.  
  147. //============================================================================
  148. // color editor click event, show color dialog
  149. procedure ColorEditorClick(Sender: TObject);
  150. var
  151. pnl: TPanel;
  152. dlgColor: TColorDialog;
  153. i, j: integer;
  154. begin
  155. pnl := TPanel(Sender);
  156. dlgColor := TColorDialog.Create(frm);
  157. dlgColor.Options := [cdFullOpen, cdAnyColor];
  158. dlgColor.Color := pnl.Color;
  159. // add quartet colors as custom ones
  160. j := Round((pnl.Tag div CountTimes) * CountTimes);
  161. for i := 0 to Pred(CountTimes) do
  162. dlgColor.CustomColors.Add(Format('Color%s=%s', [Chr(65+i), IntToHex(TPanel(lstCED[j+i]).Color, 6)]));
  163. if dlgColor.Execute then
  164. pnl.Color := dlgColor.Color;
  165. dlgColor.Free;
  166. end;
  167.  
  168. //===========================================================================
  169. // on key down event handler for form
  170. procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  171. begin
  172. if Key = VK_ESCAPE then
  173. TForm(Sender).ModalResult := mrOk;
  174. end;
  175.  
  176. //============================================================================
  177. // save settings for weather colors
  178. procedure btnApplyWeatherColorsClick(Sender: TObject);
  179. begin
  180. if not CheckEditable(Weather) then
  181. Exit;
  182.  
  183. ColorEditorWriteColor(CountTimes, CountTimes + Pred(CountWeatherColors));
  184. end;
  185.  
  186. //============================================================================
  187. // save settings for lighting colors
  188. procedure btnApplyLightingColorsClick(Sender: TObject);
  189. begin
  190. if not CheckEditable(Weather) then
  191. Exit;
  192.  
  193. ColorEditorWriteColor(CountTimes + CountWeatherColors, CountTimes + CountWeatherColors + Pred(CountLightingColors));
  194. end;
  195.  
  196. //============================================================================
  197. // view current cloud layer texture, can be used when texture name is edited by user
  198. procedure btnShowCloudTextureClick(Sender: TObject);
  199. var
  200. CloudTexture: string;
  201. begin
  202. CloudTexture := 'textures\' + LowerCase(cmbCloudTexture.Text);
  203. if not ResourceExists(CloudTexture) then begin
  204. AddMessage(CloudTexture + ' does not exist.');
  205. Exit;
  206. end;
  207. wbDDSDataToBitmap(ResourceOpenData('', CloudTexture), imgCloud.Picture.Bitmap);
  208. end;
  209.  
  210. //============================================================================
  211. // save settings for a cloud layer
  212. procedure btnApplyCloudClick(Sender: TObject);
  213. var
  214. Layer, i: integer;
  215. begin
  216. if not CheckEditable(Weather) then
  217. Exit;
  218.  
  219. Layer := lbCloudLayers.ItemIndex;
  220. SetElementEditValues(Weather, slCloudSignatures[Layer], cmbCloudTexture.Text);
  221.  
  222. if wbGameMode = gmTES5 then begin
  223. SetElementEditValues(Weather, Format('Cloud Speed\QNAM - X Speed\Layer #%d', [Layer]), edCloudXSpeed.Text);
  224. SetElementEditValues(Weather, Format('Cloud Speed\RNAM - Y Speed\Layer #%d', [Layer]), edCloudYSpeed.Text);
  225. SetElementEditValues(Weather, Format('JNAM\Layer #%d\Sunrise', [Layer]), edCloudAlpha1.Text);
  226. SetElementEditValues(Weather, Format('JNAM\Layer #%d\Day', [Layer]), edCloudAlpha2.Text);
  227. SetElementEditValues(Weather, Format('JNAM\Layer #%d\Sunset', [Layer]), edCloudAlpha3.Text);
  228. SetElementEditValues(Weather, Format('JNAM\Layer #%d\Night', [Layer]), edCloudAlpha4.Text);
  229. end
  230. else if (wbGameMode = gmFO3) or (wbGameMode = gmFNV) then
  231. SetEditValue(ElementByIndex(ElementByPath(Weather, 'ONAM'), Layer), edCloudXSpeed.Text)
  232. else if wbGameMode = gmTES4 then
  233. SetEditValue(ElementByIndex(ElementByPath(Weather, 'DATA'), Layer + 1), edCloudXSpeed.Text);
  234.  
  235. ColorEditorWriteColor(0, Pred(CountTimes));
  236. end;
  237.  
  238. //============================================================================
  239. // User clicks on a cloud layer, load cloud layer data and show cloud texture
  240. procedure lbCloudLayersClick(Sender: TObject);
  241. var
  242. Layer, i: integer;
  243. CloudTexture: string;
  244. elColors: IInterface;
  245. begin
  246. Layer := lbCloudLayers.ItemIndex;
  247.  
  248. // show cloud texture
  249. CloudTexture := LowerCase(GetElementEditValues(Weather, slCloudSignatures[Layer]));
  250. if SameText(Copy(CloudTexture, 1, 9), 'textures\') then
  251. Delete(CloudTexture, 1, 9);
  252. cmbCloudTexture.Text := CloudTexture;
  253. if CloudTexture <> '' then
  254. btnShowCloudTexture.Click
  255. else
  256. imgCloud.Picture := nil;
  257.  
  258. // fill layer parameters
  259. if wbGameMode = gmTES5 then begin
  260. edCloudXSpeed.Text := GetElementEditValues(Weather, Format('Cloud Speed\QNAM - X Speed\Layer #%d', [Layer]));
  261. edCloudYSpeed.Text := GetElementEditValues(Weather, Format('Cloud Speed\RNAM - Y Speed\Layer #%d', [Layer]));
  262. edCloudAlpha1.Text := GetElementEditValues(Weather, Format('JNAM\Layer #%d\Sunrise', [Layer]));
  263. edCloudAlpha2.Text := GetElementEditValues(Weather, Format('JNAM\Layer #%d\Day', [Layer]));
  264. edCloudAlpha3.Text := GetElementEditValues(Weather, Format('JNAM\Layer #%d\Sunset', [Layer]));
  265. edCloudAlpha4.Text := GetElementEditValues(Weather, Format('JNAM\Layer #%d\Night', [Layer]));
  266. end
  267. else if (wbGameMode = gmFO3) or (wbGameMode = gmFNV) then
  268. edCloudXSpeed.Text := GetEditValue(ElementByIndex(ElementByPath(Weather, 'ONAM'), Layer))
  269. else if wbGameMode = gmTES4 then
  270. edCloudXSpeed.Text := GetEditValue(ElementByIndex(ElementByPath(Weather, 'DATA'), Layer + 1));
  271.  
  272. // fill layer colors
  273. if wbGameMode = gmTES5 then
  274. elColors := ElementByName(ElementByIndex(ElementByPath(Weather, 'PNAM'), Layer), 'Colors')
  275. else if (wbGameMode = gmFO3) or (wbGameMode = gmFNV) then
  276. elColors := ElementByIndex(ElementByPath(Weather, 'PNAM'), Layer)
  277. else if wbGameMode = gmTES4 then begin
  278. if Layer = 0 then
  279. elColors := ElementByIndex(ElementByPath(Weather, 'NAM0'), 2)
  280. else if Layer = 1 then
  281. elColors := ElementByIndex(ElementByPath(Weather, 'NAM0'), 9);
  282. end;
  283.  
  284. for i := 0 to Pred(CountTimes) do
  285. lstCEDElement[i] := ElementByIndex(elColors, i);
  286. ColorEditorReadColor(0, Pred(CountTimes));
  287. end;
  288.  
  289. //============================================================================
  290. // User clicks on a cloud layer check box, enable or disable cloud layer
  291. procedure lbCloudLayersClickCheck(Sender: TObject);
  292. var
  293. Layer, i: integer;
  294. DisabledClouds: LongWord;
  295. begin
  296. Layer := lbCloudLayers.ItemIndex;
  297.  
  298. // can't disable cloud layers in games before Skyrim
  299. if (wbGameMode = gmTES4) or (wbGameMode = gmFO3) or (wbGameMode = gmFNV) then begin
  300. lbCloudLayers.Checked[Layer] := True;
  301. MessageDlg(Format('Can not disable cloud layer in %s', [wbGameName]), mtError, [mbOk], 0);
  302. Exit;
  303. end;
  304.  
  305. if not CheckEditable(Weather) then begin
  306. // can't edit layer, restore layer's check state back
  307. lbCloudLayers.Checked[Layer] := not lbCloudLayers.Checked[Layer];
  308. Exit;
  309. end;
  310.  
  311. // enable layer
  312. if lbCloudLayers.Checked[Layer] then begin
  313. Add(Weather, slCloudSignatures[Layer], True);
  314. DisabledClouds := GetElementNativeValues(Weather, 'NAM1');
  315. DisabledClouds := DisabledClouds and (not (1 shl Layer));
  316. SetElementNativeValues(Weather, 'NAM1', DisabledClouds);
  317. end
  318. // disable layer
  319. else begin
  320. // since disabling removes cloud texture subrecord which means a data loss, ask user first
  321. i := MessageDlg(Format('Do you really want to disable cloud layer %d?', [Layer]), mtConfirmation, [mbYes, mbNo], 0);
  322. if i = mrYes then begin
  323. RemoveElement(Weather, slCloudSignatures[Layer]);
  324. DisabledClouds := GetElementNativeValues(Weather, 'NAM1');
  325. DisabledClouds := DisabledClouds or (1 shl Layer);
  326. SetElementNativeValues(Weather, 'NAM1', DisabledClouds);
  327. // reload cloud layer data since texture is removed
  328. lbCloudLayersClick(nil);
  329. end else
  330. lbCloudLayers.Checked[Layer] := not lbCloudLayers.Checked[Layer];
  331. end;
  332. end;
  333.  
  334. //============================================================================
  335. // copy clouds from another weather
  336. procedure btnCopyCloudsClick(Sender: TObject);
  337. var
  338. i: integer;
  339. WeatherFrom: IInterface;
  340. begin
  341. if not CheckEditable(Weather) then
  342. Exit;
  343.  
  344. WeatherFrom := SelectRecord('WTHR', True);
  345. if not Assigned(WeatherFrom) or Equals(Weather, WeatherFrom) then
  346. Exit;
  347.  
  348. // copy clouds textures
  349. for i := 0 to Pred(slCloudSignatures.Count) do
  350. CopyElement(WeatherFrom, Weather, slCloudSignatures[i]);
  351.  
  352. // copy clouds speed, alpha, colors
  353. if wbGameMode = gmTES5 then begin
  354. CopyElement(WeatherFrom, Weather, 'NAM1');
  355. CopyElement(WeatherFrom, Weather, 'Cloud Speed');
  356. CopyElement(WeatherFrom, Weather, 'JNAM');
  357. CopyElement(WeatherFrom, Weather, 'PNAM');
  358. CopyElement(WeatherFrom, Weather, 'Sky Statics');
  359. end
  360. else if (wbGameMode = gmFO3) or (wbGameMode = gmFNV) then begin
  361. CopyElement(WeatherFrom, Weather, 'ONAM');
  362. CopyElement(WeatherFrom, Weather, 'PNAM');
  363. end else if wbGameMode = gmTES4 then begin
  364. ElementAssign(ElementByIndex(ElementByPath(Weather, 'NAM0'), 2), LowInteger, ElementByIndex(ElementByPath(WeatherFrom, 'NAM0'), 2), False);
  365. ElementAssign(ElementByIndex(ElementByPath(Weather, 'NAM0'), 9), LowInteger, ElementByIndex(ElementByPath(WeatherFrom, 'NAM0'), 9), False);
  366. SetElementEditValues(Weather, 'DATA\Cloud Speed (Lower)', GetElementEditValues(WeatherFrom, 'DATA\Cloud Speed (Lower)'));
  367. SetElementEditValues(Weather, 'DATA\Cloud Speed (Upper)', GetElementEditValues(WeatherFrom, 'DATA\Cloud Speed (Upper)'));
  368. end;
  369.  
  370. // I'm too lazy to reload new data, just restart the script
  371. MessageDlg('Please restart Weather Editor to see changes', mtInformation, [mbOk], 0);
  372. frm.Close;
  373. end;
  374.  
  375. //============================================================================
  376. // copy weather colors from another weather
  377. procedure btnCopyWeatherColorsClick(Sender: TObject);
  378. var
  379. WeatherFrom: IInterface;
  380. begin
  381. if not CheckEditable(Weather) then
  382. Exit;
  383.  
  384. WeatherFrom := SelectRecord('WTHR', True);
  385. if not Assigned(WeatherFrom) or Equals(Weather, WeatherFrom) then
  386. Exit;
  387.  
  388. CopyElement(WeatherFrom, Weather, 'NAM0');
  389.  
  390. MessageDlg('Please restart Weather Editor to see changes', mtInformation, [mbOk], 0);
  391. frm.Close;
  392. end;
  393.  
  394. //============================================================================
  395. // copy Directional Ambient Lighting Colors from another weather
  396. procedure btnCopyLightingColorsClick(Sender: TObject);
  397. var
  398. WeatherFrom: IInterface;
  399. begin
  400. if not CheckEditable(Weather) then
  401. Exit;
  402.  
  403. WeatherFrom := SelectRecord('WTHR', True);
  404. if not Assigned(WeatherFrom) or Equals(Weather, WeatherFrom) then
  405. Exit;
  406.  
  407. CopyElement(WeatherFrom, Weather, 'Directional Ambient Lighting Colors');
  408.  
  409. MessageDlg('Please restart Weather Editor to see changes', mtInformation, [mbOk], 0);
  410. frm.Close;
  411. end;
  412.  
  413. //============================================================================
  414. // Label control helper
  415. function CreateLabel(Parent: TControl; Left, Top: Integer; LabelText: string): TLabel;
  416. begin
  417. Result := TLabel.Create(frm);
  418. Result.Parent := Parent;
  419. Result.Left := Left;
  420. Result.Top := Top;
  421. Result.Caption := LabelText;
  422. end;
  423.  
  424. //============================================================================
  425. // Color editor control helper (based on TPanel)
  426. function CreateColorEditor(Parent: TControl; Left, Top: Integer; elColor: IInterface): TPanel;
  427. begin
  428. Result := TPanel.Create(frm);
  429. Result.Parent := Parent;
  430. Result.Left := Left;
  431. Result.Top := Top;
  432. Result.Width := iColorEditorWidth;
  433. Result.Height := iColorEditorHeight;
  434. Result.BevelOuter := bvNone;
  435. Result.Cursor := -21; //crHandPoint;
  436. // list of color elements in plugin
  437. lstCEDElement.Add(elColor);
  438. Result.Tag := Pred(lstCEDElement.Count);
  439. Result.ParentBackground := False;
  440. Result.Color := ColorElementToColor(elColor);
  441. Result.OnClick := ColorEditorClick;
  442. // list of color editors, indexes are the same for editors and elements
  443. lstCED.Add(Result);
  444. end;
  445.  
  446. //============================================================================
  447. procedure EditorUI;
  448. var
  449. i, j: integer;
  450. s: string;
  451. DisabledClouds: LongWord;
  452. lbl: TLabel;
  453. sbx: TScrollBox;
  454. e1, e2: IInterface;
  455. begin
  456. frm := TForm.Create(nil);
  457. try
  458. frm.Caption := Format('%s \ %s - %s Weather Editor', [GetFileName(Weather), Name(Weather), wbGameName]);
  459. frm.Width := 860;
  460. frm.Height := 650;
  461. frm.Position := poScreenCenter;
  462. frm.Color := clWindow;
  463. frm.KeyPreview := True;
  464. frm.OnKeyDown := FormKeyDown;
  465.  
  466. pgcWeather := TPageControl.Create(frm);
  467. pgcWeather.Parent := frm;
  468. pgcWeather.Align := alClient;
  469.  
  470. // CLOUDS TABSHEET
  471. tsClouds := TTabSheet.Create(pgcWeather);
  472. tsClouds.PageControl := pgcWeather;
  473. tsClouds.Caption := 'Clouds';
  474.  
  475. lbCloudLayers := TCheckListBox.Create(frm);
  476. lbCloudLayers.Parent := tsClouds;
  477. lbCloudLayers.Align := alLeft;
  478. lbCloudLayers.Width := 100;
  479. lbCloudLayers.OnClick := lbCloudLayersClick;
  480. lbCloudLayers.OnClickCheck := lbCloudLayersClickCheck;
  481. DisabledClouds := GetElementNativeValues(Weather, 'NAM1');
  482. for i := 0 to Pred(CountCloudLayers) do begin
  483. // Oblivion has only 2 predefined cloud names
  484. if wbGameMode = gmTES4 then begin
  485. if i = 0 then s := 'Lower'
  486. else if i = 1 then s := 'Upper';
  487. end else
  488. s := Format('Layer %d', [i]);
  489. lbCloudLayers.Items.Add(s);
  490. if DisabledClouds and (1 shl i) = 0 then
  491. lbCloudLayers.Checked[i] := True;
  492. end;
  493.  
  494. pnlCloud := TPanel.Create(frm);
  495. pnlCloud.Parent := tsClouds;
  496. pnlCloud.Align := alClient;
  497. pnlCloud.BevelOuter := bvNone;
  498.  
  499. pnlCloudEdit := TPanel.Create(frm);
  500. pnlCloudEdit.Parent := pnlCloud;
  501. pnlCloudEdit.Align := alTop;
  502. pnlCloudEdit.BevelOuter := bvNone;
  503. pnlCloudEdit.Height := 230;
  504.  
  505. imgCloud := TImage.Create(frm);
  506. imgCloud.Parent := pnlCloud;
  507. imgCloud.Align := alClient;
  508. imgCloud.Proportional := True;
  509. imgCloud.Center := True;
  510.  
  511. CreateLabel(pnlCloudEdit, 12, 12, 'Texture');
  512. cmbCloudTexture := TComboBox.Create(frm);
  513. cmbCloudTexture.Parent := pnlCloudEdit;
  514. cmbCloudTexture.Top := 8;
  515. cmbCloudTexture.Left := 70;
  516. cmbCloudTexture.Width := 500;
  517. cmbCloudTexture.DropDownCount := 30;
  518. cmbCloudTexture.Items.Assign(slCloudTextures);
  519. cmbCloudTexture.OnSelect := btnShowCloudTextureClick; // show texture when selecting from drop down list
  520.  
  521. btnShowCloudTexture := TButton.Create(frm);
  522. btnShowCloudTexture.Parent := pnlCloudEdit;
  523. btnShowCloudTexture.Left := cmbCloudTexture.Left + cmbCloudTexture.Width + 12;
  524. btnShowCloudTexture.Top := cmbCloudTexture.Top - 2;
  525. btnShowCloudTexture.Width := 100;
  526. btnShowCloudTexture.Caption := 'Show Texture';
  527. btnShowCloudTexture.OnClick := btnShowCloudTextureClick;
  528.  
  529. edCloudXSpeed := TLabeledEdit.Create(frm);
  530. edCloudXSpeed.Parent := pnlCloudEdit;
  531. edCloudXSpeed.LabelPosition := lpLeft;
  532. edCloudXSpeed.EditLabel.Caption := 'X Speed';
  533. edCloudXSpeed.Left := 70; edCloudXSpeed.Top := 40; edCloudXSpeed.Width := 70;
  534.  
  535. // only one speed value per cloud layer and no alpha in games before Skyrim
  536. if (wbGameMode = gmTES4) or (wbGameMode = gmFO3) or (wbGameMode = gmFNV) then
  537. edCloudXSpeed.EditLabel.Caption := 'Speed'
  538. else begin
  539. edCloudYSpeed := TLabeledEdit.Create(frm);
  540. edCloudYSpeed.Parent := pnlCloudEdit;
  541. edCloudYSpeed.LabelPosition := lpLeft;
  542. edCloudYSpeed.EditLabel.Caption := 'Y Speed';
  543. edCloudYSpeed.Left := 200; edCloudYSpeed.Top := 40; edCloudYSpeed.Width := 70;
  544.  
  545. edCloudAlpha1 := TLabeledEdit.Create(frm); edCloudAlpha1.Parent := pnlCloudEdit;
  546. edCloudAlpha1.LabelPosition := lpLeft; edCloudAlpha1.EditLabel.Caption := 'Alpha';
  547. edCloudAlpha1.Left := 62 + 0*iColorEditorWidth; edCloudAlpha1.Top := 155; edCloudAlpha1.Width := iColorEditorWidth - 50;
  548. edCloudAlpha2 := TLabeledEdit.Create(frm); edCloudAlpha2.Parent := pnlCloudEdit;
  549. edCloudAlpha2.LabelPosition := lpLeft; edCloudAlpha2.EditLabel.Caption := 'Alpha';
  550. edCloudAlpha2.Left := 62 + 1*iColorEditorWidth; edCloudAlpha2.Top := 155; edCloudAlpha2.Width := iColorEditorWidth - 50;
  551. edCloudAlpha3 := TLabeledEdit.Create(frm); edCloudAlpha3.Parent := pnlCloudEdit;
  552. edCloudAlpha3.LabelPosition := lpLeft; edCloudAlpha3.EditLabel.Caption := 'Alpha';
  553. edCloudAlpha3.Left := 62 + 2*iColorEditorWidth; edCloudAlpha3.Top := 155; edCloudAlpha3.Width := iColorEditorWidth - 50;
  554. edCloudAlpha4 := TLabeledEdit.Create(frm); edCloudAlpha4.Parent := pnlCloudEdit;
  555. edCloudAlpha4.LabelPosition := lpLeft; edCloudAlpha4.EditLabel.Caption := 'Alpha';
  556. edCloudAlpha4.Left := 62 + 3*iColorEditorWidth; edCloudAlpha4.Top := 155; edCloudAlpha4.Width := iColorEditorWidth - 50;
  557. end;
  558.  
  559. for i := 0 to Pred(CountTimes) do begin
  560. lbl := CreateLabel(pnlCloudEdit, 12 + i*iColorEditorWidth, 80, slColorTimes[i]);
  561. lbl.AutoSize := False;
  562. lbl.Width := iColorEditorWidth;
  563. lbl.Alignment := taCenter;
  564. CreateColorEditor(pnlCloudEdit, 12 + i*iColorEditorWidth, 100, nil);
  565. end;
  566.  
  567. btnApplyCloud := TButton.Create(frm);
  568. btnApplyCloud.Parent := pnlCloudEdit;
  569. btnApplyCloud.Left := btnShowCloudTexture.Left;
  570. btnApplyCloud.Top := 190;
  571. btnApplyCloud.Width := 100;
  572. btnApplyCloud.Caption := 'Apply Changes';
  573. btnApplyCloud.OnClick := btnApplyCloudClick;
  574.  
  575. // default selected layer
  576. lbCloudLayers.ItemIndex := 0;
  577. lbCloudLayersClick(nil);
  578.  
  579. // WEATHER COLORS TABSHEET
  580. tsWeatherColors := TTabSheet.Create(pgcWeather);
  581. tsWeatherColors.PageControl := pgcWeather;
  582. tsWeatherColors.Caption := 'Weather Colors';
  583.  
  584. sbx := TScrollBox.Create(frm);
  585. sbx.Parent := tsWeatherColors;
  586. sbx.Align := alClient;
  587. sbx.BorderStyle := bsNone;
  588. sbx.HorzScrollBar.Tracking := True;
  589. sbx.VertScrollBar.Tracking := True;
  590.  
  591. e1 := ElementByPath(Weather, 'NAM0');
  592. for i := 0 to Pred(ElementCount(e1)) do begin
  593. // skip cloud colors that are stored together with weather colors in Oblivion
  594. if (wbGameMode = gmTES4) and ((i = 2) or (i = 9)) then
  595. Continue;
  596. e2 := ElementByIndex(e1, i);
  597. for j := 0 to Pred(CountTimes) do begin
  598. if i = 0 then begin
  599. lbl := CreateLabel(sbx, 120 + j*iColorEditorWidth, 8, slColorTimes[j]);
  600. lbl.AutoSize := False;
  601. lbl.Width := iColorEditorWidth;
  602. lbl.Alignment := taCenter;
  603. end;
  604. if j = 0 then begin
  605. lbl := CreateLabel(sbx, 12, 28 + Succ(i)*iColorEditorHeight - iColorEditorHeight div 2 - 5, Name(e2));
  606. lbl.AutoSize := False;
  607. lbl.Width := 100;
  608. lbl.Alignment := taRightJustify;
  609. end;
  610. CreateColorEditor(sbx, 120 + j*iColorEditorWidth, 28 + i*iColorEditorHeight, ElementByIndex(e2, j));
  611. Inc(CountWeatherColors);
  612. end;
  613. end;
  614.  
  615. btnApplyWeatherColors := TButton.Create(frm);
  616. btnApplyWeatherColors.Parent := sbx;
  617. btnApplyWeatherColors.Width := 100;
  618. btnApplyWeatherColors.Left := 120 + CountTimes*iColorEditorWidth - btnApplyWeatherColors.Width;
  619. btnApplyWeatherColors.Top := 40 + Succ(i)*iColorEditorHeight;
  620. btnApplyWeatherColors.Caption := 'Apply Changes';
  621. btnApplyWeatherColors.OnClick := btnApplyWeatherColorsClick;
  622.  
  623. // LIGHTING COLORS TABSHEET
  624. if wbGameMode = gmTES5 then begin
  625. tsLightingColors := TTabSheet.Create(pgcWeather);
  626. tsLightingColors.PageControl := pgcWeather;
  627. tsLightingColors.Caption := 'Directional Ambient Lighting Colors';
  628.  
  629. sbx := TScrollBox.Create(frm);
  630. sbx.Parent := tsLightingColors;
  631. sbx.Align := alClient;
  632. sbx.BorderStyle := bsNone;
  633. sbx.HorzScrollBar.Tracking := True;
  634. sbx.VertScrollBar.Tracking := True;
  635.  
  636. e1 := ElementByName(Weather, 'Directional Ambient Lighting Colors');
  637. for i := 0 to Pred(CountTimes) do begin
  638. e2 := ElementByPath(ElementByIndex(e1, i), 'Directional Ambient\Colors');
  639. for j := 0 to Pred(ElementCount(e2)) do begin
  640. if j = 0 then begin
  641. lbl := CreateLabel(sbx, 120 + i*iColorEditorWidth, 8, slColorTimes[i]);
  642. lbl.AutoSize := False;
  643. lbl.Width := iColorEditorWidth;
  644. lbl.Alignment := taCenter;
  645. end;
  646. if i = 0 then begin
  647. lbl := CreateLabel(sbx, 12, 28 + Succ(j)*iColorEditorHeight - iColorEditorHeight div 2 - 5, Name(ElementByIndex(e2, j)));
  648. lbl.AutoSize := False;
  649. lbl.Width := 100;
  650. lbl.Alignment := taRightJustify;
  651. end;
  652. CreateColorEditor(sbx, 120 + i*iColorEditorWidth, 28 + j*iColorEditorHeight, ElementByIndex(e2, j));
  653. Inc(CountLightingColors);
  654. end;
  655. end;
  656.  
  657. btnApplyLightingColors := TButton.Create(frm);
  658. btnApplyLightingColors.Parent := sbx;
  659. btnApplyLightingColors.Width := 100;
  660. btnApplyLightingColors.Left := 120 + CountTimes*iColorEditorWidth - btnApplyLightingColors.Width;
  661. btnApplyLightingColors.Top := 40 + Succ(j)*iColorEditorHeight;
  662. btnApplyLightingColors.Caption := 'Apply Changes';
  663. btnApplyLightingColors.OnClick := btnApplyLightingColorsClick;
  664. end;
  665.  
  666. // TOOLS TABSHEET
  667. tsTools := TTabSheet.Create(pgcWeather);
  668. tsTools.PageControl := pgcWeather;
  669. tsTools.Caption := 'Tools';
  670.  
  671. btnCopyClouds := TButton.Create(frm);
  672. btnCopyClouds.Parent := tsTools;
  673. btnCopyClouds.Left := 16; btnCopyClouds.Top := 16; btnCopyClouds.Width := 200;
  674. btnCopyClouds.Caption := 'Copy clouds from';
  675. btnCopyClouds.OnClick := btnCopyCloudsClick;
  676.  
  677. btnCopyWeatherColors := TButton.Create(frm);
  678. btnCopyWeatherColors.Parent := tsTools;
  679. btnCopyWeatherColors.Left := 16; btnCopyWeatherColors.Top := 46; btnCopyWeatherColors.Width := 200;
  680. btnCopyWeatherColors.Caption := 'Copy weather colors from';
  681. btnCopyWeatherColors.OnClick := btnCopyWeatherColorsClick;
  682.  
  683. if wbGameMode = gmTES5 then begin
  684. btnCopyLightingColors := TButton.Create(frm);
  685. btnCopyLightingColors.Parent := tsTools;
  686. btnCopyLightingColors.Left := 16; btnCopyLightingColors.Top := 76; btnCopyLightingColors.Width := 200;
  687. btnCopyLightingColors.Caption := 'Copy lighting colors from';
  688. btnCopyLightingColors.OnClick := btnCopyLightingColorsClick;
  689. end;
  690.  
  691.  
  692. frm.ShowModal;
  693. finally
  694. frm.Free;
  695. end;
  696. end;
  697.  
  698. //============================================================================
  699. // Weather Editor
  700. procedure DoWeatherEditor(e: IInterface);
  701. var
  702. slContainers, slAssets, slFiltered: TStringList;
  703. i: integer;
  704. begin
  705. Weather := e;
  706. slCloudTextures := TwbFastStringList.Create;
  707. slCloudTextures.Sorted := True;
  708. slCloudTextures.Duplicates := dupIgnore;
  709. slCloudSignatures := TStringList.Create;
  710. slCloudSignatures.Delimiter := ',';
  711. slCloudSignatures.DelimitedText := sCloudLayerSignatures;
  712. CountCloudLayers := slCloudSignatures.Count;
  713. slColorTimes := TStringList.Create;
  714. slColorTimes.Delimiter := ',';
  715. slColorTimes.DelimitedText := sColorTimes;
  716. CountTimes := slColorTimes.Count;
  717. lstCED := TList.Create;
  718. lstCEDElement := TList.Create;
  719.  
  720. // list of available cloud textures
  721. slContainers := TStringList.Create;
  722. slAssets := TwbFastStringList.Create;
  723. try
  724. ResourceContainerList(slContainers);
  725. for i := 0 to Pred(slContainers.Count) do begin
  726. ResourceList(slContainers[i], slAssets);
  727. wbFilterStrings(slAssets, slCloudTextures, sCloudTexturesLocation);
  728. end;
  729. finally
  730. slAssets.Free;
  731. slContainers.Free;
  732. end;
  733. // delete "textures\" part
  734. slCloudTextures.Sorted := False;
  735. for i := 0 to Pred(slCloudTextures.Count) do
  736. slCloudTextures[i] := Copy(slCloudTextures[i], 10, Length(slCloudTextures[i]));
  737. slCloudTextures.Sorted := True;
  738.  
  739. EditorUI;
  740.  
  741. slCloudTextures.Free;
  742. slCloudSignatures.Free;
  743. slColorTimes.Free;
  744. lstCED.Free;
  745. lstCEDElement.Free;
  746. end;
  747.  
  748. //============================================================================
  749. function Initialize: integer;
  750. begin
  751. // game specific settings
  752. if wbGameMode = gmTES5 then begin
  753. sCloudLayerSignatures := '00TX,10TX,20TX,30TX,40TX,50TX,60TX,70TX,80TX,90TX,:0TX,;0TX,<0TX,=0TX,>0TX,?0TX,@0TX,A0TX,B0TX,C0TX,D0TX,E0TX,F0TX,G0TX,H0TX,I0TX,J0TX,K0TX,L0TX';
  754. end
  755. else if (wbGameMode = gmFO3) or (wbGameMode = gmFNV) then begin
  756. sCloudLayerSignatures := 'DNAM,CNAM,ANAM,BNAM';
  757. end
  758. else if wbGameMode = gmTES4 then begin
  759. sCloudLayerSignatures := 'CNAM,DNAM';
  760. end
  761. else begin
  762. MessageDlg(Format('Weather Editor for %s is not supported', [wbGameName]), mtInformation, [mbOk], 0)
  763. Result := 1;
  764. Exit;
  765. end;
  766. // all games have 4 time spans for colors
  767. sColorTimes := 'Sunrise,Day,Sunset,Night';
  768. end;
  769.  
  770. //============================================================================
  771. function Process(e: IInterface): integer;
  772. begin
  773. if Signature(e) <> 'WTHR' then
  774. MessageDlg(Format('The selected record %s is not a weather', [Name(e)]), mtInformation, [mbOk], 0)
  775. else
  776. DoWeatherEditor(e);
  777.  
  778. Result := 1;
  779. end;
  780.  
  781.  
  782. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement