///////////////////////////////////////////////////////////////////////////// // AGCOrientation.cpp : Implementation of CAGCOrientation // #include "pch.h" #include "AGCVector.h" #include "AGCOrientation.h" ///////////////////////////////////////////////////////////////////////////// // COrientation TC_OBJECT_EXTERN_IMPL(CAGCOrientation) ///////////////////////////////////////////////////////////////////////////// // Implementation 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* pVector = NULL; RETURN_FAILED(pVector->CreateInstance(&pVector)); IAGCVectorPtr spVector(pVector); RETURN_FAILED(pVector->InitFromVector(pVectorRaw)); CLEAROUT(ppResult, (IAGCVector*)spVector); spVector.Detach(); return S_OK; } ///////////////////////////////////////////////////////////////////////////// // ISupportErrorInfo Interface Methods 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; } ///////////////////////////////////////////////////////////////////////////// // IPersist Interface Methods STDMETHODIMP CAGCOrientation::GetClassID(CLSID* pClassID) { __try { *pClassID = GetObjectCLSID(); } __except(1) { return E_POINTER; } return S_OK; } ///////////////////////////////////////////////////////////////////////////// // IPersistStreamInit Interface Methods STDMETHODIMP CAGCOrientation::IsDirty() { // Return dirty flag XLock lock(this); return m_bDirty ? S_OK : S_FALSE; } STDMETHODIMP CAGCOrientation::Load(LPSTREAM pStm) { // Read the number of floats being read long cDims; RETURN_FAILED(pStm->Read(&cDims, sizeof(cDims), NULL)); if (DIMENSIONS != cDims) { assert(DIMENSIONS == cDims); return ERROR_INVALID_DATA; } // Read each float from the stream float r[3][3]; for (int i = 0; i < DIMENSIONS; ++i) RETURN_FAILED(pStm->Read(&r[i/3][i%3], sizeof(float), NULL)); // Save the values Orientation orientation(r); return InitFromOrientation(&orientation); } STDMETHODIMP CAGCOrientation::Save(LPSTREAM pStm, BOOL fClearDirty) { // Write out the number of floats being written long cDims = DIMENSIONS; RETURN_FAILED(pStm->Write(&cDims, sizeof(cDims), NULL)); // Write each float to the stream 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)); } // Clear the dirty flag, if specified if (fClearDirty) m_bDirty = false; // Indicate success return S_OK; } STDMETHODIMP CAGCOrientation::GetSizeMax(ULARGE_INTEGER* pCbSize) { __try { // NOTE: This needs to exactly match what's written in Save pCbSize->LowPart = sizeof(long) + sizeof(float) * DIMENSIONS; pCbSize->HighPart = 0; } __except(1) { return E_POINTER; } // Indicate success return S_OK; } STDMETHODIMP CAGCOrientation::InitNew( void) { // Initialize the vector object XLock lock(this); m_orientation.Reset(); // Indicate success return S_OK; } ///////////////////////////////////////////////////////////////////////////// // IAGCOrientation Interface Methods STDMETHODIMP CAGCOrientation::InitCopy(IAGCOrientation* pOrientation) { Orientation orientation; RETURN_FAILED(GetRawOrientation(pOrientation, &orientation)); // Save the values 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) { // Get the raw orientation Orientation orientation; RETURN_FAILED(GetRawOrientation(pOrientation, &orientation)); // Determine absolute equality XLock lock(this); const cbData = sizeof(*m_orientation[0]) * DIMENSIONS; bool bEqual = !memcmp(m_orientation[0], orientation[0], cbData); // Initialize the [out] parameter CLEAROUT(pbIsEqual, VARBOOL(bEqual)); return S_OK; } STDMETHODIMP CAGCOrientation::get_IsRoughlyEqual( IAGCOrientation* pOrientation, VARIANT_BOOL* pbIsEqual) { // Get the raw orientation Orientation orientation; RETURN_FAILED(GetRawOrientation(pOrientation, &orientation)); // Determine 'fuzzy' equality XLock lock(this); bool bEqual = m_orientation == orientation; // Initialize the [out] parameter CLEAROUT(pbIsEqual, VARBOOL(bEqual)); return S_OK; } ///////////////////////////////////////////////////////////////////////////// // IAGCOrientationPrivate Interface Methods STDMETHODIMP CAGCOrientation::InitFromOrientation(const void* pvOrientation) { Orientation orientationTemp; const Orientation* pOrientation = reinterpret_cast(pvOrientation); if (!pOrientation) pOrientation = &orientationTemp; // Determine absolute equality XLock lock(this); const cbData = sizeof(*m_orientation[0]) * DIMENSIONS; bool bEqual = !memcmp(m_orientation[0], (*pOrientation)[0], cbData); if (!bEqual) { m_orientation = *pOrientation; m_bDirty = true; } // Indicate success return S_OK; } STDMETHODIMP CAGCOrientation::CopyOrientationTo(void* pvOrientation) { XLock lock(this); Orientation* pOrientation = reinterpret_cast(pvOrientation); *pOrientation = m_orientation; return S_OK; }