mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-02-12 16:53:07 +00:00
Compare commits
8 commits
d9fafcfd5a
...
645cad3f29
Author | SHA1 | Date | |
---|---|---|---|
|
645cad3f29 | ||
|
c72a1f4b90 | ||
|
be8b7728e4 | ||
|
31981a1def | ||
|
7f4c7a6bf1 | ||
|
41ea287df4 | ||
|
a3e372c5d8 | ||
|
6224d06428 |
22
CHANGELOG.md
22
CHANGELOG.md
|
@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). All the dates are in YYYY-MM-DD format.
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). All the dates are in YYYY-MM-DD format.
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
## [v1.1] - Unreleased
|
||||||
|
This update has been brought to you by the contributions of:
|
||||||
|
Fayez Akhtar ([@Variable-ind](https://github.com/Variable-ind))
|
||||||
|
|
||||||
|
Built using Godot 4.3
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Indexed mode has finally been implemented! [#1136](https://github.com/Orama-Interactive/Pixelorama/pull/1136)
|
||||||
|
- Added a new text tool. Destructive only for now, meaning that once the text is confirmed, it cannot be changed later. [#1134](https://github.com/Orama-Interactive/Pixelorama/pull/1134)
|
||||||
|
- Implemented support for multiple grids. [#1122](https://github.com/Orama-Interactive/Pixelorama/pull/1122)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- System font names are now sorted by alphabetical order.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed crash when Pixelorama starts without a palette.
|
||||||
|
- Undo/redo now works again when the cursor is hovering over the timeline.
|
||||||
|
- Palette swatches now get deleted when the user removes all palettes
|
||||||
|
- Fixed the Palettize effect and palette exporting to images storing slightly wrong color values. [77f6bcf](https://github.com/Orama-Interactive/Pixelorama/commit/77f6bcf07bd80bc042e478bb883d05900cebe436)
|
||||||
|
- Fixed some issues with the Palettize effect where the output would be different if the palette size changed and empty swatches were added, even if the colors themselves stayed the same. Initially fixed by [bd7d3b1](https://github.com/Orama-Interactive/Pixelorama/commit/bd7d3b19cc98804e9b99754153c4d553d2048ee3), but [1dcb696](https://github.com/Orama-Interactive/Pixelorama/commit/1dcb696c35121f8208bde699f87bb75deff99d13) is the proper fix.
|
||||||
|
- Fixed recorder label not updating when project is changed. [#1139](https://github.com/Orama-Interactive/Pixelorama/pull/1139)
|
||||||
|
|
||||||
## [v1.0.5] - 2024-11-18
|
## [v1.0.5] - 2024-11-18
|
||||||
This update has been brought to you by the contributions of:
|
This update has been brought to you by the contributions of:
|
||||||
Fayez Akhtar ([@Variable-ind](https://github.com/Variable-ind))
|
Fayez Akhtar ([@Variable-ind](https://github.com/Variable-ind))
|
||||||
|
|
|
@ -921,6 +921,10 @@ right_text_tool={
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
show_pixel_indices={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
|
||||||
[input_devices]
|
[input_devices]
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ enum ViewMenu {
|
||||||
MIRROR_VIEW,
|
MIRROR_VIEW,
|
||||||
SHOW_GRID,
|
SHOW_GRID,
|
||||||
SHOW_PIXEL_GRID,
|
SHOW_PIXEL_GRID,
|
||||||
|
SHOW_PIXEL_INDICES,
|
||||||
SHOW_RULERS,
|
SHOW_RULERS,
|
||||||
SHOW_GUIDES,
|
SHOW_GUIDES,
|
||||||
SHOW_MOUSE_GUIDES,
|
SHOW_MOUSE_GUIDES,
|
||||||
|
@ -337,55 +338,8 @@ var default_height := 64 ## Found in Preferences. The default height of startup
|
||||||
var default_fill_color := Color(0, 0, 0, 0)
|
var default_fill_color := Color(0, 0, 0, 0)
|
||||||
## Found in Preferences. The distance to the guide or grig below which cursor snapping activates.
|
## Found in Preferences. The distance to the guide or grig below which cursor snapping activates.
|
||||||
var snapping_distance := 32.0
|
var snapping_distance := 32.0
|
||||||
## Found in Preferences. The grid type defined by [enum GridTypes] enum.
|
## Contains dictionaries of individual grids.
|
||||||
var grid_type := GridTypes.CARTESIAN:
|
var grids: Array[Grid] = []
|
||||||
set(value):
|
|
||||||
if value == grid_type:
|
|
||||||
return
|
|
||||||
grid_type = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The size of rectangular grid.
|
|
||||||
var grid_size := Vector2i(2, 2):
|
|
||||||
set(value):
|
|
||||||
if value == grid_size:
|
|
||||||
return
|
|
||||||
grid_size = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The size of isometric grid.
|
|
||||||
var isometric_grid_size := Vector2i(16, 8):
|
|
||||||
set(value):
|
|
||||||
if value == isometric_grid_size:
|
|
||||||
return
|
|
||||||
isometric_grid_size = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The grid offset from top-left corner of the canvas.
|
|
||||||
var grid_offset := Vector2i.ZERO:
|
|
||||||
set(value):
|
|
||||||
if value == grid_offset:
|
|
||||||
return
|
|
||||||
grid_offset = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. If [code]true[/code], The grid draws over the area extended by
|
|
||||||
## tile-mode as well.
|
|
||||||
var grid_draw_over_tile_mode := false:
|
|
||||||
set(value):
|
|
||||||
if value == grid_draw_over_tile_mode:
|
|
||||||
return
|
|
||||||
grid_draw_over_tile_mode = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The color of grid.
|
|
||||||
var grid_color := Color.BLACK:
|
|
||||||
set(value):
|
|
||||||
if value == grid_color:
|
|
||||||
return
|
|
||||||
grid_color = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The minimum zoom after which pixel grid gets drawn if enabled.
|
## Found in Preferences. The minimum zoom after which pixel grid gets drawn if enabled.
|
||||||
var pixel_grid_show_at_zoom := 1500.0: # percentage
|
var pixel_grid_show_at_zoom := 1500.0: # percentage
|
||||||
set(value):
|
set(value):
|
||||||
|
@ -602,6 +556,12 @@ var show_rulers := true:
|
||||||
var show_guides := true
|
var show_guides := true
|
||||||
## If [code]true[/code], the mouse guides are visible.
|
## If [code]true[/code], the mouse guides are visible.
|
||||||
var show_mouse_guides := false
|
var show_mouse_guides := false
|
||||||
|
## If [code]true[/code], the indices of color are shown.
|
||||||
|
var show_pixel_indices := false:
|
||||||
|
set(value):
|
||||||
|
show_pixel_indices = value
|
||||||
|
if is_instance_valid(canvas.color_index):
|
||||||
|
canvas.color_index.enabled = value
|
||||||
var display_layer_effects := true:
|
var display_layer_effects := true:
|
||||||
set(value):
|
set(value):
|
||||||
if value == display_layer_effects:
|
if value == display_layer_effects:
|
||||||
|
@ -677,6 +637,62 @@ var cel_button_scene: PackedScene = load("res://src/UI/Timeline/CelButton.tscn")
|
||||||
@onready var error_dialog: AcceptDialog = control.find_child("ErrorDialog")
|
@onready var error_dialog: AcceptDialog = control.find_child("ErrorDialog")
|
||||||
|
|
||||||
|
|
||||||
|
class Grid:
|
||||||
|
var grid_type := GridTypes.CARTESIAN:
|
||||||
|
set(value):
|
||||||
|
if value == grid_type:
|
||||||
|
return
|
||||||
|
grid_type = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. The size of rectangular grid.
|
||||||
|
var grid_size := Vector2i(2, 2):
|
||||||
|
set(value):
|
||||||
|
if value == grid_size:
|
||||||
|
return
|
||||||
|
grid_size = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. The size of isometric grid.
|
||||||
|
var isometric_grid_size := Vector2i(16, 8):
|
||||||
|
set(value):
|
||||||
|
if value == isometric_grid_size:
|
||||||
|
return
|
||||||
|
isometric_grid_size = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. The grid offset from top-left corner of the canvas.
|
||||||
|
var grid_offset := Vector2i.ZERO:
|
||||||
|
set(value):
|
||||||
|
if value == grid_offset:
|
||||||
|
return
|
||||||
|
grid_offset = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. If [code]true[/code], The grid draws over the area extended by
|
||||||
|
## tile-mode as well.
|
||||||
|
var grid_draw_over_tile_mode := false:
|
||||||
|
set(value):
|
||||||
|
if value == grid_draw_over_tile_mode:
|
||||||
|
return
|
||||||
|
grid_draw_over_tile_mode = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. The color of grid.
|
||||||
|
var grid_color := Color.BLACK:
|
||||||
|
set(value):
|
||||||
|
if value == grid_color:
|
||||||
|
return
|
||||||
|
grid_color = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
|
||||||
|
func _init(properties := {}) -> void:
|
||||||
|
Global.grids.append(self)
|
||||||
|
for prop in properties.keys():
|
||||||
|
set(prop, properties[prop])
|
||||||
|
|
||||||
|
|
||||||
func _init() -> void:
|
func _init() -> void:
|
||||||
# Load settings from the config file
|
# Load settings from the config file
|
||||||
config_cache.load(CONFIG_PATH)
|
config_cache.load(CONFIG_PATH)
|
||||||
|
@ -713,6 +729,8 @@ func _init() -> void:
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
# Initialize Grid
|
||||||
|
Grid.new() # gets auto added to grids array
|
||||||
_initialize_keychain()
|
_initialize_keychain()
|
||||||
default_width = config_cache.get_value("preferences", "default_width", default_width)
|
default_width = config_cache.get_value("preferences", "default_width", default_width)
|
||||||
default_height = config_cache.get_value("preferences", "default_height", default_height)
|
default_height = config_cache.get_value("preferences", "default_height", default_height)
|
||||||
|
@ -729,11 +747,26 @@ func _ready() -> void:
|
||||||
if get(pref) == null:
|
if get(pref) == null:
|
||||||
continue
|
continue
|
||||||
var value = config_cache.get_value("preferences", pref)
|
var value = config_cache.get_value("preferences", pref)
|
||||||
|
if pref == "grids":
|
||||||
|
if value:
|
||||||
|
update_grids(value)
|
||||||
|
else:
|
||||||
set(pref, value)
|
set(pref, value)
|
||||||
if OS.is_sandboxed():
|
if OS.is_sandboxed():
|
||||||
Global.use_native_file_dialogs = true
|
Global.use_native_file_dialogs = true
|
||||||
await get_tree().process_frame
|
await get_tree().process_frame
|
||||||
project_switched.emit()
|
project_switched.emit()
|
||||||
|
canvas.color_index.enabled = show_pixel_indices # Initialize color index preview
|
||||||
|
|
||||||
|
|
||||||
|
func update_grids(grids_data: Dictionary):
|
||||||
|
# Remove old grids
|
||||||
|
grids.clear()
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
# ADD new ones
|
||||||
|
for grid_idx in grids_data.size():
|
||||||
|
Grid.new(grids_data[grid_idx]) # gets auto added to grids array
|
||||||
|
|
||||||
|
|
||||||
func _initialize_keychain() -> void:
|
func _initialize_keychain() -> void:
|
||||||
|
|
|
@ -90,9 +90,9 @@ func get_brush_files_from_directory(directory: String): # -> Array
|
||||||
func add_randomised_brush(fpaths: Array, tooltip_name: String) -> void:
|
func add_randomised_brush(fpaths: Array, tooltip_name: String) -> void:
|
||||||
# Attempt to load the images from the file paths.
|
# Attempt to load the images from the file paths.
|
||||||
var loaded_images: Array = []
|
var loaded_images: Array = []
|
||||||
for filen in fpaths:
|
for file in fpaths:
|
||||||
var image := Image.new()
|
var image := Image.new()
|
||||||
var err := image.load(filen)
|
var err := image.load(file)
|
||||||
if err == OK:
|
if err == OK:
|
||||||
image.convert(Image.FORMAT_RGBA8)
|
image.convert(Image.FORMAT_RGBA8)
|
||||||
loaded_images.append(image)
|
loaded_images.append(image)
|
||||||
|
|
|
@ -296,14 +296,14 @@ func current_palette_select_color(mouse_button: int, index: int) -> void:
|
||||||
if color == null:
|
if color == null:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
_select_color(mouse_button, index)
|
||||||
|
|
||||||
match mouse_button:
|
match mouse_button:
|
||||||
MOUSE_BUTTON_LEFT:
|
MOUSE_BUTTON_LEFT:
|
||||||
Tools.assign_color(color, mouse_button)
|
Tools.assign_color(color, mouse_button)
|
||||||
MOUSE_BUTTON_RIGHT:
|
MOUSE_BUTTON_RIGHT:
|
||||||
Tools.assign_color(color, mouse_button)
|
Tools.assign_color(color, mouse_button)
|
||||||
|
|
||||||
_select_color(mouse_button, index)
|
|
||||||
|
|
||||||
|
|
||||||
func _select_color(mouse_button: int, index: int) -> void:
|
func _select_color(mouse_button: int, index: int) -> void:
|
||||||
match mouse_button:
|
match mouse_button:
|
||||||
|
|
|
@ -12,6 +12,7 @@ enum Dynamics { NONE, PRESSURE, VELOCITY }
|
||||||
const XY_LINE := Vector2(-0.707107, 0.707107)
|
const XY_LINE := Vector2(-0.707107, 0.707107)
|
||||||
const X_MINUS_Y_LINE := Vector2(0.707107, 0.707107)
|
const X_MINUS_Y_LINE := Vector2(0.707107, 0.707107)
|
||||||
|
|
||||||
|
var active_button := -1
|
||||||
var picking_color_for := MOUSE_BUTTON_LEFT
|
var picking_color_for := MOUSE_BUTTON_LEFT
|
||||||
var horizontal_mirror := false
|
var horizontal_mirror := false
|
||||||
var vertical_mirror := false
|
var vertical_mirror := false
|
||||||
|
@ -238,7 +239,6 @@ var _right_tools_per_layer_type := {
|
||||||
Global.LayerTypes.THREE_D: "Pan",
|
Global.LayerTypes.THREE_D: "Pan",
|
||||||
}
|
}
|
||||||
var _tool_buttons: Node
|
var _tool_buttons: Node
|
||||||
var _active_button := -1
|
|
||||||
var _last_position := Vector2i(Vector2.INF)
|
var _last_position := Vector2i(Vector2.INF)
|
||||||
|
|
||||||
|
|
||||||
|
@ -627,32 +627,28 @@ func handle_draw(position: Vector2i, event: InputEvent) -> void:
|
||||||
change_layer_automatically(draw_pos)
|
change_layer_automatically(draw_pos)
|
||||||
return
|
return
|
||||||
|
|
||||||
if event.is_action_pressed(&"activate_left_tool") and _active_button == -1 and not pen_inverted:
|
if event.is_action_pressed(&"activate_left_tool") and active_button == -1 and not pen_inverted:
|
||||||
_active_button = MOUSE_BUTTON_LEFT
|
active_button = MOUSE_BUTTON_LEFT
|
||||||
_slots[_active_button].tool_node.draw_start(draw_pos)
|
_slots[active_button].tool_node.draw_start(draw_pos)
|
||||||
elif event.is_action_released(&"activate_left_tool") and _active_button == MOUSE_BUTTON_LEFT:
|
elif event.is_action_released(&"activate_left_tool") and active_button == MOUSE_BUTTON_LEFT:
|
||||||
_slots[_active_button].tool_node.draw_end(draw_pos)
|
_slots[active_button].tool_node.draw_end(draw_pos)
|
||||||
_active_button = -1
|
active_button = -1
|
||||||
elif (
|
elif (
|
||||||
(
|
(
|
||||||
event.is_action_pressed(&"activate_right_tool")
|
event.is_action_pressed(&"activate_right_tool")
|
||||||
and _active_button == -1
|
and active_button == -1
|
||||||
and not pen_inverted
|
and not pen_inverted
|
||||||
)
|
)
|
||||||
or (
|
or event.is_action_pressed(&"activate_left_tool") and active_button == -1 and pen_inverted
|
||||||
event.is_action_pressed(&"activate_left_tool") and _active_button == -1 and pen_inverted
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
_active_button = MOUSE_BUTTON_RIGHT
|
active_button = MOUSE_BUTTON_RIGHT
|
||||||
_slots[_active_button].tool_node.draw_start(draw_pos)
|
_slots[active_button].tool_node.draw_start(draw_pos)
|
||||||
elif (
|
elif (
|
||||||
(event.is_action_released(&"activate_right_tool") and _active_button == MOUSE_BUTTON_RIGHT)
|
(event.is_action_released(&"activate_right_tool") and active_button == MOUSE_BUTTON_RIGHT)
|
||||||
or (
|
or event.is_action_released(&"activate_left_tool") and active_button == MOUSE_BUTTON_RIGHT
|
||||||
event.is_action_released(&"activate_left_tool") and _active_button == MOUSE_BUTTON_RIGHT
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
_slots[_active_button].tool_node.draw_end(draw_pos)
|
_slots[active_button].tool_node.draw_end(draw_pos)
|
||||||
_active_button = -1
|
active_button = -1
|
||||||
|
|
||||||
if event is InputEventMouseMotion:
|
if event is InputEventMouseMotion:
|
||||||
pen_pressure = event.pressure
|
pen_pressure = event.pressure
|
||||||
|
@ -683,8 +679,8 @@ func handle_draw(position: Vector2i, event: InputEvent) -> void:
|
||||||
_last_position = position
|
_last_position = position
|
||||||
_slots[MOUSE_BUTTON_LEFT].tool_node.cursor_move(position)
|
_slots[MOUSE_BUTTON_LEFT].tool_node.cursor_move(position)
|
||||||
_slots[MOUSE_BUTTON_RIGHT].tool_node.cursor_move(position)
|
_slots[MOUSE_BUTTON_RIGHT].tool_node.cursor_move(position)
|
||||||
if _active_button != -1:
|
if active_button != -1:
|
||||||
_slots[_active_button].tool_node.draw_move(draw_pos)
|
_slots[active_button].tool_node.draw_move(draw_pos)
|
||||||
|
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
var text := "[%s×%s]" % [project.size.x, project.size.y]
|
var text := "[%s×%s]" % [project.size.x, project.size.y]
|
||||||
|
|
|
@ -80,7 +80,12 @@ func update_palette() -> void:
|
||||||
palette.resize(current_palette.colors_max)
|
palette.resize(current_palette.colors_max)
|
||||||
palette.fill(TRANSPARENT)
|
palette.fill(TRANSPARENT)
|
||||||
for i in current_palette.colors:
|
for i in current_palette.colors:
|
||||||
palette[i] = current_palette.colors[i].color
|
# Due to the decimal nature of the color values, some values get rounded off
|
||||||
|
# unintentionally.
|
||||||
|
# Even though the decimal values change, the HTML code remains the same after the change.
|
||||||
|
# So we're using this trick to convert the values back to how they are shown in
|
||||||
|
# the palette.
|
||||||
|
palette[i] = Color(current_palette.colors[i].color.to_html())
|
||||||
|
|
||||||
|
|
||||||
## Displays the actual RGBA values of each pixel in the image from indexed mode.
|
## Displays the actual RGBA values of each pixel in the image from indexed mode.
|
||||||
|
@ -126,13 +131,13 @@ func resize_indices() -> void:
|
||||||
indices_image.crop(get_width(), get_height())
|
indices_image.crop(get_width(), get_height())
|
||||||
|
|
||||||
|
|
||||||
## Equivalent of [method Image.set_pixel_custom],
|
## Equivalent of [method Image.set_pixel],
|
||||||
## but also handles the logic necessary for indexed mode.
|
## but also handles the logic necessary for indexed mode.
|
||||||
func set_pixel_custom(x: int, y: int, color: Color) -> void:
|
func set_pixel_custom(x: int, y: int, color: Color) -> void:
|
||||||
set_pixelv_custom(Vector2i(x, y), color)
|
set_pixelv_custom(Vector2i(x, y), color)
|
||||||
|
|
||||||
|
|
||||||
## Equivalent of [method Image.set_pixelv_custom],
|
## Equivalent of [method Image.set_pixelv],
|
||||||
## but also handles the logic necessary for indexed mode.
|
## but also handles the logic necessary for indexed mode.
|
||||||
func set_pixelv_custom(point: Vector2i, color: Color) -> void:
|
func set_pixelv_custom(point: Vector2i, color: Color) -> void:
|
||||||
var new_color := color
|
var new_color := color
|
||||||
|
@ -142,6 +147,13 @@ func set_pixelv_custom(point: Vector2i, color: Color) -> void:
|
||||||
if not color.is_equal_approx(TRANSPARENT):
|
if not color.is_equal_approx(TRANSPARENT):
|
||||||
if palette.has(color):
|
if palette.has(color):
|
||||||
color_index = palette.find(color)
|
color_index = palette.find(color)
|
||||||
|
# If the color selected in the palette is the same then it should take prioity.
|
||||||
|
var selected_index = Palettes.current_palette_get_selected_color_index(
|
||||||
|
Tools.active_button
|
||||||
|
)
|
||||||
|
if selected_index != -1:
|
||||||
|
if palette[selected_index].is_equal_approx(color):
|
||||||
|
color_index = selected_index
|
||||||
else: # Find the most similar color
|
else: # Find the most similar color
|
||||||
var smaller_distance := color_distance(color, palette[0])
|
var smaller_distance := color_distance(color, palette[0])
|
||||||
for i in palette.size():
|
for i in palette.size():
|
||||||
|
|
|
@ -34,6 +34,7 @@ var color_mode: int = Image.FORMAT_RGBA8:
|
||||||
image.resize_indices()
|
image.resize_indices()
|
||||||
image.select_palette("", false)
|
image.select_palette("", false)
|
||||||
image.convert_rgb_to_indexed()
|
image.convert_rgb_to_indexed()
|
||||||
|
Global.canvas.color_index.queue_redraw()
|
||||||
var fill_color := Color(0)
|
var fill_color := Color(0)
|
||||||
var has_changed := false:
|
var has_changed := false:
|
||||||
set(value):
|
set(value):
|
||||||
|
|
|
@ -602,6 +602,7 @@ func _exit_tree() -> void:
|
||||||
Global.config_cache.set_value("window", "size", get_window().size)
|
Global.config_cache.set_value("window", "size", get_window().size)
|
||||||
Global.config_cache.set_value("view_menu", "draw_grid", Global.draw_grid)
|
Global.config_cache.set_value("view_menu", "draw_grid", Global.draw_grid)
|
||||||
Global.config_cache.set_value("view_menu", "draw_pixel_grid", Global.draw_pixel_grid)
|
Global.config_cache.set_value("view_menu", "draw_pixel_grid", Global.draw_pixel_grid)
|
||||||
|
Global.config_cache.set_value("view_menu", "show_pixel_indices", Global.show_pixel_indices)
|
||||||
Global.config_cache.set_value("view_menu", "show_rulers", Global.show_rulers)
|
Global.config_cache.set_value("view_menu", "show_rulers", Global.show_rulers)
|
||||||
Global.config_cache.set_value("view_menu", "show_guides", Global.show_guides)
|
Global.config_cache.set_value("view_menu", "show_guides", Global.show_guides)
|
||||||
Global.config_cache.set_value("view_menu", "show_mouse_guides", Global.show_mouse_guides)
|
Global.config_cache.set_value("view_menu", "show_mouse_guides", Global.show_mouse_guides)
|
||||||
|
|
|
@ -82,17 +82,20 @@ func scroll_palette(origin: Vector2i) -> void:
|
||||||
|
|
||||||
## Called when the color changes, either the left or the right, determined by [param mouse_button].
|
## Called when the color changes, either the left or the right, determined by [param mouse_button].
|
||||||
## If current palette has [param target_color] as a [Color], then select it.
|
## If current palette has [param target_color] as a [Color], then select it.
|
||||||
|
## This is helpful when we select color indirectly (e.g through colorpicker)
|
||||||
func find_and_select_color(target_color: Color, mouse_button: int) -> void:
|
func find_and_select_color(target_color: Color, mouse_button: int) -> void:
|
||||||
if not is_instance_valid(current_palette):
|
if not is_instance_valid(current_palette):
|
||||||
return
|
return
|
||||||
var old_index := Palettes.current_palette_get_selected_color_index(mouse_button)
|
var selected_index := Palettes.current_palette_get_selected_color_index(mouse_button)
|
||||||
|
if get_swatch_color(selected_index) == target_color: # Color already selected
|
||||||
|
return
|
||||||
for color_ind in swatches.size():
|
for color_ind in swatches.size():
|
||||||
if (
|
if (
|
||||||
target_color.is_equal_approx(swatches[color_ind].color)
|
target_color.is_equal_approx(swatches[color_ind].color)
|
||||||
or target_color.to_html() == swatches[color_ind].color.to_html()
|
or target_color.to_html() == swatches[color_ind].color.to_html()
|
||||||
):
|
):
|
||||||
var index := convert_grid_index_to_palette_index(color_ind)
|
var index := convert_grid_index_to_palette_index(color_ind)
|
||||||
select_swatch(mouse_button, index, old_index)
|
select_swatch(mouse_button, index, selected_index)
|
||||||
match mouse_button:
|
match mouse_button:
|
||||||
MOUSE_BUTTON_LEFT:
|
MOUSE_BUTTON_LEFT:
|
||||||
Palettes.left_selected_color = index
|
Palettes.left_selected_color = index
|
||||||
|
|
200
src/Preferences/GridPreferences.gd
Normal file
200
src/Preferences/GridPreferences.gd
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
extends GridContainer
|
||||||
|
|
||||||
|
# We should use pre defined initial grid colors instead of random colors
|
||||||
|
const INITIAL_GRID_COLORS := [
|
||||||
|
Color.BLACK,
|
||||||
|
Color.WHITE,
|
||||||
|
Color.YELLOW,
|
||||||
|
Color.GREEN,
|
||||||
|
Color.BLUE,
|
||||||
|
Color.GRAY,
|
||||||
|
Color.ORANGE,
|
||||||
|
Color.PINK,
|
||||||
|
Color.SIENNA,
|
||||||
|
Color.CORAL,
|
||||||
|
]
|
||||||
|
|
||||||
|
var grid_preferences: Array[GridPreference] = [
|
||||||
|
GridPreference.new("grid_type", "GridType", "selected", Global.GridTypes.CARTESIAN),
|
||||||
|
GridPreference.new("grid_size", "GridSizeValue", "value", Vector2i(2, 2)),
|
||||||
|
GridPreference.new("isometric_grid_size", "IsometricGridSizeValue", "value", Vector2i(16, 8)),
|
||||||
|
GridPreference.new("grid_offset", "GridOffsetValue", "value", Vector2i.ZERO),
|
||||||
|
GridPreference.new("grid_draw_over_tile_mode", "GridDrawOverTileMode", "button_pressed", false),
|
||||||
|
GridPreference.new("grid_color", "GridColor", "color", Color.BLACK),
|
||||||
|
]
|
||||||
|
|
||||||
|
var grid_selected: int = 0:
|
||||||
|
set(key):
|
||||||
|
grid_selected = key
|
||||||
|
for child: BaseButton in grids_select_container.get_children():
|
||||||
|
if child.get_index() == grid_selected:
|
||||||
|
child.self_modulate = Color.WHITE
|
||||||
|
else:
|
||||||
|
child.self_modulate = Color.DIM_GRAY
|
||||||
|
var grids: Dictionary = Global.config_cache.get_value(
|
||||||
|
"preferences", "grids", {0: create_default_properties()}
|
||||||
|
)
|
||||||
|
if grids.has(key):
|
||||||
|
update_pref_ui(grids[key])
|
||||||
|
|
||||||
|
@onready var grids_select_container: HFlowContainer = $GridsSelectContainer
|
||||||
|
|
||||||
|
|
||||||
|
class GridPreference:
|
||||||
|
var prop_name: String
|
||||||
|
var node_path: String
|
||||||
|
var value_type: String
|
||||||
|
var default_value
|
||||||
|
|
||||||
|
func _init(
|
||||||
|
_prop_name: String,
|
||||||
|
_node_path: String,
|
||||||
|
_value_type: String,
|
||||||
|
_default_value = null,
|
||||||
|
_require_restart := false
|
||||||
|
) -> void:
|
||||||
|
prop_name = _prop_name
|
||||||
|
node_path = _node_path
|
||||||
|
value_type = _value_type
|
||||||
|
if _default_value != null:
|
||||||
|
default_value = _default_value
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
var grids = Global.config_cache.get_value(
|
||||||
|
"preferences", "grids", {0: create_default_properties()}
|
||||||
|
)
|
||||||
|
Global.config_cache.set_value("preferences", "grids", grids)
|
||||||
|
$GridsCount.value = grids.size()
|
||||||
|
if grids.size() == 1:
|
||||||
|
add_remove_select_button(0)
|
||||||
|
for pref in grid_preferences:
|
||||||
|
if not has_node(pref.node_path):
|
||||||
|
continue
|
||||||
|
var node := get_node(pref.node_path)
|
||||||
|
var restore_default_button := RestoreDefaultButton.new()
|
||||||
|
restore_default_button.pressed.connect(
|
||||||
|
_on_grid_pref_value_changed.bind(pref.default_value, pref, restore_default_button)
|
||||||
|
)
|
||||||
|
restore_default_button.setting_name = pref.prop_name
|
||||||
|
restore_default_button.value_type = pref.value_type
|
||||||
|
restore_default_button.default_value = pref.default_value
|
||||||
|
restore_default_button.node = node
|
||||||
|
|
||||||
|
var node_position := node.get_index()
|
||||||
|
node.get_parent().add_child(restore_default_button)
|
||||||
|
node.get_parent().move_child(restore_default_button, node_position)
|
||||||
|
|
||||||
|
match pref.value_type:
|
||||||
|
"button_pressed":
|
||||||
|
node.toggled.connect(_on_grid_pref_value_changed.bind(pref, restore_default_button))
|
||||||
|
"value":
|
||||||
|
node.value_changed.connect(
|
||||||
|
_on_grid_pref_value_changed.bind(pref, restore_default_button)
|
||||||
|
)
|
||||||
|
"color":
|
||||||
|
node.get_picker().presets_visible = false
|
||||||
|
node.color_changed.connect(
|
||||||
|
_on_grid_pref_value_changed.bind(pref, restore_default_button)
|
||||||
|
)
|
||||||
|
"selected":
|
||||||
|
node.item_selected.connect(
|
||||||
|
_on_grid_pref_value_changed.bind(pref, restore_default_button)
|
||||||
|
)
|
||||||
|
grid_selected = 0
|
||||||
|
|
||||||
|
|
||||||
|
func _on_grid_pref_value_changed(value, pref: GridPreference, button: RestoreDefaultButton) -> void:
|
||||||
|
var grids: Dictionary = Global.config_cache.get_value(
|
||||||
|
"preferences", "grids", {0: create_default_properties()}
|
||||||
|
)
|
||||||
|
if grids.has(grid_selected): # Failsafe (Always true)
|
||||||
|
var grid_info: Dictionary = grids[grid_selected]
|
||||||
|
var prop := pref.prop_name
|
||||||
|
grid_info[prop] = value
|
||||||
|
grids[grid_selected] = grid_info
|
||||||
|
Global.update_grids(grids)
|
||||||
|
var default_value = pref.default_value
|
||||||
|
var disable: bool = Global.grids[grid_selected].get(prop) == default_value
|
||||||
|
if typeof(value) == TYPE_COLOR:
|
||||||
|
disable = value.is_equal_approx(default_value)
|
||||||
|
disable_restore_default_button(button, disable)
|
||||||
|
Global.config_cache.set_value("preferences", "grids", grids)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_grids_count_value_changed(value: float) -> void:
|
||||||
|
var new_grids: Dictionary = Global.config_cache.get_value(
|
||||||
|
"preferences", "grids", {0: create_default_properties()}
|
||||||
|
)
|
||||||
|
var last_grid_idx = int(value - 1)
|
||||||
|
if last_grid_idx >= grids_select_container.get_child_count():
|
||||||
|
# Add missing grids
|
||||||
|
for key in range(grids_select_container.get_child_count(), value):
|
||||||
|
if not new_grids.has(key):
|
||||||
|
var new_grid := create_default_properties()
|
||||||
|
if new_grids.has(key - 1): # Failsafe
|
||||||
|
var last_grid = new_grids[key - 1]
|
||||||
|
# This small bit of code is there to make ui look a little neater
|
||||||
|
# Reasons:
|
||||||
|
# - Usually user intends to make the next grid twice the size.
|
||||||
|
# - Having all grids being same size initially may cause confusion for some
|
||||||
|
# users when they try to change color of a middle grid not seeing it's changing
|
||||||
|
# (due to being covered by grids above it).
|
||||||
|
if (
|
||||||
|
new_grid.has("grid_size")
|
||||||
|
and new_grid.has("isometric_grid_size")
|
||||||
|
and new_grid.has("grid_color")
|
||||||
|
):
|
||||||
|
new_grid["grid_size"] = last_grid["grid_size"] * 2
|
||||||
|
new_grid["isometric_grid_size"] = last_grid["isometric_grid_size"] * 2
|
||||||
|
if key < INITIAL_GRID_COLORS.size():
|
||||||
|
new_grid["grid_color"] = INITIAL_GRID_COLORS[key]
|
||||||
|
new_grids[key] = new_grid
|
||||||
|
add_remove_select_button(key)
|
||||||
|
else:
|
||||||
|
# Remove extra grids
|
||||||
|
for key: int in range(value, new_grids.size()):
|
||||||
|
new_grids.erase(key)
|
||||||
|
add_remove_select_button(key, true)
|
||||||
|
grid_selected = min(grid_selected, last_grid_idx)
|
||||||
|
Global.update_grids(new_grids)
|
||||||
|
Global.config_cache.set_value("preferences", "grids", new_grids)
|
||||||
|
|
||||||
|
|
||||||
|
func create_default_properties() -> Dictionary:
|
||||||
|
var grid_info = {}
|
||||||
|
for pref in grid_preferences:
|
||||||
|
grid_info[pref.prop_name] = pref.default_value
|
||||||
|
return grid_info
|
||||||
|
|
||||||
|
|
||||||
|
func disable_restore_default_button(button: RestoreDefaultButton, disable: bool) -> void:
|
||||||
|
button.disabled = disable
|
||||||
|
if disable:
|
||||||
|
button.mouse_default_cursor_shape = Control.CURSOR_ARROW
|
||||||
|
button.tooltip_text = ""
|
||||||
|
else:
|
||||||
|
button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
|
||||||
|
button.tooltip_text = "Restore default value"
|
||||||
|
|
||||||
|
|
||||||
|
func add_remove_select_button(grid_idx: int, remove := false):
|
||||||
|
if not remove:
|
||||||
|
var select_button = Button.new()
|
||||||
|
select_button.text = str(grid_idx)
|
||||||
|
grids_select_container.add_child(select_button)
|
||||||
|
select_button.pressed.connect(func(): grid_selected = grid_idx)
|
||||||
|
else:
|
||||||
|
if grid_idx < grids_select_container.get_child_count():
|
||||||
|
grids_select_container.get_child(grid_idx).queue_free()
|
||||||
|
|
||||||
|
|
||||||
|
func update_pref_ui(grid_data: Dictionary):
|
||||||
|
for pref in grid_preferences:
|
||||||
|
var key = pref.prop_name
|
||||||
|
if grid_data.has(key):
|
||||||
|
var node := get_node(pref.node_path)
|
||||||
|
node.set(pref.value_type, grid_data[key])
|
||||||
|
if pref.value_type == "color":
|
||||||
|
# the signal doesn't seem to be emitted automatically
|
||||||
|
node.color_changed.emit(grid_data[key])
|
|
@ -94,21 +94,6 @@ var preferences: Array[Preference] = [
|
||||||
Preference.new("smooth_zoom", "Canvas/ZoomOptions/SmoothZoom", "button_pressed", true),
|
Preference.new("smooth_zoom", "Canvas/ZoomOptions/SmoothZoom", "button_pressed", true),
|
||||||
Preference.new("integer_zoom", "Canvas/ZoomOptions/IntegerZoom", "button_pressed", false),
|
Preference.new("integer_zoom", "Canvas/ZoomOptions/IntegerZoom", "button_pressed", false),
|
||||||
Preference.new("snapping_distance", "Canvas/SnappingOptions/DistanceValue", "value", 32.0),
|
Preference.new("snapping_distance", "Canvas/SnappingOptions/DistanceValue", "value", 32.0),
|
||||||
Preference.new(
|
|
||||||
"grid_type", "Canvas/GridOptions/GridType", "selected", Global.GridTypes.CARTESIAN
|
|
||||||
),
|
|
||||||
Preference.new("grid_size", "Canvas/GridOptions/GridSizeValue", "value", Vector2i(2, 2)),
|
|
||||||
Preference.new(
|
|
||||||
"isometric_grid_size", "Canvas/GridOptions/IsometricGridSizeValue", "value", Vector2i(16, 8)
|
|
||||||
),
|
|
||||||
Preference.new("grid_offset", "Canvas/GridOptions/GridOffsetValue", "value", Vector2i.ZERO),
|
|
||||||
Preference.new(
|
|
||||||
"grid_draw_over_tile_mode",
|
|
||||||
"Canvas/GridOptions/GridDrawOverTileMode",
|
|
||||||
"button_pressed",
|
|
||||||
false
|
|
||||||
),
|
|
||||||
Preference.new("grid_color", "Canvas/GridOptions/GridColor", "color", Color.BLACK),
|
|
||||||
Preference.new(
|
Preference.new(
|
||||||
"pixel_grid_show_at_zoom", "Canvas/PixelGridOptions/ShowAtZoom", "value", 1500.0
|
"pixel_grid_show_at_zoom", "Canvas/PixelGridOptions/ShowAtZoom", "value", 1500.0
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
[gd_scene load_steps=9 format=3 uid="uid://b3hkjj3s6pe4x"]
|
[gd_scene load_steps=11 format=3 uid="uid://b3hkjj3s6pe4x"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/Preferences/PreferencesDialog.gd" id="1"]
|
[ext_resource type="Script" path="res://src/Preferences/PreferencesDialog.gd" id="1"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bq7ibhm0txl5p" path="res://addons/keychain/ShortcutEdit.tscn" id="3"]
|
[ext_resource type="PackedScene" uid="uid://bq7ibhm0txl5p" path="res://addons/keychain/ShortcutEdit.tscn" id="3"]
|
||||||
[ext_resource type="Script" path="res://src/Preferences/ThemesPreferences.gd" id="3_nvl8k"]
|
[ext_resource type="Script" path="res://src/Preferences/ThemesPreferences.gd" id="3_nvl8k"]
|
||||||
|
[ext_resource type="Script" path="res://src/Preferences/GridPreferences.gd" id="4_76iff"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/ValueSlider.tscn" id="5_rlmsh"]
|
||||||
[ext_resource type="PackedScene" path="res://src/UI/Nodes/ValueSliderV2.tscn" id="7"]
|
[ext_resource type="PackedScene" path="res://src/UI/Nodes/ValueSliderV2.tscn" id="7"]
|
||||||
[ext_resource type="Script" path="res://src/Preferences/ExtensionsPreferences.gd" id="7_8ume5"]
|
[ext_resource type="Script" path="res://src/Preferences/ExtensionsPreferences.gd" id="7_8ume5"]
|
||||||
[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="8"]
|
[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="8"]
|
||||||
|
@ -482,6 +484,30 @@ layout_mode = 2
|
||||||
theme_override_constants/h_separation = 4
|
theme_override_constants/h_separation = 4
|
||||||
theme_override_constants/v_separation = 4
|
theme_override_constants/v_separation = 4
|
||||||
columns = 3
|
columns = 3
|
||||||
|
script = ExtResource("4_76iff")
|
||||||
|
|
||||||
|
[node name="GridsCountLabel" type="Label" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Grids Visible:"
|
||||||
|
|
||||||
|
[node name="Spacer" type="Control" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="GridsCount" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions" instance=ExtResource("5_rlmsh")]
|
||||||
|
layout_mode = 2
|
||||||
|
min_value = 1.0
|
||||||
|
max_value = 10.0
|
||||||
|
value = 1.0
|
||||||
|
|
||||||
|
[node name="GridsSelectLabel" type="Label" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Editing Grid:"
|
||||||
|
|
||||||
|
[node name="Spacer2" type="Control" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="GridsSelectContainer" type="HFlowContainer" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="GridTypeLabel" type="Label" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions"]
|
[node name="GridTypeLabel" type="Label" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
@ -1478,6 +1504,7 @@ dialog_text = "Are you sure you want to reset the selected options? There will b
|
||||||
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Language/System Language" to="." method="_on_language_pressed" binds= [1]]
|
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Language/System Language" to="." method="_on_language_pressed" binds= [1]]
|
||||||
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Interface/InterfaceOptions/ShrinkContainer/ShrinkApplyButton" to="." method="_on_shrink_apply_button_pressed"]
|
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Interface/InterfaceOptions/ShrinkContainer/ShrinkApplyButton" to="." method="_on_shrink_apply_button_pressed"]
|
||||||
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Interface/InterfaceOptions/FontSizeContainer/FontSizeApplyButton" to="." method="_on_font_size_apply_button_pressed"]
|
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Interface/InterfaceOptions/FontSizeContainer/FontSizeApplyButton" to="." method="_on_font_size_apply_button_pressed"]
|
||||||
|
[connection signal="value_changed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions/GridsCount" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Canvas/GridOptions" method="_on_grids_count_value_changed"]
|
||||||
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/ExtensionsHeader/Explore" to="Store" method="_on_explore_pressed"]
|
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/ExtensionsHeader/Explore" to="Store" method="_on_explore_pressed"]
|
||||||
[connection signal="empty_clicked" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/InstalledExtensions" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_InstalledExtensions_empty_clicked"]
|
[connection signal="empty_clicked" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/InstalledExtensions" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_InstalledExtensions_empty_clicked"]
|
||||||
[connection signal="item_selected" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/InstalledExtensions" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_InstalledExtensions_item_selected"]
|
[connection signal="item_selected" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/InstalledExtensions" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_InstalledExtensions_item_selected"]
|
||||||
|
|
|
@ -159,16 +159,17 @@ func draw_move(pos: Vector2i) -> void:
|
||||||
else:
|
else:
|
||||||
pos.x = _start_pos.x
|
pos.x = _start_pos.x
|
||||||
if Input.is_action_pressed("transform_snap_grid"):
|
if Input.is_action_pressed("transform_snap_grid"):
|
||||||
_offset = _offset.snapped(Global.grid_size)
|
_offset = _offset.snapped(Global.grids[0].grid_size)
|
||||||
var prev_pos: Vector2i = selection_node.big_bounding_rectangle.position
|
var prev_pos: Vector2i = selection_node.big_bounding_rectangle.position
|
||||||
selection_node.big_bounding_rectangle.position = prev_pos.snapped(Global.grid_size)
|
selection_node.big_bounding_rectangle.position = prev_pos.snapped(Global.grids[0].grid_size)
|
||||||
selection_node.marching_ants_outline.offset += Vector2(
|
selection_node.marching_ants_outline.offset += Vector2(
|
||||||
selection_node.big_bounding_rectangle.position - prev_pos
|
selection_node.big_bounding_rectangle.position - prev_pos
|
||||||
)
|
)
|
||||||
pos = pos.snapped(Global.grid_size)
|
pos = pos.snapped(Global.grids[0].grid_size)
|
||||||
var grid_offset := Global.grid_offset
|
var grid_offset := Global.grids[0].grid_offset
|
||||||
grid_offset = Vector2i(
|
grid_offset = Vector2i(
|
||||||
fmod(grid_offset.x, Global.grid_size.x), fmod(grid_offset.y, Global.grid_size.y)
|
fmod(grid_offset.x, Global.grids[0].grid_size.x),
|
||||||
|
fmod(grid_offset.y, Global.grids[0].grid_size.y)
|
||||||
)
|
)
|
||||||
pos += grid_offset
|
pos += grid_offset
|
||||||
|
|
||||||
|
|
|
@ -129,19 +129,20 @@ func draw_preview() -> void:
|
||||||
func snap_position(pos: Vector2) -> Vector2:
|
func snap_position(pos: Vector2) -> Vector2:
|
||||||
var snapping_distance := Global.snapping_distance / Global.camera.zoom.x
|
var snapping_distance := Global.snapping_distance / Global.camera.zoom.x
|
||||||
if Global.snap_to_rectangular_grid_boundary:
|
if Global.snap_to_rectangular_grid_boundary:
|
||||||
var grid_pos := pos.snapped(Global.grid_size)
|
var grid_pos := pos.snapped(Global.grids[0].grid_size)
|
||||||
grid_pos += Vector2(Global.grid_offset)
|
grid_pos += Vector2(Global.grids[0].grid_offset)
|
||||||
# keeping grid_pos as is would have been fine but this adds extra accuracy as to
|
# keeping grid_pos as is would have been fine but this adds extra accuracy as to
|
||||||
# which snap point (from the list below) is closest to mouse and occupy THAT point
|
# which snap point (from the list below) is closest to mouse and occupy THAT point
|
||||||
var t_l := grid_pos + Vector2(-Global.grid_size.x, -Global.grid_size.y)
|
# t_l is for "top left" and so on
|
||||||
var t_c := grid_pos + Vector2(0, -Global.grid_size.y) # t_c is for "top centre" and so on
|
var t_l := grid_pos + Vector2(-Global.grids[0].grid_size.x, -Global.grids[0].grid_size.y)
|
||||||
var t_r := grid_pos + Vector2(Global.grid_size.x, -Global.grid_size.y)
|
var t_c := grid_pos + Vector2(0, -Global.grids[0].grid_size.y)
|
||||||
var m_l := grid_pos + Vector2(-Global.grid_size.x, 0)
|
var t_r := grid_pos + Vector2(Global.grids[0].grid_size.x, -Global.grids[0].grid_size.y)
|
||||||
|
var m_l := grid_pos + Vector2(-Global.grids[0].grid_size.x, 0)
|
||||||
var m_c := grid_pos
|
var m_c := grid_pos
|
||||||
var m_r := grid_pos + Vector2(Global.grid_size.x, 0)
|
var m_r := grid_pos + Vector2(Global.grids[0].grid_size.x, 0)
|
||||||
var b_l := grid_pos + Vector2(-Global.grid_size.x, Global.grid_size.y)
|
var b_l := grid_pos + Vector2(-Global.grids[0].grid_size.x, Global.grids[0].grid_size.y)
|
||||||
var b_c := grid_pos + Vector2(0, Global.grid_size.y)
|
var b_c := grid_pos + Vector2(0, Global.grids[0].grid_size.y)
|
||||||
var b_r := grid_pos + Vector2(Global.grid_size)
|
var b_r := grid_pos + Vector2(Global.grids[0].grid_size)
|
||||||
var vec_arr: PackedVector2Array = [t_l, t_c, t_r, m_l, m_c, m_r, b_l, b_c, b_r]
|
var vec_arr: PackedVector2Array = [t_l, t_c, t_r, m_l, m_c, m_r, b_l, b_c, b_r]
|
||||||
for vec in vec_arr:
|
for vec in vec_arr:
|
||||||
if vec.distance_to(pos) < grid_pos.distance_to(pos):
|
if vec.distance_to(pos) < grid_pos.distance_to(pos):
|
||||||
|
@ -152,19 +153,22 @@ func snap_position(pos: Vector2) -> Vector2:
|
||||||
pos = grid_point.floor()
|
pos = grid_point.floor()
|
||||||
|
|
||||||
if Global.snap_to_rectangular_grid_center:
|
if Global.snap_to_rectangular_grid_center:
|
||||||
var grid_center := pos.snapped(Global.grid_size) + Vector2(Global.grid_size / 2)
|
var grid_center := (
|
||||||
grid_center += Vector2(Global.grid_offset)
|
pos.snapped(Global.grids[0].grid_size) + Vector2(Global.grids[0].grid_size / 2)
|
||||||
|
)
|
||||||
|
grid_center += Vector2(Global.grids[0].grid_offset)
|
||||||
# keeping grid_center as is would have been fine but this adds extra accuracy as to
|
# keeping grid_center as is would have been fine but this adds extra accuracy as to
|
||||||
# which snap point (from the list below) is closest to mouse and occupy THAT point
|
# which snap point (from the list below) is closest to mouse and occupy THAT point
|
||||||
var t_l := grid_center + Vector2(-Global.grid_size.x, -Global.grid_size.y)
|
# t_l is for "top left" and so on
|
||||||
var t_c := grid_center + Vector2(0, -Global.grid_size.y) # t_c is for "top centre" and so on
|
var t_l := grid_center + Vector2(-Global.grids[0].grid_size.x, -Global.grids[0].grid_size.y)
|
||||||
var t_r := grid_center + Vector2(Global.grid_size.x, -Global.grid_size.y)
|
var t_c := grid_center + Vector2(0, -Global.grids[0].grid_size.y)
|
||||||
var m_l := grid_center + Vector2(-Global.grid_size.x, 0)
|
var t_r := grid_center + Vector2(Global.grids[0].grid_size.x, -Global.grids[0].grid_size.y)
|
||||||
|
var m_l := grid_center + Vector2(-Global.grids[0].grid_size.x, 0)
|
||||||
var m_c := grid_center
|
var m_c := grid_center
|
||||||
var m_r := grid_center + Vector2(Global.grid_size.x, 0)
|
var m_r := grid_center + Vector2(Global.grids[0].grid_size.x, 0)
|
||||||
var b_l := grid_center + Vector2(-Global.grid_size.x, Global.grid_size.y)
|
var b_l := grid_center + Vector2(-Global.grids[0].grid_size.x, Global.grids[0].grid_size.y)
|
||||||
var b_c := grid_center + Vector2(0, Global.grid_size.y)
|
var b_c := grid_center + Vector2(0, Global.grids[0].grid_size.y)
|
||||||
var b_r := grid_center + Vector2(Global.grid_size)
|
var b_r := grid_center + Vector2(Global.grids[0].grid_size)
|
||||||
var vec_arr := [t_l, t_c, t_r, m_l, m_c, m_r, b_l, b_c, b_r]
|
var vec_arr := [t_l, t_c, t_r, m_l, m_c, m_r, b_l, b_c, b_r]
|
||||||
for vec in vec_arr:
|
for vec in vec_arr:
|
||||||
if vec.distance_to(pos) < grid_center.distance_to(pos):
|
if vec.distance_to(pos) < grid_center.distance_to(pos):
|
||||||
|
|
|
@ -16,17 +16,17 @@ func _input(event: InputEvent) -> void:
|
||||||
return
|
return
|
||||||
if event.is_action_pressed("transform_snap_grid"):
|
if event.is_action_pressed("transform_snap_grid"):
|
||||||
_snap_to_grid = true
|
_snap_to_grid = true
|
||||||
_offset = _offset.snapped(Global.grid_size)
|
_offset = _offset.snapped(Global.grids[0].grid_size)
|
||||||
if Global.current_project.has_selection and selection_node.is_moving_content:
|
if Global.current_project.has_selection and selection_node.is_moving_content:
|
||||||
var prev_pos: Vector2i = selection_node.big_bounding_rectangle.position
|
var prev_pos: Vector2i = selection_node.big_bounding_rectangle.position
|
||||||
selection_node.big_bounding_rectangle.position = Vector2i(
|
selection_node.big_bounding_rectangle.position = Vector2i(
|
||||||
prev_pos.snapped(Global.grid_size)
|
prev_pos.snapped(Global.grids[0].grid_size)
|
||||||
)
|
)
|
||||||
# The first time transform_snap_grid is enabled then _snap_position() is not called
|
# The first time transform_snap_grid is enabled then _snap_position() is not called
|
||||||
# and the selection had wrong offset, so do selection offsetting here
|
# and the selection had wrong offset, so do selection offsetting here
|
||||||
var grid_offset := Vector2i(
|
var grid_offset := Vector2i(
|
||||||
fmod(Global.grid_offset.x, Global.grid_size.x),
|
fmod(Global.grids[0].grid_offset.x, Global.grids[0].grid_size.x),
|
||||||
fmod(Global.grid_offset.y, Global.grid_size.y)
|
fmod(Global.grids[0].grid_offset.y, Global.grids[0].grid_size.y)
|
||||||
)
|
)
|
||||||
selection_node.big_bounding_rectangle.position += grid_offset
|
selection_node.big_bounding_rectangle.position += grid_offset
|
||||||
selection_node.marching_ants_outline.offset += Vector2(
|
selection_node.marching_ants_outline.offset += Vector2(
|
||||||
|
@ -110,16 +110,18 @@ func _snap_position(pos: Vector2) -> Vector2:
|
||||||
else:
|
else:
|
||||||
pos.x = _start_pos.x
|
pos.x = _start_pos.x
|
||||||
if _snap_to_grid: # Snap to grid
|
if _snap_to_grid: # Snap to grid
|
||||||
pos = pos.snapped(Global.grid_size)
|
pos = pos.snapped(Global.grids[0].grid_size)
|
||||||
# The part below only corrects the offset for situations when there is no selection
|
# The part below only corrects the offset for situations when there is no selection
|
||||||
# Offsets when there is selection is controlled in _input() function
|
# Offsets when there is selection is controlled in _input() function
|
||||||
if !Global.current_project.has_selection:
|
if !Global.current_project.has_selection:
|
||||||
var move_offset := Vector2.ZERO
|
var move_offset := Vector2.ZERO
|
||||||
move_offset.x = (
|
move_offset.x = (
|
||||||
_start_pos.x - (_start_pos.x / Global.grid_size.x) * Global.grid_size.x
|
_start_pos.x
|
||||||
|
- (_start_pos.x / Global.grids[0].grid_size.x) * Global.grids[0].grid_size.x
|
||||||
)
|
)
|
||||||
move_offset.y = (
|
move_offset.y = (
|
||||||
_start_pos.y - (_start_pos.y / Global.grid_size.y) * Global.grid_size.y
|
_start_pos.y
|
||||||
|
- (_start_pos.y / Global.grids[0].grid_size.y) * Global.grids[0].grid_size.y
|
||||||
)
|
)
|
||||||
pos += move_offset
|
pos += move_offset
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ var layer_metadata_texture := ImageTexture.new()
|
||||||
@onready var currently_visible_frame := $CurrentlyVisibleFrame as SubViewport
|
@onready var currently_visible_frame := $CurrentlyVisibleFrame as SubViewport
|
||||||
@onready var current_frame_drawer := $CurrentlyVisibleFrame/CurrentFrameDrawer as Node2D
|
@onready var current_frame_drawer := $CurrentlyVisibleFrame/CurrentFrameDrawer as Node2D
|
||||||
@onready var tile_mode := $TileMode as Node2D
|
@onready var tile_mode := $TileMode as Node2D
|
||||||
|
@onready var color_index := $ColorIndex as Node2D
|
||||||
@onready var pixel_grid := $PixelGrid as Node2D
|
@onready var pixel_grid := $PixelGrid as Node2D
|
||||||
@onready var grid := $Grid as Node2D
|
@onready var grid := $Grid as Node2D
|
||||||
@onready var selection := $Selection as SelectionNode
|
@onready var selection := $Selection as SelectionNode
|
||||||
|
@ -67,6 +68,7 @@ func _draw() -> void:
|
||||||
current_frame_drawer.queue_redraw()
|
current_frame_drawer.queue_redraw()
|
||||||
tile_mode.queue_redraw()
|
tile_mode.queue_redraw()
|
||||||
draw_set_transform(position, rotation, scale)
|
draw_set_transform(position, rotation, scale)
|
||||||
|
color_index.queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
func _input(event: InputEvent) -> void:
|
func _input(event: InputEvent) -> void:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_scene load_steps=22 format=3 uid="uid://ba24iuv55m4l3"]
|
[gd_scene load_steps=24 format=3 uid="uid://ba24iuv55m4l3"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/UI/Canvas/Canvas.gd" id="1"]
|
[ext_resource type="Script" path="res://src/UI/Canvas/Canvas.gd" id="1"]
|
||||||
[ext_resource type="Shader" path="res://src/Shaders/BlendLayers.gdshader" id="1_253dh"]
|
[ext_resource type="Shader" path="res://src/Shaders/BlendLayers.gdshader" id="1_253dh"]
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
[ext_resource type="Script" path="res://src/UI/Canvas/Measurements.gd" id="16_nxilb"]
|
[ext_resource type="Script" path="res://src/UI/Canvas/Measurements.gd" id="16_nxilb"]
|
||||||
[ext_resource type="Shader" path="res://src/Shaders/AutoInvertColors.gdshader" id="17_lowhf"]
|
[ext_resource type="Shader" path="res://src/Shaders/AutoInvertColors.gdshader" id="17_lowhf"]
|
||||||
[ext_resource type="Script" path="res://src/UI/Canvas/ReferenceImages.gd" id="17_qfjb4"]
|
[ext_resource type="Script" path="res://src/UI/Canvas/ReferenceImages.gd" id="17_qfjb4"]
|
||||||
|
[ext_resource type="Script" path="res://src/UI/Canvas/color_index.gd" id="18_o3xx2"]
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_6b0ox"]
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_6b0ox"]
|
||||||
shader = ExtResource("1_253dh")
|
shader = ExtResource("1_253dh")
|
||||||
|
@ -26,6 +27,11 @@ shader_parameter/origin_y_positive = true
|
||||||
[sub_resource type="CanvasItemMaterial" id="1"]
|
[sub_resource type="CanvasItemMaterial" id="1"]
|
||||||
blend_mode = 4
|
blend_mode = 4
|
||||||
|
|
||||||
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ascg6"]
|
||||||
|
shader = ExtResource("17_lowhf")
|
||||||
|
shader_parameter/width = 0.05
|
||||||
|
shader_parameter/hollow_shapes = false
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id="2"]
|
[sub_resource type="ShaderMaterial" id="2"]
|
||||||
shader = ExtResource("9")
|
shader = ExtResource("9")
|
||||||
shader_parameter/width = 0.05
|
shader_parameter/width = 0.05
|
||||||
|
@ -59,6 +65,10 @@ show_behind_parent = true
|
||||||
material = SubResource("1")
|
material = SubResource("1")
|
||||||
script = ExtResource("4")
|
script = ExtResource("4")
|
||||||
|
|
||||||
|
[node name="ColorIndex" type="Node2D" parent="."]
|
||||||
|
material = SubResource("ShaderMaterial_ascg6")
|
||||||
|
script = ExtResource("18_o3xx2")
|
||||||
|
|
||||||
[node name="PixelGrid" type="Node2D" parent="."]
|
[node name="PixelGrid" type="Node2D" parent="."]
|
||||||
script = ExtResource("6")
|
script = ExtResource("6")
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
extends Node2D
|
extends Node2D
|
||||||
|
|
||||||
|
var unique_rect_lines := PackedVector2Array()
|
||||||
|
var unique_iso_lines := PackedVector2Array()
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
Global.project_switched.connect(queue_redraw)
|
Global.project_switched.connect(queue_redraw)
|
||||||
|
@ -10,54 +13,60 @@ func _draw() -> void:
|
||||||
return
|
return
|
||||||
|
|
||||||
var target_rect: Rect2i
|
var target_rect: Rect2i
|
||||||
if Global.grid_draw_over_tile_mode:
|
unique_rect_lines.clear()
|
||||||
|
unique_iso_lines.clear()
|
||||||
|
for grid_idx in range(Global.grids.size() - 1, -1, -1):
|
||||||
|
if Global.grids[grid_idx].grid_draw_over_tile_mode:
|
||||||
target_rect = Global.current_project.tiles.get_bounding_rect()
|
target_rect = Global.current_project.tiles.get_bounding_rect()
|
||||||
else:
|
else:
|
||||||
target_rect = Rect2i(Vector2i.ZERO, Global.current_project.size)
|
target_rect = Rect2i(Vector2i.ZERO, Global.current_project.size)
|
||||||
if not target_rect.has_area():
|
if not target_rect.has_area():
|
||||||
return
|
return
|
||||||
|
|
||||||
var grid_type := Global.grid_type
|
var grid_type := Global.grids[grid_idx].grid_type
|
||||||
if grid_type == Global.GridTypes.CARTESIAN || grid_type == Global.GridTypes.ALL:
|
if grid_type == Global.GridTypes.CARTESIAN || grid_type == Global.GridTypes.ALL:
|
||||||
_draw_cartesian_grid(target_rect)
|
_draw_cartesian_grid(grid_idx, target_rect)
|
||||||
|
|
||||||
if grid_type == Global.GridTypes.ISOMETRIC || grid_type == Global.GridTypes.ALL:
|
if grid_type == Global.GridTypes.ISOMETRIC || grid_type == Global.GridTypes.ALL:
|
||||||
_draw_isometric_grid(target_rect)
|
_draw_isometric_grid(grid_idx, target_rect)
|
||||||
|
|
||||||
|
|
||||||
func _draw_cartesian_grid(target_rect: Rect2i) -> void:
|
func _draw_cartesian_grid(grid_index: int, target_rect: Rect2i) -> void:
|
||||||
|
var grid = Global.grids[grid_index]
|
||||||
var grid_multiline_points := PackedVector2Array()
|
var grid_multiline_points := PackedVector2Array()
|
||||||
|
|
||||||
var x: float = (
|
var x: float = (
|
||||||
target_rect.position.x
|
target_rect.position.x
|
||||||
+ fposmod(Global.grid_offset.x - target_rect.position.x, Global.grid_size.x)
|
+ fposmod(grid.grid_offset.x - target_rect.position.x, grid.grid_size.x)
|
||||||
)
|
)
|
||||||
while x <= target_rect.end.x:
|
while x <= target_rect.end.x:
|
||||||
|
if not Vector2(x, target_rect.position.y) in unique_rect_lines:
|
||||||
grid_multiline_points.push_back(Vector2(x, target_rect.position.y))
|
grid_multiline_points.push_back(Vector2(x, target_rect.position.y))
|
||||||
grid_multiline_points.push_back(Vector2(x, target_rect.end.y))
|
grid_multiline_points.push_back(Vector2(x, target_rect.end.y))
|
||||||
x += Global.grid_size.x
|
x += grid.grid_size.x
|
||||||
|
|
||||||
var y: float = (
|
var y: float = (
|
||||||
target_rect.position.y
|
target_rect.position.y
|
||||||
+ fposmod(Global.grid_offset.y - target_rect.position.y, Global.grid_size.y)
|
+ fposmod(grid.grid_offset.y - target_rect.position.y, grid.grid_size.y)
|
||||||
)
|
)
|
||||||
while y <= target_rect.end.y:
|
while y <= target_rect.end.y:
|
||||||
|
if not Vector2(target_rect.position.x, y) in unique_rect_lines:
|
||||||
grid_multiline_points.push_back(Vector2(target_rect.position.x, y))
|
grid_multiline_points.push_back(Vector2(target_rect.position.x, y))
|
||||||
grid_multiline_points.push_back(Vector2(target_rect.end.x, y))
|
grid_multiline_points.push_back(Vector2(target_rect.end.x, y))
|
||||||
y += Global.grid_size.y
|
y += grid.grid_size.y
|
||||||
|
|
||||||
|
unique_rect_lines.append_array(grid_multiline_points)
|
||||||
if not grid_multiline_points.is_empty():
|
if not grid_multiline_points.is_empty():
|
||||||
draw_multiline(grid_multiline_points, Global.grid_color)
|
draw_multiline(grid_multiline_points, grid.grid_color)
|
||||||
|
|
||||||
|
|
||||||
func _draw_isometric_grid(target_rect: Rect2i) -> void:
|
func _draw_isometric_grid(grid_index: int, target_rect: Rect2i) -> void:
|
||||||
|
var grid = Global.grids[grid_index]
|
||||||
var grid_multiline_points := PackedVector2Array()
|
var grid_multiline_points := PackedVector2Array()
|
||||||
|
|
||||||
var cell_size: Vector2 = Global.isometric_grid_size
|
var cell_size: Vector2 = grid.isometric_grid_size
|
||||||
var max_cell_count: Vector2 = Vector2(target_rect.size) / cell_size
|
var max_cell_count: Vector2 = Vector2(target_rect.size) / cell_size
|
||||||
var origin_offset: Vector2 = Vector2(Global.grid_offset - target_rect.position).posmodv(
|
var origin_offset: Vector2 = Vector2(grid.grid_offset - target_rect.position).posmodv(cell_size)
|
||||||
cell_size
|
|
||||||
)
|
|
||||||
|
|
||||||
# lines ↗↗↗ (from bottom-left to top-right)
|
# lines ↗↗↗ (from bottom-left to top-right)
|
||||||
var per_cell_offset: Vector2 = cell_size * Vector2(1, -1)
|
var per_cell_offset: Vector2 = cell_size * Vector2(1, -1)
|
||||||
|
@ -70,6 +79,7 @@ func _draw_isometric_grid(target_rect: Rect2i) -> void:
|
||||||
var start: Vector2 = Vector2(target_rect.position) + Vector2(0, y)
|
var start: Vector2 = Vector2(target_rect.position) + Vector2(0, y)
|
||||||
var cells_to_rect_bounds: float = minf(max_cell_count.x, y / cell_size.y)
|
var cells_to_rect_bounds: float = minf(max_cell_count.x, y / cell_size.y)
|
||||||
var end := start + cells_to_rect_bounds * per_cell_offset
|
var end := start + cells_to_rect_bounds * per_cell_offset
|
||||||
|
if not start in unique_iso_lines:
|
||||||
grid_multiline_points.push_back(start)
|
grid_multiline_points.push_back(start)
|
||||||
grid_multiline_points.push_back(end)
|
grid_multiline_points.push_back(end)
|
||||||
y += cell_size.y
|
y += cell_size.y
|
||||||
|
@ -80,6 +90,7 @@ func _draw_isometric_grid(target_rect: Rect2i) -> void:
|
||||||
var start: Vector2 = Vector2(target_rect.position) + Vector2(x, target_rect.size.y)
|
var start: Vector2 = Vector2(target_rect.position) + Vector2(x, target_rect.size.y)
|
||||||
var cells_to_rect_bounds: float = minf(max_cell_count.y, max_cell_count.x - x / cell_size.x)
|
var cells_to_rect_bounds: float = minf(max_cell_count.y, max_cell_count.x - x / cell_size.x)
|
||||||
var end: Vector2 = start + cells_to_rect_bounds * per_cell_offset
|
var end: Vector2 = start + cells_to_rect_bounds * per_cell_offset
|
||||||
|
if not start in unique_iso_lines:
|
||||||
grid_multiline_points.push_back(start)
|
grid_multiline_points.push_back(start)
|
||||||
grid_multiline_points.push_back(end)
|
grid_multiline_points.push_back(end)
|
||||||
x += cell_size.x
|
x += cell_size.x
|
||||||
|
@ -93,6 +104,7 @@ func _draw_isometric_grid(target_rect: Rect2i) -> void:
|
||||||
var start: Vector2 = Vector2(target_rect.position) + Vector2(0, y)
|
var start: Vector2 = Vector2(target_rect.position) + Vector2(0, y)
|
||||||
var cells_to_rect_bounds: float = minf(max_cell_count.x, max_cell_count.y - y / cell_size.y)
|
var cells_to_rect_bounds: float = minf(max_cell_count.x, max_cell_count.y - y / cell_size.y)
|
||||||
var end: Vector2 = start + cells_to_rect_bounds * per_cell_offset
|
var end: Vector2 = start + cells_to_rect_bounds * per_cell_offset
|
||||||
|
if not start in unique_iso_lines:
|
||||||
grid_multiline_points.push_back(start)
|
grid_multiline_points.push_back(start)
|
||||||
grid_multiline_points.push_back(end)
|
grid_multiline_points.push_back(end)
|
||||||
y += cell_size.y
|
y += cell_size.y
|
||||||
|
@ -103,9 +115,11 @@ func _draw_isometric_grid(target_rect: Rect2i) -> void:
|
||||||
var start: Vector2 = Vector2(target_rect.position) + Vector2(x, 0)
|
var start: Vector2 = Vector2(target_rect.position) + Vector2(x, 0)
|
||||||
var cells_to_rect_bounds: float = minf(max_cell_count.y, max_cell_count.x - x / cell_size.x)
|
var cells_to_rect_bounds: float = minf(max_cell_count.y, max_cell_count.x - x / cell_size.x)
|
||||||
var end: Vector2 = start + cells_to_rect_bounds * per_cell_offset
|
var end: Vector2 = start + cells_to_rect_bounds * per_cell_offset
|
||||||
|
if not start in unique_iso_lines:
|
||||||
grid_multiline_points.push_back(start)
|
grid_multiline_points.push_back(start)
|
||||||
grid_multiline_points.push_back(end)
|
grid_multiline_points.push_back(end)
|
||||||
x += cell_size.x
|
x += cell_size.x
|
||||||
|
grid_multiline_points.append_array(grid_multiline_points)
|
||||||
|
|
||||||
if not grid_multiline_points.is_empty():
|
if not grid_multiline_points.is_empty():
|
||||||
draw_multiline(grid_multiline_points, Global.grid_color)
|
draw_multiline(grid_multiline_points, grid.grid_color)
|
||||||
|
|
|
@ -214,7 +214,7 @@ func _move_with_arrow_keys(event: InputEvent) -> void:
|
||||||
if _is_action_direction(event) and arrow_key_move:
|
if _is_action_direction(event) and arrow_key_move:
|
||||||
var step := Vector2.ONE
|
var step := Vector2.ONE
|
||||||
if Input.is_key_pressed(KEY_CTRL):
|
if Input.is_key_pressed(KEY_CTRL):
|
||||||
step = Global.grid_size
|
step = Global.grids[0].grid_size
|
||||||
var input := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
|
var input := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
|
||||||
var move := input.rotated(snappedf(Global.camera.rotation, PI / 2))
|
var move := input.rotated(snappedf(Global.camera.rotation, PI / 2))
|
||||||
# These checks are needed to fix a bug where the selection got stuck
|
# These checks are needed to fix a bug where the selection got stuck
|
||||||
|
|
54
src/UI/Canvas/color_index.gd
Normal file
54
src/UI/Canvas/color_index.gd
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
const FONT_SIZE = 16
|
||||||
|
|
||||||
|
var users := 1
|
||||||
|
var enabled: bool = false:
|
||||||
|
set(value):
|
||||||
|
enabled = value
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
Global.camera.zoom_changed.connect(queue_redraw)
|
||||||
|
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
if not enabled:
|
||||||
|
return
|
||||||
|
# when we zoom out there is a visual issue that inverts the text
|
||||||
|
# (kind of how you look through a magnifying glass)
|
||||||
|
# so we should restrict the rendering distance of this preview.
|
||||||
|
var zoom_percentage := 100.0 * Global.camera.zoom.x
|
||||||
|
if zoom_percentage < Global.pixel_grid_show_at_zoom:
|
||||||
|
return
|
||||||
|
var project = ExtensionsApi.project.current_project
|
||||||
|
var cel: BaseCel = project.frames[project.current_frame].cels[project.current_layer]
|
||||||
|
if not cel is PixelCel:
|
||||||
|
return
|
||||||
|
var index_image: Image = cel.image.indices_image
|
||||||
|
if index_image.get_size() != project.size or not cel.image.is_indexed:
|
||||||
|
return
|
||||||
|
|
||||||
|
var used_rect: Rect2i = cel.image.get_used_rect()
|
||||||
|
if used_rect.size != Vector2i.ZERO:
|
||||||
|
# use smaller image for optimization
|
||||||
|
index_image = index_image.get_region(used_rect)
|
||||||
|
|
||||||
|
var font: Font = ExtensionsApi.theme.get_theme().default_font
|
||||||
|
var offset = position + Vector2(used_rect.position)
|
||||||
|
draw_set_transform(offset, rotation, Vector2(0.05, 0.05))
|
||||||
|
for x in range(index_image.get_size().x):
|
||||||
|
for y in range(index_image.get_size().y):
|
||||||
|
var index := index_image.get_pixel(x, y).r8
|
||||||
|
if index == 0:
|
||||||
|
continue
|
||||||
|
draw_string(
|
||||||
|
font,
|
||||||
|
Vector2(x, y) * 20 + Vector2.DOWN * 16,
|
||||||
|
str(index),
|
||||||
|
HORIZONTAL_ALIGNMENT_LEFT,
|
||||||
|
-1,
|
||||||
|
FONT_SIZE if (index < 100) else int(FONT_SIZE / 1.5)
|
||||||
|
)
|
||||||
|
draw_set_transform(position, rotation, scale)
|
|
@ -44,7 +44,6 @@ size_flags_vertical = 3
|
||||||
[node name="TransparentChecker" parent="VBoxContainer/VSplitContainer/PreviewPanel" instance=ExtResource("2")]
|
[node name="TransparentChecker" parent="VBoxContainer/VSplitContainer/PreviewPanel" instance=ExtResource("2")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 0
|
layout_mode = 0
|
||||||
anchors_preset = 0
|
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
|
|
||||||
|
@ -335,19 +334,23 @@ text = "Clip image content to selection"
|
||||||
mode = 2
|
mode = 2
|
||||||
title = "Open a Directory"
|
title = "Open a Directory"
|
||||||
size = Vector2i(675, 500)
|
size = Vector2i(675, 500)
|
||||||
|
always_on_top = true
|
||||||
ok_button_text = "Select Current Folder"
|
ok_button_text = "Select Current Folder"
|
||||||
file_mode = 2
|
file_mode = 2
|
||||||
access = 2
|
access = 2
|
||||||
|
|
||||||
[node name="PathValidationAlert" type="AcceptDialog" parent="."]
|
[node name="PathValidationAlert" type="AcceptDialog" parent="."]
|
||||||
|
always_on_top = true
|
||||||
dialog_text = "DirAccess path and file name are not valid!"
|
dialog_text = "DirAccess path and file name are not valid!"
|
||||||
|
|
||||||
[node name="FileExistsAlert" type="AcceptDialog" parent="."]
|
[node name="FileExistsAlert" type="AcceptDialog" parent="."]
|
||||||
|
always_on_top = true
|
||||||
dialog_text = "File %s already exists. Overwrite?"
|
dialog_text = "File %s already exists. Overwrite?"
|
||||||
|
|
||||||
[node name="ExportProgressBar" type="Window" parent="."]
|
[node name="ExportProgressBar" type="Window" parent="."]
|
||||||
visible = false
|
visible = false
|
||||||
exclusive = true
|
exclusive = true
|
||||||
|
always_on_top = true
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="ExportProgressBar"]
|
[node name="MarginContainer" type="MarginContainer" parent="ExportProgressBar"]
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
|
|
|
@ -232,6 +232,7 @@ func _setup_view_menu() -> void:
|
||||||
"Mirror View": "mirror_view",
|
"Mirror View": "mirror_view",
|
||||||
"Show Grid": "show_grid",
|
"Show Grid": "show_grid",
|
||||||
"Show Pixel Grid": "show_pixel_grid",
|
"Show Pixel Grid": "show_pixel_grid",
|
||||||
|
"Show Pixel Indices": "show_pixel_indices",
|
||||||
"Show Rulers": "show_rulers",
|
"Show Rulers": "show_rulers",
|
||||||
"Show Guides": "show_guides",
|
"Show Guides": "show_guides",
|
||||||
"Show Mouse Guides": "",
|
"Show Mouse Guides": "",
|
||||||
|
@ -261,6 +262,9 @@ func _setup_view_menu() -> void:
|
||||||
var draw_pixel_grid: bool = Global.config_cache.get_value(
|
var draw_pixel_grid: bool = Global.config_cache.get_value(
|
||||||
"view_menu", "draw_pixel_grid", Global.draw_pixel_grid
|
"view_menu", "draw_pixel_grid", Global.draw_pixel_grid
|
||||||
)
|
)
|
||||||
|
var show_pixel_indices: bool = Global.config_cache.get_value(
|
||||||
|
"view_menu", "show_pixel_indices", Global.show_pixel_indices
|
||||||
|
)
|
||||||
var show_rulers: bool = Global.config_cache.get_value(
|
var show_rulers: bool = Global.config_cache.get_value(
|
||||||
"view_menu", "show_rulers", Global.show_rulers
|
"view_menu", "show_rulers", Global.show_rulers
|
||||||
)
|
)
|
||||||
|
@ -295,6 +299,8 @@ func _setup_view_menu() -> void:
|
||||||
_toggle_show_guides()
|
_toggle_show_guides()
|
||||||
if show_mouse_guides != Global.show_mouse_guides:
|
if show_mouse_guides != Global.show_mouse_guides:
|
||||||
_toggle_show_mouse_guides()
|
_toggle_show_mouse_guides()
|
||||||
|
if show_pixel_indices != Global.show_pixel_indices:
|
||||||
|
_toggle_show_pixel_indices()
|
||||||
if display_layer_effects != Global.display_layer_effects:
|
if display_layer_effects != Global.display_layer_effects:
|
||||||
Global.display_layer_effects = display_layer_effects
|
Global.display_layer_effects = display_layer_effects
|
||||||
if snap_to_rectangular_grid_boundary != Global.snap_to_rectangular_grid_boundary:
|
if snap_to_rectangular_grid_boundary != Global.snap_to_rectangular_grid_boundary:
|
||||||
|
@ -666,6 +672,8 @@ func view_menu_id_pressed(id: int) -> void:
|
||||||
_toggle_show_guides()
|
_toggle_show_guides()
|
||||||
Global.ViewMenu.SHOW_MOUSE_GUIDES:
|
Global.ViewMenu.SHOW_MOUSE_GUIDES:
|
||||||
_toggle_show_mouse_guides()
|
_toggle_show_mouse_guides()
|
||||||
|
Global.ViewMenu.SHOW_PIXEL_INDICES:
|
||||||
|
_toggle_show_pixel_indices()
|
||||||
Global.ViewMenu.DISPLAY_LAYER_EFFECTS:
|
Global.ViewMenu.DISPLAY_LAYER_EFFECTS:
|
||||||
Global.display_layer_effects = not Global.display_layer_effects
|
Global.display_layer_effects = not Global.display_layer_effects
|
||||||
_:
|
_:
|
||||||
|
@ -820,6 +828,11 @@ func _toggle_show_pixel_grid() -> void:
|
||||||
view_menu.set_item_checked(Global.ViewMenu.SHOW_PIXEL_GRID, Global.draw_pixel_grid)
|
view_menu.set_item_checked(Global.ViewMenu.SHOW_PIXEL_GRID, Global.draw_pixel_grid)
|
||||||
|
|
||||||
|
|
||||||
|
func _toggle_show_pixel_indices() -> void:
|
||||||
|
Global.show_pixel_indices = !Global.show_pixel_indices
|
||||||
|
view_menu.set_item_checked(Global.ViewMenu.SHOW_PIXEL_INDICES, Global.show_pixel_indices)
|
||||||
|
|
||||||
|
|
||||||
func _toggle_show_rulers() -> void:
|
func _toggle_show_rulers() -> void:
|
||||||
Global.show_rulers = !Global.show_rulers
|
Global.show_rulers = !Global.show_rulers
|
||||||
view_menu.set_item_checked(Global.ViewMenu.SHOW_RULERS, Global.show_rulers)
|
view_menu.set_item_checked(Global.ViewMenu.SHOW_RULERS, Global.show_rulers)
|
||||||
|
|
Loading…
Reference in a new issue