Files
UnrealEngine/Engine/Source/Editor/MovieSceneTools/Private/FCPXML/FCPXMLNode.h
2025-05-18 13:04:45 +08:00

418 lines
14 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Containers/Array.h"
#include "Containers/UnrealString.h"
#include "HAL/Platform.h"
#include "Templates/SharedPointer.h"
class FXmlNode;
/** The FFCPXMLNode pure virtual base class represents a node in the
FCP 7 XML tree. There are derived classes for each node type, including
a "Basic" node as default node type.
NODE VISITOR CLASS
The FFCPXMLNode includes support for a NodeVisitor class to easily traverse
and modify the node structure. The FFCPXMLNode method Accepts() is called
to accept NodeVisitor objects. This implements the visitor pattern in order
to allow double dispatch based on both the type of the node and the type
of the operation (e.g. Import, Export, File Setup).
INHERITANCE
Node element inheritance is supported, when specified, by searching for
inherited elements by walking up the node's parents, looking for peer elements
with matching tags.
REFERENCE IDS
Certain node types support reference id attributes. When an id attribute
is present, the node is added the reference id map in the FFCPXMLFile
class. If the reference id already exists in the map, the current node
inherits elements from the reference node if they are not defined in
the current node.
*/
class FFCPXMLFile;
class FFCPXMLNodeVisitor;
enum class ENodeInherit : uint8
{
NoInherit,
CheckInherit
};
enum class ENodeReference : uint8
{
NoReferences,
CheckReferences
};
/** FCP XML attribute class. */
class FFCPXMLAttribute
{
public:
/** Default constructor */
FFCPXMLAttribute(const FString& InTag, const FString& InValue) : Tag(InTag), Value(InValue) {}
/** Gets the tag of the attribute */
const FString& GetTag() const;
/** Gets the value of the attribute */
const FString& GetValue() const;
/** Gets the value of the node */
bool GetValue(FString& OutValue) const;
/** Gets the value of the node */
bool GetValue(float& OutValue) const;
/** Gets the value of the node */
bool GetValue(int32& OutValue) const;
/** Gets the value of the node */
bool GetValue(bool& OutValue) const;
private:
/** The tag string */
FString Tag;
/** The value string */
FString Value;
};
/** FCP XML node class. This supports traversal by a visitor object which may modify the node tree's structure. */
class FFCPXMLNode : public TSharedFromThis<FFCPXMLNode>
{
friend class FFCPXMLNodeVisitor;
public:
/** Constructor */
FFCPXMLNode(const FString InTag, TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
/** Destructor */
virtual ~FFCPXMLNode() {}
private:
/** No default constructor allowed */
FFCPXMLNode() {}
/** No copy constructor allowed */
FFCPXMLNode(const FFCPXMLNode& rhs) {}
public:
/** Factory method to create new FCPXMLNode based on xml tag. */
static TSharedRef<FFCPXMLNode> CreateFFCPXMLNode(FString tag, TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
/** Recursive copy of data from XmlNode to this node */
void CopyFrom(FXmlNode* InNode);
/** Write data from this node into an Xml string */
void GetXmlBuffer(const FString& Indent, FString& Output) const;
/**
* Calls the appropriate visit method for a given visitor node.
* @param NodeVisitor Visitor object
*/
bool Accept(FFCPXMLNodeVisitor& NodeVisitor);
/**
* Visits the children of this node.
* @param NodeVisitor Visitor object
* @param VisitRefIdChildren When true, node will traverse refId node elements if they do not exist in current node
*/
bool VisitChildren(FFCPXMLNodeVisitor& NodeVisitor, bool VisitRefNodeChildren = false);
public:
/** Gets the tag of the node */
const FString& GetTag() const;
/** Gets the value of the node */
const FString& GetContent() const;
/** Gets the value of the node */
bool GetContent(FString& OutValue) const;
/** Gets the value of the node */
bool GetContent(float& OutValue) const;
/** Gets the value of the node */
bool GetContent(int32& OutValue) const;
/** Gets the value of the node */
bool GetContent(bool& OutValue) const;
/** Sets the new value of the node */
void SetContent(const FString& InContent);
/** Sets the new value of the node */
void SetContent(float InContent);
/** Sets the new value of the node */
void SetContent(int32 InContent);
/** Sets the new value of the node */
void SetContent(bool InContent);
/** Sets the new value of the node */
FORCEINLINE void SetContent(const TCHAR* InContent)
{
// Force an FString conversion here, otherwise it calls the bool overload
SetContent(FString(InContent));
}
/** Gets a list of child nodes */
const TArray<TSharedRef<FFCPXMLNode>>& GetChildNodes() const;
/** Gets number of child nodes */
uint32 GetChildCount() { return Children.Num(); }
/** Appends input node to children nodes */
void AppendChildNode(TSharedRef<FFCPXMLNode> InNode);
/** Creates a child node with the given tag and appends node to children. */
TSharedRef<FFCPXMLNode> CreateChildNode(const FString& InTag);
/** Retrieves child content, returning false if not found. */
template <typename T>
bool GetChildValue(const FString& InElement, T& OutValue, ENodeInherit CheckInherit = ENodeInherit::CheckInherit, ENodeReference CheckRefIds = ENodeReference::CheckReferences) const;
/** Retrieves child content, returning false if not found. */
template <typename T>
bool GetChildSubValue(const FString& InElement, const FString& InSubElement, T& OutValue, ENodeInherit CheckInherit = ENodeInherit::CheckInherit, ENodeReference CheckRefIds = ENodeReference::CheckReferences) const;
/** Retrieves child node, checking references and inheritance if specified. */
TSharedPtr<FFCPXMLNode> GetChildNode(const FString& InElement, ENodeInherit CheckInherit = ENodeInherit::CheckInherit, ENodeReference CheckRefIds = ENodeReference::CheckReferences) const;
/** Retrieves child node, checking references and inheritance if specified. */
TSharedPtr<FFCPXMLNode> GetChildNode(const FString& InElement, const FString& InSubElement, ENodeInherit CheckInherit = ENodeInherit::CheckInherit, ENodeReference CheckRefIds = ENodeReference::CheckReferences) const;
/** Adds an attribute */
void AddAttribute(const FString &InTag, const FString &InValue);
/**
* Gets all of the attributes in this node
* @return List of attributes in this node
*/
const TArray<FFCPXMLAttribute>& GetAttributes() const;
/** Gets an attribute that corresponds with the passed-in tag */
bool GetAttribute(const FString& InTag, FFCPXMLAttribute& OutAttr) const;
/** Retrieves attribute value, returning false if not found. */
template <typename T>
bool GetAttributeValue(const FString& InTag, T& OutValue) const;
public:
/** Adds reference to file's reference map if it does not already exist */
bool AddReference(const FString& InElement, const FString &InId, TSharedPtr<FFCPXMLNode> InNode);
/** Gets reference from file's reference map */
TSharedPtr<FFCPXMLNode> GetReference(const FString &InElement, const FString &InId) const;
protected:
/** The list of children nodes */
TArray<TSharedRef<FFCPXMLNode>> Children;
/** Attributes of this node */
TArray<FFCPXMLAttribute> Attributes;
/** Weak pointer to parent node */
TWeakPtr<FFCPXMLNode> Parent;
/** Weak pointer to file object */
TWeakPtr<FFCPXMLFile> ContainingFile;
/** Tag of the node */
FString Tag;
/** Content of the node */
FString Content;
private:
/** Retrieves child node without checking references and inheritance. */
TSharedPtr<FFCPXMLNode> GetChildNodeOnly(const FString& InElement) const;
/** Retrieves child node without checking references and inheritance. */
TSharedPtr<FFCPXMLNode> GetChildNodeOnly(const FString& InElement, const FString& InSubElement) const;
/** Retrieves child node from a reference, if it exists. */
TSharedPtr<FFCPXMLNode> GetChildNodeReference(const FString& InElement) const;
/** Retrieves child node from a reference, if it exists. */
TSharedPtr<FFCPXMLNode> GetChildNodeReference(const FString& InElement, const FString& InSubElement) const;
/** Retrieves child node via inheritance, if it exists. */
TSharedPtr<FFCPXMLNode> GetChildNodeInherit(const FString& InElement) const;
/** Retrieves child node via inheritance, if it exists. */
TSharedPtr<FFCPXMLNode> GetChildNodeInherit(const FString& InElement, const FString& InSubElement) const;
/** Retrieves corresponding reference node, if it exists. */
TSharedPtr<FFCPXMLNode> GetReferenceNode() const;
/** Pure virtual method that accepts a visitor to visit this node */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) = 0;
};
/** Retrieves child value, returning false if not found. */
template <typename T>
bool FFCPXMLNode::GetChildValue(const FString& InElement, T& OutValue, ENodeInherit CheckInherit, ENodeReference CheckRefIds) const
{
TSharedPtr<FFCPXMLNode> Node = GetChildNode(InElement, CheckInherit, CheckRefIds);
if (Node.IsValid())
{
return Node->GetContent(OutValue);
}
return false;
}
/** Retrieves child value, returning false if not found. */
template <typename T>
bool FFCPXMLNode::GetChildSubValue(const FString& InElement, const FString& InSubElement, T& OutValue, ENodeInherit CheckInherit, ENodeReference CheckRefIds) const
{
TSharedPtr<FFCPXMLNode> Node = GetChildNode(InElement, InSubElement, CheckInherit, CheckRefIds);
if (Node.IsValid())
{
return Node->GetContent(OutValue);
}
return false;
}
template <typename T>
bool FFCPXMLNode::GetAttributeValue(const FString& InTag, T& OutValue) const
{
for (const FFCPXMLAttribute& Attr : Attributes)
{
if (Attr.GetTag() == InTag)
{
return Attr.GetValue(OutValue);
}
}
return false;
}
/** FCP XML Node class for any node type */
class FFCPXMLBasicNode : public FFCPXMLNode
{
public:
/** Constructor */
FFCPXMLBasicNode(FString InTag, TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
private:
/** Accepts a node visitor object */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) override final;
};
/** FCP XML Node class for the xmeml node which is the root of every XML file */
class FFCPXMLXmemlNode : public FFCPXMLNode
{
public:
/** Constructor */
FFCPXMLXmemlNode(TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
private:
/** Accepts a node visitor object */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) override final;
};
/** FCP XML Node class for sequence nodes */
class FFCPXMLSequenceNode : public FFCPXMLNode
{
public:
/** Constructor */
FFCPXMLSequenceNode(TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
private:
/** Accepts a node visitor object */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) override final;
};
/** FCP XML Node class for video nodes */
class FFCPXMLVideoNode : public FFCPXMLNode
{
public:
/** Constructor */
FFCPXMLVideoNode(TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
private:
/** Accepts a node visitor object */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) override final;
};
/** FCP XML Node class for audio nodes */
class FFCPXMLAudioNode : public FFCPXMLNode
{
public:
/** Constructor */
FFCPXMLAudioNode(TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
private:
/** Accepts a node visitor object */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) override final;
};
/** FCP XML Node class for track nodes */
class FFCPXMLTrackNode : public FFCPXMLNode
{
public:
/** Constructor */
FFCPXMLTrackNode(TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
private:
/** Accepts a node visitor object */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) override final;
};
/** FCP XML Node class for clip nodes */
class FFCPXMLClipNode : public FFCPXMLNode
{
public:
/** Constructor */
FFCPXMLClipNode(TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
private:
/** Accepts a node visitor object */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) override final;
};
/** FCP XML Node class for clipitem nodes */
class FFCPXMLClipItemNode : public FFCPXMLNode
{
public:
/** Constructor */
FFCPXMLClipItemNode(TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
private:
/** Accepts a node visitor object */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) override final;
};
/** FCP XML Node class for file nodes */
class FFCPXMLFileNode : public FFCPXMLNode
{
public:
/** Constructor */
FFCPXMLFileNode(TSharedPtr<FFCPXMLNode> InParent, TSharedPtr<FFCPXMLFile> InFile);
private:
/** Accepts a node visitor object */
virtual bool DoAccept(FFCPXMLNodeVisitor& NodeVisitor) override final;
};
/**
* FCP XML node visitor abstract base class. This must contain a method
* for every node type that will be visiting the object. These inherited
* visitors can then be used to traverse the FCP XML node structure.
*/
class FFCPXMLNodeVisitor
{
public:
/** Constructor */
FFCPXMLNodeVisitor() {};
/** Destructor */
virtual ~FFCPXMLNodeVisitor() {};
public:
/** Visit anonymous node. */
virtual bool VisitNode(TSharedRef<FFCPXMLBasicNode> Node) = 0;
/** Visit xmeml node. */
virtual bool VisitNode(TSharedRef<FFCPXMLXmemlNode> Node) = 0;
/** Visit sequence node. */
virtual bool VisitNode(TSharedRef<FFCPXMLSequenceNode> Node) = 0;
/** Visit video node. */
virtual bool VisitNode(TSharedRef<FFCPXMLVideoNode> Node) = 0;
/** Visit audio node. */
virtual bool VisitNode(TSharedRef<FFCPXMLAudioNode> Node) = 0;
/** Visit track node. */
virtual bool VisitNode(TSharedRef<FFCPXMLTrackNode> Node) = 0;
/** Visit clip node. */
virtual bool VisitNode(TSharedRef<FFCPXMLClipNode> Node) = 0;
/** Visit clip item node. */
virtual bool VisitNode(TSharedRef<FFCPXMLClipItemNode> Node) = 0;
/** Visit file node. */
virtual bool VisitNode(TSharedRef<FFCPXMLFileNode> Node) = 0;
};