1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 17:19:50 +00:00

Reference Image Improvements (#961)

* Reference Image Updates

* Fixed static typing

Fixed static typing in "src\UI
\ReferenceImages\ReferenceEditPanel.gd"
Changed "ri == null" to "!ri" in "src\UI\Canvas\ReferenceImages.gd"

* Tried fixing the static typing again

Removed lambda functions for the confirmation dialog.
Removed irrelevant print statement.

* Tried fixing static typing again

I think its fixed now

* Changed Spacing

* Fixed Trailing Whitespaces and tabs

* Fixed Final Trailing Whitespace

* Fixed styling and removed useless enum

* Removed double tabs left over from previous commit

* Fixed remove ConfirmDialog Showing on startusp

* Tried Fixing gdlint issues

* Fixed Linting

* Fixed Spelling issues

* Drag and drop to rearrange reference images

Added the ability to drag and drop Reference Images similar to dragging and dropping layers. These can be dragged or used with buttons (similar to the buttons that move frames). With full undo/redo support.

Added tool buttons these should help people who draw on tablets that cannot use keyboard shortcuts (icons still need to be created)

Renamed ReferenceEditPanel.gd to ReferenceEdit.gd (because it is no longer the script of a panel) and changed the base class of the Reference Panel.

Added some more translations.

Remade ReferenceImageButton.tscn to allow for drag and drop

Added drag highlight

* Added Icons

Added icons for the tools of the Reference Images

* Applied the icons to the UI

* Fix Scripting Issues

* Fixed Linting

* Rename Move.png to move.png

* Update Canvas.gd

* Updated the tooltips

Also added the correct translations

* Rename Select.png to select.png

* Rename Select.png.import to select.png.import

* Rename Move.png.import to move.png.import

* Rename Rotate.png to rotate.png

* Rename Rotate.png.import to rotate.png.import

* Fixed import files

* Rename Scale.png to scale.png

* Rename Scale.png.import to scale.png.import

* Added logic to update the reference panel when the project changes

Also fixed visual bugs related to highlighting the current reference image.

Made it so the reference image that was selected in a project get selected again when the project opens instead of going back to -1 (nothing)

* Update Project.gd
This commit is contained in:
TheLsbt 2023-12-31 14:12:37 +02:00 committed by GitHub
parent 87b5a818bb
commit c8f37943d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 1518 additions and 290 deletions

View file

@ -2780,10 +2780,36 @@ msgstr ""
msgid "Spring towards the end" msgid "Spring towards the end"
msgstr "" msgstr ""
msgid "Silhouette" #. Used to turn images into a singular color
msgid "Monochrome"
msgstr "" msgstr ""
msgid "Blacks out the image and makes all opaque pixels a dark color." #. A tooltip to tell users to hold the Shift key while clicking the remove button
msgid "Hold Shift while pressing to instantly remove"
msgstr ""
#. Moves the reference image up in the list
msgid "Move the selected reference image to the right"
msgstr ""
#. Moves the reference image down in the list
msgid "Move the selected reference image to the left"
msgstr ""
#. Select a reference on the canvas
msgid "Selects a reference image on the canvas"
msgstr ""
#. Moves the reference on the canvas
msgid "Move the selected reference image"
msgstr ""
#. Rotates the reference on the canvas
msgid "Rotate the selected reference image"
msgstr ""
#. Rotates the reference on the canvas
msgid "Scale the selected reference image"
msgstr "" msgstr ""
#. Used in checkbuttons (like on/off switches) that enable/disable something. #. Used in checkbuttons (like on/off switches) that enable/disable something.

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cedsyi8gf2n2i"
path="res://.godot/imported/move.png-ed702c0a346cd77f0de30a0cba128fc7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/graphics/reference_images/move.png"
dest_files=["res://.godot/imported/move.png-ed702c0a346cd77f0de30a0cba128fc7.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dtd43nvphu3jj"
path="res://.godot/imported/rotate.png-456db7ada5d7cd37fa30dc5557b226be.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/graphics/reference_images/rotate.png"
dest_files=["res://.godot/imported/rotate.png-456db7ada5d7cd37fa30dc5557b226be.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://nfabwr5mgdir"
path="res://.godot/imported/scale.png-475926e4af79bb726ef59440df6e6f71.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/graphics/reference_images/scale.png"
dest_files=["res://.godot/imported/scale.png-475926e4af79bb726ef59440df6e6f71.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d2m7enib3dplc"
path="res://.godot/imported/select.png-7c7e96d5ba897a73341e1d0445a3c991.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/graphics/reference_images/select.png"
dest_files=["res://.godot/imported/select.png-7c7e96d5ba897a73341e1d0445a3c991.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -820,6 +820,26 @@ onion_skinning_settings={
"deadzone": 0.5, "deadzone": 0.5,
"events": [] "events": []
} }
reference_rotate={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
reference_scale={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194328,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
reference_quick_menu={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":82,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
cancel_reference_transform={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
[internationalization] [internationalization]

View file

@ -466,6 +466,10 @@ var cel_button_scene: PackedScene = load("res://src/UI/Timeline/CelButton.tscn")
## The perspective editor. It has the [param PerspectiveEditor.gd] script attached. ## The perspective editor. It has the [param PerspectiveEditor.gd] script attached.
@onready var perspective_editor := control.find_child("Perspective Editor") @onready var perspective_editor := control.find_child("Perspective Editor")
## The reference panel. It has the [param ReferencesPanel.gd] script attached.
@onready var reference_panel: ReferencesPanel = control.find_child("Reference Images")
## The top menu container. It has the [param TopMenuContainer.gd] script attached. ## The top menu container. It has the [param TopMenuContainer.gd] script attached.
@onready var top_menu_container: Panel = control.find_child("TopMenuContainer") @onready var top_menu_container: Panel = control.find_child("TopMenuContainer")
## The label indicating cursor position. ## The label indicating cursor position.
@ -657,6 +661,10 @@ func _initialize_keychain() -> void:
Keychain.InputAction.new("", "Transformation tools", false), Keychain.InputAction.new("", "Transformation tools", false),
"transform_copy_selection_content": "transform_copy_selection_content":
Keychain.InputAction.new("", "Transformation tools", false), Keychain.InputAction.new("", "Transformation tools", false),
"reference_rotate": Keychain.InputAction.new("", "Reference images", false),
"reference_scale": Keychain.InputAction.new("", "Reference images", false),
"reference_quick_menu": Keychain.InputAction.new("", "Reference images", false),
"cancel_reference_transform": Keychain.InputAction.new("", "Reference images", false)
} }
Keychain.groups = { Keychain.groups = {
@ -679,6 +687,7 @@ func _initialize_keychain() -> void:
"Shape tools": Keychain.InputGroup.new("Tool modifiers"), "Shape tools": Keychain.InputGroup.new("Tool modifiers"),
"Selection tools": Keychain.InputGroup.new("Tool modifiers"), "Selection tools": Keychain.InputGroup.new("Tool modifiers"),
"Transformation tools": Keychain.InputGroup.new("Tool modifiers"), "Transformation tools": Keychain.InputGroup.new("Tool modifiers"),
"Reference images": Keychain.InputGroup.new("Canvas")
} }
Keychain.ignore_actions = ["left_mouse", "right_mouse", "middle_mouse", "shift", "ctrl"] Keychain.ignore_actions = ["left_mouse", "right_mouse", "middle_mouse", "shift", "ctrl"]

View file

@ -750,7 +750,7 @@ func import_reference_image_from_path(path: String) -> void:
var ri := ReferenceImage.new() var ri := ReferenceImage.new()
ri.project = project ri.project = project
ri.deserialize({"image_path": path}) ri.deserialize({"image_path": path})
Global.canvas.add_child(ri) Global.canvas.reference_image_container.add_child(ri)
reference_image_imported.emit() reference_image_imported.emit()
@ -760,7 +760,7 @@ func import_reference_image_from_image(image: Image) -> void:
var ri := ReferenceImage.new() var ri := ReferenceImage.new()
ri.project = project ri.project = project
ri.create_from_image(image) ri.create_from_image(image)
Global.canvas.add_child(ri) Global.canvas.reference_image_container.add_child(ri)
reference_image_imported.emit() reference_image_imported.emit()

View file

@ -45,6 +45,7 @@ var animation_tags: Array[AnimationTag] = []:
var guides: Array[Guide] = [] var guides: Array[Guide] = []
var brushes: Array[Image] = [] var brushes: Array[Image] = []
var reference_images: Array[ReferenceImage] = [] var reference_images: Array[ReferenceImage] = []
var reference_index: int = -1 # The currently selected index ReferenceImage
var vanishing_points := [] ## Array of Vanishing Points var vanishing_points := [] ## Array of Vanishing Points
var fps := 6.0 var fps := 6.0
@ -250,6 +251,21 @@ func change_project() -> void:
var edit_menu_popup: PopupMenu = Global.top_menu_container.edit_menu var edit_menu_popup: PopupMenu = Global.top_menu_container.edit_menu
edit_menu_popup.set_item_disabled(Global.EditMenu.NEW_BRUSH, !has_selection) edit_menu_popup.set_item_disabled(Global.EditMenu.NEW_BRUSH, !has_selection)
# We loop through all the reference image nodes and the ones that are not apart
# of the current project we remove from the tree
# They will still be in memory though
for ri: ReferenceImage in Global.canvas.reference_image_container.get_children():
if !reference_images.has(ri):
Global.canvas.reference_image_container.remove_child(ri)
# Now we loop through this projects reference images and add them back to the tree
var canvas_references := Global.canvas.reference_image_container.get_children()
for ri: ReferenceImage in reference_images:
if !canvas_references.has(ri) and !ri.is_inside_tree():
Global.canvas.reference_image_container.add_child(ri)
# Tell the reference images that the project changed
Global.reference_panel.project_changed()
var i := 0 var i := 0
for camera in Global.cameras: for camera in Global.cameras:
camera.rotation = cameras_rotation[i] camera.rotation = cameras_rotation[i]
@ -870,3 +886,28 @@ func _update_layer_ui() -> void:
for f in frames.size(): for f in frames.size():
cel_hbox.get_child(f).layer = l cel_hbox.get_child(f).layer = l
cel_hbox.get_child(f).button_setup() cel_hbox.get_child(f).button_setup()
## Change the current reference image
func set_reference_image_index(new_index: int) -> void:
reference_index = clamp(-1, new_index, reference_images.size() - 1)
Global.canvas.reference_image_container.update_index(reference_index)
## Returns the reference image based on reference_index
func get_current_reference_image() -> ReferenceImage:
return get_reference_image(reference_index)
## Returns the reference image based on the index or null if index < 0
func get_reference_image(index: int) -> ReferenceImage:
if index < 0 or index > reference_images.size() - 1:
return null
return reference_images[index]
## Reorders the position of the reference image in the tree / reference_images array
func reorder_reference_image(from: int, to: int) -> void:
var ri: ReferenceImage = reference_images.pop_at(from)
reference_images.insert(to, ri)
Global.canvas.reference_image_container.move_child(ri, to)

View file

@ -0,0 +1,21 @@
shader_type canvas_item;
// This shader gets applied to every single reference image.
uniform bool monochrome = false;
// Used because modulate does not work when monochrome is true
uniform vec4 monchrome_color : source_color;
// Clamp the color by using the greyscale of the image to identify the brightness of each pixel
uniform float clamping : hint_range(0.0, 1.0, 0.01) = 0.0;
void fragment() {
// The original color
vec4 color = texture(TEXTURE, UV);
// Get the greyscale based on the brightest channel
float greyscale = max(max(color.r, color.g), color.b);
// Dont Use Alpha Channel past this statement!
if (greyscale < clamping) COLOR.a = 0.0;
// If we want the image to be onochrome we just set that pixels rgb color.
if (monochrome) COLOR.rgb = monchrome_color.rgb;
}

View file

@ -1,14 +0,0 @@
shader_type canvas_item;
uniform vec4 silhouette_color;
uniform bool show_silhouette;
void fragment() {
vec4 color = texture(TEXTURE, UV);
if (show_silhouette && color.a > 0.0) {
color.rgb = silhouette_color.rgb;
COLOR.rgb = color.rgb;
} else {
COLOR = color;
}
}

View file

@ -26,6 +26,7 @@ var layer_metadata_texture := ImageTexture.new()
@onready var mouse_guide_container := $MouseGuideContainer as Node2D @onready var mouse_guide_container := $MouseGuideContainer as Node2D
@onready var gizmos_3d := $Gizmos3D as Node2D @onready var gizmos_3d := $Gizmos3D as Node2D
@onready var measurements := $Measurements as Node2D @onready var measurements := $Measurements as Node2D
@onready var reference_image_container := $ReferenceImages as Node2D
func _ready() -> void: func _ready() -> void:

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=21 format=3 uid="uid://ba24iuv55m4l3"] [gd_scene load_steps=22 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"]
@ -16,6 +16,7 @@
[ext_resource type="Script" path="res://src/UI/Canvas/CropRect.gd" id="13"] [ext_resource type="Script" path="res://src/UI/Canvas/CropRect.gd" id="13"]
[ext_resource type="Script" path="res://src/UI/Canvas/Gizmos3D.gd" id="14"] [ext_resource type="Script" path="res://src/UI/Canvas/Gizmos3D.gd" id="14"]
[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="Script" path="res://src/UI/Canvas/ReferenceImages.gd" id="17_qfjb4"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_6b0ox"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_6b0ox"]
shader = ExtResource("1_253dh") shader = ExtResource("1_253dh")
@ -93,3 +94,6 @@ script = ExtResource("14")
[node name="Measurements" type="Node2D" parent="."] [node name="Measurements" type="Node2D" parent="."]
script = ExtResource("16_nxilb") script = ExtResource("16_nxilb")
[node name="ReferenceImages" type="Node2D" parent="."]
script = ExtResource("17_qfjb4")

View file

@ -0,0 +1,334 @@
extends Node2D
## This node contains [ReferenceImage] nodes
signal reference_image_changed(index: int)
enum Mode { SELECT, MOVE, ROTATE, SCALE }
var mode: Mode = Mode.SELECT
var index: int:
get:
return Global.current_project.reference_index
var drag_start_pos: Vector2
var dragging := false
var lmb_held := false ## Holds whether the LBB is being held (use dragging for actual checks)
# Original Transform
var og_pos: Vector2
var og_scale: Vector2
var og_rotation: float
var undo_data: Dictionary
var reference_menu := PopupMenu.new()
func _ready() -> void:
Global.camera.zoom_changed.connect(_update_on_zoom)
Global.control.get_node("Dialogs").add_child(reference_menu)
# Makes sure that the dark overlay disappears when the popup is hidden
reference_menu.visibility_changed.connect(func(): Global.dialog_open(reference_menu.visible))
# Emitted when a item is selected from the menu
reference_menu.id_pressed.connect(_reference_menu_id_pressed)
## Updates the index and configures the "gizmo"
func update_index(new_index: int) -> void:
index = new_index
reference_image_changed.emit(new_index)
queue_redraw()
func _input(event: InputEvent) -> void:
var local_mouse_pos := get_local_mouse_position()
# Check if that event was for the quick menu (opened by the shortcut)
if event.is_action_pressed("reference_quick_menu"):
var list: Array[ReferenceImage] = Global.current_project.reference_images
populate_reference_menu(list, true)
reference_menu.position = Global.control.get_global_mouse_position()
reference_menu.popup()
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
Global.can_draw = true
return
# Check if want to cancelthe reference transform
if event.is_action_pressed("cancel_reference_transform") and dragging:
ri.position = og_pos
ri.scale = og_scale
ri.rotation = og_rotation
dragging = false
Global.can_draw = true
commit_undo("Cancel Transform Content", undo_data)
return
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT:
if event.is_pressed():
dragging = false
lmb_held = true
undo_data = get_undo_data()
Global.can_draw = false
drag_start_pos = get_local_mouse_position()
# Set the original positions
og_pos = ri.position
og_scale = ri.scale
og_rotation = ri.rotation
if !event.is_pressed():
Global.can_draw = true
if dragging:
commit_undo("Transform Content", undo_data)
else:
# Overlapping reference images
var overlapping: Array[ReferenceImage] = []
for idx: int in Global.current_project.reference_images.size():
var r = Global.current_project.reference_images[idx]
# The bounding polygon
var p := get_reference_polygon(idx)
if Geometry2D.is_point_in_polygon(local_mouse_pos, p):
overlapping.append(r)
# Some special cases
# 1. There is only one Reference Image
if overlapping.size() == 1:
var idx := overlapping[0].get_index()
Global.current_project.set_reference_image_index(idx)
# 2. There are more than 1 Reference Images
elif overlapping.size() > 1:
populate_reference_menu(overlapping, true)
reference_menu.position = Global.control.get_global_mouse_position()
reference_menu.popup()
# 3. There are no Reference Images
else:
Global.current_project.set_reference_image_index(-1)
undo_data.clear()
dragging = false
lmb_held = false
if event is InputEventMouseMotion:
# We check if the LMB is pressed and if we're not dragging then we force the
# draggin state.
# We dont use timers because it makes more sense to wait for the users mouse to move
# and that's what defines dragging. It would be smart to add a "deadzone" to determine
# if the mouse had moved enough.
if lmb_held and !dragging:
dragging = true
if dragging:
var text := ""
if mode == Mode.SELECT:
# Scale
if Input.is_action_pressed("reference_scale"):
scale_reference_image(local_mouse_pos, ri)
text = str(
"Moving: ", (og_scale * 100).floor(), " -> ", (ri.scale * 100).floor()
)
# Rotate
elif Input.is_action_pressed("reference_rotate"):
rotate_reference_image(local_mouse_pos, ri)
text = str(
"Rotating: ",
floorf(rad_to_deg(og_rotation)),
"° -> ",
floorf(rad_to_deg(ri.rotation)),
"°"
)
else:
move_reference_image(local_mouse_pos, ri)
text = str("Moving to: ", og_pos.floor(), " -> ", ri.position.floor())
elif mode == Mode.MOVE:
move_reference_image(local_mouse_pos, ri)
text = str("Moving to: ", og_pos.floor(), " -> ", ri.position.floor())
elif mode == Mode.ROTATE:
rotate_reference_image(local_mouse_pos, ri)
text = str(
"Rotating: ",
floorf(rad_to_deg(og_rotation)),
"° -> ",
floorf(rad_to_deg(ri.rotation)),
"°"
)
elif mode == Mode.SCALE:
scale_reference_image(local_mouse_pos, ri)
text = str("Moving: ", (og_scale * 100).floor(), " -> ", (ri.scale * 100).floor())
Global.cursor_position_label.text = text
queue_redraw()
## Uniformly scales the [ReferenceImage] using this nodes "local_mouse_position".
func scale_reference_image(mouse_pos: Vector2, img: ReferenceImage) -> void:
var s = (
Vector2.ONE
* minf(
float(mouse_pos.x - drag_start_pos.x),
float(mouse_pos.y - drag_start_pos.y),
)
)
img.scale = (og_scale + (s / 100.0))
## Rotate the [ReferenceImage] using this nodes "local_mouse_position".
func rotate_reference_image(mouse_pos: Vector2, img: ReferenceImage) -> void:
var starting_angle = og_rotation - og_pos.angle_to_point(drag_start_pos)
var new_angle = img.position.angle_to_point(mouse_pos)
var angle = starting_angle + new_angle
angle = deg_to_rad(floorf(rad_to_deg(wrapf(angle, -PI, PI))))
img.rotation = angle
## Move the [ReferenceImage] using this nodes "local_mouse_position".
func move_reference_image(mouse_pos: Vector2, img: ReferenceImage) -> void:
img.position = (mouse_pos - (drag_start_pos - og_pos)).floor()
## Makes a polygon that matches the transformed [ReferenceImage]
func get_reference_polygon(i: int) -> PackedVector2Array:
if i < 0:
return []
var ri: ReferenceImage = Global.current_project.reference_images[i]
var rect := ri.get_rect()
var poly = get_transformed_rect_polygon(rect, ri.transform)
return poly
## Returns a [PackedVector2Array] based on the corners of the [Rect2].
## This function also transforms the polygon.
func get_transformed_rect_polygon(rect: Rect2, t: Transform2D) -> PackedVector2Array:
# First we scale the Rect2
rect.position *= t.get_scale()
rect.size *= t.get_scale()
# We create a polygon based on the Rect2
var p: PackedVector2Array = [
rect.position,
Vector2(rect.end.x, rect.position.y),
rect.end,
Vector2(rect.position.x, rect.end.y)
]
# Finally rotate and move the polygon
var final: PackedVector2Array = []
for v: Vector2 in p:
var vert := v.rotated(t.get_rotation()) + t.get_origin()
final.append(vert)
return final
func populate_reference_menu(items: Array[ReferenceImage], default := false):
reference_menu.clear()
# Default / Reset
if default:
reference_menu.add_item("None", 0)
reference_menu.add_separator()
for ri: ReferenceImage in items:
var idx: int = ri.get_index() + 1
var label: String = "(%o) %s" % [idx, ri.image_path]
# We trim the length of the title
label = label.left(22) + "..."
reference_menu.add_item(label, idx)
# When a id is pressed in the reference menu
func _reference_menu_id_pressed(id: int) -> void:
Global.can_draw = true
Global.current_project.set_reference_image_index(id - 1)
reference_menu.hide()
func remove_reference_image(idx: int) -> void:
var ri: ReferenceImage = Global.current_project.get_reference_image(idx)
Global.current_project.reference_images.remove_at(idx)
ri.queue_free()
Global.current_project.set_reference_image_index(-1)
Global.current_project.change_project()
Global.control.ui.find_child("Reference Images")._on_references_changed()
func _update_on_zoom() -> void:
queue_redraw()
func get_undo_data() -> Dictionary:
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return {}
var data := {}
data["position"] = ri.position
data["scale"] = ri.scale
data["rotation"] = ri.rotation
data["overlay_color"] = ri.overlay_color
data["filter"] = ri.filter
data["monochrome"] = ri.monochrome
data["color_clamping"] = ri.color_clamping
return data
func commit_undo(action: String, undo_data_tmp: Dictionary) -> void:
if !undo_data_tmp:
print("No undo data found for ReferenceImages.gd!")
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
print("No Reference Image ReferenceImages.gd!")
return
var redo_data: Dictionary = get_undo_data()
var project := Global.current_project
project.undos += 1
project.undo_redo.create_action(action)
for key in undo_data_tmp.keys():
if redo_data.has(key):
project.undo_redo.add_do_property(ri, key, redo_data.get(key))
project.undo_redo.add_undo_property(ri, key, undo_data_tmp.get(key))
project.undo_redo.add_do_method(Global.general_redo.bind(project))
project.undo_redo.add_do_method(ri.change_properties)
project.undo_redo.add_undo_method(Global.general_undo.bind(project))
project.undo_redo.add_undo_method(ri.change_properties)
project.undo_redo.commit_action()
undo_data.clear()
func _draw() -> void:
if index < 0:
return
var line_width := 2.0 / Global.camera.zoom.x
# If we are dragging show where the Reference was coming from
if dragging:
var i: ReferenceImage = Global.current_project.get_current_reference_image()
var prev_transform = Transform2D(og_rotation, og_scale, 0.0, og_pos)
var prev_poly := get_transformed_rect_polygon(i.get_rect(), prev_transform)
prev_poly.append(prev_poly[0])
draw_polyline(prev_poly, Color(1, 0.29, 0.29), line_width)
# First we highlight the Reference Images under the mouse with yellow
for ri: ReferenceImage in Global.current_project.reference_images:
var p := get_transformed_rect_polygon(ri.get_rect(), ri.transform)
p.append(p[0])
if ri.get_index() == index:
draw_polyline(p, Color(0.50, 0.99, 0.29), line_width)
elif Geometry2D.is_point_in_polygon(get_local_mouse_position(), p) and !dragging:
draw_polyline(p, Color(0.98, 0.80, 0.29), line_width)

View file

@ -0,0 +1,272 @@
extends VBoxContainer
var undo_data: Dictionary
var _prev_index: int = -1
var _ignore_spinbox_changes: bool = false
@onready var confirm_remove_dialog := $ConfirmRemoveDialog as ConfirmationDialog
@onready var timer := $Timer as Timer
@onready var references_container := Global.canvas.reference_image_container as Node2D
func _ready() -> void:
references_container.reference_image_changed.connect(_on_reference_image_changed)
func _update_properties():
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
# This is because otherwise a little dance will occur.
# This also breaks non-uniform scales (not supported UI-wise, but...)
_ignore_spinbox_changes = true
# Image Path
if OS.get_name() == "Web":
$ImageOptions/ImagePath.disabled = true
else:
$ImageOptions/ImagePath.disabled = false
if ri.image_path.is_empty():
$ImageOptions/ImagePath.text = "(No Path)"
$ImageOptions/ImagePath.tooltip_text = "(No Path)"
else:
$ImageOptions/ImagePath.text = ri.image_path
$ImageOptions/ImagePath.tooltip_text = ri.image_path
if !ri.texture:
$ImageOptions/WarningLabel.visible = true
$ImageOptions/ImagePath.visible = false
else:
$ImageOptions/WarningLabel.visible = false
$ImageOptions/ImagePath.visible = true
# Transform
$Options/Position/X.value = ri.position.x
$Options/Position/Y.value = ri.position.y
$Options/Position/X.max_value = ri.project.size.x
$Options/Position/Y.max_value = ri.project.size.y
$Options/Scale.value = ri.scale.x * 100
$Options/Rotation.value = ri.rotation_degrees
# Color
$Options/Filter.button_pressed = ri.filter
$Options/Monochrome.button_pressed = ri.monochrome
$Options/Overlay.color = Color(ri.overlay_color, 1.0)
$Options/Opacity.value = ri.overlay_color.a * 100
$Options/ColorClamping.value = ri.color_clamping * 100
_ignore_spinbox_changes = false
# Fore update the "gizmo" drawing
references_container.queue_redraw()
func _reset_properties() -> void:
# This is because otherwise a little dance will occur.
# This also breaks non-uniform scales (not supported UI-wise, but...)
_ignore_spinbox_changes = true
$ImageOptions/ImagePath.text = "None"
$ImageOptions/ImagePath.tooltip_text = "None"
$ImageOptions/ImagePath.disabled = true
$ImageOptions/WarningLabel.visible = false
$ImageOptions/ImagePath.visible = true
# Transform
$Options/Position/X.value = 0.0
$Options/Position/Y.value = 0.0
$Options/Position/X.max_value = 0.0
$Options/Position/Y.max_value = 0.0
$Options/Scale.value = 0.0
$Options/Rotation.value = 0.0
# Color
$Options/Filter.button_pressed = false
$Options/Monochrome.button_pressed = false
$Options/Overlay.color = Color.WHITE
$Options/Opacity.value = 0.0
$Options/ColorClamping.value = 0.0
_ignore_spinbox_changes = false
# Fore update the "gizmo" drawing
references_container.queue_redraw()
func _on_image_path_pressed() -> void:
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if ri.image_path.is_empty():
print("No path for this image")
return
OS.shell_open(ri.image_path.get_base_dir())
func _on_Monochrome_toggled(pressed: bool) -> void:
if _ignore_spinbox_changes:
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if timer.is_stopped():
undo_data = references_container.get_undo_data()
timer.start()
ri.monochrome = pressed
func _on_Filter_toggled(pressed: bool) -> void:
if _ignore_spinbox_changes:
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if timer.is_stopped():
undo_data = references_container.get_undo_data()
timer.start()
ri.filter = pressed
func _on_Reset_pressed():
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
var undo_data_tmp = references_container.get_undo_data()
ri.position_reset()
references_container.commit_undo("Reset Reference Image Position", undo_data_tmp)
func _on_Remove_pressed():
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
var index: int = Global.current_project.reference_index
if index > -1:
# If shift is pressed we just remove it without a dialog
if Input.is_action_pressed("shift"):
references_container.remove_reference_image(index)
else:
confirm_remove_dialog.position = Global.control.get_global_mouse_position()
confirm_remove_dialog.popup()
Global.dialog_open(true)
func _on_X_value_changed(value: float):
if _ignore_spinbox_changes:
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if timer.is_stopped():
undo_data = references_container.get_undo_data()
timer.start()
ri.position.x = value
func _on_Y_value_changed(value: float):
if _ignore_spinbox_changes:
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if timer.is_stopped():
undo_data = references_container.get_undo_data()
timer.start()
ri.position.y = value
func _on_Scale_value_changed(value: float):
if _ignore_spinbox_changes:
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if timer.is_stopped():
undo_data = references_container.get_undo_data()
timer.start()
ri.scale.x = value / 100
ri.scale.y = value / 100
func _on_Rotation_value_changed(value: float):
if _ignore_spinbox_changes:
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if timer.is_stopped():
undo_data = references_container.get_undo_data()
timer.start()
ri.rotation_degrees = value
func _on_Overlay_color_changed(color: Color):
if _ignore_spinbox_changes:
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if timer.is_stopped():
undo_data = references_container.get_undo_data()
timer.start()
ri.overlay_color = Color(color, ri.overlay_color.a)
func _on_Opacity_value_changed(value: float):
if _ignore_spinbox_changes:
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if timer.is_stopped():
undo_data = references_container.get_undo_data()
timer.start()
ri.overlay_color.a = value / 100
func _on_ColorClamping_value_changed(value: float):
if _ignore_spinbox_changes:
return
var ri: ReferenceImage = Global.current_project.get_current_reference_image()
if !ri:
return
if timer.is_stopped():
undo_data = references_container.get_undo_data()
timer.start()
ri.color_clamping = value / 100
func _on_timer_timeout() -> void:
references_container.commit_undo("Reference Image Changed", undo_data)
func _on_confirm_remove_dialog_confirmed() -> void:
var index: int = Global.current_project.reference_index
if index > -1:
references_container.remove_reference_image(index)
Global.dialog_open(false)
func _on_confirm_remove_dialog_canceled() -> void:
Global.dialog_open(false)
func _on_reference_image_porperties_changed() -> void:
_update_properties()
func _on_reference_image_changed(index: int) -> void:
# This is a check to make sure that the index is not more than the amount of references
if _prev_index > Global.current_project.reference_images.size() - 1:
return
# Disconnect the previously selected one
if _prev_index > -1:
var prev_ri: ReferenceImage = Global.current_project.get_reference_image(_prev_index)
if prev_ri.properties_changed.is_connected(_on_reference_image_porperties_changed):
prev_ri.properties_changed.disconnect(_on_reference_image_porperties_changed)
# Connect the new Reference image (if it is one)
if index > -1:
Global.current_project.reference_images[index].properties_changed.connect(
_on_reference_image_porperties_changed
)
_prev_index = index
if index < 0:
_reset_properties()
else:
_update_properties()

View file

@ -6,15 +6,38 @@ signal properties_changed
var project := Global.current_project var project := Global.current_project
var shader := preload("res://src/Shaders/SilhouetteShader.gdshader") var shader := preload("res://src/Shaders/ReferenceImageShader.gdshader")
var image_path := "" var image_path := ""
var filter := false var filter := false:
var silhouette := false set(value):
filter = value
if value:
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
else:
texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
var monochrome := false:
set(value):
monochrome = value
if material:
get_material().set_shader_parameter("monochrome", value)
var overlay_color := Color.WHITE:
set(value):
overlay_color = value
modulate = value
if material:
get_material().set_shader_parameter("monchrome_color", value)
var color_clamping := 0.0:
set(value):
color_clamping = value
if material:
get_material().set_shader_parameter("clamping", value)
func _ready() -> void: func _ready() -> void:
project.reference_images.append(self) project.reference_images.append(self)
# Make this show behind parent because we want to use _draw() to draw over it
show_behind_parent = true
func change_properties() -> void: func change_properties() -> void:
@ -24,6 +47,7 @@ func change_properties() -> void:
## Resets the position and scale of the reference image. ## Resets the position and scale of the reference image.
func position_reset() -> void: func position_reset() -> void:
position = project.size / 2.0 position = project.size / 2.0
rotation_degrees = 0.0
if texture != null: if texture != null:
scale = ( scale = (
Vector2.ONE Vector2.ONE
@ -43,12 +67,14 @@ func serialize() -> Dictionary:
"y": position.y, "y": position.y,
"scale_x": scale.x, "scale_x": scale.x,
"scale_y": scale.y, "scale_y": scale.y,
"modulate_r": modulate.r, "rotation_degrees": rotation_degrees,
"modulate_g": modulate.g, "overlay_color_r": overlay_color.r,
"modulate_b": modulate.b, "overlay_color_g": overlay_color.g,
"modulate_a": modulate.a, "overlay_color_b": overlay_color.b,
"overlay_color_a": overlay_color.a,
"filter": filter, "filter": filter,
"silhouette": silhouette, "monochrome": monochrome,
"color_clamping": color_clamping,
"image_path": image_path "image_path": image_path
} }
@ -57,7 +83,7 @@ func serialize() -> Dictionary:
## Be aware that new ReferenceImages are created via deserialization. ## Be aware that new ReferenceImages are created via deserialization.
## This is because deserialization sets up some nice defaults. ## This is because deserialization sets up some nice defaults.
func deserialize(d: Dictionary) -> void: func deserialize(d: Dictionary) -> void:
modulate = Color(1, 1, 1, 0.5) overlay_color = Color(1, 1, 1, 0.5)
if d.has("image_path"): if d.has("image_path"):
# Note that reference images are referred to by path. # Note that reference images are referred to by path.
# These images may be rather big. # These images may be rather big.
@ -69,9 +95,6 @@ func deserialize(d: Dictionary) -> void:
# Apply the silhouette shader # Apply the silhouette shader
var mat := ShaderMaterial.new() var mat := ShaderMaterial.new()
mat.shader = shader mat.shader = shader
# TODO: Lsbt - Add a option in prefrences to customize the color
# This color is almost black because it is less harsh
mat.set_shader_parameter("silhouette_color", Color(0.069, 0.069326, 0.074219))
set_material(mat) set_material(mat)
# Now that the image may have been established... # Now that the image may have been established...
@ -82,20 +105,24 @@ func deserialize(d: Dictionary) -> void:
position.y = d["y"] position.y = d["y"]
if d.has("scale_x"): if d.has("scale_x"):
scale.x = d["scale_x"] scale.x = d["scale_x"]
if d.has("rotation_degrees"):
rotation_degrees = d["rotation_degrees"]
if d.has("scale_y"): if d.has("scale_y"):
scale.y = d["scale_y"] scale.y = d["scale_y"]
if d.has("modulate_r"): if d.has("overlay_color_r"):
modulate.r = d["modulate_r"] overlay_color.r = d["overlay_color_r"]
if d.has("modulate_g"): if d.has("overlay_color_g"):
modulate.g = d["modulate_g"] overlay_color.g = d["overlay_color_g"]
if d.has("modulate_b"): if d.has("overlay_color_b"):
modulate.b = d["modulate_b"] overlay_color.b = d["overlay_color_b"]
if d.has("modulate_a"): if d.has("overlay_color_a"):
modulate.a = d["modulate_a"] overlay_color.a = d["overlay_color_a"]
if d.has("filter"): if d.has("filter"):
filter = d["filter"] filter = d["filter"]
if d.has("silhouette"): if d.has("monochrome"):
get_material().set_shader_parameter("show_silhouette", d["silhouette"]) monochrome = d["monochrome"]
if d.has("color_clamping"):
color_clamping = d["color_clamping"]
change_properties() change_properties()

View file

@ -1,98 +1,67 @@
extends Container extends Button
## UI to handle reference image editing.
var element: ReferenceImage
var _ignore_spinbox_changes := false
func _ready(): func _get_drag_data(_at_position: Vector2) -> Variant:
if OS.get_name() == "Web": var index := get_index() - 1
$Interior/PathHeader/Path.visible = false # If the index < 0 then that means this button is the "reset button"
$Interior/PathHeader/PathHTML.text = element.image_path if index < 0:
return null
set_drag_preview(self.duplicate())
var data := ["ReferenceImage", index]
return data
func _can_drop_data(_at_position: Vector2, data: Variant) -> bool:
if typeof(data) != TYPE_ARRAY:
Global.reference_panel.drag_highlight.visible = false
return false
if data[0] != "ReferenceImage":
Global.reference_panel.drag_highlight.visible = false
return false
var index := get_index() - 1
var from_index: int = data[1]
# If the index < 0 then that means this button is the "reset button"
# Or we are trying to drop on the same button
if index < 0 or index == from_index:
Global.reference_panel.drag_highlight.visible = false
return false
var side: int = -1
if get_local_mouse_position().x > size.x / 2:
side = 1
var region := Rect2(global_position + Vector2(3, 0), Vector2(6, size.y))
# Get the side
if side == 1:
region.position.x = (size.x + global_position.x) - 3
Global.reference_panel.drag_highlight.visible = true
Global.reference_panel.drag_highlight.position = region.position
Global.reference_panel.drag_highlight.size = region.size
return true
func _drop_data(_at_position: Vector2, data: Variant) -> void:
var from_index: int = data[1]
var to_index := get_index()
if get_local_mouse_position().x > size.x / 2:
if from_index > to_index:
to_index += 1
print("Help mee")
else: else:
$Interior/PathHeader/PathHTML.visible = false if from_index < to_index:
$Interior/PathHeader/Path.text = element.image_path to_index -= 1
if !element.texture: Global.reference_panel.reorder_reference_image(from_index, to_index - 1, false)
$Interior/PreviewAndOptions/PreviewPanel/Warning.text = "Image not found!"
else:
$Interior/PreviewAndOptions/PreviewPanel/Preview.texture = element.texture
element.properties_changed.connect(_update_properties)
_update_properties()
#Global.current_project.reorder_reference_image(from_index, to_index - 1)
#Global.reference_panel._on_references_changed()
func _update_properties(): #Global.reference_panel.drag_highlight.visible = false
# This is because otherwise a little dance will occur.
# This also breaks non-uniform scales (not supported UI-wise, but...)
_ignore_spinbox_changes = true
$Interior/PreviewAndOptions/Options/Scale.value = element.scale.x * 100
$Interior/PreviewAndOptions/Options/Position/X.value = element.position.x
$Interior/PreviewAndOptions/Options/Position/Y.value = element.position.y
$Interior/PreviewAndOptions/Options/Position/X.max_value = element.project.size.x
$Interior/PreviewAndOptions/Options/Position/Y.max_value = element.project.size.y
$Interior/PreviewAndOptions/Options/Opacity.value = element.modulate.a * 100
$Interior/OtherOptions/ApplyFilter.button_pressed = element.filter
_ignore_spinbox_changes = false
func _on_Reset_pressed():
element.position_reset()
element.change_properties()
func _on_Remove_pressed():
var index = Global.current_project.reference_images.find(element)
if index != -1:
queue_free()
element.queue_free()
Global.current_project.reference_images.remove_at(index)
OpenSave.reference_image_imported.emit()
func _on_Scale_value_changed(value: float):
if _ignore_spinbox_changes:
return
element.scale.x = value / 100
element.scale.y = value / 100
element.change_properties()
func _on_X_value_changed(value: float):
if _ignore_spinbox_changes:
return
element.position.x = value
element.change_properties()
func _on_Y_value_changed(value: float):
if _ignore_spinbox_changes:
return
element.position.y = value
element.change_properties()
func _on_Opacity_value_changed(value: float):
if _ignore_spinbox_changes:
return
element.modulate.a = value / 100
element.change_properties()
func _on_Path_pressed() -> void:
OS.shell_open($Interior/PathHeader/Path.text.get_base_dir())
func _on_Silhouette_toggled(button_pressed: bool) -> void:
element.silhouette = button_pressed
element.get_material().set_shader_parameter("show_silhouette", button_pressed)
element.change_properties()
func _on_ApplyFilter_toggled(button_pressed: bool) -> void:
element.filter = button_pressed
if element.texture:
if element.filter:
element.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
else:
element.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
element.change_properties()

View file

@ -1,128 +1,21 @@
[gd_scene load_steps=3 format=3 uid="uid://5quwfcfl5o1e"] [gd_scene load_steps=4 format=3 uid="uid://by3300fom3plf"]
[ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/ValueSlider.tscn" id="1"] [ext_resource type="Script" path="res://src/UI/ReferenceImages/ReferenceImageButton.gd" id="1_nf0dd"]
[ext_resource type="Script" path="res://src/UI/ReferenceImages/ReferenceImageButton.gd" id="2"]
[node name="ReferenceImageButton" type="PanelContainer"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_53xjd"]
anchors_preset = 15 draw_center = false
anchor_right = 1.0 border_width_left = 2
anchor_bottom = 1.0 border_width_top = 2
offset_right = -969.0 border_width_right = 2
offset_bottom = -581.0 border_width_bottom = 2
size_flags_horizontal = 3
script = ExtResource("2")
[node name="Interior" type="VBoxContainer" parent="."] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tuwm6"]
layout_mode = 2
[node name="PathHeader" type="HBoxContainer" parent="Interior"] [node name="ReferenceImageButton" type="Button"]
layout_mode = 2 custom_minimum_size = Vector2(64, 64)
theme_override_constants/separation = 0 theme_override_styles/pressed = SubResource("StyleBoxFlat_53xjd")
theme_override_styles/focus = SubResource("StyleBoxEmpty_tuwm6")
[node name="Path" type="LinkButton" parent="Interior/PathHeader"] toggle_mode = true
modulate = Color(0.552941, 1, 0.298039, 1) icon_alignment = 1
layout_mode = 2 expand_icon = true
size_flags_horizontal = 3 script = ExtResource("1_nf0dd")
underline = 1
[node name="PathHTML" type="Label" parent="Interior/PathHeader"]
self_modulate = Color(0.552941, 1, 0.298039, 1)
layout_mode = 2
size_flags_horizontal = 3
[node name="HSeparator" type="HSeparator" parent="Interior/PathHeader"]
layout_mode = 2
size_flags_horizontal = 3
[node name="PreviewAndOptions" type="HBoxContainer" parent="Interior"]
layout_mode = 2
[node name="Options" type="GridContainer" parent="Interior/PreviewAndOptions"]
layout_mode = 2
size_flags_horizontal = 3
columns = 2
[node name="PosLabel" type="Label" parent="Interior/PreviewAndOptions/Options"]
layout_mode = 2
text = "Position:"
[node name="Position" type="HBoxContainer" parent="Interior/PreviewAndOptions/Options"]
layout_mode = 2
size_flags_horizontal = 3
[node name="X" parent="Interior/PreviewAndOptions/Options/Position" instance=ExtResource("1")]
layout_mode = 2
allow_greater = true
allow_lesser = true
[node name="Y" parent="Interior/PreviewAndOptions/Options/Position" instance=ExtResource("1")]
layout_mode = 2
allow_greater = true
allow_lesser = true
[node name="ScaleLabel" type="Label" parent="Interior/PreviewAndOptions/Options"]
layout_mode = 2
text = "Scale:"
[node name="Scale" parent="Interior/PreviewAndOptions/Options" instance=ExtResource("1")]
layout_mode = 2
allow_greater = true
allow_lesser = true
[node name="OpacityLabel" type="Label" parent="Interior/PreviewAndOptions/Options"]
layout_mode = 2
text = "Opacity:"
[node name="Opacity" parent="Interior/PreviewAndOptions/Options" instance=ExtResource("1")]
layout_mode = 2
[node name="PreviewPanel" type="Panel" parent="Interior/PreviewAndOptions"]
custom_minimum_size = Vector2(80, 80)
layout_mode = 2
[node name="Warning" type="Label" parent="Interior/PreviewAndOptions/PreviewPanel"]
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
[node name="Preview" type="TextureRect" parent="Interior/PreviewAndOptions/PreviewPanel"]
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 2.0
offset_top = 2.0
offset_right = -2.0
offset_bottom = -2.0
expand_mode = 1
[node name="OtherOptions" type="HBoxContainer" parent="Interior"]
layout_mode = 2
alignment = 2
[node name="ApplyFilter" type="CheckBox" parent="Interior/OtherOptions"]
layout_mode = 2
tooltip_text = "Uses a magnifying filter, to enable smooth zooming in of the texture."
text = "Apply Filter"
[node name="Silhouette" type="CheckBox" parent="Interior/OtherOptions"]
layout_mode = 2
text = "Silhouette"
[node name="Reset" type="Button" parent="Interior/OtherOptions"]
layout_mode = 2
text = "Reset"
[node name="Remove" type="Button" parent="Interior/OtherOptions"]
layout_mode = 2
theme_override_colors/font_color = Color(1, 0.266667, 0.266667, 1)
text = "Remove"
[connection signal="pressed" from="Interior/PathHeader/Path" to="." method="_on_Path_pressed"]
[connection signal="value_changed" from="Interior/PreviewAndOptions/Options/Position/X" to="." method="_on_X_value_changed"]
[connection signal="value_changed" from="Interior/PreviewAndOptions/Options/Position/Y" to="." method="_on_Y_value_changed"]
[connection signal="value_changed" from="Interior/PreviewAndOptions/Options/Scale" to="." method="_on_Scale_value_changed"]
[connection signal="value_changed" from="Interior/PreviewAndOptions/Options/Opacity" to="." method="_on_Opacity_value_changed"]
[connection signal="toggled" from="Interior/OtherOptions/ApplyFilter" to="." method="_on_ApplyFilter_toggled"]
[connection signal="toggled" from="Interior/OtherOptions/Silhouette" to="." method="_on_Silhouette_toggled"]
[connection signal="pressed" from="Interior/OtherOptions/Reset" to="." method="_on_Reset_pressed"]
[connection signal="pressed" from="Interior/OtherOptions/Remove" to="." method="_on_Remove_pressed"]

View file

@ -1,27 +1,157 @@
class_name ReferencesPanel class_name ReferencesPanel
extends VBoxContainer extends PanelContainer
## Panel for reference image management ## Panel for reference image management
var reference_image_button_tscn := preload("res://src/UI/ReferenceImages/ReferenceImageButton.tscn") const ReferenceImageButton = preload("res://src/UI/ReferenceImages/ReferenceImageButton.tscn")
@onready var list = $"Scroll/List"
var list_btn_group := ButtonGroup.new()
var transform_button_group: ButtonGroup
var _ignore_ui_updates := false
@onready var list := %List as HBoxContainer
@onready var drag_highlight := $Overlay/DragHighlight as ColorRect
@onready var remove_btn := $ScrollContainer/Container/ReferenceEdit/ImageOptions/Remove as Button
@onready var transform_tools_btns := $ScrollContainer/Container/Tools/TransformTools
func _ready() -> void: func _ready() -> void:
Global.project_changed.connect(_update_reference_images) transform_button_group = transform_tools_btns.get_child(0).button_group
OpenSave.reference_image_imported.connect(_update_reference_images) transform_button_group.pressed.connect(_on_transform_tool_button_group_pressed)
list_btn_group.pressed.connect(_on_reference_image_button_pressed)
Global.canvas.reference_image_container.reference_image_changed.connect(
_on_reference_image_changed
)
OpenSave.reference_image_imported.connect(_on_references_changed)
# We call this function to update the buttons
_on_references_changed()
_update_ui()
func _update_reference_images(): func _notification(what: int) -> void:
if what == NOTIFICATION_DRAG_END:
drag_highlight.hide()
func _on_transform_tool_button_group_pressed(button: Button) -> void:
Global.canvas.reference_image_container.mode = button.get_index()
func _on_move_image_left_pressed() -> void:
var index: int = Global.current_project.reference_index
reorder_reference_image(index, index - 1)
func _on_move_image_right_pressed() -> void:
var index: int = Global.current_project.reference_index
reorder_reference_image(index, index + 1)
## This method allows you to reoreder reference image with undo redo support
## Please use this and not the method with the same name in project.gd
func reorder_reference_image(from: int, to: int, update_reference_index := true) -> void:
var project := Global.current_project
project.undo_redo.create_action("Reorder Reference Image")
project.undo_redo.add_do_method(project.reorder_reference_image.bind(from, to))
project.undo_redo.add_do_method(Global.reference_panel._on_references_changed)
if update_reference_index:
project.undo_redo.add_do_method(project.set_reference_image_index.bind(to))
else:
project.undo_redo.add_undo_method(
project.set_reference_image_index.bind(project.reference_index)
)
project.undo_redo.add_do_method(_update_ui)
project.undo_redo.add_undo_method(project.reorder_reference_image.bind(to, from))
project.undo_redo.add_undo_method(Global.reference_panel._on_references_changed)
if update_reference_index:
project.undo_redo.add_undo_method(project.set_reference_image_index.bind(from))
else:
project.undo_redo.add_undo_method(
project.set_reference_image_index.bind(project.reference_index)
)
project.undo_redo.add_undo_method(_update_ui)
project.undo_redo.commit_action()
func _update_ui() -> void:
var index: int = Global.current_project.reference_index
# Enable the buttons as a default
%MoveImageRightBtn.disabled = false
%MoveImageLeftBtn.disabled = false
if index == -1:
%MoveImageLeftBtn.disabled = true
%MoveImageRightBtn.disabled = true
if index == 0:
%MoveImageLeftBtn.disabled = true
if index == Global.current_project.reference_images.size() - 1:
%MoveImageRightBtn.disabled = true
if %MoveImageLeftBtn.disabled:
%MoveImageLeftBtn.mouse_default_cursor_shape = CURSOR_FORBIDDEN
else:
%MoveImageLeftBtn.mouse_default_cursor_shape = CURSOR_POINTING_HAND
if %MoveImageRightBtn.disabled:
%MoveImageRightBtn.mouse_default_cursor_shape = CURSOR_FORBIDDEN
else:
%MoveImageRightBtn.mouse_default_cursor_shape = CURSOR_POINTING_HAND
# Update the remove button
remove_btn.disabled = index == -1
if remove_btn.disabled:
remove_btn.mouse_default_cursor_shape = CURSOR_FORBIDDEN
else:
remove_btn.mouse_default_cursor_shape = CURSOR_POINTING_HAND
func _on_reference_image_button_pressed(button: Button) -> void:
# We subtract 1 because we already have a default button to "select no reference image
Global.current_project.set_reference_image_index(button.get_index() - 1)
# In case the signal is emitted for another node and not from a pressed button
func _on_reference_image_changed(index: int) -> void:
_update_ui()
# Update the buttons to show which one is pressed
if list_btn_group.get_buttons().size() > 0:
# First we loop through the buttons to "unpress them all"
for b: Button in list_btn_group.get_buttons():
b.set_pressed_no_signal(false)
# Then we get the wanted button and we press it
list_btn_group.get_buttons()[index + 1].set_pressed_no_signal(true)
func project_changed() -> void:
var project_reference_index := Global.current_project.reference_index
_on_references_changed()
_update_ui()
Global.current_project.set_reference_image_index(project_reference_index)
func _on_references_changed():
# When we change the project we set the default
Global.current_project.set_reference_image_index(-1)
for c in list.get_children(): for c in list.get_children():
if c is Button:
c.button_group = null
c.queue_free() c.queue_free()
# Just do this here because I'm not sure where it's done.
# By all means, change this! # The default button
for ref in Global.canvas.get_children(): var default = ReferenceImageButton.instantiate()
if ref is ReferenceImage: default.button_group = list_btn_group
ref.visible = false default.text = "none"
default.button_pressed = true
list.add_child(default)
# And update. # And update.
for ref in Global.current_project.reference_images: for ref in Global.current_project.reference_images:
ref.visible = true var l: Button = ReferenceImageButton.instantiate()
var l = reference_image_button_tscn.instantiate() l.button_group = list_btn_group
l.element = ref if ref.texture:
l.icon = ref.texture
list.add_child(l) list.add_child(l)

View file

@ -1,40 +1,399 @@
[gd_scene load_steps=2 format=3 uid="uid://b75xk2ix8xxml"] [gd_scene load_steps=13 format=3 uid="uid://cxhs8qy5ilufv"]
[ext_resource type="Script" path="res://src/UI/ReferenceImages/ReferencesPanel.gd" id="1"] [ext_resource type="Script" path="res://src/UI/ReferenceImages/ReferencesPanel.gd" id="1"]
[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="2_1qu4x"]
[ext_resource type="Texture2D" uid="uid://d1oxrkwndy5fi" path="res://assets/graphics/timeline/move_arrow.png" id="2_uqbp6"]
[ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/ValueSlider.tscn" id="3_1w6gu"]
[ext_resource type="Script" path="res://src/UI/ReferenceImages/ReferenceEdit.gd" id="3_skjtb"]
[ext_resource type="Texture2D" uid="uid://d2m7enib3dplc" path="res://assets/graphics/reference_images/select.png" id="3_us8st"]
[ext_resource type="Texture2D" uid="uid://cedsyi8gf2n2i" path="res://assets/graphics/reference_images/move.png" id="4_8mlcg"]
[ext_resource type="Texture2D" uid="uid://dtd43nvphu3jj" path="res://assets/graphics/reference_images/rotate.png" id="5_ifey7"]
[ext_resource type="Texture2D" uid="uid://nfabwr5mgdir" path="res://assets/graphics/reference_images/scale.png" id="6_7v0q5"]
[node name="Reference Images" type="VBoxContainer"] [sub_resource type="InputEventAction" id="InputEventAction_unp5j"]
action = &"move_frame_right"
[sub_resource type="Shortcut" id="Shortcut_uucm4"]
events = [SubResource("InputEventAction_unp5j")]
[sub_resource type="ButtonGroup" id="ButtonGroup_adw61"]
[node name="Reference Images" type="PanelContainer"]
custom_minimum_size = Vector2(300, 0)
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1") script = ExtResource("1")
[node name="Header" type="HBoxContainer" parent="."] [node name="ScrollContainer" type="ScrollContainer" parent="."]
layout_mode = 2
[node name="Container" type="VBoxContainer" parent="ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="Header" type="HBoxContainer" parent="ScrollContainer/Container"]
layout_mode = 2 layout_mode = 2
theme_override_constants/separation = 0 theme_override_constants/separation = 0
[node name="HSeparator2" type="HSeparator" parent="Header"] [node name="Label" type="Label" parent="ScrollContainer/Container/Header"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Label" type="Label" parent="Header"]
layout_mode = 2 layout_mode = 2
theme_type_variation = &"HeaderSmall" theme_type_variation = &"HeaderSmall"
text = "Reference Images" text = "My Reference Images"
[node name="HSeparator" type="HSeparator" parent="Header"] [node name="Tip" type="Label" parent="ScrollContainer/Container"]
layout_mode = 2 custom_minimum_size = Vector2(10, 0)
size_flags_horizontal = 3
[node name="Label" type="Label" parent="."]
layout_mode = 2 layout_mode = 2
text = "When opening an image, it may be imported as a reference." text = "When opening an image, it may be imported as a reference."
autowrap_mode = 2
[node name="Scroll" type="ScrollContainer" parent="."] [node name="Tools" type="HBoxContainer" parent="ScrollContainer/Container"]
layout_mode = 2
[node name="MoveImageLeftBtn" type="Button" parent="ScrollContainer/Container/Tools" groups=["UIButtons"]]
unique_name_in_owner = true
custom_minimum_size = Vector2(31, 31)
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Move the selected reference image to the left"
focus_mode = 0
mouse_default_cursor_shape = 2
shortcut = SubResource("Shortcut_uucm4")
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Container/Tools/MoveImageLeftBtn"]
layout_mode = 0
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -7.5
offset_top = -5.5
offset_right = 7.5
offset_bottom = 5.5
texture = ExtResource("2_uqbp6")
flip_h = true
[node name="MoveImageRightBtn" type="Button" parent="ScrollContainer/Container/Tools" groups=["UIButtons"]]
unique_name_in_owner = true
custom_minimum_size = Vector2(31, 31)
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Move the selected reference image to the right"
focus_mode = 0
mouse_default_cursor_shape = 2
shortcut = SubResource("Shortcut_uucm4")
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Container/Tools/MoveImageRightBtn"]
layout_mode = 0
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -7.5
offset_top = -5.5
offset_right = 7.5
offset_bottom = 5.5
texture = ExtResource("2_uqbp6")
[node name="Spacer" type="Control" parent="ScrollContainer/Container/Tools"]
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3
[node name="List" type="VBoxContainer" parent="Scroll"] [node name="TransformTools" type="HBoxContainer" parent="ScrollContainer/Container/Tools"]
layout_mode = 2
[node name="Select" type="Button" parent="ScrollContainer/Container/Tools/TransformTools" groups=["UIButtons"]]
custom_minimum_size = Vector2(31, 31)
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Selects a reference image on the canvas"
focus_mode = 0
mouse_default_cursor_shape = 2
toggle_mode = true
button_pressed = true
button_group = SubResource("ButtonGroup_adw61")
shortcut = SubResource("Shortcut_uucm4")
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Container/Tools/TransformTools/Select"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -12.0
offset_top = -12.0
offset_right = 12.0
offset_bottom = 12.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("3_us8st")
[node name="Move" type="Button" parent="ScrollContainer/Container/Tools/TransformTools" groups=["UIButtons"]]
custom_minimum_size = Vector2(31, 31)
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Move the selected reference image"
focus_mode = 0
mouse_default_cursor_shape = 2
toggle_mode = true
button_group = SubResource("ButtonGroup_adw61")
shortcut = SubResource("Shortcut_uucm4")
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Container/Tools/TransformTools/Move"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -12.0
offset_top = -12.0
offset_right = 12.0
offset_bottom = 12.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("4_8mlcg")
[node name="Rotate" type="Button" parent="ScrollContainer/Container/Tools/TransformTools" groups=["UIButtons"]]
custom_minimum_size = Vector2(31, 31)
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Rotate the selected image"
focus_mode = 0
mouse_default_cursor_shape = 2
toggle_mode = true
button_group = SubResource("ButtonGroup_adw61")
shortcut = SubResource("Shortcut_uucm4")
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Container/Tools/TransformTools/Rotate"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -12.0
offset_top = -12.0
offset_right = 12.0
offset_bottom = 12.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("5_ifey7")
[node name="Scale" type="Button" parent="ScrollContainer/Container/Tools/TransformTools" groups=["UIButtons"]]
custom_minimum_size = Vector2(31, 31)
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Scale the selected reference image"
focus_mode = 0
mouse_default_cursor_shape = 2
toggle_mode = true
button_group = SubResource("ButtonGroup_adw61")
shortcut = SubResource("Shortcut_uucm4")
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Container/Tools/TransformTools/Scale"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -12.0
offset_top = -12.0
offset_right = 12.0
offset_bottom = 12.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("6_7v0q5")
[node name="ReferenceImages" type="ScrollContainer" parent="ScrollContainer/Container"]
layout_mode = 2
horizontal_scroll_mode = 2
vertical_scroll_mode = 0
[node name="List" type="HBoxContainer" parent="ScrollContainer/Container/ReferenceImages"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 64)
layout_mode = 2
[node name="ReferenceEdit" type="VBoxContainer" parent="ScrollContainer/Container"]
layout_mode = 2
script = ExtResource("3_skjtb")
[node name="ImageOptions" type="HBoxContainer" parent="ScrollContainer/Container/ReferenceEdit"]
layout_mode = 2
[node name="WarningLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/ImageOptions"]
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 theme_override_colors/font_color = Color(0.972549, 1, 0.545098, 1)
text = "Image not found!"
text_overrun_behavior = 3
[node name="ImagePath" type="Button" parent="ScrollContainer/Container/ReferenceEdit/ImageOptions"]
visible = false
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 4
text = "Image Path"
alignment = 0
text_overrun_behavior = 3
[node name="Remove" type="Button" parent="ScrollContainer/Container/ReferenceEdit/ImageOptions"]
layout_mode = 2
tooltip_text = "Hold Shift while pressing to instantly remove."
theme_override_colors/font_color = Color(1, 0.490196, 0.419608, 1)
text = "Remove"
[node name="Options" type="GridContainer" parent="ScrollContainer/Container/ReferenceEdit"]
layout_mode = 2
size_flags_horizontal = 3
columns = 2
[node name="TransformLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
layout_mode = 2
text = "Transform"
[node name="Reset" type="Button" parent="ScrollContainer/Container/ReferenceEdit/Options"]
layout_mode = 2
text = "Reset Transform"
[node name="PosLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(115, 0)
layout_mode = 2
text = "Position"
[node name="Position" type="HBoxContainer" parent="ScrollContainer/Container/ReferenceEdit/Options"]
layout_mode = 2
size_flags_horizontal = 3
[node name="X" parent="ScrollContainer/Container/ReferenceEdit/Options/Position" instance=ExtResource("3_1w6gu")]
layout_mode = 2
allow_greater = true
allow_lesser = true
[node name="Y" parent="ScrollContainer/Container/ReferenceEdit/Options/Position" instance=ExtResource("3_1w6gu")]
layout_mode = 2
allow_greater = true
allow_lesser = true
[node name="ScaleLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(115, 0)
layout_mode = 2
text = "Scale"
[node name="Scale" parent="ScrollContainer/Container/ReferenceEdit/Options" instance=ExtResource("3_1w6gu")]
layout_mode = 2
allow_greater = true
allow_lesser = true
[node name="RotationLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(115, 0)
layout_mode = 2
text = "Rotation"
[node name="Rotation" parent="ScrollContainer/Container/ReferenceEdit/Options" instance=ExtResource("3_1w6gu")]
layout_mode = 2
min_value = -180.0
max_value = 180.0
[node name="ColorLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
layout_mode = 2
text = "Color Options"
[node name="Spacer2" type="Control" parent="ScrollContainer/Container/ReferenceEdit/Options"]
layout_mode = 2
[node name="FilterLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(115, 0)
layout_mode = 2
text = "Filter"
[node name="Filter" type="CheckButton" parent="ScrollContainer/Container/ReferenceEdit/Options"]
layout_mode = 2
size_flags_horizontal = 3
text = "Enabled"
[node name="MonochromeLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(115, 0)
layout_mode = 2
text = "Monochrome"
[node name="Monochrome" type="CheckButton" parent="ScrollContainer/Container/ReferenceEdit/Options"]
layout_mode = 2
size_flags_horizontal = 3
text = "Enabled"
[node name="OverlayLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(115, 0)
layout_mode = 2
text = "Overlay"
[node name="Overlay" type="ColorPickerButton" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(48, 28)
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 0.25
edit_alpha = false
[node name="OpacityLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(115, 0)
layout_mode = 2
text = "Opacity"
[node name="Opacity" parent="ScrollContainer/Container/ReferenceEdit/Options" instance=ExtResource("3_1w6gu")]
layout_mode = 2
[node name="ColorClampingLabel" type="Label" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(115, 0)
layout_mode = 2
text = "Color Clamping"
[node name="ColorClamping" type="TextureProgressBar" parent="ScrollContainer/Container/ReferenceEdit/Options"]
custom_minimum_size = Vector2(0, 24)
layout_mode = 2
size_flags_horizontal = 3
focus_mode = 2
theme_type_variation = &"ValueSlider"
nine_patch_stretch = true
stretch_margin_left = 3
stretch_margin_top = 3
stretch_margin_right = 3
stretch_margin_bottom = 3
script = ExtResource("2_1qu4x")
[node name="Timer" type="Timer" parent="ScrollContainer/Container/ReferenceEdit"]
wait_time = 0.2
one_shot = true
[node name="ConfirmRemoveDialog" type="ConfirmationDialog" parent="ScrollContainer/Container/ReferenceEdit"]
position = Vector2i(0, 36)
size = Vector2i(454, 106)
dialog_text = "Are you sure you want to remove this reference image? It will not be deleted from your file system."
dialog_autowrap = true
[node name="Overlay" type="CanvasLayer" parent="."]
[node name="DragHighlight" type="ColorRect" parent="Overlay"]
color = Color(0, 0.741176, 1, 0.501961)
[connection signal="pressed" from="ScrollContainer/Container/Tools/MoveImageLeftBtn" to="." method="_on_move_image_left_pressed"]
[connection signal="pressed" from="ScrollContainer/Container/Tools/MoveImageRightBtn" to="." method="_on_move_image_right_pressed"]
[connection signal="pressed" from="ScrollContainer/Container/ReferenceEdit/ImageOptions/Remove" to="ScrollContainer/Container/ReferenceEdit" method="_on_Remove_pressed"]
[connection signal="pressed" from="ScrollContainer/Container/ReferenceEdit/Options/Reset" to="ScrollContainer/Container/ReferenceEdit" method="_on_Reset_pressed"]
[connection signal="value_changed" from="ScrollContainer/Container/ReferenceEdit/Options/Position/X" to="ScrollContainer/Container/ReferenceEdit" method="_on_X_value_changed"]
[connection signal="value_changed" from="ScrollContainer/Container/ReferenceEdit/Options/Position/Y" to="ScrollContainer/Container/ReferenceEdit" method="_on_Y_value_changed"]
[connection signal="value_changed" from="ScrollContainer/Container/ReferenceEdit/Options/Scale" to="ScrollContainer/Container/ReferenceEdit" method="_on_Scale_value_changed"]
[connection signal="value_changed" from="ScrollContainer/Container/ReferenceEdit/Options/Rotation" to="ScrollContainer/Container/ReferenceEdit" method="_on_Rotation_value_changed"]
[connection signal="toggled" from="ScrollContainer/Container/ReferenceEdit/Options/Filter" to="ScrollContainer/Container/ReferenceEdit" method="_on_Filter_toggled"]
[connection signal="toggled" from="ScrollContainer/Container/ReferenceEdit/Options/Monochrome" to="ScrollContainer/Container/ReferenceEdit" method="_on_Monochrome_toggled"]
[connection signal="color_changed" from="ScrollContainer/Container/ReferenceEdit/Options/Overlay" to="ScrollContainer/Container/ReferenceEdit" method="_on_Overlay_color_changed"]
[connection signal="value_changed" from="ScrollContainer/Container/ReferenceEdit/Options/Opacity" to="ScrollContainer/Container/ReferenceEdit" method="_on_Opacity_value_changed"]
[connection signal="value_changed" from="ScrollContainer/Container/ReferenceEdit/Options/ColorClamping" to="ScrollContainer/Container/ReferenceEdit" method="_on_ColorClamping_value_changed"]
[connection signal="timeout" from="ScrollContainer/Container/ReferenceEdit/Timer" to="ScrollContainer/Container/ReferenceEdit" method="_on_timer_timeout"]
[connection signal="canceled" from="ScrollContainer/Container/ReferenceEdit/ConfirmRemoveDialog" to="ScrollContainer/Container/ReferenceEdit" method="_on_confirm_remove_dialog_canceled"]
[connection signal="confirmed" from="ScrollContainer/Container/ReferenceEdit/ConfirmRemoveDialog" to="ScrollContainer/Container/ReferenceEdit" method="_on_confirm_remove_dialog_confirmed"]

View file

@ -10,7 +10,7 @@
[ext_resource type="Shader" path="res://src/Shaders/Greyscale.gdshader" id="8"] [ext_resource type="Shader" path="res://src/Shaders/Greyscale.gdshader" id="8"]
[ext_resource type="Shader" path="res://src/Shaders/TransparentChecker.gdshader" id="9"] [ext_resource type="Shader" path="res://src/Shaders/TransparentChecker.gdshader" id="9"]
[ext_resource type="PackedScene" uid="uid://wo0hqxkst808" path="res://src/UI/GlobalToolOptions/GlobalToolOptions.tscn" id="10"] [ext_resource type="PackedScene" uid="uid://wo0hqxkst808" path="res://src/UI/GlobalToolOptions/GlobalToolOptions.tscn" id="10"]
[ext_resource type="PackedScene" uid="uid://b75xk2ix8xxml" path="res://src/UI/ReferenceImages/ReferencesPanel.tscn" id="11"] [ext_resource type="PackedScene" uid="uid://cxhs8qy5ilufv" path="res://src/UI/ReferenceImages/ReferencesPanel.tscn" id="11"]
[ext_resource type="PackedScene" uid="uid://cap1bhavhi33g" path="res://src/UI/PerspectiveEditor/PerspectiveEditor.tscn" id="12"] [ext_resource type="PackedScene" uid="uid://cap1bhavhi33g" path="res://src/UI/PerspectiveEditor/PerspectiveEditor.tscn" id="12"]
[ext_resource type="PackedScene" uid="uid://dl6ook010q86o" path="res://src/UI/Recorder/Recorder.tscn" id="13"] [ext_resource type="PackedScene" uid="uid://dl6ook010q86o" path="res://src/UI/Recorder/Recorder.tscn" id="13"]
[ext_resource type="Script" path="res://addons/dockable_container/layout.gd" id="14"] [ext_resource type="Script" path="res://addons/dockable_container/layout.gd" id="14"]