ToolBase.cs 81 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151
  1. /*
  2. Copyright (c) 2021 Omar Duarte
  3. Unauthorized copying of this file, via any medium is strictly prohibited.
  4. Writen by Omar Duarte, 2021.
  5. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  6. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  7. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  8. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  9. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  10. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  11. THE SOFTWARE.
  12. */
  13. using System.Linq;
  14. using UnityEngine;
  15. namespace PluginMaster
  16. {
  17. #region MANAGER
  18. public static class ToolProfile
  19. {
  20. public const string DEFAULT = "Default";
  21. }
  22. public interface IToolManager
  23. {
  24. string selectedProfileName { get; set; }
  25. string[] profileNames { get; }
  26. void SaveProfile();
  27. void SaveProfileAs(string name);
  28. void DeleteProfile();
  29. void Revert();
  30. void FactoryReset();
  31. }
  32. [System.Serializable]
  33. public class ToolManagerBase<TOOL_SETTINGS> : IToolManager, ISerializationCallbackReceiver
  34. where TOOL_SETTINGS : IToolSettings, new()
  35. {
  36. protected static ToolManagerBase<TOOL_SETTINGS> _instance = null;
  37. private static System.Collections.Generic.Dictionary<string, TOOL_SETTINGS> _staticProfiles
  38. = new System.Collections.Generic.Dictionary<string, TOOL_SETTINGS>
  39. { { ToolProfile.DEFAULT, new TOOL_SETTINGS() } };
  40. [SerializeField] private string[] _profileKeys = { ToolProfile.DEFAULT };
  41. [SerializeField] private TOOL_SETTINGS[] _profileValues = { new TOOL_SETTINGS() };
  42. private static string _staticSelectedProfileName = ToolProfile.DEFAULT;
  43. [SerializeField] private string _selectedProfileName = _staticSelectedProfileName;
  44. private static TOOL_SETTINGS _staticUnsavedProfile = new TOOL_SETTINGS();
  45. [SerializeField] private TOOL_SETTINGS _unsavedProfile = _staticUnsavedProfile;
  46. protected ToolManagerBase() { }
  47. public static ToolManagerBase<TOOL_SETTINGS> instance
  48. {
  49. get
  50. {
  51. if (_instance == null) _instance = new ToolManagerBase<TOOL_SETTINGS>();
  52. return _instance;
  53. }
  54. }
  55. public static TOOL_SETTINGS settings => _staticUnsavedProfile;
  56. private void UpdateUnsaved()
  57. {
  58. var tool = ToolManager.GetToolFromSettings(settings);
  59. if (ToolManager.tool == ToolManager.PaintTool.NONE || tool != ToolManager.tool) return;
  60. if (!_staticProfiles.ContainsKey(_staticSelectedProfileName))
  61. _staticSelectedProfileName = ToolProfile.DEFAULT;
  62. _staticUnsavedProfile.Copy(_staticProfiles[_staticSelectedProfileName]);
  63. }
  64. public string selectedProfileName
  65. {
  66. get => _staticSelectedProfileName;
  67. set
  68. {
  69. if (_staticSelectedProfileName == value) return;
  70. _staticSelectedProfileName = value;
  71. _selectedProfileName = value;
  72. UpdateUnsaved();
  73. _staticUnsavedProfile.DataChanged();
  74. }
  75. }
  76. public string[] profileNames => _staticProfiles.Keys.ToArray();
  77. public void SaveProfile()
  78. {
  79. _staticProfiles[_staticSelectedProfileName].Copy(_staticUnsavedProfile);
  80. PWBCore.staticData.SaveAndUpdateVersion();
  81. }
  82. public void SaveProfileAs(string name)
  83. {
  84. if (!_staticProfiles.ContainsKey(name))
  85. {
  86. var newProfile = new TOOL_SETTINGS();
  87. newProfile.Copy(_unsavedProfile);
  88. _staticProfiles.Add(name, newProfile);
  89. }
  90. else _staticProfiles[name].Copy(_staticUnsavedProfile);
  91. _staticSelectedProfileName = name;
  92. UpdateUnsaved();
  93. _staticUnsavedProfile.DataChanged();
  94. PWBCore.staticData.SaveAndUpdateVersion();
  95. }
  96. public void DeleteProfile()
  97. {
  98. if (_staticSelectedProfileName == ToolProfile.DEFAULT) return;
  99. _staticProfiles.Remove(_staticSelectedProfileName);
  100. _staticSelectedProfileName = ToolProfile.DEFAULT;
  101. _staticUnsavedProfile.Copy(_staticProfiles[ToolProfile.DEFAULT]);
  102. _staticUnsavedProfile.DataChanged();
  103. PWBCore.staticData.SaveAndUpdateVersion();
  104. }
  105. public void Revert()
  106. {
  107. UpdateUnsaved();
  108. _staticUnsavedProfile.DataChanged();
  109. PWBCore.staticData.SaveAndUpdateVersion();
  110. }
  111. public void FactoryReset()
  112. {
  113. _staticUnsavedProfile = new TOOL_SETTINGS();
  114. _staticUnsavedProfile.DataChanged();
  115. PWBCore.staticData.SaveAndUpdateVersion();
  116. }
  117. public void CopyToolSettings(TOOL_SETTINGS value) => _staticUnsavedProfile.Copy(value);
  118. public virtual void OnBeforeSerialize()
  119. {
  120. _selectedProfileName = _staticSelectedProfileName;
  121. _profileKeys = _staticProfiles.Keys.ToArray();
  122. _profileValues = _staticProfiles.Values.ToArray();
  123. }
  124. public virtual void OnAfterDeserialize()
  125. {
  126. _staticSelectedProfileName = _selectedProfileName;
  127. if (_profileKeys.Length > 1)
  128. {
  129. _staticProfiles.Clear();
  130. for (int i = 0; i < _profileKeys.Length; ++i) _staticProfiles.Add(_profileKeys[i], _profileValues[i]);
  131. }
  132. }
  133. }
  134. public interface IPersistentToolManager
  135. {
  136. bool applyBrushToExisting { get; set; }
  137. IPersistentData[] GetItems();
  138. void ToggleItemsVisibility();
  139. void DeletePersistentItem(long itemId, bool deleteObjects, bool registerUndo = true);
  140. void DeselectAllItems();
  141. IPersistentData Duplicate(long itemId);
  142. string GetToolName();
  143. }
  144. [System.Serializable]
  145. public class PersistentToolManagerBase<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA>
  146. : ToolManagerBase<TOOL_SETTINGS>, IPersistentToolManager
  147. where TOOL_NAME : IToolName, new()
  148. where TOOL_SETTINGS : IToolSettings, new()
  149. where CONTROL_POINT : ControlPoint, new()
  150. where TOOL_DATA : PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT>, new()
  151. where SCENE_DATA : SceneData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA>, new()
  152. {
  153. private static System.Collections.Generic.List<SCENE_DATA> _staticSceneItems = null;
  154. [SerializeField] private System.Collections.Generic.List<SCENE_DATA> _sceneItems = _staticSceneItems;
  155. private static bool _staticShowPreexistingElements = true;
  156. [SerializeField] private bool _showPreexistingElements = _staticShowPreexistingElements;
  157. private static bool _staticApplyBrushToExisting = false;
  158. [SerializeField] private bool _applyBrushToExisting = _staticApplyBrushToExisting;
  159. private static IPersistentData.Visibility _itemsVisibility = IPersistentData.Visibility.SHOW_ALL;
  160. protected PersistentToolManagerBase() { }
  161. public new static PersistentToolManagerBase<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA> instance
  162. {
  163. get
  164. {
  165. if (_instance == null)
  166. _instance = new PersistentToolManagerBase
  167. <TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA>();
  168. return _instance as PersistentToolManagerBase<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA>;
  169. }
  170. }
  171. public void AddPersistentItem(string sceneGUID, TOOL_DATA data)
  172. {
  173. if (_staticSceneItems == null)
  174. _staticSceneItems = new System.Collections.Generic.List<SCENE_DATA>();
  175. var sceneItem = _staticSceneItems.Find(i => i.sceneGUID == sceneGUID);
  176. if (sceneItem == null)
  177. {
  178. sceneItem = new SCENE_DATA();
  179. sceneItem.sceneGUID = sceneGUID;
  180. _staticSceneItems.Add(sceneItem);
  181. }
  182. if (sceneItem.items != null)
  183. {
  184. var item = sceneItem.items.Find(i => i.id == data.id);
  185. if (item != null) return;
  186. }
  187. sceneItem.AddItem(data);
  188. PWBCore.staticData.SaveAndUpdateVersion();
  189. }
  190. public string GetToolName() => (new TOOL_NAME()).value;
  191. public TOOL_DATA[] GetPersistentItems()
  192. {
  193. var items = new System.Collections.Generic.List<TOOL_DATA>();
  194. var openedSceneCount = UnityEditor.SceneManagement.EditorSceneManager.sceneCount;
  195. if (_staticSceneItems != null)
  196. {
  197. for (int i = 0; i < openedSceneCount; ++i)
  198. {
  199. string sceneGUID = UnityEditor.AssetDatabase.AssetPathToGUID
  200. (UnityEditor.SceneManagement.EditorSceneManager.GetSceneAt(i).path);
  201. var data = _staticSceneItems.Find(item => item.sceneGUID == sceneGUID);
  202. if (data == null)
  203. {
  204. _staticSceneItems.Remove(data);
  205. continue;
  206. }
  207. items.AddRange(data.items);
  208. }
  209. }
  210. return items.ToArray();
  211. }
  212. public IPersistentData[] GetItems() => GetPersistentItems();
  213. public void DeselectAllItems()
  214. {
  215. var items = GetItems();
  216. foreach (var item in items)
  217. {
  218. item.isSelected = false;
  219. item.ClearSelection();
  220. }
  221. }
  222. public IPersistentData Duplicate(long itemId)
  223. {
  224. var scenePath = UnityEngine.SceneManagement.SceneManager.GetActiveScene().path;
  225. var sceneGUID = UnityEditor.AssetDatabase.AssetPathToGUID(scenePath);
  226. var sceneItem = _staticSceneItems.Find(i => i.sceneGUID == sceneGUID);
  227. var source = GetItem(itemId);
  228. var clone = new TOOL_DATA();
  229. clone.Duplicate(source);
  230. sceneItem.AddItem(clone);
  231. PWBCore.staticData.SaveAndUpdateVersion();
  232. return clone;
  233. }
  234. public void ToggleItemsVisibility()
  235. {
  236. switch (_itemsVisibility)
  237. {
  238. case IPersistentData.Visibility.SHOW_ALL: _itemsVisibility = IPersistentData.Visibility.SHOW_OBJECTS; break;
  239. case IPersistentData.Visibility.SHOW_OBJECTS: _itemsVisibility = IPersistentData.Visibility.HIDE_ALL; break;
  240. case IPersistentData.Visibility.HIDE_ALL: _itemsVisibility = IPersistentData.Visibility.SHOW_ALL; break;
  241. }
  242. var items = GetItems();
  243. foreach (var item in items) item.visibility = _itemsVisibility;
  244. }
  245. public bool ReplaceObject(GameObject target, GameObject obj)
  246. {
  247. var items = GetPersistentItems();
  248. foreach (var item in items)
  249. if (item.ReplaceObject(target, obj)) return true;
  250. return false;
  251. }
  252. public void RemovePersistentItem(long itemId)
  253. {
  254. foreach (var item in _staticSceneItems) item.RemoveItemData(itemId);
  255. PWBCore.staticData.SaveAndUpdateVersion();
  256. }
  257. public void DeletePersistentItem(long itemId, bool deleteObjects, bool registerUndo = true)
  258. {
  259. if (registerUndo) ToolProperties.RegisterUndo("Delete Item");
  260. var parents = new System.Collections.Generic.HashSet<GameObject>();
  261. foreach (var item in _staticSceneItems)
  262. {
  263. var itemParents = item.GetParents(itemId);
  264. foreach (var parent in itemParents)
  265. if (!parents.Contains(parent)) parents.Add(parent);
  266. item.DeleteItemData(itemId, deleteObjects);
  267. }
  268. foreach (var parent in parents)
  269. {
  270. var components = parent.GetComponentsInChildren<Component>();
  271. if (components.Length == 1)
  272. {
  273. if (registerUndo) UnityEditor.Undo.DestroyObjectImmediate(parent);
  274. else Object.DestroyImmediate(parent);
  275. }
  276. }
  277. PWBCore.staticData.SaveAndUpdateVersion();
  278. }
  279. public TOOL_DATA GetItem(long itemId)
  280. {
  281. var items = GetPersistentItems();
  282. foreach (var item in items)
  283. if (item.id == itemId) return item;
  284. return null;
  285. }
  286. public TOOL_DATA GetItem(string hexItemId)
  287. {
  288. var splittedId = hexItemId.Split('_');
  289. if (splittedId.Length != 2) return null;
  290. var provider = new System.Globalization.CultureInfo("en-US");
  291. if (long.TryParse(splittedId[1], System.Globalization.NumberStyles.AllowHexSpecifier, provider, out long itemId))
  292. return GetItem(itemId);
  293. return null;
  294. }
  295. public bool showPreexistingElements
  296. {
  297. get => _staticShowPreexistingElements;
  298. set
  299. {
  300. if (_staticShowPreexistingElements == value) return;
  301. _staticShowPreexistingElements = value;
  302. _showPreexistingElements = value;
  303. PWBCore.staticData.SaveAndUpdateVersion();
  304. }
  305. }
  306. public bool applyBrushToExisting
  307. {
  308. get => _staticApplyBrushToExisting;
  309. set
  310. {
  311. if (_staticApplyBrushToExisting == value) return;
  312. _staticApplyBrushToExisting = value;
  313. _applyBrushToExisting = value;
  314. PWBCore.staticData.SaveAndUpdateVersion();
  315. }
  316. }
  317. public override void OnBeforeSerialize()
  318. {
  319. base.OnBeforeSerialize();
  320. _sceneItems = _staticSceneItems;
  321. _showPreexistingElements = _staticShowPreexistingElements;
  322. _applyBrushToExisting = _staticApplyBrushToExisting;
  323. }
  324. public override void OnAfterDeserialize()
  325. {
  326. base.OnAfterDeserialize();
  327. _staticSceneItems = _sceneItems;
  328. _staticShowPreexistingElements = _showPreexistingElements;
  329. _staticApplyBrushToExisting = _applyBrushToExisting;
  330. }
  331. }
  332. #endregion
  333. #region SETTINGS
  334. public interface IToolSettings
  335. {
  336. void DataChanged();
  337. void Copy(IToolSettings other);
  338. }
  339. public static class TilesUtils
  340. {
  341. public enum SizeType
  342. {
  343. SMALLEST_OBJECT,
  344. BIGGEST_OBJECT,
  345. CUSTOM
  346. }
  347. public static Vector3 GetCellSize(SizeType cellSizeType, BrushSettings brush,
  348. AxesUtils.SignedAxis upwardAxis, AxesUtils.SignedAxis forwardAxis,
  349. Vector3 DefaultValue, bool tangentSpace, int quarterTurns)
  350. {
  351. if (cellSizeType == SizeType.CUSTOM) return DefaultValue;
  352. if (brush == null) return DefaultValue;
  353. var cellSize = Vector3.one * (cellSizeType == SizeType.SMALLEST_OBJECT
  354. ? float.MaxValue : float.MinValue);
  355. if (ToolManager.editMode && PWBIO.selectedPersistentTilingData != null)
  356. {
  357. var prefabs = new System.Collections.Generic.HashSet<GameObject>();
  358. var objSet = PWBIO.selectedPersistentTilingData.objectSet;
  359. var scaleMultiplier = cellSizeType == SizeType.SMALLEST_OBJECT
  360. ? brush.minScaleMultiplier : brush.maxScaleMultiplier;
  361. foreach (var obj in objSet)
  362. {
  363. if (obj == null) continue;
  364. var objSize = BoundsUtils.GetBoundsRecursive(obj.transform,
  365. obj.transform.rotation * Quaternion.Euler(brush.eulerOffset)).size;
  366. cellSize = cellSizeType == SizeType.SMALLEST_OBJECT
  367. ? Vector3.Min(cellSize, objSize) : Vector3.Max(cellSize, objSize);
  368. var prefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(obj);
  369. if (prefab == null) continue;
  370. if (prefabs.Contains(prefab)) continue;
  371. prefabs.Add(prefab);
  372. var prefabSize = Vector3.Scale(BoundsUtils.GetBoundsRecursive(prefab.transform,
  373. prefab.transform.rotation * Quaternion.Euler(brush.eulerOffset)).size, scaleMultiplier);
  374. cellSize = cellSizeType == SizeType.SMALLEST_OBJECT
  375. ? Vector3.Min(cellSize, prefabSize) : Vector3.Max(cellSize, prefabSize);
  376. }
  377. }
  378. if (brush is MultibrushSettings)
  379. {
  380. var multibrush = brush as MultibrushSettings;
  381. foreach (var item in multibrush.items)
  382. {
  383. var prefab = item.prefab;
  384. if (prefab == null) continue;
  385. var scaleMultiplier = cellSizeType == SizeType.SMALLEST_OBJECT
  386. ? item.minScaleMultiplier : item.maxScaleMultiplier;
  387. var itemSize = Vector3.Scale(BoundsUtils.GetBoundsRecursive(prefab.transform,
  388. prefab.transform.rotation * Quaternion.Euler(brush.eulerOffset), ignoreDissabled: true,
  389. BoundsUtils.ObjectProperty.BOUNDING_BOX, recursive: true, useDictionary: false).size,
  390. scaleMultiplier);
  391. cellSize = cellSizeType == SizeType.SMALLEST_OBJECT
  392. ? Vector3.Min(cellSize, itemSize) : Vector3.Max(cellSize, itemSize);
  393. }
  394. }
  395. if (cellSize == Vector3.one * float.MaxValue || cellSize == Vector3.one * float.MinValue) return DefaultValue;
  396. if (tangentSpace)
  397. {
  398. if (upwardAxis.axis == AxesUtils.Axis.Y) cellSize.y = cellSize.z;
  399. else if (upwardAxis.axis == AxesUtils.Axis.X)
  400. {
  401. cellSize.x = cellSize.y;
  402. cellSize.y = cellSize.z;
  403. }
  404. }
  405. else
  406. {
  407. cellSize = Quaternion.Euler(AxesUtils.SignedAxis.GetEulerAnglesFromAxes(forwardAxis, upwardAxis)) * cellSize;
  408. if (quarterTurns > 0) cellSize = Quaternion.AngleAxis(quarterTurns * 90, upwardAxis) * cellSize;
  409. cellSize.x = Mathf.Abs(cellSize.x);
  410. cellSize.y = Mathf.Abs(cellSize.y);
  411. cellSize.z = Mathf.Abs(cellSize.z);
  412. }
  413. if (Mathf.Approximately(cellSize.x, 0)) cellSize.x = 0.5f;
  414. if (Mathf.Approximately(cellSize.y, 0)) cellSize.y = 0.5f;
  415. if (Mathf.Approximately(cellSize.z, 0)) cellSize.z = 0.5f;
  416. return cellSize;
  417. }
  418. }
  419. #region CIRCLE TOOLS
  420. [System.Serializable]
  421. public class CircleToolBase : IToolSettings
  422. {
  423. [SerializeField] private float _radius = 1f;
  424. public float radius
  425. {
  426. get => _radius;
  427. set
  428. {
  429. value = Mathf.Max(value, 0.05f);
  430. if (_radius == value) return;
  431. _radius = value;
  432. DataChanged();
  433. }
  434. }
  435. public virtual void Copy(IToolSettings other)
  436. {
  437. var otherCircleToolBase = other as CircleToolBase;
  438. if (otherCircleToolBase == null) return;
  439. _radius = otherCircleToolBase._radius;
  440. }
  441. public virtual void DataChanged() => PWBCore.SetSavePending();
  442. }
  443. [System.Serializable]
  444. public class BrushToolBase : CircleToolBase, IPaintToolSettings
  445. {
  446. [SerializeField] private PaintToolSettings _paintTool = new PaintToolSettings();
  447. public enum BrushShape { POINT, CIRCLE, SQUARE }
  448. [SerializeField] protected BrushShape _brushShape = BrushShape.CIRCLE;
  449. [SerializeField] private int _density = 50;
  450. [SerializeField] private bool _orientAlongBrushstroke = false;
  451. [SerializeField] private Vector3 _additionalOrientationAngle = Vector3.zero;
  452. public enum SpacingType { AUTO, CUSTOM }
  453. [SerializeField] private SpacingType _spacingType = SpacingType.AUTO;
  454. [SerializeField] protected float _minSpacing = 1f;
  455. [SerializeField] private bool _randomizePositions = true;
  456. [SerializeField] private float _randomness = 1f;
  457. public BrushToolBase() : base() => _paintTool.OnDataChanged += DataChanged;
  458. public BrushShape brushShape
  459. {
  460. get => _brushShape;
  461. set
  462. {
  463. if (_brushShape == value) return;
  464. _brushShape = value;
  465. DataChanged();
  466. }
  467. }
  468. public int density
  469. {
  470. get => _density;
  471. set
  472. {
  473. value = Mathf.Clamp(value, 0, 100);
  474. if (_density == value) return;
  475. _density = value;
  476. DataChanged();
  477. }
  478. }
  479. public bool orientAlongBrushstroke
  480. {
  481. get => _orientAlongBrushstroke;
  482. set
  483. {
  484. if (_orientAlongBrushstroke == value) return;
  485. _orientAlongBrushstroke = value;
  486. DataChanged();
  487. }
  488. }
  489. public Vector3 additionalOrientationAngle
  490. {
  491. get => _additionalOrientationAngle;
  492. set
  493. {
  494. if (_additionalOrientationAngle == value) return;
  495. _additionalOrientationAngle = value;
  496. DataChanged();
  497. }
  498. }
  499. public SpacingType spacingType
  500. {
  501. get => _spacingType;
  502. set
  503. {
  504. if (_spacingType == value) return;
  505. _spacingType = value;
  506. DataChanged();
  507. }
  508. }
  509. public float minSpacing
  510. {
  511. get => _minSpacing;
  512. set
  513. {
  514. if (_minSpacing == value) return;
  515. _minSpacing = value;
  516. DataChanged();
  517. }
  518. }
  519. public bool randomizePositions
  520. {
  521. get => _randomizePositions;
  522. set
  523. {
  524. if (_randomizePositions == value) return;
  525. _randomizePositions = value;
  526. DataChanged();
  527. }
  528. }
  529. public float randomness
  530. {
  531. get => _randomness;
  532. set
  533. {
  534. value = Mathf.Clamp01(value);
  535. if (_randomness == value) return;
  536. _randomness = value;
  537. DataChanged();
  538. }
  539. }
  540. public Transform parent { get => _paintTool.parent; set => _paintTool.parent = value; }
  541. public bool overwritePrefabLayer
  542. {
  543. get => _paintTool.overwritePrefabLayer;
  544. set => _paintTool.overwritePrefabLayer = value;
  545. }
  546. public int layer { get => _paintTool.layer; set => _paintTool.layer = value; }
  547. public bool autoCreateParent { get => _paintTool.autoCreateParent; set => _paintTool.autoCreateParent = value; }
  548. public bool setSurfaceAsParent { get => _paintTool.setSurfaceAsParent; set => _paintTool.setSurfaceAsParent = value; }
  549. public bool createSubparentPerPalette
  550. {
  551. get => _paintTool.createSubparentPerPalette;
  552. set => _paintTool.createSubparentPerPalette = value;
  553. }
  554. public bool createSubparentPerTool
  555. {
  556. get => _paintTool.createSubparentPerTool;
  557. set => _paintTool.createSubparentPerTool = value;
  558. }
  559. public bool createSubparentPerBrush
  560. {
  561. get => _paintTool.createSubparentPerBrush;
  562. set => _paintTool.createSubparentPerBrush = value;
  563. }
  564. public bool createSubparentPerPrefab
  565. {
  566. get => _paintTool.createSubparentPerPrefab;
  567. set => _paintTool.createSubparentPerPrefab = value;
  568. }
  569. public bool overwriteBrushProperties
  570. {
  571. get => _paintTool.overwriteBrushProperties;
  572. set => _paintTool.overwriteBrushProperties = value;
  573. }
  574. public BrushSettings brushSettings => _paintTool.brushSettings;
  575. public override void DataChanged()
  576. {
  577. base.DataChanged();
  578. BrushstrokeManager.UpdateBrushstroke();
  579. }
  580. public override void Copy(IToolSettings other)
  581. {
  582. var otherBrushToolBase = other as BrushToolBase;
  583. if (otherBrushToolBase == null) return;
  584. base.Copy(other);
  585. _paintTool.Copy(otherBrushToolBase._paintTool);
  586. _brushShape = otherBrushToolBase._brushShape;
  587. _density = otherBrushToolBase.density;
  588. _orientAlongBrushstroke = otherBrushToolBase._orientAlongBrushstroke;
  589. _additionalOrientationAngle = otherBrushToolBase._additionalOrientationAngle;
  590. _spacingType = otherBrushToolBase._spacingType;
  591. _minSpacing = otherBrushToolBase._minSpacing;
  592. _randomizePositions = otherBrushToolBase._randomizePositions;
  593. }
  594. }
  595. #endregion
  596. #region PAINT TOOLS
  597. public interface IPaintToolSettings
  598. {
  599. bool autoCreateParent { get; set; }
  600. bool setSurfaceAsParent { get; set; }
  601. bool createSubparentPerPalette { get; set; }
  602. bool createSubparentPerTool { get; set; }
  603. bool createSubparentPerBrush { get; set; }
  604. bool createSubparentPerPrefab { get; set; }
  605. Transform parent { get; set; }
  606. bool overwritePrefabLayer { get; set; }
  607. int layer { get; set; }
  608. bool overwriteBrushProperties { get; set; }
  609. BrushSettings brushSettings { get; }
  610. }
  611. [System.Serializable]
  612. public class PaintToolSettings : IPaintToolSettings, ISerializationCallbackReceiver, IToolSettings
  613. {
  614. private Transform _parent = null;
  615. [SerializeField] private string _parentGlobalId = null;
  616. [SerializeField] private bool _autoCreateParent = true;
  617. [SerializeField] private bool _setSurfaceAsParent = false;
  618. [SerializeField] private bool _createSubparentPerPalette = true;
  619. [SerializeField] private bool _createSubparentPerTool = true;
  620. [SerializeField] private bool _createSubparentPerBrush = false;
  621. [SerializeField] private bool _createSubparentPerPrefab = false;
  622. [SerializeField] private bool _overwritePrefabLayer = false;
  623. [SerializeField] private int _layer = 0;
  624. [SerializeField] private bool _overwriteBrushProperties = false;
  625. [SerializeField] private BrushSettings _brushSettings = new BrushSettings();
  626. public System.Action OnDataChanged;
  627. public PaintToolSettings()
  628. {
  629. OnDataChanged += DataChanged;
  630. _brushSettings.OnDataChangedAction += DataChanged;
  631. }
  632. public Transform parent
  633. {
  634. get
  635. {
  636. if (_parent == null && _parentGlobalId != null)
  637. {
  638. if (UnityEditor.GlobalObjectId.TryParse(_parentGlobalId, out UnityEditor.GlobalObjectId id))
  639. {
  640. var obj = UnityEditor.GlobalObjectId.GlobalObjectIdentifierToObjectSlow(id) as GameObject;
  641. if (obj == null) _parentGlobalId = null;
  642. else _parent = obj.transform;
  643. }
  644. }
  645. return _parent;
  646. }
  647. set
  648. {
  649. if (_parent == value) return;
  650. _parent = value;
  651. _parentGlobalId = _parent == null ? null
  652. : UnityEditor.GlobalObjectId.GetGlobalObjectIdSlow(_parent.gameObject).ToString();
  653. OnDataChanged();
  654. }
  655. }
  656. public bool autoCreateParent
  657. {
  658. get => _autoCreateParent;
  659. set
  660. {
  661. if (_autoCreateParent == value) return;
  662. _autoCreateParent = value;
  663. OnDataChanged();
  664. }
  665. }
  666. public bool setSurfaceAsParent
  667. {
  668. get => _setSurfaceAsParent;
  669. set
  670. {
  671. if (_setSurfaceAsParent == value) return;
  672. _setSurfaceAsParent = value;
  673. OnDataChanged();
  674. }
  675. }
  676. public bool createSubparentPerPalette
  677. {
  678. get => _createSubparentPerPalette;
  679. set
  680. {
  681. if (_createSubparentPerPalette == value) return;
  682. _createSubparentPerPalette = value;
  683. OnDataChanged();
  684. }
  685. }
  686. public bool createSubparentPerTool
  687. {
  688. get => _createSubparentPerTool;
  689. set
  690. {
  691. if (_createSubparentPerTool == value) return;
  692. _createSubparentPerTool = value;
  693. OnDataChanged();
  694. }
  695. }
  696. public bool createSubparentPerBrush
  697. {
  698. get => _createSubparentPerBrush;
  699. set
  700. {
  701. if (_createSubparentPerBrush == value) return;
  702. _createSubparentPerBrush = value;
  703. OnDataChanged();
  704. }
  705. }
  706. public bool createSubparentPerPrefab
  707. {
  708. get => _createSubparentPerPrefab;
  709. set
  710. {
  711. if (_createSubparentPerPrefab == value) return;
  712. _createSubparentPerPrefab = value;
  713. OnDataChanged();
  714. }
  715. }
  716. public bool overwritePrefabLayer
  717. {
  718. get => _overwritePrefabLayer;
  719. set
  720. {
  721. if (_overwritePrefabLayer == value) return;
  722. _overwritePrefabLayer = value;
  723. OnDataChanged();
  724. }
  725. }
  726. public int layer
  727. {
  728. get => _layer;
  729. set
  730. {
  731. if (_layer == value) return;
  732. _layer = value;
  733. OnDataChanged();
  734. }
  735. }
  736. public bool overwriteBrushProperties
  737. {
  738. get => _overwriteBrushProperties;
  739. set
  740. {
  741. if (_overwriteBrushProperties == value) return;
  742. _overwriteBrushProperties = value;
  743. OnDataChanged();
  744. }
  745. }
  746. public BrushSettings brushSettings => _brushSettings;
  747. public virtual void DataChanged() => PWBCore.SetSavePending();
  748. public void OnBeforeSerialize() { }
  749. public void OnAfterDeserialize() => _parent = null;
  750. public virtual void Copy(IToolSettings other)
  751. {
  752. var otherPaintToolSettings = other as PaintToolSettings;
  753. if (otherPaintToolSettings == null) return;
  754. _parent = otherPaintToolSettings._parent;
  755. _parentGlobalId = otherPaintToolSettings._parentGlobalId;
  756. _overwritePrefabLayer = otherPaintToolSettings._overwritePrefabLayer;
  757. _layer = otherPaintToolSettings._layer;
  758. _autoCreateParent = otherPaintToolSettings._autoCreateParent;
  759. _setSurfaceAsParent = otherPaintToolSettings._setSurfaceAsParent;
  760. _createSubparentPerPalette = otherPaintToolSettings._createSubparentPerPalette;
  761. _createSubparentPerTool = otherPaintToolSettings._createSubparentPerTool;
  762. _createSubparentPerBrush = otherPaintToolSettings._createSubparentPerBrush;
  763. _createSubparentPerPrefab = otherPaintToolSettings._createSubparentPerPrefab;
  764. _overwriteBrushProperties = otherPaintToolSettings._overwriteBrushProperties;
  765. _brushSettings.Copy(otherPaintToolSettings._brushSettings);
  766. }
  767. }
  768. #endregion
  769. #region PAINT ON SURFACE TOOLS
  770. public interface IPaintOnSurfaceToolSettings
  771. {
  772. bool paintOnMeshesWithoutCollider { get; set; }
  773. bool paintOnSelectedOnly { get; set; }
  774. bool paintOnPalettePrefabs { get; set; }
  775. }
  776. public abstract class PaintOnSurfaceToolSettingsBase : IPaintOnSurfaceToolSettings
  777. {
  778. public abstract bool paintOnMeshesWithoutCollider { get; set; }
  779. public abstract bool paintOnSelectedOnly { get; set; }
  780. public abstract bool paintOnPalettePrefabs { get; set; }
  781. public enum PaintMode
  782. {
  783. AUTO,
  784. ON_SURFACE,
  785. ON_SHAPE
  786. }
  787. }
  788. [System.Serializable]
  789. public class PaintOnSurfaceToolSettings : PaintOnSurfaceToolSettingsBase,
  790. ISerializationCallbackReceiver, IToolSettings
  791. {
  792. [SerializeField] private bool _paintOnMeshesWithoutCollider = false;
  793. [SerializeField] private bool _paintOnSelectedOnly = false;
  794. [SerializeField] private bool _paintOnPalettePrefabs = false;
  795. [SerializeField] private PaintMode _mode = PaintMode.AUTO;
  796. [SerializeField] private bool _paralellToTheSurface = true;
  797. private bool _updateMeshColliders = false;
  798. public System.Action OnDataChanged;
  799. public PaintOnSurfaceToolSettings() => OnDataChanged += DataChanged;
  800. public PaintMode mode
  801. {
  802. get => _mode;
  803. set
  804. {
  805. if (_mode == value) return;
  806. _mode = value;
  807. OnDataChanged();
  808. }
  809. }
  810. public bool perpendicularToTheSurface
  811. {
  812. get => _paralellToTheSurface;
  813. set
  814. {
  815. if (_paralellToTheSurface == value) return;
  816. _paralellToTheSurface = value;
  817. OnDataChanged();
  818. }
  819. }
  820. public override bool paintOnMeshesWithoutCollider
  821. {
  822. get
  823. {
  824. if (PWBCore.staticData.tempCollidersAction == PWBData.TempCollidersAction.NEVER_CREATE)
  825. return false;
  826. if (_updateMeshColliders)
  827. {
  828. _updateMeshColliders = false;
  829. PWBCore.UpdateTempColliders();
  830. }
  831. return _paintOnMeshesWithoutCollider;
  832. }
  833. set
  834. {
  835. if (_paintOnMeshesWithoutCollider == value) return;
  836. _paintOnMeshesWithoutCollider = value;
  837. OnDataChanged();
  838. if (_paintOnMeshesWithoutCollider) PWBCore.UpdateTempColliders();
  839. }
  840. }
  841. public override bool paintOnSelectedOnly
  842. {
  843. get => _paintOnSelectedOnly;
  844. set
  845. {
  846. if (_paintOnSelectedOnly == value) return;
  847. _paintOnSelectedOnly = value;
  848. OnDataChanged();
  849. }
  850. }
  851. public override bool paintOnPalettePrefabs
  852. {
  853. get => _paintOnPalettePrefabs;
  854. set
  855. {
  856. if (_paintOnPalettePrefabs == value) return;
  857. _paintOnPalettePrefabs = value;
  858. OnDataChanged();
  859. }
  860. }
  861. public virtual void Copy(IToolSettings other)
  862. {
  863. var otherPaintOnSurfaceToolSettings = other as PaintOnSurfaceToolSettings;
  864. if (otherPaintOnSurfaceToolSettings == null) return;
  865. _paintOnMeshesWithoutCollider = otherPaintOnSurfaceToolSettings._paintOnMeshesWithoutCollider;
  866. _paintOnSelectedOnly = otherPaintOnSurfaceToolSettings._paintOnSelectedOnly;
  867. _paintOnPalettePrefabs = otherPaintOnSurfaceToolSettings._paintOnPalettePrefabs;
  868. _mode = otherPaintOnSurfaceToolSettings._mode;
  869. _paralellToTheSurface = otherPaintOnSurfaceToolSettings._paralellToTheSurface;
  870. }
  871. public virtual void DataChanged() => PWBCore.SetSavePending();
  872. public void OnBeforeSerialize() { }
  873. public void OnAfterDeserialize() => _updateMeshColliders = _paintOnMeshesWithoutCollider;
  874. }
  875. #endregion
  876. #region SELECTION TOOLS
  877. [System.Serializable]
  878. public class SelectionToolBaseBasic : IToolSettings
  879. {
  880. [SerializeField] private bool _embedInSurface = false;
  881. [SerializeField] private bool _embedAtPivotHeight = false;
  882. [SerializeField] private float _surfaceDistance = 0f;
  883. [SerializeField] private bool _createTempColliders = true;
  884. public bool embedInSurface
  885. {
  886. get => _embedInSurface;
  887. set
  888. {
  889. if (_embedInSurface == value) return;
  890. _embedInSurface = value;
  891. DataChanged();
  892. }
  893. }
  894. public bool embedAtPivotHeight
  895. {
  896. get => _embedAtPivotHeight;
  897. set
  898. {
  899. if (_embedAtPivotHeight == value) return;
  900. _embedAtPivotHeight = value;
  901. DataChanged();
  902. }
  903. }
  904. public float surfaceDistance
  905. {
  906. get => _surfaceDistance;
  907. set
  908. {
  909. if (_surfaceDistance == value) return;
  910. _surfaceDistance = value;
  911. DataChanged();
  912. }
  913. }
  914. public bool createTempColliders
  915. {
  916. get
  917. {
  918. if (PWBCore.staticData.tempCollidersAction == PWBData.TempCollidersAction.NEVER_CREATE)
  919. return false;
  920. return _createTempColliders;
  921. }
  922. set
  923. {
  924. if (_createTempColliders == value) return;
  925. _createTempColliders = value;
  926. DataChanged();
  927. }
  928. }
  929. public virtual void Copy(IToolSettings other)
  930. {
  931. var otherSelectionTool = other as SelectionToolBaseBasic;
  932. if (otherSelectionTool == null) return;
  933. _embedInSurface = otherSelectionTool._embedInSurface;
  934. _embedAtPivotHeight = otherSelectionTool._embedAtPivotHeight;
  935. _surfaceDistance = otherSelectionTool._surfaceDistance;
  936. _createTempColliders = otherSelectionTool._createTempColliders;
  937. }
  938. public virtual void DataChanged() => PWBCore.SetSavePending();
  939. }
  940. [System.Serializable]
  941. public class SelectionToolBase : SelectionToolBaseBasic
  942. {
  943. [SerializeField] private bool _rotateToTheSurface = false;
  944. public bool rotateToTheSurface
  945. {
  946. get => _rotateToTheSurface;
  947. set
  948. {
  949. if (_rotateToTheSurface == value) return;
  950. _rotateToTheSurface = value;
  951. DataChanged();
  952. }
  953. }
  954. public override void Copy(IToolSettings other)
  955. {
  956. var otherSelectionTool = other as SelectionToolBase;
  957. if (otherSelectionTool == null) return;
  958. base.Copy(other);
  959. _rotateToTheSurface = otherSelectionTool._rotateToTheSurface;
  960. }
  961. }
  962. public interface ISelectionBrushTool
  963. {
  964. ModifierToolSettings.Command command { get; set; }
  965. bool onlyTheClosest { get; set; }
  966. bool outermostPrefabFilter { get; set; }
  967. }
  968. public interface IModifierTool
  969. {
  970. bool modifyAllButSelected { get; set; }
  971. }
  972. [System.Serializable]
  973. public class SelectionBrushToolSettings : ISelectionBrushTool, IToolSettings
  974. {
  975. public enum Command
  976. {
  977. SELECT_ALL,
  978. SELECT_PALETTE_PREFABS,
  979. SELECT_BRUSH_PREFABS
  980. }
  981. [SerializeField] private Command _command = Command.SELECT_ALL;
  982. [SerializeField] private bool _onlyTheClosest = false;
  983. [SerializeField] private bool _outermostPrefabFilter = true;
  984. public System.Action OnDataChanged;
  985. public SelectionBrushToolSettings() => OnDataChanged += DataChanged;
  986. public Command command
  987. {
  988. get => _command;
  989. set
  990. {
  991. if (_command == value) return;
  992. _command = value;
  993. DataChanged();
  994. }
  995. }
  996. public bool onlyTheClosest
  997. {
  998. get => _onlyTheClosest;
  999. set
  1000. {
  1001. if (_onlyTheClosest == value) return;
  1002. _onlyTheClosest = value;
  1003. DataChanged();
  1004. }
  1005. }
  1006. public bool outermostPrefabFilter
  1007. {
  1008. get => _outermostPrefabFilter;
  1009. set
  1010. {
  1011. if (_outermostPrefabFilter == value) return;
  1012. _outermostPrefabFilter = value;
  1013. DataChanged();
  1014. }
  1015. }
  1016. public void DataChanged() => PWBCore.SetSavePending();
  1017. public virtual void Copy(IToolSettings other)
  1018. {
  1019. var otherModifier = other as ISelectionBrushTool;
  1020. if (otherModifier == null) return;
  1021. _command = otherModifier.command;
  1022. _onlyTheClosest = otherModifier.onlyTheClosest;
  1023. _outermostPrefabFilter = otherModifier.outermostPrefabFilter;
  1024. }
  1025. }
  1026. [System.Serializable]
  1027. public class ModifierToolSettings : SelectionBrushToolSettings, IModifierTool
  1028. {
  1029. [SerializeField] private bool _allButSelected = false;
  1030. public bool modifyAllButSelected
  1031. {
  1032. get => _allButSelected;
  1033. set
  1034. {
  1035. if (_allButSelected == value) return;
  1036. _allButSelected = value;
  1037. DataChanged();
  1038. }
  1039. }
  1040. public override void Copy(IToolSettings other)
  1041. {
  1042. var otherModifier = other as IModifierTool;
  1043. if (otherModifier == null) return;
  1044. base.Copy(other);
  1045. _allButSelected = otherModifier.modifyAllButSelected;
  1046. }
  1047. }
  1048. #endregion
  1049. #region MODULAR TOOLS
  1050. public class ModularToolBase : IToolSettings, IPaintToolSettings
  1051. {
  1052. [SerializeField] private TilesUtils.SizeType _moduleSizeType = TilesUtils.SizeType.BIGGEST_OBJECT;
  1053. [SerializeField] protected Vector3 _moduleSize = Vector3.one;
  1054. [SerializeField] private Vector3 _spacing = Vector3.zero;
  1055. [SerializeField] protected AxesUtils.SignedAxis _upwardAxis = AxesUtils.SignedAxis.UP;
  1056. [SerializeField] private AxesUtils.SignedAxis _forwardAxis = AxesUtils.SignedAxis.FORWARD;
  1057. public System.Action OnDataChanged;
  1058. public ModularToolBase() : base()
  1059. {
  1060. _paintTool.OnDataChanged += DataChanged;
  1061. OnDataChanged += DataChanged;
  1062. }
  1063. public TilesUtils.SizeType moduleSizeType
  1064. {
  1065. get => _moduleSizeType;
  1066. set
  1067. {
  1068. if (_moduleSizeType == value) return;
  1069. _moduleSizeType = value;
  1070. UpdateCellSize();
  1071. OnDataChanged();
  1072. }
  1073. }
  1074. public virtual Vector3 moduleSize
  1075. {
  1076. get => _moduleSize;
  1077. set
  1078. {
  1079. if (_moduleSize == value) return;
  1080. _moduleSize = value;
  1081. OnDataChanged();
  1082. }
  1083. }
  1084. public Vector3 spacing
  1085. {
  1086. get => _spacing;
  1087. set
  1088. {
  1089. if (_spacing == value) return;
  1090. _spacing = value;
  1091. OnDataChanged();
  1092. }
  1093. }
  1094. public AxesUtils.SignedAxis upwardAxis
  1095. {
  1096. get => _upwardAxis;
  1097. set
  1098. {
  1099. if (_upwardAxis == value) return;
  1100. if (_forwardAxis.axis == value) _forwardAxis = _upwardAxis;
  1101. _upwardAxis = value;
  1102. UpdateCellSize();
  1103. OnDataChanged();
  1104. }
  1105. }
  1106. public AxesUtils.SignedAxis forwardAxis
  1107. {
  1108. get => _forwardAxis;
  1109. set
  1110. {
  1111. if(_forwardAxis == value) return;
  1112. if (_upwardAxis.axis == value) _upwardAxis = _forwardAxis;
  1113. _forwardAxis = value;
  1114. UpdateCellSize();
  1115. OnDataChanged();
  1116. }
  1117. }
  1118. public void SetUpwardAxis(AxesUtils.SignedAxis value) => _upwardAxis = value;
  1119. public void SetForwardAxis(AxesUtils.SignedAxis value) => _forwardAxis = value;
  1120. public virtual Vector3 GetCellSize(BrushSettings brush)
  1121. {
  1122. if (moduleSizeType == TilesUtils.SizeType.CUSTOM) return _moduleSize;
  1123. if (brush == null) return Vector3.one;
  1124. int quarterTurns = 0;
  1125. if (this is FloorSettings) quarterTurns = FloorManager.quarterTurns;
  1126. return TilesUtils.GetCellSize(moduleSizeType, brush, upwardAxis, forwardAxis,
  1127. moduleSize, tangentSpace: false, quarterTurns);
  1128. }
  1129. public virtual void UpdateCellSize()
  1130. {
  1131. if (moduleSizeType != TilesUtils.SizeType.CUSTOM)
  1132. {
  1133. BrushSettings brush = PaletteManager.selectedBrush;
  1134. if (overwriteBrushProperties) brush = brushSettings;
  1135. if (brush == null) return;
  1136. int quarterTurns = 0;
  1137. if (this is FloorSettings) quarterTurns = FloorManager.quarterTurns;
  1138. else if (this is WallSettings) quarterTurns = WallManager.halfTurn ? 2 : 0;
  1139. _moduleSize = TilesUtils.GetCellSize(moduleSizeType, brush, upwardAxis, forwardAxis,
  1140. moduleSize, tangentSpace: false, quarterTurns);
  1141. ToolProperties.RepainWindow();
  1142. UnityEditor.SceneView.RepaintAll();
  1143. }
  1144. }
  1145. #region PAINT TOOL
  1146. [SerializeField] private PaintToolSettings _paintTool = new PaintToolSettings();
  1147. public Transform parent { get => _paintTool.parent; set => _paintTool.parent = value; }
  1148. public bool overwritePrefabLayer
  1149. {
  1150. get => _paintTool.overwritePrefabLayer;
  1151. set => _paintTool.overwritePrefabLayer = value;
  1152. }
  1153. public int layer { get => _paintTool.layer; set => _paintTool.layer = value; }
  1154. public bool autoCreateParent { get => _paintTool.autoCreateParent; set => _paintTool.autoCreateParent = value; }
  1155. public bool setSurfaceAsParent { get => _paintTool.setSurfaceAsParent; set => _paintTool.setSurfaceAsParent = value; }
  1156. public bool createSubparentPerPalette
  1157. {
  1158. get => _paintTool.createSubparentPerPalette;
  1159. set => _paintTool.createSubparentPerPalette = value;
  1160. }
  1161. public bool createSubparentPerTool
  1162. {
  1163. get => _paintTool.createSubparentPerTool;
  1164. set => _paintTool.createSubparentPerTool = value;
  1165. }
  1166. public bool createSubparentPerBrush
  1167. {
  1168. get => _paintTool.createSubparentPerBrush;
  1169. set => _paintTool.createSubparentPerBrush = value;
  1170. }
  1171. public bool createSubparentPerPrefab
  1172. {
  1173. get => _paintTool.createSubparentPerPrefab;
  1174. set => _paintTool.createSubparentPerPrefab = value;
  1175. }
  1176. public bool overwriteBrushProperties
  1177. {
  1178. get => _paintTool.overwriteBrushProperties;
  1179. set => _paintTool.overwriteBrushProperties = value;
  1180. }
  1181. public BrushSettings brushSettings => _paintTool.brushSettings;
  1182. #endregion
  1183. public void DataChanged()
  1184. {
  1185. PWBCore.SetSavePending();
  1186. }
  1187. public virtual void Copy(IToolSettings other)
  1188. {
  1189. var otherModularToolSettings = other as ModularToolBase;
  1190. if (otherModularToolSettings == null) return;
  1191. _paintTool.Copy(otherModularToolSettings._paintTool);
  1192. _moduleSizeType = otherModularToolSettings._moduleSizeType;
  1193. _moduleSize = otherModularToolSettings._moduleSize;
  1194. _spacing = otherModularToolSettings._spacing;
  1195. _upwardAxis = otherModularToolSettings._upwardAxis;
  1196. }
  1197. }
  1198. #endregion
  1199. #endregion
  1200. #region DATA
  1201. [System.Serializable]
  1202. public class ControlPoint
  1203. {
  1204. public Vector3 position = Vector3.zero;
  1205. public ControlPoint() { }
  1206. public ControlPoint(Vector3 position) => this.position = position;
  1207. public ControlPoint(ControlPoint other) => position = other.position;
  1208. public virtual void Copy(ControlPoint other)
  1209. {
  1210. position = other.position;
  1211. }
  1212. public static implicit operator ControlPoint(Vector3 position) => new ControlPoint(position);
  1213. public static implicit operator Vector3(ControlPoint point) => point.position;
  1214. public static Vector3[] PointArrayToVectorArray(ControlPoint[] array)
  1215. => array.Select(point => point.position).ToArray();
  1216. public static ControlPoint[] VectorArrayToPointArray(Vector3[] array)
  1217. => array.Select(position => new ControlPoint(position)).ToArray();
  1218. }
  1219. [System.Serializable]
  1220. public struct ObjectId : System.IEquatable<ObjectId>
  1221. {
  1222. [SerializeField] private string _globalObjId;
  1223. public string globalObjId { get => _globalObjId; set => _globalObjId = value; }
  1224. public ObjectId(GameObject gameObject)
  1225. {
  1226. if (gameObject == null)
  1227. {
  1228. _globalObjId = null;
  1229. return;
  1230. }
  1231. _globalObjId = UnityEditor.GlobalObjectId.GetGlobalObjectIdSlow(gameObject).ToString();
  1232. }
  1233. public ObjectId(string globalObjId)
  1234. {
  1235. _globalObjId = globalObjId;
  1236. }
  1237. public override int GetHashCode()
  1238. {
  1239. int hashCode = 917907199;
  1240. hashCode = hashCode * -1521134295
  1241. + System.Collections.Generic.EqualityComparer<string>.Default.GetHashCode(_globalObjId);
  1242. return hashCode;
  1243. }
  1244. public bool Equals(ObjectId other) => _globalObjId == other._globalObjId;
  1245. public override bool Equals(object obj) => obj is ObjectId other && this.Equals(other);
  1246. public static bool operator ==(ObjectId lhs, ObjectId rhs) => lhs.Equals(rhs);
  1247. public static bool operator !=(ObjectId lhs, ObjectId rhs) => !lhs.Equals(rhs);
  1248. public void Copy(ObjectId other)
  1249. {
  1250. _globalObjId = other._globalObjId;
  1251. }
  1252. public static GameObject FindObject(ObjectId objId)
  1253. {
  1254. GameObject gameObj = null;
  1255. if (UnityEditor.GlobalObjectId.TryParse(objId.globalObjId, out UnityEditor.GlobalObjectId id))
  1256. gameObj = UnityEditor.GlobalObjectId.GlobalObjectIdentifierToObjectSlow(id) as GameObject;
  1257. return gameObj;
  1258. }
  1259. }
  1260. [System.Serializable]
  1261. public struct ObjectPose
  1262. {
  1263. [SerializeField] private Vector3 _position;
  1264. [SerializeField] private Quaternion _localRotation;
  1265. [SerializeField] private Vector3 _localScale;
  1266. public ObjectPose(Vector3 position, Quaternion localRotation, Vector3 localScale)
  1267. {
  1268. _position = position;
  1269. _localRotation = localRotation;
  1270. _localScale = localScale;
  1271. }
  1272. public ObjectPose(GameObject obj)
  1273. {
  1274. _position = obj.transform.position;
  1275. _localRotation = obj.transform.localRotation;
  1276. _localScale = obj.transform.localScale;
  1277. }
  1278. public Vector3 position { get => _position; set => _position = value; }
  1279. public Quaternion localRotation { get => _localRotation; set => _localRotation = value; }
  1280. public Vector3 localScale { get => _localScale; set => _localScale = value; }
  1281. public void Copy(ObjectPose other)
  1282. {
  1283. _position = other._position;
  1284. _localRotation = other._localRotation;
  1285. _localScale = other._localScale;
  1286. }
  1287. }
  1288. #region PERSISTENT DATA
  1289. public interface IToolName { string value { get; } }
  1290. public interface IPersistentData
  1291. {
  1292. long id { get; }
  1293. string name { get; set; }
  1294. void Rename(string newName, bool renameParentObject);
  1295. public enum Visibility
  1296. {
  1297. SHOW_ALL,
  1298. SHOW_OBJECTS,
  1299. HIDE_ALL,
  1300. }
  1301. Visibility visibility { get; set; }
  1302. void ToggleVisibility();
  1303. GameObject[] objects { get; }
  1304. bool isSelected { get; set; }
  1305. void ToggleSelection();
  1306. void ClearSelection();
  1307. void SelectAll();
  1308. bool AllPointsAreSelected();
  1309. Bounds GetBounds(float sizeMultiplier);
  1310. GameObject GetParent();
  1311. bool ControlPointIsSelected(int idx);
  1312. string toolName { get; }
  1313. }
  1314. [System.Serializable]
  1315. public class PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT> : IPersistentData, ISerializationCallbackReceiver
  1316. where TOOL_NAME : IToolName, new()
  1317. where TOOL_SETTINGS : IToolSettings, new()
  1318. where CONTROL_POINT : ControlPoint, new()
  1319. {
  1320. #region ID & NAME
  1321. private static long _nextId = System.DateTime.Now.Ticks;
  1322. [SerializeField] protected long _id = _nextId;
  1323. public static long nextId => _nextId;
  1324. public static string HexId(long value) => (new TOOL_NAME()).value + "_" + value.ToString("X");
  1325. public static string nextHexId => HexId(_nextId);
  1326. public static void SetNextId() => _nextId = System.DateTime.Now.Ticks;
  1327. public long id => _id;
  1328. public string hexId => HexId(id);
  1329. [SerializeField] private string _name = string.Empty;
  1330. public string name
  1331. {
  1332. get
  1333. {
  1334. if (string.IsNullOrEmpty(_name)) _name = hexId;
  1335. return _name;
  1336. }
  1337. set
  1338. {
  1339. if (_name == value) return;
  1340. _name = value;
  1341. PWBCore.SetSavePending();
  1342. }
  1343. }
  1344. public void Rename(string newName, bool renameParentObject)
  1345. {
  1346. var oldName = name;
  1347. if (oldName == newName) return;
  1348. name = newName;
  1349. if (!renameParentObject) return;
  1350. var parent = GetParent().transform;
  1351. if (parent == null) return;
  1352. do
  1353. {
  1354. if (parent.name == oldName)
  1355. {
  1356. parent.name = newName;
  1357. return;
  1358. }
  1359. parent = parent.transform.parent;
  1360. }
  1361. while (parent != null);
  1362. }
  1363. #endregion
  1364. #region VISIBILITY
  1365. [SerializeField] private IPersistentData.Visibility _visibility = IPersistentData.Visibility.SHOW_ALL;
  1366. public IPersistentData.Visibility visibility
  1367. {
  1368. get => _visibility;
  1369. set
  1370. {
  1371. if (_visibility == value) return;
  1372. _visibility = value;
  1373. PWBCore.SetSavePending();
  1374. }
  1375. }
  1376. public void ToggleVisibility()
  1377. {
  1378. switch (visibility)
  1379. {
  1380. case IPersistentData.Visibility.SHOW_ALL: _visibility = IPersistentData.Visibility.SHOW_OBJECTS; break;
  1381. case IPersistentData.Visibility.SHOW_OBJECTS: _visibility = IPersistentData.Visibility.HIDE_ALL; break;
  1382. case IPersistentData.Visibility.HIDE_ALL: _visibility = IPersistentData.Visibility.SHOW_ALL; break;
  1383. }
  1384. PWBCore.SetSavePending();
  1385. }
  1386. #endregion
  1387. #region SELECTION
  1388. public bool isSelected { get; set; }
  1389. public virtual void ToggleSelection() => isSelected = !isSelected;
  1390. #endregion
  1391. #region OBJECT POSES
  1392. [SerializeField]
  1393. private System.Collections.Generic.List<ObjectPose> _poses = new System.Collections.Generic.List<ObjectPose>();
  1394. [SerializeField]
  1395. private System.Collections.Generic.List<ObjectId> _objectIds = new System.Collections.Generic.List<ObjectId>();
  1396. private System.Collections.Generic.List<GameObject> _objects = new System.Collections.Generic.List<GameObject>();
  1397. private void FindObjects()
  1398. {
  1399. if (_objectIds.Count == _objects.Count) return;
  1400. var ids = _objectIds.ToArray();
  1401. _objectIds.Clear();
  1402. _poses.Clear();
  1403. _objects.Clear();
  1404. void AddPose(GameObject obj)
  1405. {
  1406. if (obj == null) return;
  1407. _objectIds.Add(new ObjectId(obj));
  1408. _objects.Add(obj);
  1409. _poses.Add(new ObjectPose(obj));
  1410. }
  1411. var first = ObjectId.FindObject(ids[0]);
  1412. if (first != null)
  1413. {
  1414. var parent = first.transform.parent;
  1415. if (parent != null && parent.childCount == ids.Length)
  1416. {
  1417. foreach (Transform child in parent) AddPose(child.gameObject);
  1418. return;
  1419. }
  1420. }
  1421. for (int i = 0; i < ids.Length; ++i)
  1422. {
  1423. var obj = ObjectId.FindObject(ids[i]);
  1424. if (obj == null) continue;
  1425. _objectIds.Add(ids[i]);
  1426. _objects.Add(obj);
  1427. _poses.Add(new ObjectPose(obj));
  1428. }
  1429. }
  1430. public void AddPose(ObjectId objId, ObjectPose pose, bool updateObjectArray = true)
  1431. {
  1432. var obj = ObjectId.FindObject(objId);
  1433. if (obj == null) return;
  1434. _poses.Add(pose);
  1435. _objectIds.Add(objId);
  1436. if (!updateObjectArray) return;
  1437. if (_objectIds.Count + 1 != _objects.Count) FindObjects();
  1438. _objects.Add(obj);
  1439. }
  1440. public void InitializePoses((ObjectId, ObjectPose)[] items)
  1441. {
  1442. _poses.Clear();
  1443. _objectIds.Clear();
  1444. _objects.Clear();
  1445. foreach (var item in items) AddPose(item.Item1, item.Item2);
  1446. }
  1447. public void InsertPose(int index, ObjectPose pose, ObjectId objId, bool updateObjectArray = true)
  1448. {
  1449. var obj = ObjectId.FindObject(objId);
  1450. if (obj == null) return;
  1451. _poses.Insert(index, pose);
  1452. _objectIds.Insert(index, objId);
  1453. if (!updateObjectArray) return;
  1454. if (_objectIds.Count + 1 != _objects.Count) FindObjects();
  1455. _objects.Insert(index, obj);
  1456. }
  1457. public void RemovePose(int index)
  1458. {
  1459. _poses.RemoveAt(index);
  1460. _objectIds.RemoveAt(index);
  1461. if (_objectIds.Count - 1 == _objects.Count) _objects.RemoveAt(index);
  1462. }
  1463. public void RemoveAllPoses()
  1464. {
  1465. _poses.Clear();
  1466. _objectIds.Clear();
  1467. _objects.Clear();
  1468. }
  1469. public void UpdatePoses()
  1470. {
  1471. if (_objectIds.Count != _objects.Count)
  1472. {
  1473. FindObjects();
  1474. return;
  1475. }
  1476. var objCount = _objectIds.Count;
  1477. var ids = _objectIds.ToArray();
  1478. var poses = _poses.ToArray();
  1479. var objs = _objects.ToArray();
  1480. _objectIds.Clear();
  1481. _poses.Clear();
  1482. _objects.Clear();
  1483. for (int i = 0; i < objCount; ++i)
  1484. {
  1485. var obj = objs[i];
  1486. if (obj == null) continue;
  1487. AddPose(new ObjectId(obj), new ObjectPose(obj));
  1488. }
  1489. }
  1490. public void AddObjects((GameObject, int)[] objects)
  1491. {
  1492. for (int i = 0; i < objects.Length; ++i)
  1493. {
  1494. var idx = objects[i].Item2;
  1495. var obj = objects[i].Item1;
  1496. if (idx > -1 && idx < objectCount)
  1497. InsertPose(idx, new ObjectPose(obj.transform.position, obj.transform.localRotation,
  1498. obj.transform.localScale), new ObjectId(obj));
  1499. else AddPose(new ObjectId(obj),
  1500. new ObjectPose(obj.transform.position, obj.transform.localRotation, obj.transform.localScale));
  1501. }
  1502. }
  1503. public bool ReplaceObject(GameObject target, GameObject obj)
  1504. {
  1505. int targetIdx = -1;
  1506. var targetId = new ObjectId(target);
  1507. for (int i = 0; i < _objectIds.Count; ++i)
  1508. {
  1509. var objId = _objectIds[i];
  1510. if (targetId == objId)
  1511. {
  1512. targetIdx = i;
  1513. break;
  1514. }
  1515. }
  1516. if (targetIdx == -1) return false;
  1517. InsertPose(targetIdx, new ObjectPose(obj.transform.position, obj.transform.localRotation,
  1518. obj.transform.localScale), new ObjectId(obj), updateObjectArray: true);
  1519. RemovePose(targetIdx + 1);
  1520. return true;
  1521. }
  1522. public int objectCount => _objectIds.Count;
  1523. public bool isEmpty()
  1524. {
  1525. if (_objectIds.Count == 0) return true;
  1526. var allObjectsAreNull = _objects.Count > 0 && !_objects.Exists(i => i != null);
  1527. return allObjectsAreNull;
  1528. }
  1529. public GameObject[] objects
  1530. {
  1531. get
  1532. {
  1533. if (_objectIds.Count != _objects.Count) FindObjects();
  1534. return _objects.ToArray();
  1535. }
  1536. }
  1537. public System.Collections.Generic.HashSet<GameObject> objectSet
  1538. {
  1539. get
  1540. {
  1541. if (_objectIds.Count != _objects.Count) FindObjects();
  1542. return new System.Collections.Generic.HashSet<GameObject>(_objects);
  1543. }
  1544. }
  1545. public System.Collections.Generic.List<GameObject> objectList
  1546. {
  1547. get
  1548. {
  1549. if (_objectIds.Count != _objects.Count) FindObjects();
  1550. return _objects.ToList();
  1551. }
  1552. }
  1553. public void DestroyGameObjects()
  1554. {
  1555. foreach (var obj in objectList) if (obj != null) UnityEditor.Undo.DestroyObjectImmediate(obj);
  1556. }
  1557. public virtual void ResetPoses(PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT> initialData)
  1558. {
  1559. var initialPoses = initialData._poses;
  1560. if (_objectIds.Count != _objects.Count) FindObjects();
  1561. for (int i = 0; i < objectCount; ++i)
  1562. {
  1563. var obj = _objects[i];
  1564. if (obj == null) obj = ObjectId.FindObject(_objectIds[i]);
  1565. if (obj == null) continue;
  1566. var pose = _poses[i];
  1567. UnityEditor.Undo.RecordObject(obj.transform, RESET_COMMAND_NAME);
  1568. obj.transform.position = pose.position;
  1569. obj.transform.localRotation = pose.localRotation;
  1570. obj.transform.localScale = pose.localScale;
  1571. obj.SetActive(true);
  1572. }
  1573. Copy(initialData);
  1574. }
  1575. public GameObject GetParent()
  1576. {
  1577. var parents = new System.Collections.Generic.List<GameObject>();
  1578. if (_objectIds.Count != _objects.Count) FindObjects();
  1579. var objList = objectList;
  1580. void GetParentList()
  1581. {
  1582. parents.Clear();
  1583. foreach (var obj in objList)
  1584. {
  1585. if (obj.transform.parent != null)
  1586. {
  1587. if (parents.Contains(obj.transform.parent.gameObject)) continue;
  1588. parents.Add(obj.transform.parent.gameObject);
  1589. }
  1590. else
  1591. {
  1592. parents.Clear();
  1593. return;
  1594. }
  1595. }
  1596. }
  1597. do
  1598. {
  1599. GetParentList();
  1600. objList = parents.ToList();
  1601. }
  1602. while (parents.Count > 1);
  1603. if (parents.Count == 0) return null;
  1604. return parents[0];
  1605. }
  1606. #endregion
  1607. #region CONTROL POINTS
  1608. [SerializeField]
  1609. protected System.Collections.Generic.List<CONTROL_POINT> _controlPoints
  1610. = new System.Collections.Generic.List<CONTROL_POINT>();
  1611. private int _selectedPointIdx = -1;
  1612. protected System.Collections.Generic.List<int> _selection = new System.Collections.Generic.List<int>();
  1613. protected Vector3[] _pointPositions = null;
  1614. private static string _commandName = null;
  1615. public const string RESET_COMMAND_NAME = "Reset persistent pose";
  1616. public static string COMMAND_NAME
  1617. {
  1618. get
  1619. {
  1620. if (_commandName == null) _commandName = "Edit " + (new TOOL_NAME()).value;
  1621. return _commandName;
  1622. }
  1623. }
  1624. public Vector3[] points => _pointPositions;
  1625. public int pointsCount => _pointPositions.Length;
  1626. public Vector3 GetPoint(int idx)
  1627. {
  1628. if (idx < 0) idx += _pointPositions.Length;
  1629. return _pointPositions[idx];
  1630. }
  1631. public Vector3 selectedPoint => _pointPositions[_selectedPointIdx];
  1632. public bool ControlPointIsSelected(int idx) => _selection.Contains(idx);
  1633. public CONTROL_POINT[] controlPoints => _controlPoints.ToArray();
  1634. public int selectionCount => _selection.Count;
  1635. public virtual bool SetPoint(int idx, Vector3 value, bool registerUndo, bool selectAll, bool moveSelection = true)
  1636. {
  1637. if (_pointPositions.Length <= 1) Initialize();
  1638. if (idx < 0 || idx >= _pointPositions.Length) return false;
  1639. if (_pointPositions[idx] == value) return false;
  1640. if (registerUndo) ToolProperties.RegisterUndo(COMMAND_NAME);
  1641. var delta = value - _pointPositions[idx];
  1642. _pointPositions[idx] = _controlPoints[idx].position = value;
  1643. var selection = _selection.ToArray();
  1644. if (!moveSelection) return true;
  1645. if (selectAll)
  1646. {
  1647. selection = new int[_controlPoints.Count];
  1648. for (int i = 0; i < selection.Length; ++i) selection[i] = i;
  1649. }
  1650. foreach (var selectedIdx in selection)
  1651. {
  1652. if (selectedIdx == idx) continue;
  1653. _controlPoints[selectedIdx].position += delta;
  1654. _pointPositions[selectedIdx] = _controlPoints[selectedIdx].position;
  1655. }
  1656. return true;
  1657. }
  1658. public void AddDeltaToSelection(Vector3 delta)
  1659. {
  1660. foreach (var selectedIdx in _selection)
  1661. {
  1662. _controlPoints[selectedIdx].position += delta;
  1663. _pointPositions[selectedIdx] = _controlPoints[selectedIdx].position;
  1664. }
  1665. }
  1666. public void AddValue(int idx, Vector3 value)
  1667. {
  1668. ToolProperties.RegisterUndo(COMMAND_NAME);
  1669. _controlPoints[idx].position += value;
  1670. _pointPositions[idx] = _controlPoints[idx].position;
  1671. }
  1672. protected virtual void UpdatePoints(bool deserializing = false)
  1673. => _pointPositions = ControlPoint.PointArrayToVectorArray(_controlPoints.ToArray());
  1674. public void RemoveSelectedPoints()
  1675. {
  1676. if (_selectedPointIdx == -1)
  1677. {
  1678. _selection.Clear();
  1679. return;
  1680. }
  1681. RemovePoints(_selection.ToArray());
  1682. }
  1683. public void RemovePoint(int idx)
  1684. {
  1685. ToolProperties.RegisterUndo(COMMAND_NAME);
  1686. if (_controlPoints.Count <= 2)
  1687. {
  1688. Initialize();
  1689. return;
  1690. }
  1691. _controlPoints.RemoveAt(idx);
  1692. if (_selectedPointIdx == idx) _selectedPointIdx = -1;
  1693. RemoveFromSelection(idx);
  1694. UpdatePoints();
  1695. }
  1696. public void RemovePoints(int[] indexes)
  1697. {
  1698. ToolProperties.RegisterUndo(COMMAND_NAME);
  1699. var toRemove = new System.Collections.Generic.List<int>(indexes);
  1700. toRemove.Sort();
  1701. if (toRemove.Count >= _pointPositions.Length - 1)
  1702. {
  1703. Initialize();
  1704. return;
  1705. }
  1706. for (int i = toRemove.Count - 1; i >= 0; --i) _controlPoints.RemoveAt(toRemove[i]);
  1707. _selectedPointIdx = -1;
  1708. _selection.Clear();
  1709. UpdatePoints();
  1710. }
  1711. public void InsertPoint(int idx, CONTROL_POINT point)
  1712. {
  1713. if (idx < 0) return;
  1714. idx = Mathf.Max(idx, 1);
  1715. ToolProperties.RegisterUndo(COMMAND_NAME);
  1716. _controlPoints.Insert(idx, point);
  1717. UpdatePoints();
  1718. }
  1719. protected void AddPoint(CONTROL_POINT point, bool registerUndo = true)
  1720. {
  1721. if (registerUndo) ToolProperties.RegisterUndo(COMMAND_NAME);
  1722. _controlPoints.Add(point);
  1723. UpdatePoints();
  1724. }
  1725. protected void AddPointRange(System.Collections.Generic.IEnumerable<CONTROL_POINT> collection)
  1726. {
  1727. ToolProperties.RegisterUndo(COMMAND_NAME);
  1728. _controlPoints.AddRange(collection);
  1729. UpdatePoints();
  1730. }
  1731. protected void PointsRemoveRange(int index, int count)
  1732. {
  1733. ToolProperties.RegisterUndo(COMMAND_NAME);
  1734. _controlPoints.RemoveRange(index, count);
  1735. UpdatePoints();
  1736. }
  1737. protected CONTROL_POINT[] PointsGetRange(int index, int count) => _controlPoints.GetRange(index, count).ToArray();
  1738. public int selectedPointIdx
  1739. {
  1740. get
  1741. {
  1742. if (_selectedPointIdx >= _pointPositions.Length) ClearSelection();
  1743. return _selectedPointIdx;
  1744. }
  1745. set
  1746. {
  1747. if (_selectedPointIdx == value) return;
  1748. _selectedPointIdx = value;
  1749. }
  1750. }
  1751. public void AddToSelection(int idx)
  1752. {
  1753. if (!_selection.Contains(idx)) _selection.Add(idx);
  1754. }
  1755. public void SelectAll()
  1756. {
  1757. _selection.Clear();
  1758. for (int i = 0; i < pointsCount; ++i) _selection.Add(i);
  1759. if (_selectedPointIdx < 0) _selectedPointIdx = 0;
  1760. }
  1761. public bool AllPointsAreSelected() => _selection.Count == pointsCount;
  1762. public void RemoveFromSelection(int idx)
  1763. {
  1764. if (_selection.Contains(idx)) _selection.Remove(idx);
  1765. }
  1766. public void ClearSelection()
  1767. {
  1768. _selectedPointIdx = -1;
  1769. _selection.Clear();
  1770. isSelected = false;
  1771. }
  1772. public void Reset() => Initialize();
  1773. public Bounds GetBounds(float sizeMultiplier)
  1774. {
  1775. var max = BoundsUtils.MIN_VECTOR3;
  1776. var min = BoundsUtils.MAX_VECTOR3;
  1777. foreach (var point in _controlPoints)
  1778. {
  1779. max = Vector3.Max(max, point);
  1780. min = Vector3.Min(min, point);
  1781. }
  1782. var size = (max - min);
  1783. var center = size / 2 + min;
  1784. size *= sizeMultiplier;
  1785. return new Bounds(center, size);
  1786. }
  1787. #endregion
  1788. #region SETTINGS
  1789. [SerializeField] protected TOOL_SETTINGS _settings = new TOOL_SETTINGS();
  1790. public TOOL_SETTINGS settings { get => _settings; set => _settings = value; }
  1791. #endregion
  1792. #region STATE
  1793. [SerializeField] private ToolManager.ToolState _state = ToolManager.ToolState.NONE;
  1794. public virtual ToolManager.ToolState state
  1795. {
  1796. get => _state;
  1797. set
  1798. {
  1799. if (_state == value) return;
  1800. ToolProperties.RegisterUndo(COMMAND_NAME);
  1801. _state = value;
  1802. }
  1803. }
  1804. #endregion
  1805. #region COMMON
  1806. public string toolName => (new TOOL_NAME()).value;
  1807. protected virtual void Initialize()
  1808. {
  1809. _selectedPointIdx = -1;
  1810. _selection.Clear();
  1811. _state = ToolManager.ToolState.NONE;
  1812. _controlPoints.Clear();
  1813. UpdatePoints();
  1814. }
  1815. [SerializeField] protected long _initialBrushId = -1;
  1816. public PersistentData() => Initialize();
  1817. public PersistentData((GameObject, int)[] objects, long initialBrushId,
  1818. PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT> data)
  1819. {
  1820. Copy(data);
  1821. _name = data.name;
  1822. _settings = new TOOL_SETTINGS();
  1823. _settings.Copy(data._settings);
  1824. _id = nextId;
  1825. SetNextId();
  1826. _initialBrushId = initialBrushId;
  1827. _selectedPointIdx = -1;
  1828. _selection.Clear();
  1829. _state = ToolManager.ToolState.PERSISTENT;
  1830. if (objects == null || objects.Length == 0) return;
  1831. _poses = new System.Collections.Generic.List<ObjectPose>();
  1832. _objectIds = new System.Collections.Generic.List<ObjectId>();
  1833. _objects = new System.Collections.Generic.List<GameObject>();
  1834. AddObjects(objects);
  1835. }
  1836. public long initialBrushId => _initialBrushId;
  1837. public void SetInitialBrushId(long value) => _initialBrushId = value;
  1838. protected void Clone(PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT> clone)
  1839. {
  1840. if (clone == null) clone = new PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT>();
  1841. clone._id = id;
  1842. clone._controlPoints.Clear();
  1843. foreach (var point in _controlPoints)
  1844. {
  1845. var pointClone = new CONTROL_POINT();
  1846. pointClone.Copy(point);
  1847. clone._controlPoints.Add(pointClone);
  1848. }
  1849. clone._pointPositions = _pointPositions == null ? null : _pointPositions.ToArray();
  1850. clone._poses = _poses.ToList();
  1851. clone._objectIds = _objectIds.ToList();
  1852. clone._objects = _objects.ToList();
  1853. clone._initialBrushId = _initialBrushId;
  1854. clone.settings.Copy(_settings);
  1855. clone._selectedPointIdx = -1;
  1856. clone._selection.Clear();
  1857. }
  1858. public virtual void Copy(PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT> other)
  1859. {
  1860. _controlPoints.Clear();
  1861. foreach (var point in other._controlPoints)
  1862. {
  1863. var pointClone = new CONTROL_POINT();
  1864. pointClone.Copy(point);
  1865. _controlPoints.Add(pointClone);
  1866. }
  1867. _selectedPointIdx = other._selectedPointIdx;
  1868. _selection = other._selection.ToList();
  1869. _pointPositions = other._pointPositions == null ? null : other._pointPositions.ToArray();
  1870. _settings = other._settings;
  1871. _poses = _poses.ToList();
  1872. _objectIds = _objectIds.ToList();
  1873. _objects = _objects.ToList();
  1874. _initialBrushId = other._initialBrushId;
  1875. }
  1876. public virtual void Duplicate(PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT> other)
  1877. {
  1878. _controlPoints.Clear();
  1879. foreach (var point in other._controlPoints)
  1880. {
  1881. var pointClone = new CONTROL_POINT();
  1882. pointClone.Copy(point);
  1883. _controlPoints.Add(pointClone);
  1884. }
  1885. _selectedPointIdx = other._selectedPointIdx;
  1886. _selection = other._selection.ToList();
  1887. _pointPositions = other._pointPositions == null ? null : other._pointPositions.ToArray();
  1888. _settings = other._settings;
  1889. _initialBrushId = other._initialBrushId;
  1890. foreach (var obj in other._objects)
  1891. {
  1892. GameObject clone = null;
  1893. var prefabName = obj.name;
  1894. var prefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(obj);
  1895. if (prefab == null)
  1896. {
  1897. clone = GameObject.Instantiate(obj);
  1898. prefabName = obj.name;
  1899. }
  1900. else
  1901. {
  1902. clone = (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(prefab);
  1903. prefabName = prefab.name;
  1904. }
  1905. clone.transform.position = obj.transform.position;
  1906. clone.transform.rotation = obj.transform.rotation;
  1907. clone.transform.localScale = obj.transform.lossyScale;
  1908. clone.name = prefabName;
  1909. Transform surface = obj.transform.parent;
  1910. while (surface != null)
  1911. {
  1912. var compCount = surface.gameObject.GetComponents<Component>().Length;
  1913. if (compCount == 1) surface = surface.parent;
  1914. else break;
  1915. }
  1916. var settings = other.settings as IPaintToolSettings;
  1917. var parent = PWBIO.GetParent(settings, prefabName,
  1918. create: true, surface, hexId);
  1919. var commandName = "Duplicate item";
  1920. UnityEditor.Undo.RegisterCreatedObjectUndo(obj, commandName);
  1921. UnityEditor.Undo.SetTransformParent(clone.transform, parent, commandName);
  1922. AddPose(new ObjectId(clone), new ObjectPose(clone));
  1923. PWBIO.AddPaintedObject(clone);
  1924. }
  1925. }
  1926. private bool _deserializing = false;
  1927. protected bool deserializing { get => _deserializing; set => _deserializing = value; }
  1928. public void OnBeforeSerialize() { }
  1929. public void OnAfterDeserialize()
  1930. {
  1931. deserializing = true;
  1932. deserializing = false;
  1933. UpdatePoints(deserializing: true);
  1934. PWBIO.repaint = true;
  1935. }
  1936. #endregion
  1937. }
  1938. [System.Serializable]
  1939. public class SceneData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA>
  1940. where TOOL_NAME : IToolName, new()
  1941. where TOOL_SETTINGS : IToolSettings, new()
  1942. where CONTROL_POINT : ControlPoint, new()
  1943. where TOOL_DATA : PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT>, new()
  1944. {
  1945. [SerializeField] private string _sceneGUID = null;
  1946. [SerializeField] private System.Collections.Generic.List<TOOL_DATA> _items = null;
  1947. public string sceneGUID { get => _sceneGUID; set => _sceneGUID = value; }
  1948. public System.Collections.Generic.List<TOOL_DATA> items => _items;
  1949. public SceneData() { }
  1950. public SceneData(string sceneGUID) => _sceneGUID = sceneGUID;
  1951. public void AddItem(TOOL_DATA data)
  1952. {
  1953. if (_items == null) _items = new System.Collections.Generic.List<TOOL_DATA>();
  1954. _items.Add(data);
  1955. }
  1956. public void RemoveItemData(long itemId) => _items.RemoveAll(i => i.id == itemId);
  1957. public void DeleteItemData(long itemId, bool deleteObjects)
  1958. {
  1959. var item = GetItem(itemId);
  1960. if (item == null) return;
  1961. if (deleteObjects) item.DestroyGameObjects();
  1962. RemoveItemData(itemId);
  1963. }
  1964. public TOOL_DATA GetItem(long itemId) => _items.Find(i => i.id == itemId);
  1965. public GameObject[] GetParents(long itemId)
  1966. {
  1967. var parents = new System.Collections.Generic.HashSet<GameObject>();
  1968. var item = GetItem(itemId);
  1969. if (item == null) return parents.ToArray();
  1970. var objs = item.objects;
  1971. foreach (var obj in objs)
  1972. {
  1973. if (obj == null) continue;
  1974. if (obj.transform.parent == null) continue;
  1975. var parent = obj.transform.parent.gameObject;
  1976. if (parents.Contains(parent)) continue;
  1977. parents.Add(parent);
  1978. do
  1979. {
  1980. if (parent.transform.parent == null) parent = null;
  1981. else
  1982. {
  1983. parent = parent.transform.parent.gameObject;
  1984. if (!parents.Contains(parent)) parents.Add(parent);
  1985. }
  1986. }
  1987. while (parent != null);
  1988. }
  1989. return parents.ToArray();
  1990. }
  1991. }
  1992. #endregion
  1993. #endregion
  1994. }