169 lines
5.6 KiB
C++
169 lines
5.6 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
|
|
#include "InteractionMechanic.h"
|
|
#include "InteractiveTool.h" //EToolShutdownType
|
|
|
|
#include "InteractiveToolActivity.generated.h"
|
|
|
|
class IToolsContextRenderAPI;
|
|
|
|
enum class EToolActivityStartResult
|
|
{
|
|
Running,
|
|
FailedStart,
|
|
|
|
// It's not clear whether we want this option. It's certainly the case that depending
|
|
// on settings, an activity may want to end immediately, or perhaps we may want to
|
|
// put single-action subtools on the same system. But the activity can just end on the
|
|
// next tick, and if we allow a third start option, the tool may need to be aware of
|
|
// it as a possibility, plus we have to decide whether or not NotifyActivitySelfEnded
|
|
// applies... Seems messy to have it, so let's keep it out until we really want it.
|
|
//ImmediatelyCompleted,
|
|
};
|
|
|
|
enum class EToolActivityEndResult
|
|
{
|
|
Completed,
|
|
Cancelled,
|
|
ErrorDuringEnd,
|
|
};
|
|
|
|
|
|
/**
|
|
* A tool activity is a sort of "sub-tool" used to break apart functionality in tools that
|
|
* provide support for different multi-interaction subtasks. It is meant to limit the sprawl
|
|
* of switch statements in the base tool, to allow subtasks to be designed similar to how a
|
|
* tool might be designed, and to ease extendability.
|
|
*
|
|
* An activity has the following expectations:
|
|
* - Setup() is called in host tool setup and Shutdown() is called in host tool Shutdown()
|
|
* - Start() is called to start the activity (such as when user clicks a button).
|
|
* - If the activity returns a result of EStartResult::ActivityRunning on Start(), it will expect
|
|
* Render() and Tick() calls from the host until either (a)- the host calls End() on the activity,
|
|
* or (b)- the activity reaches a stopping point itself and calls NotifyActivitySelfEnded() on the
|
|
* host. The activity should not require Render() and Tick() if it is not running.
|
|
*
|
|
* Compared to a UInteractionMechanic, a tool activity:
|
|
* - Expects that it is the main consumer of input, i.e. takes over the tool. Mechanics, by contrast,
|
|
* are currently often used together with other mechanics, or to support main tool functionality.
|
|
* - Should not require the hosting tool to have specific knowledge about it or be heavily involved.
|
|
* Mechanics, by contrast, currently often require tools to use various mechanic-specific getters/setters
|
|
* during the tool.
|
|
*
|
|
* Passing data back and forth can be done either by letting a tool activity use a specific
|
|
* context object that the tool can prep in the context store, or by requiring the host to
|
|
* implement specific interfaces (that the activity can check for in Setup()).
|
|
*/
|
|
UCLASS(MinimalAPI)
|
|
class UInteractiveToolActivity : public UInteractionMechanic
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
// Note about the below: we didn't really need to repeat Setup(), Tick(), and Render() here
|
|
// since these are staying the same as UInteractionMechanic and get inherited. But it is
|
|
// helpful to have the entire API that we need to implement described in one place
|
|
|
|
virtual ~UInteractiveToolActivity() {}
|
|
|
|
/**
|
|
* Should be called during a tool's Setup(). Does not start the activity.
|
|
*/
|
|
virtual void Setup(UInteractiveTool* ParentToolIn) override
|
|
{
|
|
Super::Setup(ParentToolIn);
|
|
}
|
|
|
|
/**
|
|
* Should be called during a tool's Shutdown()
|
|
*/
|
|
virtual void Shutdown(EToolShutdownType ShutdownType)
|
|
{
|
|
Super::Shutdown();
|
|
}
|
|
|
|
/**
|
|
* Check whether a Start() call will result in a success.
|
|
*/
|
|
virtual bool CanStart() const { return false; }
|
|
|
|
/**
|
|
* Attempt to start the activity.
|
|
*/
|
|
virtual EToolActivityStartResult Start() { return EToolActivityStartResult::FailedStart; }
|
|
|
|
/**
|
|
* Check whether the activity is running (though the tool can just check the result of
|
|
* Start() itself).
|
|
*/
|
|
virtual bool IsRunning() const
|
|
{
|
|
// We could keep a boolean here in the base class and update it in the base class Start() and End()
|
|
// functions so that derived classes don't have to remember to implement this. But it is probably better
|
|
// to have the inconvenience of having to implement IsRunning in the derived class than to force
|
|
// derived classes to remember to call base Start() and End() or risk giving an incorrect result here...
|
|
return ensure(false);
|
|
}
|
|
|
|
/**
|
|
* Similar to a tool, this determines whether the activity prefers an accept/cancel option to be
|
|
* displayed (if true) vs a "complete".
|
|
*/
|
|
virtual bool HasAccept() const { return false; };
|
|
|
|
/**
|
|
* If true, calling End with EToolShutdownType::Accept will result in a valid completion of
|
|
* the activity. It's up to the tool whether to respect this or not, since End() should still
|
|
* end the activity.
|
|
*/
|
|
virtual bool CanAccept() const { return false; };
|
|
|
|
/**
|
|
* Force an end to the activity.
|
|
*/
|
|
virtual EToolActivityEndResult End(EToolShutdownType) { return EToolActivityEndResult::ErrorDuringEnd; };
|
|
|
|
/**
|
|
* If the activity is running, should be called from the tool's OnTick()
|
|
*/
|
|
virtual void Tick(float DeltaTime) override {};
|
|
|
|
/**
|
|
* If the activity is running, should be called from the tool's Render()
|
|
*/
|
|
virtual void Render(IToolsContextRenderAPI* RenderAPI) override {};
|
|
|
|
protected:
|
|
|
|
|
|
private:
|
|
// We don't want to use this overload of Shutdown because an activity may need to know
|
|
// the ShutdownType if it is still running when Shutdown is called (to End properly).
|
|
virtual void Shutdown() override final
|
|
{
|
|
ensure(false);
|
|
Shutdown(EToolShutdownType::Cancel);
|
|
}
|
|
};
|
|
|
|
UINTERFACE(MinimalAPI)
|
|
class UToolActivityHost : public UInterface
|
|
{
|
|
GENERATED_BODY()
|
|
};
|
|
|
|
class IToolActivityHost
|
|
{
|
|
GENERATED_BODY()
|
|
public:
|
|
|
|
/**
|
|
* Notify the tool that the activity has ended.
|
|
*/
|
|
virtual void NotifyActivitySelfEnded(UInteractiveToolActivity* Activity) = 0;
|
|
};
|