/** * Adds velocities and creates clipping rectangles for all the * objects that have moved on the specified object list. * @param pObjList Playfield display list to draw * @param pWin Playfield window top left position * @param pClip Playfield clipping rectangle * @param bNoVelocity When reset, objects pos is updated with velocity * @param bScrolled) When set, playfield has scrolled */ void FindMovingObjects(OBJECT **pObjList, Common::Point *pWin, Common::Rect *pClip, bool bNoVelocity, bool bScrolled) { OBJECT *pObj; // object list traversal pointer for (pObj = *pObjList; pObj != NULL; pObj = pObj->pNext) { if (!bNoVelocity) { // we want to add velocities to objects position if (bScrolled) { // this playfield has scrolled // indicate change pObj->flags |= DMA_CHANGED; } } if ((pObj->flags & DMA_CHANGED) || // object changed HasPalMoved(pObj->pPal)) { // or palette moved // object has changed in some way Common::Rect rcClip; // objects clipped bounding rectangle Common::Rect rcObj; // objects bounding rectangle // calc intersection of objects previous bounding rectangle // NOTE: previous position is in screen co-ords if (IntersectRectangle(rcClip, pObj->rcPrev, *pClip)) { // previous position is within clipping rect AddClipRect(rcClip); } // calc objects current bounding rectangle if (pObj->flags & DMA_ABS) { // object position is absolute rcObj.left = fracToInt(pObj->xPos); rcObj.top = fracToInt(pObj->yPos); } else { // object position is relative to window rcObj.left = fracToInt(pObj->xPos) - pWin->x; rcObj.top = fracToInt(pObj->yPos) - pWin->y; } rcObj.right = rcObj.left + pObj->width; rcObj.bottom = rcObj.top + pObj->height; // calc intersection of object with clipping rect if (IntersectRectangle(rcClip, rcObj, *pClip)) { // current position is within clipping rect AddClipRect(rcClip); // update previous position pObj->rcPrev = rcClip; } else { // clear previous position pObj->rcPrev = Common::Rect(); } // clear changed flag pObj->flags &= ~DMA_CHANGED; } } }
BOOL dc_GenerateECRgn(PDC pdc, BOOL fForce) { RECT rc, rcInter; PCLIPRECT pcr, pgcr; PCONTROL pCtrl; // is global clip region is empty? if ((!fForce) && (!dc_IsVisible (pdc))) return FALSE; // need regenerate? if (fForce || (pdc->oldage != pdc->pGCRInfo->age)) { EmptyClipRgn (&pdc->ecrgn); pcr = pdc->lcrgn.head; while (pcr) { rc = pcr->rc; coor_LP2SP (pdc, &rc.left, &rc.top); coor_LP2SP (pdc, &rc.right, &rc.bottom); pgcr = pdc->pGCRInfo->crgn.head; while (pgcr) { if (IntersectRect (&rcInter, &rc, &pgcr->rc)) AddClipRect (&pdc->ecrgn, &rcInter); pgcr = pgcr->next; } pcr = pcr->next; } if (pdc->lcrgn.head == NULL) ClipRgnCopy (&pdc->ecrgn, &pdc->pGCRInfo->crgn); // update the DevRC; if (pdc->bIsClient) WndClientRect (pdc->hwnd, &pdc->DevRC); else WndRect (pdc->hwnd, &pdc->DevRC); IntersectClipRect (&pdc->ecrgn, &pdc->DevRC); pCtrl = Control (pdc->hwnd); if (pCtrl && !(pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN)) RestrictControlECRGN (&pdc->ecrgn, pCtrl); pdc->oldage = pdc->pGCRInfo->age; } return TRUE; }
/** * Deletes an object from the specified object list and places it * on the free list. * @param pObjList List to delete object from * @param pDelObj Object to delete */ void DelObject(OBJECT *pObjList, OBJECT *pDelObj) { OBJECT *pPrev, *pObj; // object list traversal pointers const Common::Rect rcScreen(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); // validate object pointer assert(isValidObject(pDelObj)); #ifdef DEBUG // one less object in use --numObj; assert(numObj >= 0); #endif for (pPrev = pObjList, pObj = pObjList->pNext; pObj != NULL; pPrev = pObj, pObj = pObj->pNext) { if (pObj == pDelObj) { // found object to delete if (IntersectRectangle(pDelObj->rcPrev, pDelObj->rcPrev, rcScreen)) { // allocate a clipping rect for objects previous pos AddClipRect(pDelObj->rcPrev); } // make PREV next = OBJ next - removes OBJ from list pPrev->pNext = pObj->pNext; // place free list in OBJ next pObj->pNext = pFreeObjects; // add OBJ to top of free list pFreeObjects = pObj; // delete objects palette if (pObj->pPal) FreePalette(pObj->pPal); // quit return; } } // if we get to here - object has not been found on the list // This can be triggered in Act 3 in DW1 while talking to the guard, // so this has been turned to a warning instead of an error warning("DelObject(): formally 'assert(0)!'"); }