#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 "VisualNovel/VisualNovelParagraphBox.h" #include "VisualNovel/ParagraphInputSource.h" #include "VisualNovel/DialogueChoice.h" #include "VisualNovelStoryController.generated.h" // --------------------------------------------------------------------------------------------- // struct TrackedParagraphBoxState; // --------------------------------------------------------------------------------------------- // /// Base class for a controller that plays back the story in a visual novel UCLASS() class NUCLEX_API AVisualNovelStoryController : public AActor { GENERATED_BODY() /// Initializes a new story controller for visual novels public: AVisualNovelStoryController(); // // AVisualNovelStoryController implementation // /// Displays narration or dialogue to the player in a visual novel box /// @param worldContextObject This pointer of the caller, stored for latent call /// @param latentInfo Stores the state of the stack and node graph to resume the call /// @param anchor Scene node from which the dialog will inherit its transform /// @param speaker Text that will be displayed in the speaker / narrator location /// @param paragraph Paragraph that will be displayed to the player /// @param keepOpen Whether the visual novel box should remain on screen public: UFUNCTION( BlueprintCallable, Category="Visual Novel", meta=( Latent, LatentInfo="latentInfo", HidePin="worldContextObject", DefaultToSelf="worldContextObject" ) ) void ShowParagraph( UObject *worldContextObject, struct FLatentActionInfo latentInfo, AActor *anchor, const FString &speaker, const FString ¶graph, bool keepOpen = false ); /// Displays narration like @see ShowParagraph, but requires the player to make a choice /// @param selectedChoice Choice selected by the player /// @param worldContextObject This pointer of the caller, stored for latent call /// @param latentInfo Stores the state of the stack and node graph to resume the call /// @param anchor Scene node from which the dialog will inherit its transform /// @param speaker Text that will be displayed in the speaker / narrator location /// @param paragraph Paragraph that will be displayed to the player /// @param choices Choices available to the player /// @param keepOpen Whether the visual novel box should remain on screen public: UFUNCTION( BlueprintCallable, Category="Visual Novel", meta=( Latent, LatentInfo="latentInfo", HidePin="worldContextObject", DefaultToSelf="worldContextObject", ExpandEnumAsExecs="selectedChoice" ) ) void RequireChoice( EDialogueChoice &selectedChoice, UObject *worldContextObject, struct FLatentActionInfo latentInfo, AActor *anchor, const FString &speaker, const FString ¶graph, const TArray &choices, bool keepOpen = true ); /// Fades the screen out /// @param worldContextObject This pointer of the caller, stored for latent call /// @param latentInfo Stores the state of the stack and node graph to resume the call /// @param fadeTimeInSeconds How long it will take until the screen is fully faded out public: UFUNCTION( BlueprintCallable, Category="Visual Novel", meta=( Latent, LatentInfo="latentInfo", HidePin="worldContextObject", DefaultToSelf="worldContextObject" ) ) void FadeOut( UObject *worldContextObject, struct FLatentActionInfo latentInfo, float fadeTimeInSeconds = 2.0 ); /// Fades the screen in /// @param worldContextObject This pointer of the caller, stored for latent call /// @param latentInfo Stores the state of the stack and node graph to resume the call /// @param fadeTimeInSeconds How long it will take until the screen is fully faded in public: UFUNCTION( BlueprintCallable, Category="Visual Novel", meta=( Latent, LatentInfo="latentInfo", HidePin="worldContextObject", DefaultToSelf="worldContextObject" ) ) void FadeIn( UObject *worldContextObject, struct FLatentActionInfo latentInfo, float fadeTimeInSeconds = 2.0 ); /// Instantly moves the camera to the anchor transform /// @param worldContextObject This pointer of the caller, stored for latent call /// @param latentInfo Stores the state of the stack and node graph to resume the call /// @param anchor Transform the camera will assume public: UFUNCTION(BlueprintCallable, Category="Visual Novel") void BlinkCamera(AActor *anchor); /// Flies the camera from its current anchor to a new anchor transform /// @param worldContextObject This pointer of the caller, stored for latent call /// @param latentInfo Stores the state of the stack and node graph to resume the call /// @param anchor Transform the camera will fly to /// @param flightTimeInSeconds Time within which the camera will reach the new anchor /// @param easingFunction Easing function that will be used to accelerate and stop public: UFUNCTION( BlueprintCallable, Category="Visual Novel", meta=( Latent, LatentInfo="latentInfo", HidePin="worldContextObject", DefaultToSelf="worldContextObject" ) ) void FlyCamera( UObject *worldContextObject, struct FLatentActionInfo latentInfo, AActor *anchor, float flightTimeInSeconds, TEnumAsByte easingFunction ); /// Selects the story controller's pawn as the active view target (player camera) public: UFUNCTION(BlueprintCallable, Category="Visual Novel") void SetPawnAsViewTarget(); /// Cancels the currently displayed paragraph box, if any public: UFUNCTION(BlueprintCallable, Category="Visual Novel") void CancelAllParagraphs(); /// Called when the game starts or when spawned protected: virtual void BeginPlay() 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 once per visual frame to advance the simulation /// @param deltaSeconds Time that has elapsed since the last call to Tick() protected: virtual void Tick(float deltaSeconds) override; /// Looks up other objects and performs all required initialization if not done yet protected: void InitializeIfNeeded(); /// Ensures the callbacks are subscribes to the currently assigned paragraph box protected: void EnsureParagraphBoxSubscription(); /// Removes all callback subscriptions from the active paragraph box protected: void UnsubscribeFromParagraphBox(); /// Finishes a running latent action when the player makes a choice in the paragraph box /// @param choiceIndex Index of the choice the player has made private: UFUNCTION() void choiceAccepted(int32 choiceIndex); /// Called when the tracked paragraph box' animation state changed /// @param animationState New animation state of the paragraph box private: UFUNCTION() void animationStateChanged(EParagraphBoxAnimationState animationState); /// Pawn through which the player observes and controls the story public: UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category="Visual Novel") APawn *Pawn; /// UI used to display story paragraphs and multiple-choice questions public: UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category="Visual Novel") AActor *ParagraphBox; // should be: TScriptInterface; /// Pawn through which the player observes and controls the story private: UPROPERTY(Transient) APlayerCameraManager *cameraManager; /// Player controller (as a paragraph input source) the paragraph box is controlled by private: UPROPERTY(Transient) TScriptInterface playerInputSource; /// Paragraph box to whose callbacks we are currently subscribed private: UPROPERTY(Transient) TScriptInterface subscribedParagraphBox; /// Subscribed paragraph box under the IButtonControllableParagraph interface private: UPROPERTY(Transient) TScriptInterface subscribedControllable; /// Whether this component has been initialized already private: bool initialized; /// Current state of the paragraph box private: TSharedPtr currentState; }; // --------------------------------------------------------------------------------------------- //