1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-12 16:53:07 +00:00

Add tile properties window, allowing you to change each tile's probability

More options can be added there in the future. Perhaps we could even add Godot tileset data, once we add Godot tileset exporting.
This commit is contained in:
Emmanouil Papadeas 2025-02-09 03:34:10 +02:00
parent f2f465a111
commit 34ef0d4d15
5 changed files with 118 additions and 12 deletions

View file

@ -3551,3 +3551,11 @@ msgstr ""
#: src/UI/TilesPanel.tscn
msgid "Show empty tile:"
msgstr ""
#: src/UI/TilesPanel.tscn
msgid "Tile properties"
msgstr ""
#: src/UI/TilesPanel.tscn
msgid "Probability:"
msgstr ""

View file

@ -287,7 +287,10 @@ func open_pxo_file(path: String, is_backup := false, replace_empty := true) -> v
var image := Image.create_from_data(
tile_size.x, tile_size.y, false, new_project.get_image_format(), image_data
)
tileset.add_tile(image, null, 0)
if j > tileset.tiles.size() - 1:
tileset.add_tile(image, null, 0)
else:
tileset.tiles[j].image = image
for cel in new_project.get_all_pixel_cels():
if cel is CelTileMap:
cel.find_times_used_of_tiles()

View file

@ -29,6 +29,8 @@ class Tile:
var image: Image
## The amount of tiles this tile is being used in tilemaps.
var times_used := 1
## The relative probability of this tile appearing when drawing random tiles.
var probability := 1.0
func _init(_image: Image) -> void:
image = _image
@ -38,6 +40,14 @@ class Tile:
func can_be_removed() -> bool:
return times_used <= 0
func serialize() -> Dictionary:
return {"times_used": times_used, "probability": probability}
func deserialize(dict: Dictionary, skip_times_used := false) -> void:
if not skip_times_used:
times_used = dict.get("times_used", times_used)
probability = dict.get("probability", probability)
func _init(_tile_size: Vector2i, _name := "", add_empty_tile := true) -> void:
tile_size = _tile_size
@ -150,10 +160,31 @@ func find_using_layers(project: Project) -> Array[LayerTileMap]:
return tilemaps
func pick_random_tile(selected_tile_indices: Array[int]) -> int:
if selected_tile_indices.is_empty():
for i in tiles.size():
selected_tile_indices.append(i)
var sum := 0.0
for i in selected_tile_indices:
sum += tiles[i].probability
var rand := randf_range(0.0, sum)
var current := 0.0
for i in selected_tile_indices:
current += tiles[i].probability
if current >= rand:
return i
return selected_tile_indices[0]
## Serializes the data of this class into the form of a [Dictionary],
## which is used so the data can be stored in pxo files.
func serialize() -> Dictionary:
return {"name": name, "tile_size": tile_size, "tile_amount": tiles.size()}
var dict := {"name": name, "tile_size": tile_size, "tile_amount": tiles.size()}
var tile_data := {}
for i in tiles.size():
tile_data[i] = tiles[i].serialize()
dict["tile_data"] = tile_data
return dict
## Deserializes the data of a given [member dict] [Dictionary] into class data,
@ -161,6 +192,16 @@ func serialize() -> Dictionary:
func deserialize(dict: Dictionary) -> void:
name = dict.get("name", name)
tile_size = str_to_var("Vector2i" + dict.get("tile_size"))
var tile_data := dict.get("tile_data", {}) as Dictionary
for i_str in tile_data:
var i := int(i_str)
var tile: Tile
if i > tiles.size() - 1:
tile = Tile.new(null)
tiles.append(tile)
else:
tile = tiles[i]
tile.deserialize(tile_data[i_str], true)
## Serializes the data of each tile in [member tiles] into the form of a [Dictionary],
@ -169,7 +210,7 @@ func serialize_undo_data() -> Dictionary:
var dict := {}
for tile in tiles:
var image_data := tile.image.get_data()
dict[tile.image] = [image_data.compress(), image_data.size(), tile.times_used]
dict[tile.image] = [image_data.compress(), image_data.size(), tile.serialize()]
return dict
@ -180,9 +221,10 @@ func deserialize_undo_data(dict: Dictionary, cel: CelTileMap) -> void:
for image: Image in dict:
var tile_data = dict[image]
var buffer_size := tile_data[1] as int
var tile_dictionary := tile_data[2] as Dictionary
var image_data := (tile_data[0] as PackedByteArray).decompress(buffer_size)
image.set_data(tile_size.x, tile_size.y, false, image.get_format(), image_data)
tiles[i] = Tile.new(image)
tiles[i].times_used = tile_data[2]
tiles[i].deserialize(tile_dictionary)
i += 1
updated.emit(cel, -1)

View file

@ -24,7 +24,9 @@ static var selected_tile_index := 0:
selected_tiles = [value]
_call_update_brushes()
get:
return selected_tiles.pick_random()
if is_instance_valid(current_tileset):
return current_tileset.pick_random_tile(selected_tiles)
return selected_tiles[0]
static var selected_tiles: Array[int] = [0]
static var is_flipped_h := false:
set(value):
@ -38,7 +40,7 @@ static var is_transposed := false:
set(value):
is_transposed = value
_call_update_brushes()
var current_tileset: TileSetCustom
static var current_tileset: TileSetCustom
var button_size := 36:
set(value):
if button_size == value:
@ -61,6 +63,8 @@ var tile_index_menu_popped := 0
@onready var options: Popup = $Options
@onready var tile_size_slider: ValueSlider = %TileSizeSlider
@onready var tile_button_popup_menu: PopupMenu = $TileButtonPopupMenu
@onready var tile_properties: AcceptDialog = $TileProperties
@onready var tile_probability_slider: ValueSlider = %TileProbabilitySlider
func _ready() -> void:
@ -197,7 +201,7 @@ func _on_tile_button_gui_input(event: InputEvent, index: int) -> void:
tile_button_popup_menu.popup_on_parent(Rect2(get_global_mouse_position(), Vector2.ONE))
tile_index_menu_popped = index
tile_button_popup_menu.set_item_disabled(
0, not current_tileset.tiles[index].can_be_removed()
1, not current_tileset.tiles[index].can_be_removed()
)
@ -277,9 +281,12 @@ func _on_show_empty_tile_toggled(toggled_on: bool) -> void:
func _on_tile_button_popup_menu_index_pressed(index: int) -> void:
if tile_index_menu_popped == 0:
return
if index == 0: # Delete
if index == 0: # Properties
tile_probability_slider.value = current_tileset.tiles[tile_index_menu_popped].probability
tile_properties.popup_centered()
elif index == 1: # Delete
if tile_index_menu_popped == 0:
return
if current_tileset.tiles[tile_index_menu_popped].can_be_removed():
var undo_data := current_tileset.serialize_undo_data()
current_tileset.tiles.remove_at(tile_index_menu_popped)
@ -295,3 +302,7 @@ func _on_tile_button_popup_menu_index_pressed(index: int) -> void:
project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true))
project.undo_redo.add_do_method(Global.undo_or_redo.bind(false))
project.undo_redo.commit_action()
func _on_tile_probability_slider_value_changed(value: float) -> void:
current_tileset.tiles[tile_index_menu_popped].probability = value

View file

@ -343,8 +343,49 @@ button_pressed = true
text = "On"
[node name="TileButtonPopupMenu" type="PopupMenu" parent="."]
item_count = 1
item_0/text = "Delete"
item_count = 2
item_0/text = "Properties"
item_1/text = "Delete"
item_1/id = 1
[node name="TileProperties" type="AcceptDialog" parent="."]
title = "Tile properties"
size = Vector2i(300, 200)
[node name="GridContainer" type="GridContainer" parent="TileProperties"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 8.0
offset_top = 8.0
offset_right = -8.0
offset_bottom = -49.0
grow_horizontal = 2
grow_vertical = 2
columns = 2
[node name="TileProbabilityLabel" type="Label" parent="TileProperties/GridContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Probability:"
[node name="TileProbabilitySlider" type="TextureProgressBar" parent="TileProperties/GridContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
focus_mode = 2
mouse_default_cursor_shape = 2
theme_type_variation = &"ValueSlider"
max_value = 10.0
step = 0.001
value = 1.0
allow_greater = true
nine_patch_stretch = true
stretch_margin_left = 3
stretch_margin_top = 3
stretch_margin_right = 3
stretch_margin_bottom = 3
script = ExtResource("10_wfr6s")
[connection signal="toggled" from="VBoxContainer/MarginContainer/VBoxContainer/Buttons/PlaceTiles" to="." method="_on_place_tiles_toggled"]
[connection signal="pressed" from="VBoxContainer/MarginContainer/VBoxContainer/Buttons/TransformButtonsContainer/RotateLeftButton" to="." method="_on_rotate_pressed" binds= [false]]
@ -358,3 +399,4 @@ item_0/text = "Delete"
[connection signal="value_changed" from="Options/MarginContainer/ScrollContainer/GridContainer/TileSizeSlider" to="." method="_on_tile_size_slider_value_changed"]
[connection signal="toggled" from="Options/MarginContainer/ScrollContainer/GridContainer/ShowEmptyTile" to="." method="_on_show_empty_tile_toggled"]
[connection signal="index_pressed" from="TileButtonPopupMenu" to="." method="_on_tile_button_popup_menu_index_pressed"]
[connection signal="value_changed" from="TileProperties/GridContainer/TileProbabilitySlider" to="." method="_on_tile_probability_slider_value_changed"]