TC_ItemBehaviour.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine.Events;
  6. // TODO: Fix method in select and mask node group, make distinct between layer and inside
  7. namespace TerrainComposer2
  8. {
  9. [ExecuteInEditMode]
  10. public class TC_ItemBehaviour : MonoBehaviour
  11. {
  12. [NonSerialized] public TC_ItemBehaviour parentItem;
  13. static public event RepaintAction DoRepaint;
  14. public delegate void RepaintAction();
  15. public float versionNumber = 0;
  16. public bool defaultPreset;
  17. public bool isLocked;
  18. public bool autoGenerate = true;
  19. public bool visible = true;
  20. public bool active = true;
  21. public int foldout = 2;
  22. public bool nodeFoldout = true;
  23. public int outputId;
  24. public int terrainLevel;
  25. public int level;
  26. public string notes;
  27. public int listIndex;
  28. public bool firstLoad;
  29. public TexturePreview preview = new TexturePreview();
  30. public RenderTexture rtDisplay, rtPreview;
  31. public RenderTexture rtPortal;
  32. public int isPortalCount = 0;
  33. public TC_ItemBehaviour portalNode;
  34. public List<TC_ItemBehaviour> usedAsPortalList;
  35. public Method method;
  36. public float opacity = 1;
  37. public bool abs = false;
  38. public Curve localCurve = new Curve();
  39. public Curve worldCurve = new Curve();
  40. public Transform t;
  41. public Transform parentOld;
  42. public int siblingIndexOld = -1;
  43. public CachedTransform ct = new CachedTransform();
  44. public CachedTransform ctOld = new CachedTransform();
  45. public Bounds bounds;
  46. public bool lockTransform, lockPosParent, lockPosChildren;
  47. public bool lockPosX = true, lockPosY = true, lockPosZ = true, lockRotY = true, lockScaleX = true, lockScaleY = true, lockScaleZ = true;
  48. public PositionMode positionMode;
  49. public float posY;
  50. public Vector3 posOffset;
  51. [NonSerialized] public DropPosition dropPosition;
  52. public bool controlDown;
  53. [SerializeField]int instanceID = 0;
  54. public void SetVersionNumber()
  55. {
  56. versionNumber = TC.GetVersionNumber();
  57. }
  58. public void Repaint()
  59. {
  60. if (DoRepaint != null) DoRepaint();
  61. }
  62. public void InitPreviewRenderTexture(bool assignRtDisplay = true, string name = "Preview")
  63. {
  64. TC_Compute.InitPreviewRenderTexture(ref rtPreview, name);
  65. if (assignRtDisplay) rtDisplay = rtPreview;
  66. }
  67. public virtual void Awake()
  68. {
  69. // Debug.Log("Awake");
  70. if (!firstLoad)
  71. {
  72. firstLoad = true;
  73. #if UNITY_EDITOR
  74. UnityEditor.EditorUtility.SetDirty(this);
  75. #endif
  76. }
  77. rtDisplay = null;
  78. rtPreview = null;
  79. t = transform;
  80. t.hasChanged = false;
  81. // Debug.Log("Awake " + name);
  82. // TCGenerate.singleton.AutoGenerate();
  83. // RemoveCloneText();
  84. DetectClone();
  85. }
  86. public void Lock(bool active)
  87. {
  88. if (active)
  89. {
  90. t.hideFlags = HideFlags.NotEditable;
  91. hideFlags = HideFlags.NotEditable;
  92. }
  93. else
  94. {
  95. t.hideFlags = HideFlags.None;
  96. hideFlags = HideFlags.None;
  97. }
  98. }
  99. void DetectClone()
  100. {
  101. // Detect duplicate
  102. if (instanceID == 0) { instanceID = GetInstanceID(); return; }
  103. if (instanceID != GetInstanceID() && GetInstanceID() < 0)
  104. {
  105. // Debug.Log("Detected Duplicate!");
  106. instanceID = GetInstanceID();
  107. CloneSetup();
  108. }
  109. }
  110. public virtual void CloneSetup()
  111. {
  112. RemoveCloneText();
  113. }
  114. public virtual void OnEnable()
  115. {
  116. // preview.Create(128);
  117. if (TC_Settings.instance == null) TC_Settings.GetInstance();
  118. }
  119. public void OnDisable()
  120. {
  121. // if (autoGenerate) TC_Generate.AutoGenerate();
  122. }
  123. public virtual void OnDestroy()
  124. {
  125. // RemovePortalNodes();
  126. RemoveFromPortalNode();
  127. DisposeTextures();
  128. // Debug.Log("Destroy");
  129. // TCGenerate.singleton.AutoGenerate();
  130. }
  131. public virtual void DisposeTextures()
  132. {
  133. rtDisplay = null;
  134. TC_Compute.DisposeRenderTexture(ref rtPreview);
  135. TC_Compute.DisposeRenderTexture(ref rtPortal);
  136. }
  137. void RemoveCloneText()
  138. {
  139. string name = t.name;
  140. int index = name.IndexOf("(");
  141. if (index != -1)
  142. {
  143. t.name = name.Remove(index);
  144. if (TC_Settings.instance.selectionOld != null)
  145. {
  146. index = TC_Settings.instance.selectionOld.GetSiblingIndex();
  147. t.SetSiblingIndex(index);
  148. }
  149. }
  150. }
  151. public virtual void OnTransformChildrenChanged()
  152. {
  153. // Debug.Log("Children " + name + " has changed "+TC.outputNames[outputId]);
  154. TC.RefreshOutputReferences(outputId, true);
  155. // GetItems(this);
  156. // TC_Generate.AutoGenerate();
  157. }
  158. public void SetLockPositionXZ(bool active)
  159. {
  160. if (active) ctOld.Copy(this);
  161. }
  162. //#if UNITY_EDITOR
  163. //public void OnDrawGizmosSelected()
  164. //{
  165. // if (GetType() == typeof(TC_SelectItemGroup) || GetType() == typeof(TC_SelectItem)) return;
  166. // if (UnityEditor.Selection.activeTransform == t)
  167. // {
  168. // Gizmos.DrawWireCube(bounds.center, bounds.size);
  169. // // if (GetType() == typeof(TCNode)) Debug.Log(bounds.size);
  170. // }
  171. //}
  172. //#endif
  173. public virtual void ChangeYPosition(float y) { }
  174. public virtual void SetLockChildrenPosition(bool lockPos) { }
  175. public virtual void UpdateTransforms() { }
  176. public void ResetPosition()
  177. {
  178. t.localPosition = Vector3.zero;
  179. // t.localRotation = Quaternion.identity;
  180. // t.localScale = Vector3.one;
  181. }
  182. public void ResetPositionCompensateChildren()
  183. {
  184. GameObject go = new GameObject();
  185. Transform child;
  186. int childCount = t.childCount;
  187. for (int i = 0; i < childCount; i++)
  188. {
  189. child = t.GetChild(0);
  190. child.parent = go.transform;
  191. }
  192. t.localPosition = Vector3.zero;
  193. for (int i = 0; i < childCount; i++)
  194. {
  195. child = go.transform.GetChild(0);
  196. child.parent = transform;
  197. }
  198. DestroyImmediate(go);
  199. }
  200. public virtual void DestroyMe(bool undo)
  201. {
  202. // Debug.Log("Destroy");
  203. #if UNITY_EDITOR
  204. if (undo) UnityEditor.Undo.DestroyObjectImmediate(gameObject); else DestroyImmediate(gameObject);
  205. #else
  206. Destroy(gameObject);
  207. #endif
  208. }
  209. public virtual MonoBehaviour Add<T>(string label, bool addSameLevel, bool addBefore = false, bool makeSelection = false, int startIndex = 1) where T : TC_ItemBehaviour
  210. {
  211. GameObject newItemGo = new GameObject();
  212. Transform newItemT = newItemGo.transform;
  213. Type type = typeof(T);
  214. if (label == "")
  215. {
  216. if (type == typeof(TC_LayerGroup)) label = "Layer Group";
  217. else if (type == typeof(TC_Layer)) label = "Layer";
  218. else if (type == typeof(TC_Node)) label = "Node";
  219. else if (type == typeof(TC_SelectItem)) label = "Item";
  220. else if (type == typeof(TC_SelectItemGroup)) label = "Item Group";
  221. }
  222. // Debug.Log("Add " + label);
  223. newItemT.name = label;
  224. #if UNITY_EDITOR
  225. if (makeSelection) UnityEditor.Selection.activeTransform = newItemT;
  226. #endif
  227. int index;
  228. TC_ItemBehaviour item = newItemGo.AddComponent<T>();
  229. // Version number
  230. item.SetVersionNumber();
  231. item.outputId = outputId;
  232. if (addSameLevel)
  233. {
  234. newItemT.parent = t.parent;
  235. index = t.GetSiblingIndex() + (addBefore ? 1 : 0);
  236. newItemT.SetSiblingIndex(index);
  237. }
  238. else
  239. {
  240. if (type == typeof(TC_SelectItemGroup)) { startIndex = 2; }
  241. newItemT.parent = t;
  242. newItemT.SetSiblingIndex(index = startIndex);
  243. }
  244. if (newItemT.parent != null) newItemT.localPosition = Vector3.zero;
  245. if (type == typeof(TC_Node)) ((TC_Node)item).SetDefaultSettings();
  246. else if (type == typeof(TC_LayerGroup))
  247. {
  248. if (outputId != TC.heightOutput && outputId != TC.grassOutput) item.method = Method.Lerp;
  249. item.Add<TC_NodeGroup>("Mask Group", false);
  250. item.Add<TC_LayerGroupResult>("Result", false);
  251. }
  252. else if (type == typeof(TC_Layer))
  253. {
  254. if (outputId != TC.heightOutput && outputId != TC.grassOutput) item.method = Method.Lerp;
  255. AddLayerNodeGroups((TC_Layer)item);
  256. }
  257. return item;
  258. }
  259. public void AddLayerNodeGroups(TC_Layer layer)
  260. {
  261. layer.Add<TC_NodeGroup>("Mask Group", false);
  262. TC_NodeGroup selectNodeGroup = (TC_NodeGroup)layer.Add<TC_NodeGroup>("Select Group", false);
  263. selectNodeGroup.Add<TC_Node>("", false, false, false);
  264. layer.Add<TC_SelectItemGroup>("", false);
  265. }
  266. public T GetGroup<T>(int index, bool refresh, bool resetTextures) where T : TC_GroupBehaviour
  267. {
  268. if (resetTextures) DisposeTextures();
  269. if (index >= t.childCount)
  270. {
  271. TC.MoveToDustbin(t);
  272. return null;
  273. }
  274. Transform child = t.GetChild(index);
  275. T group = child.GetComponent<T>();
  276. if (group == null)
  277. {
  278. TC.MoveToDustbin(t);
  279. }
  280. else
  281. {
  282. group.SetParameters(this, index);
  283. group.GetItems(refresh, resetTextures, true);
  284. }
  285. return group;
  286. }
  287. public void SetParameters(TC_ItemBehaviour parentItem, int index)
  288. {
  289. this.parentItem = parentItem;
  290. level = parentItem.level + 1;
  291. outputId = parentItem.outputId;
  292. listIndex = index;
  293. }
  294. public TC_ItemBehaviour Duplicate(Transform parent)
  295. {
  296. // Debug.Log("Duplicate");
  297. GameObject newGo = (GameObject)Instantiate(gameObject, t.position, t.rotation);
  298. Transform newT = newGo.transform;
  299. newT.parent = parent;
  300. if (dropPosition == DropPosition.Left) newT.SetSiblingIndex(t.GetSiblingIndex() - 1);
  301. else newT.SetSiblingIndex(t.GetSiblingIndex());
  302. newT.localScale = t.localScale;
  303. TC_ItemBehaviour item = newGo.GetComponent<TC_ItemBehaviour>();
  304. item.usedAsPortalList = null;
  305. item.isPortalCount = 0;
  306. if (item.portalNode != null)
  307. {
  308. item.portalNode.usedAsPortalList.Add(item);
  309. item.portalNode.isPortalCount++;
  310. }
  311. #if UNITY_EDITOR
  312. UnityEditor.Selection.activeObject = newGo;
  313. UnityEditor.Undo.RegisterCreatedObjectUndo(newGo, "Duplicate " + newGo.name);
  314. #endif
  315. return item;
  316. }
  317. public void RemovePortalNodes()
  318. {
  319. if (usedAsPortalList == null || usedAsPortalList.Count == 0) return;
  320. for (int i = 0; i < usedAsPortalList.Count; i++)
  321. {
  322. usedAsPortalList[i].portalNode = null;
  323. }
  324. usedAsPortalList.Clear();
  325. }
  326. public void RemoveFromPortalNode()
  327. {
  328. if (portalNode == null) return;
  329. if (portalNode.isPortalCount > 0)
  330. {
  331. portalNode.isPortalCount--;
  332. portalNode.usedAsPortalList.Remove(this);
  333. if (portalNode.isPortalCount == 0) TC_Compute.DisposeRenderTexture(ref portalNode.rtPortal);
  334. }
  335. else portalNode.isPortalCount = 0;
  336. }
  337. public void CopyTransform(TC_ItemBehaviour item)
  338. {
  339. t.position = item.t.position;
  340. t.rotation = item.t.rotation;
  341. t.localScale = item.t.localScale;
  342. }
  343. public virtual void GetItems(bool refresh, bool rebuildGlobalLists, bool resetTextures) { }
  344. public virtual void SetFirstLoad(bool active)
  345. {
  346. firstLoad = active;
  347. }
  348. public virtual bool ContainsCollisionNode() { return false; }
  349. }
  350. [Serializable]
  351. public class Curve
  352. {
  353. public bool active;
  354. public Vector2 range = new Vector2(0, 1);
  355. public AnimationCurve curve = AnimationCurve.Linear(0, 0, 1, 1);
  356. public Vector4[] c;
  357. public float[] curveKeys;
  358. public int length;
  359. public float Calc(float v)
  360. {
  361. return curve.Evaluate(v) * v;
  362. }
  363. public void ConvertCurve(float scale = 1)
  364. {
  365. if (curve.keys.Length < 2 || !active) { length = 0; return; }
  366. length = curve.keys.Length;
  367. c = new Vector4[curve.length - 1];
  368. curveKeys = new float[curve.length];
  369. // Reporter.Log("Convert curve "+c.Length+", "+curveKeys.Length);
  370. float p1x, p1y, tp1, p2x, p2y, tp2;
  371. for (int i = 0; i < c.Length; i++)
  372. {
  373. p1x = curve.keys[i].time;
  374. p1y = curve.keys[i].value * scale;
  375. tp1 = curve.keys[i].outTangent;
  376. p2x = curve.keys[i + 1].time;
  377. p2y = curve.keys[i + 1].value * scale;
  378. tp2 = curve.keys[i + 1].inTangent;
  379. c[i].x = (p1x * tp1 + p1x * tp2 - p2x * tp1 - p2x * tp2 - 2 * p1y + 2 * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x);
  380. c[i].y = ((-p1x * p1x * tp1 - 2 * p1x * p1x * tp2 + 2 * p2x * p2x * tp1 + p2x * p2x * tp2 - p1x * p2x * tp1 + p1x * p2x * tp2 + 3 * p1x * p1y - 3 * p1x * p2y + 3 * p1y * p2x - 3 * p2x * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x));
  381. c[i].z = ((p1x * p1x * p1x * tp2 - p2x * p2x * p2x * tp1 - p1x * p2x * p2x * tp1 - 2 * p1x * p2x * p2x * tp2 + 2 * p1x * p1x * p2x * tp1 + p1x * p1x * p2x * tp2 - 6 * p1x * p1y * p2x + 6 * p1x * p2x * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x));
  382. c[i].w = ((p1x * p2x * p2x * p2x * tp1 - p1x * p1x * p2x * p2x * tp1 + p1x * p1x * p2x * p2x * tp2 - p1x * p1x * p1x * p2x * tp2 - p1y * p2x * p2x * p2x + p1x * p1x * p1x * p2y + 3 * p1x * p1y * p2x * p2x - 3 * p1x * p1x * p2x * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x));
  383. }
  384. for (int i = 0; i < curveKeys.Length; i++) curveKeys[i] = curve.keys[i].time;
  385. // Reporter.Log(p1x + ", " + p1y + ", " + tp1 + ", " + p2x + ", " + p2y + ", " + tp2);
  386. // Reporter.Log("Evaluate Unity: " + anim.Evaluate(0.1f) + ", " + anim.Evaluate(0.2f) + ", " + anim.Evaluate(0.3f) + ", " + anim.Evaluate(0.4f) + ", " + anim.Evaluate(0.5f) + ", " + anim.Evaluate(0.6f) + ", " + anim.Evaluate(0.76f) + ", " + anim.Evaluate(0.88f) + ", " + anim.Evaluate(0.98f));
  387. // Reporter.Log("Evaluate Cubic: " + Evaluate(0.1f) + ", " + Evaluate(0.2f) + ", " + Evaluate(0.3f) + ", " + Evaluate(0.4f) + ", " + Evaluate(0.5f) + ", " + Evaluate(0.6f) + ", " + Evaluate(0.76f) + ", " + Evaluate(0.88f) + ", " + anim.Evaluate(0.98f));
  388. }
  389. }
  390. }