// SpineAnalysis.c #include "SpineAnalysis.h" #include #include "utils.h" // CP# means Control Point or Handle // // // CP0 // ********************************* // // // // CP1 // ********************************* // // // // CP2 // ********************************* // // // // CP3 // ********************************* // // //************************************************************************************** // // Functions for SpineAnalysis // //************************************************************************************* typedef struct tag_LINEHANDLES { int nCount; ANNPOINT AnnPoints[2]; } LINEHANDLES, *pLINEHANDLES; L_INT L_EXPORT EXT_CALLBACK LineHandlesCallback(HANNOBJECT hObject, pANNHANDLEINFO pHandleInfo, L_VOID L_FAR * pUserData) { pLINEHANDLES pLineHandles = (pLINEHANDLES)pUserData; if (pHandleInfo->nType == ANNHANDLETYPE_DEFAULT_HANDLE) { pLineHandles->AnnPoints[pLineHandles->nCount] = pHandleInfo->ptLocationContainer; pLineHandles->nCount++; } return SUCCESS_NOCHANGE; } L_VOID SpineAnalysis_AddHandle(HANNOBJECT hObject, pHANDLEDEF pHandleDef) { L_UINT uFlags = ANNHANDLE_LOCATION | ANNHANDLE_CONTAINER_COORDINATES | ANNHANDLE_ID | ANNHANDLE_PEN_COLOR | ANNHANDLE_FILL_COLOR | ANNHANDLE_SHAPE; ANNHANDLE AnnHandle; LINEHANDLES LineHandles; AnnHandle.uStructSize = sizeof(ANNHANDLE); AnnHandle.nShape = pHandleDef->nShape; AnnHandle.crPen = RGB(0,0,0); AnnHandle.hCursor= NULL; LineHandles.nCount = 0; L_AnnEnumerateHandles(hObject, LineHandlesCallback, &LineHandles); AnnHandle.aptContainer.x = (LineHandles.AnnPoints[0].x + LineHandles.AnnPoints[1].x) / 2; AnnHandle.aptContainer.y = (LineHandles.AnnPoints[0].y + LineHandles.AnnPoints[1].y) / 2; AnnHandle.nID = pHandleDef->nID; AnnHandle.crFill = pHandleDef->crFill; AnnHandle.uFlags = uFlags; L_AnnAddUserHandle(hObject, &AnnHandle); } #define SPINEANALYSIS_NUMPOINTS 4 HANDLEDEF SpineAnalysis_HandleDef[SPINEANALYSIS_NUMPOINTS] = { HANDLE_ID_CP0, ANNHANDLE_SHAPE_CIRCLE, RGB( 0, 0, 0) , HANDLE_ID_CP1, ANNHANDLE_SHAPE_CIRCLE, RGB(255, 0, 0) , HANDLE_ID_CP2, ANNHANDLE_SHAPE_CIRCLE, RGB( 0,255, 0) , HANDLE_ID_CP3, ANNHANDLE_SHAPE_CIRCLE, RGB( 0, 0,255) , }; L_VOID SpineAnalysis_AddUserHandles(HANNOBJECT hObject) { L_INT nCount; HANNOBJECT AnnObjectNeighbors[4]; // this object is made of four polygons AnnGetNeighborObjects(hObject, AnnObjectNeighbors, &nCount); AnnSortNeighborObjects(hObject, AnnObjectNeighbors, nCount); // Add user handles SpineAnalysis_AddHandle(AnnObjectNeighbors[0], SpineAnalysis_HandleDef + 0); SpineAnalysis_AddHandle(AnnObjectNeighbors[1], SpineAnalysis_HandleDef + 1); SpineAnalysis_AddHandle(AnnObjectNeighbors[2], SpineAnalysis_HandleDef + 2); SpineAnalysis_AddHandle(AnnObjectNeighbors[3], SpineAnalysis_HandleDef + 3); } //*************** SpineAnalysis Create functions HANNOBJECT CreateLine(HANNOBJECT hContainer, POINT pt0, POINT pt1) { HANNOBJECT hLine; L_AnnCreateItem(hContainer, ANNOBJECT_LINE, TRUE, &hLine); L_AnnDefine(hLine, &pt0, ANNDEFINE_BEGINSET); L_AnnDefine(hLine, &pt1, ANNDEFINE_END); return hLine; } L_VOID SpineAnalysis_LButtonDown(HWND hWnd, LPCHILDDATA pData) { L_AnnAddUndoNode(pData->hAutomation); L_AnnCreateItem(pData->hContainer, ANNOBJECT_RECT, FALSE, &pData->hRect); L_AnnDefine(pData->hRect, &pData->ptStart, ANNDEFINE_BEGINSET); pData->fCapture = TRUE; L_AnnRestrictCursor(pData->hContainer, NULL, NULL, &pData->rcOldClip, TRUE); } L_VOID SpineAnalysis_LButtonUp(LPCHILDDATA pData, L_UINT uTool) { POINT pt0, pt1; HANNOBJECT hLine[4]; L_INT i; LONG y[4]; LONG dy; L_AnnDefine(pData->hRect, &pData->ptEnd, ANNDEFINE_END); y[0] = min(pData->ptStart.y, pData->ptEnd.y); y[3] = max(pData->ptStart.y, pData->ptEnd.y); dy = (y[3]-y[0])/3; y[1] = 1*dy + y[0]; y[2] = 2*dy + y[0]; pt0.x = pData->ptStart.x; pt1.x = pData->ptEnd.x; for (i=0; i<4; i++) { pt0.y = y[i]; pt1.y = y[i]; hLine[i] = CreateLine(pData->hContainer, pt0, pt1); AnnSetID(hLine[i], uTool, i); //Set tag to identify line 0,1,2 L_AnnSetSelected(hLine[i], TRUE, 0); HideDefaultHandles(hLine[i]); } //Bring the first line to the front of the z-order //This line will have all the user handles L_AnnBringToFront(hLine[0]); // Remove original rectangle from container and free L_AnnRemove(pData->hRect); L_AnnDestroy(pData->hRect, 0); // set the default settings from the automation object, and group the objects L_AnnSetAutoDefaults(pData->hAutomation, pData->hContainer, ANNFLAG_SELECTED|ANNFLAG_RECURSE); L_AnnGroup(pData->hContainer, ANNFLAG_SELECTED|ANNFLAG_RECURSE, NULL); L_AnnDumpObject(pData->hContainer); SpineAnalysis_AddUserHandles(hLine[0]); DebugClipCursor(&pData->rcOldClip); } //*************** SpineAnalysis Update functions #define MIN_DIST (4) L_VOID SpineAnalysis_RestrictPoint(HANNOBJECT hObject, HANNOBJECT hObjectNeighbors[], LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { ANNRECT arcContainer; RECT rcClip; POINT pt[SPINEANALYSIS_NUMPOINTS]; GetHandleInfo(pData->AnnObjectNeighbors[0], HANDLE_ID_CP0, pt + 0, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[1], HANDLE_ID_CP1, pt + 1, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[2], HANDLE_ID_CP2, pt + 2, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[3], HANDLE_ID_CP3, pt + 3, NULL, NULL); L_AnnGetRect(pData->hContainer, &arcContainer, NULL); L_AnnConvert(pData->hContainer, (LPPOINT)&rcClip, (pANNPOINT)&arcContainer, 2, ANNCONVERT_TO_CLIENT); rcClip.left = pt[0].x; rcClip.right = pt[0].x + 1; switch(pData->nUserHandleID) { case HANDLE_ID_CP0: rcClip.bottom = pt[1].y - MIN_DIST + 1; break; case HANDLE_ID_CP1: rcClip.top = pt[0].y + MIN_DIST; rcClip.bottom = pt[2].y - MIN_DIST + 1; break; case HANDLE_ID_CP2: rcClip.top = pt[1].y + MIN_DIST; rcClip.bottom = pt[3].y - MIN_DIST + 1; break; case HANDLE_ID_CP3: rcClip.top = pt[2].y + MIN_DIST; break; } L_AnnRestrictCursor(pData->hContainer, &rcClip, NULL, NULL, FALSE); } L_VOID SpineAnalysis_Handle_LButtonDown(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { L_INT32 nCount; AnnGetNeighborObjects( pData->hObjectChange, pData->AnnObjectNeighbors, &nCount); AnnSortNeighborObjects(pData->hObjectChange, pData->AnnObjectNeighbors, nCount); SpineAnalysis_RestrictPoint(pData->hObjectChange, pData->AnnObjectNeighbors, pData, pMousePos); switch (pData->nUserHandleID) { case HANDLE_ID_CP0: L_AnnDefine(pData->AnnObjectNeighbors[0], &pMousePos->pt, ANNDEFINE_BEGINMOVE); break; case HANDLE_ID_CP1: L_AnnDefine(pData->AnnObjectNeighbors[1], &pMousePos->pt, ANNDEFINE_BEGINMOVE); break; case HANDLE_ID_CP2: L_AnnDefine(pData->AnnObjectNeighbors[2], &pMousePos->pt, ANNDEFINE_BEGINMOVE); break; case HANDLE_ID_CP3: L_AnnDefine(pData->AnnObjectNeighbors[3], &pMousePos->pt, ANNDEFINE_BEGINMOVE); break; } } L_VOID SpineAnalysis_Handle_MouseMove(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { SpineAnalysis_RestrictPoint(pData->hObjectChange, pData->AnnObjectNeighbors, pData, pMousePos); switch (pData->nUserHandleID) { case HANDLE_ID_CP0: L_AnnDefine(pData->AnnObjectNeighbors[0], &pMousePos->pt, ANNDEFINE_APPEND); break; case HANDLE_ID_CP1: L_AnnDefine(pData->AnnObjectNeighbors[1], &pMousePos->pt, ANNDEFINE_APPEND); break; case HANDLE_ID_CP2: L_AnnDefine(pData->AnnObjectNeighbors[2], &pMousePos->pt, ANNDEFINE_APPEND); break; case HANDLE_ID_CP3: L_AnnDefine(pData->AnnObjectNeighbors[3], &pMousePos->pt, ANNDEFINE_APPEND); break; } } L_VOID SpineAnalysis_Handle_LButtonUp(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { SpineAnalysis_RestrictPoint(pData->hObjectChange, pData->AnnObjectNeighbors, pData, pMousePos); switch (pData->nUserHandleID) { case HANDLE_ID_CP0: L_AnnDefine(pData->AnnObjectNeighbors[0], &pMousePos->pt, ANNDEFINE_END); MoveHandle(pData->AnnObjectNeighbors[0], pData->nUserHandleID, pMousePos->pt); break; case HANDLE_ID_CP1: L_AnnDefine(pData->AnnObjectNeighbors[1], &pMousePos->pt, ANNDEFINE_END); MoveHandle(pData->AnnObjectNeighbors[1], pData->nUserHandleID, pMousePos->pt); break; case HANDLE_ID_CP2: L_AnnDefine(pData->AnnObjectNeighbors[2], &pMousePos->pt, ANNDEFINE_END); MoveHandle(pData->AnnObjectNeighbors[2], pData->nUserHandleID, pMousePos->pt); break; case HANDLE_ID_CP3: L_AnnDefine(pData->AnnObjectNeighbors[3], &pMousePos->pt, ANNDEFINE_END); MoveHandle(pData->AnnObjectNeighbors[3], pData->nUserHandleID, pMousePos->pt); break; } }