The-Powder-Toy/src/interface/Panel.cpp

455 lines
11 KiB
C++

#pragma once
#include <vector>
//#include "Platform.h"
#include "interface/Panel.h"
#include "interface/Point.h"
#include "interface/Window.h"
#include "interface/Component.h"
#include "graphics/Graphics.h"
using namespace ui;
Panel::Panel(Point position, Point size):
Component(position, size),
InnerSize(size),
ViewportPosition(0, 0),
mouseInside(false)
{
#ifdef OGLI
GLint lastVid;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &lastVid);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &myVidTex);
glBindTexture(GL_TEXTURE_2D, myVidTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, XRES+BARSIZE, YRES+MENUSIZE, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
//FBO
glGenFramebuffers(1, &myVid);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, myVid);
glEnable(GL_BLEND);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, myVidTex, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Reset framebuffer binding
glDisable(GL_TEXTURE_2D);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, lastVid);
#else
myVid = new pixel[(XRES+BARSIZE)*(YRES+MENUSIZE)];
#endif
}
Panel::~Panel()
{
for(unsigned i = 0; i < children.size(); ++i)
{
if( children[i] )
delete children[i];
}
#ifdef OGLI
glDeleteTextures(1, &myVidTex);
glDeleteFramebuffers(1, &myVid);
#else
delete[] myVid;
#endif
}
void Panel::AddChild(Component* c)
{
c->SetParent(this);
c->SetParentWindow(this->GetParentWindow());
}
int Panel::GetChildCount()
{
return children.size();
}
Component* Panel::GetChild(unsigned idx)
{
return children[idx];
}
void Panel::RemoveChild(Component* c)
{
for(int i = 0; i < children.size(); ++i)
{
if(children[i] == c)
{
//remove child from parent. Does not free memory
children.erase(children.begin() + i);
break;
}
}
}
void Panel::RemoveChild(unsigned idx, bool freeMem)
{
if(freeMem)
delete children[idx];
children.erase(children.begin() + idx);
}
void Panel::Draw(const Point& screenPos)
{
// draw ourself first
XDraw(screenPos);
#ifdef OGLI
GLint lastVid;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &lastVid);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, myVid);
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
#else
pixel * lastVid = ui::Engine::Ref().g->vid;
ui::Engine::Ref().g->vid = myVid;
std::fill(myVid, myVid+((XRES+BARSIZE)*(YRES+MENUSIZE)), 0);
#endif
// attempt to draw all children
for(int i = 0; i < children.size(); ++i)
{
// the component must be visible
if(children[i]->Visible)
{
//check if the component is in the screen, draw if it is
if( children[i]->Position.X + ViewportPosition.X + children[i]->Size.X >= 0 &&
children[i]->Position.Y + ViewportPosition.Y + children[i]->Size.Y >= 0 &&
children[i]->Position.X + ViewportPosition.X < ui::Engine::Ref().GetWidth() &&
children[i]->Position.Y + ViewportPosition.Y < ui::Engine::Ref().GetHeight() )
{
Point scrpos = /*screenPos + */children[i]->Position + ViewportPosition;
children[i]->Draw(scrpos);
}
}
}
#ifdef OGLI
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, lastVid);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, myVidTex);
int x = screenPos.X, y = screenPos.Y;
int h = Size.Y, w = Size.X;
double texX = double(Size.X)/double(XRES+BARSIZE), texY = 1, texYB = 1-(double(Size.Y)/double(YRES+MENUSIZE));
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glTexCoord2d(0, texYB);
glVertex2f(x, y+h);
glTexCoord2d(texX, texYB);
glVertex2f(x+w, y+h);
glTexCoord2d(texX, texY);
glVertex2f(x+w, y);
glTexCoord2d(0, texY);
glVertex2f(x, y);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
#else
ui::Engine::Ref().g->vid = lastVid;
//dst=(pixel *)sdl_scrn->pixels+y*sdl_scrn->pitch/PIXELSIZE+x;
for (int row = 0; row < Size.Y; row++)
{
std::copy(myVid+(row*(XRES+BARSIZE)), myVid+(row*(XRES+BARSIZE))+Size.X, lastVid+((screenPos.Y+row)*(XRES+BARSIZE))+screenPos.X);
}
#endif
}
void Panel::Tick(float dt)
{
// tick ourself first
XTick(dt);
// tick our children
for(unsigned i = 0; i < children.size(); ++i)
children[i]->Tick(dt);
}
void Panel::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt)
{
XOnKeyPress(key, character, shift, ctrl, alt);
}
void Panel::OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt)
{
XOnKeyRelease(key, character, shift, ctrl, alt);
}
void Panel::OnMouseClick(int localx, int localy, unsigned button)
{
bool childclicked = false;
//check if clicked a child
for(int i = children.size()-1; i >= 0 ; --i)
{
//child must be unlocked
if(!children[i]->Locked)
{
//is mouse inside?
if( localx >= children[i]->Position.X + ViewportPosition.X &&
localy >= children[i]->Position.Y + ViewportPosition.Y &&
localx < children[i]->Position.X + ViewportPosition.X + children[i]->Size.X &&
localy < children[i]->Position.Y + ViewportPosition.Y + children[i]->Size.Y )
{
childclicked = true;
GetParentWindow()->FocusComponent(children[i]);
children[i]->OnMouseClick(localx - children[i]->Position.X - ViewportPosition.X, localy - children[i]->Position.Y - ViewportPosition.Y, button);
break;
}
}
}
//if a child wasn't clicked, send click to ourself
if(!childclicked)
{
XOnMouseClick(localx, localy, button);
GetParentWindow()->FocusComponent(this);
}
}
void Panel::OnMouseDown(int x, int y, unsigned button)
{
XOnMouseDown(x, y, button);
for(int i = 0; i < children.size(); ++i)
{
if(!children[i]->Locked)
children[i]->OnMouseDown(x, y, button);
}
}
void Panel::OnMouseHover(int localx, int localy)
{
// check if hovering on children
for(int i = children.size() - 1; i >= 0; --i)
{
if(!children[i]->Locked)
{
if( localx >= children[i]->Position.X &&
localy >= children[i]->Position.Y &&
localx < children[i]->Position.X + children[i]->Size.X &&
localy < children[i]->Position.Y + children[i]->Size.Y )
{
children[i]->OnMouseHover(localx - children[i]->Position.X, localy - children[i]->Position.Y);
break;
}
}
}
// always allow hover on parent (?)
XOnMouseHover(localx, localy);
}
void Panel::OnMouseMoved(int localx, int localy, int dx, int dy)
{
XOnMouseMoved(localx, localy, dx, dy);
for(int i = 0; i < children.size(); ++i)
{
if(!children[i]->Locked)
children[i]->OnMouseMoved(localx - children[i]->Position.X - ViewportPosition.X, localy - children[i]->Position.Y - ViewportPosition.Y, dx, dy);
}
}
void Panel::OnMouseMovedInside(int localx, int localy, int dx, int dy)
{
for(int i = 0; i < children.size(); ++i)
{
if(!children[i]->Locked)
{
Point local (localx - children[i]->Position.X - ViewportPosition.X, localy - children[i]->Position.Y - ViewportPosition.Y)
, prevlocal (local.X - dx, local.Y - dy);
// mouse currently inside?
if( local.X >= 0 &&
local.Y >= 0 &&
local.X < children[i]->Size.X &&
local.Y < children[i]->Size.Y )
{
children[i]->OnMouseMovedInside(localx - children[i]->Position.X - ViewportPosition.X, localy - children[i]->Position.Y - ViewportPosition.Y, dx, dy);
// was the mouse outside?
if(!(prevlocal.X >= 0 &&
prevlocal.Y >= 0 &&
prevlocal.X < children[i]->Size.X &&
prevlocal.Y < children[i]->Size.Y ) )
{
children[i]->OnMouseEnter(local.X, local.Y);
}
}
// if not currently inside
else
{
// was the mouse inside?
if( prevlocal.X >= 0 &&
prevlocal.Y >= 0 &&
prevlocal.X < children[i]->Size.X &&
prevlocal.Y < children[i]->Size.Y )
{
children[i]->OnMouseLeave(local.X, local.Y);
}
}
}
}
// always allow hover on parent (?)
XOnMouseMovedInside(localx, localy, dx, dy);
}
void Panel::OnMouseEnter(int localx, int localy)
{
mouseInside = true;
XOnMouseEnter(localx, localy);
}
void Panel::OnMouseLeave(int localx, int localy)
{
mouseInside = false;
XOnMouseLeave(localx, localy);
}
void Panel::OnMouseUnclick(int localx, int localy, unsigned button)
{
bool childunclicked = false;
//check if clicked a child
for(int i = children.size()-1; i >= 0 ; --i)
{
//child must be unlocked
if(!children[i]->Locked)
{
//is mouse inside?
if( localx >= children[i]->Position.X + ViewportPosition.X &&
localy >= children[i]->Position.Y + ViewportPosition.Y &&
localx < children[i]->Position.X + ViewportPosition.X + children[i]->Size.X &&
localy < children[i]->Position.Y + ViewportPosition.Y + children[i]->Size.Y )
{
childunclicked = true;
children[i]->OnMouseUnclick(localx - children[i]->Position.X - ViewportPosition.X, localy - children[i]->Position.Y - ViewportPosition.Y, button);
break;
}
}
}
//if a child wasn't clicked, send click to ourself
if(!childunclicked)
{
XOnMouseUnclick(localx, localy, button);
}
}
void Panel::OnMouseUp(int x, int y, unsigned button)
{
XOnMouseUp(x, y, button);
for(int i = 0; i < children.size(); ++i)
{
if(!children[i]->Locked)
children[i]->OnMouseUp(x, y, button);
}
}
void Panel::OnMouseWheel(int localx, int localy, int d)
{
XOnMouseWheel(localx, localy, d);
for(int i = 0; i < children.size(); ++i)
{
if(!children[i]->Locked)
children[i]->OnMouseWheel(localx - children[i]->Position.X - ViewportPosition.X, localy - children[i]->Position.Y - ViewportPosition.Y, d);
}
}
void Panel::OnMouseWheelInside(int localx, int localy, int d)
{
XOnMouseWheelInside(localx, localy, d);
//check if clicked a child
for(int i = children.size()-1; i >= 0 ; --i)
{
//child must be unlocked
if(!children[i]->Locked)
{
//is mouse inside?
if( localx >= children[i]->Position.X + ViewportPosition.X &&
localy >= children[i]->Position.Y + ViewportPosition.Y &&
localx < children[i]->Position.X + ViewportPosition.X + children[i]->Size.X &&
localy < children[i]->Position.Y + ViewportPosition.Y + children[i]->Size.Y )
{
children[i]->OnMouseWheelInside(localx - children[i]->Position.X - ViewportPosition.X, localy - children[i]->Position.Y - ViewportPosition.Y, d);
break;
}
}
}
}
// ***** OVERRIDEABLES *****
// Kept empty.
void Panel::XDraw(const Point& screenPos)
{
}
void Panel::XTick(float dt)
{
}
void Panel::XOnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt)
{
}
void Panel::XOnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt)
{
}
void Panel::XOnMouseClick(int localx, int localy, unsigned button)
{
}
void Panel::XOnMouseDown(int x, int y, unsigned button)
{
}
void Panel::XOnMouseHover(int localx, int localy)
{
}
void Panel::XOnMouseMoved(int localx, int localy, int dx, int dy)
{
}
void Panel::XOnMouseMovedInside(int localx, int localy, int dx, int dy)
{
}
void Panel::XOnMouseEnter(int localx, int localy)
{
}
void Panel::XOnMouseLeave(int localx, int localy)
{
}
void Panel::XOnMouseUnclick(int localx, int localy, unsigned button)
{
}
void Panel::XOnMouseUp(int x, int y, unsigned button)
{
}
void Panel::XOnMouseWheel(int localx, int localy, int d)
{
}
void Panel::XOnMouseWheelInside(int localx, int localy, int d)
{
}