Files
2026-02-02 04:50:13 +01:00

1184 lines
32 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/gui/GuiSet.h"
#include "hpl1/engine/math/Math.h"
#include "hpl1/engine/system/low_level_system.h"
#include "hpl1/engine/graphics/Graphics.h"
#include "hpl1/engine/graphics/LowLevelGraphics.h"
#include "hpl1/engine/graphics/font_data.h"
#include "hpl1/engine/resources/FileSearcher.h"
#include "hpl1/engine/resources/FrameBitmap.h"
#include "hpl1/engine/resources/ImageManager.h"
#include "hpl1/engine/resources/ResourceImage.h"
#include "hpl1/engine/resources/Resources.h"
#include "hpl1/engine/resources/TextureManager.h"
#include "hpl1/engine/scene/Camera3D.h"
#include "hpl1/engine/scene/Scene.h"
#include "hpl1/engine/gui/Gui.h"
#include "hpl1/engine/gui/GuiGfxElement.h"
#include "hpl1/engine/gui/GuiMaterial.h"
#include "hpl1/engine/gui/GuiPopUp.h"
#include "hpl1/engine/gui/GuiSkin.h"
#include "hpl1/engine/gui/Widget.h"
#include "hpl1/engine/gui/GuiPopUpMessageBox.h"
#include "hpl1/engine/gui/WidgetButton.h"
#include "hpl1/engine/gui/WidgetCheckBox.h"
#include "hpl1/engine/gui/WidgetComboBox.h"
#include "hpl1/engine/gui/WidgetFrame.h"
#include "hpl1/engine/gui/WidgetImage.h"
#include "hpl1/engine/gui/WidgetLabel.h"
#include "hpl1/engine/gui/WidgetListBox.h"
#include "hpl1/engine/gui/WidgetSlider.h"
#include "hpl1/engine/gui/WidgetTextBox.h"
#include "hpl1/engine/gui/WidgetWindow.h"
namespace hpl {
//////////////////////////////////////////////////////////////////////////
// RENDER OBJECT
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
bool cGuiRenderObjectCompare::operator()(const cGuiRenderObject &aObjectA,
const cGuiRenderObject &aObjectB) const {
// Z
float fZA = aObjectA.mvPos.z;
float fZB = aObjectB.mvPos.z;
if (fZA != fZB) {
return fZA < fZB;
}
// Clip Region
cGuiClipRegion *pClipA = aObjectA.mpClipRegion;
cGuiClipRegion *pClipB = aObjectB.mpClipRegion;
if (pClipA != pClipB) {
return pClipA > pClipB;
}
// Material
iGuiMaterial *pMaterialA = aObjectA.mpCustomMaterial ? aObjectA.mpCustomMaterial : aObjectA.mpGfx->mpMaterial;
iGuiMaterial *pMaterialB = aObjectB.mpCustomMaterial ? aObjectB.mpCustomMaterial : aObjectB.mpGfx->mpMaterial;
if (pMaterialA != pMaterialB) {
return pMaterialA > pMaterialB;
}
// Texture
iTexture *pTextureA = aObjectA.mpGfx->mvTextures[0];
iTexture *pTextureB = aObjectB.mpGfx->mvTextures[0];
if (pTextureA != pTextureB) {
return pTextureA > pTextureB;
}
// Equal
return false;
}
//////////////////////////////////////////////////////////////////////////
// CLIP REGION
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cGuiClipRegion::~cGuiClipRegion() {
Clear();
}
void cGuiClipRegion::Clear() {
STLDeleteAll(mlstChildren);
}
cGuiClipRegion *cGuiClipRegion::CreateChild(const cVector3f &avPos, const cVector2f &avSize) {
cGuiClipRegion *pRegion = hplNew(cGuiClipRegion, ());
if (mRect.w < 0) {
pRegion->mRect = cRect2f(cVector2f(avPos.x, avPos.y), avSize);
} else {
cRect2f temp = cRect2f(cVector2f(avPos.x, avPos.y), avSize);
pRegion->mRect = cMath::ClipRect(temp, mRect);
if (pRegion->mRect.w < 0)
pRegion->mRect.w = 0;
if (pRegion->mRect.h < 0)
pRegion->mRect.h = 0;
}
mlstChildren.push_back(pRegion);
return pRegion;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cGuiSet::cGuiSet(const tString &asName, cGui *apGui, cGuiSkin *apSkin,
cResources *apResources, cGraphics *apGraphics,
cSound *apSound, cScene *apScene) {
mpGui = apGui;
mpSkin = NULL;
msName = asName;
mpResources = apResources;
mpGraphics = apGraphics;
mpSound = apSound;
mpScene = apScene;
mpGfxCurrentPointer = NULL;
mpFocusedWidget = NULL;
mpAttentionWidget = NULL;
mvDrawOffset = 0;
mvVirtualSize = mpGraphics->GetLowLevel()->GetVirtualSize();
mfVirtualMinZ = -1000;
mfVirtualMaxZ = 1000;
mbActive = true;
mbDrawMouse = true;
mfMouseZ = 20;
mbIs3D = false;
mv3DSize = 1;
m_mtx3DTransform = cMatrixf::Identity;
mbCullBackface = false;
mpWidgetRoot = hplNew(iWidget, (eWidgetType_Root, this, mpSkin));
mpWidgetRoot->AddCallback(eGuiMessage_OnDraw, this, kGuiCallback(DrawMouse));
mpCurrentClipRegion = &mBaseClipRegion;
mbDestroyingSet = false;
mlDrawPrio = 0;
for (int i = 0; i < 3; ++i)
mvMouseDown[i] = false;
SetSkin(apSkin);
}
//-----------------------------------------------------------------------
cGuiSet::~cGuiSet() {
mbDestroyingSet = true;
STLDeleteAll(mlstPopUps);
STLDeleteAll(mlstWidgets);
hplDelete(mpWidgetRoot);
mbDestroyingSet = false;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cGuiSet::Update(float afTimeStep) {
/////////////////////////////
// Popups
if (mlstPopUps.empty() == false) {
STLDeleteAll(mlstPopUps);
}
/////////////////////////////
// Update widgets
tWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iWidget *pWidget = *it;
pWidget->Update(afTimeStep);
}
}
//-----------------------------------------------------------------------
void cGuiSet::DrawAll(float afTimeStep) {
if (mbActive == false)
return;
///////////////////////////////
// Draw all widgets
SetCurrentClipRegion(&mBaseClipRegion);
mpWidgetRoot->Draw(afTimeStep, &mBaseClipRegion);
SetCurrentClipRegion(&mBaseClipRegion);
}
//-----------------------------------------------------------------------
bool cGuiSet::SendMessage(eGuiMessage aMessage, cGuiMessageData &aData) {
switch (aMessage) {
case eGuiMessage_MouseMove:
return OnMouseMove(aData);
case eGuiMessage_MouseDown:
return OnMouseDown(aData);
case eGuiMessage_MouseUp:
return OnMouseUp(aData);
case eGuiMessage_MouseDoubleClick:
return OnMouseDoubleClick(aData);
case eGuiMessage_KeyPress:
return OnKeyPress(aData);
default:
break;
}
return false;
}
//-----------------------------------------------------------------------
// TODO: Support multi textures
void cGuiSet::Render() {
iLowLevelGraphics *pLowLevelGraphics = mpGraphics->GetLowLevel();
///////////////////////////////////
// Init rendering
// 3D projection
if (mbIs3D) {
cCamera3D *pCam = static_cast<cCamera3D *>(mpScene->GetCamera());
pLowLevelGraphics->SetDepthTestActive(true);
// Invert the y coordinate: = -y, this also get the gui into the correct position.
// Also scale to size
cMatrixf mtxPreMul = cMath::MatrixScale(cVector3f(mv3DSize.x / mvVirtualSize.x,
-mv3DSize.y / mvVirtualSize.y,
mv3DSize.z / (mfVirtualMaxZ - mfVirtualMinZ)));
// Create the final model matrix
cMatrixf mtxModel = cMath::MatrixMul(m_mtx3DTransform, mtxPreMul);
mtxModel = cMath::MatrixMul(pCam->GetViewMatrix(), mtxModel);
pLowLevelGraphics->SetMatrix(eMatrix_ModelView, mtxModel);
// No need for projection matrix, should be setup, right? :)
pLowLevelGraphics->SetCullActive(mbCullBackface);
}
// Screen projection
else {
pLowLevelGraphics->SetDepthTestActive(false);
pLowLevelGraphics->SetIdentityMatrix(eMatrix_ModelView);
pLowLevelGraphics->SetOrthoProjection(mvVirtualSize, mfVirtualMinZ, mfVirtualMaxZ);
}
///////////////////////////////
// Render all clip regions
RenderClipRegion();
///////////////////////////////
// Clear the render object set
mBaseClipRegion.Clear();
if (mbIs3D) {
if (mbCullBackface == false)
pLowLevelGraphics->SetCullActive(true);
}
}
//-----------------------------------------------------------------------
void cGuiSet::DrawGfx(cGuiGfxElement *apGfx, const cVector3f &avPos, const cVector2f &avSize,
const cColor &aColor, eGuiMaterial aMaterial) {
if (mpCurrentClipRegion == NULL)
return;
if (mpCurrentClipRegion->mRect.w == 0 || mpCurrentClipRegion->mRect.h == 0)
return;
cVector3f vAbsPos = avPos + apGfx->GetOffset() + mvDrawOffset;
if (mpCurrentClipRegion->mRect.w > 0) {
cRect2f gfxRect;
gfxRect.x = vAbsPos.x;
gfxRect.y = vAbsPos.y;
if (avSize.x < 0) {
gfxRect.w = apGfx->GetImageSize().x;
gfxRect.h = apGfx->GetImageSize().y;
} else {
gfxRect.w = avSize.x;
gfxRect.h = avSize.y;
}
if (cMath::BoxCollision(mpCurrentClipRegion->mRect, gfxRect) == false)
return;
}
apGfx->Flush();
cGuiRenderObject object;
// Log("Clip: %f %f\n",mpCurrentClipRegion->mRect.w,mpCurrentClipRegion->mRect.h);
object.mpGfx = apGfx;
object.mpClipRegion = mpCurrentClipRegion;
object.mvPos = vAbsPos;
if (avSize.x < 0)
object.mvSize = apGfx->GetImageSize();
else
object.mvSize = avSize;
object.mColor = aColor;
if (aMaterial != eGuiMaterial_LastEnum)
object.mpCustomMaterial = mpGui->GetMaterial(aMaterial);
else
object.mpCustomMaterial = NULL;
m_setRenderObjects.insert(object);
}
//-----------------------------------------------------------------------
void cGuiSet::DrawFont(const tWString &asText,
FontData *apFont, const cVector3f &avPos,
const cVector2f &avSize, const cColor &aColor,
eFontAlign aAlign, eGuiMaterial aMaterial) {
int lCount = 0;
// float lXAdd = 0;
cVector3f vPos = avPos;
if (aAlign == eFontAlign_Center) {
vPos.x -= apFont->getLength(avSize, asText.c_str()) / 2;
} else if (aAlign == eFontAlign_Right) {
vPos.x -= apFont->getLength(avSize, asText.c_str());
}
while (asText[lCount] != 0) {
wchar_t lGlyphNum = ((wchar_t)asText[lCount]);
if (lGlyphNum < apFont->getFirstChar() ||
lGlyphNum > apFont->getLastChar()) {
lCount++;
continue;
}
lGlyphNum -= apFont->getFirstChar();
Glyph *pGlyph = apFont->getGlyph(lGlyphNum);
if (pGlyph) {
cVector2f vOffset(pGlyph->_offset * avSize);
cVector2f vSize(pGlyph->_size * avSize); // *apFont->GetSizeRatio());
DrawGfx(pGlyph->_guiGfx, vPos + vOffset, vSize, aColor, aMaterial);
vPos.x += pGlyph->_advance * avSize.x;
}
lCount++;
}
}
//-----------------------------------------------------------------------
cWidgetWindow *cGuiSet::CreateWidgetWindow(const cVector3f &avLocalPos,
const cVector2f &avSize,
const tWString &asText,
iWidget *apParent,
const tString &asName) {
cWidgetWindow *pWindow = hplNew(cWidgetWindow, (this, mpSkin));
pWindow->SetPosition(avLocalPos);
pWindow->SetSize(avSize);
pWindow->SetText(asText);
pWindow->SetName(asName);
AddWidget(pWindow, apParent);
return pWindow;
}
cWidgetFrame *cGuiSet::CreateWidgetFrame(const cVector3f &avLocalPos,
const cVector2f &avSize,
bool abDrawFrame,
iWidget *apParent,
const tString &asName) {
cWidgetFrame *pFrame = hplNew(cWidgetFrame, (this, mpSkin));
pFrame->SetPosition(avLocalPos);
pFrame->SetSize(avSize);
pFrame->SetDrawFrame(abDrawFrame);
pFrame->SetName(asName);
AddWidget(pFrame, apParent);
return pFrame;
}
cWidgetButton *cGuiSet::CreateWidgetButton(const cVector3f &avLocalPos,
const cVector2f &avSize,
const tWString &asText,
iWidget *apParent,
const tString &asName) {
cWidgetButton *pButton = hplNew(cWidgetButton, (this, mpSkin));
pButton->SetPosition(avLocalPos);
pButton->SetSize(avSize);
pButton->SetText(asText);
pButton->SetName(asName);
AddWidget(pButton, apParent);
return pButton;
}
cWidgetLabel *cGuiSet::CreateWidgetLabel(const cVector3f &avLocalPos,
const cVector2f &avSize,
const tWString &asText,
iWidget *apParent,
const tString &asName) {
cWidgetLabel *pLabel = hplNew(cWidgetLabel, (this, mpSkin));
pLabel->SetPosition(avLocalPos);
pLabel->SetSize(avSize);
pLabel->SetText(asText);
pLabel->SetName(asName);
AddWidget(pLabel, apParent);
return pLabel;
}
cWidgetSlider *cGuiSet::CreateWidgetSlider(eWidgetSliderOrientation aOrientation,
const cVector3f &avLocalPos,
const cVector2f &avSize,
int alMaxValue,
iWidget *apParent,
const tString &asName) {
cWidgetSlider *pSlider = hplNew(cWidgetSlider, (this, mpSkin, aOrientation));
pSlider->SetPosition(avLocalPos);
pSlider->SetSize(avSize);
pSlider->SetMaxValue(alMaxValue);
pSlider->SetName(asName);
AddWidget(pSlider, apParent);
return pSlider;
}
cWidgetTextBox *cGuiSet::CreateWidgetTextBox(const cVector3f &avLocalPos,
const cVector2f &avSize,
const tWString &asText,
iWidget *apParent,
const tString &asName) {
cWidgetTextBox *pTextBox = hplNew(cWidgetTextBox, (this, mpSkin));
pTextBox->SetPosition(avLocalPos);
pTextBox->SetSize(avSize);
pTextBox->SetText(asText);
pTextBox->SetName(asName);
AddWidget(pTextBox, apParent);
return pTextBox;
}
cWidgetCheckBox *cGuiSet::CreateWidgetCheckBox(const cVector3f &avLocalPos,
const cVector2f &avSize,
const tWString &asText,
iWidget *apParent,
const tString &asName) {
cWidgetCheckBox *pCheckBox = hplNew(cWidgetCheckBox, (this, mpSkin));
pCheckBox->SetPosition(avLocalPos);
pCheckBox->SetSize(avSize);
pCheckBox->SetText(asText);
pCheckBox->SetName(asName);
AddWidget(pCheckBox, apParent);
return pCheckBox;
}
cWidgetImage *cGuiSet::CreateWidgetImage(const tString &asFile,
const cVector3f &avLocalPos,
const cVector2f &avSize,
eGuiMaterial aMaterial,
bool abAnimate,
iWidget *apParent,
const tString &asName) {
cWidgetImage *pImage = hplNew(cWidgetImage, (this, mpSkin));
cGuiGfxElement *pGfx = NULL;
if (asFile != "") {
if (abAnimate) {
pGfx = mpGui->CreateGfxImageBuffer(asFile, aMaterial, true);
} else {
pGfx = mpGui->CreateGfxImage(asFile, aMaterial);
}
}
pImage->SetPosition(avLocalPos);
if (pGfx && avSize.x < 0) {
pImage->SetSize(pGfx->GetImageSize());
} else {
pImage->SetSize(avSize);
}
pImage->SetImage(pGfx);
pImage->SetName(asName);
AddWidget(pImage, apParent);
return pImage;
}
cWidgetListBox *cGuiSet::CreateWidgetListBox(const cVector3f &avLocalPos,
const cVector2f &avSize,
iWidget *apParent,
const tString &asName) {
cWidgetListBox *pListBox = hplNew(cWidgetListBox, (this, mpSkin));
pListBox->SetPosition(avLocalPos);
pListBox->SetSize(avSize);
pListBox->SetName(asName);
AddWidget(pListBox, apParent);
return pListBox;
}
cWidgetComboBox *cGuiSet::CreateWidgetComboBox(const cVector3f &avLocalPos,
const cVector2f &avSize,
const tWString &asText,
iWidget *apParent,
const tString &asName) {
cWidgetComboBox *pComboBox = hplNew(cWidgetComboBox, (this, mpSkin));
pComboBox->SetPosition(avLocalPos);
pComboBox->SetSize(avSize);
pComboBox->SetText(asText);
pComboBox->SetName(asName);
AddWidget(pComboBox, apParent);
return pComboBox;
}
//-----------------------------------------------------------------------
iWidget *cGuiSet::GetWidgetFromName(const tString &asName) {
return (iWidget *)STLFindByName(mlstWidgets, asName);
}
//-----------------------------------------------------------------------
void cGuiSet::DestroyWidget(iWidget *apWidget) {
if (apWidget == mpFocusedWidget)
mpFocusedWidget = NULL;
STLFindAndDelete(mlstWidgets, apWidget);
}
//-----------------------------------------------------------------------
void cGuiSet::CreatePopUpMessageBox(const tWString &asLabel, const tWString &asText,
const tWString &asButton1, const tWString &asButton2,
void *apCallbackObject, tGuiCallbackFunc apCallback) {
/* cGuiPopUpMessageBox *pMessageBox = */ (void)hplNew(cGuiPopUpMessageBox, (this, asLabel, asText,
asButton1, asButton2,
apCallbackObject, apCallback));
}
//-----------------------------------------------------------------------
void cGuiSet::DestroyPopUp(iGuiPopUp *apPopUp) {
mlstPopUps.push_back(apPopUp);
}
//-----------------------------------------------------------------------
void cGuiSet::SetActive(bool abX) {
if (mbActive == abX)
return;
mbActive = abX;
}
//-----------------------------------------------------------------------
void cGuiSet::SetDrawMouse(bool abX) {
if (mbDrawMouse == abX)
return;
mbDrawMouse = abX;
}
//-----------------------------------------------------------------------
void cGuiSet::SetRootWidgetClips(bool abX) {
mpWidgetRoot->SetClipActive(abX);
if (abX)
mpWidgetRoot->SetSize(mvVirtualSize);
else
mpWidgetRoot->SetSize(0);
}
bool cGuiSet::GetRootWidgetClips() {
return mpWidgetRoot->GetClipActive();
}
//-----------------------------------------------------------------------
void cGuiSet::SetVirtualSize(const cVector2f &avSize, float afMinZ, float afMaxZ) {
mvVirtualSize = avSize;
mfVirtualMinZ = afMinZ;
mfVirtualMaxZ = afMaxZ;
}
//-----------------------------------------------------------------------
void cGuiSet::SetFocusedWidget(iWidget *apWidget) {
if (mpFocusedWidget) {
cGuiMessageData data = cGuiMessageData(mvMousePos, 0);
mpFocusedWidget->ProcessMessage(eGuiMessage_LostFocus, data);
}
mpFocusedWidget = apWidget;
if (mpFocusedWidget) {
cGuiMessageData data = cGuiMessageData(mvMousePos, 0);
mpFocusedWidget->ProcessMessage(eGuiMessage_GotFocus, data);
}
}
//-----------------------------------------------------------------------
void cGuiSet::SetAttentionWidget(iWidget *apWidget) {
if (mpAttentionWidget == apWidget)
return;
mpAttentionWidget = apWidget;
// Log("Sett attn: %d\n",mpAttentionWidget);
if (mpFocusedWidget && mpFocusedWidget->IsConnectedTo(mpAttentionWidget) == false) {
// Log("Lost focus %d\n",mpFocusedWidget);
cGuiMessageData data = cGuiMessageData(mvMousePos, 0);
mpFocusedWidget->ProcessMessage(eGuiMessage_LostFocus, data);
mpFocusedWidget = NULL;
}
if (mpAttentionWidget && mpFocusedWidget == NULL) {
// Log("Got focus %d\n",apWidget);
mpFocusedWidget = apWidget;
if (mpFocusedWidget) {
cGuiMessageData data = cGuiMessageData(mvMousePos, 0);
mpFocusedWidget->ProcessMessage(eGuiMessage_GotFocus, data);
}
}
}
//-----------------------------------------------------------------------
void cGuiSet::SetIs3D(bool abX) {
mbIs3D = abX;
}
void cGuiSet::Set3DSize(const cVector3f &avSize) {
mv3DSize = avSize;
}
void cGuiSet::Set3DTransform(const cMatrixf &a_mtxTransform) {
m_mtx3DTransform = a_mtxTransform;
}
//-----------------------------------------------------------------------
void cGuiSet::SetCurrentPointer(cGuiGfxElement *apGfx) {
mpGfxCurrentPointer = apGfx;
}
//-----------------------------------------------------------------------
bool cGuiSet::HasFocus() {
return mpGui->GetFocusedSet() == this;
}
//-----------------------------------------------------------------------
void cGuiSet::SetSkin(cGuiSkin *apSkin) {
// if(mpSkin == apSkin) return; Remove til there is a real skin
mpSkin = apSkin;
if (mpSkin) {
mpGfxCurrentPointer = mpSkin->GetGfx(eGuiSkinGfx_PointerNormal);
} else {
mpGfxCurrentPointer = NULL;
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
#define kLogRender (false)
static void SetClipArea(iLowLevelGraphics *pLowLevelGraphics, cGuiClipRegion *apRegion) {
cRect2f &clipRect = apRegion->mRect;
//////////////////////////////////
// Set up clip area
if (apRegion->mRect.w > 0) {
cPlanef plane;
cVector2f vVirtualSize = pLowLevelGraphics->GetVirtualSize();
cVector2f vScreenSize = pLowLevelGraphics->GetScreenSize();
cRect2l vScissorRect((int)((clipRect.x / vVirtualSize.x) * vScreenSize.x), (int)((clipRect.y / vVirtualSize.y) * vScreenSize.y),
(int)((clipRect.w / vVirtualSize.x) * vScreenSize.x), (int)((clipRect.h / vVirtualSize.y) * vScreenSize.y));
pLowLevelGraphics->SetScissorActive(true);
pLowLevelGraphics->SetScissorRect(vScissorRect);
// Bottom
/*plane.FromNormalPoint(cVector3f(0,-1,0),cVector3f(0,clipRect.y+clipRect.h,0));
pLowLevelGraphics->SetClipPlane(0, plane);
pLowLevelGraphics->SetClipPlaneActive(0, true);
//Top
plane.FromNormalPoint(cVector3f(0,1,0),cVector3f(0,clipRect.y,0));
pLowLevelGraphics->SetClipPlane(1, plane);
pLowLevelGraphics->SetClipPlaneActive(1, true);
//Right
plane.FromNormalPoint(cVector3f(1,0,0),cVector3f(clipRect.x,0,0));
pLowLevelGraphics->SetClipPlane(2, plane);
pLowLevelGraphics->SetClipPlaneActive(2, true);
//Left
plane.FromNormalPoint(cVector3f(-1,0,0),cVector3f(clipRect.x+clipRect.w,0,0));
pLowLevelGraphics->SetClipPlane(3, plane);
pLowLevelGraphics->SetClipPlaneActive(3, true);*/
if (kLogRender)
Log("-- Clip region: %d Clipping: x %f y %f w %f h %f\n", apRegion,
apRegion->mRect.x, apRegion->mRect.y,
apRegion->mRect.w, apRegion->mRect.h);
} else {
if (kLogRender)
Log("-- Clip region: %d No clipping!\n", apRegion);
}
}
//-----------------------------------------------------------------------
void cGuiSet::RenderClipRegion() {
iLowLevelGraphics *pLowLevelGraphics = mpGraphics->GetLowLevel();
if (kLogRender)
Log("-------------------\n");
///////////////////////////////////////
// See if there is anything to draw
tGuiRenderObjectSet &setRenderObjects = m_setRenderObjects;
if (setRenderObjects.empty()) {
if (kLogRender)
Log("------------------------\n");
return;
}
//////////////////////////////////
// Graphics setup
pLowLevelGraphics->SetTexture(0, NULL);
//////////////////////////////////
// Set up variables
tGuiRenderObjectSetIt it = setRenderObjects.begin();
iGuiMaterial *pLastMaterial = NULL;
iTexture *pLastTexture = NULL;
cGuiClipRegion *pLastClipRegion = NULL;
cGuiGfxElement *pGfx = it->mpGfx;
iGuiMaterial *pMaterial = it->mpCustomMaterial ? it->mpCustomMaterial : pGfx->mpMaterial;
iTexture *pTexture = pGfx->mvTextures[0];
cGuiClipRegion *pClipRegion = it->mpClipRegion;
int lIdxAdd = 0;
///////////////////////////////////
// Iterate objects
while (it != setRenderObjects.end()) {
///////////////////////////////
// Start rendering
if (pLastMaterial != pMaterial) {
pMaterial->BeforeRender();
if (kLogRender)
Log("Material %s before\n", pMaterial->GetName().c_str());
}
////////////////////////////
// SetClip area
if (pLastClipRegion != pClipRegion) {
SetClipArea(pLowLevelGraphics, pClipRegion);
}
pLowLevelGraphics->SetTexture(0, pTexture);
if (kLogRender)
Log("Texture %d\n", pTexture);
//////////////////////////
// Iterate for all with same texture and material
do {
cGuiRenderObject object = *it;
pGfx = object.mpGfx;
if (kLogRender) {
if (pGfx->mvImages[0])
Log(" gfx: %d '%s'\n", pGfx, pGfx->mvImages[0]->GetName().c_str());
else
Log(" gfx: %d 'null'\n");
}
///////////////////////////
// Add object to batch
for (int i = 0; i < 4; ++i) {
cVertex &vtx = pGfx->mvVtx[i];
cVector3f &vVtxPos = vtx.pos;
cVector3f &vPos = object.mvPos;
pLowLevelGraphics->AddVertexToBatch_Raw(
cVector3f(vVtxPos.x * object.mvSize.x + vPos.x,
vVtxPos.y * object.mvSize.y + vPos.y,
vPos.z),
vtx.col * object.mColor,
vtx.tex);
}
for (int i = 0; i < 4; i++)
pLowLevelGraphics->AddIndexToBatch(lIdxAdd + i);
lIdxAdd += 4;
///////////////////////////
// Set last texture
pLastMaterial = pMaterial;
pLastTexture = pTexture;
pLastClipRegion = pClipRegion;
/////////////////////////////
// Get next object
++it;
if (it == setRenderObjects.end())
break;
pGfx = it->mpGfx;
pMaterial = it->mpCustomMaterial ? it->mpCustomMaterial : pGfx->mpMaterial;
pTexture = it->mpGfx->mvTextures[0];
pClipRegion = it->mpClipRegion;
} while (pTexture == pLastTexture &&
pMaterial == pLastMaterial &&
pClipRegion == pLastClipRegion);
//////////////////////////////
// Render batch
pLowLevelGraphics->FlushQuadBatch(eVtxBatchFlag_Position | eVtxBatchFlag_Texture0 |
eVtxBatchFlag_Color0,
false);
pLowLevelGraphics->ClearBatch();
lIdxAdd = 0;
/////////////////////////////////
// Clip region end
if (pLastClipRegion != pClipRegion || it == setRenderObjects.end()) {
if (pLastClipRegion->mRect.w > 0) {
pLowLevelGraphics->SetScissorActive(false);
// for(int i=0; i<4; ++i) pLowLevelGraphics->SetClipPlaneActive(i, false);
}
}
/////////////////////////////////
// Material end
if (pLastMaterial != pMaterial || it == setRenderObjects.end()) {
pLastMaterial->AfterRender();
if (kLogRender)
Log("Material %d '%s' after. new: %d '%s'\n", pLastMaterial, pLastMaterial->GetName().c_str(),
pMaterial, pMaterial->GetName().c_str());
}
}
///////////////////////////////
// Clear render objects
m_setRenderObjects.clear();
if (kLogRender)
Log("---------- END %d -----------\n");
}
//-----------------------------------------------------------------------
void cGuiSet::AddWidget(iWidget *apWidget, iWidget *apParent) {
mlstWidgets.push_front(apWidget);
if (apParent)
apParent->AttachChild(apWidget);
else
mpWidgetRoot->AttachChild(apWidget);
apWidget->Init();
}
//-----------------------------------------------------------------------
bool cGuiSet::OnMouseMove(cGuiMessageData &aData) {
///////////////////////////
// Set up variables
mvMousePos = aData.mvPos;
aData.mlVal = 0;
if (mvMouseDown[0])
aData.mlVal |= eGuiMouseButton_Left;
if (mvMouseDown[1])
aData.mlVal |= eGuiMouseButton_Middle;
if (mvMouseDown[2])
aData.mlVal |= eGuiMouseButton_Right;
///////////////////////////
// Call widgets
bool bRet = false;
bool bPointerSet = false;
tWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iWidget *pWidget = *it;
if (pWidget->PointIsInside(mvMousePos, false)) {
////////////////////////////
// Mouse enter event
if (pWidget->GetMouseIsOver() == false) {
pWidget->SetMouseIsOver(true);
if (pWidget->ProcessMessage(eGuiMessage_MouseEnter, aData)) {
bRet = true;
}
}
////////////////////////////
// Set pointer
if (bPointerSet == false && pWidget->GetPointerGfx()) {
if (mpAttentionWidget &&
pWidget->IsConnectedTo(mpAttentionWidget) == false) {
} else {
if (mpGfxCurrentPointer != pWidget->GetPointerGfx()) {
if (pWidget->IsEnabled()) {
SetCurrentPointer(pWidget->GetPointerGfx());
}
}
bPointerSet = true;
}
}
} else {
////////////////////////////
// Mouse leave event
if (pWidget->GetMouseIsOver()) {
pWidget->SetMouseIsOver(false);
pWidget->ProcessMessage(eGuiMessage_MouseLeave, aData);
// In case the widget is moved under the mouse again, check:
if (mpFocusedWidget == pWidget && pWidget->PointIsInside(mvMousePos, false)) {
pWidget->SetMouseIsOver(true);
if (pWidget->ProcessMessage(eGuiMessage_MouseEnter, aData))
bRet = true;
}
}
}
////////////////////////////
// Mouse move event
if (pWidget->GetMouseIsOver() || mpFocusedWidget == pWidget) {
if (pWidget->ProcessMessage(eGuiMessage_MouseMove, aData))
bRet = true;
}
}
return bRet;
}
//-----------------------------------------------------------------------
bool cGuiSet::OnMouseDown(cGuiMessageData &aData) {
///////////////////////////
// Set up variables
mvMouseDown[cMath::Log2ToInt(aData.mlVal)] = true;
aData.mvPos = mvMousePos;
iWidget *pOldFocus = mpFocusedWidget;
///////////////////////////
// Call widgets
bool bRet = false;
tWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iWidget *pWidget = *it;
// If these is an attention set, do send clicks to any other widgets
if (mpAttentionWidget && pWidget->IsConnectedTo(mpAttentionWidget) == false) {
continue;
}
if (pWidget->GetMouseIsOver()) {
if (mpFocusedWidget != pWidget) {
if (pWidget->ProcessMessage(eGuiMessage_GotFocus, aData)) {
mpFocusedWidget = pWidget;
}
} else {
mpFocusedWidget = pWidget;
}
// Log("Got focus %d\n",pWidget);
if (pWidget->ProcessMessage(eGuiMessage_MouseDown, aData)) {
bRet = true;
break;
}
}
}
// Se if anything was clicked
if (bRet == false) {
mpFocusedWidget = NULL;
}
// Lost focus callback
if (mpFocusedWidget != pOldFocus) {
// Log("Lost focus %d\n",pOldFocus);
if (pOldFocus)
pOldFocus->ProcessMessage(eGuiMessage_LostFocus, aData);
}
return bRet;
}
//-----------------------------------------------------------------------
bool cGuiSet::OnMouseUp(cGuiMessageData &aData) {
///////////////////////////
// Set up variables
mvMouseDown[cMath::Log2ToInt(aData.mlVal)] = false;
aData.mvPos = mvMousePos;
///////////////////////////
// Call widgets
bool bRet = false;
if (mpFocusedWidget) {
bRet = mpFocusedWidget->ProcessMessage(eGuiMessage_MouseUp, aData);
}
if (bRet == false) {
tWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iWidget *pWidget = *it;
// If these is an attention set, do send clicks to any other widgets
if (mpAttentionWidget && pWidget->IsConnectedTo(mpAttentionWidget) == false) {
continue;
}
if (pWidget != mpFocusedWidget && pWidget->GetMouseIsOver()) {
if (pWidget->ProcessMessage(eGuiMessage_MouseUp, aData)) {
bRet = true;
break;
}
}
}
}
return bRet;
}
//-----------------------------------------------------------------------
bool cGuiSet::OnMouseDoubleClick(cGuiMessageData &aData) {
///////////////////////////
// Set up variables
aData.mvPos = mvMousePos;
///////////////////////////
// Call widgets
bool bRet = false;
tWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iWidget *pWidget = *it;
// If these is an attention set, do send clicks to any other widgets
if (mpAttentionWidget && pWidget->IsConnectedTo(mpAttentionWidget) == false) {
continue;
}
if (pWidget->GetMouseIsOver()) {
if (pWidget->ProcessMessage(eGuiMessage_MouseDoubleClick, aData)) {
bRet = true;
break;
}
}
}
return bRet;
}
//-----------------------------------------------------------------------
bool cGuiSet::OnKeyPress(cGuiMessageData &aData) {
///////////////////////////
// Set up variables
aData.mvPos = mvMousePos;
///////////////////////////
// Call widgets
bool bRet = false;
if (mpFocusedWidget) {
bRet = mpFocusedWidget->ProcessMessage(eGuiMessage_KeyPress, aData);
}
if (bRet == false) {
tWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iWidget *pWidget = *it;
// If these is an attention set, do send clicks to any other widgets
if (mpAttentionWidget && pWidget->IsConnectedTo(mpAttentionWidget) == false) {
continue;
}
if (pWidget->GetMouseIsOver() && mpFocusedWidget != pWidget) {
if (pWidget->ProcessMessage(eGuiMessage_KeyPress, aData)) {
bRet = true;
break;
}
}
}
}
return bRet;
}
//-----------------------------------------------------------------------
bool cGuiSet::DrawMouse(iWidget *apWidget, cGuiMessageData &aData) {
if (HasFocus() && mbDrawMouse && mpGfxCurrentPointer) {
DrawGfx(mpGfxCurrentPointer, cVector3f(mvMousePos.x, mvMousePos.y, mfMouseZ),
mpGfxCurrentPointer->GetImageSize(), cColor(1, 1));
}
return true;
}
kGuiCalllbackDeclaredFuncEnd(cGuiSet, DrawMouse)
//-----------------------------------------------------------------------
} // namespace hpl