#include "pch.h"
#include "AGCVector.h"
#include "AGCOrientation.h"
TC_OBJECT_EXTERN_IMPL(CAGCOrientation)
HRESULT CAGCOrientation::GetRawOrientation(IAGCOrientation* pOrientation,
Orientation* pOrientationRaw)
{
__try
{
if (!pOrientation)
return E_POINTER;
IAGCOrientationPrivate* pPrivate = NULL;
RETURN_FAILED(pOrientation->QueryInterface(__uuidof(pPrivate),
(void**)&pPrivate));
assert(pPrivate);
if (!pPrivate)
return E_INVALIDARG;
HRESULT hr = pPrivate->CopyOrientationTo(pOrientationRaw);
pPrivate->Release();
return hr;
}
__except(1)
{
return E_POINTER;
}
}
HRESULT CAGCOrientation::CreateResultVector(const Vector* pVectorRaw,
IAGCVector** ppResult)
{
CComObject<CAGCVector>* pVector = NULL;
RETURN_FAILED(pVector->CreateInstance(&pVector));
IAGCVectorPtr spVector(pVector);
RETURN_FAILED(pVector->InitFromVector(pVectorRaw));
CLEAROUT(ppResult, (IAGCVector*)spVector);
spVector.Detach();
return S_OK;
}
STDMETHODIMP CAGCOrientation::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IAGCOrientation
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP CAGCOrientation::GetClassID(CLSID* pClassID)
{
__try
{
*pClassID = GetObjectCLSID();
}
__except(1)
{
return E_POINTER;
}
return S_OK;
}
STDMETHODIMP CAGCOrientation::IsDirty()
{
XLock lock(this);
return m_bDirty ? S_OK : S_FALSE;
}
STDMETHODIMP CAGCOrientation::Load(LPSTREAM pStm)
{
long cDims;
RETURN_FAILED(pStm->Read(&cDims, sizeof(cDims), NULL));
if (DIMENSIONS != cDims)
{
assert(DIMENSIONS == cDims);
return ERROR_INVALID_DATA;
}
float r[3][3];
for (int i = 0; i < DIMENSIONS; ++i)
RETURN_FAILED(pStm->Read(&r[i/3][i%3], sizeof(float), NULL));
Orientation orientation(r);
return InitFromOrientation(&orientation);
}
STDMETHODIMP CAGCOrientation::Save(LPSTREAM pStm, BOOL fClearDirty)
{
long cDims = DIMENSIONS;
RETURN_FAILED(pStm->Write(&cDims, sizeof(cDims), NULL));
XLock lock(this);
for (int i = 0; i < DIMENSIONS; ++i)
{
float r = m_orientation[i/3][i%3];
RETURN_FAILED(pStm->Write(&r, sizeof(r), NULL));
}
if (fClearDirty)
m_bDirty = false;
return S_OK;
}
STDMETHODIMP CAGCOrientation::GetSizeMax(ULARGE_INTEGER* pCbSize)
{
__try
{
pCbSize->LowPart = sizeof(long) + sizeof(float) * DIMENSIONS;
pCbSize->HighPart = 0;
}
__except(1)
{
return E_POINTER;
}
return S_OK;
}
STDMETHODIMP CAGCOrientation::InitNew( void)
{
XLock lock(this);
m_orientation.Reset();
return S_OK;
}
STDMETHODIMP CAGCOrientation::InitCopy(IAGCOrientation* pOrientation)
{
Orientation orientation;
RETURN_FAILED(GetRawOrientation(pOrientation, &orientation));
return InitFromOrientation(&orientation);
}
STDMETHODIMP CAGCOrientation::get_Forward(IAGCVector** ppVector)
{
XLock lock(this);
return CreateResultVector(&m_orientation.GetForward(), ppVector);
}
STDMETHODIMP CAGCOrientation::get_Backward(IAGCVector** ppVector)
{
XLock lock(this);
return CreateResultVector(&m_orientation.GetBackward(), ppVector);
}
STDMETHODIMP CAGCOrientation::get_Up(IAGCVector** ppVector)
{
XLock lock(this);
return CreateResultVector(&m_orientation.GetUp(), ppVector);
}
STDMETHODIMP CAGCOrientation::get_Right(IAGCVector** ppVector)
{
XLock lock(this);
return CreateResultVector(&m_orientation.GetRight(), ppVector);
}
STDMETHODIMP CAGCOrientation::get_IsEqual(IAGCOrientation* pOrientation,
VARIANT_BOOL* pbIsEqual)
{
Orientation orientation;
RETURN_FAILED(GetRawOrientation(pOrientation, &orientation));
XLock lock(this);
const size_t cbData = sizeof(*m_orientation[0]) * DIMENSIONS;
bool bEqual = !memcmp(m_orientation[0], orientation[0], cbData);
CLEAROUT(pbIsEqual, VARBOOL(bEqual));
return S_OK;
}
STDMETHODIMP CAGCOrientation::get_IsRoughlyEqual(
IAGCOrientation* pOrientation, VARIANT_BOOL* pbIsEqual)
{
Orientation orientation;
RETURN_FAILED(GetRawOrientation(pOrientation, &orientation));
XLock lock(this);
bool bEqual = m_orientation == orientation;
CLEAROUT(pbIsEqual, VARBOOL(bEqual));
return S_OK;
}
STDMETHODIMP CAGCOrientation::InitFromOrientation(const void* pvOrientation)
{
Orientation orientationTemp;
const Orientation* pOrientation =
reinterpret_cast<const Orientation*>(pvOrientation);
if (!pOrientation)
pOrientation = &orientationTemp;
XLock lock(this);
const size_t cbData = sizeof(*m_orientation[0]) * DIMENSIONS;
bool bEqual = !memcmp(m_orientation[0], (*pOrientation)[0], cbData);
if (!bEqual)
{
m_orientation = *pOrientation;
m_bDirty = true;
}
return S_OK;
}
STDMETHODIMP CAGCOrientation::CopyOrientationTo(void* pvOrientation)
{
XLock lock(this);
Orientation* pOrientation = reinterpret_cast<Orientation*>(pvOrientation);
*pOrientation = m_orientation;
return S_OK;
}