diff --git a/Content/Data/Input/Homeland/Hearth/IA_PreCookTouchBegin.uasset b/Content/Data/Input/Homeland/Hearth/IA_PreCookTouchBegin.uasset new file mode 100644 index 0000000..efae4fe Binary files /dev/null and b/Content/Data/Input/Homeland/Hearth/IA_PreCookTouchBegin.uasset differ diff --git a/Content/Data/Input/Homeland/Hearth/IA_PreCookTouchEnd.uasset b/Content/Data/Input/Homeland/Hearth/IA_PreCookTouchEnd.uasset new file mode 100644 index 0000000..fcebecc Binary files /dev/null and b/Content/Data/Input/Homeland/Hearth/IA_PreCookTouchEnd.uasset differ diff --git a/Content/Data/Input/Homeland/Hearth/IMC_PreCookInputContext.uasset b/Content/Data/Input/Homeland/Hearth/IMC_PreCookInputContext.uasset new file mode 100644 index 0000000..374ba41 Binary files /dev/null and b/Content/Data/Input/Homeland/Hearth/IMC_PreCookInputContext.uasset differ diff --git a/Content/Lua/HomeLand/UI/Hearth/Widgets/PreCookCenterWidget.lua b/Content/Lua/HomeLand/UI/Hearth/Widgets/PreCookCenterWidget.lua index d5cc1b4..27c513a 100644 --- a/Content/Lua/HomeLand/UI/Hearth/Widgets/PreCookCenterWidget.lua +++ b/Content/Lua/HomeLand/UI/Hearth/Widgets/PreCookCenterWidget.lua @@ -4,13 +4,18 @@ local SlateBlueprintLibrary = import("SlateBlueprintLibrary") local WidgetLayoutLibrary = import("WidgetLayoutLibrary") local BusyGamePlayLibrary = import("BusyGamePlayLibrary") +local CUT_MASK_DISPLAY_TIME = 1.2 -- 刀光显示的时长 +local CUT_MASK_FADEOUT_TIME = 0.6 -- 刀光开始渐隐的时间点 + --- @class PreCookCenterWidget --- @field ImgContainer table --- @field ImgCookMaterial table +--- @field BtnMain table local PreCookCenterWidget = {} function PreCookCenterWidget:ctor() - self.mouse_tracks = {} + self.mouse_tracks = {} -- 记录当前鼠标的轨迹 + self.rendering_tracks = {} -- 正在被渲染的刀光 self.is_pressed = false end @@ -18,22 +23,20 @@ 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:BP_BindLuaEnhancedInput(self.IA_TouchBegin, function() self.is_pressed = true - -- self.bHasScriptImplementedTick = true - print("pressed") + self.mouse_tracks = {} + self.rendering_tracks = {self.mouse_tracks} + print("new track start") end) - -- self.BtnMain.OnClicked:Add(function() - -- print("onclicked") - -- end) - self.DataTexture = BusyGamePlayLibrary.CreateTextureBuffer(self) + self:BP_BindLuaEnhancedInput(self.IA_TouchEnd, function() + self.is_pressed = false + self.mouse_tracks = {} + print("track end") + end) + + self.BtnMain:SetVisibility(ESlateVisibility.Collapsed) end function PreCookCenterWidget:Construct() @@ -67,43 +70,6 @@ function PreCookCenterWidget:AddCookMaterial(pre_cook_material_id) 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) -end - - --- 从起点到终点画一条线,以这条线为新的x坐标轴,将所有的点坐标映射到新坐标系下 local function TransformCurveToEndpointAxes(points) local A = points[1] @@ -152,39 +118,105 @@ local function NormalizeCurveYToHalfRange(points) end +local function UpdateCutMaskData(rendering_tracks, delta_time) + local new_visible_tracks = {} + for _, track in ipairs(rendering_tracks) do + local is_visible = false + for _, point in pairs(track) do + local remain = math.max(point.remain - delta_time, 0) + point.remain = remain + if remain > 0 then is_visible = true end + end + if is_visible then + table.insert(new_visible_tracks, track) + end + end + return new_visible_tracks +end + +local function DrawCutMaskImage(widget, mouse_tracks) + local FVector2D = import("Vector2D") + local FWidgetTransform = import("WidgetTransform") + -- 设置图片合理的位移、旋转、缩放的参数 + 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) +end + + +-- 更新刀痕的材质 +local function UpdateCusMaskMaterial(widget, texture, mouse_track) + local transformed_tracks = TransformCurveToEndpointAxes(mouse_track) + local normalize_tracks = NormalizeCurveYToHalfRange(transformed_tracks) + + local offsets = {} + for _, track in ipairs(normalize_tracks) do + table.insert(offsets, track.Y) + end + + BusyGamePlayLibrary.UpdateTextureBuffer(texture, offsets) + + local material = widget:GetDynamicMaterial() + material:SetTextureParameterValue("Param", texture) + material:SetScalarParameterValue("VertexCount", #offsets) + material:SetScalarParameterValue("SourceWidth", 512) +end + +function PreCookCenterWidget:GetValidCutMaskWidget() + return self.ImgMask +end + +function PreCookCenterWidget:ResetAllCutMaskWidget() +end + + 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) + -- 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 fixed_x, fixed_y = cursor_pos.X - left_top.X, cursor_pos.Y - left_top.Y + if fixed_x < 0 or fixed_x > size.X or fixed_y < 0 or fixed_y > size.Y then return end + + + -- 更新鼠标移动轨迹 if self.is_pressed then - table.insert(mouse_tracks, {X=fixed_x, Y=fixed_y, remain=0.5}) - end - - -- 计算样条参数 - 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) + local last_point = self.mouse_tracks[#self.mouse_tracks] + if not last_point or math.abs(last_point.X - fixed_x) > 1 or math.abs(last_point.Y - fixed_y) > 1 then + table.insert(self.mouse_tracks, {X=fixed_x, Y=fixed_y, remain=0.5}) end - - 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 + -- 更新正在渲染的轨迹数据 + local rendering_tracks = UpdateCutMaskData(self.rendering_tracks, delta_time) + + -- 绘制刀迹 + for _, track in ipairs(rendering_tracks) do + if #track > 2 then + local widget = self:GetValidCutMaskWidget() + DrawCutMaskImage(widget, track) + -- UpdateCusMaskMaterial(widget, self.DataTexture, track) + end + end + + -- print("Ticking", #rendering_tracks) + + self.rendering_tracks = rendering_tracks end diff --git a/Content/UI/HomeLand/Hearth/WBP_PreCookStationPanel.uasset b/Content/UI/HomeLand/Hearth/WBP_PreCookStationPanel.uasset index 2c7d417..2829fdb 100644 Binary files a/Content/UI/HomeLand/Hearth/WBP_PreCookStationPanel.uasset and b/Content/UI/HomeLand/Hearth/WBP_PreCookStationPanel.uasset differ diff --git a/Content/UI/HomeLand/Hearth/Widgets/PrepCookStation/WBP_PreCookCenterWidget.uasset b/Content/UI/HomeLand/Hearth/Widgets/PrepCookStation/WBP_PreCookCenterWidget.uasset index b8c35cb..ee720ba 100644 Binary files a/Content/UI/HomeLand/Hearth/Widgets/PrepCookStation/WBP_PreCookCenterWidget.uasset and b/Content/UI/HomeLand/Hearth/Widgets/PrepCookStation/WBP_PreCookCenterWidget.uasset differ diff --git a/Source/BusyRabbit/Private/Core/PW_UserWidget.cpp b/Source/BusyRabbit/Private/Core/PW_UserWidget.cpp index 88e30d3..0b5ea01 100644 --- a/Source/BusyRabbit/Private/Core/PW_UserWidget.cpp +++ b/Source/BusyRabbit/Private/Core/PW_UserWidget.cpp @@ -4,6 +4,8 @@ #include "Core/PW_UserWidget.h" #include "Core/UI/PW_UIHud.h" #include "slua.h" +#include "EnhancedInput/Public/EnhancedInputSubsystems.h" +#include "EnhancedInput/Public/EnhancedInputComponent.h" UPW_SimpleWidget::UPW_SimpleWidget():bVisible(true){ bVisible = true; @@ -36,7 +38,6 @@ FLuaWidgetEventHandle UPW_SimpleWidget::BP_BindLuaEvent(const FName& EventName, TMap& FunctionPool = LuaFuncMappings.FindOrAdd(EventName); HandleIndex += 1; FunctionPool.Add(HandleIndex, InLuaFunction.value); - //FunctionPool[HandleIndex] = InLuaFunction.value; Handle.EventName = EventName; Handle.HandleIndex = HandleIndex; return Handle; @@ -65,29 +66,22 @@ void UPW_SimpleWidget::BP_EmitLuaEvent(const FName& EventName, const FLuaBPVar& } } -FReply UPW_SimpleWidget::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent){ - slua::LuaVar SelfTable = GetSelfTable(); - if (SelfTable.isTable()) { - slua::LuaVar LuaCallback = SelfTable.getFromTable(TEXT("LuaMouseButtonDown")); - if (LuaCallback.isFunction()) { - LuaCallback.call(); - } - } - return FReply::Unhandled(); - //return Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent); +void UPW_SimpleWidget::BP_BindLuaEnhancedInput(UInputAction* Action, FLuaBPVar Callback) { + UEnhancedInputComponent* EnhancedInput; + if (!Action) return; + + EnhancedInput = CastChecked(GetOwningPlayer()->InputComponent); + if (!EnhancedInput) return; + + EnhancedInput->BindActionInstanceLambda(Action, ETriggerEvent::Triggered, [Callback](const FInputActionInstance& ActionInstance) { + slua::LuaVar LuaCallback = Callback.value; + if (!LuaCallback.isFunction()) return; + LuaCallback.call(); + }); } -FReply UPW_SimpleWidget::NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent){ - slua::LuaVar SelfTable = GetSelfTable(); - if (SelfTable.isTable()) { - slua::LuaVar LuaCallback = SelfTable.getFromTable(TEXT("LuaMouseButtonUp")); - if (LuaCallback.isFunction()) { - LuaCallback.call(); - } - } - return FReply::Unhandled(); - //return Super::NativeOnMouseButtonUp(InGeometry, InMouseEvent); -} + + void UPW_UserWidget::BP_Close(){ APW_UIHud* Hud = Cast(GetPlayerContext().GetHUD()); @@ -105,12 +99,33 @@ void UPW_UserWidget::FrameWorkSetVisible(bool InVisible){ _RefreshVisible(); } +void UPW_UserWidget::_UpdateInputState(bool bNeedRegister) { + APlayerController* PC; + UEnhancedInputLocalPlayerSubsystem* Subsystem; + + if (!InputMappingContext) return; + + PC = GetOwningPlayer(); + if (!PC) return; + + Subsystem = ULocalPlayer::GetSubsystem(PC->GetLocalPlayer()); + if (!Subsystem) return; + + if (bNeedRegister) { + Subsystem->AddMappingContext(InputMappingContext, 0); + } + else { + Subsystem->RemoveMappingContext(InputMappingContext); + } +} + void UPW_UserWidget::_RefreshVisible(){ - bool FinalVisible = bFrameWorkVisible && bVisible; - if (FinalVisible) { + bool bFinalVisible = bFrameWorkVisible && bVisible; + if (bFinalVisible) { SetVisibility(ESlateVisibility::SelfHitTestInvisible); } else { SetVisibility(ESlateVisibility::Collapsed); } + _UpdateInputState(bFinalVisible); } diff --git a/Source/BusyRabbit/Private/Core/UI/PW_UILayer.cpp b/Source/BusyRabbit/Private/Core/UI/PW_UILayer.cpp index 1c6f84d..250448b 100644 --- a/Source/BusyRabbit/Private/Core/UI/PW_UILayer.cpp +++ b/Source/BusyRabbit/Private/Core/UI/PW_UILayer.cpp @@ -65,6 +65,7 @@ void UPW_UILayer::PopWidget(const UPW_UserWidget* WidgetInst){ } } for (i = 0; i < NeedRemoveWidgets.Num(); ++i) { + NeedRemoveWidgets[i]->FrameWorkSetVisible(false); NeedRemoveWidgets[i]->RemoveFromParent(); } if (NeedShowWidget) { diff --git a/Source/BusyRabbit/Public/Core/PW_UserWidget.h b/Source/BusyRabbit/Public/Core/PW_UserWidget.h index 631dcd2..e3f2f7c 100644 --- a/Source/BusyRabbit/Public/Core/PW_UserWidget.h +++ b/Source/BusyRabbit/Public/Core/PW_UserWidget.h @@ -51,10 +51,8 @@ public: UFUNCTION(BlueprintCallable) void BP_EmitLuaEvent(const FName& EventName, const FLuaBPVar& InLuaArgs); -public: - virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)override; - - virtual FReply NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)override; + UFUNCTION(BlueprintCallable) + void BP_BindLuaEnhancedInput(class UInputAction* Action, FLuaBPVar Callback); public: @@ -73,8 +71,7 @@ protected: // lua相关 * */ UCLASS() -class BUSYRABBIT_API UPW_UserWidget : public UPW_SimpleWidget -{ +class BUSYRABBIT_API UPW_UserWidget : public UPW_SimpleWidget{ GENERATED_BODY() public: UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, DisplayName="是否全局唯一") @@ -84,6 +81,9 @@ public: UPROPERTY(BlueprintReadOnly, EditDefaultsOnly) EWidgetLayoutType LayoutType; + UPROPERTY(EditDefaultsOnly, Category = "Input") + TObjectPtr InputMappingContext; + public: UFUNCTION(BlueprintCallable) void BP_Close(); @@ -95,6 +95,8 @@ public: void FrameWorkSetVisible(bool InVisible); protected: + void _UpdateInputState(bool bNeedRegister); + void _RefreshVisible(); protected: