mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
279 lines
7.9 KiB
C++
279 lines
7.9 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/math/Math.h"
|
|
#include "hpl1/engine/system/low_level_system.h"
|
|
#include "hpl1/engine/resources/FrameTexture.h"
|
|
#include "hpl1/engine/resources/ResourceImage.h"
|
|
#include "hpl1/engine/graphics/bitmap2D.h"
|
|
#include "hpl1/engine/graphics/Texture.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;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
}
|