2025-08-27 00:56:05 +08:00
|
|
|
|
local DataTableUtils = require("Utils.DataTableUtils")
|
|
|
|
|
|
local ESlateVisibility = import("ESlateVisibility")
|
|
|
|
|
|
local SlateBlueprintLibrary = import("SlateBlueprintLibrary")
|
|
|
|
|
|
local WidgetLayoutLibrary = import("WidgetLayoutLibrary")
|
2025-08-29 00:51:54 +08:00
|
|
|
|
local BusyGamePlayLibrary = import("BusyGamePlayLibrary")
|
2025-08-27 00:56:05 +08:00
|
|
|
|
|
|
|
|
|
|
--- @class PreCookCenterWidget
|
|
|
|
|
|
--- @field ImgContainer table
|
|
|
|
|
|
--- @field ImgCookMaterial table
|
|
|
|
|
|
local PreCookCenterWidget = {}
|
|
|
|
|
|
|
|
|
|
|
|
function PreCookCenterWidget:ctor()
|
|
|
|
|
|
self.mouse_tracks = {}
|
|
|
|
|
|
self.is_pressed = false
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function PreCookCenterWidget:OnInitialized()
|
|
|
|
|
|
self.bHasScriptImplementedTick = true
|
|
|
|
|
|
|
|
|
|
|
|
self.BtnMain.OnReleased:Add(function()
|
|
|
|
|
|
-- self.bHasScriptImplementedTick = false
|
|
|
|
|
|
self.is_pressed = false
|
|
|
|
|
|
print("release")
|
|
|
|
|
|
end)
|
|
|
|
|
|
self.BtnMain.OnPressed:Add(function()
|
|
|
|
|
|
self.mouse_tracks = {}
|
|
|
|
|
|
self.is_pressed = true
|
|
|
|
|
|
-- self.bHasScriptImplementedTick = true
|
|
|
|
|
|
print("pressed")
|
|
|
|
|
|
end)
|
|
|
|
|
|
-- self.BtnMain.OnClicked:Add(function()
|
|
|
|
|
|
-- print("onclicked")
|
|
|
|
|
|
-- end)
|
2025-08-29 00:51:54 +08:00
|
|
|
|
|
|
|
|
|
|
self.DataTexture = BusyGamePlayLibrary.CreateTextureBuffer(self)
|
2025-08-27 00:56:05 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function PreCookCenterWidget:Construct()
|
|
|
|
|
|
-- self.bHasScriptImplementedTick = true
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function PreCookCenterWidget:Destruct()
|
|
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function PreCookCenterWidget:SetEmpty()
|
|
|
|
|
|
self.ImgContainer:SetVisibility(ESlateVisibility.Collapsed)
|
|
|
|
|
|
self.ImgCookMaterial:SetVisibility(ESlateVisibility.Collapsed)
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function PreCookCenterWidget:AddContainer(pre_cook_contianer_id)
|
|
|
|
|
|
local row = DataTableUtils.GetDataTableRow("PreCookItemConfig", pre_cook_contianer_id)
|
|
|
|
|
|
if not row then return end
|
|
|
|
|
|
self.ImgContainer:SetBrushFromSoftTexture(row.CenterDisplayResource, true)
|
|
|
|
|
|
self.ImgContainer:SetVisibility(ESlateVisibility.SelfHitTestInvisible)
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function PreCookCenterWidget:RemoveContainer()
|
|
|
|
|
|
self.ImgContainer:SetVisibility(ESlateVisibility.Collapsed)
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function PreCookCenterWidget:AddCookMaterial(pre_cook_material_id)
|
|
|
|
|
|
local row = DataTableUtils.GetDataTableRow("PreCookItemConfig", pre_cook_material_id)
|
|
|
|
|
|
if not row then return end
|
|
|
|
|
|
self.ImgCookMaterial:SetBrushFromSoftTexture(row.CenterDisplayResource, true)
|
|
|
|
|
|
self.ImgCookMaterial:SetVisibility(ESlateVisibility.SelfHitTestInvisible)
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function UpdateOldMouseTrack(old_mouse_tracks, delta_time)
|
|
|
|
|
|
local new_mouse_tracks = {}
|
|
|
|
|
|
for _, track in pairs(old_mouse_tracks) do
|
|
|
|
|
|
track.remain = track.remain - delta_time
|
|
|
|
|
|
if track.remain > 0 then
|
|
|
|
|
|
table.insert(new_mouse_tracks, track)
|
|
|
|
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
return new_mouse_tracks
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function UpdateCutMaskByTracks(widget, mouse_tracks)
|
|
|
|
|
|
local FVector2D = import("Vector2D")
|
|
|
|
|
|
local FWidgetTransform = import("WidgetTransform")
|
|
|
|
|
|
if #mouse_tracks < 2 then return end
|
|
|
|
|
|
|
|
|
|
|
|
local translation, scale = FVector2D(), FVector2D()
|
|
|
|
|
|
local render_transform = FWidgetTransform()
|
|
|
|
|
|
local first_point, last_point = mouse_tracks[1], mouse_tracks[#mouse_tracks]
|
|
|
|
|
|
local delta_x = last_point.X - first_point.X
|
|
|
|
|
|
local delta_y = last_point.Y - first_point.Y
|
|
|
|
|
|
local mask_length = (delta_x^2 + delta_y^2)^0.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
translation.X, translation.Y = first_point.X, first_point.Y
|
|
|
|
|
|
scale.X, scale.Y = mask_length / 512, 1
|
|
|
|
|
|
render_transform.Scale = scale
|
|
|
|
|
|
render_transform.Translation = translation
|
|
|
|
|
|
render_transform.Angle = (math.atan(delta_y, delta_x) / (2 * math.pi)) * 360
|
|
|
|
|
|
|
|
|
|
|
|
widget:SetRenderTransform(render_transform)
|
2025-08-29 00:51:54 +08:00
|
|
|
|
end
|
2025-08-27 00:56:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-08-29 00:51:54 +08:00
|
|
|
|
--- 从起点到终点画一条线,以这条线为新的x坐标轴,将所有的点坐标映射到新坐标系下
|
|
|
|
|
|
local function TransformCurveToEndpointAxes(points)
|
|
|
|
|
|
local A = points[1]
|
|
|
|
|
|
local B = points[#points]
|
2025-08-27 00:56:05 +08:00
|
|
|
|
|
2025-08-29 00:51:54 +08:00
|
|
|
|
-- 计算向量AB
|
|
|
|
|
|
local dx = B.X - A.X
|
|
|
|
|
|
local dy = B.Y - A.Y
|
|
|
|
|
|
local len = math.sqrt(dx * dx + dy * dy)
|
|
|
|
|
|
if len == 0 then
|
|
|
|
|
|
return {}
|
|
|
|
|
|
-- error("Start and end points are the same, cannot define X-axis.")
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- 计算X轴单位向量
|
|
|
|
|
|
local ux = dx / len
|
|
|
|
|
|
local uy = dy / len
|
|
|
|
|
|
|
|
|
|
|
|
-- 计算Y轴单位向量(逆时针旋转90度)
|
|
|
|
|
|
local vx = -uy
|
|
|
|
|
|
local vy = ux
|
|
|
|
|
|
|
|
|
|
|
|
-- 映射所有点到新坐标系
|
|
|
|
|
|
local new_points = {}
|
|
|
|
|
|
for i, point in ipairs(points) do
|
|
|
|
|
|
local apx = point.X - A.X
|
|
|
|
|
|
local apy = point.Y - A.Y
|
|
|
|
|
|
local new_x = apx * ux + apy * uy -- 点积与X轴单位向量
|
|
|
|
|
|
local new_y = apx * vx + apy * vy -- 点积与Y轴单位向量
|
|
|
|
|
|
new_points[i] = {X = new_x, Y = new_y}
|
|
|
|
|
|
end
|
2025-08-27 00:56:05 +08:00
|
|
|
|
|
2025-08-29 00:51:54 +08:00
|
|
|
|
return new_points
|
|
|
|
|
|
end
|
2025-08-27 00:56:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-08-29 00:51:54 +08:00
|
|
|
|
--- 将曲线的Y坐标规范到(-0.5,0.5)的范围内,供材质使用
|
|
|
|
|
|
local function NormalizeCurveYToHalfRange(points)
|
|
|
|
|
|
if #points < 2 then return end
|
|
|
|
|
|
local length = points[#points].X - points[1].X
|
|
|
|
|
|
for _, point in pairs(points) do
|
|
|
|
|
|
point.Y = - point.Y / length -- 临时加个取反
|
|
|
|
|
|
point.X = point.X / length
|
|
|
|
|
|
end
|
|
|
|
|
|
return points
|
2025-08-27 00:56:05 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
2025-08-29 00:51:54 +08:00
|
|
|
|
|
2025-08-27 00:56:05 +08:00
|
|
|
|
function PreCookCenterWidget:Tick(geometry, delta_time)
|
|
|
|
|
|
local size = SlateBlueprintLibrary.GetLocalSize(geometry)
|
|
|
|
|
|
local cursor_pos = WidgetLayoutLibrary.GetMousePositionOnViewport(self)
|
|
|
|
|
|
local left_top = SlateBlueprintLibrary.GetLocalTopLeft(geometry)
|
|
|
|
|
|
local fixed_x = math.min(math.max(cursor_pos.X - left_top.X, 0), size.X)
|
|
|
|
|
|
local fixed_y = math.min(math.max(cursor_pos.Y - left_top.Y, 0), size.Y)
|
|
|
|
|
|
|
|
|
|
|
|
local mouse_tracks = UpdateOldMouseTrack(self.mouse_tracks, delta_time)
|
|
|
|
|
|
|
|
|
|
|
|
if self.is_pressed then
|
|
|
|
|
|
table.insert(mouse_tracks, {X=fixed_x, Y=fixed_y, remain=0.5})
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- 计算样条参数
|
2025-08-29 00:51:54 +08:00
|
|
|
|
if #mouse_tracks > 2 then
|
|
|
|
|
|
local transformed_tracks = TransformCurveToEndpointAxes(mouse_tracks)
|
|
|
|
|
|
local normalize_tracks = NormalizeCurveYToHalfRange(transformed_tracks)
|
2025-08-27 00:56:05 +08:00
|
|
|
|
|
2025-08-29 00:51:54 +08:00
|
|
|
|
local offsets = {}
|
|
|
|
|
|
for _, track in pairs(normalize_tracks) do
|
|
|
|
|
|
table.insert(offsets, track.Y)
|
|
|
|
|
|
end
|
2025-08-27 00:56:05 +08:00
|
|
|
|
|
2025-08-29 00:51:54 +08:00
|
|
|
|
BusyGamePlayLibrary.UpdateTextureBuffer(self.DataTexture, offsets)
|
2025-08-27 00:56:05 +08:00
|
|
|
|
|
2025-08-29 00:51:54 +08:00
|
|
|
|
local mi = self.ImgMask:GetDynamicMaterial()
|
|
|
|
|
|
mi:SetTextureParameterValue("Param", self.DataTexture)
|
|
|
|
|
|
mi:SetScalarParameterValue("VertexCount", #offsets)
|
|
|
|
|
|
mi:SetScalarParameterValue("SourceWidth", 512)
|
|
|
|
|
|
UpdateCutMaskByTracks(self.ImgMask, mouse_tracks)
|
|
|
|
|
|
end
|
2025-08-27 00:56:05 +08:00
|
|
|
|
|
2025-08-29 00:51:54 +08:00
|
|
|
|
self.mouse_tracks = mouse_tracks
|
2025-08-27 00:56:05 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Class(nil, nil, PreCookCenterWidget)
|