技术方向可行

使用鼠标轨迹生成偏移应用到材质上实现扭曲技术可行
This commit is contained in:
2025-08-29 00:51:54 +08:00
parent be6e40383d
commit 11896c87b1
7 changed files with 94 additions and 57 deletions

View File

@ -2,8 +2,7 @@ local DataTableUtils = require("Utils.DataTableUtils")
local ESlateVisibility = import("ESlateVisibility")
local SlateBlueprintLibrary = import("SlateBlueprintLibrary")
local WidgetLayoutLibrary = import("WidgetLayoutLibrary")
local BusyGamePlayLibrary = import("BusyGamePlayLibrary")
--- @class PreCookCenterWidget
--- @field ImgContainer table
@ -33,6 +32,8 @@ function PreCookCenterWidget:OnInitialized()
-- self.BtnMain.OnClicked:Add(function()
-- print("onclicked")
-- end)
self.DataTexture = BusyGamePlayLibrary.CreateTextureBuffer(self)
end
function PreCookCenterWidget:Construct()
@ -69,7 +70,6 @@ end
local function UpdateOldMouseTrack(old_mouse_tracks, delta_time)
local new_mouse_tracks = {}
-- local new_track = {x=fixed_x, y=fixed_y, remain=1.0}
for _, track in pairs(old_mouse_tracks) do
track.remain = track.remain - delta_time
if track.remain > 0 then
@ -79,15 +79,6 @@ local function UpdateOldMouseTrack(old_mouse_tracks, delta_time)
return new_mouse_tracks
end
--- 将鼠标的轨迹坐标规范到以起始点到终点所连直线为x轴的坐标系下
local function NormalizeTrackParam(mouse_tracks)
end
--- 根据指定点坐标,求解三次样条参数
local function GetSplineParams(normalize_params)
end
local function UpdateCutMaskByTracks(widget, mouse_tracks)
local FVector2D = import("Vector2D")
@ -108,32 +99,59 @@ local function UpdateCutMaskByTracks(widget, mouse_tracks)
render_transform.Scale = scale
render_transform.Translation = translation
render_transform.Angle = (math.atan(delta_y, delta_x) / (2 * math.pi)) * 360
-- render_transform.Scale = FVector2D(mask_length / 512, 1)
print(render_transform.Angle, math.atan(delta_y, delta_x))
widget:SetRenderTransform(render_transform)
--[[
/** The amount to translate the widget in slate units */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Transform, meta=( Delta = "1" ))
FVector2D Translation;
/** The scale to apply to the widget */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Transform, meta=( UIMin = "-5", UIMax = "5", Delta = "0.05" ))
FVector2D Scale;
/** The amount to shear the widget in slate units */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Transform, meta=( UIMin = "-89", ClampMin = "-89", UIMax = "89", ClampMax = "89", Delta = "1" ))
FVector2D Shear;
/** The angle in degrees to rotate */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Transform, meta=( UIMin = "-180", UIMax = "180", Delta = "1" ))
float Angle;
]]
end
--- 从起点到终点画一条线以这条线为新的x坐标轴将所有的点坐标映射到新坐标系下
local function TransformCurveToEndpointAxes(points)
local A = points[1]
local B = points[#points]
-- 计算向量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
return new_points
end
--- 将曲线的Y坐标规范到(-0.50.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
end
function PreCookCenterWidget:Tick(geometry, delta_time)
local size = SlateBlueprintLibrary.GetLocalSize(geometry)
local cursor_pos = WidgetLayoutLibrary.GetMousePositionOnViewport(self)
@ -148,28 +166,26 @@ function PreCookCenterWidget:Tick(geometry, delta_time)
end
-- 计算样条参数
local normalize_params = NormalizeTrackParam(mouse_tracks)
local A, B, C, D = GetSplineParams(normalize_params) -- Ax^3 + Bx^2 + Cx + D
if #mouse_tracks > 2 then
local transformed_tracks = TransformCurveToEndpointAxes(mouse_tracks)
local normalize_tracks = NormalizeCurveYToHalfRange(transformed_tracks)
-- 计算划痕位置
local offsets = {}
for _, track in pairs(normalize_tracks) do
table.insert(offsets, track.Y)
end
UpdateCutMaskByTracks(self.ImgMask, mouse_tracks)
BusyGamePlayLibrary.UpdateTextureBuffer(self.DataTexture, offsets)
local mi = self.ImgMask:GetDynamicMaterial()
mi:SetTextureParameterValue("Param", self.DataTexture)
mi:SetScalarParameterValue("VertexCount", #offsets)
mi:SetScalarParameterValue("SourceWidth", 512)
UpdateCutMaskByTracks(self.ImgMask, mouse_tracks)
end
self.mouse_tracks = mouse_tracks
-- print(fixed_x, fixed_y, #self.mouse_tracks)
end
-- function PreCookCenterWidget:LuaMouseButtonDown()
-- print("on mouse button down")
-- end
-- function PreCookCenterWidget:LuaMouseButtonUp()
-- print("on mouse button up")
-- end
return Class(nil, nil, PreCookCenterWidget)

View File

@ -83,9 +83,26 @@ bool UBusyGamePlayLibrary::GetCookMaterialStateConfig(const FName& RowName, FBus
return GetTableConfig<FBusyCookMaterialStateConfig>(TEXT("CookMaterialStateConfig"), RowName, RowData);
}
FLuaBPVar UBusyGamePlayLibrary::TestTable(const FName& RowName){
UDataTable* Table = UBusyGamePlayLibrary::GetGameDataTable("CookMaterialStateConfig");
auto Config = Table->FindRow<FTableRowBase>(RowName, "", true);
return FLuaBPVar();
FLuaBPVar UBusyGamePlayLibrary::CreateTextureBuffer(UObject* WorldContextObject){
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
auto DataTexture = UTexture2D::CreateTransient(512, 1, PF_R32_FLOAT);
DataTexture->Filter = TF_Trilinear;
DataTexture->AddressX = TA_Clamp;
DataTexture->AddressY = TA_Clamp;
DataTexture->UpdateResource();
return ULuaBlueprintLibrary::CreateVarFromObject(WorldContextObject, DataTexture);
}
void UBusyGamePlayLibrary::UpdateTextureBuffer(UTexture2D *DataTexture, TArray<float> FloatData){
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>д<EFBFBD><D0B4>
DataTexture->GetPlatformData()->Mips[0];
FTexture2DMipMap& Mip = DataTexture->GetPlatformData()->Mips[0];
void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD><DDB8>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD>
FMemory::Memcpy(Data, FloatData.GetData(), FloatData.Num() * sizeof(float));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Mip.BulkData.Unlock();
DataTexture->UpdateResource();
}

View File

@ -60,6 +60,10 @@ public:
static bool GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData);
UFUNCTION(BlueprintPure)
static FLuaBPVar TestTable(const FName& RowName);
static FLuaBPVar CreateTextureBuffer(UObject* WorldContextObject);
UFUNCTION(BlueprintCallable)
static void UpdateTextureBuffer(UTexture2D* DataTexture, TArray<float> FloatData);
};