--information:Handle v0.1.0 by Korarei --label:配置 --require:2004800 --select@source:Source,Image=0,Layer=1 --file@image:Image,"" --track@layer:Layer,-100,100,0,1,--- --group:Layout,true --separator:Padding --track@layout_padding_x:Layout::Padding::X,-10000,10000,0,0.01 --track@layout_padding_y:Layout::Padding::Y,-10000,10000,0,0.01 --group:Transform,false --track@transform_rotation:Transform::Rotation,-3600,3600,0,0.01 --separator:Scale --track@transform_scale_x:Transform::Scale::X,-1000,1000,100,0.01 --track@transform_scale_y:Transform::Scale::Y,-1000,1000,100,0.01 --group:Additional Options,false --select@layer_reference:Layer Reference,Absolute=0,Relative=1 --[[pixelshader@render: Texture2D source_texture : register(t0); Texture2D handle_texture : register(t1); SamplerState linear_sampler : register(s0); cbuffer Constants : register(b0) { float2 resolution; float2 padding; float4 transform; } float4 render(float4 pos : SV_Position) : SV_Target { float2 size; source_texture.GetDimensions(size.x, size.y); float2 origin = (resolution - size) * 0.5; float2 extent = origin + size; const float4 base = source_texture.Sample(linear_sampler, (pos.xy - origin) * rcp(size)); float2 corners[4]; corners[0] = origin - padding; corners[1] = float2(extent.x + padding.x, origin.y - padding.y); corners[2] = float2(origin.x - padding.x, extent.y + padding.y); corners[3] = extent + padding; float4 handle = 0.0; [unroll] for (int i = 0; i < 4; ++i) { const float2 p = pos.xy - corners[i]; const float2 uv = float2(dot(p, transform.xy), dot(p, transform.zw)) + 0.5; const float4 src = handle_texture.Sample(linear_sampler, lerp(uv, 1.0 - uv, step(uv, 0.0))); handle = mad(handle, 1.0 - src.a, src); } return mad(base, 1.0 - handle.a, handle); } ]] do local obj, math = obj, math transform_rotation = math.rad(transform_rotation) transform_scale_x = transform_scale_x * 0.01 transform_scale_y = transform_scale_y * 0.01 local function copyxform(dst, src) dst.cx, dst.cy, dst.cz = src.cx, src.cy, src.cz dst.ox, dst.oy, dst.oz = src.ox, src.oy, src.oz dst.rx, dst.ry, dst.rz = src.rx, src.ry, src.rz dst.sx, dst.sy, dst.sz = src.sx, src.sy, src.sz dst.alpha = src.alpha end local src_w, src_h = obj.w, obj.h if not obj.copybuffer("cache:src", "object") then print("@error", "Failed to copy buffer") obj.load("text", "") return end local xform = {} copyxform(xform, obj) if source == 0 then if image == "" then print("@error", "Invalid source image path") obj.load("text", "") return end if not obj.load("image", image) then print("@error", "Failed to load image data") obj.load("text", "") return end else layer = math.max(layer_reference == 0 and layer or layer + obj.layer, 0) if layer == 0 or layer == obj.layer then print("@error", "Invalid source layer") obj.load("text", "") return end if not obj.load("layer", layer, true) then print("@error", "Failed to load layer data") obj.load("text", "") return end end local dst_w, dst_h local m00, m01, m10, m11 do local w, h = obj.w * transform_scale_x, obj.h * transform_scale_y if math.abs(w * h) < 1.0 then if not obj.copybuffer("object", "cache:src") then print("@error", "Failed to copy buffer") obj.load("text", "") return end copyxform(obj, xform) return end local dir_x = math.cos(transform_rotation) local dir_y = math.sin(transform_rotation) local proj_x = math.abs(dir_x) local proj_y = math.abs(dir_y) local extent_w = math.abs(w) local extent_h = math.abs(h) local bbox_w = extent_w * proj_x + extent_h * proj_y local bbox_h = extent_w * proj_y + extent_h * proj_x dst_w = math.ceil(math.max(src_w, math.abs(src_w * 0.5 + layout_padding_x) * 2.0 + bbox_w)) dst_h = math.ceil(math.max(src_h, math.abs(src_h * 0.5 + layout_padding_y) * 2.0 + bbox_h)) local scale_x = 1.0 / w local scale_y = 1.0 / h m00 = dir_x * scale_x m01 = dir_y * scale_x m10 = -dir_y * scale_y m11 = dir_x * scale_y end obj.clearbuffer("cache:dst", dst_w, dst_h) obj.pixelshader("render", "cache:dst", { "cache:src", "object" }, { dst_w, dst_h, layout_padding_x, layout_padding_y, m00, m01, m10, m11, }, "copy", "clip") if not obj.copybuffer("object", "cache:dst") then print("@error", "Failed to copy buffer") obj.load("text", "") return end copyxform(obj, xform) end