Files
XCEngine/engine/src/Scripting/Mono/MonoScriptRuntime.cpp

9061 lines
337 KiB
C++

#include "Scripting/Mono/MonoScriptRuntime.h"
#include "Components/CameraComponent.h"
#include "Components/GameObject.h"
#include "Components/LightComponent.h"
#include "Components/MeshFilterComponent.h"
#include "Components/MeshRendererComponent.h"
#include "Components/RigidbodyComponent.h"
#include "Components/TransformComponent.h"
#include "Debug/Logger.h"
#include "Input/InputManager.h"
#include "Physics/PhysicsWorld.h"
#include "Rendering/Caches/DirectionalShadowSurfaceCache.h"
#include "Rendering/Execution/CameraFramePlan.h"
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
#include "Rendering/Execution/CameraFrameRenderGraphFrameData.h"
#include "Rendering/Execution/Internal/CameraFrameGraph/SurfaceUtils.h"
#include "Rendering/Graph/RenderGraph.h"
#include "Rendering/Graph/RenderGraphRecordingContext.h"
#include "Rendering/GraphicsSettingsState.h"
#include "Rendering/Internal/RenderPipelineFactory.h"
#include "Rendering/Passes/BuiltinFinalColorPass.h"
#include "Rendering/Passes/BuiltinVectorFullscreenPass.h"
#include "Rendering/Planning/FullscreenPassDesc.h"
#include "Rendering/Planning/SceneRenderRequestPlanner.h"
#include "Rendering/Pipelines/NativeSceneRecorder.h"
#include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h"
#include "Rendering/RenderPassGraphContract.h"
#include "Rendering/RenderPipeline.h"
#include "Rendering/RenderPipelineAsset.h"
#include "Rendering/RenderPipelineStageGraphContract.h"
#include "Resources/BuiltinResources.h"
#include "Core/Asset/ResourceManager.h"
#include "Scene/Scene.h"
#include "Scripting/ScriptComponent.h"
#include "Scripting/ScriptEngine.h"
#include <mono/jit/jit.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/attrdefs.h>
#include <mono/metadata/blob.h>
#include <mono/metadata/class.h>
#include <mono/metadata/image.h>
#include <mono/metadata/loader.h>
#include <mono/metadata/metadata.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/object.h>
#include <mono/metadata/reflection.h>
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <fstream>
#include <limits>
#include <unordered_set>
#include <utility>
namespace XCEngine {
namespace Scripting {
namespace {
constexpr const char* kManagedRenderingNamespace = "XCEngine.Rendering";
struct MonoRootState {
MonoDomain* rootDomain = nullptr;
bool initialized = false;
bool cleanupRegistered = false;
};
enum class ManagedComponentKind {
Unknown,
Script,
Transform,
Rigidbody,
Camera,
Light,
MeshFilter,
MeshRenderer,
};
struct ManagedComponentTypeInfo {
ManagedComponentKind kind = ManagedComponentKind::Unknown;
MonoClass* monoClass = nullptr;
std::string assemblyName;
std::string namespaceName;
std::string className;
};
MonoRootState& GetMonoRootState() {
static MonoRootState state;
return state;
}
Components::Scene*& GetInternalCallScene() {
static Components::Scene* scene = nullptr;
return scene;
}
float& GetInternalCallDeltaTime() {
static float deltaTime = 0.0f;
return deltaTime;
}
bool& GetInternalCallRegistrationState() {
static bool registered = false;
return registered;
}
struct ManagedScriptableRenderContextState {
uint64_t handle = 0;
Rendering::CameraFrameStage stage = Rendering::CameraFrameStage::MainScene;
const Rendering::RenderPipelineStageRenderGraphContext* graphContext = nullptr;
Rendering::Pipelines::NativeSceneRecorder* sceneRecorder = nullptr;
struct RasterPassRecordRequest {
Containers::String passName = {};
Rendering::FullscreenPassDesc passDesc = {};
Rendering::RenderGraphTextureHandle sourceColorTexture = {};
std::vector<Rendering::RenderGraphTextureHandle> readTextures = {};
std::vector<Rendering::RenderGraphTextureHandle> readDepthTextures = {};
std::vector<Rendering::RenderPassGraphTextureBindingRequest>
textureBindings = {};
std::vector<Rendering::RenderGraphTextureHandle> colorTargets = {};
Rendering::RenderGraphTextureHandle depthTarget = {};
};
uint64_t nextPendingRasterPassHandle = 1u;
std::unordered_map<uint64_t, RasterPassRecordRequest>
pendingRasterPassRequests = {};
std::vector<RasterPassRecordRequest> rasterPassRequests = {};
};
struct ManagedCameraRenderRequestContextState {
uint64_t handle = 0;
Rendering::CameraRenderRequest* request = nullptr;
size_t renderedBaseCameraCount = 0u;
size_t renderedRequestCount = 0u;
Rendering::DirectionalShadowPlanningSettings
directionalShadowPlanningSettings = {};
bool suppressDirectionalShadow = false;
};
struct ManagedRenderSceneSetupContextState {
uint64_t handle = 0;
const Rendering::CameraFramePlan* plan = nullptr;
Rendering::RenderSceneData* sceneData = nullptr;
bool explicitlyConfigured = false;
};
struct ManagedDirectionalShadowExecutionContextState {
uint64_t handle = 0;
const Rendering::CameraFramePlan* plan = nullptr;
const Rendering::DirectionalShadowSurfaceAllocation*
shadowAllocation = nullptr;
Rendering::DirectionalShadowExecutionState* shadowState =
nullptr;
bool explicitlyConfigured = false;
};
struct ManagedScriptableRenderPipelinePlanningContextState {
uint64_t handle = 0;
Rendering::CameraFramePlan* plan = nullptr;
};
uint64_t& GetManagedScriptableRenderContextNextHandle() {
static uint64_t nextHandle = 1;
return nextHandle;
}
std::unordered_map<uint64_t, ManagedScriptableRenderContextState*>&
GetManagedScriptableRenderContextRegistry() {
static std::unordered_map<uint64_t, ManagedScriptableRenderContextState*> registry;
return registry;
}
ManagedScriptableRenderContextState* FindManagedScriptableRenderContextState(
uint64_t handle) {
const auto it = GetManagedScriptableRenderContextRegistry().find(handle);
return it != GetManagedScriptableRenderContextRegistry().end()
? it->second
: nullptr;
}
ManagedScriptableRenderContextState::RasterPassRecordRequest*
FindPendingManagedRasterPassRecordRequest(
ManagedScriptableRenderContextState* state,
uint64_t rasterPassHandle) {
if (state == nullptr || rasterPassHandle == 0u) {
return nullptr;
}
const auto it =
state->pendingRasterPassRequests.find(rasterPassHandle);
return it != state->pendingRasterPassRequests.end()
? &it->second
: nullptr;
}
uint64_t RegisterManagedScriptableRenderContextState(
ManagedScriptableRenderContextState& state) {
uint64_t handle = GetManagedScriptableRenderContextNextHandle()++;
if (handle == 0) {
handle = GetManagedScriptableRenderContextNextHandle()++;
}
state.handle = handle;
GetManagedScriptableRenderContextRegistry()[handle] = &state;
return handle;
}
void UnregisterManagedScriptableRenderContextState(uint64_t handle) {
if (handle == 0) {
return;
}
GetManagedScriptableRenderContextRegistry().erase(handle);
}
const Rendering::RenderCameraData& ResolveManagedScriptableRenderContextCameraData(
const ManagedScriptableRenderContextState* state) {
if (state != nullptr &&
state->graphContext != nullptr) {
return state->graphContext->sceneData.cameraData;
}
static const Rendering::RenderCameraData kDefaultCameraData = {};
return kDefaultCameraData;
}
const Rendering::RenderLightingData& ResolveManagedScriptableRenderContextLightingData(
const ManagedScriptableRenderContextState* state) {
if (state != nullptr &&
state->graphContext != nullptr) {
return state->graphContext->sceneData.lighting;
}
static const Rendering::RenderLightingData kDefaultLightingData = {};
return kDefaultLightingData;
}
const Rendering::RenderEnvironmentData&
ResolveManagedScriptableRenderContextEnvironmentData(
const ManagedScriptableRenderContextState* state) {
if (state != nullptr &&
state->graphContext != nullptr) {
return state->graphContext->sceneData.environment;
}
static const Rendering::RenderEnvironmentData kDefaultEnvironmentData = {};
return kDefaultEnvironmentData;
}
const Rendering::ResolvedFinalColorPolicy&
ResolveManagedScriptableRenderContextFinalColorPolicy(
const ManagedScriptableRenderContextState* state) {
if (state != nullptr &&
state->graphContext != nullptr) {
return state->graphContext->finalColorPolicy;
}
static const Rendering::ResolvedFinalColorPolicy
kDefaultFinalColorPolicy = {};
return kDefaultFinalColorPolicy;
}
Rendering::CameraFrameColorSource
ResolveManagedScriptableRenderContextStageColorSource(
const ManagedScriptableRenderContextState* state) {
if (state != nullptr &&
state->graphContext != nullptr) {
return state->graphContext->stageColorSource;
}
return Rendering::CameraFrameColorSource::ExplicitSurface;
}
bool ResolveManagedScriptableRenderContextUsesGraphManagedOutputColor(
const ManagedScriptableRenderContextState* state) {
return state != nullptr &&
state->graphContext != nullptr &&
state->graphContext->usesGraphManagedOutputColor;
}
int32_t EncodeManagedRenderGraphTextureHandle(
Rendering::RenderGraphTextureHandle handle) {
return handle.IsValid()
? static_cast<int32_t>(handle.index)
: -1;
}
Rendering::RenderGraphTextureHandle
DecodeManagedRenderGraphTextureHandle(
int32_t handleValue) {
Rendering::RenderGraphTextureHandle handle = {};
if (handleValue < 0) {
return handle;
}
handle.index = static_cast<Core::uint32>(handleValue);
return handle;
}
Rendering::RenderGraphTextureHandle
ResolveManagedScriptableRenderContextSourceColorTexture(
const ManagedScriptableRenderContextState* state) {
if (state == nullptr ||
state->graphContext == nullptr) {
return {};
}
if (state->graphContext->sourceColorTexture.IsValid()) {
return state->graphContext->sourceColorTexture;
}
const Rendering::CameraFrameRenderGraphResources* const resources =
Rendering::TryGetCameraFrameRenderGraphResources(
state->graphContext->blackboard);
if (resources == nullptr) {
return {};
}
switch (state->stage) {
case Rendering::CameraFrameStage::PostProcess:
return resources->mainScene.color;
case Rendering::CameraFrameStage::FinalOutput:
return resources->postProcess.color.IsValid()
? resources->postProcess.color
: resources->mainScene.color;
default:
return {};
}
}
Rendering::RenderGraphTextureHandle
ResolveManagedPrimaryColorTarget(
const std::vector<Rendering::RenderGraphTextureHandle>& colorTargets) {
const auto it =
std::find_if(
colorTargets.begin(),
colorTargets.end(),
[](Rendering::RenderGraphTextureHandle handle) {
return handle.IsValid();
});
return it != colorTargets.end()
? *it
: Rendering::RenderGraphTextureHandle{};
}
Rendering::RenderGraphTextureHandle
ResolveManagedScriptableRenderContextPrimaryColorTarget(
const ManagedScriptableRenderContextState* state) {
if (state == nullptr ||
state->graphContext == nullptr) {
return {};
}
return ResolveManagedPrimaryColorTarget(
state->graphContext->colorTargets);
}
Rendering::RenderGraphTextureHandle
ResolveManagedScriptableRenderContextDepthTarget(
const ManagedScriptableRenderContextState* state) {
return state != nullptr &&
state->graphContext != nullptr
? state->graphContext->depthTarget
: Rendering::RenderGraphTextureHandle{};
}
Rendering::RenderGraphTextureDesc
BuildManagedFullscreenTransientDepthTextureDesc(
const Rendering::RenderSurface& surface) {
Rendering::RenderGraphTextureDesc desc = {};
desc.width =
surface.GetWidth() > 0u
? surface.GetWidth()
: surface.GetRenderAreaWidth();
desc.height =
surface.GetHeight() > 0u
? surface.GetHeight()
: surface.GetRenderAreaHeight();
desc.format = static_cast<Core::uint32>(
RHI::Format::D24_UNorm_S8_UInt);
desc.textureType = static_cast<Core::uint32>(
RHI::TextureType::Texture2D);
desc.sampleCount = 1u;
desc.sampleQuality = 0u;
return desc;
}
Rendering::RenderGraphRecordingSourceBinding
BuildManagedScriptableRenderContextSourceBinding(
const Rendering::RenderPipelineStageRenderGraphContext& context,
Rendering::RenderGraphTextureHandle sourceColorTexture) {
if (!sourceColorTexture.IsValid()) {
return {};
}
Rendering::RenderGraphRecordingSourceBinding binding =
Rendering::MakeRenderGraphRecordingSourceBinding(
context.sourceSurface,
context.sourceColorView,
context.sourceColorState,
sourceColorTexture);
const bool usesContextSource =
context.sourceColorTexture.IsValid() &&
context.sourceColorTexture.index == sourceColorTexture.index;
if (!usesContextSource) {
binding.sourceColorView = nullptr;
binding.sourceColorState =
RHI::ResourceStates::PixelShaderResource;
}
if (binding.sourceSurface == nullptr) {
binding.sourceSurface = &context.surfaceTemplate;
}
return binding;
}
bool RecordManagedFullscreenRasterPass(
const Rendering::RenderPipelineStageRenderGraphContext& stageContext,
Rendering::RenderPass& pass,
Rendering::RenderGraphTextureHandle sourceColorTexture,
std::vector<Rendering::RenderGraphTextureHandle> colorTargets,
std::vector<Rendering::RenderGraphTextureHandle> additionalReadTextures,
std::vector<Rendering::RenderGraphTextureHandle> additionalReadDepthTextures,
std::vector<Rendering::RenderPassGraphTextureBindingRequest>
textureBindings,
Rendering::RenderGraphTextureHandle depthTarget,
const Containers::String& passName) {
if (!Rendering::IsCameraFrameFullscreenSequenceStage(stageContext.stage) ||
!sourceColorTexture.IsValid() ||
!ResolveManagedPrimaryColorTarget(colorTargets).IsValid()) {
return false;
}
const Rendering::RenderGraphRecordingContext baseContext =
Rendering::BuildRenderGraphRecordingContext(
stageContext);
Rendering::RenderGraphRecordingContextBuildParams params = {};
if (!passName.Empty()) {
params.passName = &passName;
}
params.overrideSourceBinding = true;
params.sourceBinding =
BuildManagedScriptableRenderContextSourceBinding(
stageContext,
sourceColorTexture);
params.overrideColorTargets = true;
params.colorTargets = std::move(colorTargets);
params.overrideDepthTarget = true;
params.depthTarget = depthTarget;
const Rendering::RenderGraphRecordingContext recordingContext =
Rendering::BuildRenderGraphRecordingContext(
baseContext,
std::move(params));
const Rendering::RenderPassRenderGraphContext renderGraphContext =
Rendering::BuildRenderPassRenderGraphContext(recordingContext);
Rendering::RenderPass* const passPtr = &pass;
Rendering::RenderPassGraphIO io =
Rendering::BuildSourceColorFullscreenRasterPassGraphIO();
io.writeDepth = depthTarget.IsValid();
return Rendering::RecordCallbackRasterRenderPass(
renderGraphContext,
io,
[passPtr](const Rendering::RenderPassContext& passContext) {
return passPtr != nullptr &&
passPtr->Execute(passContext);
},
std::move(additionalReadTextures),
std::move(additionalReadDepthTextures),
std::move(textureBindings));
}
bool RecordManagedFullscreenPassToTexture(
const Rendering::RenderPipelineStageRenderGraphContext& stageContext,
Rendering::RenderPass& pass,
Rendering::RenderGraphTextureHandle sourceColorTexture,
Rendering::RenderGraphTextureHandle outputColorTexture,
const Containers::String& passName) {
return RecordManagedFullscreenRasterPass(
stageContext,
pass,
sourceColorTexture,
{ outputColorTexture },
{},
{},
{},
{},
passName);
}
const Rendering::DirectionalShadowRenderPlan&
ResolveManagedScriptableRenderContextDirectionalShadowPlan(
const ManagedScriptableRenderContextState* state) {
if (state != nullptr &&
state->graphContext != nullptr) {
return state->graphContext->directionalShadowPlan;
}
static const Rendering::DirectionalShadowRenderPlan
kDefaultDirectionalShadowPlan = {};
return kDefaultDirectionalShadowPlan;
}
uint64_t& GetManagedCameraRenderRequestContextNextHandle() {
static uint64_t nextHandle = 1;
return nextHandle;
}
std::unordered_map<uint64_t, ManagedCameraRenderRequestContextState*>&
GetManagedCameraRenderRequestContextRegistry() {
static std::unordered_map<uint64_t, ManagedCameraRenderRequestContextState*>
registry;
return registry;
}
ManagedCameraRenderRequestContextState*
FindManagedCameraRenderRequestContextState(
uint64_t handle) {
const auto it =
GetManagedCameraRenderRequestContextRegistry().find(handle);
return it != GetManagedCameraRenderRequestContextRegistry().end()
? it->second
: nullptr;
}
uint64_t RegisterManagedCameraRenderRequestContextState(
ManagedCameraRenderRequestContextState& state) {
uint64_t handle =
GetManagedCameraRenderRequestContextNextHandle()++;
if (handle == 0) {
handle =
GetManagedCameraRenderRequestContextNextHandle()++;
}
state.handle = handle;
GetManagedCameraRenderRequestContextRegistry()[handle] =
&state;
return handle;
}
void UnregisterManagedCameraRenderRequestContextState(
uint64_t handle) {
if (handle == 0) {
return;
}
GetManagedCameraRenderRequestContextRegistry().erase(handle);
}
uint64_t& GetManagedRenderSceneSetupContextNextHandle() {
static uint64_t nextHandle = 1;
return nextHandle;
}
std::unordered_map<uint64_t, ManagedRenderSceneSetupContextState*>&
GetManagedRenderSceneSetupContextRegistry() {
static std::unordered_map<uint64_t, ManagedRenderSceneSetupContextState*>
registry;
return registry;
}
ManagedRenderSceneSetupContextState*
FindManagedRenderSceneSetupContextState(
uint64_t handle) {
const auto it =
GetManagedRenderSceneSetupContextRegistry().find(handle);
return it != GetManagedRenderSceneSetupContextRegistry().end()
? it->second
: nullptr;
}
uint64_t RegisterManagedRenderSceneSetupContextState(
ManagedRenderSceneSetupContextState& state) {
uint64_t handle =
GetManagedRenderSceneSetupContextNextHandle()++;
if (handle == 0) {
handle =
GetManagedRenderSceneSetupContextNextHandle()++;
}
state.handle = handle;
GetManagedRenderSceneSetupContextRegistry()[handle] =
&state;
return handle;
}
void UnregisterManagedRenderSceneSetupContextState(
uint64_t handle) {
if (handle == 0) {
return;
}
GetManagedRenderSceneSetupContextRegistry().erase(handle);
}
uint64_t& GetManagedDirectionalShadowExecutionContextNextHandle() {
static uint64_t nextHandle = 1;
return nextHandle;
}
std::unordered_map<
uint64_t,
ManagedDirectionalShadowExecutionContextState*>&
GetManagedDirectionalShadowExecutionContextRegistry() {
static std::unordered_map<
uint64_t,
ManagedDirectionalShadowExecutionContextState*>
registry;
return registry;
}
ManagedDirectionalShadowExecutionContextState*
FindManagedDirectionalShadowExecutionContextState(
uint64_t handle) {
const auto it =
GetManagedDirectionalShadowExecutionContextRegistry().find(
handle);
return it !=
GetManagedDirectionalShadowExecutionContextRegistry()
.end()
? it->second
: nullptr;
}
uint64_t RegisterManagedDirectionalShadowExecutionContextState(
ManagedDirectionalShadowExecutionContextState& state) {
uint64_t handle =
GetManagedDirectionalShadowExecutionContextNextHandle()++;
if (handle == 0) {
handle =
GetManagedDirectionalShadowExecutionContextNextHandle()++;
}
state.handle = handle;
GetManagedDirectionalShadowExecutionContextRegistry()[handle] =
&state;
return handle;
}
void UnregisterManagedDirectionalShadowExecutionContextState(
uint64_t handle) {
if (handle == 0) {
return;
}
GetManagedDirectionalShadowExecutionContextRegistry().erase(
handle);
}
uint64_t& GetManagedScriptableRenderPipelinePlanningContextNextHandle() {
static uint64_t nextHandle = 1;
return nextHandle;
}
std::unordered_map<uint64_t, ManagedScriptableRenderPipelinePlanningContextState*>&
GetManagedScriptableRenderPipelinePlanningContextRegistry() {
static std::unordered_map<
uint64_t,
ManagedScriptableRenderPipelinePlanningContextState*> registry;
return registry;
}
ManagedScriptableRenderPipelinePlanningContextState*
FindManagedScriptableRenderPipelinePlanningContextState(
uint64_t handle) {
const auto it =
GetManagedScriptableRenderPipelinePlanningContextRegistry().find(
handle);
return it !=
GetManagedScriptableRenderPipelinePlanningContextRegistry().end()
? it->second
: nullptr;
}
uint64_t RegisterManagedScriptableRenderPipelinePlanningContextState(
ManagedScriptableRenderPipelinePlanningContextState& state) {
uint64_t handle =
GetManagedScriptableRenderPipelinePlanningContextNextHandle()++;
if (handle == 0) {
handle =
GetManagedScriptableRenderPipelinePlanningContextNextHandle()++;
}
state.handle = handle;
GetManagedScriptableRenderPipelinePlanningContextRegistry()[handle] =
&state;
return handle;
}
void UnregisterManagedScriptableRenderPipelinePlanningContextState(
uint64_t handle) {
if (handle == 0) {
return;
}
GetManagedScriptableRenderPipelinePlanningContextRegistry().erase(handle);
}
bool TryResolveManagedCameraFrameStage(
int32_t value,
Rendering::CameraFrameStage& outStage) {
switch (value) {
case static_cast<int32_t>(Rendering::CameraFrameStage::PreScenePasses):
outStage = Rendering::CameraFrameStage::PreScenePasses;
return true;
case static_cast<int32_t>(Rendering::CameraFrameStage::ShadowCaster):
outStage = Rendering::CameraFrameStage::ShadowCaster;
return true;
case static_cast<int32_t>(Rendering::CameraFrameStage::DepthOnly):
outStage = Rendering::CameraFrameStage::DepthOnly;
return true;
case static_cast<int32_t>(Rendering::CameraFrameStage::MainScene):
outStage = Rendering::CameraFrameStage::MainScene;
return true;
case static_cast<int32_t>(Rendering::CameraFrameStage::PostProcess):
outStage = Rendering::CameraFrameStage::PostProcess;
return true;
case static_cast<int32_t>(Rendering::CameraFrameStage::FinalOutput):
outStage = Rendering::CameraFrameStage::FinalOutput;
return true;
case static_cast<int32_t>(Rendering::CameraFrameStage::PostScenePasses):
outStage = Rendering::CameraFrameStage::PostScenePasses;
return true;
case static_cast<int32_t>(Rendering::CameraFrameStage::OverlayPasses):
outStage = Rendering::CameraFrameStage::OverlayPasses;
return true;
default:
outStage = Rendering::CameraFrameStage::MainScene;
return false;
}
}
void CleanupMonoRootDomainAtExit() {
MonoRootState& rootState = GetMonoRootState();
if (!rootState.rootDomain) {
return;
}
mono_domain_set(rootState.rootDomain, true);
mono_jit_cleanup(rootState.rootDomain);
rootState.rootDomain = nullptr;
rootState.initialized = false;
GetInternalCallRegistrationState() = false;
}
std::string BuildFullClassName(const std::string& namespaceName, const std::string& className) {
return namespaceName.empty() ? className : namespaceName + "." + className;
}
std::string BuildClassKey(
const std::string& assemblyName,
const std::string& namespaceName,
const std::string& className) {
return assemblyName + "|" + BuildFullClassName(namespaceName, className);
}
std::string SafeString(const char* value) {
return value ? std::string(value) : std::string();
}
std::string TrimAssemblyName(const std::string& assemblyName) {
constexpr const char* kDllSuffix = ".dll";
if (assemblyName.size() >= 4u &&
assemblyName.substr(assemblyName.size() - 4u) == kDllSuffix) {
return assemblyName.substr(0u, assemblyName.size() - 4u);
}
return assemblyName;
}
std::string TrimWhitespace(std::string value) {
auto isWhitespace = [](unsigned char ch) {
return std::isspace(ch) != 0;
};
value.erase(
value.begin(),
std::find_if(
value.begin(),
value.end(),
[&](char ch) {
return !isWhitespace(static_cast<unsigned char>(ch));
}));
value.erase(
std::find_if(
value.rbegin(),
value.rend(),
[&](char ch) {
return !isWhitespace(static_cast<unsigned char>(ch));
}).base(),
value.end());
return value;
}
bool NormalizeManagedAssemblyDescriptor(
MonoScriptRuntime::ManagedAssemblyDescriptor& descriptor,
const std::filesystem::path& assemblyDirectory,
std::unordered_set<std::string>& ioAssemblyNames,
std::string* outError) {
descriptor.name = TrimAssemblyName(TrimWhitespace(descriptor.name));
if (descriptor.name.empty() && !descriptor.path.empty()) {
descriptor.name =
TrimAssemblyName(descriptor.path.stem().string());
}
if (descriptor.name.empty()) {
if (outError != nullptr) {
*outError = "Managed engine assembly name is empty.";
}
return false;
}
if (descriptor.path.empty() && !assemblyDirectory.empty()) {
descriptor.path = assemblyDirectory / (descriptor.name + ".dll");
}
if (!descriptor.path.empty()) {
descriptor.path = descriptor.path.lexically_normal();
}
if (!ioAssemblyNames.insert(descriptor.name).second) {
if (outError != nullptr) {
*outError =
"Managed engine assembly name is duplicated: " +
descriptor.name;
}
return false;
}
return true;
}
bool LoadManagedAssemblyManifest(
const std::filesystem::path& assemblyDirectory,
const std::filesystem::path& manifestPath,
std::vector<MonoScriptRuntime::ManagedAssemblyDescriptor>& outAssemblies,
std::string* outError) {
outAssemblies.clear();
std::error_code ec;
if (manifestPath.empty() ||
!std::filesystem::exists(manifestPath, ec)) {
return true;
}
std::ifstream input(manifestPath);
if (!input.is_open()) {
if (outError != nullptr) {
*outError =
"Failed to open managed engine assembly manifest: " +
manifestPath.string();
}
return false;
}
std::unordered_set<std::string> assemblyNames;
std::string line;
size_t lineNumber = 0u;
while (std::getline(input, line)) {
++lineNumber;
const size_t commentStart = line.find('#');
if (commentStart != std::string::npos) {
line.erase(commentStart);
}
line = TrimWhitespace(std::move(line));
if (line.empty()) {
continue;
}
MonoScriptRuntime::ManagedAssemblyDescriptor descriptor;
const size_t separator = line.find('=');
if (separator == std::string::npos) {
descriptor.name = line;
} else {
descriptor.name = line.substr(0u, separator);
std::string relativePath =
TrimWhitespace(line.substr(separator + 1u));
if (!relativePath.empty()) {
descriptor.path =
(assemblyDirectory / relativePath).lexically_normal();
}
}
if (!NormalizeManagedAssemblyDescriptor(
descriptor,
assemblyDirectory,
assemblyNames,
outError)) {
if (outError != nullptr && !outError->empty()) {
*outError +=
" Manifest: " + manifestPath.string() +
" line " + std::to_string(lineNumber) + ".";
}
return false;
}
outAssemblies.push_back(std::move(descriptor));
}
return true;
}
bool DiscoverManagedAssembliesByConvention(
const MonoScriptRuntime::Settings& settings,
std::vector<MonoScriptRuntime::ManagedAssemblyDescriptor>& outAssemblies) {
outAssemblies.clear();
std::error_code ec;
if (settings.assemblyDirectory.empty() ||
!std::filesystem::exists(settings.assemblyDirectory, ec)) {
return true;
}
const std::string coreAssemblyName =
TrimAssemblyName(settings.coreAssemblyName);
const std::string appAssemblyName =
TrimAssemblyName(settings.appAssemblyName);
std::unordered_set<std::string> reservedNames = {
coreAssemblyName,
appAssemblyName,
"mscorlib"};
for (std::filesystem::directory_iterator it(
settings.assemblyDirectory,
ec), end;
it != end && !ec;
it.increment(ec)) {
if (ec || !it->is_regular_file(ec)) {
continue;
}
const std::filesystem::path path = it->path();
if (path.extension() != ".dll") {
continue;
}
const std::string assemblyName =
TrimAssemblyName(path.stem().string());
if (assemblyName.rfind("XCEngine.", 0u) != 0u ||
reservedNames.contains(assemblyName)) {
continue;
}
outAssemblies.push_back(
MonoScriptRuntime::ManagedAssemblyDescriptor{
assemblyName,
path.lexically_normal()});
}
std::sort(
outAssemblies.begin(),
outAssemblies.end(),
[](const MonoScriptRuntime::ManagedAssemblyDescriptor& lhs,
const MonoScriptRuntime::ManagedAssemblyDescriptor& rhs) {
return lhs.name < rhs.name;
});
return true;
}
MonoScriptRuntime::ManagedAssemblyDescriptor BuildManagedAssemblyDescriptor(
const std::string& assemblyName,
const std::filesystem::path& assemblyPath) {
return MonoScriptRuntime::ManagedAssemblyDescriptor{
assemblyName,
assemblyPath};
}
bool IsMonoClassOrSubclass(MonoClass* monoClass, MonoClass* potentialBaseClass) {
if (!monoClass || !potentialBaseClass) {
return false;
}
return monoClass == potentialBaseClass
|| mono_class_is_subclass_of(monoClass, potentialBaseClass, 0) != 0;
}
std::string MonoStringToUtf8(MonoString* stringObject) {
if (!stringObject) {
return std::string();
}
char* utf8 = mono_string_to_utf8(stringObject);
std::string result = utf8 ? std::string(utf8) : std::string();
if (utf8) {
mono_free(utf8);
}
return result;
}
MonoScriptRuntime* GetActiveMonoScriptRuntime() {
return dynamic_cast<MonoScriptRuntime*>(ScriptEngine::Get().GetRuntime());
}
void ClearManagedRenderPipelineSelection(MonoScriptRuntime* runtime) {
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor =
Rendering::GetGraphicsSettingsState()
.GetConfiguredRenderPipelineAssetDescriptor();
if (runtime != nullptr && descriptor.managedAssetHandle != 0u) {
runtime->ReleaseExternalManagedObject(descriptor.managedAssetHandle);
}
Rendering::GetGraphicsSettingsState()
.ClearConfiguredRenderPipelineAssetDescriptor();
}
bool TryUnboxManagedBoolean(MonoObject* boxedValue, bool& outValue) {
outValue = false;
if (!boxedValue) {
return false;
}
void* const rawValue = mono_object_unbox(boxedValue);
if (!rawValue) {
return false;
}
outValue = (*static_cast<mono_bool*>(rawValue)) != 0;
return true;
}
bool TryUnboxManagedInt32(MonoObject* boxedValue, int32_t& outValue) {
outValue = 0;
if (!boxedValue) {
return false;
}
void* const rawValue = mono_object_unbox(boxedValue);
if (!rawValue) {
return false;
}
outValue = *static_cast<int32_t*>(rawValue);
return true;
}
struct ManagedFinalColorSettingsData {
uint8_t outputTransferMode = 0;
uint8_t exposureMode = 0;
uint16_t exposurePadding = 0;
float exposureValue = 1.0f;
uint8_t toneMappingMode = 0;
uint8_t toneMappingPadding[3] = {};
XCEngine::Math::Vector4 finalColorScale = XCEngine::Math::Vector4::One();
};
static_assert(
sizeof(ManagedFinalColorSettingsData) ==
sizeof(Rendering::FinalColorSettings),
"Managed final color bridge layout must match native FinalColorSettings.");
struct ManagedFinalColorOverrideSettingsData {
uint8_t overrideOutputTransferMode = 0u;
uint8_t outputTransferMode = 0u;
uint8_t overrideExposureMode = 0u;
uint8_t exposureMode = 0u;
uint8_t overrideExposureValue = 0u;
uint8_t exposureValuePadding[3] = {};
float exposureValue = 1.0f;
uint8_t overrideToneMappingMode = 0u;
uint8_t toneMappingMode = 0u;
uint8_t overrideFinalColorScale = 0u;
uint8_t finalColorScalePadding = 0u;
XCEngine::Math::Vector4 finalColorScale = XCEngine::Math::Vector4::One();
};
static_assert(
sizeof(ManagedFinalColorOverrideSettingsData) ==
sizeof(Rendering::FinalColorOverrideSettings),
"Managed final color override bridge layout must match native FinalColorOverrideSettings.");
struct ManagedRenderGraphTextureDescData {
uint32_t width = 0u;
uint32_t height = 0u;
uint32_t format = 0u;
uint32_t textureType = 0u;
uint32_t sampleCount = 0u;
uint32_t sampleQuality = 0u;
};
static_assert(
sizeof(ManagedRenderGraphTextureDescData) ==
sizeof(Rendering::RenderGraphTextureDesc),
"Managed render graph texture desc bridge layout must match native RenderGraphTextureDesc.");
struct ManagedDirectionalShadowSamplingSettingsData {
float receiverDepthBias = 0.0010f;
float normalBiasScale = 2.0f;
float shadowStrength = 0.85f;
};
static_assert(
sizeof(ManagedDirectionalShadowSamplingSettingsData) ==
sizeof(Rendering::DirectionalShadowSamplingSettings),
"Managed directional shadow sampling bridge layout must match native DirectionalShadowSamplingSettings.");
struct ManagedDirectionalShadowCasterBiasSettingsData {
float depthBiasFactor = 2.5f;
int32_t depthBiasUnits = 4;
};
static_assert(
sizeof(ManagedDirectionalShadowCasterBiasSettingsData) ==
sizeof(Rendering::DirectionalShadowCasterBiasSettings),
"Managed directional shadow caster bias bridge layout must match native DirectionalShadowCasterBiasSettings.");
struct ManagedDirectionalShadowPlanningSettingsData {
uint32_t mapDimension = 2048u;
float minFocusDistance = 5.0f;
float maxFocusDistance = 32.0f;
float perspectiveFocusFactor = 1.0f;
float orthographicFocusFactor = 2.0f;
float minDepthRange = 20.0f;
float boundsPadding = 0.5f;
float minDepthPadding = 2.0f;
ManagedDirectionalShadowSamplingSettingsData sampling = {};
ManagedDirectionalShadowCasterBiasSettingsData casterBias = {};
};
static_assert(
sizeof(ManagedDirectionalShadowPlanningSettingsData) ==
sizeof(Rendering::DirectionalShadowPlanningSettings),
"Managed directional shadow planning bridge layout must match native DirectionalShadowPlanningSettings.");
struct ManagedFilteringSettingsData {
int32_t renderQueueMin = std::numeric_limits<int32_t>::lowest();
int32_t renderQueueMax = std::numeric_limits<int32_t>::max();
uint32_t renderLayerMask = std::numeric_limits<uint32_t>::max();
uint8_t requireShadowCasting = 0u;
uint8_t reservedEditorObjectIdFilter = 0u;
};
static_assert(
sizeof(ManagedFilteringSettingsData) ==
sizeof(Rendering::FilteringSettings),
"Managed filtering settings bridge layout must match native FilteringSettings.");
struct ManagedSortingSettingsData {
uint32_t sortMode = 0u;
};
static_assert(
sizeof(ManagedSortingSettingsData) ==
sizeof(Rendering::SortingSettings),
"Managed sorting settings bridge layout must match native SortingSettings.");
struct ManagedRendererListDescData {
uint32_t type = 0u;
ManagedFilteringSettingsData filtering = {};
ManagedSortingSettingsData sorting = {};
};
static_assert(
sizeof(ManagedRendererListDescData) ==
sizeof(Rendering::RendererListDesc),
"Managed renderer list desc bridge layout must match native RendererListDesc.");
struct ManagedDepthStateData {
uint8_t writeEnabled = 1u;
uint8_t compareFunction =
static_cast<uint8_t>(Resources::MaterialComparisonFunc::Less);
};
static_assert(
sizeof(ManagedDepthStateData) ==
sizeof(Rendering::DepthState),
"Managed depth state bridge layout must match native DepthState.");
struct ManagedStencilFaceStateData {
uint8_t failOperation =
static_cast<uint8_t>(Resources::MaterialStencilOp::Keep);
uint8_t passOperation =
static_cast<uint8_t>(Resources::MaterialStencilOp::Keep);
uint8_t depthFailOperation =
static_cast<uint8_t>(Resources::MaterialStencilOp::Keep);
uint8_t compareFunction =
static_cast<uint8_t>(Resources::MaterialComparisonFunc::Always);
};
static_assert(
sizeof(ManagedStencilFaceStateData) ==
sizeof(Rendering::StencilFaceState),
"Managed stencil face state bridge layout must match native StencilFaceState.");
struct ManagedStencilStateData {
uint8_t enabled = 0u;
uint8_t readMask = 0xFFu;
uint8_t writeMask = 0xFFu;
ManagedStencilFaceStateData frontFace = {};
ManagedStencilFaceStateData backFace = {};
};
static_assert(
sizeof(ManagedStencilStateData) ==
sizeof(Rendering::StencilState),
"Managed stencil state bridge layout must match native StencilState.");
struct ManagedRenderStateBlockData {
uint32_t mask = 0u;
ManagedDepthStateData depthState = {};
ManagedStencilStateData stencilState = {};
uint8_t stencilReference = 0u;
};
static_assert(
sizeof(ManagedRenderStateBlockData) ==
sizeof(Rendering::RenderStateBlock),
"Managed render state block bridge layout must match native RenderStateBlock.");
Rendering::FinalColorOutputTransferMode ResolveManagedFinalColorOutputTransferMode(
uint8_t value) {
switch (value) {
case 1:
return Rendering::FinalColorOutputTransferMode::LinearToSRGB;
default:
return Rendering::FinalColorOutputTransferMode::Disabled;
}
}
Rendering::FinalColorExposureMode ResolveManagedFinalColorExposureMode(
uint8_t value) {
switch (value) {
case 1:
return Rendering::FinalColorExposureMode::Fixed;
default:
return Rendering::FinalColorExposureMode::Disabled;
}
}
Rendering::FinalColorToneMappingMode ResolveManagedFinalColorToneMappingMode(
uint8_t value) {
switch (value) {
case 1:
return Rendering::FinalColorToneMappingMode::Neutral;
case 2:
return Rendering::FinalColorToneMappingMode::ACES;
default:
return Rendering::FinalColorToneMappingMode::Disabled;
}
}
Resources::MaterialComparisonFunc ResolveManagedMaterialComparisonFunc(
uint8_t value) {
switch (value) {
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Never):
return Resources::MaterialComparisonFunc::Never;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Equal):
return Resources::MaterialComparisonFunc::Equal;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::LessEqual):
return Resources::MaterialComparisonFunc::LessEqual;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Greater):
return Resources::MaterialComparisonFunc::Greater;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::NotEqual):
return Resources::MaterialComparisonFunc::NotEqual;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::GreaterEqual):
return Resources::MaterialComparisonFunc::GreaterEqual;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Always):
return Resources::MaterialComparisonFunc::Always;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Less):
default:
return Resources::MaterialComparisonFunc::Less;
}
}
Resources::MaterialStencilOp ResolveManagedMaterialStencilOp(
uint8_t value) {
switch (value) {
case static_cast<uint8_t>(Resources::MaterialStencilOp::Zero):
return Resources::MaterialStencilOp::Zero;
case static_cast<uint8_t>(Resources::MaterialStencilOp::Replace):
return Resources::MaterialStencilOp::Replace;
case static_cast<uint8_t>(Resources::MaterialStencilOp::IncrSat):
return Resources::MaterialStencilOp::IncrSat;
case static_cast<uint8_t>(Resources::MaterialStencilOp::DecrSat):
return Resources::MaterialStencilOp::DecrSat;
case static_cast<uint8_t>(Resources::MaterialStencilOp::Invert):
return Resources::MaterialStencilOp::Invert;
case static_cast<uint8_t>(Resources::MaterialStencilOp::IncrWrap):
return Resources::MaterialStencilOp::IncrWrap;
case static_cast<uint8_t>(Resources::MaterialStencilOp::DecrWrap):
return Resources::MaterialStencilOp::DecrWrap;
case static_cast<uint8_t>(Resources::MaterialStencilOp::Keep):
default:
return Resources::MaterialStencilOp::Keep;
}
}
Rendering::RenderStateMask ResolveManagedRenderStateMask(
uint32_t value) {
const uint32_t knownMask =
Rendering::ToRenderStateMaskBits(Rendering::RenderStateMask::Depth) |
Rendering::ToRenderStateMaskBits(Rendering::RenderStateMask::Stencil);
return static_cast<Rendering::RenderStateMask>(
value & knownMask);
}
bool TryResolveManagedRendererListType(
uint32_t value,
Rendering::RendererListType& outType) {
switch (value) {
case static_cast<uint32_t>(Rendering::RendererListType::AllVisible):
outType = Rendering::RendererListType::AllVisible;
return true;
case static_cast<uint32_t>(Rendering::RendererListType::Opaque):
outType = Rendering::RendererListType::Opaque;
return true;
case static_cast<uint32_t>(Rendering::RendererListType::Transparent):
outType = Rendering::RendererListType::Transparent;
return true;
case static_cast<uint32_t>(Rendering::RendererListType::ShadowCaster):
outType = Rendering::RendererListType::ShadowCaster;
return true;
default:
outType = Rendering::RendererListType::AllVisible;
return false;
}
}
Rendering::RendererSortMode ResolveManagedRendererSortMode(
uint32_t value) {
switch (value) {
case static_cast<uint32_t>(Rendering::RendererSortMode::FrontToBack):
return Rendering::RendererSortMode::FrontToBack;
case static_cast<uint32_t>(Rendering::RendererSortMode::BackToFront):
return Rendering::RendererSortMode::BackToFront;
case static_cast<uint32_t>(Rendering::RendererSortMode::None):
default:
return Rendering::RendererSortMode::None;
}
}
Rendering::FilteringSettings BuildManagedFilteringSettings(
const ManagedFilteringSettingsData& filteringData) {
Rendering::FilteringSettings filteringSettings = {};
filteringSettings.renderQueueMin = filteringData.renderQueueMin;
filteringSettings.renderQueueMax = filteringData.renderQueueMax;
filteringSettings.renderLayerMask = filteringData.renderLayerMask;
filteringSettings.requireShadowCasting =
filteringData.requireShadowCasting != 0u;
return filteringSettings;
}
Rendering::SortingSettings BuildManagedSortingSettings(
const ManagedSortingSettingsData& sortingData) {
Rendering::SortingSettings sortingSettings = {};
sortingSettings.sortMode =
ResolveManagedRendererSortMode(
sortingData.sortMode);
return sortingSettings;
}
bool TryBuildManagedRendererListDesc(
const ManagedRendererListDescData& rendererListDescData,
Rendering::RendererListDesc& outRendererListDesc) {
outRendererListDesc = {};
if (!TryResolveManagedRendererListType(
rendererListDescData.type,
outRendererListDesc.type)) {
return false;
}
outRendererListDesc.filtering =
BuildManagedFilteringSettings(
rendererListDescData.filtering);
outRendererListDesc.sorting =
BuildManagedSortingSettings(
rendererListDescData.sorting);
return true;
}
Rendering::DepthState BuildManagedDepthState(
const ManagedDepthStateData& depthStateData) {
Rendering::DepthState depthState = {};
depthState.writeEnabled = depthStateData.writeEnabled != 0u;
depthState.compareFunction =
ResolveManagedMaterialComparisonFunc(
depthStateData.compareFunction);
return depthState;
}
Rendering::StencilFaceState BuildManagedStencilFaceState(
const ManagedStencilFaceStateData& stencilFaceData) {
Rendering::StencilFaceState stencilFaceState = {};
stencilFaceState.failOp =
ResolveManagedMaterialStencilOp(
stencilFaceData.failOperation);
stencilFaceState.passOp =
ResolveManagedMaterialStencilOp(
stencilFaceData.passOperation);
stencilFaceState.depthFailOp =
ResolveManagedMaterialStencilOp(
stencilFaceData.depthFailOperation);
stencilFaceState.compareFunction =
ResolveManagedMaterialComparisonFunc(
stencilFaceData.compareFunction);
return stencilFaceState;
}
Rendering::StencilState BuildManagedStencilState(
const ManagedStencilStateData& stencilStateData) {
Rendering::StencilState stencilState = {};
stencilState.enabled = stencilStateData.enabled != 0u;
stencilState.readMask = stencilStateData.readMask;
stencilState.writeMask = stencilStateData.writeMask;
stencilState.frontFace =
BuildManagedStencilFaceState(
stencilStateData.frontFace);
stencilState.backFace =
BuildManagedStencilFaceState(
stencilStateData.backFace);
return stencilState;
}
Rendering::RenderStateBlock BuildManagedRenderStateBlock(
const ManagedRenderStateBlockData& renderStateBlockData) {
Rendering::RenderStateBlock renderStateBlock = {};
renderStateBlock.mask =
ResolveManagedRenderStateMask(
renderStateBlockData.mask);
renderStateBlock.depthState =
BuildManagedDepthState(
renderStateBlockData.depthState);
renderStateBlock.stencilState =
BuildManagedStencilState(
renderStateBlockData.stencilState);
renderStateBlock.stencilReference =
renderStateBlockData.stencilReference;
return renderStateBlock;
}
bool TryUnboxManagedFinalColorSettings(
MonoObject* boxedValue,
Rendering::FinalColorSettings& outSettings) {
outSettings = {};
outSettings.exposureValue = 1.0f;
outSettings.finalColorScale = XCEngine::Math::Vector4::One();
if (!boxedValue) {
return false;
}
void* const rawValue = mono_object_unbox(boxedValue);
if (!rawValue) {
return false;
}
const auto* const managedSettings =
static_cast<const ManagedFinalColorSettingsData*>(rawValue);
outSettings.outputTransferMode =
ResolveManagedFinalColorOutputTransferMode(
managedSettings->outputTransferMode);
outSettings.exposureMode =
ResolveManagedFinalColorExposureMode(
managedSettings->exposureMode);
outSettings.exposureValue = managedSettings->exposureValue;
outSettings.toneMappingMode =
ResolveManagedFinalColorToneMappingMode(
managedSettings->toneMappingMode);
outSettings.finalColorScale = managedSettings->finalColorScale;
return true;
}
Rendering::FinalColorSettings BuildManagedFinalColorSettings(
const ManagedFinalColorSettingsData& managedSettings) {
Rendering::FinalColorSettings settings = {};
settings.exposureValue = 1.0f;
settings.finalColorScale = XCEngine::Math::Vector4::One();
settings.outputTransferMode =
ResolveManagedFinalColorOutputTransferMode(
managedSettings.outputTransferMode);
settings.exposureMode =
ResolveManagedFinalColorExposureMode(
managedSettings.exposureMode);
settings.exposureValue = managedSettings.exposureValue;
settings.toneMappingMode =
ResolveManagedFinalColorToneMappingMode(
managedSettings.toneMappingMode);
settings.finalColorScale = managedSettings.finalColorScale;
return settings;
}
ManagedFinalColorOverrideSettingsData BuildManagedFinalColorOverrideSettings(
const Rendering::FinalColorOverrideSettings& nativeSettings) {
ManagedFinalColorOverrideSettingsData managedSettings = {};
managedSettings.overrideOutputTransferMode =
nativeSettings.overrideOutputTransferMode
? 1u
: 0u;
managedSettings.outputTransferMode =
static_cast<uint8_t>(nativeSettings.outputTransferMode);
managedSettings.overrideExposureMode =
nativeSettings.overrideExposureMode
? 1u
: 0u;
managedSettings.exposureMode =
static_cast<uint8_t>(nativeSettings.exposureMode);
managedSettings.overrideExposureValue =
nativeSettings.overrideExposureValue
? 1u
: 0u;
managedSettings.exposureValue =
nativeSettings.exposureValue;
managedSettings.overrideToneMappingMode =
nativeSettings.overrideToneMappingMode
? 1u
: 0u;
managedSettings.toneMappingMode =
static_cast<uint8_t>(nativeSettings.toneMappingMode);
managedSettings.overrideFinalColorScale =
nativeSettings.overrideFinalColorScale
? 1u
: 0u;
managedSettings.finalColorScale =
nativeSettings.finalColorScale;
return managedSettings;
}
bool SupportsManagedRenderPipelineStageGraphRecording(
Rendering::CameraFrameStage stage) {
return Rendering::SupportsCameraFramePipelineGraphRecording(stage) ||
Rendering::IsCameraFrameFullscreenSequenceStage(stage) ||
Rendering::IsCameraFrameScenePassRequestStage(stage);
}
bool SupportsManagedScriptableRenderContextSceneRecordingStage(
Rendering::CameraFrameStage stage) {
return stage == Rendering::CameraFrameStage::MainScene ||
Rendering::IsCameraFrameScenePassRequestStage(stage);
}
Rendering::RenderPass* ConfigureManagedFullscreenPass(
std::vector<std::unique_ptr<Rendering::RenderPass>>& passPool,
size_t passIndex,
const Rendering::FullscreenPassDesc& passDesc) {
while (passPool.size() <= passIndex) {
passPool.push_back(nullptr);
}
std::unique_ptr<Rendering::RenderPass>& passSlot = passPool[passIndex];
switch (passDesc.type) {
case Rendering::FullscreenPassType::ColorScale: {
Rendering::Passes::BuiltinVectorFullscreenPass* fullscreenPass =
dynamic_cast<Rendering::Passes::BuiltinVectorFullscreenPass*>(
passSlot.get());
if (fullscreenPass == nullptr) {
passSlot =
std::make_unique<Rendering::Passes::BuiltinVectorFullscreenPass>();
fullscreenPass =
static_cast<Rendering::Passes::BuiltinVectorFullscreenPass*>(
passSlot.get());
}
fullscreenPass->SetShaderPath(
Resources::GetBuiltinColorScalePostProcessShaderPath());
fullscreenPass->SetPreferredPassName("ColorScale");
fullscreenPass->SetVectorPayload(passDesc.colorScale.scale);
return fullscreenPass;
}
case Rendering::FullscreenPassType::ShaderVector: {
Rendering::Passes::BuiltinVectorFullscreenPass* fullscreenPass =
dynamic_cast<Rendering::Passes::BuiltinVectorFullscreenPass*>(
passSlot.get());
if (fullscreenPass == nullptr) {
passSlot =
std::make_unique<Rendering::Passes::BuiltinVectorFullscreenPass>();
fullscreenPass =
static_cast<Rendering::Passes::BuiltinVectorFullscreenPass*>(
passSlot.get());
}
fullscreenPass->SetShaderPath(passDesc.shaderVector.shaderPath);
fullscreenPass->SetPreferredPassName(passDesc.shaderVector.passName);
fullscreenPass->SetVectorPayload(passDesc.shaderVector.vectorPayload);
return fullscreenPass;
}
case Rendering::FullscreenPassType::FinalColor: {
Rendering::Passes::BuiltinFinalColorPass* finalColorPass =
dynamic_cast<Rendering::Passes::BuiltinFinalColorPass*>(
passSlot.get());
if (finalColorPass == nullptr) {
passSlot =
std::make_unique<Rendering::Passes::BuiltinFinalColorPass>();
finalColorPass =
static_cast<Rendering::Passes::BuiltinFinalColorPass*>(
passSlot.get());
}
finalColorPass->SetShaderPath(
Resources::GetBuiltinFinalColorShaderPath());
finalColorPass->SetSettings(passDesc.finalColor.settings);
return finalColorPass;
}
default:
return nullptr;
}
}
} // namespace
class MonoManagedRenderPipelineAssetRuntime final
: public Rendering::Pipelines::ManagedRenderPipelineAssetRuntime
, public std::enable_shared_from_this<MonoManagedRenderPipelineAssetRuntime> {
public:
MonoManagedRenderPipelineAssetRuntime(
MonoScriptRuntime* runtime,
std::weak_ptr<void> runtimeLifetime,
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor)
: m_runtime(runtime)
, m_runtimeLifetime(std::move(runtimeLifetime))
, m_descriptor(std::move(descriptor)) {
}
~MonoManagedRenderPipelineAssetRuntime() override {
ReleaseManagedAsset();
}
std::unique_ptr<Rendering::RenderPipelineStageRecorder> CreateStageRecorder() const override;
void ConfigureCameraRenderRequest(
Rendering::CameraRenderRequest& request,
size_t renderedBaseCameraCount,
size_t renderedRequestCount,
const Rendering::DirectionalShadowPlanningSettings&
directionalShadowSettings) const override;
void ConfigureCameraFramePlan(
Rendering::CameraFramePlan& plan) const override;
bool ConfigureRenderSceneSetup(
const Rendering::CameraFramePlan& plan,
Rendering::RenderSceneData& sceneData) const override;
bool ConfigureDirectionalShadowExecutionState(
const Rendering::CameraFramePlan& plan,
const Rendering::DirectionalShadowSurfaceAllocation&
shadowAllocation,
Rendering::DirectionalShadowExecutionState& shadowState)
const override;
bool TryGetDefaultFinalColorSettings(
Rendering::FinalColorSettings& settings) const override;
std::shared_ptr<const Rendering::RenderPipelineAsset>
GetPipelineRendererAsset() const override;
Rendering::Pipelines::ManagedPipelineRendererAssetPolicy
GetPipelineRendererAssetPolicy() const override;
MonoScriptRuntime* GetRuntime() const {
return m_runtime;
}
bool IsRuntimeAlive() const {
return m_runtime != nullptr &&
!m_runtimeLifetime.expired() &&
m_runtime->m_initialized;
}
bool AcquireManagedPipelineHandle(uint32_t& outPipelineHandle) const;
private:
bool EnsureManagedAsset() const;
bool SyncManagedAssetRuntimeState() const;
bool TryGetManagedRuntimeResourceVersion(int32_t& outVersion) const;
void ReleaseManagedPipeline() const;
void ReleaseManagedAsset() const;
MonoObject* GetManagedAssetObject() const;
MonoMethod* ResolveDisposePipelineMethod(MonoObject* pipelineObject) const;
MonoMethod* ResolveCreatePipelineMethod(MonoObject* assetObject) const;
MonoMethod* ResolveConfigureCameraRenderRequestMethod(
MonoObject* assetObject) const;
MonoMethod* ResolveConfigureCameraFramePlanMethod(
MonoObject* assetObject) const;
MonoMethod* ResolveGetDefaultFinalColorSettingsMethod(
MonoObject* assetObject) const;
MonoMethod* ResolveGetRuntimeResourceVersionMethod(
MonoObject* assetObject) const;
MonoMethod* ResolveConfigureRenderSceneSetupMethod(
MonoObject* assetObject) const;
MonoMethod* ResolveConfigureDirectionalShadowExecutionStateMethod(
MonoObject* assetObject) const;
MonoMethod* ResolveReleaseRuntimeResourcesMethod(
MonoObject* assetObject) const;
MonoScriptRuntime* m_runtime = nullptr;
std::weak_ptr<void> m_runtimeLifetime;
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor m_descriptor;
mutable uint32_t m_assetHandle = 0;
mutable MonoMethod* m_disposePipelineMethod = nullptr;
mutable MonoMethod* m_createPipelineMethod = nullptr;
mutable MonoMethod* m_configureCameraRenderRequestMethod = nullptr;
mutable MonoMethod* m_configureCameraFramePlanMethod = nullptr;
mutable MonoMethod* m_getDefaultFinalColorSettingsMethod = nullptr;
mutable MonoMethod* m_getRuntimeResourceVersionMethod = nullptr;
mutable MonoMethod* m_configureRenderSceneSetupMethod =
nullptr;
mutable MonoMethod*
m_configureDirectionalShadowExecutionStateMethod = nullptr;
mutable MonoMethod* m_releaseRuntimeResourcesMethod = nullptr;
mutable bool m_ownsManagedAssetHandle = false;
mutable bool m_assetCreationAttempted = false;
mutable bool m_runtimeResourceVersionResolved = false;
mutable int32_t m_runtimeResourceVersion = 0;
mutable uint32_t m_pipelineHandle = 0;
mutable bool m_pipelineCreationAttempted = false;
};
class MonoManagedRenderPipelineStageRecorder final
: public Rendering::RenderPipelineStageRecorder {
public:
explicit MonoManagedRenderPipelineStageRecorder(
std::shared_ptr<const MonoManagedRenderPipelineAssetRuntime> assetRuntime)
: m_assetRuntime(std::move(assetRuntime))
, m_runtime(
m_assetRuntime != nullptr
? m_assetRuntime->GetRuntime()
: nullptr) {
}
~MonoManagedRenderPipelineStageRecorder() override {
Shutdown();
}
bool Initialize(const Rendering::RenderContext&) override {
return GetManagedPipelineObject() != nullptr;
}
void Shutdown() override {
for (std::unique_ptr<Rendering::RenderPass>& pass :
m_fullscreenPassPool) {
if (pass != nullptr) {
pass->Shutdown();
}
}
m_fullscreenPassPool.clear();
if (m_ownedSceneDrawBackend != nullptr) {
m_ownedSceneDrawBackend->Shutdown();
}
m_ownedSharedPipelineBackendAsset.reset();
m_supportsStageContextualMethod = nullptr;
m_supportsStageMethod = nullptr;
m_recordStageMethod = nullptr;
m_resolvedPipelineHandle = 0;
m_boundSceneDrawBackend = nullptr;
}
void SetPipelineBackend(
Rendering::RenderPipelineBackend* pipelineBackend) override {
m_boundSceneDrawBackend =
dynamic_cast<Rendering::SceneDrawBackend*>(pipelineBackend);
}
bool SupportsStageRenderGraph(Rendering::CameraFrameStage stage) const override {
return SupportsStageRenderGraph(
Rendering::RenderPipelineStageSupportContext{
stage,
-1 });
}
bool SupportsStageRenderGraph(
const Rendering::RenderPipelineStageSupportContext& context) const override {
if (!SupportsManagedRenderPipelineStageGraphRecording(context.stage) ||
!IsRuntimeAlive()) {
return false;
}
MonoObject* const pipelineObject = GetManagedPipelineObject();
if (!pipelineObject) {
return false;
}
MonoMethod* const contextualMethod =
ResolveSupportsStageContextualMethod(
pipelineObject);
if (contextualMethod != nullptr) {
int32_t managedStage =
static_cast<int32_t>(context.stage);
int32_t rendererIndex =
context.rendererIndex;
void* args[2] = {
&managedStage,
&rendererIndex };
MonoObject* result = nullptr;
if (!m_runtime->InvokeManagedMethod(
pipelineObject,
contextualMethod,
args,
&result)) {
return false;
}
bool supportsStage = false;
return TryUnboxManagedBoolean(
result,
supportsStage) &&
supportsStage;
}
return SupportsStageRenderGraphFallback(
pipelineObject,
context.stage);
}
private:
bool SupportsStageRenderGraphFallback(
MonoObject* pipelineObject,
Rendering::CameraFrameStage stage) const {
if (!SupportsManagedRenderPipelineStageGraphRecording(stage) ||
!IsRuntimeAlive()) {
return false;
}
MonoMethod* const method = ResolveSupportsStageMethod(pipelineObject);
if (!pipelineObject || !method) {
return false;
}
int32_t managedStage = static_cast<int32_t>(stage);
void* args[1] = { &managedStage };
MonoObject* result = nullptr;
if (!m_runtime->InvokeManagedMethod(
pipelineObject,
method,
args,
&result)) {
return false;
}
bool supportsStage = false;
return TryUnboxManagedBoolean(result, supportsStage) && supportsStage;
}
public:
bool RecordStageRenderGraph(
const Rendering::RenderPipelineStageRenderGraphContext& context) override {
if (!IsRuntimeAlive()) {
return false;
}
MonoObject* const pipelineObject = GetManagedPipelineObject();
MonoMethod* const method = ResolveRecordStageMethod(pipelineObject);
if (!pipelineObject || !method) {
return false;
}
ManagedScriptableRenderContextState managedContextState = {};
managedContextState.stage = context.stage;
managedContextState.graphContext = &context;
Rendering::SceneDrawBackend* const sceneDrawBackend =
ResolveSceneDrawBackend();
if (sceneDrawBackend == nullptr) {
return false;
}
Rendering::Pipelines::NativeSceneRecorder sceneRecorder(
*sceneDrawBackend,
context);
managedContextState.sceneRecorder = &sceneRecorder;
const uint64_t managedContextHandle =
RegisterManagedScriptableRenderContextState(managedContextState);
MonoObject* const managedContextObject =
m_runtime->CreateManagedScriptableRenderContext(managedContextHandle);
if (managedContextObject == nullptr) {
UnregisterManagedScriptableRenderContextState(managedContextHandle);
return false;
}
void* args[1] = { managedContextObject };
MonoObject* result = nullptr;
const bool invokeSucceeded = m_runtime->InvokeManagedMethod(
pipelineObject,
method,
args,
&result);
UnregisterManagedScriptableRenderContextState(managedContextHandle);
if (!invokeSucceeded) {
return false;
}
bool recorded = false;
if (!(TryUnboxManagedBoolean(result, recorded) && recorded)) {
return false;
}
return FlushManagedRasterPasses(
context,
managedContextState);
}
private:
bool IsRuntimeAlive() const {
return m_assetRuntime != nullptr &&
m_assetRuntime->IsRuntimeAlive() &&
m_runtime != nullptr;
}
MonoObject* GetManagedPipelineObject() const {
if (!IsRuntimeAlive()) {
return nullptr;
}
uint32_t pipelineHandle = 0;
if (!m_assetRuntime->AcquireManagedPipelineHandle(pipelineHandle) ||
pipelineHandle == 0) {
return nullptr;
}
if (pipelineHandle != m_resolvedPipelineHandle) {
m_supportsStageContextualMethod = nullptr;
m_supportsStageMethod = nullptr;
m_recordStageMethod = nullptr;
m_resolvedPipelineHandle = pipelineHandle;
}
return m_runtime->GetManagedObject(pipelineHandle);
}
MonoMethod* ResolveSupportsStageContextualMethod(
MonoObject* pipelineObject) const {
if (m_supportsStageContextualMethod == nullptr) {
m_supportsStageContextualMethod =
m_runtime->ResolveManagedMethod(
pipelineObject,
"SupportsStageRenderGraphContextual",
2);
}
return m_supportsStageContextualMethod;
}
MonoMethod* ResolveSupportsStageMethod(MonoObject* pipelineObject) const {
if (m_supportsStageMethod == nullptr) {
m_supportsStageMethod =
m_runtime->ResolveManagedMethod(
pipelineObject,
"SupportsStageRenderGraph",
1);
}
return m_supportsStageMethod;
}
MonoMethod* ResolveRecordStageMethod(MonoObject* pipelineObject) const {
if (m_recordStageMethod == nullptr) {
m_recordStageMethod =
m_runtime->ResolveManagedMethod(
pipelineObject,
"RecordStageRenderGraph",
1);
}
return m_recordStageMethod;
}
bool FlushManagedRasterPasses(
const Rendering::RenderPipelineStageRenderGraphContext& context,
const ManagedScriptableRenderContextState& managedContextState) {
if (managedContextState.rasterPassRequests.empty()) {
return true;
}
if (!Rendering::IsCameraFrameFullscreenSequenceStage(context.stage)) {
return false;
}
Rendering::RenderGraphTextureHandle currentSourceColor =
ResolveManagedScriptableRenderContextSourceColorTexture(
&managedContextState);
const Rendering::RenderGraphTextureHandle finalOutputColor =
ResolveManagedScriptableRenderContextPrimaryColorTarget(
&managedContextState);
if (!currentSourceColor.IsValid() ||
!finalOutputColor.IsValid()) {
return false;
}
for (size_t passIndex = 0u;
passIndex < managedContextState.rasterPassRequests.size();
++passIndex) {
const ManagedScriptableRenderContextState::RasterPassRecordRequest&
request = managedContextState.rasterPassRequests[passIndex];
Rendering::RenderPass* const pass =
ConfigureManagedFullscreenPass(
m_fullscreenPassPool,
passIndex,
request.passDesc);
if (pass == nullptr) {
return false;
}
const Containers::String resolvedPassName =
!request.passName.Empty()
? request.passName
: managedContextState.rasterPassRequests.size() == 1u
? context.passName
: Rendering::BuildRenderGraphSequencePassName(
context.passName,
passIndex);
const Rendering::RenderGraphTextureHandle resolvedSourceColor =
request.sourceColorTexture.IsValid()
? request.sourceColorTexture
: currentSourceColor;
std::vector<Rendering::RenderGraphTextureHandle>
resolvedColorTargets =
request.colorTargets;
if (!ResolveManagedPrimaryColorTarget(resolvedColorTargets)
.IsValid()) {
const bool isLastPass =
passIndex + 1u ==
managedContextState.rasterPassRequests.size();
const Rendering::RenderGraphTextureHandle resolvedOutputColor =
isLastPass
? finalOutputColor
: context.graphBuilder.CreateTransientTexture(
resolvedPassName + ".Color",
Rendering::BuildFullscreenTransientTextureDesc(
context.surfaceTemplate));
resolvedColorTargets = { resolvedOutputColor };
}
if (!RecordManagedFullscreenRasterPass(
context,
*pass,
resolvedSourceColor,
resolvedColorTargets,
request.readTextures,
request.readDepthTextures,
request.textureBindings,
request.depthTarget,
resolvedPassName)) {
return false;
}
currentSourceColor =
ResolveManagedPrimaryColorTarget(
resolvedColorTargets);
}
return true;
}
Rendering::SceneDrawBackend* ResolveSceneDrawBackend() {
if (m_boundSceneDrawBackend != nullptr) {
return m_boundSceneDrawBackend;
}
const bool useDefaultNativeBackend =
m_assetRuntime != nullptr &&
m_assetRuntime->GetPipelineRendererAssetPolicy() ==
Rendering::Pipelines::ManagedPipelineRendererAssetPolicy::
DefaultNativeBackend;
const std::shared_ptr<const Rendering::RenderPipelineAsset>
resolvedPipelineBackendAsset =
m_assetRuntime == nullptr
? nullptr
: useDefaultNativeBackend
? Rendering::Internal::CreateDefaultPipelineBackendAsset()
: m_assetRuntime->GetSharedPipelineBackendAsset();
if (resolvedPipelineBackendAsset == nullptr) {
return nullptr;
}
if (m_ownedSceneDrawBackend == nullptr ||
resolvedPipelineBackendAsset !=
m_ownedSharedPipelineBackendAsset) {
if (m_ownedSceneDrawBackend != nullptr) {
m_ownedSceneDrawBackend->Shutdown();
}
m_ownedSceneDrawBackend =
useDefaultNativeBackend
? Rendering::Internal::CreateDefaultSceneDrawBackend()
: Rendering::Internal::CreateSceneDrawBackendFromAsset(
resolvedPipelineBackendAsset);
m_ownedSharedPipelineBackendAsset =
resolvedPipelineBackendAsset;
}
return m_ownedSceneDrawBackend.get();
}
std::shared_ptr<const MonoManagedRenderPipelineAssetRuntime> m_assetRuntime;
MonoScriptRuntime* m_runtime = nullptr;
mutable MonoMethod* m_supportsStageContextualMethod = nullptr;
mutable MonoMethod* m_supportsStageMethod = nullptr;
mutable MonoMethod* m_recordStageMethod = nullptr;
mutable uint32_t m_resolvedPipelineHandle = 0;
std::vector<std::unique_ptr<Rendering::RenderPass>> m_fullscreenPassPool = {};
Rendering::SceneDrawBackend* m_boundSceneDrawBackend = nullptr;
std::shared_ptr<const Rendering::RenderPipelineAsset>
m_ownedSharedPipelineBackendAsset = nullptr;
std::unique_ptr<Rendering::SceneDrawBackend> m_ownedSceneDrawBackend =
nullptr;
};
std::unique_ptr<Rendering::RenderPipelineStageRecorder>
MonoManagedRenderPipelineAssetRuntime::CreateStageRecorder() const {
if (!IsRuntimeAlive() || !m_descriptor.IsValid()) {
return nullptr;
}
return std::make_unique<MonoManagedRenderPipelineStageRecorder>(
shared_from_this());
}
void MonoManagedRenderPipelineAssetRuntime::ConfigureCameraRenderRequest(
Rendering::CameraRenderRequest& request,
size_t renderedBaseCameraCount,
size_t renderedRequestCount,
const Rendering::DirectionalShadowPlanningSettings&
directionalShadowSettings) const {
if (!EnsureManagedAsset()) {
request.directionalShadow = {};
Rendering::ApplyDefaultRenderPipelineAssetCameraRenderRequestPolicy(
request,
renderedBaseCameraCount,
renderedRequestCount,
directionalShadowSettings);
return;
}
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const method =
ResolveConfigureCameraRenderRequestMethod(assetObject);
if (assetObject == nullptr || method == nullptr) {
request.directionalShadow = {};
Rendering::ApplyDefaultRenderPipelineAssetCameraRenderRequestPolicy(
request,
renderedBaseCameraCount,
renderedRequestCount,
directionalShadowSettings);
return;
}
ManagedCameraRenderRequestContextState requestContextState =
{};
requestContextState.request = &request;
requestContextState.renderedBaseCameraCount = renderedBaseCameraCount;
requestContextState.renderedRequestCount = renderedRequestCount;
requestContextState.directionalShadowPlanningSettings =
directionalShadowSettings;
const uint64_t requestContextHandle =
RegisterManagedCameraRenderRequestContextState(
requestContextState);
MonoObject* const requestContextObject =
m_runtime->CreateManagedCameraRenderRequestContext(
requestContextHandle);
if (requestContextObject == nullptr) {
UnregisterManagedCameraRenderRequestContextState(
requestContextHandle);
request.directionalShadow = {};
Rendering::ApplyDefaultRenderPipelineAssetCameraRenderRequestPolicy(
request,
renderedBaseCameraCount,
renderedRequestCount,
directionalShadowSettings);
return;
}
void* args[1] = { requestContextObject };
m_runtime->InvokeManagedMethod(
assetObject,
method,
args,
nullptr);
request.directionalShadow = {};
if (requestContextState.suppressDirectionalShadow) {
} else {
Rendering::ApplyDefaultRenderPipelineAssetCameraRenderRequestPolicy(
request,
renderedBaseCameraCount,
renderedRequestCount,
requestContextState.directionalShadowPlanningSettings);
}
UnregisterManagedCameraRenderRequestContextState(
requestContextHandle);
}
void MonoManagedRenderPipelineAssetRuntime::ConfigureCameraFramePlan(
Rendering::CameraFramePlan& plan) const {
if (!EnsureManagedAsset()) {
return;
}
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const method =
ResolveConfigureCameraFramePlanMethod(assetObject);
if (assetObject == nullptr || method == nullptr) {
return;
}
ManagedScriptableRenderPipelinePlanningContextState
planningContextState = {};
planningContextState.plan = &plan;
const uint64_t planningContextHandle =
RegisterManagedScriptableRenderPipelinePlanningContextState(
planningContextState);
MonoObject* const planningContextObject =
m_runtime->CreateManagedScriptableRenderPipelinePlanningContext(
planningContextHandle);
if (planningContextObject == nullptr) {
UnregisterManagedScriptableRenderPipelinePlanningContextState(
planningContextHandle);
return;
}
void* args[1] = { planningContextObject };
m_runtime->InvokeManagedMethod(
assetObject,
method,
args,
nullptr);
UnregisterManagedScriptableRenderPipelinePlanningContextState(
planningContextHandle);
}
bool MonoManagedRenderPipelineAssetRuntime::ConfigureRenderSceneSetup(
const Rendering::CameraFramePlan& plan,
Rendering::RenderSceneData& sceneData) const {
if (!EnsureManagedAsset()) {
return false;
}
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const method =
ResolveConfigureRenderSceneSetupMethod(assetObject);
if (assetObject == nullptr || method == nullptr) {
return false;
}
ManagedRenderSceneSetupContextState setupContextState = {};
setupContextState.plan = &plan;
setupContextState.sceneData = &sceneData;
const uint64_t setupContextHandle =
RegisterManagedRenderSceneSetupContextState(
setupContextState);
MonoObject* const setupContextObject =
m_runtime->CreateManagedRenderSceneSetupContext(
setupContextHandle);
if (setupContextObject == nullptr) {
UnregisterManagedRenderSceneSetupContextState(
setupContextHandle);
return false;
}
void* args[1] = { setupContextObject };
m_runtime->InvokeManagedMethod(
assetObject,
method,
args,
nullptr);
UnregisterManagedRenderSceneSetupContextState(
setupContextHandle);
return setupContextState.explicitlyConfigured;
}
bool MonoManagedRenderPipelineAssetRuntime::
ConfigureDirectionalShadowExecutionState(
const Rendering::CameraFramePlan& plan,
const Rendering::DirectionalShadowSurfaceAllocation&
shadowAllocation,
Rendering::DirectionalShadowExecutionState& shadowState) const {
if (!EnsureManagedAsset()) {
return false;
}
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const method =
ResolveConfigureDirectionalShadowExecutionStateMethod(
assetObject);
if (assetObject == nullptr || method == nullptr) {
return false;
}
ManagedDirectionalShadowExecutionContextState executionState =
{};
executionState.plan = &plan;
executionState.shadowAllocation = &shadowAllocation;
executionState.shadowState = &shadowState;
const uint64_t executionContextHandle =
RegisterManagedDirectionalShadowExecutionContextState(
executionState);
MonoObject* const executionContextObject =
m_runtime->CreateManagedDirectionalShadowExecutionContext(
executionContextHandle);
if (executionContextObject == nullptr) {
UnregisterManagedDirectionalShadowExecutionContextState(
executionContextHandle);
return false;
}
void* args[1] = { executionContextObject };
m_runtime->InvokeManagedMethod(
assetObject,
method,
args,
nullptr);
UnregisterManagedDirectionalShadowExecutionContextState(
executionContextHandle);
return executionState.explicitlyConfigured;
}
bool MonoManagedRenderPipelineAssetRuntime::TryGetDefaultFinalColorSettings(
Rendering::FinalColorSettings& settings) const {
settings = {};
settings.exposureValue = 1.0f;
settings.finalColorScale = XCEngine::Math::Vector4::One();
if (!EnsureManagedAsset()) {
return false;
}
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const method =
ResolveGetDefaultFinalColorSettingsMethod(assetObject);
if (assetObject == nullptr || method == nullptr) {
return false;
}
MonoObject* managedSettings = nullptr;
if (!m_runtime->InvokeManagedMethod(
assetObject,
method,
nullptr,
&managedSettings)) {
return false;
}
return TryUnboxManagedFinalColorSettings(
managedSettings,
settings);
}
std::shared_ptr<const Rendering::RenderPipelineAsset>
MonoManagedRenderPipelineAssetRuntime::GetPipelineRendererAsset() const {
if (!SyncManagedAssetRuntimeState()) {
return nullptr;
}
// Current Mono-backed SRP assets do not materialize a shared native
// backend asset. They bind the engine default native backend explicitly
// through DefaultNativeBackend.
return nullptr;
}
Rendering::Pipelines::ManagedPipelineRendererAssetPolicy
MonoManagedRenderPipelineAssetRuntime::GetPipelineRendererAssetPolicy() const {
return SyncManagedAssetRuntimeState()
? Rendering::Pipelines::ManagedPipelineRendererAssetPolicy::DefaultNativeBackend
: Rendering::Pipelines::ManagedPipelineRendererAssetPolicy::Unspecified;
}
bool MonoManagedRenderPipelineAssetRuntime::AcquireManagedPipelineHandle(
uint32_t& outPipelineHandle) const {
if (!SyncManagedAssetRuntimeState()) {
outPipelineHandle = 0;
return false;
}
if (m_pipelineHandle != 0) {
outPipelineHandle = m_pipelineHandle;
return true;
}
if (m_pipelineCreationAttempted) {
outPipelineHandle = 0;
return false;
}
m_pipelineCreationAttempted = true;
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const createPipelineMethod =
ResolveCreatePipelineMethod(assetObject);
if (assetObject == nullptr || createPipelineMethod == nullptr) {
outPipelineHandle = 0;
return false;
}
MonoObject* pipelineObject = nullptr;
if (!m_runtime->InvokeManagedMethod(
assetObject,
createPipelineMethod,
nullptr,
&pipelineObject) ||
pipelineObject == nullptr) {
outPipelineHandle = 0;
return false;
}
if (!IsMonoClassOrSubclass(
mono_object_get_class(pipelineObject),
m_runtime->m_scriptableRenderPipelineClass)) {
m_runtime->SetError(
"Managed render pipeline asset returned a non-ScriptableRenderPipeline instance: " +
m_descriptor.GetFullName() + ".");
outPipelineHandle = 0;
return false;
}
m_pipelineHandle = m_runtime->RetainExternalManagedObject(pipelineObject);
outPipelineHandle = m_pipelineHandle;
return m_pipelineHandle != 0;
}
bool MonoManagedRenderPipelineAssetRuntime::EnsureManagedAsset() const {
if (m_assetHandle != 0) {
return true;
}
if (m_assetCreationAttempted || !IsRuntimeAlive() || !m_descriptor.IsValid()) {
return false;
}
m_assetCreationAttempted = true;
if (m_descriptor.HasManagedAssetHandle()) {
MonoObject* const assetObject =
m_runtime->GetExternalManagedObject(
m_descriptor.managedAssetHandle);
MonoClass* const assetClass =
assetObject != nullptr
? mono_object_get_class(assetObject)
: nullptr;
if (assetClass == nullptr) {
m_runtime->SetError(
"Managed render pipeline asset handle is no longer valid: " +
m_descriptor.GetFullName() + ".");
return false;
}
if (!IsMonoClassOrSubclass(
assetClass,
m_runtime->m_scriptableRenderPipelineAssetClass)) {
m_runtime->SetError(
"Managed render pipeline asset must derive from ScriptableRenderPipelineAsset: " +
m_descriptor.GetFullName() + ".");
return false;
}
m_assetHandle = m_descriptor.managedAssetHandle;
m_ownsManagedAssetHandle = false;
return true;
}
MonoClass* assetClass = nullptr;
if (!m_runtime->ResolveManagedClass(
m_descriptor.assemblyName,
m_descriptor.namespaceName,
m_descriptor.className,
assetClass) ||
assetClass == nullptr) {
return false;
}
if (!IsMonoClassOrSubclass(
assetClass,
m_runtime->m_scriptableRenderPipelineAssetClass)) {
m_runtime->SetError(
"Managed render pipeline asset must derive from ScriptableRenderPipelineAsset: " +
m_descriptor.GetFullName() + ".");
return false;
}
m_ownsManagedAssetHandle =
m_runtime->CreateExternalManagedObject(assetClass, m_assetHandle) &&
m_assetHandle != 0;
return m_ownsManagedAssetHandle;
}
bool MonoManagedRenderPipelineAssetRuntime::SyncManagedAssetRuntimeState() const {
if (!EnsureManagedAsset()) {
return false;
}
int32_t runtimeResourceVersion = 0;
if (!TryGetManagedRuntimeResourceVersion(runtimeResourceVersion)) {
return false;
}
if (!m_runtimeResourceVersionResolved) {
m_runtimeResourceVersion = runtimeResourceVersion;
m_runtimeResourceVersionResolved = true;
return true;
}
if (runtimeResourceVersion == m_runtimeResourceVersion) {
return true;
}
ReleaseManagedPipeline();
m_runtimeResourceVersion = runtimeResourceVersion;
return true;
}
bool MonoManagedRenderPipelineAssetRuntime::TryGetManagedRuntimeResourceVersion(
int32_t& outVersion) const {
outVersion = 0;
if (!EnsureManagedAsset()) {
return false;
}
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const method =
ResolveGetRuntimeResourceVersionMethod(assetObject);
if (assetObject == nullptr || method == nullptr) {
return false;
}
MonoObject* managedVersion = nullptr;
if (!m_runtime->InvokeManagedMethod(
assetObject,
method,
nullptr,
&managedVersion)) {
return false;
}
return TryUnboxManagedInt32(managedVersion, outVersion);
}
void MonoManagedRenderPipelineAssetRuntime::ReleaseManagedPipeline() const {
m_pipelineCreationAttempted = false;
m_disposePipelineMethod = nullptr;
if (!IsRuntimeAlive()) {
m_pipelineHandle = 0;
return;
}
if (m_pipelineHandle != 0) {
MonoObject* const pipelineObject =
m_runtime->GetManagedObject(m_pipelineHandle);
MonoMethod* const disposeMethod =
ResolveDisposePipelineMethod(pipelineObject);
if (pipelineObject != nullptr && disposeMethod != nullptr) {
m_runtime->InvokeManagedMethod(
pipelineObject,
disposeMethod,
nullptr,
nullptr);
}
m_runtime->DestroyExternalManagedObject(m_pipelineHandle);
m_pipelineHandle = 0;
}
}
void MonoManagedRenderPipelineAssetRuntime::ReleaseManagedAsset() const {
ReleaseManagedPipeline();
m_releaseRuntimeResourcesMethod = nullptr;
m_createPipelineMethod = nullptr;
m_configureCameraRenderRequestMethod = nullptr;
m_configureCameraFramePlanMethod = nullptr;
m_getDefaultFinalColorSettingsMethod = nullptr;
m_getRuntimeResourceVersionMethod = nullptr;
m_configureRenderSceneSetupMethod = nullptr;
m_configureDirectionalShadowExecutionStateMethod = nullptr;
m_runtimeResourceVersionResolved = false;
m_runtimeResourceVersion = 0;
const bool ownsManagedAssetHandle = m_ownsManagedAssetHandle;
m_ownsManagedAssetHandle = false;
m_assetCreationAttempted = false;
if (!IsRuntimeAlive()) {
m_assetHandle = 0;
return;
}
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const releaseRuntimeResourcesMethod =
ResolveReleaseRuntimeResourcesMethod(assetObject);
if (assetObject != nullptr && releaseRuntimeResourcesMethod != nullptr) {
m_runtime->InvokeManagedMethod(
assetObject,
releaseRuntimeResourcesMethod,
nullptr,
nullptr);
}
if (m_assetHandle != 0 && ownsManagedAssetHandle) {
m_runtime->DestroyExternalManagedObject(m_assetHandle);
}
m_assetHandle = 0;
}
MonoObject* MonoManagedRenderPipelineAssetRuntime::GetManagedAssetObject() const {
return m_assetHandle != 0
? m_runtime->GetManagedObject(m_assetHandle)
: nullptr;
}
MonoMethod* MonoManagedRenderPipelineAssetRuntime::ResolveDisposePipelineMethod(
MonoObject* pipelineObject) const {
if (m_disposePipelineMethod == nullptr) {
m_disposePipelineMethod =
m_runtime->ResolveManagedMethod(
pipelineObject,
"DisposeInstance",
0);
}
return m_disposePipelineMethod;
}
MonoMethod* MonoManagedRenderPipelineAssetRuntime::ResolveCreatePipelineMethod(
MonoObject* assetObject) const {
if (m_createPipelineMethod == nullptr) {
m_createPipelineMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"CreatePipeline",
0);
}
return m_createPipelineMethod;
}
MonoMethod*
MonoManagedRenderPipelineAssetRuntime::ResolveConfigureCameraRenderRequestMethod(
MonoObject* assetObject) const {
if (m_configureCameraRenderRequestMethod == nullptr) {
m_configureCameraRenderRequestMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"ConfigureCameraRenderRequest",
1);
}
return m_configureCameraRenderRequestMethod;
}
MonoMethod*
MonoManagedRenderPipelineAssetRuntime::ResolveConfigureCameraFramePlanMethod(
MonoObject* assetObject) const {
if (m_configureCameraFramePlanMethod == nullptr) {
m_configureCameraFramePlanMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"ConfigureCameraFramePlanInstance",
1);
}
return m_configureCameraFramePlanMethod;
}
MonoMethod*
MonoManagedRenderPipelineAssetRuntime::ResolveGetDefaultFinalColorSettingsMethod(
MonoObject* assetObject) const {
if (m_getDefaultFinalColorSettingsMethod == nullptr) {
m_getDefaultFinalColorSettingsMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"GetDefaultFinalColorSettings",
0);
}
return m_getDefaultFinalColorSettingsMethod;
}
MonoMethod*
MonoManagedRenderPipelineAssetRuntime::ResolveGetRuntimeResourceVersionMethod(
MonoObject* assetObject) const {
if (m_getRuntimeResourceVersionMethod == nullptr) {
m_getRuntimeResourceVersionMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"GetRuntimeResourceVersionInstance",
0);
}
return m_getRuntimeResourceVersionMethod;
}
MonoMethod*
MonoManagedRenderPipelineAssetRuntime::
ResolveConfigureRenderSceneSetupMethod(
MonoObject* assetObject) const {
if (m_configureRenderSceneSetupMethod == nullptr) {
m_configureRenderSceneSetupMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"ConfigureRenderSceneSetupInstance",
1);
}
return m_configureRenderSceneSetupMethod;
}
MonoMethod*
MonoManagedRenderPipelineAssetRuntime::
ResolveConfigureDirectionalShadowExecutionStateMethod(
MonoObject* assetObject) const {
if (m_configureDirectionalShadowExecutionStateMethod ==
nullptr) {
m_configureDirectionalShadowExecutionStateMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"ConfigureDirectionalShadowExecutionStateInstance",
1);
}
return m_configureDirectionalShadowExecutionStateMethod;
}
MonoMethod*
MonoManagedRenderPipelineAssetRuntime::ResolveReleaseRuntimeResourcesMethod(
MonoObject* assetObject) const {
if (m_releaseRuntimeResourcesMethod == nullptr) {
m_releaseRuntimeResourcesMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"ReleaseRuntimeResourcesInstance",
0);
}
return m_releaseRuntimeResourcesMethod;
}
class MonoManagedRenderPipelineBridge final
: public Rendering::Pipelines::ManagedRenderPipelineBridge {
public:
MonoManagedRenderPipelineBridge(
MonoScriptRuntime* runtime,
std::weak_ptr<void> runtimeLifetime)
: m_runtime(runtime)
, m_runtimeLifetime(std::move(runtimeLifetime)) {
}
std::shared_ptr<const Rendering::Pipelines::ManagedRenderPipelineAssetRuntime>
CreateAssetRuntime(
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& descriptor)
const override {
if (!IsRuntimeAlive() || !descriptor.IsValid()) {
return nullptr;
}
return std::make_shared<MonoManagedRenderPipelineAssetRuntime>(
m_runtime,
m_runtimeLifetime,
descriptor);
}
private:
bool IsRuntimeAlive() const {
return m_runtime != nullptr &&
!m_runtimeLifetime.expired() &&
m_runtime->m_initialized;
}
MonoScriptRuntime* m_runtime = nullptr;
std::weak_ptr<void> m_runtimeLifetime;
};
namespace {
ManagedComponentTypeInfo ResolveManagedComponentTypeInfo(MonoClass* monoClass) {
ManagedComponentTypeInfo typeInfo;
if (!monoClass) {
return typeInfo;
}
typeInfo.monoClass = monoClass;
typeInfo.namespaceName = SafeString(mono_class_get_namespace(monoClass));
typeInfo.className = SafeString(mono_class_get_name(monoClass));
if (typeInfo.namespaceName == "XCEngine" && typeInfo.className == "Transform") {
typeInfo.kind = ManagedComponentKind::Transform;
return typeInfo;
}
if (typeInfo.namespaceName == "XCEngine" && typeInfo.className == "Rigidbody") {
typeInfo.kind = ManagedComponentKind::Rigidbody;
return typeInfo;
}
if (typeInfo.namespaceName == "XCEngine" && typeInfo.className == "Camera") {
typeInfo.kind = ManagedComponentKind::Camera;
return typeInfo;
}
if (typeInfo.namespaceName == "XCEngine" && typeInfo.className == "Light") {
typeInfo.kind = ManagedComponentKind::Light;
return typeInfo;
}
if (typeInfo.namespaceName == "XCEngine" && typeInfo.className == "MeshFilter") {
typeInfo.kind = ManagedComponentKind::MeshFilter;
return typeInfo;
}
if (typeInfo.namespaceName == "XCEngine" && typeInfo.className == "MeshRenderer") {
typeInfo.kind = ManagedComponentKind::MeshRenderer;
return typeInfo;
}
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
if (runtime
&& runtime->IsClassAvailable(
runtime->GetSettings().appAssemblyName,
typeInfo.namespaceName,
typeInfo.className)) {
typeInfo.kind = ManagedComponentKind::Script;
typeInfo.assemblyName = runtime->GetSettings().appAssemblyName;
}
return typeInfo;
}
ManagedComponentTypeInfo ResolveManagedComponentTypeInfo(MonoReflectionType* reflectionType) {
if (!reflectionType) {
return {};
}
MonoType* monoType = mono_reflection_type_get_type(reflectionType);
if (!monoType) {
return {};
}
return ResolveManagedComponentTypeInfo(mono_class_from_mono_type(monoType));
}
Components::GameObject* FindGameObjectByUUIDRecursive(Components::GameObject* gameObject, uint64_t uuid) {
if (!gameObject) {
return nullptr;
}
if (gameObject->GetUUID() == uuid) {
return gameObject;
}
for (Components::GameObject* child : gameObject->GetChildren()) {
if (Components::GameObject* found = FindGameObjectByUUIDRecursive(child, uuid)) {
return found;
}
}
return nullptr;
}
ScriptComponent* FindScriptComponentByUUIDRecursive(Components::GameObject* gameObject, uint64_t scriptComponentUUID) {
if (!gameObject || scriptComponentUUID == 0) {
return nullptr;
}
for (ScriptComponent* component : gameObject->GetComponents<ScriptComponent>()) {
if (component && component->GetScriptComponentUUID() == scriptComponentUUID) {
return component;
}
}
for (Components::GameObject* child : gameObject->GetChildren()) {
if (ScriptComponent* found = FindScriptComponentByUUIDRecursive(child, scriptComponentUUID)) {
return found;
}
}
return nullptr;
}
Components::GameObject* FindGameObjectByUUID(uint64_t uuid) {
Components::Scene* scene = GetInternalCallScene();
if (!scene || uuid == 0) {
return nullptr;
}
for (Components::GameObject* root : scene->GetRootGameObjects()) {
if (Components::GameObject* found = FindGameObjectByUUIDRecursive(root, uuid)) {
return found;
}
}
return nullptr;
}
ScriptComponent* FindScriptComponentByUUID(uint64_t scriptComponentUUID) {
Components::Scene* scene = GetInternalCallScene();
if (!scene || scriptComponentUUID == 0) {
return nullptr;
}
for (Components::GameObject* root : scene->GetRootGameObjects()) {
if (ScriptComponent* found = FindScriptComponentByUUIDRecursive(root, scriptComponentUUID)) {
return found;
}
}
return nullptr;
}
Components::Component* FindNativeComponent(Components::GameObject* gameObject, ManagedComponentKind componentKind) {
if (!gameObject) {
return nullptr;
}
switch (componentKind) {
case ManagedComponentKind::Transform:
return gameObject->GetTransform();
case ManagedComponentKind::Rigidbody:
return gameObject->GetComponent<Components::RigidbodyComponent>();
case ManagedComponentKind::Camera:
return gameObject->GetComponent<Components::CameraComponent>();
case ManagedComponentKind::Light:
return gameObject->GetComponent<Components::LightComponent>();
case ManagedComponentKind::MeshFilter:
return gameObject->GetComponent<Components::MeshFilterComponent>();
case ManagedComponentKind::MeshRenderer:
return gameObject->GetComponent<Components::MeshRendererComponent>();
case ManagedComponentKind::Script:
case ManagedComponentKind::Unknown:
return nullptr;
}
return nullptr;
}
bool HasNativeComponent(Components::GameObject* gameObject, ManagedComponentKind componentKind) {
return FindNativeComponent(gameObject, componentKind) != nullptr;
}
bool IsMatchingScriptComponent(const ScriptComponent* component, const ManagedComponentTypeInfo& typeInfo) {
return component
&& component->HasScriptClass()
&& typeInfo.kind == ManagedComponentKind::Script
&& component->GetAssemblyName() == typeInfo.assemblyName
&& component->GetNamespaceName() == typeInfo.namespaceName
&& component->GetClassName() == typeInfo.className;
}
Components::Component* AddOrGetNativeComponent(Components::GameObject* gameObject, ManagedComponentKind componentKind) {
if (!gameObject) {
return nullptr;
}
switch (componentKind) {
case ManagedComponentKind::Transform:
return gameObject->GetTransform();
case ManagedComponentKind::Rigidbody:
return gameObject->GetComponent<Components::RigidbodyComponent>()
? static_cast<Components::Component*>(gameObject->GetComponent<Components::RigidbodyComponent>())
: static_cast<Components::Component*>(gameObject->AddComponent<Components::RigidbodyComponent>());
case ManagedComponentKind::Camera:
return gameObject->GetComponent<Components::CameraComponent>()
? static_cast<Components::Component*>(gameObject->GetComponent<Components::CameraComponent>())
: static_cast<Components::Component*>(gameObject->AddComponent<Components::CameraComponent>());
case ManagedComponentKind::Light:
return gameObject->GetComponent<Components::LightComponent>()
? static_cast<Components::Component*>(gameObject->GetComponent<Components::LightComponent>())
: static_cast<Components::Component*>(gameObject->AddComponent<Components::LightComponent>());
case ManagedComponentKind::MeshFilter:
return gameObject->GetComponent<Components::MeshFilterComponent>()
? static_cast<Components::Component*>(gameObject->GetComponent<Components::MeshFilterComponent>())
: static_cast<Components::Component*>(gameObject->AddComponent<Components::MeshFilterComponent>());
case ManagedComponentKind::MeshRenderer:
return gameObject->GetComponent<Components::MeshRendererComponent>()
? static_cast<Components::Component*>(gameObject->GetComponent<Components::MeshRendererComponent>())
: static_cast<Components::Component*>(gameObject->AddComponent<Components::MeshRendererComponent>());
case ManagedComponentKind::Script:
case ManagedComponentKind::Unknown:
return nullptr;
}
return nullptr;
}
ScriptComponent* FindMatchingScriptComponent(
Components::GameObject* gameObject,
const ManagedComponentTypeInfo& typeInfo) {
if (!gameObject || typeInfo.kind != ManagedComponentKind::Script) {
return nullptr;
}
for (ScriptComponent* component : gameObject->GetComponents<ScriptComponent>()) {
if (IsMatchingScriptComponent(component, typeInfo)) {
return component;
}
}
return nullptr;
}
ScriptComponent* FindMatchingScriptComponentInChildren(
Components::GameObject* gameObject,
const ManagedComponentTypeInfo& typeInfo) {
if (!gameObject) {
return nullptr;
}
if (ScriptComponent* component = FindMatchingScriptComponent(gameObject, typeInfo)) {
return component;
}
for (Components::GameObject* child : gameObject->GetChildren()) {
if (ScriptComponent* component = FindMatchingScriptComponentInChildren(child, typeInfo)) {
return component;
}
}
return nullptr;
}
ScriptComponent* FindMatchingScriptComponentInParent(
Components::GameObject* gameObject,
const ManagedComponentTypeInfo& typeInfo) {
while (gameObject) {
if (ScriptComponent* component = FindMatchingScriptComponent(gameObject, typeInfo)) {
return component;
}
gameObject = gameObject->GetParent();
}
return nullptr;
}
Components::Component* FindNativeComponentInChildren(
Components::GameObject* gameObject,
ManagedComponentKind componentKind) {
if (!gameObject) {
return nullptr;
}
if (Components::Component* component = FindNativeComponent(gameObject, componentKind)) {
return component;
}
for (Components::GameObject* child : gameObject->GetChildren()) {
if (Components::Component* component = FindNativeComponentInChildren(child, componentKind)) {
return component;
}
}
return nullptr;
}
Components::Component* FindNativeComponentInParent(
Components::GameObject* gameObject,
ManagedComponentKind componentKind) {
while (gameObject) {
if (Components::Component* component = FindNativeComponent(gameObject, componentKind)) {
return component;
}
gameObject = gameObject->GetParent();
}
return nullptr;
}
bool DestroyNativeComponentInstance(Components::GameObject* gameObject, Components::Component* component) {
if (!gameObject || !component || component == gameObject->GetTransform()) {
return false;
}
if (component->IsEnabled() && gameObject->IsActiveInHierarchy()) {
component->OnDisable();
}
component->OnDestroy();
return gameObject->RemoveComponent(component);
}
Components::CameraComponent* FindCameraComponent(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return gameObject ? gameObject->GetComponent<Components::CameraComponent>() : nullptr;
}
Components::LightComponent* FindLightComponent(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return gameObject ? gameObject->GetComponent<Components::LightComponent>() : nullptr;
}
Components::MeshFilterComponent* FindMeshFilterComponent(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return gameObject ? gameObject->GetComponent<Components::MeshFilterComponent>() : nullptr;
}
Components::MeshRendererComponent* FindMeshRendererComponent(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return gameObject ? gameObject->GetComponent<Components::MeshRendererComponent>() : nullptr;
}
Components::RigidbodyComponent* FindRigidbodyComponent(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return gameObject ? gameObject->GetComponent<Components::RigidbodyComponent>() : nullptr;
}
Components::Space ResolveManagedSpace(int32_t value) {
return value == static_cast<int32_t>(Components::Space::World)
? Components::Space::World
: Components::Space::Self;
}
Physics::PhysicsBodyType ResolveManagedPhysicsBodyType(int32_t value) {
switch (value) {
case static_cast<int32_t>(Physics::PhysicsBodyType::Static):
return Physics::PhysicsBodyType::Static;
case static_cast<int32_t>(Physics::PhysicsBodyType::Kinematic):
return Physics::PhysicsBodyType::Kinematic;
case static_cast<int32_t>(Physics::PhysicsBodyType::Dynamic):
default:
return Physics::PhysicsBodyType::Dynamic;
}
}
Physics::PhysicsForceMode ResolveManagedForceMode(int32_t value) {
switch (value) {
case static_cast<int32_t>(Physics::PhysicsForceMode::Acceleration):
return Physics::PhysicsForceMode::Acceleration;
case static_cast<int32_t>(Physics::PhysicsForceMode::Impulse):
return Physics::PhysicsForceMode::Impulse;
case static_cast<int32_t>(Physics::PhysicsForceMode::VelocityChange):
return Physics::PhysicsForceMode::VelocityChange;
case static_cast<int32_t>(Physics::PhysicsForceMode::Force):
default:
return Physics::PhysicsForceMode::Force;
}
}
Physics::PhysicsWorld* FindRuntimePhysicsWorld() {
return ScriptEngine::Get().GetRuntimePhysicsWorld();
}
MonoArray* CreateManagedComponentArray(MonoClass* componentClass, const std::vector<MonoObject*>& components) {
if (!componentClass) {
return nullptr;
}
MonoDomain* domain = mono_domain_get();
if (!domain) {
return nullptr;
}
MonoArray* array = mono_array_new(domain, componentClass, static_cast<uintptr_t>(components.size()));
if (!array) {
return nullptr;
}
for (uintptr_t index = 0; index < components.size(); ++index) {
mono_array_setref(array, index, components[index]);
}
return array;
}
void LogManagedMessage(
XCEngine::Debug::LogLevel level,
MonoString* message,
MonoString* file,
int32_t line,
MonoString* member) {
const std::string messageText = MonoStringToUtf8(message);
const std::string fileText = MonoStringToUtf8(file);
const std::string memberText = MonoStringToUtf8(member);
XCEngine::Debug::Logger::Get().Log(
level,
XCEngine::Debug::LogCategory::Scripting,
XCEngine::Containers::String(messageText.c_str()),
fileText.c_str(),
line,
memberText.c_str());
}
void InternalCall_Debug_Log(MonoString* message, MonoString* file, int32_t line, MonoString* member) {
LogManagedMessage(XCEngine::Debug::LogLevel::Info, message, file, line, member);
}
void InternalCall_Debug_LogWarning(MonoString* message, MonoString* file, int32_t line, MonoString* member) {
LogManagedMessage(XCEngine::Debug::LogLevel::Warning, message, file, line, member);
}
void InternalCall_Debug_LogError(MonoString* message, MonoString* file, int32_t line, MonoString* member) {
LogManagedMessage(XCEngine::Debug::LogLevel::Error, message, file, line, member);
}
float InternalCall_Time_GetDeltaTime() {
return GetInternalCallDeltaTime();
}
float InternalCall_Time_GetFixedDeltaTime() {
return ScriptEngine::Get().GetRuntimeFixedDeltaTime();
}
mono_bool InternalCall_Input_GetKey(int32_t keyCode) {
return XCEngine::Input::InputManager::Get().IsKeyDown(
static_cast<XCEngine::Input::KeyCode>(keyCode)) ? 1 : 0;
}
mono_bool InternalCall_Input_GetKeyDown(int32_t keyCode) {
return XCEngine::Input::InputManager::Get().IsKeyPressed(
static_cast<XCEngine::Input::KeyCode>(keyCode)) ? 1 : 0;
}
mono_bool InternalCall_Input_GetKeyUp(int32_t keyCode) {
return XCEngine::Input::InputManager::Get().IsKeyReleased(
static_cast<XCEngine::Input::KeyCode>(keyCode)) ? 1 : 0;
}
mono_bool InternalCall_Input_GetMouseButton(int32_t button) {
return XCEngine::Input::InputManager::Get().IsMouseButtonDown(
static_cast<XCEngine::Input::MouseButton>(button)) ? 1 : 0;
}
mono_bool InternalCall_Input_GetMouseButtonDown(int32_t button) {
return XCEngine::Input::InputManager::Get().IsMouseButtonClicked(
static_cast<XCEngine::Input::MouseButton>(button)) ? 1 : 0;
}
mono_bool InternalCall_Input_GetMouseButtonUp(int32_t button) {
return XCEngine::Input::InputManager::Get().IsMouseButtonReleased(
static_cast<XCEngine::Input::MouseButton>(button)) ? 1 : 0;
}
mono_bool InternalCall_Input_GetButton(MonoString* buttonName) {
return XCEngine::Input::InputManager::Get().GetButton(
XCEngine::Containers::String(MonoStringToUtf8(buttonName).c_str())) ? 1 : 0;
}
mono_bool InternalCall_Input_GetButtonDown(MonoString* buttonName) {
return XCEngine::Input::InputManager::Get().GetButtonDown(
XCEngine::Containers::String(MonoStringToUtf8(buttonName).c_str())) ? 1 : 0;
}
mono_bool InternalCall_Input_GetButtonUp(MonoString* buttonName) {
return XCEngine::Input::InputManager::Get().GetButtonUp(
XCEngine::Containers::String(MonoStringToUtf8(buttonName).c_str())) ? 1 : 0;
}
float InternalCall_Input_GetAxis(MonoString* axisName) {
return XCEngine::Input::InputManager::Get().GetAxis(
XCEngine::Containers::String(MonoStringToUtf8(axisName).c_str()));
}
float InternalCall_Input_GetAxisRaw(MonoString* axisName) {
return XCEngine::Input::InputManager::Get().GetAxisRaw(
XCEngine::Containers::String(MonoStringToUtf8(axisName).c_str()));
}
mono_bool InternalCall_Input_GetAnyKey() {
return XCEngine::Input::InputManager::Get().IsAnyKeyDown() ? 1 : 0;
}
mono_bool InternalCall_Input_GetAnyKeyDown() {
return XCEngine::Input::InputManager::Get().IsAnyKeyPressed() ? 1 : 0;
}
void InternalCall_Input_GetMousePosition(XCEngine::Math::Vector3* outPosition) {
if (!outPosition) {
return;
}
const XCEngine::Math::Vector2 position = XCEngine::Input::InputManager::Get().GetMousePosition();
*outPosition = XCEngine::Math::Vector3(position.x, position.y, 0.0f);
}
void InternalCall_Input_GetMouseScrollDelta(XCEngine::Math::Vector2* outDelta) {
if (!outDelta) {
return;
}
*outDelta = XCEngine::Math::Vector2(
0.0f,
XCEngine::Input::InputManager::Get().GetMouseScrollDelta());
}
MonoString* InternalCall_GameObject_GetName(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return mono_string_new(
mono_domain_get(),
gameObject ? gameObject->GetName().c_str() : "");
}
void InternalCall_GameObject_SetName(uint64_t gameObjectUUID, MonoString* name) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return;
}
gameObject->SetName(MonoStringToUtf8(name));
}
MonoString* InternalCall_GameObject_GetTag(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return mono_string_new(
mono_domain_get(),
gameObject ? gameObject->GetTag().c_str() : "");
}
void InternalCall_GameObject_SetTag(uint64_t gameObjectUUID, MonoString* tag) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return;
}
gameObject->SetTag(MonoStringToUtf8(tag));
}
mono_bool InternalCall_GameObject_CompareTag(uint64_t gameObjectUUID, MonoString* tag) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return (gameObject && gameObject->CompareTag(MonoStringToUtf8(tag))) ? 1 : 0;
}
int32_t InternalCall_GameObject_GetLayer(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return gameObject ? static_cast<int32_t>(gameObject->GetLayer()) : 0;
}
void InternalCall_GameObject_SetLayer(uint64_t gameObjectUUID, int32_t layer) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return;
}
gameObject->SetLayer(static_cast<uint8_t>(std::clamp(layer, 0, 31)));
}
mono_bool InternalCall_GameObject_GetActiveSelf(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return (gameObject && gameObject->IsActive()) ? 1 : 0;
}
mono_bool InternalCall_GameObject_GetActiveInHierarchy(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return (gameObject && gameObject->IsActiveInHierarchy()) ? 1 : 0;
}
void InternalCall_GameObject_SetActive(uint64_t gameObjectUUID, mono_bool active) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return;
}
gameObject->SetActive(active != 0);
}
mono_bool InternalCall_GameObject_HasComponent(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(componentType);
if (typeInfo.kind == ManagedComponentKind::Script) {
return FindMatchingScriptComponent(gameObject, typeInfo) ? 1 : 0;
}
return HasNativeComponent(gameObject, typeInfo.kind) ? 1 : 0;
}
MonoObject* InternalCall_GameObject_GetComponent(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return nullptr;
}
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
if (!runtime) {
return nullptr;
}
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(componentType);
if (typeInfo.kind == ManagedComponentKind::Script) {
ScriptComponent* component = FindMatchingScriptComponent(gameObject, typeInfo);
if (!component) {
return nullptr;
}
if (!runtime->HasManagedInstance(component)) {
ScriptEngine::Get().OnScriptComponentEnabled(component);
}
return runtime->GetManagedInstanceObject(component);
}
if (!HasNativeComponent(gameObject, typeInfo.kind) || !typeInfo.monoClass) {
return nullptr;
}
return runtime->CreateManagedComponentWrapper(typeInfo.monoClass, gameObjectUUID);
}
MonoArray* InternalCall_GameObject_GetComponents(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return nullptr;
}
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
if (!runtime) {
return nullptr;
}
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(componentType);
if (!typeInfo.monoClass) {
return nullptr;
}
std::vector<MonoObject*> managedComponents;
auto appendNativeComponents = [&](const auto& nativeComponents) {
for (const auto* component : nativeComponents) {
if (!component || !component->GetGameObject()) {
continue;
}
if (MonoObject* managedObject =
runtime->CreateManagedComponentWrapper(typeInfo.monoClass, component->GetGameObject()->GetUUID())) {
managedComponents.push_back(managedObject);
}
}
};
switch (typeInfo.kind) {
case ManagedComponentKind::Script:
for (ScriptComponent* component : gameObject->GetComponents<ScriptComponent>()) {
if (!IsMatchingScriptComponent(component, typeInfo)) {
continue;
}
if (!runtime->HasManagedInstance(component)) {
ScriptEngine::Get().OnScriptComponentEnabled(component);
}
if (MonoObject* managedObject = runtime->GetManagedInstanceObject(component)) {
managedComponents.push_back(managedObject);
}
}
break;
case ManagedComponentKind::Transform:
appendNativeComponents(gameObject->GetComponents<Components::TransformComponent>());
break;
case ManagedComponentKind::Rigidbody:
appendNativeComponents(gameObject->GetComponents<Components::RigidbodyComponent>());
break;
case ManagedComponentKind::Camera:
appendNativeComponents(gameObject->GetComponents<Components::CameraComponent>());
break;
case ManagedComponentKind::Light:
appendNativeComponents(gameObject->GetComponents<Components::LightComponent>());
break;
case ManagedComponentKind::MeshFilter:
appendNativeComponents(gameObject->GetComponents<Components::MeshFilterComponent>());
break;
case ManagedComponentKind::MeshRenderer:
appendNativeComponents(gameObject->GetComponents<Components::MeshRendererComponent>());
break;
case ManagedComponentKind::Unknown:
return nullptr;
}
return CreateManagedComponentArray(typeInfo.monoClass, managedComponents);
}
MonoObject* InternalCall_GameObject_GetComponentInChildren(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return nullptr;
}
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
if (!runtime) {
return nullptr;
}
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(componentType);
if (typeInfo.kind == ManagedComponentKind::Script) {
ScriptComponent* component = FindMatchingScriptComponentInChildren(gameObject, typeInfo);
if (!component) {
return nullptr;
}
if (!runtime->HasManagedInstance(component)) {
ScriptEngine::Get().OnScriptComponentEnabled(component);
}
return runtime->GetManagedInstanceObject(component);
}
Components::Component* component = FindNativeComponentInChildren(gameObject, typeInfo.kind);
if (!component || !typeInfo.monoClass) {
return nullptr;
}
return runtime->CreateManagedComponentWrapper(typeInfo.monoClass, component->GetGameObject()->GetUUID());
}
MonoObject* InternalCall_GameObject_GetComponentInParent(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return nullptr;
}
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
if (!runtime) {
return nullptr;
}
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(componentType);
if (typeInfo.kind == ManagedComponentKind::Script) {
ScriptComponent* component = FindMatchingScriptComponentInParent(gameObject, typeInfo);
if (!component) {
return nullptr;
}
if (!runtime->HasManagedInstance(component)) {
ScriptEngine::Get().OnScriptComponentEnabled(component);
}
return runtime->GetManagedInstanceObject(component);
}
Components::Component* component = FindNativeComponentInParent(gameObject, typeInfo.kind);
if (!component || !typeInfo.monoClass) {
return nullptr;
}
return runtime->CreateManagedComponentWrapper(typeInfo.monoClass, component->GetGameObject()->GetUUID());
}
MonoObject* InternalCall_GameObject_AddComponent(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return nullptr;
}
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
if (!runtime) {
return nullptr;
}
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(componentType);
if (typeInfo.kind == ManagedComponentKind::Script) {
ScriptComponent* component = gameObject->AddComponent<ScriptComponent>();
component->SetScriptClass(typeInfo.assemblyName, typeInfo.namespaceName, typeInfo.className);
return runtime->GetManagedInstanceObject(component);
}
if (!AddOrGetNativeComponent(gameObject, typeInfo.kind) || !typeInfo.monoClass) {
return nullptr;
}
return runtime->CreateManagedComponentWrapper(typeInfo.monoClass, gameObjectUUID);
}
uint64_t InternalCall_GameObject_Find(MonoString* name) {
Components::Scene* scene = GetInternalCallScene();
if (!scene) {
return 0;
}
Components::GameObject* gameObject = scene->Find(MonoStringToUtf8(name));
return gameObject ? gameObject->GetUUID() : 0;
}
uint64_t InternalCall_GameObject_Create(MonoString* name, uint64_t parentGameObjectUUID) {
Components::Scene* scene = GetInternalCallScene();
if (!scene) {
return 0;
}
Components::GameObject* parent = nullptr;
if (parentGameObjectUUID != 0) {
parent = FindGameObjectByUUID(parentGameObjectUUID);
if (!parent || parent->GetScene() != scene) {
return 0;
}
}
std::string objectName = MonoStringToUtf8(name);
if (objectName.empty()) {
objectName = "GameObject";
}
Components::GameObject* created = scene->CreateGameObject(objectName, parent);
return created ? created->GetUUID() : 0;
}
void InternalCall_GameObject_Destroy(uint64_t gameObjectUUID) {
Components::Scene* scene = GetInternalCallScene();
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!scene || !gameObject || gameObject->GetScene() != scene) {
return;
}
scene->DestroyGameObject(gameObject);
}
void InternalCall_Object_Destroy(MonoObject* object) {
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
if (!runtime || !object) {
return;
}
runtime->DestroyManagedObject(object);
}
mono_bool InternalCall_Behaviour_GetEnabled(uint64_t scriptComponentUUID) {
ScriptComponent* component = FindScriptComponentByUUID(scriptComponentUUID);
return (component && component->IsEnabled()) ? 1 : 0;
}
void InternalCall_Behaviour_SetEnabled(uint64_t scriptComponentUUID, mono_bool enabled) {
ScriptComponent* component = FindScriptComponentByUUID(scriptComponentUUID);
if (!component) {
return;
}
component->SetEnabled(enabled != 0);
}
void InternalCall_Transform_GetLocalPosition(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outPosition) {
if (!outPosition) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outPosition = XCEngine::Math::Vector3::Zero();
return;
}
*outPosition = gameObject->GetTransform()->GetLocalPosition();
}
void InternalCall_Transform_SetLocalPosition(uint64_t gameObjectUUID, XCEngine::Math::Vector3* position) {
if (!position) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->SetLocalPosition(*position);
}
void InternalCall_Transform_GetLocalRotation(uint64_t gameObjectUUID, XCEngine::Math::Quaternion* outRotation) {
if (!outRotation) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outRotation = XCEngine::Math::Quaternion::Identity();
return;
}
*outRotation = gameObject->GetTransform()->GetLocalRotation();
}
void InternalCall_Transform_SetLocalRotation(uint64_t gameObjectUUID, XCEngine::Math::Quaternion* rotation) {
if (!rotation) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->SetLocalRotation(*rotation);
}
void InternalCall_Transform_GetLocalScale(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outScale) {
if (!outScale) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outScale = XCEngine::Math::Vector3::One();
return;
}
*outScale = gameObject->GetTransform()->GetLocalScale();
}
void InternalCall_Transform_SetLocalScale(uint64_t gameObjectUUID, XCEngine::Math::Vector3* scale) {
if (!scale) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->SetLocalScale(*scale);
}
void InternalCall_Transform_GetLocalEulerAngles(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outEulerAngles) {
if (!outEulerAngles) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outEulerAngles = XCEngine::Math::Vector3::Zero();
return;
}
*outEulerAngles = gameObject->GetTransform()->GetLocalEulerAngles();
}
void InternalCall_Transform_SetLocalEulerAngles(uint64_t gameObjectUUID, XCEngine::Math::Vector3* eulerAngles) {
if (!eulerAngles) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->SetLocalEulerAngles(*eulerAngles);
}
void InternalCall_Transform_GetPosition(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outPosition) {
if (!outPosition) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outPosition = XCEngine::Math::Vector3::Zero();
return;
}
*outPosition = gameObject->GetTransform()->GetPosition();
}
void InternalCall_Transform_SetPosition(uint64_t gameObjectUUID, XCEngine::Math::Vector3* position) {
if (!position) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->SetPosition(*position);
}
void InternalCall_Transform_GetRotation(uint64_t gameObjectUUID, XCEngine::Math::Quaternion* outRotation) {
if (!outRotation) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outRotation = XCEngine::Math::Quaternion::Identity();
return;
}
*outRotation = gameObject->GetTransform()->GetRotation();
}
void InternalCall_Transform_SetRotation(uint64_t gameObjectUUID, XCEngine::Math::Quaternion* rotation) {
if (!rotation) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->SetRotation(*rotation);
}
void InternalCall_Transform_GetScale(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outScale) {
if (!outScale) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outScale = XCEngine::Math::Vector3::One();
return;
}
*outScale = gameObject->GetTransform()->GetScale();
}
void InternalCall_Transform_SetScale(uint64_t gameObjectUUID, XCEngine::Math::Vector3* scale) {
if (!scale) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->SetScale(*scale);
}
void InternalCall_Transform_GetForward(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outForward) {
if (!outForward) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outForward = XCEngine::Math::Vector3::Forward();
return;
}
*outForward = gameObject->GetTransform()->GetForward();
}
void InternalCall_Transform_GetRight(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outRight) {
if (!outRight) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outRight = XCEngine::Math::Vector3::Right();
return;
}
*outRight = gameObject->GetTransform()->GetRight();
}
void InternalCall_Transform_GetUp(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outUp) {
if (!outUp) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outUp = XCEngine::Math::Vector3::Up();
return;
}
*outUp = gameObject->GetTransform()->GetUp();
}
void InternalCall_Transform_Translate(uint64_t gameObjectUUID, XCEngine::Math::Vector3* translation, int32_t relativeTo) {
if (!translation) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->Translate(*translation, ResolveManagedSpace(relativeTo));
}
void InternalCall_Transform_Rotate(uint64_t gameObjectUUID, XCEngine::Math::Vector3* eulers, int32_t relativeTo) {
if (!eulers) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->Rotate(*eulers, ResolveManagedSpace(relativeTo));
}
void InternalCall_Transform_RotateAxisAngle(
uint64_t gameObjectUUID,
XCEngine::Math::Vector3* axis,
float angle,
int32_t relativeTo) {
if (!axis) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->Rotate(*axis, angle, ResolveManagedSpace(relativeTo));
}
void InternalCall_Transform_LookAt(uint64_t gameObjectUUID, XCEngine::Math::Vector3* target) {
if (!target) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->LookAt(*target);
}
void InternalCall_Transform_LookAtWithUp(
uint64_t gameObjectUUID,
XCEngine::Math::Vector3* target,
XCEngine::Math::Vector3* up) {
if (!target || !up) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
return;
}
gameObject->GetTransform()->LookAt(*target, *up);
}
void InternalCall_Transform_TransformPoint(uint64_t gameObjectUUID, XCEngine::Math::Vector3* point, XCEngine::Math::Vector3* outPoint) {
if (!point || !outPoint) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outPoint = *point;
return;
}
*outPoint = gameObject->GetTransform()->TransformPoint(*point);
}
void InternalCall_Transform_InverseTransformPoint(uint64_t gameObjectUUID, XCEngine::Math::Vector3* point, XCEngine::Math::Vector3* outPoint) {
if (!point || !outPoint) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outPoint = *point;
return;
}
*outPoint = gameObject->GetTransform()->InverseTransformPoint(*point);
}
void InternalCall_Transform_TransformDirection(uint64_t gameObjectUUID, XCEngine::Math::Vector3* direction, XCEngine::Math::Vector3* outDirection) {
if (!direction || !outDirection) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outDirection = *direction;
return;
}
*outDirection = gameObject->GetTransform()->TransformDirection(*direction);
}
void InternalCall_Transform_InverseTransformDirection(uint64_t gameObjectUUID, XCEngine::Math::Vector3* direction, XCEngine::Math::Vector3* outDirection) {
if (!direction || !outDirection) {
return;
}
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetTransform()) {
*outDirection = *direction;
return;
}
*outDirection = gameObject->GetTransform()->InverseTransformDirection(*direction);
}
uint64_t InternalCall_Transform_GetParent(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || !gameObject->GetParent()) {
return 0;
}
return gameObject->GetParent()->GetUUID();
}
void InternalCall_Transform_SetParent(uint64_t gameObjectUUID, uint64_t parentGameObjectUUID, mono_bool worldPositionStays) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return;
}
Components::GameObject* parent = parentGameObjectUUID != 0 ? FindGameObjectByUUID(parentGameObjectUUID) : nullptr;
gameObject->SetParent(parent, worldPositionStays != 0);
}
int32_t InternalCall_Transform_GetChildCount(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return gameObject ? static_cast<int32_t>(gameObject->GetChildCount()) : 0;
}
uint64_t InternalCall_Transform_GetChild(uint64_t gameObjectUUID, int32_t index) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject || index < 0) {
return 0;
}
Components::GameObject* child = gameObject->GetChild(static_cast<size_t>(index));
return child ? child->GetUUID() : 0;
}
float InternalCall_Camera_GetFieldOfView(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return component ? component->GetFieldOfView() : 0.0f;
}
void InternalCall_Camera_SetFieldOfView(uint64_t gameObjectUUID, float value) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetFieldOfView(value);
}
float InternalCall_Camera_GetNearClipPlane(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return component ? component->GetNearClipPlane() : 0.0f;
}
void InternalCall_Camera_SetNearClipPlane(uint64_t gameObjectUUID, float value) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetNearClipPlane(value);
}
float InternalCall_Camera_GetFarClipPlane(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return component ? component->GetFarClipPlane() : 0.0f;
}
void InternalCall_Camera_SetFarClipPlane(uint64_t gameObjectUUID, float value) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetFarClipPlane(value);
}
float InternalCall_Camera_GetDepth(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return component ? component->GetDepth() : 0.0f;
}
void InternalCall_Camera_SetDepth(uint64_t gameObjectUUID, float value) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetDepth(value);
}
mono_bool InternalCall_Camera_GetPrimary(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return (component && component->IsPrimary()) ? 1 : 0;
}
void InternalCall_Camera_SetPrimary(uint64_t gameObjectUUID, mono_bool value) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetPrimary(value != 0);
}
int32_t InternalCall_Camera_GetClearMode(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return component != nullptr
? static_cast<int32_t>(component->GetClearMode())
: 0;
}
void InternalCall_Camera_SetClearMode(uint64_t gameObjectUUID, int32_t value) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetClearMode(
static_cast<Components::CameraClearMode>(value));
}
int32_t InternalCall_Camera_GetStackType(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return component != nullptr
? static_cast<int32_t>(component->GetStackType())
: 0;
}
void InternalCall_Camera_SetStackType(uint64_t gameObjectUUID, int32_t value) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetStackType(
static_cast<Components::CameraStackType>(value));
}
int32_t InternalCall_Camera_GetProjectionType(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return component != nullptr
? static_cast<int32_t>(component->GetProjectionType())
: 0;
}
mono_bool InternalCall_Camera_GetSkyboxEnabled(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return (component && component->IsSkyboxEnabled()) ? 1 : 0;
}
mono_bool InternalCall_Camera_GetHasSkyboxMaterial(uint64_t gameObjectUUID) {
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
return (component && component->GetSkyboxMaterial() != nullptr) ? 1 : 0;
}
mono_bool InternalCall_Camera_GetHasFinalColorOverrides(
uint64_t gameObjectUUID) {
Components::CameraComponent* component =
FindCameraComponent(gameObjectUUID);
return (component &&
component->GetFinalColorOverrides().HasOverrides())
? 1
: 0;
}
void InternalCall_Camera_GetFinalColorOverrideSettings(
uint64_t gameObjectUUID,
ManagedFinalColorOverrideSettingsData* outSettings) {
if (outSettings == nullptr) {
return;
}
Components::CameraComponent* component =
FindCameraComponent(gameObjectUUID);
const Rendering::FinalColorOverrideSettings sourceSettings =
component != nullptr
? component->GetFinalColorOverrides()
: Rendering::FinalColorOverrideSettings{};
*outSettings =
BuildManagedFinalColorOverrideSettings(
sourceSettings);
}
void InternalCall_Camera_GetSkyboxTopColor(
uint64_t gameObjectUUID,
XCEngine::Math::Color* outColor) {
if (outColor == nullptr) {
return;
}
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
*outColor = component != nullptr
? component->GetSkyboxTopColor()
: XCEngine::Math::Color();
}
void InternalCall_Camera_GetSkyboxHorizonColor(
uint64_t gameObjectUUID,
XCEngine::Math::Color* outColor) {
if (outColor == nullptr) {
return;
}
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
*outColor = component != nullptr
? component->GetSkyboxHorizonColor()
: XCEngine::Math::Color();
}
void InternalCall_Camera_GetSkyboxBottomColor(
uint64_t gameObjectUUID,
XCEngine::Math::Color* outColor) {
if (outColor == nullptr) {
return;
}
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
*outColor = component != nullptr
? component->GetSkyboxBottomColor()
: XCEngine::Math::Color();
}
float InternalCall_Light_GetIntensity(uint64_t gameObjectUUID) {
Components::LightComponent* component = FindLightComponent(gameObjectUUID);
return component ? component->GetIntensity() : 0.0f;
}
void InternalCall_Light_SetIntensity(uint64_t gameObjectUUID, float value) {
Components::LightComponent* component = FindLightComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetIntensity(value);
}
float InternalCall_Light_GetRange(uint64_t gameObjectUUID) {
Components::LightComponent* component = FindLightComponent(gameObjectUUID);
return component ? component->GetRange() : 0.0f;
}
void InternalCall_Light_SetRange(uint64_t gameObjectUUID, float value) {
Components::LightComponent* component = FindLightComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetRange(value);
}
float InternalCall_Light_GetSpotAngle(uint64_t gameObjectUUID) {
Components::LightComponent* component = FindLightComponent(gameObjectUUID);
return component ? component->GetSpotAngle() : 0.0f;
}
void InternalCall_Light_SetSpotAngle(uint64_t gameObjectUUID, float value) {
Components::LightComponent* component = FindLightComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetSpotAngle(value);
}
mono_bool InternalCall_Light_GetCastsShadows(uint64_t gameObjectUUID) {
Components::LightComponent* component = FindLightComponent(gameObjectUUID);
return (component && component->GetCastsShadows()) ? 1 : 0;
}
void InternalCall_Light_SetCastsShadows(uint64_t gameObjectUUID, mono_bool value) {
Components::LightComponent* component = FindLightComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetCastsShadows(value != 0);
}
MonoString* InternalCall_MeshFilter_GetMeshPath(uint64_t gameObjectUUID) {
Components::MeshFilterComponent* component = FindMeshFilterComponent(gameObjectUUID);
return mono_string_new(
mono_domain_get(),
component ? component->GetMeshPath().c_str() : "");
}
void InternalCall_MeshFilter_SetMeshPath(uint64_t gameObjectUUID, MonoString* path) {
Components::MeshFilterComponent* component = FindMeshFilterComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetMeshPath(MonoStringToUtf8(path));
}
int32_t InternalCall_MeshRenderer_GetMaterialCount(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
return component ? static_cast<int32_t>(component->GetMaterialCount()) : 0;
}
MonoString* InternalCall_MeshRenderer_GetMaterialPath(uint64_t gameObjectUUID, int32_t index) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
const std::string path =
(component && index >= 0) ? component->GetMaterialPath(static_cast<size_t>(index)) : std::string();
return mono_string_new(mono_domain_get(), path.c_str());
}
void InternalCall_MeshRenderer_SetMaterialPath(uint64_t gameObjectUUID, int32_t index, MonoString* path) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component || index < 0) {
return;
}
component->SetMaterialPath(static_cast<size_t>(index), MonoStringToUtf8(path));
}
void InternalCall_MeshRenderer_ClearMaterials(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component) {
return;
}
component->ClearMaterials();
}
mono_bool InternalCall_MeshRenderer_GetCastShadows(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
return (component && component->GetCastShadows()) ? 1 : 0;
}
void InternalCall_MeshRenderer_SetCastShadows(uint64_t gameObjectUUID, mono_bool value) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetCastShadows(value != 0);
}
mono_bool InternalCall_MeshRenderer_GetReceiveShadows(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
return (component && component->GetReceiveShadows()) ? 1 : 0;
}
void InternalCall_MeshRenderer_SetReceiveShadows(uint64_t gameObjectUUID, mono_bool value) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetReceiveShadows(value != 0);
}
int32_t InternalCall_MeshRenderer_GetRenderLayer(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
return component ? static_cast<int32_t>(component->GetRenderLayer()) : 0;
}
void InternalCall_MeshRenderer_SetRenderLayer(uint64_t gameObjectUUID, int32_t value) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetRenderLayer(static_cast<uint32_t>(std::max(value, 0)));
}
int32_t InternalCall_Rigidbody_GetBodyType(uint64_t gameObjectUUID) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
return component
? static_cast<int32_t>(component->GetBodyType())
: static_cast<int32_t>(Physics::PhysicsBodyType::Dynamic);
}
void InternalCall_Rigidbody_SetBodyType(uint64_t gameObjectUUID, int32_t value) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetBodyType(ResolveManagedPhysicsBodyType(value));
}
float InternalCall_Rigidbody_GetMass(uint64_t gameObjectUUID) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
return component ? component->GetMass() : 1.0f;
}
void InternalCall_Rigidbody_SetMass(uint64_t gameObjectUUID, float value) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetMass(value);
}
float InternalCall_Rigidbody_GetLinearDamping(uint64_t gameObjectUUID) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
return component ? component->GetLinearDamping() : 0.0f;
}
void InternalCall_Rigidbody_SetLinearDamping(uint64_t gameObjectUUID, float value) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetLinearDamping(value);
}
float InternalCall_Rigidbody_GetAngularDamping(uint64_t gameObjectUUID) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
return component ? component->GetAngularDamping() : 0.05f;
}
void InternalCall_Rigidbody_SetAngularDamping(uint64_t gameObjectUUID, float value) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetAngularDamping(value);
}
void InternalCall_Rigidbody_GetLinearVelocity(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outVelocity) {
if (!outVelocity) {
return;
}
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
*outVelocity = component ? component->GetLinearVelocity() : XCEngine::Math::Vector3::Zero();
}
void InternalCall_Rigidbody_SetLinearVelocity(uint64_t gameObjectUUID, XCEngine::Math::Vector3* velocity) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component || !velocity) {
return;
}
component->SetLinearVelocity(*velocity);
}
void InternalCall_Rigidbody_GetAngularVelocity(uint64_t gameObjectUUID, XCEngine::Math::Vector3* outVelocity) {
if (!outVelocity) {
return;
}
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
*outVelocity = component ? component->GetAngularVelocity() : XCEngine::Math::Vector3::Zero();
}
void InternalCall_Rigidbody_SetAngularVelocity(uint64_t gameObjectUUID, XCEngine::Math::Vector3* velocity) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component || !velocity) {
return;
}
component->SetAngularVelocity(*velocity);
}
mono_bool InternalCall_Rigidbody_GetUseGravity(uint64_t gameObjectUUID) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
return (component && component->GetUseGravity()) ? 1 : 0;
}
void InternalCall_Rigidbody_SetUseGravity(uint64_t gameObjectUUID, mono_bool value) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetUseGravity(value != 0);
}
mono_bool InternalCall_Rigidbody_GetEnableCCD(uint64_t gameObjectUUID) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
return (component && component->GetEnableCCD()) ? 1 : 0;
}
void InternalCall_Rigidbody_SetEnableCCD(uint64_t gameObjectUUID, mono_bool value) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetEnableCCD(value != 0);
}
void InternalCall_Rigidbody_AddForce(uint64_t gameObjectUUID, XCEngine::Math::Vector3* force, int32_t forceMode) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component || !force) {
return;
}
component->AddForce(*force, ResolveManagedForceMode(forceMode));
}
void InternalCall_Rigidbody_ClearForces(uint64_t gameObjectUUID) {
Components::RigidbodyComponent* component = FindRigidbodyComponent(gameObjectUUID);
if (!component) {
return;
}
component->ClearForces();
}
mono_bool InternalCall_Physics_Raycast(
XCEngine::Math::Vector3* origin,
XCEngine::Math::Vector3* direction,
float maxDistance,
uint64_t* outHitGameObjectUUID,
XCEngine::Math::Vector3* outHitPoint,
XCEngine::Math::Vector3* outHitNormal,
float* outHitDistance,
int32_t* outHitIsTrigger) {
if (outHitGameObjectUUID) {
*outHitGameObjectUUID = 0;
}
if (outHitPoint) {
*outHitPoint = XCEngine::Math::Vector3::Zero();
}
if (outHitNormal) {
*outHitNormal = XCEngine::Math::Vector3::Zero();
}
if (outHitDistance) {
*outHitDistance = 0.0f;
}
if (outHitIsTrigger) {
*outHitIsTrigger = 0;
}
Physics::PhysicsWorld* physicsWorld = FindRuntimePhysicsWorld();
if (!physicsWorld || !origin || !direction) {
return 0;
}
Physics::RaycastHit hit;
if (!physicsWorld->Raycast(*origin, *direction, maxDistance, hit)) {
return 0;
}
if (outHitGameObjectUUID) {
*outHitGameObjectUUID = hit.gameObject ? hit.gameObject->GetUUID() : 0;
}
if (outHitPoint) {
*outHitPoint = hit.point;
}
if (outHitNormal) {
*outHitNormal = hit.normal;
}
if (outHitDistance) {
*outHitDistance = hit.distance;
}
if (outHitIsTrigger) {
*outHitIsTrigger = hit.isTrigger ? 1 : 0;
}
return 1;
}
void InternalCall_Rendering_SetRenderPipelineAsset(MonoObject* assetObject) {
MonoScriptRuntime* const runtime = GetActiveMonoScriptRuntime();
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor currentDescriptor =
Rendering::GetGraphicsSettingsState()
.GetConfiguredRenderPipelineAssetDescriptor();
if (assetObject == nullptr) {
ClearManagedRenderPipelineSelection(runtime);
return;
}
MonoClass* const monoClass = mono_object_get_class(assetObject);
if (monoClass == nullptr) {
return;
}
if (runtime != nullptr &&
!runtime->IsScriptableRenderPipelineAssetObject(assetObject)) {
return;
}
MonoImage* image = mono_class_get_image(monoClass);
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor = {};
descriptor.assemblyName =
TrimAssemblyName(SafeString(image != nullptr ? mono_image_get_name(image) : nullptr));
descriptor.namespaceName = SafeString(mono_class_get_namespace(monoClass));
descriptor.className = SafeString(mono_class_get_name(monoClass));
descriptor.managedAssetHandle =
runtime != nullptr
? runtime->RetainExternalManagedObjectReference(assetObject)
: 0u;
if (!descriptor.IsValid() ||
descriptor.managedAssetHandle == 0u) {
if (runtime != nullptr &&
descriptor.managedAssetHandle != 0u) {
runtime->ReleaseExternalManagedObject(
descriptor.managedAssetHandle);
}
return;
}
if (runtime != nullptr &&
currentDescriptor.managedAssetHandle != 0u &&
currentDescriptor.managedAssetHandle != descriptor.managedAssetHandle) {
runtime->ReleaseExternalManagedObject(
currentDescriptor.managedAssetHandle);
}
Rendering::GetGraphicsSettingsState()
.SetConfiguredRenderPipelineAssetDescriptor(descriptor);
}
MonoObject* InternalCall_Rendering_GetRenderPipelineAsset() {
MonoScriptRuntime* const runtime = GetActiveMonoScriptRuntime();
if (runtime == nullptr) {
return nullptr;
}
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor =
Rendering::GetGraphicsSettingsState()
.GetConfiguredRenderPipelineAssetDescriptor();
if (!descriptor.IsValid()) {
return nullptr;
}
if (descriptor.managedAssetHandle == 0u) {
if (!runtime->TryEnsureManagedRenderPipelineAssetHandle(descriptor)) {
return nullptr;
}
Rendering::GetGraphicsSettingsState()
.SetConfiguredRenderPipelineAssetDescriptor(descriptor);
}
return runtime->GetExternalManagedObject(
descriptor.managedAssetHandle);
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetStage(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return state != nullptr
? static_cast<int32_t>(state->stage)
: static_cast<int32_t>(Rendering::CameraFrameStage::MainScene);
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetRendererIndex(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return state != nullptr &&
state->graphContext != nullptr
? state->graphContext->rendererIndex
: -1;
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetSourceColorTextureHandle(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return EncodeManagedRenderGraphTextureHandle(
ResolveManagedScriptableRenderContextSourceColorTexture(
state));
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetPrimaryColorTargetHandle(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return EncodeManagedRenderGraphTextureHandle(
ResolveManagedScriptableRenderContextPrimaryColorTarget(
state));
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetDepthTargetHandle(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return EncodeManagedRenderGraphTextureHandle(
ResolveManagedScriptableRenderContextDepthTarget(
state));
}
int32_t InternalCall_Rendering_ScriptableRenderContext_CreateTransientTexture(
uint64_t nativeHandle,
MonoString* name,
ManagedRenderGraphTextureDescData* descData) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
state->graphContext == nullptr ||
descData == nullptr) {
return -1;
}
const auto* const desc =
reinterpret_cast<const Rendering::RenderGraphTextureDesc*>(
descData);
if (!desc->IsValid()) {
return -1;
}
const Rendering::RenderGraphTextureHandle handle =
state->graphContext->graphBuilder.CreateTransientTexture(
Containers::String(MonoStringToUtf8(name).c_str()),
*desc);
return EncodeManagedRenderGraphTextureHandle(handle);
}
int32_t
InternalCall_Rendering_ScriptableRenderContext_CreateFullscreenTransientColorTexture(
uint64_t nativeHandle,
MonoString* name) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
state->graphContext == nullptr) {
return -1;
}
const Rendering::RenderGraphTextureHandle handle =
state->graphContext->graphBuilder.CreateTransientTexture(
Containers::String(MonoStringToUtf8(name).c_str()),
Rendering::BuildFullscreenTransientTextureDesc(
state->graphContext->surfaceTemplate));
return EncodeManagedRenderGraphTextureHandle(handle);
}
int32_t
InternalCall_Rendering_ScriptableRenderContext_CreateFullscreenTransientDepthTexture(
uint64_t nativeHandle,
MonoString* name) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
state->graphContext == nullptr) {
return -1;
}
const Rendering::RenderGraphTextureHandle handle =
state->graphContext->graphBuilder.CreateTransientTexture(
Containers::String(MonoStringToUtf8(name).c_str()),
BuildManagedFullscreenTransientDepthTextureDesc(
state->graphContext->surfaceTemplate));
return EncodeManagedRenderGraphTextureHandle(handle);
}
uint64_t InternalCall_Rendering_ScriptableRenderContext_BeginRasterPass(
uint64_t nativeHandle,
MonoString* passName) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
state->graphContext == nullptr ||
!Rendering::IsCameraFrameFullscreenSequenceStage(state->stage)) {
return 0u;
}
const Containers::String passNameString(
MonoStringToUtf8(passName).c_str());
if (passNameString.Empty()) {
return 0u;
}
uint64_t rasterPassHandle =
state->nextPendingRasterPassHandle++;
if (rasterPassHandle == 0u) {
rasterPassHandle =
state->nextPendingRasterPassHandle++;
}
ManagedScriptableRenderContextState::RasterPassRecordRequest
request = {};
request.passName = passNameString;
state->pendingRasterPassRequests[rasterPassHandle] =
std::move(request);
return rasterPassHandle;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_SetRasterPassSourceColorTexture(
uint64_t nativeHandle,
uint64_t rasterPassHandle,
int32_t sourceTextureHandle) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
ManagedScriptableRenderContextState::RasterPassRecordRequest*
const request =
FindPendingManagedRasterPassRecordRequest(
state,
rasterPassHandle);
if (request == nullptr) {
return 0;
}
const Rendering::RenderGraphTextureHandle sourceColorTexture =
DecodeManagedRenderGraphTextureHandle(
sourceTextureHandle);
if (!sourceColorTexture.IsValid()) {
return 0;
}
request->sourceColorTexture = sourceColorTexture;
return 1;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadTexture(
uint64_t nativeHandle,
uint64_t rasterPassHandle,
int32_t textureHandle) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
ManagedScriptableRenderContextState::RasterPassRecordRequest*
const request =
FindPendingManagedRasterPassRecordRequest(
state,
rasterPassHandle);
if (request == nullptr) {
return 0;
}
const Rendering::RenderGraphTextureHandle readTexture =
DecodeManagedRenderGraphTextureHandle(
textureHandle);
if (!readTexture.IsValid()) {
return 0;
}
request->readTextures.push_back(readTexture);
return 1;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture(
uint64_t nativeHandle,
uint64_t rasterPassHandle,
int32_t textureHandle) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
ManagedScriptableRenderContextState::RasterPassRecordRequest*
const request =
FindPendingManagedRasterPassRecordRequest(
state,
rasterPassHandle);
if (request == nullptr) {
return 0;
}
const Rendering::RenderGraphTextureHandle readDepthTexture =
DecodeManagedRenderGraphTextureHandle(
textureHandle);
if (!readDepthTexture.IsValid()) {
return 0;
}
request->readDepthTextures.push_back(readDepthTexture);
return 1;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_AddRasterPassTextureBinding(
uint64_t nativeHandle,
uint64_t rasterPassHandle,
MonoString* shaderResourceName,
int32_t textureHandle,
mono_bool isDepth) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
ManagedScriptableRenderContextState::RasterPassRecordRequest*
const request =
FindPendingManagedRasterPassRecordRequest(
state,
rasterPassHandle);
if (request == nullptr) {
return 0;
}
const Containers::String shaderResourceNameString(
MonoStringToUtf8(shaderResourceName).c_str());
if (shaderResourceNameString.Empty()) {
return 0;
}
const Rendering::RenderGraphTextureHandle texture =
DecodeManagedRenderGraphTextureHandle(
textureHandle);
if (!texture.IsValid()) {
return 0;
}
Rendering::RenderPassGraphTextureBindingRequest
bindingRequest = {};
bindingRequest.resourceName =
shaderResourceNameString;
bindingRequest.texture = texture;
bindingRequest.aspect =
isDepth != 0
? Rendering::RenderGraphTextureAspect::Depth
: Rendering::RenderGraphTextureAspect::Color;
auto existingBinding =
std::find_if(
request->textureBindings.begin(),
request->textureBindings.end(),
[&shaderResourceNameString](
const Rendering::RenderPassGraphTextureBindingRequest&
existingRequest) {
return existingRequest.resourceName ==
shaderResourceNameString;
});
if (existingBinding != request->textureBindings.end()) {
*existingBinding = std::move(bindingRequest);
} else {
request->textureBindings.push_back(
std::move(bindingRequest));
}
return 1;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment(
uint64_t nativeHandle,
uint64_t rasterPassHandle,
int32_t colorAttachmentIndex,
int32_t textureHandle) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
ManagedScriptableRenderContextState::RasterPassRecordRequest*
const request =
FindPendingManagedRasterPassRecordRequest(
state,
rasterPassHandle);
if (request == nullptr ||
colorAttachmentIndex < 0) {
return 0;
}
const Rendering::RenderGraphTextureHandle colorAttachment =
DecodeManagedRenderGraphTextureHandle(
textureHandle);
if (!colorAttachment.IsValid()) {
return 0;
}
if (request->colorTargets.size() <=
static_cast<size_t>(colorAttachmentIndex)) {
request->colorTargets.resize(
static_cast<size_t>(colorAttachmentIndex) + 1u);
}
request->colorTargets[static_cast<size_t>(colorAttachmentIndex)] =
colorAttachment;
return 1;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment(
uint64_t nativeHandle,
uint64_t rasterPassHandle,
int32_t textureHandle) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
ManagedScriptableRenderContextState::RasterPassRecordRequest*
const request =
FindPendingManagedRasterPassRecordRequest(
state,
rasterPassHandle);
if (request == nullptr) {
return 0;
}
const Rendering::RenderGraphTextureHandle depthAttachment =
DecodeManagedRenderGraphTextureHandle(
textureHandle);
if (!depthAttachment.IsValid()) {
return 0;
}
request->depthTarget = depthAttachment;
return 1;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution(
uint64_t nativeHandle,
uint64_t rasterPassHandle,
XCEngine::Math::Vector4* vectorPayload) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
ManagedScriptableRenderContextState::RasterPassRecordRequest*
const request =
FindPendingManagedRasterPassRecordRequest(
state,
rasterPassHandle);
if (request == nullptr ||
vectorPayload == nullptr) {
return 0;
}
request->passDesc =
Rendering::FullscreenPassDesc::MakeColorScale(
*vectorPayload);
return 1;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscreenExecution(
uint64_t nativeHandle,
uint64_t rasterPassHandle,
MonoString* shaderPath,
MonoString* shaderPassName,
XCEngine::Math::Vector4* vectorPayload) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
ManagedScriptableRenderContextState::RasterPassRecordRequest*
const request =
FindPendingManagedRasterPassRecordRequest(
state,
rasterPassHandle);
if (request == nullptr ||
vectorPayload == nullptr) {
return 0;
}
const Containers::String shaderPathString(
MonoStringToUtf8(shaderPath).c_str());
if (shaderPathString.Empty()) {
return 0;
}
request->passDesc =
Rendering::FullscreenPassDesc::MakeShaderVector(
shaderPathString,
*vectorPayload,
Containers::String(MonoStringToUtf8(shaderPassName).c_str()));
return request->passDesc.IsValid()
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreenExecution(
uint64_t nativeHandle,
uint64_t rasterPassHandle,
ManagedFinalColorSettingsData* settingsData) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
ManagedScriptableRenderContextState::RasterPassRecordRequest*
const request =
FindPendingManagedRasterPassRecordRequest(
state,
rasterPassHandle);
if (request == nullptr ||
settingsData == nullptr) {
return 0;
}
request->passDesc =
Rendering::FullscreenPassDesc::MakeFinalColor(
BuildManagedFinalColorSettings(
*settingsData));
return request->passDesc.IsValid()
? 1
: 0;
}
mono_bool InternalCall_Rendering_ScriptableRenderContext_CommitRasterPass(
uint64_t nativeHandle,
uint64_t rasterPassHandle) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
state->graphContext == nullptr ||
!Rendering::IsCameraFrameFullscreenSequenceStage(state->stage)) {
return 0;
}
auto it =
state->pendingRasterPassRequests.find(
rasterPassHandle);
if (it == state->pendingRasterPassRequests.end()) {
return 0;
}
ManagedScriptableRenderContextState::RasterPassRecordRequest
request = std::move(it->second);
state->pendingRasterPassRequests.erase(it);
if (!request.passDesc.IsValid() ||
!ResolveManagedPrimaryColorTarget(request.colorTargets)
.IsValid()) {
return 0;
}
state->rasterPassRequests.push_back(std::move(request));
return 1;
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetStageColorSource(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextStageColorSource(state));
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_GetStageUsesGraphManagedOutputColor(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextUsesGraphManagedOutputColor(
state)
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowEnabled(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.enabled
? 1
: 0;
}
void InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowViewProjection(
uint64_t nativeHandle,
XCEngine::Math::Matrix4x4* outViewProjection) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outViewProjection =
ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.cameraData.viewProjection;
}
float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowOrthographicHalfExtent(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.orthographicHalfExtent;
}
float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowNearClipPlane(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.nearClipPlane;
}
float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowFarClipPlane(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.farClipPlane;
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapWidth(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.mapWidth);
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapHeight(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.mapHeight);
}
float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowWorldTexelSize(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.texelWorldSize;
}
float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowReceiverDepthBias(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.sampling.receiverDepthBias;
}
float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowNormalBiasScale(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.sampling.normalBiasScale;
}
float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowStrength(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.sampling.shadowStrength;
}
float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasFactor(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.casterBias.depthBiasFactor;
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasUnits(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state)
.casterBias.depthBiasUnits;
}
void InternalCall_Rendering_ScriptableRenderContext_GetCameraView(
uint64_t nativeHandle,
XCEngine::Math::Matrix4x4* outView) {
if (outView == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outView =
ResolveManagedScriptableRenderContextCameraData(state).view;
}
void InternalCall_Rendering_ScriptableRenderContext_GetCameraProjection(
uint64_t nativeHandle,
XCEngine::Math::Matrix4x4* outProjection) {
if (outProjection == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outProjection =
ResolveManagedScriptableRenderContextCameraData(state).projection;
}
void InternalCall_Rendering_ScriptableRenderContext_GetCameraViewProjection(
uint64_t nativeHandle,
XCEngine::Math::Matrix4x4* outViewProjection) {
if (outViewProjection == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outViewProjection =
ResolveManagedScriptableRenderContextCameraData(state).viewProjection;
}
void InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldPosition(
uint64_t nativeHandle,
XCEngine::Math::Vector3* outWorldPosition) {
if (outWorldPosition == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outWorldPosition =
ResolveManagedScriptableRenderContextCameraData(state).worldPosition;
}
void InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldRight(
uint64_t nativeHandle,
XCEngine::Math::Vector3* outWorldRight) {
if (outWorldRight == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outWorldRight =
ResolveManagedScriptableRenderContextCameraData(state).worldRight;
}
void InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldUp(
uint64_t nativeHandle,
XCEngine::Math::Vector3* outWorldUp) {
if (outWorldUp == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outWorldUp =
ResolveManagedScriptableRenderContextCameraData(state).worldUp;
}
void InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldForward(
uint64_t nativeHandle,
XCEngine::Math::Vector3* outWorldForward) {
if (outWorldForward == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outWorldForward =
ResolveManagedScriptableRenderContextCameraData(state).worldForward;
}
void InternalCall_Rendering_ScriptableRenderContext_GetCameraClearColor(
uint64_t nativeHandle,
XCEngine::Math::Color* outClearColor) {
if (outClearColor == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outClearColor =
ResolveManagedScriptableRenderContextCameraData(state).clearColor;
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetCameraClearFlags(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextCameraData(state).clearFlags);
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_GetCameraPerspectiveProjection(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextCameraData(state)
.perspectiveProjection
? 1
: 0;
}
float InternalCall_Rendering_ScriptableRenderContext_GetCameraVerticalFovRadians(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextCameraData(state)
.verticalFovRadians;
}
float InternalCall_Rendering_ScriptableRenderContext_GetCameraOrthographicSize(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextCameraData(state)
.orthographicSize;
}
float InternalCall_Rendering_ScriptableRenderContext_GetCameraAspectRatio(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextCameraData(state)
.aspectRatio;
}
float InternalCall_Rendering_ScriptableRenderContext_GetCameraNearClipPlane(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextCameraData(state)
.nearClipPlane;
}
float InternalCall_Rendering_ScriptableRenderContext_GetCameraFarClipPlane(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextCameraData(state)
.farClipPlane;
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetCameraViewportWidth(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextCameraData(state).viewportWidth);
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetCameraViewportHeight(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextCameraData(state).viewportHeight);
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightEnabled(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextLightingData(state)
.mainDirectionalLight.enabled
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightCastsShadows(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextLightingData(state)
.mainDirectionalLight.castsShadows
? 1
: 0;
}
void InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightDirection(
uint64_t nativeHandle,
XCEngine::Math::Vector3* outDirection) {
if (outDirection == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outDirection = ResolveManagedScriptableRenderContextLightingData(state)
.mainDirectionalLight.direction;
}
void InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightColor(
uint64_t nativeHandle,
XCEngine::Math::Color* outColor) {
if (outColor == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outColor = ResolveManagedScriptableRenderContextLightingData(state)
.mainDirectionalLight.color;
}
float
InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightIntensity(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextLightingData(state)
.mainDirectionalLight.intensity;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_GetHasMainDirectionalShadow(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextLightingData(state)
.HasMainDirectionalShadow()
? 1
: 0;
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetAdditionalLightCount(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextLightingData(state)
.additionalLightCount);
}
int32_t InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentMode(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextEnvironmentData(state).mode);
}
void InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxTopColor(
uint64_t nativeHandle,
XCEngine::Math::Color* outColor) {
if (outColor == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outColor = ResolveManagedScriptableRenderContextEnvironmentData(state)
.skybox.topColor;
}
void InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxHorizonColor(
uint64_t nativeHandle,
XCEngine::Math::Color* outColor) {
if (outColor == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outColor = ResolveManagedScriptableRenderContextEnvironmentData(state)
.skybox.horizonColor;
}
void InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxBottomColor(
uint64_t nativeHandle,
XCEngine::Math::Color* outColor) {
if (outColor == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outColor = ResolveManagedScriptableRenderContextEnvironmentData(state)
.skybox.bottomColor;
}
int32_t
InternalCall_Rendering_ScriptableRenderContext_GetFinalColorOutputTransferMode(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextFinalColorPolicy(state)
.outputTransferMode);
}
int32_t
InternalCall_Rendering_ScriptableRenderContext_GetFinalColorExposureMode(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextFinalColorPolicy(state)
.exposureMode);
}
float InternalCall_Rendering_ScriptableRenderContext_GetFinalColorExposureValue(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextFinalColorPolicy(state)
.exposureValue;
}
int32_t
InternalCall_Rendering_ScriptableRenderContext_GetFinalColorToneMappingMode(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return static_cast<int32_t>(
ResolveManagedScriptableRenderContextFinalColorPolicy(state)
.toneMappingMode);
}
void InternalCall_Rendering_ScriptableRenderContext_GetFinalColorScale(
uint64_t nativeHandle,
XCEngine::Math::Vector4* outScale) {
if (outScale == nullptr) {
return;
}
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
*outScale = ResolveManagedScriptableRenderContextFinalColorPolicy(state)
.finalColorScale;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_GetFinalColorHasPipelineDefaults(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextFinalColorPolicy(state)
.hasPipelineDefaults
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides(
uint64_t nativeHandle) {
const ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
return ResolveManagedScriptableRenderContextFinalColorPolicy(state)
.hasCameraOverrides
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_RecordScenePhase(
uint64_t nativeHandle,
int32_t scenePhase) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
state->graphContext == nullptr ||
state->sceneRecorder == nullptr ||
!SupportsManagedScriptableRenderContextSceneRecordingStage(
state->stage)) {
return 0;
}
return state->sceneRecorder->RecordScenePhase(
static_cast<Rendering::ScenePhase>(scenePhase))
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_RecordSceneInjectionPoint(
uint64_t nativeHandle,
int32_t injectionPoint) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
state->graphContext == nullptr ||
state->sceneRecorder == nullptr ||
state->stage != Rendering::CameraFrameStage::MainScene) {
return 0;
}
return state->sceneRecorder->RecordInjectionPoint(
static_cast<Rendering::SceneRenderInjectionPoint>(injectionPoint))
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_RecordNativeSceneFeaturePass(
uint64_t nativeHandle,
int32_t featurePassId) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
state->graphContext == nullptr ||
state->sceneRecorder == nullptr ||
state->stage != Rendering::CameraFrameStage::MainScene) {
return 0;
}
const Rendering::NativeSceneFeaturePassId
resolvedFeaturePassId =
static_cast<Rendering::NativeSceneFeaturePassId>(
featurePassId);
if (resolvedFeaturePassId ==
Rendering::NativeSceneFeaturePassId::Invalid) {
return 0;
}
return state->sceneRecorder->RecordFeaturePass(
resolvedFeaturePassId)
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc(
uint64_t nativeHandle,
int32_t scenePhase,
ManagedRendererListDescData* rendererListDescData,
MonoString* overrideMaterialPath,
MonoString* shaderPassName,
ManagedRenderStateBlockData* renderStateBlockData) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
state->graphContext == nullptr ||
state->sceneRecorder == nullptr ||
!SupportsManagedScriptableRenderContextSceneRecordingStage(
state->stage) ||
rendererListDescData == nullptr) {
return 0;
}
Rendering::DrawSettings drawSettings = {};
drawSettings.scenePhase =
static_cast<Rendering::ScenePhase>(scenePhase);
if (!TryBuildManagedRendererListDesc(
*rendererListDescData,
drawSettings.rendererListDesc)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"ScriptableRenderContext DrawRenderers received an unsupported renderer-list type");
return 0;
}
const std::string overrideMaterialPathUtf8 =
MonoStringToUtf8(overrideMaterialPath);
if (!overrideMaterialPathUtf8.empty()) {
drawSettings.overrideMaterial =
Resources::ResourceManager::Get().Load<Resources::Material>(
overrideMaterialPathUtf8.c_str());
if (!drawSettings.overrideMaterial.IsValid()) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
(Containers::String(
"ScriptableRenderContext DrawRenderers failed to load override material: ") +
Containers::String(overrideMaterialPathUtf8.c_str()))
.CStr());
return 0;
}
}
const std::string shaderPassNameUtf8 =
MonoStringToUtf8(shaderPassName);
if (!shaderPassNameUtf8.empty()) {
drawSettings.shaderPassName =
Containers::String(shaderPassNameUtf8.c_str());
}
if (renderStateBlockData != nullptr) {
drawSettings.renderStateBlock =
BuildManagedRenderStateBlock(
*renderStateBlockData);
}
return state->sceneRecorder->RecordSceneDrawSettings(
drawSettings)
? 1
: 0;
}
int32_t
InternalCall_Rendering_CameraRenderRequestContext_GetRenderedBaseCameraCount(
uint64_t nativeHandle) {
const ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
return state != nullptr
? static_cast<int32_t>(state->renderedBaseCameraCount)
: 0;
}
int32_t
InternalCall_Rendering_CameraRenderRequestContext_GetRenderedRequestCount(
uint64_t nativeHandle) {
const ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
return state != nullptr
? static_cast<int32_t>(state->renderedRequestCount)
: 0;
}
uint64_t
InternalCall_Rendering_CameraRenderRequestContext_GetCameraGameObjectUUID(
uint64_t nativeHandle) {
const ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
if (state == nullptr ||
state->request == nullptr ||
state->request->camera == nullptr ||
state->request->camera->GetGameObject() == nullptr) {
return 0u;
}
return state->request->camera->GetGameObject()->GetUUID();
}
int32_t InternalCall_Rendering_CameraRenderRequestContext_GetRendererIndex(
uint64_t nativeHandle) {
const ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
return state != nullptr &&
state->request != nullptr
? state->request->rendererIndex
: -1;
}
void InternalCall_Rendering_CameraRenderRequestContext_SetRendererIndex(
uint64_t nativeHandle,
int32_t rendererIndex) {
ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
if (state == nullptr || state->request == nullptr) {
return;
}
state->request->rendererIndex = rendererIndex;
}
mono_bool
InternalCall_Rendering_CameraRenderRequestContext_GetHasDirectionalShadow(
uint64_t nativeHandle) {
const ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
return state != nullptr &&
state->request != nullptr &&
state->request->directionalShadow.IsValid()
? 1
: 0;
}
void
InternalCall_Rendering_CameraRenderRequestContext_GetDirectionalShadowPlanningSettings(
uint64_t nativeHandle,
ManagedDirectionalShadowPlanningSettingsData* outSettings) {
const ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
if (outSettings == nullptr) {
return;
}
const Rendering::DirectionalShadowPlanningSettings sourceSettings =
state != nullptr
? state->directionalShadowPlanningSettings
: Rendering::DirectionalShadowPlanningSettings();
*outSettings =
*reinterpret_cast<const ManagedDirectionalShadowPlanningSettingsData*>(
&sourceSettings);
}
void
InternalCall_Rendering_CameraRenderRequestContext_SetDirectionalShadowPlanningSettings(
uint64_t nativeHandle,
ManagedDirectionalShadowPlanningSettingsData* settings) {
ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
if (state == nullptr ||
settings == nullptr) {
return;
}
state->directionalShadowPlanningSettings =
*reinterpret_cast<const Rendering::DirectionalShadowPlanningSettings*>(
settings);
}
void InternalCall_Rendering_CameraRenderRequestContext_ClearDirectionalShadow(
uint64_t nativeHandle) {
ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
if (state == nullptr || state->request == nullptr) {
return;
}
state->request->directionalShadow = {};
state->suppressDirectionalShadow = true;
}
int32_t InternalCall_Rendering_CameraRenderRequestContext_GetClearFlags(
uint64_t nativeHandle) {
const ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
return state != nullptr &&
state->request != nullptr
? static_cast<int32_t>(state->request->clearFlags)
: static_cast<int32_t>(Rendering::RenderClearFlags::All);
}
void InternalCall_Rendering_CameraRenderRequestContext_SetClearFlags(
uint64_t nativeHandle,
int32_t clearFlags) {
ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
if (state == nullptr || state->request == nullptr) {
return;
}
state->request->clearFlags =
static_cast<Rendering::RenderClearFlags>(clearFlags);
}
void InternalCall_Rendering_CameraRenderRequestContext_SetResolvedFinalColorPolicy(
uint64_t nativeHandle,
ManagedFinalColorSettingsData* settings,
mono_bool hasPipelineDefaults,
mono_bool hasCameraOverrides) {
ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
if (state == nullptr ||
state->request == nullptr ||
settings == nullptr) {
return;
}
const Rendering::FinalColorSettings resolvedSettings =
BuildManagedFinalColorSettings(*settings);
Rendering::ResolvedFinalColorPolicy resolvedPolicy = {};
resolvedPolicy.outputTransferMode =
resolvedSettings.outputTransferMode;
resolvedPolicy.exposureMode =
resolvedSettings.exposureMode;
resolvedPolicy.exposureValue =
resolvedSettings.exposureValue;
resolvedPolicy.toneMappingMode =
resolvedSettings.toneMappingMode;
resolvedPolicy.finalColorScale =
resolvedSettings.finalColorScale;
resolvedPolicy.hasPipelineDefaults =
hasPipelineDefaults != 0;
resolvedPolicy.hasCameraOverrides =
hasCameraOverrides != 0;
state->request->finalColorPolicy =
resolvedPolicy;
}
void InternalCall_Rendering_CameraRenderRequestContext_ClearFinalColorPolicy(
uint64_t nativeHandle) {
ManagedCameraRenderRequestContextState* const state =
FindManagedCameraRenderRequestContextState(nativeHandle);
if (state == nullptr || state->request == nullptr) {
return;
}
state->request->finalColorPolicy = {};
}
int32_t
InternalCall_Rendering_RenderSceneSetupContext_GetRendererIndex(
uint64_t nativeHandle) {
const ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
return state != nullptr &&
state->plan != nullptr
? state->plan->request.rendererIndex
: -1;
}
uint64_t
InternalCall_Rendering_RenderSceneSetupContext_GetCameraGameObjectUUID(
uint64_t nativeHandle) {
const ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
if (state == nullptr ||
state->plan == nullptr ||
state->plan->request.camera == nullptr ||
state->plan->request.camera->GetGameObject() == nullptr) {
return 0u;
}
return state->plan->request.camera->GetGameObject()->GetUUID();
}
mono_bool
InternalCall_Rendering_RenderSceneSetupContext_GetIsConfigured(
uint64_t nativeHandle) {
const ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
return state != nullptr &&
state->explicitlyConfigured
? 1
: 0;
}
int32_t InternalCall_Rendering_RenderSceneSetupContext_GetClearFlags(
uint64_t nativeHandle) {
const ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
return state != nullptr &&
state->plan != nullptr
? static_cast<int32_t>(state->plan->request.clearFlags)
: 0;
}
mono_bool
InternalCall_Rendering_RenderSceneSetupContext_GetHasMainSceneDepthAttachment(
uint64_t nativeHandle) {
const ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
return state != nullptr &&
state->plan != nullptr &&
state->plan->GetMainSceneSurface().GetDepthAttachment() != nullptr
? 1
: 0;
}
mono_bool
InternalCall_Rendering_RenderSceneSetupContext_GetHasMainDirectionalShadow(
uint64_t nativeHandle) {
const ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
return state != nullptr &&
state->sceneData != nullptr &&
state->sceneData->lighting.HasMainDirectionalShadow()
? 1
: 0;
}
void InternalCall_Rendering_RenderSceneSetupContext_SetEnvironmentNone(
uint64_t nativeHandle) {
ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
if (state == nullptr || state->sceneData == nullptr) {
return;
}
state->sceneData->environment = {};
state->explicitlyConfigured = true;
}
mono_bool
InternalCall_Rendering_RenderSceneSetupContext_UseCameraSkyboxMaterial(
uint64_t nativeHandle) {
ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
if (state == nullptr ||
state->plan == nullptr ||
state->sceneData == nullptr ||
state->plan->request.camera == nullptr) {
return 0;
}
const Resources::Material* skyboxMaterial =
state->plan->request.camera->GetSkyboxMaterial();
if (skyboxMaterial == nullptr) {
return 0;
}
state->sceneData->environment = {};
state->sceneData->environment.mode =
Rendering::RenderEnvironmentMode::MaterialSkybox;
state->sceneData->environment.materialSkybox.material =
skyboxMaterial;
state->explicitlyConfigured = true;
return 1;
}
void InternalCall_Rendering_RenderSceneSetupContext_SetProceduralSkybox(
uint64_t nativeHandle,
XCEngine::Math::Color* topColor,
XCEngine::Math::Color* horizonColor,
XCEngine::Math::Color* bottomColor) {
ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
if (state == nullptr || state->sceneData == nullptr) {
return;
}
state->sceneData->environment = {};
state->sceneData->environment.mode =
Rendering::RenderEnvironmentMode::ProceduralSkybox;
state->sceneData->environment.skybox.topColor =
topColor != nullptr ? *topColor : XCEngine::Math::Color();
state->sceneData->environment.skybox.horizonColor =
horizonColor != nullptr ? *horizonColor : XCEngine::Math::Color();
state->sceneData->environment.skybox.bottomColor =
bottomColor != nullptr ? *bottomColor : XCEngine::Math::Color();
state->explicitlyConfigured = true;
}
void
InternalCall_Rendering_RenderSceneSetupContext_ClearGlobalShaderKeywords(
uint64_t nativeHandle) {
ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
if (state == nullptr || state->sceneData == nullptr) {
return;
}
state->sceneData->globalShaderKeywords = {};
state->explicitlyConfigured = true;
}
void InternalCall_Rendering_RenderSceneSetupContext_SetGlobalShaderKeyword(
uint64_t nativeHandle,
MonoString* keyword,
mono_bool enabled) {
ManagedRenderSceneSetupContextState* const state =
FindManagedRenderSceneSetupContextState(nativeHandle);
if (state == nullptr || state->sceneData == nullptr) {
return;
}
const XCEngine::Containers::String normalizedKeyword =
Resources::NormalizeShaderKeywordToken(
XCEngine::Containers::String(
MonoStringToUtf8(keyword).c_str()));
if (normalizedKeyword.Empty()) {
state->explicitlyConfigured = true;
return;
}
Resources::ShaderKeywordSet& keywordSet =
state->sceneData->globalShaderKeywords;
bool foundKeyword = false;
size_t foundIndex = 0;
for (size_t keywordIndex = 0;
keywordIndex < keywordSet.enabledKeywords.Size();
++keywordIndex) {
if (keywordSet.enabledKeywords[keywordIndex] ==
normalizedKeyword) {
foundKeyword = true;
foundIndex = keywordIndex;
break;
}
}
if (enabled != 0) {
if (!foundKeyword) {
keywordSet.enabledKeywords.PushBack(normalizedKeyword);
}
} else if (foundKeyword) {
const size_t lastIndex =
keywordSet.enabledKeywords.Size() - 1;
if (foundIndex != lastIndex) {
keywordSet.enabledKeywords[foundIndex] =
keywordSet.enabledKeywords[lastIndex];
}
keywordSet.enabledKeywords.PopBack();
}
Resources::NormalizeShaderKeywordSetInPlace(keywordSet);
state->explicitlyConfigured = true;
}
mono_bool
InternalCall_Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow(
uint64_t nativeHandle) {
const ManagedDirectionalShadowExecutionContextState* const state =
FindManagedDirectionalShadowExecutionContextState(
nativeHandle);
return state != nullptr &&
state->plan != nullptr &&
state->plan->directionalShadow.IsValid()
? 1
: 0;
}
int32_t
InternalCall_Rendering_DirectionalShadowExecutionContext_GetRendererIndex(
uint64_t nativeHandle) {
const ManagedDirectionalShadowExecutionContextState* const state =
FindManagedDirectionalShadowExecutionContextState(
nativeHandle);
return state != nullptr &&
state->plan != nullptr
? state->plan->request.rendererIndex
: -1;
}
mono_bool
InternalCall_Rendering_DirectionalShadowExecutionContext_GetIsConfigured(
uint64_t nativeHandle) {
const ManagedDirectionalShadowExecutionContextState* const state =
FindManagedDirectionalShadowExecutionContextState(
nativeHandle);
return state != nullptr &&
state->explicitlyConfigured
? 1
: 0;
}
mono_bool
InternalCall_Rendering_DirectionalShadowExecutionContext_UseDefaultMainDirectionalShadowExecution(
uint64_t nativeHandle) {
ManagedDirectionalShadowExecutionContextState* const state =
FindManagedDirectionalShadowExecutionContextState(
nativeHandle);
if (state == nullptr ||
state->plan == nullptr ||
state->shadowAllocation == nullptr ||
state->shadowState == nullptr) {
return 0;
}
Rendering::ApplyDefaultRenderPipelineDirectionalShadowExecutionPolicy(
*state->plan,
*state->shadowAllocation,
*state->shadowState);
state->explicitlyConfigured = true;
return state->shadowState->shadowCasterRequest.IsValid() &&
state->shadowState->shadowData.IsValid()
? 1
: 0;
}
void InternalCall_Rendering_DirectionalShadowExecutionContext_ClearDirectionalShadowExecution(
uint64_t nativeHandle) {
ManagedDirectionalShadowExecutionContextState* const state =
FindManagedDirectionalShadowExecutionContextState(
nativeHandle);
if (state == nullptr || state->shadowState == nullptr) {
return;
}
*state->shadowState = {};
state->explicitlyConfigured = true;
}
int32_t
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex(
uint64_t nativeHandle) {
const ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
return state != nullptr &&
state->plan != nullptr
? state->plan->request.rendererIndex
: -1;
}
mono_bool
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_IsStageRequested(
uint64_t nativeHandle,
int32_t stage) {
const ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
if (state == nullptr || state->plan == nullptr) {
return 0;
}
Rendering::CameraFrameStage resolvedStage =
Rendering::CameraFrameStage::MainScene;
if (!TryResolveManagedCameraFrameStage(stage, resolvedStage)) {
return 0;
}
return state->plan->HasFrameStage(resolvedStage) ? 1 : 0;
}
int32_t
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetStageColorSource(
uint64_t nativeHandle,
int32_t stage) {
const ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
if (state == nullptr || state->plan == nullptr) {
return static_cast<int32_t>(
Rendering::CameraFrameColorSource::ExplicitSurface);
}
Rendering::CameraFrameStage resolvedStage =
Rendering::CameraFrameStage::MainScene;
if (!TryResolveManagedCameraFrameStage(stage, resolvedStage)) {
return static_cast<int32_t>(
Rendering::CameraFrameColorSource::ExplicitSurface);
}
return static_cast<int32_t>(
state->plan->ResolveStageColorSource(resolvedStage));
}
mono_bool
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetStageUsesGraphManagedOutputColor(
uint64_t nativeHandle,
int32_t stage) {
const ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
if (state == nullptr || state->plan == nullptr) {
return 0;
}
Rendering::CameraFrameStage resolvedStage =
Rendering::CameraFrameStage::MainScene;
if (!TryResolveManagedCameraFrameStage(stage, resolvedStage)) {
return 0;
}
return state->plan->UsesGraphManagedOutputColor(resolvedStage)
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestFullscreenStage(
uint64_t nativeHandle,
int32_t stage,
int32_t source,
mono_bool usesGraphManagedOutputColor) {
ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
if (state == nullptr || state->plan == nullptr) {
return 0;
}
Rendering::CameraFrameStage resolvedStage =
Rendering::CameraFrameStage::MainScene;
if (!TryResolveManagedCameraFrameStage(stage, resolvedStage)) {
return 0;
}
const Rendering::CameraFrameColorSource resolvedSource =
static_cast<Rendering::CameraFrameColorSource>(source);
return state->plan->RequestFullscreenStage(
resolvedStage,
resolvedSource,
usesGraphManagedOutputColor != 0,
true)
? 1
: 0;
}
void InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearFullscreenStage(
uint64_t nativeHandle,
int32_t stage) {
ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
if (state == nullptr || state->plan == nullptr) {
return;
}
Rendering::CameraFrameStage resolvedStage =
Rendering::CameraFrameStage::MainScene;
if (!TryResolveManagedCameraFrameStage(stage, resolvedStage)) {
return;
}
state->plan->ClearFullscreenStage(resolvedStage, true);
}
mono_bool
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestShadowCasterStage(
uint64_t nativeHandle) {
ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
return state != nullptr &&
state->plan != nullptr &&
state->plan->RequestShadowCasterStage(true)
? 1
: 0;
}
void InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearShadowCasterStage(
uint64_t nativeHandle) {
ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
if (state == nullptr || state->plan == nullptr) {
return;
}
state->plan->ClearShadowCasterStage(true);
}
mono_bool
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetHasExplicitShadowCasterStageConfiguration(
uint64_t nativeHandle) {
const ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
return state != nullptr &&
state->plan != nullptr &&
state->plan->HasExplicitShadowCasterStageConfiguration()
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestDepthOnlyStage(
uint64_t nativeHandle) {
ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
return state != nullptr &&
state->plan != nullptr &&
state->plan->RequestDepthOnlyStage(true)
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestCameraDepthOnlyStage(
uint64_t nativeHandle) {
ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
if (state == nullptr || state->plan == nullptr) {
return 0;
}
Rendering::DepthOnlyRenderRequest& depthOnlyRequest =
state->plan->request.depthOnly;
depthOnlyRequest = {};
depthOnlyRequest.surface =
Rendering::CameraFramePlan::BuildCameraDepthOnlySurfaceTemplate(
state->plan->request.surface);
depthOnlyRequest.clearFlags =
Rendering::RenderClearFlags::Depth;
if (!depthOnlyRequest.IsValid()) {
depthOnlyRequest = {};
state->plan->ClearDepthOnlyStage(true);
return 0;
}
return state->plan->RequestDepthOnlyStage(true)
? 1
: 0;
}
void InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearDepthOnlyStage(
uint64_t nativeHandle) {
ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
if (state == nullptr || state->plan == nullptr) {
return;
}
state->plan->ClearDepthOnlyStage(true);
}
mono_bool
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetHasExplicitDepthOnlyStageConfiguration(
uint64_t nativeHandle) {
const ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
return state != nullptr &&
state->plan != nullptr &&
state->plan->HasExplicitDepthOnlyStageConfiguration()
? 1
: 0;
}
mono_bool
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetHasFinalColorProcessing(
uint64_t nativeHandle) {
const ManagedScriptableRenderPipelinePlanningContextState* const state =
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
return state != nullptr &&
state->plan != nullptr &&
state->plan->finalColorPolicy.RequiresProcessing()
? 1
: 0;
}
void RegisterInternalCalls() {
if (GetInternalCallRegistrationState()) {
return;
}
mono_add_internal_call("XCEngine.InternalCalls::Debug_Log", reinterpret_cast<const void*>(&InternalCall_Debug_Log));
mono_add_internal_call("XCEngine.InternalCalls::Debug_LogWarning", reinterpret_cast<const void*>(&InternalCall_Debug_LogWarning));
mono_add_internal_call("XCEngine.InternalCalls::Debug_LogError", reinterpret_cast<const void*>(&InternalCall_Debug_LogError));
mono_add_internal_call("XCEngine.InternalCalls::Time_GetDeltaTime", reinterpret_cast<const void*>(&InternalCall_Time_GetDeltaTime));
mono_add_internal_call("XCEngine.InternalCalls::Time_GetFixedDeltaTime", reinterpret_cast<const void*>(&InternalCall_Time_GetFixedDeltaTime));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetKey", reinterpret_cast<const void*>(&InternalCall_Input_GetKey));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetKeyDown", reinterpret_cast<const void*>(&InternalCall_Input_GetKeyDown));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetKeyUp", reinterpret_cast<const void*>(&InternalCall_Input_GetKeyUp));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetMouseButton", reinterpret_cast<const void*>(&InternalCall_Input_GetMouseButton));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetMouseButtonDown", reinterpret_cast<const void*>(&InternalCall_Input_GetMouseButtonDown));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetMouseButtonUp", reinterpret_cast<const void*>(&InternalCall_Input_GetMouseButtonUp));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetButton", reinterpret_cast<const void*>(&InternalCall_Input_GetButton));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetButtonDown", reinterpret_cast<const void*>(&InternalCall_Input_GetButtonDown));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetButtonUp", reinterpret_cast<const void*>(&InternalCall_Input_GetButtonUp));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetAxis", reinterpret_cast<const void*>(&InternalCall_Input_GetAxis));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetAxisRaw", reinterpret_cast<const void*>(&InternalCall_Input_GetAxisRaw));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetAnyKey", reinterpret_cast<const void*>(&InternalCall_Input_GetAnyKey));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetAnyKeyDown", reinterpret_cast<const void*>(&InternalCall_Input_GetAnyKeyDown));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetMousePosition", reinterpret_cast<const void*>(&InternalCall_Input_GetMousePosition));
mono_add_internal_call("XCEngine.InternalCalls::Input_GetMouseScrollDelta", reinterpret_cast<const void*>(&InternalCall_Input_GetMouseScrollDelta));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetName", reinterpret_cast<const void*>(&InternalCall_GameObject_GetName));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_SetName", reinterpret_cast<const void*>(&InternalCall_GameObject_SetName));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetTag", reinterpret_cast<const void*>(&InternalCall_GameObject_GetTag));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_SetTag", reinterpret_cast<const void*>(&InternalCall_GameObject_SetTag));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_CompareTag", reinterpret_cast<const void*>(&InternalCall_GameObject_CompareTag));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetLayer", reinterpret_cast<const void*>(&InternalCall_GameObject_GetLayer));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_SetLayer", reinterpret_cast<const void*>(&InternalCall_GameObject_SetLayer));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetActiveSelf", reinterpret_cast<const void*>(&InternalCall_GameObject_GetActiveSelf));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetActiveInHierarchy", reinterpret_cast<const void*>(&InternalCall_GameObject_GetActiveInHierarchy));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_SetActive", reinterpret_cast<const void*>(&InternalCall_GameObject_SetActive));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_HasComponent", reinterpret_cast<const void*>(&InternalCall_GameObject_HasComponent));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetComponent", reinterpret_cast<const void*>(&InternalCall_GameObject_GetComponent));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetComponents", reinterpret_cast<const void*>(&InternalCall_GameObject_GetComponents));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetComponentInChildren", reinterpret_cast<const void*>(&InternalCall_GameObject_GetComponentInChildren));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetComponentInParent", reinterpret_cast<const void*>(&InternalCall_GameObject_GetComponentInParent));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_AddComponent", reinterpret_cast<const void*>(&InternalCall_GameObject_AddComponent));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_Find", reinterpret_cast<const void*>(&InternalCall_GameObject_Find));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_Create", reinterpret_cast<const void*>(&InternalCall_GameObject_Create));
mono_add_internal_call("XCEngine.InternalCalls::GameObject_Destroy", reinterpret_cast<const void*>(&InternalCall_GameObject_Destroy));
mono_add_internal_call("XCEngine.InternalCalls::Object_Destroy", reinterpret_cast<const void*>(&InternalCall_Object_Destroy));
mono_add_internal_call("XCEngine.InternalCalls::Behaviour_GetEnabled", reinterpret_cast<const void*>(&InternalCall_Behaviour_GetEnabled));
mono_add_internal_call("XCEngine.InternalCalls::Behaviour_SetEnabled", reinterpret_cast<const void*>(&InternalCall_Behaviour_SetEnabled));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetLocalPosition", reinterpret_cast<const void*>(&InternalCall_Transform_GetLocalPosition));
mono_add_internal_call("XCEngine.InternalCalls::Transform_SetLocalPosition", reinterpret_cast<const void*>(&InternalCall_Transform_SetLocalPosition));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetLocalRotation", reinterpret_cast<const void*>(&InternalCall_Transform_GetLocalRotation));
mono_add_internal_call("XCEngine.InternalCalls::Transform_SetLocalRotation", reinterpret_cast<const void*>(&InternalCall_Transform_SetLocalRotation));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetLocalScale", reinterpret_cast<const void*>(&InternalCall_Transform_GetLocalScale));
mono_add_internal_call("XCEngine.InternalCalls::Transform_SetLocalScale", reinterpret_cast<const void*>(&InternalCall_Transform_SetLocalScale));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetLocalEulerAngles", reinterpret_cast<const void*>(&InternalCall_Transform_GetLocalEulerAngles));
mono_add_internal_call("XCEngine.InternalCalls::Transform_SetLocalEulerAngles", reinterpret_cast<const void*>(&InternalCall_Transform_SetLocalEulerAngles));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetPosition", reinterpret_cast<const void*>(&InternalCall_Transform_GetPosition));
mono_add_internal_call("XCEngine.InternalCalls::Transform_SetPosition", reinterpret_cast<const void*>(&InternalCall_Transform_SetPosition));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetRotation", reinterpret_cast<const void*>(&InternalCall_Transform_GetRotation));
mono_add_internal_call("XCEngine.InternalCalls::Transform_SetRotation", reinterpret_cast<const void*>(&InternalCall_Transform_SetRotation));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetScale", reinterpret_cast<const void*>(&InternalCall_Transform_GetScale));
mono_add_internal_call("XCEngine.InternalCalls::Transform_SetScale", reinterpret_cast<const void*>(&InternalCall_Transform_SetScale));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetForward", reinterpret_cast<const void*>(&InternalCall_Transform_GetForward));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetRight", reinterpret_cast<const void*>(&InternalCall_Transform_GetRight));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetUp", reinterpret_cast<const void*>(&InternalCall_Transform_GetUp));
mono_add_internal_call("XCEngine.InternalCalls::Transform_Translate", reinterpret_cast<const void*>(&InternalCall_Transform_Translate));
mono_add_internal_call("XCEngine.InternalCalls::Transform_Rotate", reinterpret_cast<const void*>(&InternalCall_Transform_Rotate));
mono_add_internal_call("XCEngine.InternalCalls::Transform_RotateAxisAngle", reinterpret_cast<const void*>(&InternalCall_Transform_RotateAxisAngle));
mono_add_internal_call("XCEngine.InternalCalls::Transform_LookAt", reinterpret_cast<const void*>(&InternalCall_Transform_LookAt));
mono_add_internal_call("XCEngine.InternalCalls::Transform_LookAtWithUp", reinterpret_cast<const void*>(&InternalCall_Transform_LookAtWithUp));
mono_add_internal_call("XCEngine.InternalCalls::Transform_TransformPoint", reinterpret_cast<const void*>(&InternalCall_Transform_TransformPoint));
mono_add_internal_call("XCEngine.InternalCalls::Transform_InverseTransformPoint", reinterpret_cast<const void*>(&InternalCall_Transform_InverseTransformPoint));
mono_add_internal_call("XCEngine.InternalCalls::Transform_TransformDirection", reinterpret_cast<const void*>(&InternalCall_Transform_TransformDirection));
mono_add_internal_call("XCEngine.InternalCalls::Transform_InverseTransformDirection", reinterpret_cast<const void*>(&InternalCall_Transform_InverseTransformDirection));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetParent", reinterpret_cast<const void*>(&InternalCall_Transform_GetParent));
mono_add_internal_call("XCEngine.InternalCalls::Transform_SetParent", reinterpret_cast<const void*>(&InternalCall_Transform_SetParent));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetChildCount", reinterpret_cast<const void*>(&InternalCall_Transform_GetChildCount));
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetChild", reinterpret_cast<const void*>(&InternalCall_Transform_GetChild));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetFieldOfView", reinterpret_cast<const void*>(&InternalCall_Camera_GetFieldOfView));
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetFieldOfView", reinterpret_cast<const void*>(&InternalCall_Camera_SetFieldOfView));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetNearClipPlane", reinterpret_cast<const void*>(&InternalCall_Camera_GetNearClipPlane));
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetNearClipPlane", reinterpret_cast<const void*>(&InternalCall_Camera_SetNearClipPlane));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetFarClipPlane", reinterpret_cast<const void*>(&InternalCall_Camera_GetFarClipPlane));
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetFarClipPlane", reinterpret_cast<const void*>(&InternalCall_Camera_SetFarClipPlane));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetDepth", reinterpret_cast<const void*>(&InternalCall_Camera_GetDepth));
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetDepth", reinterpret_cast<const void*>(&InternalCall_Camera_SetDepth));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetPrimary", reinterpret_cast<const void*>(&InternalCall_Camera_GetPrimary));
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetPrimary", reinterpret_cast<const void*>(&InternalCall_Camera_SetPrimary));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetClearMode", reinterpret_cast<const void*>(&InternalCall_Camera_GetClearMode));
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetClearMode", reinterpret_cast<const void*>(&InternalCall_Camera_SetClearMode));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetStackType", reinterpret_cast<const void*>(&InternalCall_Camera_GetStackType));
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetStackType", reinterpret_cast<const void*>(&InternalCall_Camera_SetStackType));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetProjectionType", reinterpret_cast<const void*>(&InternalCall_Camera_GetProjectionType));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetSkyboxEnabled", reinterpret_cast<const void*>(&InternalCall_Camera_GetSkyboxEnabled));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetHasSkyboxMaterial", reinterpret_cast<const void*>(&InternalCall_Camera_GetHasSkyboxMaterial));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetHasFinalColorOverrides", reinterpret_cast<const void*>(&InternalCall_Camera_GetHasFinalColorOverrides));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetFinalColorOverrideSettings", reinterpret_cast<const void*>(&InternalCall_Camera_GetFinalColorOverrideSettings));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetSkyboxTopColor", reinterpret_cast<const void*>(&InternalCall_Camera_GetSkyboxTopColor));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetSkyboxHorizonColor", reinterpret_cast<const void*>(&InternalCall_Camera_GetSkyboxHorizonColor));
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetSkyboxBottomColor", reinterpret_cast<const void*>(&InternalCall_Camera_GetSkyboxBottomColor));
mono_add_internal_call("XCEngine.InternalCalls::Light_GetIntensity", reinterpret_cast<const void*>(&InternalCall_Light_GetIntensity));
mono_add_internal_call("XCEngine.InternalCalls::Light_SetIntensity", reinterpret_cast<const void*>(&InternalCall_Light_SetIntensity));
mono_add_internal_call("XCEngine.InternalCalls::Light_GetRange", reinterpret_cast<const void*>(&InternalCall_Light_GetRange));
mono_add_internal_call("XCEngine.InternalCalls::Light_SetRange", reinterpret_cast<const void*>(&InternalCall_Light_SetRange));
mono_add_internal_call("XCEngine.InternalCalls::Light_GetSpotAngle", reinterpret_cast<const void*>(&InternalCall_Light_GetSpotAngle));
mono_add_internal_call("XCEngine.InternalCalls::Light_SetSpotAngle", reinterpret_cast<const void*>(&InternalCall_Light_SetSpotAngle));
mono_add_internal_call("XCEngine.InternalCalls::Light_GetCastsShadows", reinterpret_cast<const void*>(&InternalCall_Light_GetCastsShadows));
mono_add_internal_call("XCEngine.InternalCalls::Light_SetCastsShadows", reinterpret_cast<const void*>(&InternalCall_Light_SetCastsShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshFilter_GetMeshPath", reinterpret_cast<const void*>(&InternalCall_MeshFilter_GetMeshPath));
mono_add_internal_call("XCEngine.InternalCalls::MeshFilter_SetMeshPath", reinterpret_cast<const void*>(&InternalCall_MeshFilter_SetMeshPath));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetMaterialCount", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetMaterialCount));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetMaterialPath", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetMaterialPath));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_SetMaterialPath", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_SetMaterialPath));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_ClearMaterials", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_ClearMaterials));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetCastShadows", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetCastShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_SetCastShadows", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_SetCastShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetReceiveShadows", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetReceiveShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_SetReceiveShadows", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_SetReceiveShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetRenderLayer", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetRenderLayer));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_SetRenderLayer", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_SetRenderLayer));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_GetBodyType", reinterpret_cast<const void*>(&InternalCall_Rigidbody_GetBodyType));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_SetBodyType", reinterpret_cast<const void*>(&InternalCall_Rigidbody_SetBodyType));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_GetMass", reinterpret_cast<const void*>(&InternalCall_Rigidbody_GetMass));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_SetMass", reinterpret_cast<const void*>(&InternalCall_Rigidbody_SetMass));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_GetLinearDamping", reinterpret_cast<const void*>(&InternalCall_Rigidbody_GetLinearDamping));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_SetLinearDamping", reinterpret_cast<const void*>(&InternalCall_Rigidbody_SetLinearDamping));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_GetAngularDamping", reinterpret_cast<const void*>(&InternalCall_Rigidbody_GetAngularDamping));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_SetAngularDamping", reinterpret_cast<const void*>(&InternalCall_Rigidbody_SetAngularDamping));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_GetLinearVelocity", reinterpret_cast<const void*>(&InternalCall_Rigidbody_GetLinearVelocity));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_SetLinearVelocity", reinterpret_cast<const void*>(&InternalCall_Rigidbody_SetLinearVelocity));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_GetAngularVelocity", reinterpret_cast<const void*>(&InternalCall_Rigidbody_GetAngularVelocity));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_SetAngularVelocity", reinterpret_cast<const void*>(&InternalCall_Rigidbody_SetAngularVelocity));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_GetUseGravity", reinterpret_cast<const void*>(&InternalCall_Rigidbody_GetUseGravity));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_SetUseGravity", reinterpret_cast<const void*>(&InternalCall_Rigidbody_SetUseGravity));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_GetEnableCCD", reinterpret_cast<const void*>(&InternalCall_Rigidbody_GetEnableCCD));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_SetEnableCCD", reinterpret_cast<const void*>(&InternalCall_Rigidbody_SetEnableCCD));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_AddForce", reinterpret_cast<const void*>(&InternalCall_Rigidbody_AddForce));
mono_add_internal_call("XCEngine.InternalCalls::Rigidbody_ClearForces", reinterpret_cast<const void*>(&InternalCall_Rigidbody_ClearForces));
mono_add_internal_call("XCEngine.InternalCalls::Physics_Raycast", reinterpret_cast<const void*>(&InternalCall_Physics_Raycast));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_SetRenderPipelineAsset", reinterpret_cast<const void*>(&InternalCall_Rendering_SetRenderPipelineAsset));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_GetRenderPipelineAsset", reinterpret_cast<const void*>(&InternalCall_Rendering_GetRenderPipelineAsset));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetStage));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetRendererIndex", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetRendererIndex));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetSourceColorTextureHandle", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetSourceColorTextureHandle));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetPrimaryColorTargetHandle", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetPrimaryColorTargetHandle));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetDepthTargetHandle", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetDepthTargetHandle));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_CreateTransientTexture", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_CreateTransientTexture));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_CreateFullscreenTransientColorTexture", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_CreateFullscreenTransientColorTexture));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_CreateFullscreenTransientDepthTexture", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_CreateFullscreenTransientDepthTexture));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_BeginRasterPass", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_BeginRasterPass));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassSourceColorTexture", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassSourceColorTexture));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassReadTexture", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadTexture));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassTextureBinding", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassTextureBinding));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassColorAttachment", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscreenExecution", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscreenExecution));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreenExecution", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreenExecution));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_CommitRasterPass", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_CommitRasterPass));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetStageColorSource", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetStageColorSource));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetStageUsesGraphManagedOutputColor", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetStageUsesGraphManagedOutputColor));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowEnabled", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowEnabled));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowViewProjection", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowViewProjection));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowOrthographicHalfExtent", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowOrthographicHalfExtent));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowNearClipPlane", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowNearClipPlane));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowFarClipPlane", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowFarClipPlane));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapWidth", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapWidth));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapHeight", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapHeight));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowWorldTexelSize", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowWorldTexelSize));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowReceiverDepthBias", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowReceiverDepthBias));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowNormalBiasScale", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowNormalBiasScale));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowStrength", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowStrength));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasFactor", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasFactor));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasUnits", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasUnits));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraView", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraView));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraProjection", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraProjection));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraViewProjection", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraViewProjection));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraWorldPosition", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldPosition));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraWorldRight", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldRight));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraWorldUp", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldUp));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraWorldForward", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldForward));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraClearColor", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraClearColor));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraClearFlags", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraClearFlags));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraPerspectiveProjection", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraPerspectiveProjection));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraVerticalFovRadians", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraVerticalFovRadians));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraOrthographicSize", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraOrthographicSize));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraAspectRatio", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraAspectRatio));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraNearClipPlane", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraNearClipPlane));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraFarClipPlane", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraFarClipPlane));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraViewportWidth", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraViewportWidth));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraViewportHeight", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetCameraViewportHeight));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightEnabled", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightEnabled));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightCastsShadows", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightCastsShadows));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightDirection", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightDirection));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightColor", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightColor));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightIntensity", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightIntensity));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetHasMainDirectionalShadow", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetHasMainDirectionalShadow));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetAdditionalLightCount", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetAdditionalLightCount));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetEnvironmentMode", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentMode));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetEnvironmentSkyboxTopColor", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxTopColor));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetEnvironmentSkyboxHorizonColor", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxHorizonColor));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetEnvironmentSkyboxBottomColor", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxBottomColor));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorOutputTransferMode", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorOutputTransferMode));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorExposureMode", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorExposureMode));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorExposureValue", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorExposureValue));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorToneMappingMode", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorToneMappingMode));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorScale", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorScale));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorHasPipelineDefaults", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorHasPipelineDefaults));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordScenePhase", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_RecordScenePhase));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_DrawRenderersByDesc", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordSceneInjectionPoint", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_RecordSceneInjectionPoint));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordNativeSceneFeaturePass", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_RecordNativeSceneFeaturePass));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_IsStageRequested", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_IsStageRequested));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetStageColorSource", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetStageColorSource));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetStageUsesGraphManagedOutputColor", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetStageUsesGraphManagedOutputColor));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_RequestFullscreenStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestFullscreenStage));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_ClearFullscreenStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearFullscreenStage));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_RequestShadowCasterStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestShadowCasterStage));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_ClearShadowCasterStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearShadowCasterStage));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetHasExplicitShadowCasterStageConfiguration", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetHasExplicitShadowCasterStageConfiguration));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_RequestDepthOnlyStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestDepthOnlyStage));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_RequestCameraDepthOnlyStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestCameraDepthOnlyStage));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_ClearDepthOnlyStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearDepthOnlyStage));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetHasExplicitDepthOnlyStageConfiguration", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetHasExplicitDepthOnlyStageConfiguration));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetHasFinalColorProcessing", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetHasFinalColorProcessing));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetRenderedBaseCameraCount", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetRenderedBaseCameraCount));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetRenderedRequestCount", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetRenderedRequestCount));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetCameraGameObjectUUID", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetCameraGameObjectUUID));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetRendererIndex", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetRendererIndex));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_SetRendererIndex", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_SetRendererIndex));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetHasDirectionalShadow", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetHasDirectionalShadow));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetDirectionalShadowPlanningSettings", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetDirectionalShadowPlanningSettings));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_SetDirectionalShadowPlanningSettings", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_SetDirectionalShadowPlanningSettings));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_ClearDirectionalShadow", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_ClearDirectionalShadow));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetClearFlags", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetClearFlags));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_SetClearFlags", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_SetClearFlags));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_SetResolvedFinalColorPolicy", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_SetResolvedFinalColorPolicy));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_ClearFinalColorPolicy", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_ClearFinalColorPolicy));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetRendererIndex", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetRendererIndex));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetCameraGameObjectUUID", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetCameraGameObjectUUID));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetIsConfigured", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetIsConfigured));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetClearFlags", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetClearFlags));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetHasMainSceneDepthAttachment", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetHasMainSceneDepthAttachment));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetHasMainDirectionalShadow", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetHasMainDirectionalShadow));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_SetEnvironmentNone", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_SetEnvironmentNone));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_UseCameraSkyboxMaterial", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_UseCameraSkyboxMaterial));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_SetProceduralSkybox", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_SetProceduralSkybox));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_ClearGlobalShaderKeywords", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_ClearGlobalShaderKeywords));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_SetGlobalShaderKeyword", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_SetGlobalShaderKeyword));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow", reinterpret_cast<const void*>(&InternalCall_Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_GetRendererIndex", reinterpret_cast<const void*>(&InternalCall_Rendering_DirectionalShadowExecutionContext_GetRendererIndex));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_GetIsConfigured", reinterpret_cast<const void*>(&InternalCall_Rendering_DirectionalShadowExecutionContext_GetIsConfigured));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_UseDefaultMainDirectionalShadowExecution", reinterpret_cast<const void*>(&InternalCall_Rendering_DirectionalShadowExecutionContext_UseDefaultMainDirectionalShadowExecution));
mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_ClearDirectionalShadowExecution", reinterpret_cast<const void*>(&InternalCall_Rendering_DirectionalShadowExecutionContext_ClearDirectionalShadowExecution));
GetInternalCallRegistrationState() = true;
}
} // namespace
MonoScriptRuntime::MonoScriptRuntime(Settings settings)
: m_settings(std::move(settings)) {
ResolveSettings();
}
MonoScriptRuntime::~MonoScriptRuntime() {
Shutdown();
}
bool MonoScriptRuntime::Initialize() {
m_lastError.clear();
if (!ResolveSettings()) {
return false;
}
if (m_initialized) {
return true;
}
if (!InitializeRootDomain()) {
return false;
}
if (!CreateAppDomain()) {
return false;
}
if (!LoadAssemblies()) {
DestroyAppDomain();
return false;
}
if (!DiscoverScriptClasses()) {
DestroyAppDomain();
return false;
}
m_runtimeLifetimeToken = std::make_shared<int>(0);
m_initialized = true;
Rendering::Pipelines::SetManagedRenderPipelineBridge(
std::make_shared<MonoManagedRenderPipelineBridge>(
this,
m_runtimeLifetimeToken));
return true;
}
void MonoScriptRuntime::Shutdown() {
Rendering::Pipelines::ClearManagedRenderPipelineBridge();
ClearManagedRenderPipelineSelection(this);
GetManagedScriptableRenderContextRegistry().clear();
GetManagedScriptableRenderContextNextHandle() = 1;
GetManagedCameraRenderRequestContextRegistry().clear();
GetManagedCameraRenderRequestContextNextHandle() = 1;
GetManagedRenderSceneSetupContextRegistry().clear();
GetManagedRenderSceneSetupContextNextHandle() = 1;
GetManagedDirectionalShadowExecutionContextRegistry().clear();
GetManagedDirectionalShadowExecutionContextNextHandle() = 1;
GetManagedScriptableRenderPipelinePlanningContextRegistry().clear();
GetManagedScriptableRenderPipelinePlanningContextNextHandle() = 1;
ClearManagedInstances();
ClearExternalManagedObjects();
ClearClassCache();
m_coreAssembly = nullptr;
m_appAssembly = nullptr;
m_coreImage = nullptr;
m_appImage = nullptr;
m_loadedManagedAssemblies.clear();
m_componentClass = nullptr;
m_behaviourClass = nullptr;
m_gameObjectClass = nullptr;
m_monoBehaviourClass = nullptr;
m_scriptableRenderPipelineAssetClass = nullptr;
m_scriptableRenderPipelineClass = nullptr;
m_scriptableRenderContextClass = nullptr;
m_cameraRenderRequestContextClass = nullptr;
m_renderSceneSetupContextClass = nullptr;
m_directionalShadowExecutionContextClass = nullptr;
m_scriptableRenderPipelinePlanningContextClass = nullptr;
m_serializeFieldAttributeClass = nullptr;
m_gameObjectConstructor = nullptr;
m_scriptableRenderContextConstructor = nullptr;
m_cameraRenderRequestContextConstructor = nullptr;
m_renderSceneSetupContextConstructor = nullptr;
m_directionalShadowExecutionContextConstructor = nullptr;
m_scriptableRenderPipelinePlanningContextConstructor = nullptr;
m_managedGameObjectUUIDField = nullptr;
m_gameObjectUUIDField = nullptr;
m_scriptComponentUUIDField = nullptr;
DestroyAppDomain();
m_activeScene = nullptr;
GetInternalCallScene() = nullptr;
GetInternalCallDeltaTime() = 0.0f;
m_runtimeLifetimeToken.reset();
m_initialized = false;
}
bool MonoScriptRuntime::IsClassAvailable(
const std::string& assemblyName,
const std::string& namespaceName,
const std::string& className) const {
return FindClassMetadata(assemblyName, namespaceName, className) != nullptr;
}
bool MonoScriptRuntime::TryGetAvailableScriptClasses(
std::vector<ScriptClassDescriptor>& outClasses) const {
outClasses.clear();
if (!m_initialized) {
return false;
}
outClasses.reserve(m_classes.size());
for (const auto& [key, metadata] : m_classes) {
(void)key;
outClasses.push_back(
ScriptClassDescriptor{
metadata.assemblyName,
metadata.namespaceName,
metadata.className
});
}
std::sort(
outClasses.begin(),
outClasses.end(),
[](const ScriptClassDescriptor& lhs, const ScriptClassDescriptor& rhs) {
if (lhs.assemblyName != rhs.assemblyName) {
return lhs.assemblyName < rhs.assemblyName;
}
if (lhs.namespaceName != rhs.namespaceName) {
return lhs.namespaceName < rhs.namespaceName;
}
return lhs.className < rhs.className;
});
return true;
}
bool MonoScriptRuntime::TryGetAvailableRenderPipelineAssetClasses(
std::vector<ScriptClassDescriptor>& outClasses) const {
outClasses.clear();
if (!m_initialized) {
return false;
}
outClasses = m_renderPipelineAssetClasses;
std::sort(
outClasses.begin(),
outClasses.end(),
[](const ScriptClassDescriptor& lhs, const ScriptClassDescriptor& rhs) {
if (lhs.assemblyName != rhs.assemblyName) {
return lhs.assemblyName < rhs.assemblyName;
}
if (lhs.namespaceName != rhs.namespaceName) {
return lhs.namespaceName < rhs.namespaceName;
}
return lhs.className < rhs.className;
});
return true;
}
std::vector<std::string> MonoScriptRuntime::GetScriptClassNames(const std::string& assemblyName) const {
std::vector<ScriptClassDescriptor> classes;
if (!TryGetAvailableScriptClasses(classes)) {
return {};
}
std::vector<std::string> classNames;
classNames.reserve(classes.size());
for (const ScriptClassDescriptor& descriptor : classes) {
if (!assemblyName.empty() && descriptor.assemblyName != assemblyName) {
continue;
}
classNames.push_back(descriptor.GetFullName());
}
return classNames;
}
bool MonoScriptRuntime::TryGetClassFieldMetadata(
const std::string& assemblyName,
const std::string& namespaceName,
const std::string& className,
std::vector<ScriptFieldMetadata>& outFields) const {
outFields.clear();
const ClassMetadata* metadata = FindClassMetadata(assemblyName, namespaceName, className);
if (!metadata) {
return false;
}
outFields.reserve(metadata->fields.size());
for (const auto& [fieldName, fieldMetadata] : metadata->fields) {
outFields.push_back(ScriptFieldMetadata{fieldName, fieldMetadata.type});
}
std::sort(
outFields.begin(),
outFields.end(),
[](const ScriptFieldMetadata& lhs, const ScriptFieldMetadata& rhs) {
return lhs.name < rhs.name;
});
return true;
}
bool MonoScriptRuntime::TryGetClassFieldDefaultValues(
const std::string& assemblyName,
const std::string& namespaceName,
const std::string& className,
std::vector<ScriptFieldDefaultValue>& outFields) const {
outFields.clear();
const ClassMetadata* metadata = FindClassMetadata(assemblyName, namespaceName, className);
if (!metadata) {
return false;
}
SetCurrentDomain();
MonoObject* instance = mono_object_new(m_appDomain, metadata->monoClass);
if (!instance) {
return false;
}
mono_runtime_object_init(instance);
outFields.reserve(metadata->fields.size());
for (const auto& [fieldName, fieldMetadata] : metadata->fields) {
ScriptFieldValue value;
if (!TryReadFieldValue(instance, fieldMetadata, value)) {
outFields.clear();
return false;
}
outFields.push_back(ScriptFieldDefaultValue{fieldName, fieldMetadata.type, value});
}
std::sort(
outFields.begin(),
outFields.end(),
[](const ScriptFieldDefaultValue& lhs, const ScriptFieldDefaultValue& rhs) {
return lhs.fieldName < rhs.fieldName;
});
return true;
}
bool MonoScriptRuntime::HasManagedInstance(const ScriptComponent* component) const {
const InstanceData* instanceData = FindInstance(component);
return instanceData != nullptr && GetManagedObject(*instanceData) != nullptr;
}
MonoObject* MonoScriptRuntime::GetManagedInstanceObject(const ScriptComponent* component) const {
const InstanceData* instanceData = FindInstance(component);
return instanceData ? GetManagedObject(*instanceData) : nullptr;
}
bool MonoScriptRuntime::TryGetFieldValue(
const ScriptComponent* component,
const std::string& fieldName,
ScriptFieldValue& outValue) const {
const InstanceData* instanceData = FindInstance(component);
if (!instanceData || !instanceData->classMetadata) {
return false;
}
const auto fieldIt = instanceData->classMetadata->fields.find(fieldName);
if (fieldIt == instanceData->classMetadata->fields.end()) {
return false;
}
MonoObject* instance = GetManagedObject(*instanceData);
if (!instance) {
return false;
}
return TryReadFieldValue(instance, fieldIt->second, outValue);
}
void MonoScriptRuntime::OnRuntimeStart(Components::Scene* scene) {
m_activeScene = nullptr;
GetInternalCallDeltaTime() = 0.0f;
if (Initialize()) {
m_activeScene = scene;
GetInternalCallScene() = scene;
}
}
void MonoScriptRuntime::OnRuntimeStop(Components::Scene* scene) {
if (scene != nullptr) {
ClearManagedRenderPipelineSelection(this);
}
ClearManagedInstances();
m_activeScene = nullptr;
GetInternalCallScene() = nullptr;
GetInternalCallDeltaTime() = 0.0f;
}
bool MonoScriptRuntime::TrySetManagedFieldValue(
const ScriptRuntimeContext& context,
const std::string& fieldName,
const ScriptFieldValue& value) {
const InstanceData* instanceData = FindInstance(context);
if (!instanceData || !instanceData->classMetadata) {
return false;
}
const auto metadataIt = instanceData->classMetadata->fields.find(fieldName);
if (metadataIt == instanceData->classMetadata->fields.end()) {
return false;
}
if (!IsScriptFieldValueCompatible(metadataIt->second.type, value)) {
return false;
}
MonoObject* instance = GetManagedObject(*instanceData);
if (!instance) {
return false;
}
return TrySetFieldValue(instance, metadataIt->second, value);
}
bool MonoScriptRuntime::TryGetManagedFieldValue(
const ScriptRuntimeContext& context,
const std::string& fieldName,
ScriptFieldValue& outValue) const {
const InstanceData* instanceData = FindInstance(context);
if (!instanceData || !instanceData->classMetadata) {
return false;
}
const auto metadataIt = instanceData->classMetadata->fields.find(fieldName);
if (metadataIt == instanceData->classMetadata->fields.end()) {
return false;
}
MonoObject* instance = GetManagedObject(*instanceData);
if (!instance) {
return false;
}
return TryReadFieldValue(instance, metadataIt->second, outValue);
}
void MonoScriptRuntime::SyncManagedFieldsToStorage(const ScriptRuntimeContext& context) {
if (!context.component) {
return;
}
const InstanceData* instanceData = FindInstance(context);
if (!instanceData || !instanceData->classMetadata) {
return;
}
MonoObject* instance = GetManagedObject(*instanceData);
if (!instance) {
return;
}
ScriptFieldStorage& fieldStorage = context.component->GetFieldStorage();
const std::vector<std::string> fieldNames = fieldStorage.GetFieldNames();
for (const std::string& fieldName : fieldNames) {
StoredScriptField* storedField = fieldStorage.FindField(fieldName);
if (!storedField) {
continue;
}
const auto metadataIt = instanceData->classMetadata->fields.find(fieldName);
if (metadataIt == instanceData->classMetadata->fields.end() || storedField->type != metadataIt->second.type) {
continue;
}
ScriptFieldValue value;
if (!TryReadFieldValue(instance, metadataIt->second, value)) {
continue;
}
fieldStorage.SetFieldValue(fieldName, storedField->type, value);
}
}
bool MonoScriptRuntime::CreateScriptInstance(const ScriptRuntimeContext& context) {
if (!context.component) {
SetError("Cannot create a managed script instance without a ScriptComponent.");
return false;
}
if (FindInstance(context)) {
return true;
}
if (!Initialize()) {
return false;
}
const std::string assemblyName = context.component->GetAssemblyName().empty()
? m_settings.appAssemblyName
: context.component->GetAssemblyName();
const ClassMetadata* classMetadata = FindClassMetadata(
assemblyName,
context.component->GetNamespaceName(),
context.component->GetClassName());
if (!classMetadata) {
SetError("Managed script class was not found: " + assemblyName + "|" + context.component->GetFullClassName());
return false;
}
SetCurrentDomain();
MonoObject* instance = mono_object_new(m_appDomain, classMetadata->monoClass);
if (!instance) {
SetError("Mono failed to allocate a managed object for " + classMetadata->fullName + ".");
return false;
}
mono_runtime_object_init(instance);
if (!ApplyContextFields(context, instance) || !ApplyStoredFields(context, *classMetadata, instance)) {
return false;
}
const uint32_t gcHandle = mono_gchandle_new(instance, false);
const InstanceKey key{context.gameObjectUUID, context.scriptComponentUUID};
m_instances[key] = InstanceData{classMetadata, gcHandle};
return true;
}
void MonoScriptRuntime::DestroyScriptInstance(const ScriptRuntimeContext& context) {
InstanceData* instanceData = FindInstance(context);
if (!instanceData) {
return;
}
if (instanceData->gcHandle != 0) {
mono_gchandle_free(instanceData->gcHandle);
}
m_instances.erase(InstanceKey{context.gameObjectUUID, context.scriptComponentUUID});
}
void MonoScriptRuntime::InvokeMethod(
const ScriptRuntimeContext& context,
ScriptLifecycleMethod method,
float deltaTime) {
const InstanceData* instanceData = FindInstance(context);
if (!instanceData || !instanceData->classMetadata) {
return;
}
MonoMethod* managedMethod = instanceData->classMetadata->lifecycleMethods[static_cast<size_t>(method)];
if (!managedMethod) {
return;
}
MonoObject* instance = GetManagedObject(*instanceData);
if (!instance) {
return;
}
const float previousDeltaTime = GetInternalCallDeltaTime();
GetInternalCallDeltaTime() = deltaTime;
InvokeManagedMethod(instance, managedMethod, nullptr);
GetInternalCallDeltaTime() = previousDeltaTime;
}
void MonoScriptRuntime::InvokePhysicsMessage(
const ScriptRuntimeContext& context,
ScriptPhysicsMessage message,
Components::GameObject* other) {
const InstanceData* instanceData = FindInstance(context);
if (!instanceData || !instanceData->classMetadata) {
return;
}
const PhysicsMessageMethods& methods =
instanceData->classMetadata->physicsMessageMethods[static_cast<size_t>(message)];
MonoMethod* managedMethod = methods.withGameObject ? methods.withGameObject : methods.withoutArgs;
if (!managedMethod) {
return;
}
MonoObject* instance = GetManagedObject(*instanceData);
if (!instance) {
return;
}
if (methods.withGameObject) {
MonoObject* managedOther = other ? CreateManagedGameObject(other->GetUUID()) : nullptr;
if (other && !managedOther) {
return;
}
void* args[1];
args[0] = managedOther;
InvokeManagedMethod(instance, managedMethod, args);
return;
}
InvokeManagedMethod(instance, managedMethod, nullptr);
}
size_t MonoScriptRuntime::InstanceKeyHasher::operator()(const InstanceKey& key) const {
const size_t h1 = std::hash<uint64_t>{}(key.gameObjectUUID);
const size_t h2 = std::hash<uint64_t>{}(key.scriptComponentUUID);
return h1 ^ (h2 + 0x9e3779b97f4a7c15ULL + (h1 << 6) + (h1 >> 2));
}
std::filesystem::path MonoScriptRuntime::GetEngineAssemblyManifestPath(
const std::filesystem::path& assemblyDirectory) {
return assemblyDirectory / EngineAssemblyManifestFileName;
}
bool MonoScriptRuntime::DiscoverEngineAssemblies(
Settings& ioSettings,
std::string* outError) {
if (!ioSettings.engineAssemblies.empty()) {
std::unordered_set<std::string> assemblyNames;
for (ManagedAssemblyDescriptor& assembly :
ioSettings.engineAssemblies) {
if (!NormalizeManagedAssemblyDescriptor(
assembly,
ioSettings.assemblyDirectory,
assemblyNames,
outError)) {
return false;
}
}
return true;
}
if (ioSettings.assemblyDirectory.empty()) {
return true;
}
std::vector<ManagedAssemblyDescriptor> discoveredAssemblies;
const std::filesystem::path manifestPath =
GetEngineAssemblyManifestPath(ioSettings.assemblyDirectory);
if (!LoadManagedAssemblyManifest(
ioSettings.assemblyDirectory,
manifestPath,
discoveredAssemblies,
outError)) {
return false;
}
if (discoveredAssemblies.empty() &&
!DiscoverManagedAssembliesByConvention(
ioSettings,
discoveredAssemblies)) {
if (outError != nullptr) {
*outError =
"Failed to discover managed engine assemblies in " +
ioSettings.assemblyDirectory.string();
}
return false;
}
ioSettings.engineAssemblies = std::move(discoveredAssemblies);
return true;
}
bool MonoScriptRuntime::ResolveSettings() {
if (!m_settings.coreAssemblyPath.empty() && m_settings.assemblyDirectory.empty()) {
m_settings.assemblyDirectory = m_settings.coreAssemblyPath.parent_path();
}
if (!m_settings.appAssemblyPath.empty() && m_settings.assemblyDirectory.empty()) {
m_settings.assemblyDirectory = m_settings.appAssemblyPath.parent_path();
}
if (m_settings.coreAssemblyPath.empty() && !m_settings.assemblyDirectory.empty()) {
m_settings.coreAssemblyPath = m_settings.assemblyDirectory / (m_settings.coreAssemblyName + ".dll");
}
if (m_settings.appAssemblyPath.empty() && !m_settings.assemblyDirectory.empty()) {
m_settings.appAssemblyPath = m_settings.assemblyDirectory / (m_settings.appAssemblyName + ".dll");
}
if (m_settings.corlibDirectory.empty()) {
if (!m_settings.assemblyDirectory.empty()) {
m_settings.corlibDirectory = m_settings.assemblyDirectory;
} else if (!m_settings.coreAssemblyPath.empty()) {
m_settings.corlibDirectory = m_settings.coreAssemblyPath.parent_path();
}
}
std::string discoveryError;
if (!DiscoverEngineAssemblies(m_settings, &discoveryError)) {
SetError(discoveryError);
return false;
}
return true;
}
bool MonoScriptRuntime::InitializeRootDomain() {
MonoRootState& rootState = GetMonoRootState();
if (rootState.initialized) {
return true;
}
if (!m_settings.corlibDirectory.empty()) {
const std::string corlibDirectory = m_settings.corlibDirectory.string();
mono_set_assemblies_path(corlibDirectory.c_str());
}
mono_config_parse(nullptr);
rootState.rootDomain = mono_jit_init_version("XCEngineRootDomain", "v4.0.30319");
if (!rootState.rootDomain) {
SetError("Failed to initialize the Mono root domain.");
return false;
}
mono_domain_set(rootState.rootDomain, true);
RegisterInternalCalls();
rootState.initialized = true;
if (!rootState.cleanupRegistered) {
std::atexit(&CleanupMonoRootDomainAtExit);
rootState.cleanupRegistered = true;
}
return true;
}
bool MonoScriptRuntime::CreateAppDomain() {
if (m_appDomain) {
return true;
}
MonoRootState& rootState = GetMonoRootState();
if (!rootState.rootDomain) {
SetError("Mono root domain is not initialized.");
return false;
}
mono_domain_set(rootState.rootDomain, true);
m_appDomain = mono_domain_create_appdomain(const_cast<char*>("XCEngineScriptDomain"), nullptr);
if (!m_appDomain) {
SetError("Failed to create the Mono app domain.");
return false;
}
mono_domain_set(m_appDomain, true);
return true;
}
void MonoScriptRuntime::DestroyAppDomain() {
if (!m_appDomain) {
return;
}
MonoRootState& rootState = GetMonoRootState();
if (rootState.rootDomain) {
mono_domain_set(rootState.rootDomain, true);
}
mono_domain_unload(m_appDomain);
m_appDomain = nullptr;
if (rootState.rootDomain) {
mono_domain_set(rootState.rootDomain, true);
}
}
void MonoScriptRuntime::SetCurrentDomain() const {
if (m_appDomain) {
mono_domain_set(m_appDomain, true);
}
}
bool MonoScriptRuntime::LoadAssemblies() {
if (m_settings.coreAssemblyPath.empty() || m_settings.appAssemblyPath.empty()) {
SetError("Managed assembly paths are not configured.");
return false;
}
SetCurrentDomain();
m_loadedManagedAssemblies.clear();
if (!LoadAssemblyImage(
BuildManagedAssemblyDescriptor(
m_settings.coreAssemblyName,
m_settings.coreAssemblyPath),
"script core",
m_coreAssembly,
m_coreImage)) {
return false;
}
for (const ManagedAssemblyDescriptor& assembly :
m_settings.engineAssemblies) {
MonoAssembly* loadedAssembly = nullptr;
MonoImage* loadedImage = nullptr;
if (!LoadAssemblyImage(
assembly,
"engine",
loadedAssembly,
loadedImage)) {
return false;
}
}
if (!LoadAssemblyImage(
BuildManagedAssemblyDescriptor(
m_settings.appAssemblyName,
m_settings.appAssemblyPath),
"game scripts",
m_appAssembly,
m_appImage)) {
return false;
}
return true;
}
bool MonoScriptRuntime::LoadAssemblyImage(
const ManagedAssemblyDescriptor& descriptor,
const char* roleLabel,
MonoAssembly*& outAssembly,
MonoImage*& outImage) {
outAssembly = nullptr;
outImage = nullptr;
if (descriptor.name.empty() || descriptor.path.empty()) {
SetError(
"Managed " + std::string(roleLabel) +
" assembly descriptor is incomplete.");
return false;
}
if (!std::filesystem::exists(descriptor.path)) {
SetError(
"Managed " + std::string(roleLabel) +
" assembly does not exist: " + descriptor.path.string());
return false;
}
if (m_loadedManagedAssemblies.contains(descriptor.name)) {
SetError(
"Managed assembly name is loaded more than once: " +
descriptor.name);
return false;
}
outAssembly = mono_domain_assembly_open(
m_appDomain,
descriptor.path.string().c_str());
if (!outAssembly) {
SetError(
"Failed to load managed " + std::string(roleLabel) +
" assembly: " + descriptor.path.string());
return false;
}
outImage = mono_assembly_get_image(outAssembly);
if (!outImage) {
SetError(
"Failed to access the managed " + std::string(roleLabel) +
" image: " + descriptor.path.string());
return false;
}
m_loadedManagedAssemblies.emplace(
descriptor.name,
LoadedManagedAssemblyData{outAssembly, outImage});
return true;
}
bool MonoScriptRuntime::DiscoverScriptClasses() {
ClearClassCache();
m_componentClass = mono_class_from_name(
m_coreImage,
m_settings.baseNamespace.c_str(),
"Component");
if (!m_componentClass) {
SetError("Failed to locate the managed Component base type.");
return false;
}
m_behaviourClass = mono_class_from_name(
m_coreImage,
m_settings.baseNamespace.c_str(),
"Behaviour");
if (!m_behaviourClass) {
SetError("Failed to locate the managed Behaviour base type.");
return false;
}
m_gameObjectClass = mono_class_from_name(
m_coreImage,
m_settings.baseNamespace.c_str(),
"GameObject");
if (!m_gameObjectClass) {
SetError("Failed to locate the managed GameObject wrapper type.");
return false;
}
m_gameObjectConstructor = mono_class_get_method_from_name(m_gameObjectClass, ".ctor", 1);
m_managedGameObjectUUIDField = mono_class_get_field_from_name(m_gameObjectClass, "m_uuid");
if (!m_gameObjectConstructor || !m_managedGameObjectUUIDField) {
SetError("Failed to locate the managed GameObject constructor or UUID field.");
return false;
}
m_monoBehaviourClass = mono_class_from_name(
m_coreImage,
m_settings.baseNamespace.c_str(),
m_settings.baseClassName.c_str());
if (!m_monoBehaviourClass) {
SetError("Failed to locate the managed base type " + BuildFullClassName(m_settings.baseNamespace, m_settings.baseClassName) + ".");
return false;
}
m_scriptableRenderPipelineAssetClass = mono_class_from_name(
m_coreImage,
kManagedRenderingNamespace,
"ScriptableRenderPipelineAsset");
if (!m_scriptableRenderPipelineAssetClass) {
SetError("Failed to locate the managed ScriptableRenderPipelineAsset base type.");
return false;
}
m_scriptableRenderPipelineClass = mono_class_from_name(
m_coreImage,
kManagedRenderingNamespace,
"ScriptableRenderPipeline");
if (!m_scriptableRenderPipelineClass) {
SetError("Failed to locate the managed ScriptableRenderPipeline base type.");
return false;
}
m_scriptableRenderContextClass = mono_class_from_name(
m_coreImage,
kManagedRenderingNamespace,
"ScriptableRenderContext");
if (!m_scriptableRenderContextClass) {
SetError("Failed to locate the managed ScriptableRenderContext type.");
return false;
}
m_scriptableRenderContextConstructor = mono_class_get_method_from_name(
m_scriptableRenderContextClass,
".ctor",
1);
if (!m_scriptableRenderContextConstructor) {
SetError(
"Failed to locate the managed ScriptableRenderContext constructor.");
return false;
}
m_cameraRenderRequestContextClass = mono_class_from_name(
m_coreImage,
kManagedRenderingNamespace,
"CameraRenderRequestContext");
if (!m_cameraRenderRequestContextClass) {
SetError(
"Failed to locate the managed CameraRenderRequestContext type.");
return false;
}
m_cameraRenderRequestContextConstructor =
mono_class_get_method_from_name(
m_cameraRenderRequestContextClass,
".ctor",
1);
if (!m_cameraRenderRequestContextConstructor) {
SetError(
"Failed to locate the managed CameraRenderRequestContext constructor.");
return false;
}
m_renderSceneSetupContextClass = mono_class_from_name(
m_coreImage,
kManagedRenderingNamespace,
"RenderSceneSetupContext");
if (!m_renderSceneSetupContextClass) {
SetError(
"Failed to locate the managed RenderSceneSetupContext type.");
return false;
}
m_renderSceneSetupContextConstructor =
mono_class_get_method_from_name(
m_renderSceneSetupContextClass,
".ctor",
1);
if (!m_renderSceneSetupContextConstructor) {
SetError(
"Failed to locate the managed RenderSceneSetupContext constructor.");
return false;
}
m_directionalShadowExecutionContextClass = mono_class_from_name(
m_coreImage,
kManagedRenderingNamespace,
"DirectionalShadowExecutionContext");
if (!m_directionalShadowExecutionContextClass) {
SetError(
"Failed to locate the managed DirectionalShadowExecutionContext type.");
return false;
}
m_directionalShadowExecutionContextConstructor =
mono_class_get_method_from_name(
m_directionalShadowExecutionContextClass,
".ctor",
1);
if (!m_directionalShadowExecutionContextConstructor) {
SetError(
"Failed to locate the managed DirectionalShadowExecutionContext constructor.");
return false;
}
m_scriptableRenderPipelinePlanningContextClass = mono_class_from_name(
m_coreImage,
kManagedRenderingNamespace,
"ScriptableRenderPipelinePlanningContext");
if (!m_scriptableRenderPipelinePlanningContextClass) {
SetError(
"Failed to locate the managed ScriptableRenderPipelinePlanningContext type.");
return false;
}
m_scriptableRenderPipelinePlanningContextConstructor =
mono_class_get_method_from_name(
m_scriptableRenderPipelinePlanningContextClass,
".ctor",
1);
if (!m_scriptableRenderPipelinePlanningContextConstructor) {
SetError(
"Failed to locate the managed ScriptableRenderPipelinePlanningContext constructor.");
return false;
}
m_serializeFieldAttributeClass = mono_class_from_name(
m_coreImage,
m_settings.baseNamespace.c_str(),
"SerializeField");
if (!m_serializeFieldAttributeClass) {
SetError("Failed to locate the managed SerializeField attribute type.");
return false;
}
m_gameObjectUUIDField = mono_class_get_field_from_name(m_componentClass, "m_gameObjectUUID");
m_scriptComponentUUIDField = mono_class_get_field_from_name(m_behaviourClass, "m_scriptComponentUUID");
if (!m_gameObjectUUIDField || !m_scriptComponentUUIDField) {
SetError("Failed to locate the managed context fields for Component/Behaviour.");
return false;
}
DiscoverScriptClassesInImage(m_settings.appAssemblyName, m_appImage);
DiscoverRenderPipelineAssetClassesInImage(
m_settings.coreAssemblyName,
m_coreImage);
for (const ManagedAssemblyDescriptor& assembly :
m_settings.engineAssemblies) {
DiscoverRenderPipelineAssetClassesInImage(
assembly.name,
FindLoadedAssemblyImage(assembly.name));
}
DiscoverRenderPipelineAssetClassesInImage(
m_settings.appAssemblyName,
m_appImage);
return true;
}
void MonoScriptRuntime::DiscoverScriptClassesInImage(const std::string& assemblyName, MonoImage* image) {
if (!image) {
return;
}
const int typeCount = mono_image_get_table_rows(image, MONO_TABLE_TYPEDEF);
for (int index = 1; index <= typeCount; ++index) {
const uint32_t typeToken = mono_metadata_make_token(MONO_TABLE_TYPEDEF, index);
MonoClass* monoClass = mono_class_get(image, typeToken);
if (!monoClass || !IsMonoBehaviourSubclass(monoClass)) {
continue;
}
if ((mono_class_get_flags(monoClass) & MONO_TYPE_ATTR_ABSTRACT) != 0) {
continue;
}
ClassMetadata metadata;
metadata.assemblyName = assemblyName;
metadata.namespaceName = SafeString(mono_class_get_namespace(monoClass));
metadata.className = SafeString(mono_class_get_name(monoClass));
metadata.fullName = BuildFullClassName(metadata.namespaceName, metadata.className);
metadata.monoClass = monoClass;
for (size_t methodIndex = 0; methodIndex < LifecycleMethodCount; ++methodIndex) {
metadata.lifecycleMethods[methodIndex] = mono_class_get_method_from_name(
monoClass,
ToLifecycleMethodName(static_cast<ScriptLifecycleMethod>(methodIndex)),
0);
}
for (size_t methodIndex = 0; methodIndex < PhysicsMessageCount; ++methodIndex) {
PhysicsMessageMethods& methods = metadata.physicsMessageMethods[methodIndex];
methods.withGameObject = mono_class_get_method_from_name(
monoClass,
ToPhysicsMessageMethodName(static_cast<ScriptPhysicsMessage>(methodIndex)),
1);
methods.withoutArgs = mono_class_get_method_from_name(
monoClass,
ToPhysicsMessageMethodName(static_cast<ScriptPhysicsMessage>(methodIndex)),
0);
}
void* fieldIterator = nullptr;
while (MonoClassField* field = mono_class_get_fields(monoClass, &fieldIterator)) {
const uint32_t fieldFlags = mono_field_get_flags(field);
if ((fieldFlags & MONO_FIELD_ATTR_STATIC) != 0
|| (fieldFlags & MONO_FIELD_ATTR_LITERAL) != 0
|| (fieldFlags & MONO_FIELD_ATTR_INIT_ONLY) != 0) {
continue;
}
const bool isPublicField = (fieldFlags & MONO_FIELD_ATTR_PUBLIC) != 0;
if (!isPublicField && !HasSerializeFieldAttribute(field)) {
continue;
}
FieldMetadata fieldMetadata = BuildFieldMetadata(field);
if (fieldMetadata.type == ScriptFieldType::None) {
continue;
}
metadata.fields.emplace(mono_field_get_name(field), std::move(fieldMetadata));
}
m_classes.emplace(
BuildClassKey(metadata.assemblyName, metadata.namespaceName, metadata.className),
std::move(metadata));
}
}
void MonoScriptRuntime::DiscoverRenderPipelineAssetClassesInImage(
const std::string& assemblyName,
MonoImage* image) {
if (!image || m_scriptableRenderPipelineAssetClass == nullptr) {
return;
}
const int typeCount = mono_image_get_table_rows(image, MONO_TABLE_TYPEDEF);
for (int index = 1; index <= typeCount; ++index) {
const uint32_t typeToken =
mono_metadata_make_token(MONO_TABLE_TYPEDEF, index);
MonoClass* monoClass = mono_class_get(image, typeToken);
if (monoClass == nullptr ||
monoClass == m_scriptableRenderPipelineAssetClass ||
!IsMonoClassOrSubclass(
monoClass,
m_scriptableRenderPipelineAssetClass)) {
continue;
}
if ((mono_class_get_flags(monoClass) & MONO_TYPE_ATTR_ABSTRACT) != 0) {
continue;
}
const ScriptClassDescriptor descriptor{
assemblyName,
SafeString(mono_class_get_namespace(monoClass)),
SafeString(mono_class_get_name(monoClass))};
if (std::find(
m_renderPipelineAssetClasses.begin(),
m_renderPipelineAssetClasses.end(),
descriptor) == m_renderPipelineAssetClasses.end()) {
m_renderPipelineAssetClasses.push_back(descriptor);
}
}
}
bool MonoScriptRuntime::IsMonoBehaviourSubclass(MonoClass* monoClass) const {
if (!monoClass || !m_monoBehaviourClass || monoClass == m_monoBehaviourClass) {
return false;
}
MonoClass* current = monoClass;
while (current) {
if (current == m_monoBehaviourClass) {
return true;
}
current = mono_class_get_parent(current);
}
return false;
}
bool MonoScriptRuntime::IsSupportedComponentFieldClass(MonoClass* monoClass) const {
if (!IsMonoClassOrSubclass(monoClass, m_componentClass)) {
return false;
}
if (monoClass == m_componentClass || monoClass == m_behaviourClass || monoClass == m_monoBehaviourClass) {
return false;
}
if (IsScriptComponentFieldClass(monoClass)) {
return true;
}
const std::string namespaceName = SafeString(mono_class_get_namespace(monoClass));
const std::string className = SafeString(mono_class_get_name(monoClass));
if (namespaceName != m_settings.baseNamespace) {
return false;
}
return className == "Transform"
|| className == "Rigidbody"
|| className == "Camera"
|| className == "Light"
|| className == "MeshFilter"
|| className == "MeshRenderer";
}
bool MonoScriptRuntime::IsScriptComponentFieldClass(MonoClass* monoClass) const {
if (!monoClass || monoClass == m_monoBehaviourClass) {
return false;
}
return IsMonoClassOrSubclass(monoClass, m_monoBehaviourClass);
}
bool MonoScriptRuntime::HasSerializeFieldAttribute(MonoClassField* field) const {
if (!field || !m_serializeFieldAttributeClass) {
return false;
}
MonoClass* ownerClass = mono_field_get_parent(field);
if (!ownerClass) {
return false;
}
MonoCustomAttrInfo* attributes = mono_custom_attrs_from_field(ownerClass, field);
if (!attributes) {
return false;
}
const mono_bool hasAttribute = mono_custom_attrs_has_attr(attributes, m_serializeFieldAttributeClass);
mono_custom_attrs_free(attributes);
return hasAttribute != 0;
}
MonoScriptRuntime::FieldMetadata MonoScriptRuntime::BuildFieldMetadata(MonoClassField* field) const {
FieldMetadata metadata;
metadata.field = field;
if (!field) {
return metadata;
}
MonoType* monoType = mono_field_get_type(field);
if (!monoType) {
return metadata;
}
switch (mono_type_get_type(monoType)) {
case MONO_TYPE_R4:
metadata.type = ScriptFieldType::Float;
return metadata;
case MONO_TYPE_R8:
metadata.type = ScriptFieldType::Double;
return metadata;
case MONO_TYPE_BOOLEAN:
metadata.type = ScriptFieldType::Bool;
return metadata;
case MONO_TYPE_I4:
metadata.type = ScriptFieldType::Int32;
return metadata;
case MONO_TYPE_U8:
metadata.type = ScriptFieldType::UInt64;
return metadata;
case MONO_TYPE_STRING:
metadata.type = ScriptFieldType::String;
return metadata;
case MONO_TYPE_CLASS: {
MonoClass* referenceClass = mono_class_from_mono_type(monoType);
if (!referenceClass) {
return metadata;
}
const std::string namespaceName = SafeString(mono_class_get_namespace(referenceClass));
const std::string className = SafeString(mono_class_get_name(referenceClass));
if (namespaceName == m_settings.baseNamespace && className == "GameObject") {
metadata.type = ScriptFieldType::GameObject;
return metadata;
}
if (IsSupportedComponentFieldClass(referenceClass)) {
metadata.type = ScriptFieldType::Component;
metadata.componentClass = referenceClass;
}
return metadata;
}
case MONO_TYPE_VALUETYPE: {
MonoClass* valueTypeClass = mono_class_from_mono_type(monoType);
if (!valueTypeClass) {
return metadata;
}
if (mono_class_is_enum(valueTypeClass) != 0) {
MonoType* underlyingType = mono_class_enum_basetype(valueTypeClass);
if (!underlyingType) {
return metadata;
}
switch (mono_type_get_type(underlyingType)) {
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_I2:
case MONO_TYPE_U2:
case MONO_TYPE_I4:
case MONO_TYPE_U4:
metadata.type = ScriptFieldType::Int32;
metadata.isEnum = true;
metadata.enumUnderlyingType = static_cast<int32_t>(mono_type_get_type(underlyingType));
return metadata;
default:
return metadata;
}
}
const std::string namespaceName = SafeString(mono_class_get_namespace(valueTypeClass));
const std::string className = SafeString(mono_class_get_name(valueTypeClass));
if (namespaceName != m_settings.baseNamespace) {
return metadata;
}
if (className == "Vector2") {
metadata.type = ScriptFieldType::Vector2;
return metadata;
}
if (className == "Vector3") {
metadata.type = ScriptFieldType::Vector3;
return metadata;
}
if (className == "Vector4") {
metadata.type = ScriptFieldType::Vector4;
return metadata;
}
return metadata;
}
default:
return metadata;
}
}
const char* MonoScriptRuntime::ToLifecycleMethodName(ScriptLifecycleMethod method) {
switch (method) {
case ScriptLifecycleMethod::Awake: return "Awake";
case ScriptLifecycleMethod::OnEnable: return "OnEnable";
case ScriptLifecycleMethod::Start: return "Start";
case ScriptLifecycleMethod::FixedUpdate: return "FixedUpdate";
case ScriptLifecycleMethod::Update: return "Update";
case ScriptLifecycleMethod::LateUpdate: return "LateUpdate";
case ScriptLifecycleMethod::OnDisable: return "OnDisable";
case ScriptLifecycleMethod::OnDestroy: return "OnDestroy";
}
return "";
}
const char* MonoScriptRuntime::ToPhysicsMessageMethodName(ScriptPhysicsMessage message) {
switch (message) {
case ScriptPhysicsMessage::CollisionEnter: return "OnCollisionEnter";
case ScriptPhysicsMessage::CollisionStay: return "OnCollisionStay";
case ScriptPhysicsMessage::CollisionExit: return "OnCollisionExit";
case ScriptPhysicsMessage::TriggerEnter: return "OnTriggerEnter";
case ScriptPhysicsMessage::TriggerStay: return "OnTriggerStay";
case ScriptPhysicsMessage::TriggerExit: return "OnTriggerExit";
}
return "";
}
const MonoScriptRuntime::ClassMetadata* MonoScriptRuntime::FindClassMetadata(
const std::string& assemblyName,
const std::string& namespaceName,
const std::string& className) const {
const auto it = m_classes.find(BuildClassKey(assemblyName, namespaceName, className));
return it != m_classes.end() ? &it->second : nullptr;
}
bool MonoScriptRuntime::ResolveManagedClass(
const std::string& assemblyName,
const std::string& namespaceName,
const std::string& className,
MonoClass*& outClass) const {
outClass = nullptr;
if (!m_initialized || assemblyName.empty() || className.empty()) {
return false;
}
MonoImage* image = FindLoadedAssemblyImage(assemblyName);
if (!image) {
return false;
}
SetCurrentDomain();
outClass = mono_class_from_name(
image,
namespaceName.c_str(),
className.c_str());
return outClass != nullptr;
}
bool MonoScriptRuntime::CreateExternalManagedObject(
const std::string& assemblyName,
const std::string& namespaceName,
const std::string& className,
uint32_t& outHandle) {
outHandle = 0;
MonoClass* monoClass = nullptr;
if (!ResolveManagedClass(
assemblyName,
namespaceName,
className,
monoClass)) {
SetError(
"Managed class was not found: " +
assemblyName + "|" +
BuildFullClassName(namespaceName, className));
return false;
}
return CreateExternalManagedObject(monoClass, outHandle);
}
bool MonoScriptRuntime::CreateExternalManagedObject(
MonoClass* monoClass,
uint32_t& outHandle) {
outHandle = 0;
if (!m_initialized || !monoClass) {
return false;
}
SetCurrentDomain();
MonoObject* const instance = mono_object_new(m_appDomain, monoClass);
if (!instance) {
SetError(
"Mono failed to allocate a managed object for " +
BuildFullClassName(
SafeString(mono_class_get_namespace(monoClass)),
SafeString(mono_class_get_name(monoClass))) + ".");
return false;
}
mono_runtime_object_init(instance);
outHandle = RetainExternalManagedObject(instance);
return outHandle != 0;
}
uint32_t MonoScriptRuntime::RetainExternalManagedObject(MonoObject* instance) {
if (!m_initialized || !instance) {
return 0;
}
SetCurrentDomain();
const uint32_t gcHandle = mono_gchandle_new(instance, false);
if (gcHandle == 0) {
return 0;
}
m_externalManagedObjects[gcHandle] = ExternalManagedObjectData{
mono_object_get_class(instance),
gcHandle
};
return gcHandle;
}
MonoObject* MonoScriptRuntime::GetExternalManagedObject(uint32_t gcHandle) const {
return GetManagedObject(gcHandle);
}
uint32_t MonoScriptRuntime::RetainExternalManagedObjectReference(
MonoObject* managedObject) {
return RetainExternalManagedObject(managedObject);
}
void MonoScriptRuntime::ReleaseExternalManagedObject(uint32_t gcHandle) {
DestroyExternalManagedObject(gcHandle);
}
bool MonoScriptRuntime::IsScriptableRenderPipelineAssetObject(
MonoObject* managedObject) const {
return managedObject != nullptr &&
m_scriptableRenderPipelineAssetClass != nullptr &&
IsMonoClassOrSubclass(
mono_object_get_class(managedObject),
m_scriptableRenderPipelineAssetClass);
}
bool MonoScriptRuntime::TryEnsureManagedRenderPipelineAssetHandle(
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& ioDescriptor) {
if (!m_initialized || !ioDescriptor.IsValid()) {
return false;
}
if (ioDescriptor.managedAssetHandle != 0u) {
MonoObject* const assetObject =
GetExternalManagedObject(ioDescriptor.managedAssetHandle);
if (IsScriptableRenderPipelineAssetObject(assetObject)) {
return true;
}
ioDescriptor.managedAssetHandle = 0u;
}
MonoClass* assetClass = nullptr;
if (!ResolveManagedClass(
ioDescriptor.assemblyName,
ioDescriptor.namespaceName,
ioDescriptor.className,
assetClass) ||
assetClass == nullptr) {
return false;
}
if (!IsMonoClassOrSubclass(
assetClass,
m_scriptableRenderPipelineAssetClass)) {
SetError(
"Managed render pipeline asset must derive from ScriptableRenderPipelineAsset: " +
ioDescriptor.GetFullName() + ".");
return false;
}
return CreateExternalManagedObject(assetClass, ioDescriptor.managedAssetHandle) &&
ioDescriptor.managedAssetHandle != 0u;
}
void MonoScriptRuntime::DestroyExternalManagedObject(uint32_t gcHandle) {
if (gcHandle == 0) {
return;
}
const auto it = m_externalManagedObjects.find(gcHandle);
if (it == m_externalManagedObjects.end()) {
return;
}
SetCurrentDomain();
mono_gchandle_free(gcHandle);
m_externalManagedObjects.erase(it);
}
MonoObject* MonoScriptRuntime::CreateManagedScriptableRenderContext(
uint64_t nativeHandle) {
if (!m_initialized ||
nativeHandle == 0 ||
m_scriptableRenderContextClass == nullptr ||
m_scriptableRenderContextConstructor == nullptr) {
return nullptr;
}
SetCurrentDomain();
MonoObject* const contextObject =
mono_object_new(m_appDomain, m_scriptableRenderContextClass);
if (contextObject == nullptr) {
SetError(
"Mono failed to allocate a managed ScriptableRenderContext.");
return nullptr;
}
void* args[1];
uint64_t nativeHandleArgument = nativeHandle;
args[0] = &nativeHandleArgument;
MonoObject* exception = nullptr;
mono_runtime_invoke(
m_scriptableRenderContextConstructor,
contextObject,
args,
&exception);
if (exception != nullptr) {
RecordException(exception);
return nullptr;
}
return contextObject;
}
MonoObject*
MonoScriptRuntime::CreateManagedCameraRenderRequestContext(
uint64_t nativeHandle) {
if (!m_initialized ||
nativeHandle == 0 ||
m_cameraRenderRequestContextClass == nullptr ||
m_cameraRenderRequestContextConstructor == nullptr) {
return nullptr;
}
SetCurrentDomain();
MonoObject* const contextObject =
mono_object_new(
m_appDomain,
m_cameraRenderRequestContextClass);
if (contextObject == nullptr) {
SetError(
"Mono failed to allocate a managed CameraRenderRequestContext.");
return nullptr;
}
void* args[1];
uint64_t nativeHandleArgument = nativeHandle;
args[0] = &nativeHandleArgument;
MonoObject* exception = nullptr;
mono_runtime_invoke(
m_cameraRenderRequestContextConstructor,
contextObject,
args,
&exception);
if (exception != nullptr) {
RecordException(exception);
return nullptr;
}
return contextObject;
}
MonoObject*
MonoScriptRuntime::CreateManagedRenderSceneSetupContext(
uint64_t nativeHandle) {
if (!m_initialized ||
nativeHandle == 0 ||
m_renderSceneSetupContextClass == nullptr ||
m_renderSceneSetupContextConstructor == nullptr) {
return nullptr;
}
SetCurrentDomain();
MonoObject* const contextObject =
mono_object_new(
m_appDomain,
m_renderSceneSetupContextClass);
if (contextObject == nullptr) {
SetError(
"Mono failed to allocate a managed RenderSceneSetupContext.");
return nullptr;
}
void* args[1];
uint64_t nativeHandleArgument = nativeHandle;
args[0] = &nativeHandleArgument;
MonoObject* exception = nullptr;
mono_runtime_invoke(
m_renderSceneSetupContextConstructor,
contextObject,
args,
&exception);
if (exception != nullptr) {
RecordException(exception);
return nullptr;
}
return contextObject;
}
MonoObject*
MonoScriptRuntime::CreateManagedDirectionalShadowExecutionContext(
uint64_t nativeHandle) {
if (!m_initialized ||
nativeHandle == 0 ||
m_directionalShadowExecutionContextClass == nullptr ||
m_directionalShadowExecutionContextConstructor == nullptr) {
return nullptr;
}
SetCurrentDomain();
MonoObject* const contextObject =
mono_object_new(
m_appDomain,
m_directionalShadowExecutionContextClass);
if (contextObject == nullptr) {
SetError(
"Mono failed to allocate a managed DirectionalShadowExecutionContext.");
return nullptr;
}
void* args[1];
uint64_t nativeHandleArgument = nativeHandle;
args[0] = &nativeHandleArgument;
MonoObject* exception = nullptr;
mono_runtime_invoke(
m_directionalShadowExecutionContextConstructor,
contextObject,
args,
&exception);
if (exception != nullptr) {
RecordException(exception);
return nullptr;
}
return contextObject;
}
MonoObject*
MonoScriptRuntime::CreateManagedScriptableRenderPipelinePlanningContext(
uint64_t nativeHandle) {
if (!m_initialized ||
nativeHandle == 0 ||
m_scriptableRenderPipelinePlanningContextClass == nullptr ||
m_scriptableRenderPipelinePlanningContextConstructor == nullptr) {
return nullptr;
}
SetCurrentDomain();
MonoObject* const contextObject =
mono_object_new(
m_appDomain,
m_scriptableRenderPipelinePlanningContextClass);
if (contextObject == nullptr) {
SetError(
"Mono failed to allocate a managed ScriptableRenderPipelinePlanningContext.");
return nullptr;
}
void* args[1];
uint64_t nativeHandleArgument = nativeHandle;
args[0] = &nativeHandleArgument;
MonoObject* exception = nullptr;
mono_runtime_invoke(
m_scriptableRenderPipelinePlanningContextConstructor,
contextObject,
args,
&exception);
if (exception != nullptr) {
RecordException(exception);
return nullptr;
}
return contextObject;
}
MonoScriptRuntime::InstanceData* MonoScriptRuntime::FindInstance(const ScriptRuntimeContext& context) {
const auto it = m_instances.find(InstanceKey{context.gameObjectUUID, context.scriptComponentUUID});
return it != m_instances.end() ? &it->second : nullptr;
}
const MonoScriptRuntime::InstanceData* MonoScriptRuntime::FindInstance(const ScriptRuntimeContext& context) const {
const auto it = m_instances.find(InstanceKey{context.gameObjectUUID, context.scriptComponentUUID});
return it != m_instances.end() ? &it->second : nullptr;
}
const MonoScriptRuntime::InstanceData* MonoScriptRuntime::FindInstance(const ScriptComponent* component) const {
if (!component || !component->GetGameObject()) {
return nullptr;
}
const auto it = m_instances.find(InstanceKey{
component->GetGameObject()->GetUUID(),
component->GetScriptComponentUUID()
});
return it != m_instances.end() ? &it->second : nullptr;
}
MonoObject* MonoScriptRuntime::GetManagedObject(const InstanceData& instanceData) const {
if (instanceData.gcHandle == 0) {
return nullptr;
}
SetCurrentDomain();
return mono_gchandle_get_target(instanceData.gcHandle);
}
MonoObject* MonoScriptRuntime::GetManagedObject(uint32_t gcHandle) const {
if (gcHandle == 0 ||
m_externalManagedObjects.find(gcHandle) == m_externalManagedObjects.end()) {
return nullptr;
}
SetCurrentDomain();
return mono_gchandle_get_target(gcHandle);
}
MonoMethod* MonoScriptRuntime::ResolveManagedMethod(
MonoClass* monoClass,
const char* methodName,
int parameterCount) const {
if (!monoClass || !methodName) {
return nullptr;
}
SetCurrentDomain();
for (MonoClass* currentClass = monoClass;
currentClass != nullptr;
currentClass = mono_class_get_parent(currentClass)) {
if (MonoMethod* const method =
mono_class_get_method_from_name(
currentClass,
methodName,
parameterCount);
method != nullptr) {
return method;
}
}
return nullptr;
}
MonoMethod* MonoScriptRuntime::ResolveManagedMethod(
MonoObject* instance,
const char* methodName,
int parameterCount) const {
return instance != nullptr
? ResolveManagedMethod(
mono_object_get_class(instance),
methodName,
parameterCount)
: nullptr;
}
bool MonoScriptRuntime::ApplyContextFields(const ScriptRuntimeContext& context, MonoObject* instance) {
if (!instance) {
return false;
}
SetCurrentDomain();
if (m_gameObjectUUIDField) {
uint64_t gameObjectUUID = context.gameObjectUUID;
mono_field_set_value(instance, m_gameObjectUUIDField, &gameObjectUUID);
}
if (m_scriptComponentUUIDField) {
uint64_t scriptComponentUUID = context.scriptComponentUUID;
mono_field_set_value(instance, m_scriptComponentUUIDField, &scriptComponentUUID);
}
return true;
}
bool MonoScriptRuntime::ApplyStoredFields(
const ScriptRuntimeContext& context,
const ClassMetadata& metadata,
MonoObject* instance) {
if (!context.component || !instance) {
return false;
}
const ScriptFieldStorage& fieldStorage = context.component->GetFieldStorage();
for (const std::string& fieldName : fieldStorage.GetFieldNames()) {
const StoredScriptField* storedField = fieldStorage.FindField(fieldName);
if (!storedField) {
continue;
}
const auto metadataIt = metadata.fields.find(fieldName);
if (metadataIt == metadata.fields.end() || storedField->type != metadataIt->second.type) {
continue;
}
if (!TrySetFieldValue(instance, metadataIt->second, storedField->value)) {
return false;
}
}
return true;
}
MonoObject* MonoScriptRuntime::CreateManagedComponentWrapper(MonoClass* componentClass, uint64_t gameObjectUUID) {
if (!m_initialized || !componentClass || gameObjectUUID == 0) {
return nullptr;
}
SetCurrentDomain();
MonoMethod* constructor = mono_class_get_method_from_name(componentClass, ".ctor", 1);
if (!constructor) {
return nullptr;
}
MonoObject* managedObject = mono_object_new(m_appDomain, componentClass);
if (!managedObject) {
return nullptr;
}
void* args[1];
uint64_t uuidArgument = gameObjectUUID;
args[0] = &uuidArgument;
MonoObject* exception = nullptr;
mono_runtime_invoke(constructor, managedObject, args, &exception);
if (exception) {
RecordException(exception);
return nullptr;
}
return managedObject;
}
MonoObject* MonoScriptRuntime::CreateManagedGameObject(uint64_t gameObjectUUID) {
if (gameObjectUUID == 0 || !m_gameObjectClass || !m_gameObjectConstructor) {
return nullptr;
}
SetCurrentDomain();
MonoObject* managedObject = mono_object_new(m_appDomain, m_gameObjectClass);
if (!managedObject) {
return nullptr;
}
void* args[1];
uint64_t uuidArgument = gameObjectUUID;
args[0] = &uuidArgument;
MonoObject* exception = nullptr;
mono_runtime_invoke(m_gameObjectConstructor, managedObject, args, &exception);
if (exception) {
RecordException(exception);
return nullptr;
}
return managedObject;
}
bool MonoScriptRuntime::TryExtractComponentReference(
MonoObject* managedObject,
ComponentReference& outReference) const {
outReference = ComponentReference{};
if (!managedObject) {
return true;
}
if (!m_componentClass || !m_gameObjectUUIDField) {
return false;
}
SetCurrentDomain();
MonoClass* monoClass = mono_object_get_class(managedObject);
if (!IsMonoClassOrSubclass(monoClass, m_componentClass)) {
return false;
}
uint64_t gameObjectUUID = 0;
mono_field_get_value(managedObject, m_gameObjectUUIDField, &gameObjectUUID);
if (gameObjectUUID == 0) {
return false;
}
uint64_t scriptComponentUUID = 0;
if (m_scriptComponentUUIDField && IsMonoClassOrSubclass(monoClass, m_behaviourClass)) {
mono_field_get_value(managedObject, m_scriptComponentUUIDField, &scriptComponentUUID);
}
outReference = ComponentReference{gameObjectUUID, scriptComponentUUID};
return true;
}
bool MonoScriptRuntime::DestroyManagedObject(MonoObject* managedObject) {
if (!m_initialized || !managedObject) {
return false;
}
SetCurrentDomain();
MonoClass* monoClass = mono_object_get_class(managedObject);
if (!monoClass) {
return false;
}
if (monoClass == m_gameObjectClass) {
uint64_t gameObjectUUID = 0;
mono_field_get_value(managedObject, m_managedGameObjectUUIDField, &gameObjectUUID);
Components::Scene* scene = GetInternalCallScene();
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!scene || !gameObject || gameObject->GetScene() != scene) {
return false;
}
scene->DestroyGameObject(gameObject);
return true;
}
if (monoClass != m_componentClass && !mono_class_is_subclass_of(monoClass, m_componentClass, false)) {
return false;
}
uint64_t gameObjectUUID = 0;
mono_field_get_value(managedObject, m_gameObjectUUIDField, &gameObjectUUID);
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
if (!gameObject) {
return false;
}
if (monoClass == m_behaviourClass || mono_class_is_subclass_of(monoClass, m_behaviourClass, false)) {
uint64_t scriptComponentUUID = 0;
mono_field_get_value(managedObject, m_scriptComponentUUIDField, &scriptComponentUUID);
if (scriptComponentUUID != 0) {
ScriptComponent* component = FindScriptComponentByUUID(scriptComponentUUID);
return DestroyNativeComponentInstance(gameObject, component);
}
}
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(monoClass);
switch (typeInfo.kind) {
case ManagedComponentKind::Rigidbody:
return DestroyNativeComponentInstance(gameObject, gameObject->GetComponent<Components::RigidbodyComponent>());
case ManagedComponentKind::Camera:
return DestroyNativeComponentInstance(gameObject, gameObject->GetComponent<Components::CameraComponent>());
case ManagedComponentKind::Light:
return DestroyNativeComponentInstance(gameObject, gameObject->GetComponent<Components::LightComponent>());
case ManagedComponentKind::MeshFilter:
return DestroyNativeComponentInstance(gameObject, gameObject->GetComponent<Components::MeshFilterComponent>());
case ManagedComponentKind::MeshRenderer:
return DestroyNativeComponentInstance(gameObject, gameObject->GetComponent<Components::MeshRendererComponent>());
case ManagedComponentKind::Transform:
case ManagedComponentKind::Script:
case ManagedComponentKind::Unknown:
return false;
}
return false;
}
bool MonoScriptRuntime::TryExtractGameObjectReference(
MonoObject* managedObject,
GameObjectReference& outReference) const {
outReference = GameObjectReference{};
if (!managedObject) {
return true;
}
if (!m_gameObjectClass || !m_managedGameObjectUUIDField) {
return false;
}
if (mono_object_get_class(managedObject) != m_gameObjectClass) {
return false;
}
uint64_t gameObjectUUID = 0;
mono_field_get_value(managedObject, m_managedGameObjectUUIDField, &gameObjectUUID);
outReference = GameObjectReference{gameObjectUUID};
return true;
}
bool MonoScriptRuntime::TrySetFieldValue(
MonoObject* instance,
const FieldMetadata& fieldMetadata,
const ScriptFieldValue& value) {
if (!instance || !fieldMetadata.field) {
return false;
}
SetCurrentDomain();
if (fieldMetadata.isEnum) {
if (!std::holds_alternative<int32_t>(value)) {
return false;
}
const int32_t storedValue = std::get<int32_t>(value);
switch (fieldMetadata.enumUnderlyingType) {
case MONO_TYPE_I1: {
if (storedValue < std::numeric_limits<int8_t>::min()
|| storedValue > std::numeric_limits<int8_t>::max()) {
return false;
}
int8_t nativeValue = static_cast<int8_t>(storedValue);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case MONO_TYPE_U1: {
if (storedValue < 0 || storedValue > std::numeric_limits<uint8_t>::max()) {
return false;
}
uint8_t nativeValue = static_cast<uint8_t>(storedValue);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case MONO_TYPE_I2: {
if (storedValue < std::numeric_limits<int16_t>::min()
|| storedValue > std::numeric_limits<int16_t>::max()) {
return false;
}
int16_t nativeValue = static_cast<int16_t>(storedValue);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case MONO_TYPE_U2: {
if (storedValue < 0 || storedValue > std::numeric_limits<uint16_t>::max()) {
return false;
}
uint16_t nativeValue = static_cast<uint16_t>(storedValue);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case MONO_TYPE_I4: {
int32_t nativeValue = storedValue;
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case MONO_TYPE_U4: {
if (storedValue < 0) {
return false;
}
uint32_t nativeValue = static_cast<uint32_t>(storedValue);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
default:
return false;
}
}
switch (fieldMetadata.type) {
case ScriptFieldType::Float: {
float nativeValue = std::get<float>(value);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case ScriptFieldType::Double: {
double nativeValue = std::get<double>(value);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case ScriptFieldType::Bool: {
mono_bool nativeValue = std::get<bool>(value) ? 1 : 0;
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case ScriptFieldType::Int32: {
int32_t nativeValue = std::get<int32_t>(value);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case ScriptFieldType::UInt64: {
uint64_t nativeValue = std::get<uint64_t>(value);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case ScriptFieldType::String: {
MonoString* managedString = mono_string_new(m_appDomain, std::get<std::string>(value).c_str());
mono_field_set_value(instance, fieldMetadata.field, managedString);
return true;
}
case ScriptFieldType::Vector2: {
Math::Vector2 nativeValue = std::get<Math::Vector2>(value);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case ScriptFieldType::Vector3: {
Math::Vector3 nativeValue = std::get<Math::Vector3>(value);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case ScriptFieldType::Vector4: {
Math::Vector4 nativeValue = std::get<Math::Vector4>(value);
mono_field_set_value(instance, fieldMetadata.field, &nativeValue);
return true;
}
case ScriptFieldType::GameObject: {
const GameObjectReference reference = std::get<GameObjectReference>(value);
MonoObject* managedGameObject = CreateManagedGameObject(reference.gameObjectUUID);
if (reference.gameObjectUUID != 0 && !managedGameObject) {
return false;
}
mono_field_set_value(instance, fieldMetadata.field, managedGameObject);
return true;
}
case ScriptFieldType::Component: {
const ComponentReference reference = std::get<ComponentReference>(value);
if (reference.gameObjectUUID == 0 && reference.scriptComponentUUID == 0) {
mono_field_set_value(instance, fieldMetadata.field, nullptr);
return true;
}
if (!fieldMetadata.componentClass) {
return false;
}
MonoObject* managedComponent = nullptr;
if (IsScriptComponentFieldClass(fieldMetadata.componentClass)) {
if (reference.gameObjectUUID == 0 || reference.scriptComponentUUID == 0) {
return false;
}
ScriptComponent* component = FindScriptComponentByUUID(reference.scriptComponentUUID);
if (!component
|| !component->GetGameObject()
|| component->GetGameObject()->GetUUID() != reference.gameObjectUUID
|| component->GetAssemblyName() != m_settings.appAssemblyName
|| component->GetNamespaceName() != SafeString(mono_class_get_namespace(fieldMetadata.componentClass))
|| component->GetClassName() != SafeString(mono_class_get_name(fieldMetadata.componentClass))) {
return false;
}
if (!HasManagedInstance(component)) {
ScriptEngine::Get().OnScriptComponentEnabled(component);
}
managedComponent = GetManagedInstanceObject(component);
if (!managedComponent) {
return false;
}
} else {
if (reference.gameObjectUUID == 0 || reference.scriptComponentUUID != 0) {
return false;
}
Components::GameObject* targetObject = FindGameObjectByUUID(reference.gameObjectUUID);
if (!targetObject) {
return false;
}
const std::string namespaceName = SafeString(mono_class_get_namespace(fieldMetadata.componentClass));
const std::string className = SafeString(mono_class_get_name(fieldMetadata.componentClass));
if (namespaceName != m_settings.baseNamespace) {
return false;
}
bool hasComponent = false;
if (className == "Transform") {
hasComponent = targetObject->GetTransform() != nullptr;
} else if (className == "Rigidbody") {
hasComponent = targetObject->GetComponent<Components::RigidbodyComponent>() != nullptr;
} else if (className == "Camera") {
hasComponent = targetObject->GetComponent<Components::CameraComponent>() != nullptr;
} else if (className == "Light") {
hasComponent = targetObject->GetComponent<Components::LightComponent>() != nullptr;
} else if (className == "MeshFilter") {
hasComponent = targetObject->GetComponent<Components::MeshFilterComponent>() != nullptr;
} else if (className == "MeshRenderer") {
hasComponent = targetObject->GetComponent<Components::MeshRendererComponent>() != nullptr;
} else {
return false;
}
if (!hasComponent) {
return false;
}
managedComponent = CreateManagedComponentWrapper(fieldMetadata.componentClass, reference.gameObjectUUID);
if (!managedComponent) {
return false;
}
}
mono_field_set_value(instance, fieldMetadata.field, managedComponent);
return true;
}
case ScriptFieldType::None:
return false;
}
return false;
}
bool MonoScriptRuntime::TryReadFieldValue(
MonoObject* instance,
const FieldMetadata& fieldMetadata,
ScriptFieldValue& outValue) const {
if (!instance || !fieldMetadata.field) {
return false;
}
if (fieldMetadata.isEnum) {
switch (fieldMetadata.enumUnderlyingType) {
case MONO_TYPE_I1: {
int8_t nativeValue = 0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = static_cast<int32_t>(nativeValue);
return true;
}
case MONO_TYPE_U1: {
uint8_t nativeValue = 0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = static_cast<int32_t>(nativeValue);
return true;
}
case MONO_TYPE_I2: {
int16_t nativeValue = 0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = static_cast<int32_t>(nativeValue);
return true;
}
case MONO_TYPE_U2: {
uint16_t nativeValue = 0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = static_cast<int32_t>(nativeValue);
return true;
}
case MONO_TYPE_I4: {
int32_t nativeValue = 0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = nativeValue;
return true;
}
case MONO_TYPE_U4: {
uint32_t nativeValue = 0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
if (nativeValue > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
return false;
}
outValue = static_cast<int32_t>(nativeValue);
return true;
}
default:
return false;
}
}
switch (fieldMetadata.type) {
case ScriptFieldType::Float: {
float nativeValue = 0.0f;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = nativeValue;
return true;
}
case ScriptFieldType::Double: {
double nativeValue = 0.0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = nativeValue;
return true;
}
case ScriptFieldType::Bool: {
mono_bool nativeValue = 0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = (nativeValue != 0);
return true;
}
case ScriptFieldType::Int32: {
int32_t nativeValue = 0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = nativeValue;
return true;
}
case ScriptFieldType::UInt64: {
uint64_t nativeValue = 0;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = nativeValue;
return true;
}
case ScriptFieldType::String: {
MonoObject* managedObject = mono_field_get_value_object(m_appDomain, fieldMetadata.field, instance);
if (!managedObject) {
outValue = std::string();
return true;
}
MonoString* managedString = reinterpret_cast<MonoString*>(managedObject);
char* utf8 = mono_string_to_utf8(managedString);
outValue = utf8 ? std::string(utf8) : std::string();
if (utf8) {
mono_free(utf8);
}
return true;
}
case ScriptFieldType::Vector2: {
Math::Vector2 nativeValue;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = nativeValue;
return true;
}
case ScriptFieldType::Vector3: {
Math::Vector3 nativeValue;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = nativeValue;
return true;
}
case ScriptFieldType::Vector4: {
Math::Vector4 nativeValue;
mono_field_get_value(instance, fieldMetadata.field, &nativeValue);
outValue = nativeValue;
return true;
}
case ScriptFieldType::GameObject: {
MonoObject* managedObject = mono_field_get_value_object(m_appDomain, fieldMetadata.field, instance);
GameObjectReference reference;
if (!TryExtractGameObjectReference(managedObject, reference)) {
return false;
}
outValue = reference;
return true;
}
case ScriptFieldType::Component: {
MonoObject* managedObject = mono_field_get_value_object(m_appDomain, fieldMetadata.field, instance);
ComponentReference reference;
if (!TryExtractComponentReference(managedObject, reference)) {
return false;
}
outValue = reference;
return true;
}
case ScriptFieldType::None:
return false;
}
return false;
}
void MonoScriptRuntime::ClearManagedInstances() {
for (auto& [key, instanceData] : m_instances) {
(void)key;
if (instanceData.gcHandle != 0) {
mono_gchandle_free(instanceData.gcHandle);
}
}
m_instances.clear();
}
void MonoScriptRuntime::ClearExternalManagedObjects() {
for (auto& [gcHandle, objectData] : m_externalManagedObjects) {
(void)objectData;
if (gcHandle != 0) {
mono_gchandle_free(gcHandle);
}
}
m_externalManagedObjects.clear();
}
void MonoScriptRuntime::ClearClassCache() {
m_classes.clear();
m_renderPipelineAssetClasses.clear();
}
MonoImage* MonoScriptRuntime::FindLoadedAssemblyImage(
const std::string& assemblyName) const {
const auto it = m_loadedManagedAssemblies.find(assemblyName);
return it != m_loadedManagedAssemblies.end()
? it->second.image
: nullptr;
}
bool MonoScriptRuntime::InvokeManagedMethod(
MonoObject* instance,
MonoMethod* method,
void** args,
MonoObject** outReturnValue) {
if (!instance || !method) {
if (outReturnValue) {
*outReturnValue = nullptr;
}
return false;
}
SetCurrentDomain();
MonoObject* exception = nullptr;
MonoObject* returnValue = mono_runtime_invoke(method, instance, args, &exception);
if (exception) {
if (outReturnValue) {
*outReturnValue = nullptr;
}
RecordException(exception);
return false;
}
if (outReturnValue) {
*outReturnValue = returnValue;
}
return true;
}
void MonoScriptRuntime::RecordException(MonoObject* exception) {
m_lastError = "Managed exception";
if (!exception) {
return;
}
MonoObject* secondaryException = nullptr;
MonoString* exceptionString = mono_object_to_string(exception, &secondaryException);
if (!exceptionString || secondaryException) {
return;
}
char* utf8 = mono_string_to_utf8(exceptionString);
if (!utf8) {
return;
}
m_lastError = utf8;
mono_free(utf8);
}
void MonoScriptRuntime::SetError(const std::string& error) {
m_lastError = error;
}
} // namespace Scripting
} // namespace XCEngine