267 lines
8.0 KiB
C++
267 lines
8.0 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2006-2010 - Frictional Games
|
|
*
|
|
* This file is part of HPL1 Engine.
|
|
*/
|
|
|
|
#include "hpl1/engine/resources/FrameBitmap.h"
|
|
#include "hpl1/engine/graphics/Texture.h"
|
|
#include "hpl1/engine/graphics/bitmap2D.h"
|
|
#include "hpl1/engine/math/Math.h"
|
|
#include "hpl1/engine/resources/FrameTexture.h"
|
|
#include "hpl1/engine/resources/ResourceImage.h"
|
|
#include "hpl1/engine/system/low_level_system.h"
|
|
|
|
namespace hpl {
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CONSTRUCTORS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cFrameBitmap::cFrameBitmap(Bitmap2D *apBitmap, cFrameTexture *apFrmTex, int alHandle) : iFrameBase() {
|
|
mpBitmap = apBitmap;
|
|
mpFrameTexture = apFrmTex;
|
|
mpBitmap->fillRect(cRect2l(0, 0, 0, 0), cColor(1, 1));
|
|
mlMinHole = 6;
|
|
mlHandle = alHandle;
|
|
mbIsFull = false;
|
|
mbIsLocked = false;
|
|
|
|
// Root node in rect tree
|
|
mRects.Insert(cFBitmapRect(0, 0, mpBitmap->getWidth(), mpBitmap->getHeight(), -1));
|
|
}
|
|
|
|
cFrameBitmap::~cFrameBitmap() {
|
|
hplDelete(mpBitmap);
|
|
mpBitmap = NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PUBLIC METHODS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
#define DEBUG_BTREE (false)
|
|
|
|
cResourceImage *cFrameBitmap::AddBitmap(Bitmap2D *apSrc) {
|
|
cResourceImage *pImage = NULL;
|
|
// source size
|
|
//+2 because we are gonna have a border to get rid if some antialiasing problems
|
|
int lSW = apSrc->getWidth() + 2;
|
|
int lSH = apSrc->getHeight() + 2;
|
|
|
|
// destination size
|
|
// int lDW = mpBitmap->getWidth();
|
|
// int lDH = mpBitmap->getHeight();
|
|
|
|
cVector2l vPos;
|
|
|
|
bool bFoundEmptyNode = false;
|
|
bool bFoundNode = false;
|
|
// Debug
|
|
int node = 0;
|
|
|
|
if (DEBUG_BTREE)
|
|
Log("**** Image %d *****\n", mlPicCount);
|
|
|
|
// Get the leaves of the tree and search it for a good pos.
|
|
tRectTreeNodeList lstNodes = mRects.GetLeafList();
|
|
tRectTreeNodeListIt it;
|
|
for (it = lstNodes.begin(); it != lstNodes.end(); ++it) {
|
|
if (DEBUG_BTREE)
|
|
Log("Checking node %d:\n", node++);
|
|
tRectTreeNode *TopNode = *it;
|
|
cFBitmapRect *pData = TopNode->GetData();
|
|
|
|
// Check if the space is free
|
|
if (pData->mlHandle < 0) {
|
|
if (DEBUG_BTREE)
|
|
Log("Found free node\n");
|
|
bFoundEmptyNode = true; // An empty node was found.. bitmap not full yet.
|
|
|
|
// Check if the Image fits in the rect
|
|
cRect2l NewRect = cRect2l(pData->mRect.x, pData->mRect.y, lSW, lSH);
|
|
if (DEBUG_BTREE)
|
|
Log("Fit: [%d:%d:%d:%d] in [%d:%d:%d:%d]\n",
|
|
NewRect.x, NewRect.y, NewRect.w, NewRect.h,
|
|
pData->mRect.x, pData->mRect.y, pData->mRect.w, pData->mRect.h);
|
|
|
|
if (cMath::BoxFit(NewRect, pData->mRect)) {
|
|
if (DEBUG_BTREE)
|
|
Log("The node fits!\n");
|
|
bFoundNode = true;
|
|
|
|
// If the bitmap fits perfectly add the node without splitting
|
|
if (MinimumFit(NewRect, pData->mRect)) {
|
|
if (DEBUG_BTREE)
|
|
Log("Minimum fit!\n");
|
|
pData->mRect = NewRect;
|
|
pData->mlHandle = 1;
|
|
}
|
|
// If there is still space left, make new nodes.
|
|
else {
|
|
if (DEBUG_BTREE)
|
|
Log("Normal fit!\n");
|
|
// Insert 2 children for the top node (lower and upper part.
|
|
tRectTreeNode *UpperNode;
|
|
// Upper
|
|
UpperNode = mRects.InsertAt(cFBitmapRect(NewRect.x, NewRect.y,
|
|
pData->mRect.w, NewRect.h, -2),
|
|
TopNode,
|
|
eBinTreeNode_Left);
|
|
|
|
// Lower
|
|
mRects.InsertAt(cFBitmapRect(NewRect.x, NewRect.y + NewRect.h,
|
|
pData->mRect.w, pData->mRect.h - NewRect.h, -3),
|
|
TopNode,
|
|
eBinTreeNode_Right);
|
|
|
|
// Split the Upper Node into 2 nodes.
|
|
pData = UpperNode->GetData(); // Get the data for the upper node.
|
|
// Upper split, this is the new bitmap
|
|
mRects.InsertAt(cFBitmapRect(NewRect.x, NewRect.y,
|
|
NewRect.w, NewRect.h, 2),
|
|
UpperNode,
|
|
eBinTreeNode_Left);
|
|
|
|
// Lower split, this is empty
|
|
mRects.InsertAt(cFBitmapRect(NewRect.x + NewRect.w, NewRect.y,
|
|
pData->mRect.w - NewRect.w, NewRect.h, -4),
|
|
UpperNode,
|
|
eBinTreeNode_Right);
|
|
}
|
|
|
|
vPos = cVector2l(NewRect.x + 1, NewRect.y + 1); //+1 for the right pos
|
|
|
|
// Draw 4 times so we get a nice extra border
|
|
for (int i = 0; i < 2; i++)
|
|
for (int j = 0; j < 2; j++) {
|
|
apSrc->drawToBitmap(*mpBitmap, cVector2l(NewRect.x + i * 2, NewRect.y + j * 2));
|
|
}
|
|
// Fix the border a little more:
|
|
for (int i = -1; i < 2; i++)
|
|
for (int j = -1; j < 2; j++)
|
|
if ((i == 0 || j == 0) && (i != j)) {
|
|
apSrc->drawToBitmap(*mpBitmap, cVector2l(NewRect.x + 1 + i, NewRect.y + 1 + j));
|
|
}
|
|
// Draw the final
|
|
apSrc->drawToBitmap(*mpBitmap, cVector2l(NewRect.x + 1, NewRect.y + 1));
|
|
|
|
mlPicCount++;
|
|
mpFrameTexture->SetPicCount(mlPicCount);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bFoundNode) {
|
|
// Create the image resource
|
|
pImage = hplNew(cResourceImage, (apSrc->getFileName(), mpFrameTexture, this,
|
|
cRect2l(vPos, cVector2l(lSW - 2, lSH - 2)), //-2 to get the correct size.
|
|
cVector2l(mpBitmap->getWidth(), mpBitmap->getHeight()),
|
|
mlHandle));
|
|
|
|
if (!bFoundEmptyNode) {
|
|
mbIsFull = true;
|
|
}
|
|
|
|
mbIsUpdated = true;
|
|
}
|
|
|
|
/// LAST DEBUG ///
|
|
if (DEBUG_BTREE) {
|
|
Log("Current Tree begin:\n");
|
|
tRectTreeNodeList lstNodes2 = mRects.GetNodeList();
|
|
tRectTreeNodeListIt it2;
|
|
int node2 = 0;
|
|
for (it2 = lstNodes2.begin(); it2 != lstNodes2.end(); ++it) {
|
|
cRect2l Rect = (*it2)->GetData()->mRect;
|
|
int h = (*it)->GetData()->mlHandle;
|
|
Log(" %d: [%d:%d:%d:%d]:%d\n", node2, Rect.x, Rect.y, Rect.w, Rect.h, h);
|
|
node2++;
|
|
}
|
|
Log("Current Tree end:\n");
|
|
Log("-----------------\n");
|
|
|
|
Log("Current Leaves begin:\n");
|
|
lstNodes2 = mRects.GetLeafList();
|
|
node2 = 0;
|
|
for (it2 = lstNodes2.begin(); it2 != lstNodes2.end(); ++it) {
|
|
cRect2l Rect = (*it2)->GetData()->mRect;
|
|
int h = (*it2)->GetData()->mlHandle;
|
|
Log(" %d: [%d:%d:%d:%d]: %d\n", node2, Rect.x, Rect.y, Rect.w, Rect.h, h);
|
|
node2++;
|
|
}
|
|
Log("Current Tree end:\n");
|
|
Log("-----------------\n");
|
|
}
|
|
|
|
return pImage;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
bool cFrameBitmap::MinimumFit(cRect2l aSrc, cRect2l aDest) {
|
|
if (aDest.w - aSrc.w < mlMinHole && aDest.h - aSrc.h < mlMinHole)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
bool cFrameBitmap::IsUpdated() {
|
|
return mbIsUpdated;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
bool cFrameBitmap::IsFull() {
|
|
return mbIsFull;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
bool cFrameBitmap::FlushToTexture() {
|
|
if (mbIsUpdated) {
|
|
mpFrameTexture->GetTexture()->CreateFromBitmap(mpBitmap);
|
|
mpFrameTexture->GetTexture()->SetWrapS(eTextureWrap_ClampToEdge);
|
|
mpFrameTexture->GetTexture()->SetWrapT(eTextureWrap_ClampToEdge);
|
|
|
|
// mpFrameTexture->SetPicCount(mlPicCount);
|
|
mbIsUpdated = false;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
} // namespace hpl
|