#include "pch.h"
#include "AGCVector.h"
TC_OBJECT_EXTERN_IMPL(CAGCVector)
HRESULT CAGCVector::GetRawVector(IAGCVector* pVector, Vector* pVectorRaw)
{
__try
{
if (!pVector)
return E_POINTER;
IAGCVectorPrivate* pPrivate = NULL;
RETURN_FAILED(pVector->QueryInterface(__uuidof(pPrivate), (void**)&pPrivate));
assert(pPrivate);
if (!pPrivate)
return E_INVALIDARG;
HRESULT hr = pPrivate->CopyVectorTo(pVectorRaw);
pPrivate->Release();
return hr;
}
__except(1)
{
return E_POINTER;
}
}
HRESULT CAGCVector::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 CAGCVector::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IAGCVector
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP CAGCVector::GetClassID(CLSID* pClassID)
{
__try
{
*pClassID = GetObjectCLSID();
}
__except(1)
{
return E_POINTER;
}
return S_OK;
}
STDMETHODIMP CAGCVector::IsDirty()
{
XLock lock(this);
return m_bDirty ? S_OK : S_FALSE;
}
STDMETHODIMP CAGCVector::Load(LPSTREAM pStm)
{
long cDims;
RETURN_FAILED(pStm->Read(&cDims, sizeof(cDims), NULL));
if (DIMENSIONS != cDims)
{
assert(DIMENSIONS == cDims);
return ERROR_INVALID_DATA;
}
float xArg, yArg, zArg;
RETURN_FAILED(pStm->Read(&xArg, sizeof(xArg), NULL));
RETURN_FAILED(pStm->Read(&yArg, sizeof(yArg), NULL));
RETURN_FAILED(pStm->Read(&zArg, sizeof(zArg), NULL));
return InitXYZ(xArg, yArg, zArg);
}
STDMETHODIMP CAGCVector::Save(LPSTREAM pStm, BOOL fClearDirty)
{
long cDims = DIMENSIONS;
RETURN_FAILED(pStm->Write(&cDims, sizeof(cDims), NULL));
XLock lock(this);
float xArg = m_vector.X(), yArg = m_vector.Y(), zArg = m_vector.Z();
RETURN_FAILED(pStm->Write(&xArg, sizeof(xArg), NULL));
RETURN_FAILED(pStm->Write(&yArg, sizeof(yArg), NULL));
RETURN_FAILED(pStm->Write(&zArg, sizeof(zArg), NULL));
if (fClearDirty)
m_bDirty = false;
return S_OK;
}
STDMETHODIMP CAGCVector::GetSizeMax(ULARGE_INTEGER* pCbSize)
{
__try
{
pCbSize->LowPart = sizeof(long) + sizeof(float) * DIMENSIONS;
pCbSize->HighPart = 0;
}
__except(1)
{
return E_POINTER;
}
return S_OK;
}
STDMETHODIMP CAGCVector::InitNew( void)
{
XLock lock(this);
m_vector = Vector::GetZero();
return S_OK;
}
STDMETHODIMP CAGCVector::Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog)
{
CComVariant varX(0.f), varY(0.f), varZ(0.f);
RETURN_FAILED(pPropBag->Read(L"X", &varX, pErrorLog));
RETURN_FAILED(pPropBag->Read(L"Y", &varY, pErrorLog));
RETURN_FAILED(pPropBag->Read(L"Z", &varZ, pErrorLog));
return InitXYZ(V_R4(&varX), V_R4(&varY), V_R4(&varZ));
}
STDMETHODIMP CAGCVector::Save(IPropertyBag* pPropBag, BOOL fClearDirty, BOOL)
{
XLock lock(this);
RETURN_FAILED(pPropBag->Write(L"X", &CComVariant(m_vector.X())));
RETURN_FAILED(pPropBag->Write(L"Y", &CComVariant(m_vector.Y())));
RETURN_FAILED(pPropBag->Write(L"Z", &CComVariant(m_vector.Z())));
if (fClearDirty)
m_bDirty = false;
return S_OK;
}
STDMETHODIMP CAGCVector::put_X(float Val)
{
XLock lock(this);
if (m_vector.X() != Val)
{
m_vector.SetX(Val);
m_bDirty = true;
}
return S_OK;
}
STDMETHODIMP CAGCVector::get_X(float* pVal)
{
XLock lock(this);
CLEAROUT(pVal, m_vector.X());
return S_OK;
}
STDMETHODIMP CAGCVector::put_Y(float Val)
{
XLock lock(this);
if (m_vector.Y() != Val)
{
m_vector.SetY(Val);
m_bDirty = true;
}
return S_OK;
}
STDMETHODIMP CAGCVector::get_Y(float* pVal)
{
XLock lock(this);
CLEAROUT(pVal, m_vector.Y());
return S_OK;
}
STDMETHODIMP CAGCVector::put_Z(float Val)
{
XLock lock(this);
if (m_vector.Z() != Val)
{
m_vector.SetZ(Val);
m_bDirty = true;
}
return S_OK;
}
STDMETHODIMP CAGCVector::get_Z(float* pVal)
{
XLock lock(this);
CLEAROUT(pVal, m_vector.Z());
return S_OK;
}
STDMETHODIMP CAGCVector::put_DisplayString(BSTR bstrDisplayString)
{
if (!BSTRLen(bstrDisplayString))
return E_INVALIDARG;
CComBSTR bstrFmt;
if (!bstrFmt.LoadString(IDS_FMT_VECTOR))
return HRESULT_FROM_WIN32(::GetLastError());
float xArg, yArg, zArg;
if (3 != swscanf(bstrDisplayString, bstrFmt, &xArg, &yArg, &zArg))
return E_INVALIDARG;
return InitXYZ(xArg, yArg, zArg);
}
STDMETHODIMP CAGCVector::get_DisplayString(BSTR* pbstrDisplayString)
{
CComBSTR bstrFmt;
if (!bstrFmt.LoadString(IDS_FMT_VECTOR))
return HRESULT_FROM_WIN32(::GetLastError());
XLock lock(this);
OLECHAR szText[_MAX_PATH];
swprintf(szText, bstrFmt, m_vector.X(), m_vector.Y(), m_vector.Z());
CComBSTR bstr(szText);
CLEAROUT(pbstrDisplayString, (BSTR)bstr);
bstr.Detach();
return S_OK;
}
STDMETHODIMP CAGCVector::InitXYZ(float xArg, float yArg, float zArg)
{
XLock lock(this);
if (m_vector.X() != xArg || m_vector.Y() != yArg || m_vector.Z() != zArg)
{
m_vector.SetX(xArg);
m_vector.SetY(yArg);
m_vector.SetZ(zArg);
m_bDirty = true;
}
return S_OK;
}
STDMETHODIMP CAGCVector::InitCopy(IAGCVector* pVector)
{
float xArg, yArg, zArg;
RETURN_FAILED(pVector->get_X(&xArg));
RETURN_FAILED(pVector->get_Y(&yArg));
RETURN_FAILED(pVector->get_Z(&zArg));
return InitXYZ(xArg, yArg, zArg);
}
STDMETHODIMP CAGCVector::InitRandomDirection()
{
return InitFromVector(&Vector::RandomDirection());
}
STDMETHODIMP CAGCVector::InitRandomPosition(float fRadius)
{
return InitFromVector(&Vector::RandomPosition(fRadius));
}
STDMETHODIMP CAGCVector::get_IsZero(VARIANT_BOOL* pbIsZero)
{
XLock lock(this);
CLEAROUT(pbIsZero, VARBOOL(m_vector.IsZero()));
return S_OK;
}
STDMETHODIMP CAGCVector::get_IsEqual(IAGCVector* pVector,
VARIANT_BOOL* pbIsEqual)
{
Vector vector;
RETURN_FAILED(GetRawVector(pVector, &vector));
XLock lock(this);
CLEAROUT(pbIsEqual, VARBOOL(vector == m_vector));
return S_OK;
}
STDMETHODIMP CAGCVector::get_Length(float* pfLength)
{
XLock lock(this);
CLEAROUT(pfLength, m_vector.Length());
return S_OK;
}
STDMETHODIMP CAGCVector::get_LengthSquared(float* pfLengthSquared)
{
XLock lock(this);
CLEAROUT(pfLengthSquared, m_vector.LengthSquared());
return S_OK;
}
STDMETHODIMP CAGCVector::get_OrthogonalVector(IAGCVector** ppResult)
{
XLock lock(this);
return CreateResultVector(&m_vector.GetOrthogonalVector(), ppResult);
}
STDMETHODIMP CAGCVector::Add(IAGCVector* pVector, IAGCVector** ppResult)
{
Vector vector;
RETURN_FAILED(GetRawVector(pVector, &vector));
XLock lock(this);
return CreateResultVector(&(m_vector + vector), ppResult);
}
STDMETHODIMP CAGCVector::Subtract(IAGCVector* pVector, IAGCVector** ppResult)
{
Vector vector;
RETURN_FAILED(GetRawVector(pVector, &vector));
XLock lock(this);
return CreateResultVector(&(m_vector - vector), ppResult);
}
STDMETHODIMP CAGCVector::Multiply(float f, IAGCVector** ppResult)
{
XLock lock(this);
return CreateResultVector(&(m_vector * f), ppResult);
}
STDMETHODIMP CAGCVector::Divide(float f, IAGCVector** ppResult)
{
XLock lock(this);
return CreateResultVector(&(m_vector / f), ppResult);
}
STDMETHODIMP CAGCVector::Normalize(IAGCVector** ppResult)
{
XLock lock(this);
return CreateResultVector(&m_vector.Normalize(), ppResult);
}
STDMETHODIMP CAGCVector::CrossProduct(IAGCVector* pVector,
IAGCVector** ppResult)
{
Vector vector;
RETURN_FAILED(GetRawVector(pVector, &vector));
XLock lock(this);
return CreateResultVector(&::CrossProduct(m_vector, vector), ppResult);
}
STDMETHODIMP CAGCVector::Interpolate(IAGCVector* pVector, float fValue,
IAGCVector** ppResult)
{
Vector vector;
RETURN_FAILED(GetRawVector(pVector, &vector));
XLock lock(this);
return CreateResultVector(&::Interpolate(m_vector, vector, fValue), ppResult);
}
STDMETHODIMP CAGCVector::AddInPlace(IAGCVector* pVector)
{
Vector vector;
RETURN_FAILED(GetRawVector(pVector, &vector));
XLock lock(this);
return InitFromVector(&(m_vector + vector));
}
STDMETHODIMP CAGCVector::SubtractInPlace(IAGCVector* pVector)
{
Vector vector;
RETURN_FAILED(GetRawVector(pVector, &vector));
XLock lock(this);
return InitFromVector(&(m_vector - vector));
}
STDMETHODIMP CAGCVector::MultiplyInPlace(float f)
{
XLock lock(this);
return InitFromVector(&(m_vector * f));
}
STDMETHODIMP CAGCVector::DivideInPlace(float f)
{
XLock lock(this);
return InitFromVector(&(m_vector / f));
}
STDMETHODIMP CAGCVector::NormalizeInPlace()
{
XLock lock(this);
m_vector.SetNormalize();
return S_OK;
}
STDMETHODIMP CAGCVector::CrossProductInPlace(IAGCVector* pVector)
{
Vector vector;
RETURN_FAILED(GetRawVector(pVector, &vector));
XLock lock(this);
return InitFromVector(&::CrossProduct(m_vector, vector));
}
STDMETHODIMP CAGCVector::InterpolateInPlace(IAGCVector* pVector, float fValue)
{
Vector vector;
RETURN_FAILED(GetRawVector(pVector, &vector));
XLock lock(this);
return InitFromVector(&::Interpolate(m_vector, vector, fValue));
}
STDMETHODIMP CAGCVector::InitFromVector(const void* pvVector)
{
Vector vectorTemp;
const Vector* pVector = reinterpret_cast<const Vector*>(pvVector);
if (!pVector)
{
vectorTemp = Vector::GetZero();
pVector = &vectorTemp;
}
return InitXYZ(pVector->X(), pVector->Y(), pVector->Z());
}
STDMETHODIMP CAGCVector::CopyVectorTo(void* pvVector)
{
XLock lock(this);
Vector* pVector = reinterpret_cast<Vector*>(pvVector);
pVector->SetX(m_vector.X());
pVector->SetY(m_vector.Y());
pVector->SetZ(m_vector.Z());
return S_OK;
}