diff --git a/project/OverlappingDemos.tscn b/project/OverlappingDemos.tscn index af2cfc8..ae3e557 100644 --- a/project/OverlappingDemos.tscn +++ b/project/OverlappingDemos.tscn @@ -9,7 +9,7 @@ anchor_bottom = 1.0 script = ExtResource( 1 ) source_image_rect_path = NodePath("VBoxContainer2/VBoxContainer/HBoxContainer/TextureRect") result_image_rect_path = NodePath("VBoxContainer2/VBoxContainer/HBoxContainer2/TextureRect") -settings_label_path = NodePath("VBoxContainer2/VBoxContainer/HBoxContainer3/Label2") +settings_label_path = NodePath("VBoxContainer2/VBoxContainer/HBoxContainer3/ScrollContainer/Label2") [node name="VBoxContainer2" type="VBoxContainer" parent="."] margin_left = 7.0 @@ -58,18 +58,29 @@ expand = true [node name="HBoxContainer3" type="VBoxContainer" parent="VBoxContainer2/VBoxContainer"] margin_left = 608.0 -margin_right = 659.0 +margin_right = 1010.0 margin_bottom = 562.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 [node name="Label" type="Label" parent="VBoxContainer2/VBoxContainer/HBoxContainer3"] -margin_right = 51.0 +margin_right = 402.0 margin_bottom = 14.0 text = "Settings" -[node name="Label2" type="Label" parent="VBoxContainer2/VBoxContainer/HBoxContainer3"] +[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer2/VBoxContainer/HBoxContainer3"] margin_top = 18.0 -margin_right = 51.0 -margin_bottom = 32.0 +margin_right = 402.0 +margin_bottom = 562.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Label2" type="Label" parent="VBoxContainer2/VBoxContainer/HBoxContainer3/ScrollContainer"] +margin_right = 402.0 +margin_bottom = 544.0 +size_flags_horizontal = 3 +size_flags_vertical = 7 +autowrap = true [node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer2"] margin_top = 566.0 diff --git a/project/TextureRect.gd b/project/TextureRect.gd index ce0db7a..78b9a45 100644 --- a/project/TextureRect.gd +++ b/project/TextureRect.gd @@ -13,6 +13,46 @@ enum SampleDataType { SAMPLE_DATA_TYPE_TILED = 1, }; +class TileEntry: + var tile_name : String = "" + var symmetry : int = 0 + var weight : float = 1 + var image : Image + var images : Array + + func _to_string(): + var t : String = "" + + if image: + t = "simple" + else: + t = "complex (" + str(images.size()) + ")" + + return "[ TileEntry " + t + " tile_name: " + tile_name + ", symmetry: " + str(symmetry) + " weight: " + str(weight) + " ]\n" + +class NeighbourEntry: + var left : String = "" + var left_orientation : int = 0 + var right : String = "" + var right_orientation : int = 0 + + func setup(l : String, r : String): + left = l.get_slice(" ", 0) + var s : String = l.get_slice(" ", 1) + + if (s != ""): + left_orientation = int(s) + + right = r.get_slice(" ", 0) + + s = l.get_slice(" ", 1) + + if (s != ""): + right_orientation = int(s) + + func _to_string(): + return "[ NeighbourEntry left: " + left + "(" + str(left_orientation) + "), right: " + right + "(" + str(right_orientation) + ") ]\n" + class SampleData: var type : int = 0 var image_name : String = "" @@ -25,6 +65,9 @@ class SampleData: var limit : int = 0 var screenshots : int = 0 var periodic_input : int = true + var tiles : Array + var neighbours : Array + var image : Image func _to_string(): return "SampleData\ntype: " + str(type) + \ @@ -37,8 +80,9 @@ class SampleData: "\nground: " + str(ground) + \ "\nlimit: " + str(limit) + \ "\nscreenshots: " + str(screenshots) + \ - "\nperiodic_input: " + str(periodic_input) - + "\nperiodic_input: " + str(periodic_input) + \ + "\ntiles: " + str(tiles) + \ + "\nneighbours: " + str(neighbours) var data : Array @@ -88,9 +132,80 @@ func load_data(): entry.screenshots = int(attrib_value) elif attrib_name == "periodic_input": entry.periodic_input = int(attrib_value) - + + if entry.type == SampleDataType.SAMPLE_DATA_TYPE_TILED: + var e : Array = load_tile_entry(entry) + entry.tiles = e[0] + entry.neighbours = e[1] + else: + entry.image = ResourceLoader.load("res://samples/" + entry.image_name + ".png") + data.push_back(entry) +func load_tile_entry(entry : SampleData) -> Array: + var xmlp : XMLParser = XMLParser.new() + xmlp.open("res://samples/" + entry.image_name + "/data.xml") + + var tiles : Array + var neighbours : Array + + while xmlp.read() == OK: + if xmlp.get_node_type() == XMLParser.NODE_ELEMENT: + if xmlp.get_node_name() == "tile": + var e : TileEntry = TileEntry.new() + + for i in range(xmlp.get_attribute_count()): + var attrib_name : String = xmlp.get_attribute_name(i) + var attrib_value : String = xmlp.get_attribute_value(i) + + if attrib_name == "name": + e.tile_name = attrib_value + elif attrib_name == "symmetry": + e.symmetry = int(attrib_value) + elif attrib_name == "weight": + e.weight = float(attrib_value) + + var simple_image_path : String = "res://samples/" + entry.image_name + "/" + e.tile_name + ".png" + + var file : File = File.new() + if !file.file_exists(simple_image_path): + var indx : int = 0 + while true: + var image_path : String = "res://samples/" + entry.image_name + "/" + e.tile_name + " " + str(indx) + ".png" + + if !file.file_exists(image_path): + break + + e.images.push_back(ResourceLoader.load(image_path)) + indx += 1 + else: + e.image = ResourceLoader.load(simple_image_path) + + + + tiles.push_back(e) + elif xmlp.get_node_name() == "neighbor": + var e : NeighbourEntry = NeighbourEntry.new() + + var left : String + var right : String + + for i in range(xmlp.get_attribute_count()): + var attrib_name : String = xmlp.get_attribute_name(i) + var attrib_value : String = xmlp.get_attribute_value(i) + + if attrib_name == "left": + left = attrib_value + elif attrib_name == "right": + right = attrib_value + + e.setup(left, right) + neighbours.push_back(e) + + + return [ tiles, neighbours ] + + func _enter_tree(): _on_next_pressed() @@ -110,13 +225,11 @@ func generate_image_overlapping(): var indexer : ImageIndexer = ImageIndexer.new() - var img : Image = ResourceLoader.load("res://samples/" + sd.image_name + ".png") var source_tex : ImageTexture = ImageTexture.new(); - source_tex.create_from_image(img, 0) + source_tex.create_from_image(sd.image, 0) get_node(source_image_rect_path).texture = source_tex - indexer.index_image(img) - var indices : PoolIntArray = indexer.get_color_indices() + var indices : PoolIntArray = indexer.index_image(sd.image) var wfc : OverlappingWaveFormCollapse = OverlappingWaveFormCollapse.new() wfc.pattern_size = sd.pattern_size @@ -126,10 +239,10 @@ func generate_image_overlapping(): wfc.periodic_input = sd.periodic_input - wfc.out_height = img.get_height() - wfc.out_width = img.get_width() + wfc.out_height = sd.image.get_height() + wfc.out_width = sd.image.get_width() - wfc.set_input(indices, img.get_width(), img.get_height()) + wfc.set_input(indices, sd.image.get_width(), sd.image.get_height()) #todo #if sd.width > 0 && sd.height > 0: @@ -151,7 +264,7 @@ func generate_image_overlapping(): var data : PoolByteArray = indexer.indices_to_argb8_data(res) var res_img : Image = Image.new() - res_img.create_from_data(img.get_width(), img.get_height(), false, Image.FORMAT_RGBA8, data) + res_img.create_from_data(sd.image.get_width(), sd.image.get_height(), false, Image.FORMAT_RGBA8, data) var res_tex : ImageTexture = ImageTexture.new(); res_tex.create_from_image(res_img, 0) @@ -159,12 +272,69 @@ func generate_image_overlapping(): get_node(result_image_rect_path).texture = res_tex func generate_image_tiled(): - #load data xml - #process - #index all images -> need new api to the indexer - #add_neighbour set binding names -> {left_tile, left_orientation, right_tile, right_orientation} - #left_orientation -> might need constants - pass + get_node(source_image_rect_path).texture = null + get_node(result_image_rect_path).texture = null + + var sd : SampleData = data[_current_data_index] + + get_node(settings_label_path).text = str(_current_data_index) + "\n" + sd.to_string() + + var indexer : ImageIndexer = ImageIndexer.new() + var wfc : TilingWaveFormCollapse = TilingWaveFormCollapse.new() + + for i in range(sd.tiles.size()): + var te : TileEntry = sd.tiles[i] + + if !te.image: + var tile_index : int = wfc.tile_add(te.symmetry, te.weight) + wfc.tile_name_set(tile_index, te.tile_name) + + for img in te.images: + var indices : PoolIntArray = indexer.index_image(img) + wfc.tile_data_add(tile_index, indices, img.get_width(), img.get_height()) + else: + var indices : PoolIntArray = indexer.index_image(te.image) + var tile_index : int = wfc.tile_add_generated(indices, te.image.get_width(), te.image.get_height(), te.symmetry, te.weight) + wfc.tile_name_set(tile_index, te.tile_name) + + + for i in range(sd.neighbours.size()): + var ne : NeighbourEntry = sd.neighbours[i] + + wfc.neighbour_data_add_str(ne.left, ne.left_orientation, ne.right, ne.right_orientation) + + wfc.periodic_output = sd.periodic + + wfc.wave_width = sd.width + wfc.wave_height = sd.height + + #todo + #if sd.width > 0 && sd.height > 0: + # wfc.set_input(indices, sd.width, sd.height) + #else: + # wfc.set_input(indices, img.get_width(), img.get_height()) + + randomize() + wfc.set_seed(randi()) + + wfc.initialize() + + var res : PoolIntArray = wfc.generate_image_index_data() + + if (res.size() == 0): + print("(res.size() == 0)") + return + + var data : PoolByteArray = indexer.indices_to_argb8_data(res) + + var res_img : Image = Image.new() + res_img.create_from_data(sd.width, sd.height, false, Image.FORMAT_RGBA8, data) + + var res_tex : ImageTexture = ImageTexture.new(); + res_tex.create_from_image(res_img, 0) + + get_node(result_image_rect_path).texture = res_tex + func _on_prev_pressed(): while true: