mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-02-20 12:33:14 +00:00
TileMode for selection, (plus some other fixes) (#834)
* Tilemode selections * Selection TileMode * Fixed some bugs with the ORIGINAL tile mode Image brushes needed to be adjusted * remove behaviour checkbutton * fixed remaining things * formating * formatting * formatting * formatting * fix crash on rotating image * Fix Color getting transparent on double chicking same swatch twice * typo * typo * Update RotateImage.gd * Use sheckbox instead of option button * make checkbox directly under select menu
This commit is contained in:
parent
7c14af7129
commit
7b189cc45e
5 changed files with 141 additions and 50 deletions
|
@ -13,6 +13,61 @@ func is_pixel_selected(pixel: Vector2) -> bool:
|
|||
return selected
|
||||
|
||||
|
||||
func get_nearest_position(pixel: Vector2) -> Vector2:
|
||||
if Global.canvas.selection.flag_tilemode:
|
||||
# functions more or less the same way as the tilemode
|
||||
var size = Global.current_project.size
|
||||
var selection_rect = get_used_rect()
|
||||
var start_x = selection_rect.position.x - selection_rect.size.x
|
||||
var end_x = selection_rect.position.x + 2 * selection_rect.size.x
|
||||
var start_y = selection_rect.position.y - selection_rect.size.y
|
||||
var end_y = selection_rect.position.y + 2 * selection_rect.size.y
|
||||
for x in range(start_x, end_x, selection_rect.size.x):
|
||||
for y in range(start_y, end_y, selection_rect.size.y):
|
||||
var test_image = Image.new()
|
||||
test_image.create(size.x, size.y, false, Image.FORMAT_LA8)
|
||||
test_image.blit_rect(self, selection_rect, Vector2(x, y))
|
||||
test_image.lock()
|
||||
if (
|
||||
pixel.x < 0
|
||||
or pixel.y < 0
|
||||
or pixel.x >= test_image.get_width()
|
||||
or pixel.y >= test_image.get_height()
|
||||
):
|
||||
continue
|
||||
var selected: bool = test_image.get_pixelv(pixel).a > 0
|
||||
test_image.unlock()
|
||||
if selected:
|
||||
var offset = Vector2(x, y) - selection_rect.position
|
||||
return offset
|
||||
return Vector2.ZERO
|
||||
else:
|
||||
return Vector2.ZERO
|
||||
|
||||
|
||||
func get_point_in_tile_mode(pixel: Vector2) -> Array:
|
||||
var result = []
|
||||
if Global.canvas.selection.flag_tilemode:
|
||||
var selection_rect = get_used_rect()
|
||||
var start_x = selection_rect.position.x - selection_rect.size.x
|
||||
var end_x = selection_rect.position.x + 2 * selection_rect.size.x
|
||||
var start_y = selection_rect.position.y - selection_rect.size.y
|
||||
var end_y = selection_rect.position.y + 2 * selection_rect.size.y
|
||||
for x in range(start_x, end_x, selection_rect.size.x):
|
||||
for y in range(start_y, end_y, selection_rect.size.y):
|
||||
result.append(Vector2(x, y) + pixel - selection_rect.position)
|
||||
else:
|
||||
result.append(pixel)
|
||||
return result
|
||||
|
||||
|
||||
func get_canon_position(position) -> Vector2:
|
||||
if Global.canvas.selection.flag_tilemode:
|
||||
return position - get_nearest_position(position)
|
||||
else:
|
||||
return position
|
||||
|
||||
|
||||
func select_pixel(pixel: Vector2, select := true) -> void:
|
||||
lock()
|
||||
if select:
|
||||
|
|
|
@ -86,6 +86,15 @@ func get_canon_position(position: Vector2) -> Vector2:
|
|||
return position
|
||||
|
||||
|
||||
func get_point_in_tiles(pixel: Vector2) -> Array:
|
||||
var positions = Global.canvas.tile_mode.get_tile_positions()
|
||||
positions.append(Vector2.ZERO)
|
||||
var result = []
|
||||
for pos in positions:
|
||||
result.append(pos + pixel)
|
||||
return result
|
||||
|
||||
|
||||
func has_point(point: Vector2) -> bool:
|
||||
var positions = Global.canvas.tile_mode.get_tile_positions()
|
||||
positions.append(Vector2.ZERO) # The central tile is included manually
|
||||
|
|
|
@ -374,38 +374,44 @@ func _draw_tool_circle_from_map(position: Vector2) -> PoolVector2Array:
|
|||
return result
|
||||
|
||||
|
||||
func draw_tool_brush(position: Vector2) -> void:
|
||||
func draw_tool_brush(brush_position: Vector2) -> void:
|
||||
var project: Project = Global.current_project
|
||||
position = project.tiles.get_canon_position(position)
|
||||
# image brushes work differently, (we have to consider all 8 surrounding points)
|
||||
var central_point = project.tiles.get_canon_position(brush_position)
|
||||
var positions = project.tiles.get_point_in_tiles(central_point)
|
||||
if Global.current_project.has_selection and project.tiles.mode == Tiles.MODE.NONE:
|
||||
positions = Global.current_project.selection_map.get_point_in_tile_mode(central_point)
|
||||
|
||||
var size := _brush_image.get_size()
|
||||
var dst := position - (size / 2).floor()
|
||||
var dst_rect := Rect2(dst, size)
|
||||
var draw_rect := _get_draw_rect()
|
||||
dst_rect = dst_rect.clip(draw_rect)
|
||||
if dst_rect.size == Vector2.ZERO:
|
||||
return
|
||||
var src_rect := Rect2(dst_rect.position - dst, dst_rect.size)
|
||||
var brush_image: Image = remove_unselected_parts_of_brush(_brush_image, dst)
|
||||
dst = dst_rect.position
|
||||
_draw_brush_image(brush_image, src_rect, dst)
|
||||
for i in positions.size():
|
||||
var position: Vector2 = positions[i]
|
||||
var dst: Vector2 = position - (size / 2).floor()
|
||||
var dst_rect := Rect2(dst, size)
|
||||
var draw_rect := _get_draw_rect()
|
||||
dst_rect = dst_rect.clip(draw_rect)
|
||||
if dst_rect.size == Vector2.ZERO:
|
||||
continue
|
||||
var src_rect := Rect2(dst_rect.position - dst, dst_rect.size)
|
||||
var brush_image: Image = remove_unselected_parts_of_brush(_brush_image, dst)
|
||||
dst = dst_rect.position
|
||||
_draw_brush_image(brush_image, src_rect, dst)
|
||||
|
||||
# Handle Mirroring
|
||||
var mirror_x = (project.x_symmetry_point + 1) - dst.x - src_rect.size.x
|
||||
var mirror_y = (project.y_symmetry_point + 1) - dst.y - src_rect.size.y
|
||||
# Handle Mirroring
|
||||
var mirror_x = (project.x_symmetry_point + 1) - dst.x - src_rect.size.x
|
||||
var mirror_y = (project.y_symmetry_point + 1) - dst.y - src_rect.size.y
|
||||
|
||||
if Tools.horizontal_mirror:
|
||||
var x_dst := Vector2(mirror_x, dst.y)
|
||||
var mirror_brush_x: Image = remove_unselected_parts_of_brush(_mirror_brushes.x, x_dst)
|
||||
_draw_brush_image(mirror_brush_x, _flip_rect(src_rect, size, true, false), x_dst)
|
||||
if Tools.horizontal_mirror:
|
||||
var x_dst := Vector2(mirror_x, dst.y)
|
||||
var mirror_brush_x: Image = remove_unselected_parts_of_brush(_mirror_brushes.x, x_dst)
|
||||
_draw_brush_image(mirror_brush_x, _flip_rect(src_rect, size, true, false), x_dst)
|
||||
if Tools.vertical_mirror:
|
||||
var xy_dst := Vector2(mirror_x, mirror_y)
|
||||
var mirror_brush_xy := remove_unselected_parts_of_brush(_mirror_brushes.xy, xy_dst)
|
||||
_draw_brush_image(mirror_brush_xy, _flip_rect(src_rect, size, true, true), xy_dst)
|
||||
if Tools.vertical_mirror:
|
||||
var xy_dst := Vector2(mirror_x, mirror_y)
|
||||
var mirror_brush_xy := remove_unselected_parts_of_brush(_mirror_brushes.xy, xy_dst)
|
||||
_draw_brush_image(mirror_brush_xy, _flip_rect(src_rect, size, true, true), xy_dst)
|
||||
if Tools.vertical_mirror:
|
||||
var y_dst := Vector2(dst.x, mirror_y)
|
||||
var mirror_brush_y: Image = remove_unselected_parts_of_brush(_mirror_brushes.y, y_dst)
|
||||
_draw_brush_image(mirror_brush_y, _flip_rect(src_rect, size, false, true), y_dst)
|
||||
var y_dst := Vector2(dst.x, mirror_y)
|
||||
var mirror_brush_y: Image = remove_unselected_parts_of_brush(_mirror_brushes.y, y_dst)
|
||||
_draw_brush_image(mirror_brush_y, _flip_rect(src_rect, size, false, true), y_dst)
|
||||
|
||||
|
||||
func remove_unselected_parts_of_brush(brush: Image, dst: Vector2) -> Image:
|
||||
|
@ -429,6 +435,17 @@ func remove_unselected_parts_of_brush(brush: Image, dst: Vector2) -> Image:
|
|||
func draw_indicator(left: bool) -> void:
|
||||
var color := Global.left_tool_color if left else Global.right_tool_color
|
||||
draw_indicator_at(snap_position(_cursor), Vector2.ZERO, color)
|
||||
if (
|
||||
Global.current_project.has_selection
|
||||
and Global.current_project.tiles.mode == Tiles.MODE.NONE
|
||||
):
|
||||
var position := _line_start if _draw_line else _cursor
|
||||
var nearest_pos := Global.current_project.selection_map.get_nearest_position(position)
|
||||
if nearest_pos != Vector2.ZERO:
|
||||
var offset := nearest_pos
|
||||
draw_indicator_at(snap_position(_cursor), offset, Color.green)
|
||||
return
|
||||
|
||||
if Global.current_project.tiles.mode and Global.current_project.tiles.has_point(_cursor):
|
||||
var position := _line_start if _draw_line else _cursor
|
||||
var nearest_tile := Global.current_project.tiles.get_nearest_tile(position)
|
||||
|
@ -470,6 +487,8 @@ func _set_pixel(position: Vector2, ignore_mirroring := false) -> void:
|
|||
|
||||
func _set_pixel_no_cache(position: Vector2, ignore_mirroring := false) -> void:
|
||||
position = _stroke_project.tiles.get_canon_position(position)
|
||||
if Global.current_project.has_selection:
|
||||
position = Global.current_project.selection_map.get_canon_position(position)
|
||||
if !_stroke_project.can_pixel_get_drawn(position):
|
||||
return
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
extends Node2D
|
||||
|
||||
enum SelectionOperation { ADD, SUBTRACT, INTERSECT }
|
||||
|
||||
enum SelectionFlags { TILE_MODE }
|
||||
const KEY_MOVE_ACTION_NAMES := ["ui_up", "ui_down", "ui_left", "ui_right"]
|
||||
const CLIPBOARD_FILE_PATH := "user://clipboard.txt"
|
||||
|
||||
# flags (additional properties of selection that can be toggled)
|
||||
var flag_tilemode = false
|
||||
|
||||
var is_moving_content := false
|
||||
var arrow_key_move := false
|
||||
var is_pasting := false
|
||||
|
|
|
@ -299,13 +299,14 @@ func _setup_image_menu() -> void:
|
|||
|
||||
func _setup_select_menu() -> void:
|
||||
# Order as in Global.SelectMenu enum
|
||||
var select_menu_items := ["All", "Clear", "Invert"]
|
||||
var select_menu_items := ["All", "Clear", "Invert", "Tile Mode"]
|
||||
var select_menu: PopupMenu = select_menu_button.get_popup()
|
||||
var i := 0
|
||||
for item in select_menu_items:
|
||||
select_menu.add_item(item, i)
|
||||
i += 1
|
||||
|
||||
for i in select_menu_items.size():
|
||||
var item: String = select_menu_items[i]
|
||||
if item == "Tile Mode":
|
||||
select_menu.add_check_item(item, i)
|
||||
else:
|
||||
select_menu.add_item(item, i)
|
||||
select_menu.connect("id_pressed", self, "select_menu_id_pressed")
|
||||
|
||||
|
||||
|
@ -474,6 +475,23 @@ func view_menu_id_pressed(id: int) -> void:
|
|||
Global.canvas.update()
|
||||
|
||||
|
||||
func window_menu_id_pressed(id: int) -> void:
|
||||
if not Global.can_draw:
|
||||
return
|
||||
match id:
|
||||
Global.WindowMenu.WINDOW_OPACITY:
|
||||
_popup_dialog(window_opacity_dialog)
|
||||
Global.WindowMenu.MOVABLE_PANELS:
|
||||
ui.tabs_visible = !ui.tabs_visible
|
||||
window_menu.set_item_checked(id, ui.tabs_visible)
|
||||
Global.WindowMenu.ZEN_MODE:
|
||||
_toggle_zen_mode()
|
||||
Global.WindowMenu.FULLSCREEN_MODE:
|
||||
_toggle_fullscreen()
|
||||
_:
|
||||
_handle_metadata(id, window_menu_button)
|
||||
|
||||
|
||||
func _tile_mode_submenu_id_pressed(id: int) -> void:
|
||||
Global.current_project.tiles.mode = id
|
||||
Global.transparent_checker.fit_rect(Global.current_project.tiles.get_bounding_rect())
|
||||
|
@ -497,23 +515,6 @@ func _snap_to_submenu_id_pressed(id: int) -> void:
|
|||
snap_to_submenu.set_item_checked(id, Global.snap_to_perspective_guides)
|
||||
|
||||
|
||||
func window_menu_id_pressed(id: int) -> void:
|
||||
if not Global.can_draw:
|
||||
return
|
||||
match id:
|
||||
Global.WindowMenu.WINDOW_OPACITY:
|
||||
_popup_dialog(window_opacity_dialog)
|
||||
Global.WindowMenu.MOVABLE_PANELS:
|
||||
ui.tabs_visible = !ui.tabs_visible
|
||||
window_menu.set_item_checked(id, ui.tabs_visible)
|
||||
Global.WindowMenu.ZEN_MODE:
|
||||
_toggle_zen_mode()
|
||||
Global.WindowMenu.FULLSCREEN_MODE:
|
||||
_toggle_fullscreen()
|
||||
_:
|
||||
_handle_metadata(id, window_menu_button)
|
||||
|
||||
|
||||
func _panels_submenu_id_pressed(id: int) -> void:
|
||||
if zen_mode:
|
||||
return
|
||||
|
@ -699,6 +700,10 @@ func select_menu_id_pressed(id: int) -> void:
|
|||
Global.canvas.selection.clear_selection(true)
|
||||
Global.SelectMenu.INVERT:
|
||||
Global.canvas.selection.invert()
|
||||
Global.SelectMenu.TILE_MODE:
|
||||
var state = select_menu_button.get_popup().is_item_checked(id)
|
||||
Global.canvas.selection.flag_tilemode = !state
|
||||
select_menu_button.get_popup().set_item_checked(id, !state)
|
||||
_:
|
||||
_handle_metadata(id, select_menu_button)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue