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

Make clipping masks work with Move tool and offset image dialog (#1057)

* made clipping masks work with offset image dialog

* move tool now works with clipping masks
This commit is contained in:
Variable 2024-07-30 21:29:55 +05:00 committed by GitHub
parent f27d152cb3
commit 1d82bd95e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 81 additions and 8 deletions

View file

@ -172,10 +172,18 @@ void fragment() {
if (!origin_y_positive) {
current_origin.y = -current_origin.y;
}
// get origin of previous layer (used for clipping masks to work correctly)
vec2 prev_origin = texture(metadata, vec2(float(i - 1), 2.0 / metadata_size_float.y)).rg;
if (!origin_x_positive) {
prev_origin.x = -prev_origin.x;
}
if (!origin_y_positive) {
prev_origin.y = -prev_origin.y;
}
float current_opacity = texture(metadata, vec2(layer_index, 1.0 / metadata_size_float.y)).r;
vec2 uv = UV - current_origin;
vec4 layer_color = texture(layers, vec3(uv, float(i)));
vec4 prev_layer_color = texture(layers, vec3(uv, float(i - 1)));
vec4 prev_layer_color = texture(layers, vec3(UV - prev_origin, float(i - 1)));
float clipping_mask = texture(metadata, vec2(layer_index, 3.0 / metadata_size_float.y)).r;
layer_color.a *= prev_layer_color.a * step(0.5, clipping_mask) + 1.0 * step(clipping_mask, 0.5);
layer_color.a = border_trim(layer_color, uv);

View file

@ -10,9 +10,6 @@ var wrap_around := false
func _ready() -> void:
super._ready()
var sm := ShaderMaterial.new()
sm.shader = shader
preview.set_material(sm)
# Set in the order of the Animate enum
animate_panel.add_float_property(
"Offset X", $VBoxContainer/OffsetOptions/OffsetSliders.get_sliders()[0]
@ -39,17 +36,85 @@ func commit_action(cel: Image, project := Global.current_project) -> void:
var params := {"offset": offset, "wrap_around": wrap_around, "selection": selection_tex}
if !has_been_confirmed:
for param in params:
preview.material.set_shader_parameter(param, params[param])
recalculate_preview(params)
else:
var gen := ShaderImageEffect.new()
gen.generate_image(cel, shader, params, project.size)
func _on_OffsetSliders_value_changed(_value: Vector2) -> void:
update_preview()
update_preview() # (from here, commit_action will be called, and then recalculate_preview)
func _on_WrapCheckBox_toggled(button_pressed: bool) -> void:
wrap_around = button_pressed
update_preview()
update_preview() # (from here, commit_action will be called, and then recalculate_preview)
func recalculate_preview(params: Dictionary) -> void:
var frame := Global.current_project.frames[_preview_idx]
commit_idx = _preview_idx
match affect:
SELECTED_CELS:
selected_cels.fill(Color(0, 0, 0, 0))
blend_layers(selected_cels, frame, params, true)
preview_image.copy_from(selected_cels)
_:
current_frame.fill(Color(0, 0, 0, 0))
blend_layers(current_frame, frame, params)
preview_image.copy_from(current_frame)
## Altered version of blend_layers() located in DrawingAlgos.gd
## This function is REQUIRED in order for offset effect to work correctly with cliping masks
func blend_layers(
image: Image,
frame: Frame,
effect_params := {},
only_selected_cels := false,
only_selected_layers := false,
) -> void:
var project := Global.current_project
var frame_index := project.frames.find(frame)
var previous_ordered_layers: Array[int] = project.ordered_layers
project.order_layers(frame_index)
var textures: Array[Image] = []
var gen := ShaderImageEffect.new()
# Nx4 texture, where N is the number of layers and the first row are the blend modes,
# the second are the opacities, the third are the origins and the fourth are the
# clipping mask booleans.
var metadata_image := Image.create(project.layers.size(), 4, false, Image.FORMAT_R8)
for i in project.layers.size():
var ordered_index := project.ordered_layers[i]
var layer := project.layers[ordered_index]
var include := true if layer.is_visible_in_hierarchy() else false
if only_selected_cels and include:
var test_array := [frame_index, i]
if not test_array in project.selected_cels:
include = false
if only_selected_layers and include:
var layer_is_selected := false
for selected_cel in project.selected_cels:
if i == selected_cel[1]:
layer_is_selected = true
break
if not layer_is_selected:
include = false
var cel := frame.cels[ordered_index]
var cel_image := layer.display_effects(cel)
if include: ## apply offset effect to it
gen.generate_image(cel_image, shader, effect_params, project.size)
textures.append(cel_image)
DrawingAlgos.set_layer_metadata_image(layer, cel, metadata_image, ordered_index, include)
var texture_array := Texture2DArray.new()
texture_array.create_from_images(textures)
var params := {
"layers": texture_array,
"metadata": ImageTexture.create_from_image(metadata_image),
}
var blended := Image.create(project.size.x, project.size.y, false, image.get_format())
var blend_layers_shader = DrawingAlgos.blend_layers_shader
gen.generate_image(blended, blend_layers_shader, params, project.size)
image.blend_rect(blended, Rect2i(Vector2i.ZERO, project.size), Vector2i.ZERO)
# Re-order the layers again to ensure correct canvas drawing
project.ordered_layers = previous_ordered_layers