Files
alexei lebedev 2815323fbc [mutable] Moved the Mutable plugin out of Experimental status into Beta.
#jira UE-223488
#rb jordi.rovira
#tests Editor
#rnx

#virtualized

[CL 36035608 by alexei lebedev in ue5-main branch]
2024-09-05 07:16:19 -04:00

202 lines
4.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MuT/ASTOpImagePatch.h"
#include "Containers/Map.h"
#include "MuR/ModelPrivate.h"
#include "MuR/RefCounted.h"
#include "MuR/Types.h"
namespace mu
{
ASTOpImagePatch::ASTOpImagePatch()
: base(this)
, patch(this)
{
}
//-------------------------------------------------------------------------------------------------
ASTOpImagePatch::~ASTOpImagePatch()
{
// Explicit call needed to avoid recursive destruction
ASTOp::RemoveChildren();
}
//-------------------------------------------------------------------------------------------------
bool ASTOpImagePatch::IsEqual(const ASTOp& otherUntyped) const
{
if (otherUntyped.GetOpType()==GetOpType())
{
const ASTOpImagePatch* other = static_cast<const ASTOpImagePatch*>(&otherUntyped);
return base == other->base &&
patch == other->patch &&
location == other->location;
}
return false;
}
//-------------------------------------------------------------------------------------------------
uint64 ASTOpImagePatch::Hash() const
{
uint64 res = std::hash<OP_TYPE>()(OP_TYPE::IM_PATCH);
hash_combine(res, base.child().get());
hash_combine(res, patch.child().get());
return res;
}
//-------------------------------------------------------------------------------------------------
mu::Ptr<ASTOp> ASTOpImagePatch::Clone(MapChildFuncRef mapChild) const
{
Ptr<ASTOpImagePatch> n = new ASTOpImagePatch();
n->base = mapChild(base.child());
n->patch = mapChild(patch.child());
n->location = location;
return n;
}
//-------------------------------------------------------------------------------------------------
void ASTOpImagePatch::ForEachChild(const TFunctionRef<void(ASTChild&)> f)
{
f(base);
f(patch);
}
//-------------------------------------------------------------------------------------------------
void ASTOpImagePatch::Link(FProgram& program, FLinkerOptions*)
{
// Already linked?
if (!linkedAddress)
{
OP::ImagePatchArgs args;
memset(&args, 0, sizeof(args));
if (base) args.base = base->linkedAddress;
if (patch) args.patch = patch->linkedAddress;
args.minX = location[0];
args.minY = location[1];
linkedAddress = (OP::ADDRESS)program.m_opAddress.Num();
program.m_opAddress.Add((uint32_t)program.m_byteCode.Num());
AppendCode(program.m_byteCode, OP_TYPE::IM_PATCH);
AppendCode(program.m_byteCode, args);
}
}
//-------------------------------------------------------------------------------------------------
FImageDesc ASTOpImagePatch::GetImageDesc(bool returnBestOption, FGetImageDescContext* context) const
{
FImageDesc res;
// Local context in case it is necessary
FGetImageDescContext localContext;
if (!context)
{
context = &localContext;
}
else
{
// Cached result?
FImageDesc* PtrValue = context->m_results.Find(this);
if (PtrValue)
{
return *PtrValue;
}
}
// Actual work
if (base)
{
res = base->GetImageDesc(returnBestOption, context);
}
// Cache the result
if (context)
{
context->m_results.Add(this, res);
}
return res;
}
//-------------------------------------------------------------------------------------------------
mu::Ptr<ImageSizeExpression> ASTOpImagePatch::GetImageSizeExpression() const
{
if (base)
{
return base->GetImageSizeExpression();
}
return nullptr;
}
//-------------------------------------------------------------------------------------------------
void ASTOpImagePatch::GetLayoutBlockSize(int* pBlockX, int* pBlockY)
{
// We didn't find any layout yet.
*pBlockX = 0;
*pBlockY = 0;
// Try the source
if (base)
{
base->GetLayoutBlockSize( pBlockX, pBlockY );
}
if (patch && *pBlockX == 0 && *pBlockY == 0)
{
patch->GetLayoutBlockSize(pBlockX, pBlockY);
}
}
FSourceDataDescriptor ASTOpImagePatch::GetSourceDataDescriptor(FGetSourceDataDescriptorContext* Context) const
{
// Cache management
TUniquePtr<FGetSourceDataDescriptorContext> LocalContext;
if (!Context)
{
LocalContext.Reset(new FGetSourceDataDescriptorContext);
Context = LocalContext.Get();
}
FSourceDataDescriptor* Found = Context->Cache.Find(this);
if (Found)
{
return *Found;
}
// Not cached: calculate
FSourceDataDescriptor Result;
if (base)
{
FSourceDataDescriptor SourceDesc = base->GetSourceDataDescriptor(Context);
Result.CombineWith(SourceDesc);
}
if (patch)
{
FSourceDataDescriptor SourceDesc = patch->GetSourceDataDescriptor(Context);
Result.CombineWith(SourceDesc);
}
Context->Cache.Add(this, Result);
return Result;
}
}