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:
parent
f27d152cb3
commit
1d82bd95e5
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue