Advertisement
Guest User

Untitled

a guest
Nov 19th, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.72 KB | None | 0 0
  1. {
  2. New script template, only shows processed records
  3. Assigning any nonzero value to Result will terminate script
  4. }
  5. unit RemoveDefaultProperties;
  6. var
  7. // couldn't figure out how to do it with just one...
  8. configKeys: TStringList;
  9. configValues: TStringList;
  10.  
  11. function HasConfig(key: String) : boolean;
  12. begin
  13. Result := (configKeys.indexOf(key) >= 0);
  14. end;
  15.  
  16. function GetConfig(key: String) : String;
  17. var
  18. i: integer;
  19. begin
  20. i := configKeys.indexOf(key);
  21.  
  22. if i >= 0 then begin
  23. Result := configValues[i];
  24. end else begin
  25. Result := '';
  26. end;
  27. end;
  28.  
  29.  
  30. procedure SetConfig(key: String; val: String);
  31. var
  32. i: integer;
  33. begin
  34. i := configKeys.indexOf(key);
  35.  
  36. if i < 0 then begin
  37. i := configKeys.add(key);
  38. configValues.insert(i, val);
  39. exit;
  40. end else begin
  41. configValues[i] := val;
  42. end;
  43. end;
  44.  
  45. // Called before processing
  46. // You can remove it if script doesn't require initialization code
  47. function Initialize: integer;
  48. var
  49. i, j, spacePos, curIndex: integer;
  50. curLine, testStr, key, val: string;
  51.  
  52. fileLines : TStringList;
  53. begin
  54. configKeys := TStringList.create;
  55. configValues := TStringList.create;
  56.  
  57. fileLines := TStringList.Create;
  58. fileLines.loadFromFile(ProgramPath + 'Edit Scripts\default-value-config.txt');
  59.  
  60. for i:=0 to fileLines.count-1 do begin
  61. curLine := trim(fileLines[i]);
  62. if (length(curLine) > 0) then begin
  63.  
  64. if (curLine[1] <> '#') then begin
  65. spacePos := -1;
  66. for j:=1 to length(curLine) do begin
  67. if curLine[j] = '=' then begin
  68. spacePos := j;
  69. break;
  70. end;
  71. //AddMessage(curLine[j]);
  72. end;
  73. if spacePos <> -1 then begin
  74. key := trim(copy(curLine, 0, spacePos-1));
  75. val := trim(copy(curLine, spacePos+1, length(curLine)));
  76. if (key <> '') then begin
  77. SetConfig(key, val);
  78. end;
  79. end else begin
  80. key := curLine;
  81. val := '';
  82. SetConfig(key, val);
  83. end;
  84. end;
  85. end;
  86. end;
  87.  
  88. Result := 0;
  89. end;
  90.  
  91. procedure dumpElement(e: IInterface; prefix: String);
  92. var
  93. i: Integer;
  94. child: IInterface;
  95. begin
  96. for i := 0 to ElementCount(e)-1 do begin
  97. child := ElementByIndex(e, i);
  98. AddMessage(prefix+DisplayName(child)+'='+GetEditValue(child));
  99. dumpElement(child, prefix+' ');
  100. end
  101. end;
  102.  
  103. procedure dumpElem(e: IInterface);
  104. begin
  105. dumpElement(e, '');
  106. end;
  107.  
  108. function startsWith(needle: String; haystack: String): boolean;
  109. var
  110. len: Integer;
  111. cmp: String;
  112. begin
  113. if needle = haystack then begin
  114. Result := true;
  115. exit;
  116. end;
  117.  
  118. len := length(needle);
  119.  
  120. if len > length(haystack) then begin
  121. Result := false;
  122. exit;
  123. end;
  124.  
  125. cmp := copy(haystack, 0, len);
  126.  
  127. Result := (cmp = needle);
  128. end;
  129.  
  130. function getObjectLinksTo(entry: IInterface): IInterface;
  131. var
  132. value: IInterface;
  133. begin
  134. value := ElementByPath(entry, 'Value\Object Union\Object v2\FormID');
  135.  
  136. Result := nil;
  137.  
  138. if(not assigned(value)) then begin
  139. exit;
  140. end;
  141.  
  142. Result := LinksTo(value);
  143. end;
  144.  
  145. function BoolToStr(str: string): boolean;
  146. begin
  147. Result := (str = 'True');
  148. end;
  149.  
  150. function checkPropValue(propType: string; expectedValue: string; prop: IInterface): boolean;
  151. var
  152. valueString: string;
  153. valueBool: boolean;
  154. valueInt: integer;
  155. valueFloat: float;
  156. begin
  157.  
  158. Result := false;
  159. valueString := GetElementEditValues(prop, propType);
  160.  
  161. // AddMessage('Comparing: '+expectedValue+'='+valueString);
  162.  
  163. if (propType = 'Int32') then begin
  164. //valueInt := ParseInt(expectedValue);
  165. Result := (StrToInt(expectedValue) = StrToInt(valueString));
  166. exit;
  167. end;
  168.  
  169. if (propType = 'Float') then begin
  170. // maybe add a comparison function?
  171. Result := (StrToFloat(expectedValue) = StrToFloat(valueString));
  172. exit;
  173. end;
  174.  
  175. if (propType = 'Bool') then begin
  176. Result := (BoolToStr(expectedValue) = BoolToStr(valueString));
  177. exit;
  178. end;
  179.  
  180. Result := (expectedValue = valueString);
  181.  
  182. end;
  183.  
  184. function checkObjectEmpty(prop: IInterface): boolean;
  185. var
  186. valueRecord : IInterface;
  187. begin
  188. Result := false;
  189. valueRecord := getObjectLinksTo(prop);
  190. if(not assigned(valueRecord)) then begin
  191. // this means: the property for this object is set, but it should be empty
  192. AddMessage('Found a missing object!');
  193. Result := true;
  194. end;
  195. end;
  196.  
  197. function checkDefaultEmptyValue(propType: string; prop: IInterface): boolean;
  198. var
  199. expectedString: string;
  200. begin
  201. expectedString := '';
  202. Result := false;
  203.  
  204. if(propType = 'Object') then begin
  205. Result := checkObjectEmpty(prop);
  206. exit;
  207. end;
  208.  
  209. if (propType = 'Int32') or (propType = 'Float') then begin
  210. Result := checkPropValue(propType, '0', prop);
  211. exit;
  212. end;
  213.  
  214. if (propType = 'Bool') then begin
  215. Result := checkPropValue(propType, 'False', prop);
  216. exit;
  217. end;
  218.  
  219. Result := checkPropValue(propType, '', prop);
  220.  
  221. end;
  222.  
  223. function processScalarEntry(path: string; nameKey: string; entry: IInterface): boolean;
  224. var
  225. propType: string;
  226. name: string;
  227. valueString: string;
  228. valueRecord: IInterface;
  229.  
  230. configIndex: integer;
  231. expectedValue: string;
  232. begin
  233. Result := false;
  234.  
  235. name := GetElementEditValues(entry, nameKey);
  236. propType := GetElementEditValues(entry, 'Type');
  237.  
  238. // AddMessage('SCALAR: Path: '+path+', Name: '+name);
  239.  
  240.  
  241.  
  242. // important part
  243. configIndex := configKeys.indexOf(path+'.'+nameKey);
  244. // AddMessage('Got key index: '+IntToStr(configIndex));
  245. if(configIndex < 0) then begin
  246. // no explicit mention exists, but maybe the parent exists?
  247. configIndex := configKeys.indexOf(path);
  248. if(configIndex < 0) then begin
  249. // nope. disregard.
  250. exit;
  251. end;
  252.  
  253. Result := checkDefaultEmptyValue(propType, entry);
  254. exit;
  255. end;
  256.  
  257. // here, we might have a value
  258. // for objects, check defaultemptyvalue right away
  259. if(propType = 'Object') then begin
  260. Result := checkDefaultEmptyValue(propType, entry);
  261. exit;
  262. end;
  263. // for everything else, check if we have an explicit default value
  264. expectedValue := configValues[configIndex];
  265. if(expectedValue = '') then begin
  266. { // this is somewhat shitty because of the way I made it, but well... }
  267. { if(propType = 'String') then begin }
  268. { Result := checkPropValue(propType, entry); }
  269. { exit; }
  270. { end; }
  271.  
  272. // otherwise, default
  273. Result := checkDefaultEmptyValue(propType, entry);
  274. exit;
  275. end;
  276.  
  277. // finally, compare the value from the config
  278. Result := checkPropValue(propType, expectedValue, entry);
  279.  
  280. // valueString := GetElementEditValues(entry, propType);
  281.  
  282. // AddMessage('Scalar; '+nameKey+' ('+propType+') = '+valueString);
  283.  
  284.  
  285.  
  286.  
  287. end;
  288.  
  289. procedure processStruct(path: string; struct: IInterface);
  290. var
  291. i: integer;
  292. curMember, val: IInterface;
  293. isEmpty: boolean;
  294. begin
  295. val := struct;//ElementByName(struct, 'Value\Array of Struct');
  296.  
  297. //for i := 0 to ElementCount(val)-1 do begin
  298. i := 0;
  299. while (i < ElementCount(val)) do begin
  300. curMember := ElementByIndex(val, i);
  301.  
  302. isEmpty := processScalarEntry(path, 'memberName', curMember);
  303. if(isEmpty) then begin
  304. // try erasing it
  305. AddMessage('ERASING: '+path+'['+IntToStr(i)+'].'+GetElementEditValues(curMember, 'memberName'));
  306. RemoveElement(val, i);
  307. end else begin
  308. i := i + 1;
  309. end;
  310. end;
  311. end;
  312.  
  313. procedure processArray(path: string; arr: IInterface);
  314. var
  315. propType, arrayType: string;
  316. val, curMember: IInterface;
  317. i: integer;
  318. begin
  319. propType :=GetElementEditValues(arr, 'Type');
  320. arrayType := copy(propType, 10, 99);
  321.  
  322. // AddMessage('This is an array of: '+arrayType);
  323. val := ElementByName(arr, 'Value');
  324. if(not assigned(val)) then begin
  325. exit;
  326. end;
  327.  
  328. val := ElementByName(val, propType);
  329.  
  330. for i := 0 to ElementCount(val)-1 do begin
  331. curMember := ElementByIndex(val, i);
  332. // dumpElem(val);
  333.  
  334. if(arrayType = 'Struct') then begin
  335. processStruct(path, curMember); // don't consider the array be part of the path
  336. end;
  337. end;
  338.  
  339.  
  340. end;
  341.  
  342. procedure processProperty(path: string; prop: IInterface);
  343. var
  344. propName, propType, subPath: string;
  345. isEmpty: boolean;
  346. begin
  347. propName := GetElementEditValues(prop, 'propertyName');
  348. propType := GetElementEditValues(prop, 'Type');
  349.  
  350. subPath := path+'.'+propName;
  351.  
  352. if(startsWith('Array of', propType)) then begin
  353. processArray(subPath, prop);
  354. end else if(propType = 'Struct') then begin
  355. processStruct(subPath, prop);
  356. end else begin
  357. isEmpty := processScalarEntry(path, 'propertyName', prop);
  358. if(isEmpty) then begin
  359. AddMessage('ERASING: '+path+'.'+GetElementEditValues(prop, 'propertyName'));
  360. RemoveElement(val, prop);
  361. end;
  362. end;
  363. end;
  364.  
  365.  
  366. procedure processScript(script: IInterface);
  367. var
  368. properties, prop: IInterface;
  369. i: integer;
  370. scriptName : string;
  371. begin
  372. scriptName := GetElementEditValues(script, 'scriptName');
  373. // AddMessage('script: '+scriptName);
  374. properties := ElementByName(script, 'Properties');
  375.  
  376. for i := 0 to ElementCount(properties)-1 do begin
  377. prop := ElementByIndex(properties, i);
  378. //dumpElem(prop);
  379. processProperty(scriptName, prop);
  380. end;
  381. end;
  382.  
  383. // called for every record selected in xEdit
  384. function Process(e: IInterface): integer;
  385. var
  386. scriptRoot, scripts, curScript: IInterface;
  387. i: integer;
  388. begin
  389. Result := 0;
  390.  
  391. scriptRoot := ElementByName(e, 'VMAD - Virtual Machine Adapter');
  392.  
  393. if(not assigned(scriptRoot)) then begin
  394. exit;
  395. end;
  396. AddMessage('Checking '+EditorID(e));
  397.  
  398. scripts := ElementByName(scriptRoot, 'Scripts');
  399.  
  400. for i := 0 to ElementCount(scripts)-1 do begin
  401. curScript := ElementByIndex(scripts, i);
  402.  
  403. BeginUpdate(curScript);
  404. try
  405. processScript(curScript);
  406. finally
  407. EndUpdate(curScript);
  408. end;
  409.  
  410. end;
  411.  
  412. // comment this out if you don't want those messages
  413.  
  414. // processing code goes here
  415.  
  416. end;
  417.  
  418. // Called after processing
  419. // You can remove it if script doesn't require finalization code
  420. function Finalize: integer;
  421. begin
  422. Result := 0;
  423. end;
  424.  
  425. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement