diff --git a/Translations/Translations.pot b/Translations/Translations.pot index fb38ac224ce..a61ccaf0183 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -2609,3 +2609,9 @@ msgstr "" #. Found under certain image effects that support properties that can be animated. A type of interpolation. msgid "Backing out at ends" msgstr "" + +msgid "Silhouette" +msgstr "" + +msgid "Blacks out the image and makes all opaque pixels a dark color." +msgstr "" diff --git a/src/Shaders/SilhouetteShader.gdshader b/src/Shaders/SilhouetteShader.gdshader new file mode 100644 index 00000000000..dc9d4d37da3 --- /dev/null +++ b/src/Shaders/SilhouetteShader.gdshader @@ -0,0 +1,14 @@ +shader_type canvas_item; + +uniform vec4 silhouette_color: hint_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 + } +} \ No newline at end of file diff --git a/src/UI/ReferenceImages/ReferenceImage.gd b/src/UI/ReferenceImages/ReferenceImage.gd index 60e55ebbd15..307b53b07ce 100644 --- a/src/UI/ReferenceImages/ReferenceImage.gd +++ b/src/UI/ReferenceImages/ReferenceImage.gd @@ -6,9 +6,12 @@ signal properties_changed var project = Global.current_project +var shader: Shader = preload("res://src/Shaders/SilhouetteShader.gdshader") + var image_path: String = "" var filter = false +var silhouette := false func _ready() -> void: @@ -43,6 +46,7 @@ func serialize() -> Dictionary: "modulate_b": modulate.b, "modulate_a": modulate.a, "filter": filter, + "silhouette": silhouette, "image_path": image_path } @@ -63,6 +67,14 @@ func deserialize(d: Dictionary) -> void: # don't do FLAG_REPEAT - it could cause visual issues itex.create_from_image(img, Texture.FLAG_MIPMAPS) texture = itex + # 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_param("silhouette_color", Color(0.069, 0.069326, 0.074219)) + set_material(mat) + # Now that the image may have been established... position_reset() if d.has("x"): @@ -83,6 +95,8 @@ func deserialize(d: Dictionary) -> void: modulate.a = d["modulate_a"] if d.has("filter"): filter = d["filter"] + if d.has("silhouette"): + get_material().set_shader_param("show_silhouette", d["silhouette"]) change_properties() diff --git a/src/UI/ReferenceImages/ReferenceImageButton.gd b/src/UI/ReferenceImages/ReferenceImageButton.gd index 7a69a139e6c..8e44586e456 100644 --- a/src/UI/ReferenceImages/ReferenceImageButton.gd +++ b/src/UI/ReferenceImages/ReferenceImageButton.gd @@ -90,3 +90,9 @@ func _on_ApplyFilter_toggled(button_pressed: bool) -> void: else: element.texture.flags = Texture.FLAG_MIPMAPS element.change_properties() + + +func _on_Silhouette_toggled(button_pressed: bool) -> void: + element.silhouette = button_pressed + element.get_material().set_shader_param("show_silhouette", button_pressed) + element.change_properties() diff --git a/src/UI/ReferenceImages/ReferenceImageButton.tscn b/src/UI/ReferenceImages/ReferenceImageButton.tscn index 8333aed28fa..43028e09579 100644 --- a/src/UI/ReferenceImages/ReferenceImageButton.tscn +++ b/src/UI/ReferenceImages/ReferenceImageButton.tscn @@ -14,41 +14,41 @@ script = ExtResource( 2 ) [node name="Interior" type="VBoxContainer" parent="."] margin_left = 7.0 margin_top = 7.0 -margin_right = 304.0 +margin_right = 325.0 margin_bottom = 133.0 [node name="PathHeader" type="HBoxContainer" parent="Interior"] -margin_right = 297.0 +margin_right = 318.0 margin_bottom = 14.0 custom_constants/separation = 0 [node name="Path" type="LinkButton" parent="Interior/PathHeader"] modulate = Color( 0.552941, 1, 0.298039, 1 ) -margin_right = 99.0 +margin_right = 106.0 margin_bottom = 14.0 size_flags_horizontal = 3 underline = 1 [node name="PathHTML" type="Label" parent="Interior/PathHeader"] self_modulate = Color( 0.552941, 1, 0.298039, 1 ) -margin_left = 99.0 -margin_right = 198.0 +margin_left = 106.0 +margin_right = 212.0 margin_bottom = 14.0 size_flags_horizontal = 3 [node name="HSeparator" type="HSeparator" parent="Interior/PathHeader"] -margin_left = 198.0 -margin_right = 297.0 +margin_left = 212.0 +margin_right = 318.0 margin_bottom = 14.0 size_flags_horizontal = 3 [node name="PreviewAndOptions" type="HBoxContainer" parent="Interior"] margin_top = 18.0 -margin_right = 297.0 +margin_right = 318.0 margin_bottom = 98.0 [node name="Options" type="GridContainer" parent="Interior/PreviewAndOptions"] -margin_right = 213.0 +margin_right = 234.0 margin_bottom = 80.0 size_flags_horizontal = 3 columns = 2 @@ -62,18 +62,18 @@ align = 2 [node name="Position" type="HBoxContainer" parent="Interior/PreviewAndOptions/Options"] margin_left = 60.0 -margin_right = 213.0 +margin_right = 234.0 margin_bottom = 24.0 size_flags_horizontal = 3 [node name="X" parent="Interior/PreviewAndOptions/Options/Position" instance=ExtResource( 1 )] -margin_right = 74.0 +margin_right = 85.0 allow_greater = true allow_lesser = true [node name="Y" parent="Interior/PreviewAndOptions/Options/Position" instance=ExtResource( 1 )] -margin_left = 78.0 -margin_right = 153.0 +margin_left = 89.0 +margin_right = 174.0 allow_greater = true allow_lesser = true @@ -87,7 +87,7 @@ align = 2 [node name="Scale" parent="Interior/PreviewAndOptions/Options" instance=ExtResource( 1 )] margin_left = 60.0 margin_top = 28.0 -margin_right = 213.0 +margin_right = 234.0 margin_bottom = 52.0 allow_greater = true allow_lesser = true @@ -102,12 +102,12 @@ align = 2 [node name="Opacity" parent="Interior/PreviewAndOptions/Options" instance=ExtResource( 1 )] margin_left = 60.0 margin_top = 56.0 -margin_right = 213.0 +margin_right = 234.0 margin_bottom = 80.0 [node name="PreviewPanel" type="Panel" parent="Interior/PreviewAndOptions"] -margin_left = 217.0 -margin_right = 297.0 +margin_left = 238.0 +margin_right = 318.0 margin_bottom = 80.0 rect_min_size = Vector2( 80, 80 ) @@ -129,27 +129,34 @@ expand = true [node name="OtherOptions" type="HBoxContainer" parent="Interior"] margin_top = 102.0 -margin_right = 297.0 +margin_right = 318.0 margin_bottom = 126.0 alignment = 2 [node name="ApplyFilter" type="CheckBox" parent="Interior/OtherOptions"] -margin_left = 76.0 -margin_right = 177.0 +margin_right = 101.0 margin_bottom = 24.0 hint_tooltip = "Uses a magnifying filter, to enable smooth zooming in of the texture." text = "Apply Filter" align = 1 +[node name="Silhouette" type="CheckBox" parent="Interior/OtherOptions"] +margin_left = 105.0 +margin_right = 198.0 +margin_bottom = 24.0 +hint_tooltip = "Blacks out the image and makes all opaque pixels a dark color." +text = "Silhouette" + [node name="Reset" type="Button" parent="Interior/OtherOptions"] -margin_left = 181.0 -margin_right = 229.0 +margin_left = 202.0 +margin_right = 250.0 margin_bottom = 24.0 text = "Reset" +icon_align = 1 [node name="Remove" type="Button" parent="Interior/OtherOptions"] -margin_left = 233.0 -margin_right = 297.0 +margin_left = 254.0 +margin_right = 318.0 margin_bottom = 24.0 custom_colors/font_color = Color( 1, 0.266667, 0.266667, 1 ) text = "Remove" @@ -160,5 +167,6 @@ text = "Remove" [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"]