2025-11-28 00:35:46 +09:00

307 lines
8.0 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
#include "ManipulationEventsink.h"
#include "CoreObject.h"
#include <math.h>
CManipulationEventSink::CManipulationEventSink(HWND hWnd, CCoreObject *coRef, int iTimerId, BOOL inertia):
m_coRef(coRef),
m_hWnd(hWnd),
m_iTimerId(iTimerId),
m_bInertia(inertia),
m_pConnPoint(NULL),
m_cRefCount(1)
{
}
HRESULT STDMETHODCALLTYPE CManipulationEventSink::ManipulationStarted(
FLOAT x,
FLOAT y)
{
UNREFERENCED_PARAMETER(x);
UNREFERENCED_PARAMETER(y);
// Stop object if it is in the state of inertia
m_coRef->bIsInertiaActive = FALSE;
KillTimer(m_hWnd, m_iTimerId);
m_coRef->doDrawing->RestoreRealPosition();
return S_OK;
}
HRESULT STDMETHODCALLTYPE CManipulationEventSink::ManipulationDelta(
FLOAT x,
FLOAT y,
FLOAT translationDeltaX,
FLOAT translationDeltaY,
FLOAT scaleDelta,
FLOAT expansionDelta,
FLOAT rotationDelta,
FLOAT cumulativeTranslationX,
FLOAT cumulativeTranslationY,
FLOAT cumulativeScale,
FLOAT cumulativeExpansion,
FLOAT cumulativeRotation)
{
UNREFERENCED_PARAMETER(cumulativeRotation);
UNREFERENCED_PARAMETER(cumulativeExpansion);
UNREFERENCED_PARAMETER(cumulativeScale);
UNREFERENCED_PARAMETER(cumulativeTranslationX);
UNREFERENCED_PARAMETER(cumulativeTranslationY);
UNREFERENCED_PARAMETER(expansionDelta);
CDrawingObject* dObj = m_coRef->doDrawing;
IManipulationProcessor* mp= m_coRef->manipulationProc;
HRESULT hr = S_OK;
// Apply transformation based on rotationDelta (in radians)
FLOAT rads = 180.0f / 3.14159f;
dObj->SetManipulationOrigin(x, y);
dObj->Rotate(rotationDelta*rads);
// Apply translation based on scaleDelta
dObj->Scale(scaleDelta);
// Apply translation based on translationDelta
dObj->Translate(translationDeltaX, translationDeltaY, m_bInertia);
if(!m_bInertia)
{
// Set values for one finger rotations
FLOAT fPivotRadius = (FLOAT)(sqrt(pow(dObj->GetWidth()/2, 2)+ pow(dObj->GetHeight()/2, 2)))*0.4f;
FLOAT fPivotPtX = dObj->GetCenterX();
FLOAT fPivotPtY = dObj->GetCenterY();
HRESULT hrPPX = mp->put_PivotPointX(fPivotPtX);
HRESULT hrPPY = mp->put_PivotPointY(fPivotPtY);
HRESULT hrPR = mp->put_PivotRadius(fPivotRadius);
if(FAILED(hrPPX) || FAILED(hrPPY) || FAILED(hrPR))
{
hr = E_FAIL;
}
}
return hr;
}
HRESULT STDMETHODCALLTYPE CManipulationEventSink::ManipulationCompleted(
FLOAT x,
FLOAT y,
FLOAT cumulativeTranslationX,
FLOAT cumulativeTranslationY,
FLOAT cumulativeScale,
FLOAT cumulativeExpansion,
FLOAT cumulativeRotation)
{
UNREFERENCED_PARAMETER(cumulativeRotation);
UNREFERENCED_PARAMETER(cumulativeExpansion);
UNREFERENCED_PARAMETER(cumulativeScale);
UNREFERENCED_PARAMETER(cumulativeTranslationX);
UNREFERENCED_PARAMETER(cumulativeTranslationY);
UNREFERENCED_PARAMETER(x);
UNREFERENCED_PARAMETER(y);
HRESULT hr = S_OK;
IInertiaProcessor* ip = m_coRef->inertiaProc;
IManipulationProcessor* mp = m_coRef->manipulationProc;
if(!m_bInertia)
{
HRESULT hrSI = SetupInertia(ip, mp);
HRESULT hrCO = S_OK;
if(FAILED(hrSI) || FAILED(hrCO))
{
hr = E_FAIL;
}
// Set the core objects inertia state to TRUE so it can
// be processed when another object is being manipulated
m_coRef->bIsInertiaActive = TRUE;
// Kick off timer that handles inertia
SetTimer(m_hWnd, m_iTimerId, DESIRED_MILLISECONDS, NULL);
}
else
{
m_coRef->bIsInertiaActive = FALSE;
// Stop timer that handles inertia
KillTimer(m_hWnd, m_iTimerId);
}
return hr;
}
HRESULT CManipulationEventSink::SetupInertia(IInertiaProcessor* ip, IManipulationProcessor* mp)
{
HRESULT hr = S_OK;
// Set desired properties for inertia events
// Deceleration for tranlations in pixel / msec^2
HRESULT hrPutDD = ip->put_DesiredDeceleration(0.003f);
// Deceleration for rotations in radians / msec^2
HRESULT hrPutDAD = ip->put_DesiredAngularDeceleration(0.000015f);
// Set initial origins
HRESULT hrPutIOX = ip->put_InitialOriginX(m_coRef->doDrawing->GetCenterX());
HRESULT hrPutIOY = ip->put_InitialOriginY(m_coRef->doDrawing->GetCenterY());
FLOAT fVX;
FLOAT fVY;
FLOAT fVR;
HRESULT hrPutVX = mp->GetVelocityX(&fVX);
HRESULT hrGetVY = mp->GetVelocityY(&fVY);
HRESULT hrGetAV = mp->GetAngularVelocity(&fVR);
// Set initial velocities for inertia processor
HRESULT hrPutIVX = ip->put_InitialVelocityX(fVX);
HRESULT hrPutIVY = ip->put_InitialVelocityY(fVY);
HRESULT hrPutIAV = ip->put_InitialAngularVelocity(fVR);
if(FAILED(hrPutDD) || FAILED(hrPutDAD) || FAILED(hrPutIOX) || FAILED(hrPutIOY)
|| FAILED(hrPutVX) || FAILED(hrGetVY) || FAILED(hrGetAV) || FAILED(hrPutIVX)
|| FAILED(hrPutIVY) || FAILED(hrPutIAV))
{
hr = E_FAIL;
}
return hr;
}
ULONG CManipulationEventSink::AddRef()
{
return ++m_cRefCount;
}
ULONG CManipulationEventSink::Release()
{
m_cRefCount--;
if(m_cRefCount == 0)
{
delete this;
return 0;
}
return m_cRefCount;
}
HRESULT CManipulationEventSink::QueryInterface(REFIID riid, LPVOID *ppvObj)
{
HRESULT hr = S_OK;
if(ppvObj == NULL)
{
hr = E_POINTER;
}
if(!FAILED(hr))
{
*ppvObj = NULL;
if (IID__IManipulationEvents == riid)
{
*ppvObj = static_cast<_IManipulationEvents*>(this);
}
else if (IID_IUnknown == riid)
{
*ppvObj = static_cast<IUnknown*>(this);
}
if(*ppvObj)
{
AddRef();
}
else
{
hr = E_NOINTERFACE;
}
}
return hr;
}
// Set up the connection to a manipulation or inertia processor
BOOL CManipulationEventSink::SetupConnPt(IUnknown *manipulationProc)
{
BOOL success = FALSE;
IConnectionPointContainer* pConPointContainer = NULL;
// Only connect if there isn't already an active connection
if (m_pConnPoint == NULL)
{
// Check if supports connectable objects
success = SUCCEEDED(manipulationProc->QueryInterface(IID_IConnectionPointContainer,
(LPVOID*)&(pConPointContainer)));
// Get connection point interface
if(success)
{
success = SUCCEEDED(pConPointContainer->FindConnectionPoint(
_uuidof(_IManipulationEvents),
&(m_pConnPoint)));
}
// Clean up connection point container
if (pConPointContainer != NULL)
{
pConPointContainer->Release();
pConPointContainer = NULL;
}
// Hook event object to the connection point
IUnknown* pUnk = NULL;
if(success)
{
// Get pointer to manipulation event sink's IUnknown pointer
success = SUCCEEDED(QueryInterface(IID_IUnknown, (LPVOID*)&pUnk));
}
// Establish connection point to callback interface
if(success)
{
success = SUCCEEDED(m_pConnPoint->Advise(pUnk, &(m_uID)));
}
// Clean up IUnknown pointer
if(pUnk != NULL)
{
pUnk->Release();
}
if (!success && m_pConnPoint != NULL)
{
m_pConnPoint->Release();
m_pConnPoint = NULL;
}
}
return success;
}
VOID CManipulationEventSink::RemoveConnPt()
{
// Clean up the connection point associated to this event sink
if(m_pConnPoint)
{
m_pConnPoint->Unadvise(m_uID);
m_pConnPoint->Release();
m_pConnPoint = NULL;
}
}