#pragma once #pragma region CPL License /* Nuclex Unreal Module Copyright (C) 2014-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #include #include // --------------------------------------------------------------------------------------------- // /// Helper to cast between different 'script' interfaces /// @typeparam TTargetInterface Target interface type /// @typeparam TForeignInterface Source interface from which to cast /// @return An interface pointer to the target interface if it is implemented template TScriptInterface interface_cast( const TScriptInterface &foreign ) { // If the input pointer was empty anyway, return an empty pointer UObject *object = foreign.GetObject(); if(object == nullptr) { return TScriptInterface(); } // Try to cast the input UObject to its IInterface. This only works if // the interface is implemented in C++, otherwise it will return nullptr. // Internally, GetInterfaceAddress(To::UClassType::StaticClass()) is called. TTargetInterface *targetInterface = Cast(object); if(targetInterface == nullptr) { // Interface is not implemented in C++ (or a layer of Blueprint sits inbetween). // It is still possible that the object will /claim/ to implement the interface // and offers all of the interface methods via Unreal's poor reflection API. if(object->GetClass()->ImplementsInterface(TTargetInterface::UClassType::StaticClass())) { TScriptInterface result; result.SetObject(object); return result; } } else { // The UObject actually inherits from the IInterface class in C++, // so we're done and can enable direct calls, too. TScriptInterface result; result.SetObject(object); result.SetInterface(targetInterface); return result; } // Interface is neither inherited or faked by the foreign object, return empty return TScriptInterface(); } // --------------------------------------------------------------------------------------------- // /// Helper to cast from an UObject to a 'script' interface /// @typeparam TTargetInterface Target interface type /// @return An interface pointer to the target interface if it is implemented template TScriptInterface interface_cast(UObject *object) { // If the input pointer was empty anyway, return an empty pointer if(object == nullptr) { return TScriptInterface(); } // Try to cast the input UObject to its IInterface. This only works if // the interface is implemented in C++, otherwise it will return nullptr. // Internally, GetInterfaceAddress(To::UClassType::StaticClass()) is called. TTargetInterface *targetInterface = Cast(object); if(targetInterface == nullptr) { // Interface is not implemented in C++ (or a layer of Blueprint sits inbetween). // It is still possible that the object will /claim/ to implement the interface // and offers all of the interface methods via Unreal's poor reflection API. if(object->GetClass()->ImplementsInterface(TTargetInterface::UClassType::StaticClass())) { TScriptInterface result; result.SetObject(object); return result; } } else { // The UObject actually inherits from the IInterface class in C++, // so we're done and can enable direct calls, too. TScriptInterface result; result.SetObject(object); result.SetInterface(targetInterface); return result; } // Interface is neither inherited nor faked by the foreign object, return empty return TScriptInterface(); } // --------------------------------------------------------------------------------------------- //