/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. // Description : Part of CryEngine's extension framework. #ifndef CRYINCLUDE_CRYEXTENSION_ICRYUNKNOWN_H #define CRYINCLUDE_CRYEXTENSION_ICRYUNKNOWN_H #pragma once #include "CryTypeID.h" #include struct ICryFactory; struct ICryUnknown; namespace InterfaceCastSemantics { template const CryInterfaceID& cryiidof() { return T::IID(); } #define _BEFRIEND_CRYIIDOF() \ template \ friend const CryInterfaceID&InterfaceCastSemantics::cryiidof(); template Dst* cryinterface_cast(Src* p) { return static_cast(p ? p->QueryInterface(cryiidof()) : 0); } template Dst* cryinterface_cast(const Src* p) { return static_cast(p ? p->QueryInterface(cryiidof()) : 0); } namespace Internal { template struct cryinterface_cast_shared_ptr_helper; template struct cryinterface_cast_shared_ptr_helper { static AZStd::shared_ptr Op(const AZStd::shared_ptr& p) { Dst* dp = cryinterface_cast(p.get()); return dp ? AZStd::shared_ptr(p, dp) : AZStd::shared_ptr(); } }; template struct cryinterface_cast_shared_ptr_helper { static AZStd::shared_ptr Op(const AZStd::shared_ptr& p) { ICryUnknown* dp = cryinterface_cast(p.get()); return dp ? AZStd::shared_ptr(*((const AZStd::shared_ptr*) & p), dp) : AZStd::shared_ptr(); } }; template struct cryinterface_cast_shared_ptr_helper { static AZStd::shared_ptr Op(const AZStd::shared_ptr& p) { const ICryUnknown* dp = cryinterface_cast(p.get()); return dp ? AZStd::shared_ptr(*((const AZStd::shared_ptr*) & p), dp) : AZStd::shared_ptr(); } }; } // namespace Internal template AZStd::shared_ptr cryinterface_cast(const AZStd::shared_ptr& p) { return Internal::cryinterface_cast_shared_ptr_helper::Op(p); } #define _BEFRIEND_CRYINTERFACE_CAST() \ template \ friend Dst * InterfaceCastSemantics::cryinterface_cast(Src*); \ template \ friend Dst * InterfaceCastSemantics::cryinterface_cast(const Src*); \ template \ friend AZStd::shared_ptr InterfaceCastSemantics::cryinterface_cast(const AZStd::shared_ptr&); } // namespace InterfaceCastSemantics using InterfaceCastSemantics::cryiidof; using InterfaceCastSemantics::cryinterface_cast; template bool CryIsSameClassInstance(S* p0, T* p1) { return static_cast(p0) == static_cast(p1) || cryinterface_cast(p0) == cryinterface_cast(p1); } template bool CryIsSameClassInstance(const AZStd::shared_ptr& p0, T* p1) { return CryIsSameClassInstance(p0.get(), p1); } template bool CryIsSameClassInstance(S* p0, const AZStd::shared_ptr& p1) { return CryIsSameClassInstance(p0, p1.get()); } template bool CryIsSameClassInstance(const AZStd::shared_ptr& p0, const AZStd::shared_ptr& p1) { return CryIsSameClassInstance(p0.get(), p1.get()); } namespace CompositeQuerySemantics { template AZStd::shared_ptr crycomposite_query(Src* p, const char* name, bool* pExposed = 0) { void* pComposite = p ? p->QueryComposite(name) : 0; pExposed ? *pExposed = pComposite != 0 : 0; return pComposite ? *static_cast*>(pComposite) : AZStd::shared_ptr(); } template AZStd::shared_ptr crycomposite_query(const Src* p, const char* name, bool* pExposed = 0) { void* pComposite = p ? p->QueryComposite(name) : 0; pExposed ? *pExposed = pComposite != 0 : 0; return pComposite ? *static_cast*>(pComposite) : AZStd::shared_ptr(); } template AZStd::shared_ptr crycomposite_query(const AZStd::shared_ptr& p, const char* name, bool* pExposed = 0) { return crycomposite_query(p.get(), name, pExposed); } template AZStd::shared_ptr crycomposite_query(const AZStd::shared_ptr& p, const char* name, bool* pExposed = 0) { return crycomposite_query(p.get(), name, pExposed); } #define _BEFRIEND_CRYCOMPOSITE_QUERY() \ template \ friend AZStd::shared_ptr CompositeQuerySemantics::crycomposite_query(Src*, const char*, bool*); \ template \ friend AZStd::shared_ptr CompositeQuerySemantics::crycomposite_query(const Src*, const char*, bool*); \ template \ friend AZStd::shared_ptr CompositeQuerySemantics::crycomposite_query(const AZStd::shared_ptr&, const char*, bool*); \ template \ friend AZStd::shared_ptr CompositeQuerySemantics::crycomposite_query(const AZStd::shared_ptr&, const char*, bool*); } // namespace CompositeQuerySemantics using CompositeQuerySemantics::crycomposite_query; #define _BEFRIEND_MAKE_SHARED() \ template \ friend class AZStd::Internal::sp_ms_deleter; \ template \ friend AZStd::shared_ptr AZStd::make_shared(); \ template \ friend AZStd::shared_ptr AZStd::allocate_shared(A const& a); // prevent explicit destruction from client side #define _PROTECTED_DTOR(iname) \ protected: \ virtual ~iname() {} // Befriending cryinterface_cast() and crycomposite_query() via CRYINTERFACE_DECLARE is actually only needed for ICryUnknown // since QueryInterface() and QueryComposite() are usually not redeclared in derived interfaces but it doesn't hurt either #define CRYINTERFACE_DECLARE(iname, iidHigh, iidLow) \ _BEFRIEND_CRYIIDOF() \ _BEFRIEND_CRYINTERFACE_CAST() \ _BEFRIEND_CRYCOMPOSITE_QUERY() \ _BEFRIEND_MAKE_SHARED() \ _PROTECTED_DTOR(iname) \ \ private: \ static const CryInterfaceID& IID() \ { \ static const CryInterfaceID iid = {(uint64) iidHigh##LL, (uint64) iidLow##LL}; \ return iid; \ } \ public: struct ICryUnknown { CRYINTERFACE_DECLARE(ICryUnknown, 0x1000000010001000, 0x1000100000000000) virtual ICryFactory * GetFactory() const = 0; protected: virtual void* QueryInterface(const CryInterfaceID& iid) const = 0; virtual void* QueryComposite(const char* name) const = 0; }; DECLARE_SMART_POINTERS(ICryUnknown); #endif // CRYINCLUDE_CRYEXTENSION_ICRYUNKNOWN_H