mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-18 09:09:47 +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:
parent
87b5a818bb
commit
c8f37943d8
|
@ -2780,10 +2780,36 @@ msgstr ""
|
|||
msgid "Spring towards the end"
|
||||
msgstr ""
|
||||
|
||||
msgid "Silhouette"
|
||||
#. Used to turn images into a singular color
|
||||
msgid "Monochrome"
|
||||
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 ""
|
||||
|
||||
#. Used in checkbuttons (like on/off switches) that enable/disable something.
|
||||
|
|
BIN
assets/graphics/reference_images/move.png
Normal file
BIN
assets/graphics/reference_images/move.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 192 B |
34
assets/graphics/reference_images/move.png.import
Normal file
34
assets/graphics/reference_images/move.png.import
Normal 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
|
BIN
assets/graphics/reference_images/rotate.png
Normal file
BIN
assets/graphics/reference_images/rotate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 215 B |
34
assets/graphics/reference_images/rotate.png.import
Normal file
34
assets/graphics/reference_images/rotate.png.import
Normal 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
|
BIN
assets/graphics/reference_images/scale.png
Normal file
BIN
assets/graphics/reference_images/scale.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 204 B |
34
assets/graphics/reference_images/scale.png.import
Normal file
34
assets/graphics/reference_images/scale.png.import
Normal 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
|
BIN
assets/graphics/reference_images/select.png
Normal file
BIN
assets/graphics/reference_images/select.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 194 B |
34
assets/graphics/reference_images/select.png.import
Normal file
34
assets/graphics/reference_images/select.png.import
Normal 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
|
|
@ -820,6 +820,26 @@ onion_skinning_settings={
|
|||
"deadzone": 0.5,
|
||||
"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]
|
||||
|
||||
|
|
|
@ -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.
|
||||
@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.
|
||||
@onready var top_menu_container: Panel = control.find_child("TopMenuContainer")
|
||||
## The label indicating cursor position.
|
||||
|
@ -657,6 +661,10 @@ func _initialize_keychain() -> void:
|
|||
Keychain.InputAction.new("", "Transformation tools", false),
|
||||
"transform_copy_selection_content":
|
||||
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 = {
|
||||
|
@ -679,6 +687,7 @@ func _initialize_keychain() -> void:
|
|||
"Shape tools": Keychain.InputGroup.new("Tool modifiers"),
|
||||
"Selection 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"]
|
||||
|
||||
|
|
|
@ -750,7 +750,7 @@ func import_reference_image_from_path(path: String) -> void:
|
|||
var ri := ReferenceImage.new()
|
||||
ri.project = project
|
||||
ri.deserialize({"image_path": path})
|
||||
Global.canvas.add_child(ri)
|
||||
Global.canvas.reference_image_container.add_child(ri)
|
||||
reference_image_imported.emit()
|
||||
|
||||
|
||||
|
@ -760,7 +760,7 @@ func import_reference_image_from_image(image: Image) -> void:
|
|||
var ri := ReferenceImage.new()
|
||||
ri.project = project
|
||||
ri.create_from_image(image)
|
||||
Global.canvas.add_child(ri)
|
||||
Global.canvas.reference_image_container.add_child(ri)
|
||||
reference_image_imported.emit()
|
||||
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ var animation_tags: Array[AnimationTag] = []:
|
|||
var guides: Array[Guide] = []
|
||||
var brushes: Array[Image] = []
|
||||
var reference_images: Array[ReferenceImage] = []
|
||||
var reference_index: int = -1 # The currently selected index ReferenceImage
|
||||
var vanishing_points := [] ## Array of Vanishing Points
|
||||
var fps := 6.0
|
||||
|
||||
|
@ -250,6 +251,21 @@ func change_project() -> void:
|
|||
var edit_menu_popup: PopupMenu = Global.top_menu_container.edit_menu
|
||||
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
|
||||
for camera in Global.cameras:
|
||||
camera.rotation = cameras_rotation[i]
|
||||
|
@ -870,3 +886,28 @@ func _update_layer_ui() -> void:
|
|||
for f in frames.size():
|
||||
cel_hbox.get_child(f).layer = l
|
||||
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)
|
||||
|
|
21
src/Shaders/ReferenceImageShader.gdshader
Normal file
21
src/Shaders/ReferenceImageShader.gdshader
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ var layer_metadata_texture := ImageTexture.new()
|
|||
@onready var mouse_guide_container := $MouseGuideContainer as Node2D
|
||||
@onready var gizmos_3d := $Gizmos3D as Node2D
|
||||
@onready var measurements := $Measurements as Node2D
|
||||
@onready var reference_image_container := $ReferenceImages as Node2D
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
|
|
|
@ -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="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/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/ReferenceImages.gd" id="17_qfjb4"]
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_6b0ox"]
|
||||
shader = ExtResource("1_253dh")
|
||||
|
@ -93,3 +94,6 @@ script = ExtResource("14")
|
|||
|
||||
[node name="Measurements" type="Node2D" parent="."]
|
||||
script = ExtResource("16_nxilb")
|
||||
|
||||
[node name="ReferenceImages" type="Node2D" parent="."]
|
||||
script = ExtResource("17_qfjb4")
|
||||
|
|
334
src/UI/Canvas/ReferenceImages.gd
Normal file
334
src/UI/Canvas/ReferenceImages.gd
Normal 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)
|
272
src/UI/ReferenceImages/ReferenceEdit.gd
Normal file
272
src/UI/ReferenceImages/ReferenceEdit.gd
Normal 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()
|
|
@ -6,15 +6,38 @@ signal properties_changed
|
|||
|
||||
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 filter := false
|
||||
var silhouette := false
|
||||
var filter := 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:
|
||||
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:
|
||||
|
@ -24,6 +47,7 @@ func change_properties() -> void:
|
|||
## Resets the position and scale of the reference image.
|
||||
func position_reset() -> void:
|
||||
position = project.size / 2.0
|
||||
rotation_degrees = 0.0
|
||||
if texture != null:
|
||||
scale = (
|
||||
Vector2.ONE
|
||||
|
@ -43,12 +67,14 @@ func serialize() -> Dictionary:
|
|||
"y": position.y,
|
||||
"scale_x": scale.x,
|
||||
"scale_y": scale.y,
|
||||
"modulate_r": modulate.r,
|
||||
"modulate_g": modulate.g,
|
||||
"modulate_b": modulate.b,
|
||||
"modulate_a": modulate.a,
|
||||
"rotation_degrees": rotation_degrees,
|
||||
"overlay_color_r": overlay_color.r,
|
||||
"overlay_color_g": overlay_color.g,
|
||||
"overlay_color_b": overlay_color.b,
|
||||
"overlay_color_a": overlay_color.a,
|
||||
"filter": filter,
|
||||
"silhouette": silhouette,
|
||||
"monochrome": monochrome,
|
||||
"color_clamping": color_clamping,
|
||||
"image_path": image_path
|
||||
}
|
||||
|
||||
|
@ -57,7 +83,7 @@ func serialize() -> Dictionary:
|
|||
## Be aware that new ReferenceImages are created via deserialization.
|
||||
## This is because deserialization sets up some nice defaults.
|
||||
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"):
|
||||
# Note that reference images are referred to by path.
|
||||
# These images may be rather big.
|
||||
|
@ -69,9 +95,6 @@ func deserialize(d: Dictionary) -> void:
|
|||
# Apply the silhouette shader
|
||||
var mat := ShaderMaterial.new()
|
||||
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)
|
||||
|
||||
# Now that the image may have been established...
|
||||
|
@ -82,20 +105,24 @@ func deserialize(d: Dictionary) -> void:
|
|||
position.y = d["y"]
|
||||
if d.has("scale_x"):
|
||||
scale.x = d["scale_x"]
|
||||
if d.has("rotation_degrees"):
|
||||
rotation_degrees = d["rotation_degrees"]
|
||||
if d.has("scale_y"):
|
||||
scale.y = d["scale_y"]
|
||||
if d.has("modulate_r"):
|
||||
modulate.r = d["modulate_r"]
|
||||
if d.has("modulate_g"):
|
||||
modulate.g = d["modulate_g"]
|
||||
if d.has("modulate_b"):
|
||||
modulate.b = d["modulate_b"]
|
||||
if d.has("modulate_a"):
|
||||
modulate.a = d["modulate_a"]
|
||||
if d.has("overlay_color_r"):
|
||||
overlay_color.r = d["overlay_color_r"]
|
||||
if d.has("overlay_color_g"):
|
||||
overlay_color.g = d["overlay_color_g"]
|
||||
if d.has("overlay_color_b"):
|
||||
overlay_color.b = d["overlay_color_b"]
|
||||
if d.has("overlay_color_a"):
|
||||
overlay_color.a = d["overlay_color_a"]
|
||||
if d.has("filter"):
|
||||
filter = d["filter"]
|
||||
if d.has("silhouette"):
|
||||
get_material().set_shader_parameter("show_silhouette", d["silhouette"])
|
||||
if d.has("monochrome"):
|
||||
monochrome = d["monochrome"]
|
||||
if d.has("color_clamping"):
|
||||
color_clamping = d["color_clamping"]
|
||||
change_properties()
|
||||
|
||||
|
||||
|
|
|
@ -1,98 +1,67 @@
|
|||
extends Container
|
||||
## UI to handle reference image editing.
|
||||
|
||||
var element: ReferenceImage
|
||||
var _ignore_spinbox_changes := false
|
||||
extends Button
|
||||
|
||||
|
||||
func _ready():
|
||||
if OS.get_name() == "Web":
|
||||
$Interior/PathHeader/Path.visible = false
|
||||
$Interior/PathHeader/PathHTML.text = element.image_path
|
||||
func _get_drag_data(_at_position: Vector2) -> Variant:
|
||||
var index := get_index() - 1
|
||||
# If the index < 0 then that means this button is the "reset button"
|
||||
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:
|
||||
$Interior/PathHeader/PathHTML.visible = false
|
||||
$Interior/PathHeader/Path.text = element.image_path
|
||||
if from_index < to_index:
|
||||
to_index -= 1
|
||||
|
||||
if !element.texture:
|
||||
$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.reference_panel.reorder_reference_image(from_index, to_index - 1, false)
|
||||
|
||||
#Global.current_project.reorder_reference_image(from_index, to_index - 1)
|
||||
#Global.reference_panel._on_references_changed()
|
||||
|
||||
func _update_properties():
|
||||
# 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()
|
||||
#Global.reference_panel.drag_highlight.visible = false
|
||||
|
|
|
@ -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="2"]
|
||||
[ext_resource type="Script" path="res://src/UI/ReferenceImages/ReferenceImageButton.gd" id="1_nf0dd"]
|
||||
|
||||
[node name="ReferenceImageButton" type="PanelContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_right = -969.0
|
||||
offset_bottom = -581.0
|
||||
size_flags_horizontal = 3
|
||||
script = ExtResource("2")
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_53xjd"]
|
||||
draw_center = false
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
|
||||
[node name="Interior" type="VBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tuwm6"]
|
||||
|
||||
[node name="PathHeader" type="HBoxContainer" parent="Interior"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 0
|
||||
|
||||
[node name="Path" type="LinkButton" parent="Interior/PathHeader"]
|
||||
modulate = Color(0.552941, 1, 0.298039, 1)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
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"]
|
||||
[node name="ReferenceImageButton" type="Button"]
|
||||
custom_minimum_size = Vector2(64, 64)
|
||||
theme_override_styles/pressed = SubResource("StyleBoxFlat_53xjd")
|
||||
theme_override_styles/focus = SubResource("StyleBoxEmpty_tuwm6")
|
||||
toggle_mode = true
|
||||
icon_alignment = 1
|
||||
expand_icon = true
|
||||
script = ExtResource("1_nf0dd")
|
||||
|
|
|
@ -1,27 +1,157 @@
|
|||
class_name ReferencesPanel
|
||||
extends VBoxContainer
|
||||
extends PanelContainer
|
||||
## Panel for reference image management
|
||||
|
||||
var reference_image_button_tscn := preload("res://src/UI/ReferenceImages/ReferenceImageButton.tscn")
|
||||
@onready var list = $"Scroll/List"
|
||||
const ReferenceImageButton = preload("res://src/UI/ReferenceImages/ReferenceImageButton.tscn")
|
||||
|
||||
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:
|
||||
Global.project_changed.connect(_update_reference_images)
|
||||
OpenSave.reference_image_imported.connect(_update_reference_images)
|
||||
transform_button_group = transform_tools_btns.get_child(0).button_group
|
||||
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():
|
||||
if c is Button:
|
||||
c.button_group = null
|
||||
c.queue_free()
|
||||
# Just do this here because I'm not sure where it's done.
|
||||
# By all means, change this!
|
||||
for ref in Global.canvas.get_children():
|
||||
if ref is ReferenceImage:
|
||||
ref.visible = false
|
||||
|
||||
# The default button
|
||||
var default = ReferenceImageButton.instantiate()
|
||||
default.button_group = list_btn_group
|
||||
default.text = "none"
|
||||
default.button_pressed = true
|
||||
list.add_child(default)
|
||||
|
||||
# And update.
|
||||
for ref in Global.current_project.reference_images:
|
||||
ref.visible = true
|
||||
var l = reference_image_button_tscn.instantiate()
|
||||
l.element = ref
|
||||
var l: Button = ReferenceImageButton.instantiate()
|
||||
l.button_group = list_btn_group
|
||||
if ref.texture:
|
||||
l.icon = ref.texture
|
||||
list.add_child(l)
|
||||
|
|
|
@ -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/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
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
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
|
||||
theme_override_constants/separation = 0
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="Header"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Label" type="Label" parent="Header"]
|
||||
[node name="Label" type="Label" parent="ScrollContainer/Container/Header"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"HeaderSmall"
|
||||
text = "Reference Images"
|
||||
text = "My Reference Images"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="Header"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
[node name="Tip" type="Label" parent="ScrollContainer/Container"]
|
||||
custom_minimum_size = Vector2(10, 0)
|
||||
layout_mode = 2
|
||||
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
|
||||
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
|
||||
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"]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[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="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://dl6ook010q86o" path="res://src/UI/Recorder/Recorder.tscn" id="13"]
|
||||
[ext_resource type="Script" path="res://addons/dockable_container/layout.gd" id="14"]
|
||||
|
|
Loading…
Reference in a new issue