#pragma once #pragma region CPL License /* Nuclex Unreal Module Copyright (C) 2014-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #include #include #include #include "DialogInputSource.h" #include "DialogPlayerController.generated.h" // --------------------------------------------------------------------------------------------- // /// Player controller for interacting with a UIs using the mouse, keyboard or a VR headset UCLASS() class NUCLEX_API ADialogPlayerController : public APlayerController, public IDialogInputSource { GENERATED_BODY() /// Initializes a new player controller for UI interaction public: ADialogPlayerController(); // // ADialogPlayerController implementation // /// Binds the dialog controls to the default input actions if set up for the project public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="UI") void BindToDefaultInputActions(); virtual void BindToDefaultInputActions_Implementation(); /// Accepts the currently active selection when the player presses the accept key public: UFUNCTION(BlueprintCallable, Category="UI") void InjectAccept(); /// Cancels the currently active dialog when the player presses the cancel key public: UFUNCTION(BlueprintCallable, Category="UI") void InjectCancel(); /// Selects the element above the currently selected one when the player presses up public: UFUNCTION(BlueprintCallable, Category="UI") void InjectUp(); /// Selects the element above the currently selected one when the player presses down public: UFUNCTION(BlueprintCallable, Category="UI") void InjectDown(); /// Selects the element above the currently selected one when the player presses left public: UFUNCTION(BlueprintCallable, Category="UI") void InjectLeft(); /// Selects the element above the currently selected one when the player presses right public: UFUNCTION(BlueprintCallable, Category="UI") void InjectRight(); // // IDialogInputSource implementation // /// Retrieves the dialog to which player input is currently being sent /// @returns The dialog to which input is currently being sent public: virtual const TScriptInterface< IButtonControllableDialog > GetActiveDialog_Implementation() override { return this->ActiveDialog; }; /// Selects the active dialog, enables UI input and shows the mouse cursor (unless VR) /// @param targetDialog Dialog to which all UI input will be sent /// @param enableMouse Whether the mouse cursor will be shown (only if VR is disabled) public: virtual void BeginDialogInput_Implementation( const TScriptInterface &targetDialog ) override; /// Disables UI input and hides the mouse cursor /// @param disableMouse Whether the mouse cursor should be disabled public: virtual void EndDialogInput_Implementation() override; // // Internal implementation // /// Binds gameplay functions to the input actions defined in the project protected: virtual void SetupInputComponent() override; /// Called when the game ends or when the actor is deleted from the running game /// @param endPlayReason Reason why the component is not in the game anymore protected: virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override; /// Called when the player controller possesses a pawn /// @param pawn Pawn that is being posssessed protected: virtual void OnPossess(APawn *pawn) override; /// Called when the player controller is ejected from its possessed pawn protected: virtual void OnUnPossess() override; /// Sends a mouse down event to the UI on a touch or mouse button press private: void pointerPressed(); /// Sends a mouse up event to the UI on a touch or mouse button release private: void pointerReleased(); /// Looks the pawn's widget interaction component if the pawn has changed private: void updatePawnWidgetInteractionComponent(); /// Whether input will be sent to the currently active dialog, if any /// @remarks /// It's safe to leave this on all the time. It will only take effect when /// a dialog is assigned to the player controller. Setting it to off will /// prevent any input from being routed to the active dialog, even if /// the BeginDialogInput() method is called. public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="UI") bool EnableDialogInput; /// Whether the mouse cursor will automatically be shown when a dialog is active /// @remarks /// If this property is set, the mouse cursor will be toggled visible whenever /// dialog input is enabled and a dialog is assigned. If this property is /// not set, the player controller will leave the mouse as it is at all times. /// If you have a virtual mouse cursor (VR controllers or virtual crosshair /// mouse for in-game computers like in Doom3) it makes sense to disable this. public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="UI") bool AutoShowMouse; /// Whether mouse input will be forwarded to the pawn's widget interaction component /// @remarks /// This is a conveniency feature. If enabled, whenever this player controller /// possesses a pawn, it will check for widget interaction components in the pawn. /// If there's exactly one such component on the pawn, mouse input will be forwarded /// to the component, relieving you of the effort of implementing it in your pawn. public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="UI") bool FeedPawnWidgetInteraction; /// Dialog input is currently being sent to (can be null if no dialog is active) public: UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Transient, Category="UI") TScriptInterface ActiveDialog; /// Widget interaction component in the currently active pawn, if any private: UPROPERTY(Transient) UWidgetInteractionComponent *widgetInteraction; /// Dialog input is currently being sent to (can be null if no dialog is active) private: UPROPERTY(Transient) APawn *checkedPawn; /// Whether the left mouse button is currently down /// @remarks /// Used to allow clean state transfers when the widget interaction component /// changes whiel the mouse button is being held private: bool isLeftMouseButtonPressed; /// Whether this instance's inject methods have been bound to their default input actions private: bool defaultInputActionsBound; /// Cached key for the left mouse button in Unreal's input system private: const FKey leftMouseButtonKey; }; // --------------------------------------------------------------------------------------------- //