-
-
Notifications
You must be signed in to change notification settings - Fork 397
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Reference Images: Part 1 * Reference Images: Proper import workflow * Reference Images: gdformat/gdlint checks * Reference Images: Remove random src/Main.tscn changes * Reference Images: Switch to ValueSliders, autowraps, fix opacity going out of range
- Loading branch information
Showing
11 changed files
with
361 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
class_name ReferenceImage | ||
extends Sprite | ||
# A class describing a reference image | ||
|
||
signal properties_changed | ||
|
||
var project = Global.current_project | ||
|
||
var image_path: String = "" | ||
|
||
|
||
func _ready() -> void: | ||
project.reference_images.append(self) | ||
|
||
|
||
func change_properties(): | ||
emit_signal("properties_changed") | ||
|
||
|
||
# Resets the position and scale of the reference image. | ||
func position_reset(): | ||
position = project.size / 2.0 | ||
if texture != null: | ||
scale = ( | ||
Vector2.ONE | ||
* min(project.size.x / texture.get_width(), project.size.y / texture.get_height()) | ||
) | ||
else: | ||
scale = Vector2.ONE | ||
|
||
|
||
# Serialize details of the reference image. | ||
func serialize(): | ||
return { | ||
"x": position.x, | ||
"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, | ||
"image_path": image_path | ||
} | ||
|
||
|
||
# Load details of the reference image from a dictionary. | ||
# Be aware that new ReferenceImages are created via deserialization. | ||
# This is because deserialization sets up some nice defaults. | ||
func deserialize(d: Dictionary): | ||
modulate = 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. | ||
# Also | ||
image_path = d["image_path"] | ||
var img = Image.new() | ||
if img.load(image_path) == OK: | ||
var itex = ImageTexture.new() | ||
# don't do FLAG_REPEAT - it could cause visual issues | ||
itex.create_from_image(img, Texture.FLAG_MIPMAPS | Texture.FLAG_FILTER) | ||
texture = itex | ||
# Now that the image may have been established... | ||
position_reset() | ||
if d.has("x"): | ||
position.x = d["x"] | ||
if d.has("y"): | ||
position.y = d["y"] | ||
if d.has("scale_x"): | ||
scale.x = d["scale_x"] | ||
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"] | ||
change_properties() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
extends Container | ||
# UI to handle reference image editing. | ||
|
||
var element: ReferenceImage | ||
var _ignore_spinbox_changes = false | ||
|
||
|
||
func _ready(): | ||
$Interior/Path.text = element.image_path | ||
element.connect("properties_changed", self, "_update_properties") | ||
_update_properties() | ||
|
||
|
||
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/Options/Scale.value = element.scale.x * 100 | ||
$Interior/Options/X.value = element.position.x | ||
$Interior/Options/Y.value = element.position.y | ||
$Interior/Options/X.max_value = element.project.size.x | ||
$Interior/Options/Y.max_value = element.project.size.y | ||
$Interior/Options2/Opacity.value = element.modulate.a * 100 | ||
_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(index) | ||
Global.current_project.change_project() | ||
|
||
|
||
func _on_Scale_value_changed(value): | ||
if _ignore_spinbox_changes: | ||
return | ||
element.scale.x = value / 100 | ||
element.scale.y = value / 100 | ||
element.change_properties() | ||
|
||
|
||
func _on_X_value_changed(value): | ||
if _ignore_spinbox_changes: | ||
return | ||
element.position.x = value | ||
element.change_properties() | ||
|
||
|
||
func _on_Y_value_changed(value): | ||
if _ignore_spinbox_changes: | ||
return | ||
element.position.y = value | ||
element.change_properties() | ||
|
||
|
||
func _on_Opacity_value_changed(value): | ||
if _ignore_spinbox_changes: | ||
return | ||
element.modulate.a = value / 100 | ||
element.change_properties() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
[gd_scene load_steps=3 format=2] | ||
|
||
[ext_resource path="res://src/UI/ReferenceImageButton.gd" type="Script" id=1] | ||
[ext_resource path="res://src/UI/Nodes/ValueSlider.tscn" type="PackedScene" id=2] | ||
|
||
[node name="ReferenceImageButton" type="PanelContainer"] | ||
anchor_right = 1.0 | ||
anchor_bottom = 1.0 | ||
margin_right = -969.0 | ||
margin_bottom = -581.0 | ||
size_flags_horizontal = 3 | ||
script = ExtResource( 1 ) | ||
|
||
[node name="Interior" type="VBoxContainer" parent="."] | ||
margin_left = 7.0 | ||
margin_top = 7.0 | ||
margin_right = 304.0 | ||
margin_bottom = 132.0 | ||
|
||
[node name="Path" type="Label" parent="Interior"] | ||
margin_right = 297.0 | ||
margin_bottom = 14.0 | ||
size_flags_horizontal = 3 | ||
autowrap = true | ||
|
||
[node name="Options" type="HBoxContainer" parent="Interior"] | ||
margin_top = 18.0 | ||
margin_right = 297.0 | ||
margin_bottom = 42.0 | ||
|
||
[node name="Label2" type="Label" parent="Interior/Options"] | ||
margin_top = 5.0 | ||
margin_right = 56.0 | ||
margin_bottom = 19.0 | ||
text = "Position:" | ||
|
||
[node name="X" parent="Interior/Options" instance=ExtResource( 2 )] | ||
margin_left = 60.0 | ||
margin_right = 122.0 | ||
allow_greater = true | ||
allow_lesser = true | ||
|
||
[node name="Y" parent="Interior/Options" instance=ExtResource( 2 )] | ||
margin_left = 126.0 | ||
margin_right = 189.0 | ||
allow_greater = true | ||
allow_lesser = true | ||
|
||
[node name="Label" type="Label" parent="Interior/Options"] | ||
margin_left = 193.0 | ||
margin_top = 5.0 | ||
margin_right = 230.0 | ||
margin_bottom = 19.0 | ||
text = "Scale:" | ||
|
||
[node name="Scale" parent="Interior/Options" instance=ExtResource( 2 )] | ||
margin_left = 234.0 | ||
margin_right = 297.0 | ||
allow_greater = true | ||
allow_lesser = true | ||
|
||
[node name="Options2" type="HBoxContainer" parent="Interior"] | ||
margin_top = 46.0 | ||
margin_right = 297.0 | ||
margin_bottom = 70.0 | ||
|
||
[node name="Label" type="Label" parent="Interior/Options2"] | ||
margin_top = 5.0 | ||
margin_right = 53.0 | ||
margin_bottom = 19.0 | ||
text = "Opacity:" | ||
|
||
[node name="Opacity" parent="Interior/Options2" instance=ExtResource( 2 )] | ||
margin_left = 57.0 | ||
margin_right = 177.0 | ||
|
||
[node name="Reset" type="Button" parent="Interior/Options2"] | ||
margin_left = 181.0 | ||
margin_right = 229.0 | ||
margin_bottom = 24.0 | ||
text = "Reset" | ||
|
||
[node name="Remove" type="Button" parent="Interior/Options2"] | ||
margin_left = 233.0 | ||
margin_right = 297.0 | ||
margin_bottom = 24.0 | ||
text = "Remove" | ||
|
||
[connection signal="value_changed" from="Interior/Options/X" to="." method="_on_X_value_changed"] | ||
[connection signal="value_changed" from="Interior/Options/Y" to="." method="_on_Y_value_changed"] | ||
[connection signal="value_changed" from="Interior/Options/Scale" to="." method="_on_Scale_value_changed"] | ||
[connection signal="value_changed" from="Interior/Options2/Opacity" to="." method="_on_Opacity_value_changed"] | ||
[connection signal="pressed" from="Interior/Options2/Reset" to="." method="_on_Reset_pressed"] | ||
[connection signal="pressed" from="Interior/Options2/Remove" to="." method="_on_Remove_pressed"] |
Oops, something went wrong.