OverlapWFC.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. using System;
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. #if UNITY_EDITOR
  5. using UnityEditor;
  6. #endif
  7. [ExecuteInEditMode]
  8. class OverlapWFC : MonoBehaviour{
  9. public Training training = null;
  10. public int gridsize = 1;
  11. public int width = 20;
  12. public int depth = 20;
  13. public int seed = 0;
  14. //[HideInInspector]
  15. public int N = 2;
  16. public bool periodicInput = false;
  17. public bool periodicOutput = false;
  18. public int symmetry = 1;
  19. public int foundation = 0;
  20. public int iterations = 0;
  21. public bool incremental = false;
  22. public OverlappingModel model = null;
  23. public GameObject[,] rendering;
  24. public GameObject output;
  25. private Transform group;
  26. private bool undrawn = true;
  27. public static bool IsPrefabRef(UnityEngine.Object o){
  28. #if UNITY_EDITOR
  29. return PrefabUtility.GetOutermostPrefabInstanceRoot(o) != null;
  30. #else
  31. return true;
  32. #endif
  33. }
  34. static GameObject CreatePrefab(UnityEngine.Object fab, Vector3 pos, Quaternion rot) {
  35. #if UNITY_EDITOR
  36. GameObject e = PrefabUtility.InstantiatePrefab(fab as GameObject) as GameObject;
  37. e.transform.position = pos;
  38. e.transform.rotation = rot;
  39. return e;
  40. #else
  41. GameObject o = GameObject.Instantiate(fab as GameObject) as GameObject;
  42. o.transform.position = pos;
  43. o.transform.rotation = rot;
  44. return o;
  45. #endif
  46. }
  47. public void Clear(){
  48. if (group != null){
  49. if (Application.isPlaying){Destroy(group.gameObject);} else {
  50. DestroyImmediate(group.gameObject);
  51. }
  52. group = null;
  53. }
  54. }
  55. void Awake(){}
  56. void Start(){
  57. Generate();
  58. }
  59. void Update(){
  60. if (incremental){
  61. Run();
  62. }
  63. }
  64. public void Generate() {
  65. if (training == null){Debug.Log("Can't Generate: no designated Training component");}
  66. if (IsPrefabRef(training.gameObject)){
  67. GameObject o = CreatePrefab(training.gameObject, new Vector3(0,99999f,0f), Quaternion.identity);
  68. training = o.GetComponent<Training>();
  69. }
  70. if (training.sample == null){
  71. training.Compile();
  72. }
  73. if (output == null){
  74. Transform ot = transform.Find("output-overlap");
  75. if (ot != null){output = ot.gameObject;}}
  76. if (output == null){
  77. output = new GameObject("output-overlap");
  78. output.transform.parent = transform;
  79. output.transform.position = this.gameObject.transform.position;
  80. output.transform.rotation = this.gameObject.transform.rotation;}
  81. for (int i = 0; i < output.transform.childCount; i++){
  82. GameObject go = output.transform.GetChild(i).gameObject;
  83. if (Application.isPlaying){Destroy(go);} else {DestroyImmediate(go);}
  84. }
  85. group = new GameObject(training.gameObject.name).transform;
  86. group.parent = output.transform;
  87. group.position = output.transform.position;
  88. group.rotation = output.transform.rotation;
  89. group.localScale = new Vector3(1f, 1f, 1f);
  90. rendering = new GameObject[width, depth];
  91. model = new OverlappingModel(training.sample, N, width, depth, periodicInput, periodicOutput, symmetry, foundation);
  92. undrawn = true;
  93. }
  94. void OnDrawGizmos(){
  95. Gizmos.color = Color.cyan;
  96. Gizmos.matrix = transform.localToWorldMatrix;
  97. Gizmos.DrawWireCube(new Vector3(width*gridsize/2f-gridsize*0.5f, depth*gridsize/2f-gridsize*0.5f, 0f),
  98. new Vector3(width*gridsize, depth*gridsize, gridsize));
  99. }
  100. public void Run(){
  101. if (model == null){return;}
  102. if (undrawn == false) { return; }
  103. if (model.Run(seed, iterations)){
  104. Draw();
  105. }
  106. }
  107. public GameObject GetTile(int x, int y){
  108. return rendering[x,y];
  109. }
  110. public void Draw(){
  111. if (output == null){return;}
  112. if (group == null){return;}
  113. undrawn = false;
  114. try{
  115. for (int y = 0; y < depth; y++){
  116. for (int x = 0; x < width; x++){
  117. if (rendering[x,y] == null){
  118. int v = (int)model.Sample(x, y);
  119. if (v != 99 && v < training.tiles.Length){
  120. Vector3 pos = new Vector3(x*gridsize, y*gridsize, 0f);
  121. int rot = (int)training.RS[v];
  122. GameObject fab = training.tiles[v] as GameObject;
  123. if (fab != null){
  124. GameObject tile = (GameObject)Instantiate(fab, new Vector3() , Quaternion.identity);
  125. Vector3 fscale = tile.transform.localScale;
  126. tile.transform.parent = group;
  127. tile.transform.localPosition = pos;
  128. tile.transform.localEulerAngles = new Vector3(0, 0, 360 - (rot * 90));
  129. tile.transform.localScale = fscale;
  130. rendering[x,y] = tile;
  131. }
  132. } else
  133. {
  134. undrawn = true;
  135. }
  136. }
  137. }
  138. }
  139. } catch (IndexOutOfRangeException) {
  140. model = null;
  141. return;
  142. }
  143. }
  144. }
  145. #if UNITY_EDITOR
  146. [CustomEditor (typeof(OverlapWFC))]
  147. public class WFCGeneratorEditor : Editor {
  148. public override void OnInspectorGUI () {
  149. OverlapWFC generator = (OverlapWFC)target;
  150. if (generator.training != null){
  151. if(GUILayout.Button("generate")){
  152. generator.Generate();
  153. }
  154. if (generator.model != null){
  155. if(GUILayout.Button("RUN")){
  156. generator.Run();
  157. }
  158. }
  159. }
  160. DrawDefaultInspector ();
  161. }
  162. }
  163. #endif