📄 chanim.cpp
字号:
ChDibBmp* pDibNew = new ChDibBmp();
ASSERT( pDibNew );
pDibNew->Create( pDIB->GetBitmapInfoAddress()->bmiHeader.biWidth,
pDIB->GetBitmapInfoAddress()->bmiHeader.biHeight,
24 );
pDIB->CopyBits( pDibNew,
0, 0,
pDIB->GetBitmapInfoAddress()->bmiHeader.biWidth,
pDIB->GetBitmapInfoAddress()->bmiHeader.biHeight,
0, 0 );
delete pDIB;
pDIB = pDibNew;
}
m_pDibBkgnd = pDIB;
m_boolBackgroundDirty = true;
Invalidate(true);
UpdateWindow();
return true;
//DeferredNewBackground();
}
bool ChAnimView::DeferredNewBackground()
{
ChDibBmp* pDIB = m_pDibBkgnd;
m_boolBackgroundDirty = false;
// Create a new buffer and palette
if ( pDIB->GetBitmapInfoAddress()->bmiHeader.biBitCount <= 8 )
{
if (!Create(pDIB)) {
return false;
}
// Map the colors of the background DIB to
// the identity palette we just created for the background
pDIB->MapColorsToPalette(GetPalette());
}
else
{
m_bUseCreateDIBSection = false;
if (m_pOneToOneClrTab) free(m_pOneToOneClrTab);
m_pOneToOneClrTab = 0;
if (m_pPal) delete m_pPal;
m_pPal = 0;
if (m_pDIB) delete m_pDIB;
m_pDIB = new ChDibBmp;
if( !m_pDIB->Create(pDIB->GetWidth(), pDIB->GetHeight(),
pDIB->GetBitmapInfoAddress()->bmiHeader.biBitCount ) )
{
return false;
}
CSize sizeTotal;
sizeTotal.cx = m_pDIB->GetWidth();
sizeTotal.cy = m_pDIB->GetHeight();
SetScrollSizes(sizeTotal);
}
// Render the entire scene to the off-screen buffer
Render();
// Paint the off-screen buffer to the window
//Draw();
//Invalidate(true);
return true;
}
// Render the scene to the off-screen buffer
// pClipRect defaults to NULL
void ChAnimView::Render(CRect* pClipRect)
{
// make sure we have something to render to
if (!m_pDIB) return;
CRect rcDraw;
// get the background DIB and render it
m_pDibBkgnd->GetRect(&rcDraw);
// If a clip rect was supplied use it
if (pClipRect) {
rcDraw.IntersectRect(pClipRect, &rcDraw);
}
// draw the image of the DIB to the os buffer
ASSERT(m_pDIB);
m_pDibBkgnd->CopyBits(m_pDIB,
rcDraw.left,
rcDraw.top,
rcDraw.right - rcDraw.left,
rcDraw.bottom - rcDraw.top,
rcDraw.left,
rcDraw.top);
#if 1
// Render the sprite list from the bottom of the list to the top
// Note that we always clip to the background DIB
POSITION pos = m_spriteList.GetTailPosition();
CSprite *pSprite;
while (pos) {
pSprite = m_spriteList.GetPrev(pos);
pSprite->Render(m_pDIB, &rcDraw);
}
#endif
}
// Draw a section of the off-screen image buffer to the screen.
void ChAnimView::Draw(CDC* pDC, LPRECT pRect)
{
CDC* pdc;
CRect rcDraw;
if(m_boolBackgroundDirty)
{
DeferredNewBackground();
}
// Make sure we have what we need to do a paint.
if ( m_pDIB && !m_pOneToOneClrTab)
{
if ( m_pDIB->GetBitmapInfoAddress()->bmiHeader.biBitCount <= 8 )
{
return;
}
}
else if (!m_pDIB || !m_pOneToOneClrTab)
{
return;
}
// See if a DC was supplied, and get one if not.
if (pDC) {
pdc = pDC;
} else {
pdc = GetDC();
ChScrollWnd::OnPrepareDC(pdc); // jwd
}
// See if a clip rect was supplied, and use the client area if not.
if (pRect) {
rcDraw = *pRect; // this is in logicals; jwd
} else {
GetClientRect(rcDraw);
pdc->DPtoLP(LPRECT(rcDraw)); // fixed scrolling bug; jwd
}
// Get the clip box.
CRect rcClip;
pdc->GetClipBox(rcClip);
// Create a rect for the DIB.
CRect rcDIB;
rcDIB.left = rcDIB.top = 0;
rcDIB.right = m_pDIB->GetWidth() - 1;
rcDIB.bottom = m_pDIB->GetHeight() - 1;
// Find a rectangle that describes the intersection of the draw
// rect, clip rect, and DIB rect.
CRect rcBlt;
rcBlt.IntersectRect(&rcDraw, &rcClip);
rcBlt.IntersectRect(&rcBlt, &rcDIB);
// Copy the update rectangle from the off-screen DC to the
// window DC. Note that the DIB origin is the bottom-left corner.
int w, h, xs, xd, yd, ys;
w = rcBlt.right - rcBlt.left;
h = rcBlt.bottom - rcBlt.top;
xs = xd = rcBlt.left;
yd = rcBlt.top;
if (m_bUseCreateDIBSection) {
ys = rcBlt.top;
} else {
ys = m_pDIB->GetHeight() - rcBlt.bottom;
}
// Center the image, if requested, and it's smaller than window
if( m_boolCenterIt )
{
if(m_pDIB->GetWidth() - 1 < rcDraw.right - rcDraw.left)
{
xd += ((rcDraw.right - rcDraw.left) - (m_pDIB->GetWidth() - 1)) / 2;
}
if(m_pDIB->GetHeight() - 1 < rcDraw.bottom - rcDraw.top)
{
yd += ((rcDraw.bottom - rcDraw.top) - (m_pDIB->GetHeight() - 1)) / 2;
}
}
// If we have a palette, select and realize it.
CPalette* ppalOld = NULL;
if(m_pPal) {
ppalOld = pdc->SelectPalette(m_pPal, 0);
pdc->RealizePalette();
}
BYTE* pBits;
if (m_bUseCreateDIBSection) {
HDC dcMem = ::CreateCompatibleDC(pdc->GetSafeHdc());
HBITMAP hbmOld = (HBITMAP) ::SelectObject(dcMem, m_hbmSection);
// Note: you do not need to select the palette into
// the memory DC because the DIB section is using palette
// index values not colors.
::BitBlt(pdc->GetSafeHdc(),
xd, yd,
w, h,
dcMem,
xs, ys,
SRCCOPY);
::SelectObject(dcMem, hbmOld);
::DeleteDC(dcMem);
} else {
pBits = (BYTE*)m_pDIB->GetBitsAddress();
::StretchDIBits(pdc->GetSafeHdc(),
xd, // Destination x
yd, // Destination y
w, // Destination width
h, // Destination height
xs, // Source x
ys, // Source y
w, // Source width
h, // Source height
pBits, // Pointer to bits
m_pOneToOneClrTab ? m_pOneToOneClrTab :
m_pDIB->GetBitmapInfoAddress(), // BITMAPINFO
m_pOneToOneClrTab ? DIB_PAL_COLORS : DIB_RGB_COLORS, // Options
SRCCOPY); // Rop
}
// Select old palette if we altered it.
if (ppalOld) pdc->SelectPalette(ppalOld, 0);
// Release the DC if it was one we created.
if (!pDC) ReleaseDC(pdc);
}
// Add a region to the dirty list.
void ChAnimView::AddDirtyRegion(CRect* prcNew)
{
// Get the rectangle currently at the top of the list.
POSITION pos = m_DirtyList.GetHeadPosition();
if (pos) {
CRect* prcTop = (CRect*)m_DirtyList.GetNext(pos);
CRect rcTest;
// If the new one intersects the top one merge them.
if (rcTest.IntersectRect(prcTop, prcNew)) {
prcTop->UnionRect(prcTop, prcNew);
return;
}
}
// List is empty, or there was no intersection.
CRect* prc = new CRect;
*prc = *prcNew; // Copy the data.
// Add a new rectangle to the list.
m_DirtyList.AddHead((CObject*)prc);
}
// Render and draw all the dirty regions.
void ChAnimView::RenderAndDrawDirtyList()
{
POSITION pos = m_DirtyList.GetHeadPosition();
// Render all the dirty regions.
while (pos) {
// Get the next region.
CRect* pRect = (CRect*)m_DirtyList.GetNext(pos);
// Render it.
Render(pRect);
}
// Draw all the dirty regions to the screen.
while (!m_DirtyList.IsEmpty()) {
// Get the next region.
CRect* pRect = (CRect*)m_DirtyList.RemoveHead();
Draw(NULL, pRect);
// Done with it.
delete pRect;
}
}
// Empty the dirty list.
void ChAnimView::EmptyDirtyList()
{
while (!m_DirtyList.IsEmpty()) {
CRect* prc = (CRect*)m_DirtyList.RemoveHead();
delete prc;
}
}
void ChAnimView::Animate( bool boolRun)
{
if( boolRun )
{
if (m_uiTimer) return;
m_uiTimer = SetTimer(1, 55, NULL);
//m_uiTimer = SetTimer(1, 100, NULL);
}
else
{
if (m_uiTimer)
{
KillTimer(1);
m_uiTimer = 0;
}
}
}
// called by system timer mgr (to be defined)
void ChAnimView::OnTick()
{
if (!m_characters.IsEmpty())
{// Walk the character list and update any which are moving
ChPosition pos = m_characters.GetHeadPosition();
// !!!!!!!!! ?????????? need to change for varying framerates
chuint32 luCurrMsec = 1000;
while (pos) {
ChAnimCastMember* pch = m_characters.GetNext(pos);
pch->Tick(luCurrMsec);
}
// redraw the changes
RenderAndDrawDirtyList();
}
// Now set the cursor; Animating may bring an anchor under the cursor
POINT point;
::GetCursorPos( &point );
// Need to make sure it's in our area first
LRESULT hitCode = ::SendMessage( GetSafeHwnd(),
WM_NCHITTEST,
0,
MAKELONG((short)point.x, (short)point.y));
if( HTCLIENT == hitCode)
{
ScreenToClient( &point );
SetCursor( point );
}
}
ChAnimView* ChAnimView::AnimateCharacter( chuint32 luId, bool boolRun )
{
ChAnimCastMember* pch = FindChar(luId);
if (pch) pch->Animate(boolRun);
return this;
}
ChAnimView* ChAnimView::ShowCharacter( chuint32 luId, bool boolShow )
{
ChAnimCastMember* pch = FindChar(luId);
if (pch) pch->Show(boolShow);
return this;
}
ChAnimCastMember * ChAnimView::FindChar(chuint32 luId)
{
if (m_characters.IsEmpty()) return 0;
ChPosition pos = m_characters.GetHeadPosition();
while (pos) {
ChAnimCastMember* pch = m_characters.GetNext(pos);
if( pch->GetId() == luId) return pch;
}
return 0;
}
// A new sprite has been added to the document
void ChAnimView::NewSprite(CSprite* pSprite)
{
// map the colors in the sprite DIB to the
// palette in the off-screen buffered view
if (m_pPal) {
pSprite->MapColorsToPalette(m_pPal);
}
// Render the scene
Render();
// Draw the new scene to the screen
Draw();
}
// add a cast member to the view; checks for uniqueness by id and replaces if
// a dupe. consumes pChar and deletes it when char is deleted or replaced
void ChAnimView::AddCharacter( ChAnimCastMember * pChar )
{
ChAnimCastMember * pOldChar = FindChar( pChar->GetId() );
if (pOldChar)
{
DeleteCharacter(pChar->GetId());
}
m_characters.AddTail( pChar );
pChar->OnAddition( this );
// Add it to the character list
return;
}
ChAnimView* ChAnimView::DeleteCharacter( chuint32 luId )
{
if (m_characters.IsEmpty()) return this;
ChPosition pos = m_characters.GetHeadPosition();
while (pos)
{
ChPosition oldpos = pos;
ChAnimCastMember* pch = m_characters.GetNext(pos);
if( pch->GetId() == luId)
{
m_characters.Remove(oldpos);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -