/**
* Helper class for flash to interact with non game-specific code (ie. play a sound)
*/
#ifndef __GAMESWF_HELPER__
#define __GAMESWF_HELPER__
#include "RKSingleton.h"
#include "gameswf/gameswf.h" //!< gameswf::Point
#include <RKString.h>
struct RKVector;
struct RKVector2;
struct RKRect;
class RKCamera;
class RKRenderLayer;
namespace gameswf
{
struct FunctionCall;
class CharacterHandle;
class FlashFX;
FlashFX* load(const char* filename, bool background = false);
void unload(FlashFX* swf);
void preserveVisibility(const char* filename);
void pushVisibiliyList();
void popVisibiliyList();
}
class GameSWFHelper : public RKSingleton < GameSWFHelper >
{
GameSWFHelper(const GameSWFHelper&);
GameSWFHelper& operator=(const GameSWFHelper&);
public:
GameSWFHelper();
/// \brief Sets a camera's viewport on a custom RenderLayer. Used for 3D UI elements
/// \param a_hHandle The CharacterHandle who's bounds will be used
/// \param a_pCamera The camera who's viewport will be set
/// \param a_pRenderLayer The custom renderLayer a_pCamera will render on
/// \note Will make the camera orthographic
/// \precondition a_pCamera cannot be controlled by a CameraController - CameraControllers reset camera aspect to the screen aspect every update.
static void SetCameraViewportToCharacterHandle(const RKRect &viewport, RKCamera* a_pCamera, RKRenderLayer* a_pRenderLayer);
/// \brief Set a renderlayer's custom camera to NULL
/// \param a_pRenderLayer The custom renderLayer which we clear the custom camera
static void ClearCustomCamera(RKRenderLayer* a_pRenderLayer);
/// \brief Takes a position in world-space, and returns the position in screen-space of the specified swf
/// \param a_pFX The swf who's size will determine the screen-space coordinates
/// \param a_worldPosition The position in the world to be translated into screen-space
/// \note If you use this to position a CharacterHandle, it will only work if the CharacterHandle has no parent (top level). Nested CharacterHandles will be positioned incorrectly.
static gameswf::Point WorldToSWFCoordinates(const gameswf::FlashFX* a_pFX, const RKVector& a_worldPosition);
/// \brief Checks if the target character handle is valid, logging "Invalid handle" and the given message under the "ui" type if not.
/// \param a_hHandle The handle to check the validity of
/// \param a_sErrorMessage An optional error message to output additional information if the handle is invalid.
/// \return Returns the result of CharacterHandle::IsValid()
static bool IsHandleValidLog(gameswf::CharacterHandle a_hHandle, const char* a_sErrorMessage /* = nullptr*/);
/// \brief Finds a handle in a flash element, and assigns it the given text if valid
/// \param a_sHandleName the name of the character handle to find
/// \param a_sText The text to assign to the handle provided it is valid
/// \param a_pFX The swf in which to find the handle
/// \param a_sErrorMessage The message to output if the handle is invalid. NOTE: Calls IsHandleValidLog internally
/// \return True if the handle is valid and the text was assigned, false if not.
static bool SetHandleText(const char* a_sHandleName, const char* a_sText, gameswf::FlashFX* a_pFX, const char* a_sErrorMessage /*= nullptr*/);
/// \brief Recursively checks parents to see if they are visible. If any are not, returns false
/// \param a_hHandle The handle to check
/// \return True if all ancestors are currently visible, false if any are.
static bool AreAllAncestorsVisible(gameswf::CharacterHandle& a_hHandle);
/// \brief Sets all the children to (in)visible and (dis/en)abled
/// \param a_hHandle The parent handle
/// \param a_bVisible Determines if the visibility to true or false
static void SetAllChildrenVisible(gameswf::CharacterHandle& a_hHandle, bool a_bVisible);
/// \brief Reorders a swf with a relative layer distance to another given swf
/// \param a_pSWFBeingReordered The SWF that will have its order changed
/// \param a_pRelativeSWF The SWF that a_pSWFBeingReordered will be moved in relation to
/// \param a_order The layer distance from a_pRelativeSWF that a_pSWFBeingReordered will be moved to. A positive number will move it on top.
static void SetRelativeSWFOrder(gameswf::FlashFX* a_pSWFBeingReordered, gameswf::FlashFX* a_pRelativeSWF, int a_order);
/// \brief Checks if the given CharacterHandle is on a frame with the given label name
/// \param a_hHandle The CharacterHandle to check
/// \param a_sLabelName The label name to check
/// \return True if the frame the CharacterHandle is on has a label of the given name.
static bool IsOnFrame(gameswf::CharacterHandle& a_hHandle, const char* a_sLabelName);
/// \brief Recurses up the hierarchy to find the world position of a CharacterHandle within the space of its swf
/// \param a_hHandle The CharacterHandle to find the position of
/// \note This value differs from CharacterHandle::getWorldPosition - getWorldPosition is affected by additional scale factors
/// \return The world position relative to the swf's stage
static gameswf::Point GetHandleWorldPosition(gameswf::CharacterHandle& a_hHandle);
/// \brief Recurse to the ends of all lower hierarchies, printing the full path of the end nodes
/// \note Requires RKLog info to be output, with filterType "ui"
static void PrintLeafNames(gameswf::CharacterHandle& a_hHandle);
/// \brief Sets a BNE.Text/BNE.TextButton's localization ID in ActionScript
/// \param a_hHandle The handle of type BNE.Text or BNE.ButtonText to set the localization ID of
/// \param a_sLocalizationID The localization ID of the target string
/// \note This will not work with paramaterized strings
static void SetLocalizationID(gameswf::CharacterHandle& a_hHandle, const char* a_sLocalizationID);
/// \brief Unregister BNE.Text and BNE.TextButton from automatically updating with the StringPack.
/// \note This behaviour is only desired when setting localization from code.
static void ClearAutomaticLocalization(gameswf::CharacterHandle& a_hHandle);
/// \brief Get the HTML text for a string with a given font.
/// \param a_sFontName The font name.
/// \param a_sText The original text.
static RKString GetHtmlText(const char* a_sFontName, const char* a_sText);
/// \brief Sets a button to be enabled at the BNE.Button/BNE.TextButton level - this is an independent disable from the gameswf::CharacterHandle
/// \param a_hButton The button to set enabled/disabled
/// \param a_bIsEnabled If the button is to be enabled or disabled
static void SetButtonEnabled(gameswf::CharacterHandle& a_hButton, bool a_bIsEnabled);
/// \brief Compares the current frame the element is on, and determines if it falls between the given animation label names
/// \param a_hElement The MovieClip being tested if it falls between animation labels
/// \param a_sStartLabelName The name of the label to start checking from (inclusive)
/// \param a_sEndLabelName The name of the label to finish checking from (exclusive/inclusive dependant on next member)
/// \param a_bInclusiveOfEndLabel A flag to determine if the end label name should be factored if it falls between animations. Inclusive is likely used if the end label is "animName_end" - a specific identifier that the animation has ended, while exclusive would be used if it's the start of the next animation.
/// \return True if the MovieClip is currently on a frame between the two labels.
static bool IsBetweenAnimations(gameswf::CharacterHandle& a_hElement, const char* a_sStartLabelName, const char* a_sEndLabelName, bool a_bInclusiveOfEndLabel = false);
private:
/// \brief Plays a sound through Soundpack
static void PlaySound(const gameswf::FunctionCall& a_fn);
/// \brief Informs SCRIPT of the button that was pressed, the function name, and the parameter
static void ButtonPressedToScript(const gameswf::FunctionCall& a_fn);
/// \brief Gets the device width
static void GetDeviceWidth(const gameswf::FunctionCall& a_fn);
/// \brief Gets the device height
static void GetDeviceHeight(const gameswf::FunctionCall& a_fn);
/// \brief Gets the device aspect ratio
static void GetDeviceAspect(const gameswf::FunctionCall& a_fn);
/// \brief Gets if on frame with the specified label
static void IsOnFrameWithLabel(const gameswf::FunctionCall& a_fn);
};
/// \brief Static functions to get around passing in int 0 values to/from flash. Flash discards a single argument of int 0 (assumed it as no argument), where it is used heavily when referencing button/callback indices, etc.
namespace ASIntArg
{
static const int From(int a_ASInt) { return a_ASInt - 1; }
static const int To(int a_rawIndex) { return a_rawIndex + 1; }
}
#endif // __GAMESWF_HELPER__