TilePainter.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. using System;
  2. using System.IO;
  3. using System.Collections;
  4. using UnityEngine;
  5. using System.Collections.Generic;
  6. #if UNITY_EDITOR
  7. using UnityEditor;
  8. #endif
  9. [RequireComponent(typeof(BoxCollider))]
  10. public class TilePainter : MonoBehaviour{
  11. public int gridsize = 1;
  12. public int width = 20;
  13. public int height = 20;
  14. public GameObject tiles;
  15. private bool _changed = true;
  16. public Vector3 cursor;
  17. public bool focused = false;
  18. public GameObject[,] tileobs;
  19. int colidx = 0;
  20. public List<UnityEngine.Object> palette = new List<UnityEngine.Object>();
  21. public UnityEngine.Object color = null;
  22. Quaternion color_rotation;
  23. #if UNITY_EDITOR
  24. private static bool IsAssetAFolder(UnityEngine.Object obj){
  25. string path = "";
  26. if (obj == null){return false;}
  27. path = AssetDatabase.GetAssetPath(obj.GetInstanceID());
  28. if (path.Length > 0){
  29. if (Directory.Exists(path)){
  30. return true;
  31. }else{
  32. return false;}
  33. }
  34. return false;
  35. }
  36. public void Encode(){
  37. }
  38. static GameObject CreatePrefab(UnityEngine.Object fab, Vector3 pos, Quaternion rot) {
  39. GameObject o = PrefabUtility.InstantiatePrefab(fab as GameObject) as GameObject;
  40. if (o == null){
  41. Debug.Log(IsAssetAFolder(fab));
  42. return o;}
  43. o.transform.position = pos;
  44. o.transform.rotation = rot;
  45. return o;
  46. }
  47. public void Restore(){
  48. Transform palt = transform.Find("palette");
  49. if (palt != null){GameObject.DestroyImmediate(palt.gameObject);}
  50. GameObject pal = new GameObject("palette");
  51. pal.hideFlags = HideFlags.HideInHierarchy;
  52. BoxCollider bc = pal.AddComponent<BoxCollider>();
  53. bc.size = new Vector3(palette.Count*gridsize, gridsize, 0f);
  54. bc.center = new Vector3((palette.Count-1f)*gridsize*0.5f, 0f, 0f);
  55. pal.transform.parent = this.gameObject.transform;
  56. pal.transform.localPosition = new Vector3(0f, -gridsize*2, 0f);
  57. pal.transform.rotation = transform.rotation;
  58. int palette_folder = -1;
  59. for (int i = 0; i < palette.Count; i++){
  60. UnityEngine.Object o = palette[i];
  61. if (IsAssetAFolder(o)){
  62. palette_folder = i;
  63. }
  64. else {
  65. if (o != null){
  66. GameObject g = CreatePrefab(o, new Vector3() , transform.rotation);
  67. g.transform.parent = pal.transform;
  68. g.transform.localPosition = new Vector3(i*gridsize, 0f, 0f);
  69. }
  70. }
  71. }
  72. if (palette_folder != -1){
  73. string path = AssetDatabase.GetAssetPath(palette[palette_folder].GetInstanceID());
  74. path = path.Trim().Replace("Assets/Resources/", "");
  75. palette.RemoveAt(palette_folder);
  76. UnityEngine.Object[] contents = (UnityEngine.Object[]) Resources.LoadAll(path);
  77. foreach (UnityEngine.Object o in contents){
  78. if (!palette.Contains(o)){palette.Add(o);}
  79. }
  80. Restore();
  81. }
  82. tileobs = new GameObject[width, height];
  83. if (tiles == null){
  84. tiles = new GameObject("tiles");
  85. tiles.transform.parent = this.gameObject.transform;
  86. tiles.transform.localPosition = new Vector3();
  87. }
  88. int cnt = tiles.transform.childCount;
  89. List<GameObject> trash = new List<GameObject>();
  90. for (int i = 0; i < cnt; i++){
  91. GameObject tile = tiles.transform.GetChild(i).gameObject;
  92. Vector3 tilepos = tile.transform.localPosition;
  93. int X = (int)(tilepos.x / gridsize);
  94. int Y = (int)(tilepos.y / gridsize);
  95. if (ValidCoords(X, Y)){
  96. tileobs[X, Y] = tile;
  97. } else {
  98. trash.Add(tile);
  99. }
  100. }
  101. for (int i = 0; i < trash.Count; i++){
  102. if (Application.isPlaying){Destroy(trash[i]);} else {DestroyImmediate(trash[i]);}}
  103. if (color == null){
  104. if (palette.Count > 0){
  105. color = palette[0];
  106. }
  107. }
  108. }
  109. public void Resize(){
  110. transform.localScale = new Vector3(1,1,1);
  111. if (_changed){
  112. _changed = false;
  113. Restore();
  114. }
  115. }
  116. public void Awake(){
  117. Restore();
  118. }
  119. public void OnEnable(){
  120. Restore();
  121. }
  122. void OnValidate(){
  123. _changed = true;
  124. BoxCollider bounds = this.GetComponent<BoxCollider>();
  125. bounds.center = new Vector3((width*gridsize)*0.5f-gridsize*0.5f, (height*gridsize)*0.5f-gridsize*0.5f, 0f);
  126. bounds.size = new Vector3(width*gridsize, (height*gridsize), 0f);
  127. }
  128. public Vector3 GridV3(Vector3 pos){
  129. Vector3 p = transform.InverseTransformPoint(pos) + new Vector3(gridsize*0.5f,gridsize*0.5f, 0f);
  130. return new Vector3((int)(p.x/gridsize), (int)(p.y/gridsize), 0);
  131. }
  132. public bool ValidCoords(int x, int y){
  133. if (tileobs == null) {return false;}
  134. return (x >= 0 && y >= 0 && x < tileobs.GetLength(0) && y < tileobs.GetLength(1));
  135. }
  136. public void CycleColor(){
  137. colidx += 1;
  138. if (colidx >= palette.Count){
  139. colidx = 0;
  140. }
  141. color = (UnityEngine.Object)palette[colidx];
  142. }
  143. public void Turn(){
  144. if (this.ValidCoords((int)cursor.x, (int)cursor.y)){
  145. GameObject o = tileobs[(int)cursor.x, (int)cursor.y];
  146. if (o != null){
  147. o.transform.Rotate(0f, 0f, 90f);
  148. }
  149. }
  150. }
  151. public Vector3 Local(Vector3 p){
  152. return this.transform.TransformPoint(p);
  153. }
  154. public UnityEngine.Object PrefabSource(GameObject o){
  155. if (o == null)
  156. {
  157. return null;
  158. }
  159. UnityEngine.Object fab = PrefabUtility.GetCorrespondingObjectFromSource(o);
  160. if (fab == null)
  161. {
  162. fab = Resources.Load(o.name);
  163. }
  164. if (fab == null)
  165. {
  166. fab = palette[0];
  167. }
  168. return fab;
  169. }
  170. public void Drag(Vector3 mouse, TileLayerEditor.TileOperation op){
  171. Resize();
  172. if (tileobs == null){Restore();}
  173. if (this.ValidCoords((int)cursor.x, (int)cursor.y)){
  174. if (op == TileLayerEditor.TileOperation.Sampling){
  175. UnityEngine.Object s = PrefabSource(tileobs[(int)cursor.x, (int)cursor.y]);
  176. Debug.Log(s);
  177. if (s != null){
  178. color = s;
  179. color_rotation = tileobs[(int)cursor.x, (int)cursor.y].transform.localRotation;
  180. }
  181. } else {
  182. DestroyImmediate(tileobs[(int)cursor.x, (int)cursor.y]);
  183. if (op == TileLayerEditor.TileOperation.Drawing){
  184. if (color == null){return;}
  185. GameObject o = CreatePrefab(color, new Vector3() , color_rotation);
  186. o.transform.parent = tiles.transform;
  187. o.transform.localPosition = (cursor*gridsize);
  188. o.transform.localRotation = color_rotation;
  189. tileobs[(int)cursor.x, (int)cursor.y] = o;
  190. }
  191. }
  192. } else {
  193. if (op == TileLayerEditor.TileOperation.Sampling){
  194. if (cursor.y == -1 && cursor.x >= 0 && cursor.x < palette.Count){
  195. color = palette[(int)cursor.x];
  196. color_rotation = Quaternion.identity;
  197. }
  198. }
  199. }
  200. }
  201. public void Clear(){
  202. tileobs = new GameObject[width, height];
  203. DestroyImmediate(tiles);
  204. tiles = new GameObject("tiles");
  205. tiles.transform.parent = gameObject.transform;
  206. tiles.transform.localPosition = new Vector3();
  207. }
  208. public void OnDrawGizmos(){
  209. Gizmos.color = Color.white;
  210. Gizmos.matrix = transform.localToWorldMatrix;
  211. if (focused){
  212. Gizmos.color = new Color(1f,0f,0f,0.6f);
  213. Gizmos.DrawRay((cursor*gridsize)+Vector3.forward*-49999f, Vector3.forward*99999f);
  214. Gizmos.DrawRay((cursor*gridsize)+Vector3.right*-49999f, Vector3.right*99999f);
  215. Gizmos.DrawRay((cursor*gridsize)+Vector3.up*-49999f, Vector3.up*99999f);
  216. Gizmos.color = Color.yellow;
  217. }
  218. Gizmos.DrawWireCube( new Vector3((width*gridsize)*0.5f-gridsize*0.5f, (height*gridsize)*0.5f-gridsize*0.5f, 0f),
  219. new Vector3(width*gridsize, (height*gridsize), 0f));
  220. }
  221. #endif
  222. }
  223. #if UNITY_EDITOR
  224. [CustomEditor(typeof(TilePainter))]
  225. public class TileLayerEditor : Editor{
  226. public enum TileOperation {None, Drawing, Erasing, Sampling};
  227. private TileOperation operation;
  228. public override void OnInspectorGUI () {
  229. TilePainter me = (TilePainter)target;
  230. GUILayout.Label("Assign a prefab to the color property");
  231. GUILayout.Label("or the pallete array.");
  232. GUILayout.Label("drag : paint tiles");
  233. GUILayout.Label("[s]+click : sample tile color");
  234. GUILayout.Label("[x]+drag : erase tiles");
  235. GUILayout.Label("[space] : rotate tile");
  236. GUILayout.Label("[b] : cycle color");
  237. if(GUILayout.Button("CLEAR")){
  238. me.Clear();}
  239. DrawDefaultInspector();}
  240. private bool AmHovering(Event e){
  241. TilePainter me = (TilePainter)target;
  242. RaycastHit hit;
  243. if (Physics.Raycast(HandleUtility.GUIPointToWorldRay(Event.current.mousePosition), out hit, Mathf.Infinity) &&
  244. hit.collider.GetComponentInParent<TilePainter>() == me)
  245. {
  246. me.cursor = me.GridV3(hit.point);
  247. me.focused = true;
  248. Renderer rend = me.gameObject.GetComponentInChildren<Renderer>( );
  249. if( rend ) EditorUtility.SetSelectedRenderState( rend, EditorSelectedRenderState.Wireframe );
  250. return true;
  251. }
  252. me.focused = false;
  253. return false;
  254. }
  255. public void ProcessEvents(){
  256. TilePainter me = (TilePainter)target;
  257. int controlID = GUIUtility.GetControlID(1778, FocusType.Passive);
  258. EditorWindow currentWindow = EditorWindow.mouseOverWindow;
  259. if(currentWindow && AmHovering(Event.current)){
  260. Event current = Event.current;
  261. bool leftbutton = (current.button == 0);
  262. switch(current.type){
  263. case EventType.KeyDown:
  264. if (current.keyCode == KeyCode.S) operation = TileOperation.Sampling;
  265. if (current.keyCode == KeyCode.X) operation = TileOperation.Erasing;
  266. current.Use();
  267. return;
  268. case EventType.KeyUp:
  269. operation = TileOperation.None;
  270. if (current.keyCode == KeyCode.Space) me.Turn();
  271. if (current.keyCode == KeyCode.B) me.CycleColor();
  272. current.Use();
  273. return;
  274. case EventType.MouseDown:
  275. if (leftbutton)
  276. {
  277. if (operation == TileOperation.None){
  278. operation = TileOperation.Drawing;
  279. }
  280. me.Drag(current.mousePosition, operation);
  281. current.Use();
  282. return;
  283. }
  284. break;
  285. case EventType.MouseDrag:
  286. if (leftbutton)
  287. {
  288. if (operation != TileOperation.None){
  289. me.Drag(current.mousePosition, operation);
  290. current.Use();
  291. }
  292. return;
  293. }
  294. break;
  295. case EventType.MouseUp:
  296. if (leftbutton)
  297. {
  298. operation = TileOperation.None;
  299. current.Use();
  300. return;
  301. }
  302. break;
  303. case EventType.MouseMove:
  304. me.Resize();
  305. current.Use();
  306. break;
  307. case EventType.Repaint:
  308. break;
  309. case EventType.Layout:
  310. HandleUtility.AddDefaultControl(controlID);
  311. break;
  312. }
  313. }
  314. }
  315. void OnSceneGUI (){
  316. ProcessEvents();
  317. }
  318. void DrawEvents(){
  319. Handles.BeginGUI();
  320. Handles.EndGUI();
  321. }}
  322. #endif