First iteration of GUI code. GUI is rendered on top of everything, world still separate.

This commit is contained in:
2015-09-22 14:39:08 +02:00
parent 0e6fcfb2ba
commit 1d500eb4f6
12 changed files with 855 additions and 54 deletions
+247
View File
@@ -0,0 +1,247 @@
#ifndef GUI_Frame_h__
#define GUI_Frame_h__
#include <memory>
#include <map>
#include "Core/Util/Rectangle.h"
#include "Core/EventBroker.h"
#include "Core/EKeyDown.h"
#include "Core/EKeyUp.h"
#include "Core/ResourceManager.h"
#include "Core/Renderer.h"
#include "Core/RenderQueue.h"
#include "Core/Texture.h"
#include "Input/EInputCommand.h"
namespace dd
{
namespace GUI
{
class Frame : public Rectangle
{
public:
enum class Anchor
{
Left,
Right,
Top,
Bottom
};
static const int BaseWidth = 1280;
static const int BaseHeight = 720;
// Set up a base frame with an event broker
Frame(dd::EventBroker* eventBroker)
: EventBroker(eventBroker)
, Rectangle()
{ Initialize(); }
// Create a frame as a child
Frame(Frame* parent, std::string name)
: m_Name(name)
{
SetParent(parent);
Initialize();
}
~Frame()
{
/*for (auto layer : m_Children)
{
for (auto child : layer.second)
{
delete child.second;
}
}
if (m_Parent)
{
m_Parent->RemoveChild(this);
}*/
}
Frame* Parent() const { return m_Parent; }
void SetParent(Frame* parent)
{
if (parent == nullptr) {
LOG_ERROR("Failed to parent frame \"%s\": Invalid parent", m_Name.c_str());
return;
}
Width = parent->Width;
Height = parent->Height;
m_Layer = parent->Layer() + 1;
parent->AddChild(this);
m_Parent = parent;
EventBroker = parent->EventBroker;
}
void AddChild(Frame* child)
{
m_Children[child->m_Layer].insert(std::make_pair(child->Name(), child));
if (m_Parent) {
m_Parent->AddChild(child);
}
}
void RemoveChild(Frame* child)
{
auto it = m_Children.find(child->m_Layer);
if (it != m_Children.end()) {
m_Children.erase(it);
}
if (m_Parent) {
m_Parent->RemoveChild(child);
}
}
std::string Name() const { return m_Name; }
void SetName(std::string val) { m_Name = val; }
int Layer() const { return m_Layer; }
bool Hidden() const
{
if (m_Parent)
return m_Parent->Hidden() || m_Hidden;
else
return m_Hidden;
}
bool Visible() const
{
return !Hidden();
}
virtual void Hide() { m_Hidden = true; }
virtual void Show() { m_Hidden = false; }
int Left() const override
{
if (m_Parent)
return m_Parent->Left() + X;
else
return X;
}
int Right() const override
{
if (m_Parent)
return std::min(m_Parent->Right(), Left() + Width);
else
return Left() + Width;
}
int Top() const override
{
if (m_Parent)
return m_Parent->Top() + Y;
else
return Y;
}
int Bottom() const override
{
if (m_Parent)
return std::min(m_Parent->Bottom(), Top() + Height);
else
return Top() + Height;
}
glm::vec2 Scale()
{
if (m_Parent)
return m_Parent->Scale();
else
return glm::vec2(Width, Height) / glm::vec2(BaseWidth, BaseHeight);
}
Rectangle AbsoluteRectangle()
{
int left = Left();
if (m_Parent)
left = std::max(left, m_Parent->Left());
int top = Top();
if (m_Parent)
top = std::max(top, m_Parent->Top());
int width = Right() - left;
int height = Bottom() - top;
return Rectangle(left, top, width, height);
}
void UpdateLayered(double dt)
{
// Update ourselves
this->Update(dt);
// Update children
for (auto& pairLayer : m_Children) {
auto children = pairLayer.second;
for (auto& pairChild : children) {
auto child = pairChild.second;
child->Update(dt);
}
}
}
virtual void Update(double dt) { }
void DrawLayered(RenderQueueCollection& rq)
{
if (this->Hidden())
return;
// Draw ourselves
this->Draw(rq);
// Draw children
for (auto& pairLayer : m_Children) {
auto children = pairLayer.second;
for (auto& pairChild : children) {
auto child = pairChild.second;
if (child->Hidden())
continue;
child->Draw(rq);
}
}
}
virtual void Draw(RenderQueueCollection& rq) { }
protected:
dd::EventBroker* EventBroker;
std::string m_Name = "UIParent";
int m_Layer = 0;
bool m_Hidden = false;
Frame* m_Parent = nullptr;
typedef std::multimap<std::string, Frame*> Children_t; // name -> frame
std::map<int, Children_t> m_Children; // layer -> Children_t
virtual bool OnKeyDown(const Events::KeyDown& event) { return false; }
virtual bool OnKeyUp(const Events::KeyUp& event) { return false; }
//virtual bool OnMouseDown(const Events::KeyDown &event) { }
//virtual bool OnMouseUp(const Events::KeyDown &event) { }
virtual bool OnCommand(const Events::InputCommand& event) { return false; }
private:
EventRelay<Frame, Events::KeyDown> m_EKeyDown;
EventRelay<Frame, Events::KeyUp> m_EKeyUp;
EventRelay<Frame, Events::InputCommand> m_EInputCommand;
void Initialize()
{
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Frame::OnKeyDown);
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Frame::OnKeyUp);
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Frame::OnCommand);
}
};
}
}
#endif // GUI_Frame_h__
+98
View File
@@ -0,0 +1,98 @@
#ifndef GUI_GameFrame_h__
#define GUI_GameFrame_h__
#include "GUI/Frame.h"
#include "GUI/MainMenuFrame.h"
#include "GUI/WorldFrame.h"
#include "GUI/Viewport.h"
#include "GUI/TextureFrame.h"
#include "GUI/PlayerHUD.h"
#include "GameWorld.h"
#include "Events/GameStart.h"
#include "Events/GameOver.h"
#include "Events/Dead.h"
namespace dd
{
namespace GUI
{
class GameFrame : public Frame
{
public:
GameFrame(Frame* parent, std::string name)
: Frame(parent, name)
, m_GameOver(false)
{
EVENT_SUBSCRIBE_MEMBER(m_EGameStart, &GUI::GameFrame::OnGameStart);
EVENT_SUBSCRIBE_MEMBER(m_EGameOver, &GUI::GameFrame::OnGameOver);
m_World = std::make_shared<GameWorld>(EventBroker, ResourceManager);
m_WorldFrame = new WorldFrame(this, "GameWorldFrame", m_World);
{
vp1 = new Viewport(m_WorldFrame, "Viewport1", m_World);
vp1->X = 0;
vp1->Width = this->Width / 2.f;
new PlayerHUD(vp1, "PlayerHUD", m_World, 1);
vp2 = new Viewport(m_WorldFrame, "Viewport2", m_World);
vp2->X = vp1->Right();
vp2->Width = this->Width / 2.f;
new PlayerHUD(vp2, "PlayerHUD", m_World, 2);
m_FreeCamViewport = new Viewport(m_WorldFrame, "ViewportFreeCam", m_World);
m_FreeCamViewport->Hide();
}
m_WorldFrame->Hide();
m_World->Initialize();
m_MainMenuFrame = new MainMenuFrame(this, "MainMenu");
}
private:
EventRelay <Frame, Events::GameStart> m_EGameStart;
bool OnGameStart(const Events::GameStart& event)
{
m_WorldFrame->Show();
return true;
}
EventRelay <Frame, Events::GameOver> m_EGameOver;
bool OnGameOver(const Events::GameOver& event)
{
m_GameOver = true;
return true;
}
std::shared_ptr<GameWorld> m_World;
MainMenuFrame* m_MainMenuFrame;
WorldFrame* m_WorldFrame;
Viewport* vp1;
Viewport* vp2;
Viewport* m_FreeCamViewport;
bool m_GameOver;
bool OnKeyUp(const Events::KeyUp& event) override
{
if (event.KeyCode == GLFW_KEY_1) {
if (m_FreeCamViewport->Hidden())
m_FreeCamViewport->Show();
else
m_FreeCamViewport->Hide();
}
return true;
}
};
}
}
#endif // GUI_GameFrame_h__
+88
View File
@@ -0,0 +1,88 @@
#ifndef GUI_TextureFrame_h__
#define GUI_TextureFrame_h__
#include "GUI/Frame.h"
#include "Core/Texture.h"
namespace dd
{
namespace GUI
{
class TextureFrame : public Frame
{
public:
TextureFrame(Frame* parent, std::string name)
: Frame(parent, name) { }
void Draw(RenderQueueCollection& rq) override
{
if (m_Texture == nullptr)
return;
// Main texture
{
FrameJob job;
job.Scissor = m_Parent->AbsoluteRectangle();
job.Viewport = Rectangle(Left(), Top(), Width, Height);
job.TextureID = m_Texture->ResourceID;
job.DiffuseTexture = *m_Texture;
job.Color = glm::vec4(m_Color.r, m_Color.g, m_Color.b, m_Color.a * m_CurrentFade);
rq.GUI.Add(job);
}
// Texture while fading
if (m_FadeTexture && m_CurrentFade < 1) {
FrameJob job;
job.Scissor = m_Parent->AbsoluteRectangle();
job.Viewport = Rectangle(Left(), Top(), Width, Height);
job.TextureID = m_FadeTexture->ResourceID;
job.DiffuseTexture = *m_FadeTexture;
job.Color = glm::vec4(m_Color.r, m_Color.g, m_Color.b, m_Color.a);
rq.GUI.Add(job);
}
}
dd::Texture* Texture() const { return m_Texture; }
void SetTexture(std::string resourceName)
{
m_Texture = ResourceManager::Load<dd::Texture>(resourceName);
}
void FadeToTexture(std::string resourceName, double duration)
{
m_FadeTexture = m_Texture;
SetTexture(resourceName);
m_FadeDuration = duration;
m_CurrentFade = 0.f;
}
void Update(double dt) override
{
if (m_CurrentFade < 1) {
m_CurrentFade += dt / m_FadeDuration;
if (m_CurrentFade > 1) {
m_FadeTexture = nullptr;
m_CurrentFade = 1;
m_FadeDuration = 0;
}
}
}
glm::vec4 Color() const { return m_Color; }
void SetColor(glm::vec4 val) { m_Color = val; }
protected:
dd::Texture* m_Texture = nullptr;
dd::Texture* m_FadeTexture = nullptr;
glm::vec4 m_Color = glm::vec4(1.f, 1.f, 1.f, 1.f);
float m_FadeDuration = 0.f;
float m_CurrentFade = 1.f;
};
}
}
#endif // GUI_TextureFrame_h__
+81
View File
@@ -0,0 +1,81 @@
#ifndef GUI_Viewport_h__
#define GUI_Viewport_h__
#include <memory>
#include "GUI/Frame.h"
#include "World.h"
#include "Systems/TransformSystem.h"
#include "Components/Transform.h"
#include "Components/Camera.h"
#include "RenderQueue.h"
#include "Camera.h"
namespace GUI
{
class Viewport : public Frame
{
public:
Viewport(Frame* parent, std::string name, std::shared_ptr<World> world)
: Frame(parent, name)
, m_World(world)
{ }
EntityID CameraEntity() const { return m_CameraEntity; }
void SetCameraEntity(EntityID cameraEntity)
{
m_CameraEntity = cameraEntity;
auto transformComponent = m_World->GetComponent<Components::Transform>(cameraEntity);
if (!transformComponent)
return;
auto cameraComponent = m_World->GetComponent<Components::Camera>(cameraEntity);
if (!cameraComponent)
return;
m_Camera = std::make_shared<Camera>(cameraComponent->FOV, cameraComponent->NearClip, cameraComponent->FarClip);
}
void Update(double dt) override
{
if (!m_TransformSystem)
m_TransformSystem = m_World->GetSystem<Systems::TransformSystem>();
auto transformComponent = m_World->GetComponent<Components::Transform>(m_CameraEntity);
if (!transformComponent)
return;
auto cameraComponent = m_World->GetComponent<Components::Camera>(m_CameraEntity);
if (!cameraComponent)
return;
Components::Transform absoluteTransform = m_TransformSystem->AbsoluteTransform(m_CameraEntity);
m_Camera->SetFOV(cameraComponent->FOV);
m_Camera->SetNearClip(cameraComponent->NearClip);
m_Camera->SetFarClip(cameraComponent->FarClip);
m_Camera->SetPosition(absoluteTransform.Position);
m_Camera->SetOrientation(absoluteTransform.Orientation);
}
void Draw(std::shared_ptr<Renderer> renderer) override
{
if (!m_Camera)
return;
renderer->SetCamera(m_Camera);
renderer->SetViewport(AbsoluteRectangle());
renderer->DrawWorld(m_Parent->RenderQueue);
}
private:
std::shared_ptr<World> m_World;
std::shared_ptr<Systems::TransformSystem> m_TransformSystem;
std::shared_ptr<Camera> m_Camera;
EntityID m_CameraEntity;
};
}
#endif // GUI_Viewport_h__
+241
View File
@@ -0,0 +1,241 @@
#ifndef GUI_WorldFrame_h__
#define GUI_WorldFrame_h__
#include "GUI/Frame.h"
#include "GUI/Viewport.h"
#include "RenderQueue.h"
#include "World.h"
#include "Systems/TransformSystem.h"
#include "Events/SetViewportCamera.h"
#include "Components/Transform.h"
#include "Components/Model.h"
#include "Components/Sprite.h"
#include "Components/PointLight.h"
#include "Components/BlendMap.h"
namespace GUI
{
class WorldFrame : public Frame
{
public:
WorldFrame(Frame* parent, std::string name, std::shared_ptr<World> world)
: Frame(parent, name)
, m_World(world)
{
EVENT_SUBSCRIBE_MEMBER(m_ESetViewportCamera, &WorldFrame::OnSetViewportCamera);
}
void Update(double dt) override
{
if (!m_TransformSystem)
m_TransformSystem = m_World->GetSystem<Systems::TransformSystem>();
m_World->Update(dt);
}
void Draw(std::shared_ptr<Renderer> renderer) override
{
RenderQueue.Clear();
renderer->ClearPointLights();
for (auto &pair : *m_World->GetEntities())
{
EntityID entity = pair.first;
auto templateComponent = m_World->GetComponent<Components::Template>(entity);
if (templateComponent)
continue;
auto transform = m_World->GetComponent<Components::Transform>(entity);
if (!transform)
continue;
auto modelComponent = m_World->GetComponent<Components::Model>(entity);
if (modelComponent)
{
Model* modelAsset = nullptr;
if (modelComponent->AverageNormals)
{
modelAsset = ResourceManager->Load<Model>("AveragedModel", modelComponent->ModelFile);
}
else
{
modelAsset = ResourceManager->Load<Model>("Model", modelComponent->ModelFile);
}
if (modelAsset)
{
Components::Transform absoluteTransform = m_TransformSystem->AbsoluteTransform(entity);
glm::mat4 modelMatrix = glm::translate(glm::mat4(), absoluteTransform.Position)
* glm::toMat4(absoluteTransform.Orientation)
* glm::scale(absoluteTransform.Scale);
auto blendmapComponent = m_World->GetComponent<Components::BlendMap>(entity);
if (blendmapComponent)
{
BlendMapTexture RedTexture;
RedTexture.Diffuse = *ResourceManager->Load<Texture>("Texture", blendmapComponent->TextureRed);
RedTexture.Normal = *ResourceManager->Load<Texture>("Texture", blendmapComponent->TextureRedNormal);
RedTexture.Specular = *ResourceManager->Load<Texture>("Texture", blendmapComponent->TextureRedSpecular);
BlendMapTexture GreenTexture;
GreenTexture.Diffuse = *ResourceManager->Load<Texture>("Texture", blendmapComponent->TextureGreen);
GreenTexture.Normal = *ResourceManager->Load<Texture>("Texture", blendmapComponent->TextureGreenNormal);
GreenTexture.Specular = *ResourceManager->Load<Texture>("Texture", blendmapComponent->TextureGreenSpecular);
BlendMapTexture BlueTexture;
BlueTexture.Diffuse = *ResourceManager->Load<Texture>("Texture", blendmapComponent->TextureBlue);
BlueTexture.Normal = *ResourceManager->Load<Texture>("Texture", blendmapComponent->TextureBlueNormal);
BlueTexture.Specular = *ResourceManager->Load<Texture>("Texture", blendmapComponent->TextureBlueSpecular);
float textureRepeat = blendmapComponent->TextureRepeats;
EnqueueBlendMapModel(modelAsset, RedTexture, GreenTexture, BlueTexture, textureRepeat, modelMatrix, modelComponent->Color);
}
else
{
EnqueueModel(modelAsset, modelMatrix, modelComponent->Transparent, modelComponent->Color);
}
}
}
auto spriteComponent = m_World->GetComponent<Components::Sprite>(entity);
if (spriteComponent)
{
auto textureAsset = ResourceManager->Load<Texture>("Texture", spriteComponent->SpriteFile);
if (textureAsset)
{
Components::Transform absoluteTransform = m_TransformSystem->AbsoluteTransform(entity);
glm::quat orientation2D = glm::angleAxis(glm::eulerAngles(absoluteTransform.Orientation).z, glm::vec3(0, 0, -1));
glm::mat4 modelMatrix = glm::translate(absoluteTransform.Position)
* glm::toMat4(orientation2D)
* glm::scale(absoluteTransform.Scale);
EnqueueSprite(textureAsset, modelMatrix, spriteComponent->Color);
}
}
auto pointLightComponent = m_World->GetComponent<Components::PointLight>(entity);
if (pointLightComponent)
{
glm::vec3 position = m_TransformSystem->AbsolutePosition(entity);
renderer->AddPointLightToDraw(
position,
pointLightComponent->Specular,
pointLightComponent->Diffuse,
pointLightComponent->specularExponent,
pointLightComponent->ConstantAttenuation,
pointLightComponent->LinearAttenuation,
pointLightComponent->QuadraticAttenuation,
pointLightComponent->Radius
);
}
}
RenderQueue.Sort();
}
protected:
std::shared_ptr<World> m_World;
private:
struct BlendMapTexture
{
GLuint Diffuse;
GLuint Normal;
GLuint Specular;
};
EventRelay<Frame, Events::SetViewportCamera> m_ESetViewportCamera;
bool OnSetViewportCamera(const Events::SetViewportCamera &event)
{
// Search next layer for viewports and update cameras
auto itpair = m_Children[m_Layer + 1].equal_range(event.ViewportFrame);
for (auto it = itpair.first; it != itpair.second; ++it)
{
auto viewportFrame = dynamic_cast<GUI::Viewport*>(it->second);
if (!viewportFrame)
continue;
viewportFrame->SetCameraEntity(event.CameraEntity);
}
return true;
}
std::shared_ptr<Systems::TransformSystem> m_TransformSystem;
void EnqueueModel(Model* model, glm::mat4 modelMatrix, float transparent, glm::vec4 color)
{
for (auto texGroup : model->TextureGroups)
{
ModelJob job;
job.TextureID = texGroup.Texture->ResourceID;
job.DiffuseTexture = *texGroup.Texture;
job.NormalTexture = (texGroup.NormalMap) ? *texGroup.NormalMap : 0;
job.SpecularTexture = (texGroup.SpecularMap) ? *texGroup.SpecularMap : 0;
job.VAO = model->VAO;
job.StartIndex = texGroup.StartIndex;
job.EndIndex = texGroup.EndIndex;
job.ModelMatrix = modelMatrix;
job.Transparent = transparent;
job.Color = color;
if(job.Transparent)
{
RenderQueue.Forward.Add(job);
}
else
{
RenderQueue.Deferred.Add(job);
}
}
}
void EnqueueBlendMapModel(Model* model, BlendMapTexture textureRed, BlendMapTexture textureGreen, BlendMapTexture textureBlue, float textureRepeat, glm::mat4 modelMatrix, glm::vec4 color)
{
for (auto texGroup : model->TextureGroups)
{
BlendMapModelJob job;
job.TextureID = texGroup.Texture->ResourceID;
job.DiffuseTexture = *texGroup.Texture;
job.NormalTexture = (texGroup.NormalMap) ? *texGroup.NormalMap : 0;
job.SpecularTexture = (texGroup.SpecularMap) ? *texGroup.SpecularMap : 0;
job.BlendMapTextureRed = textureRed.Diffuse;
job.BlendMapTextureRedNormal = textureRed.Normal;
job.BlendMapTextureRedSpecular = textureRed.Specular;
job.BlendMapTextureGreen = textureGreen.Diffuse;
job.BlendMapTextureGreenNormal = textureGreen.Normal;
job.BlendMapTextureGreenSpecular = textureGreen.Specular;
job.BlendMapTextureBlue = textureBlue.Diffuse;
job.BlendMapTextureBlueNormal = textureBlue.Normal;
job.BlendMapTextureBlueSpecular = textureBlue.Specular;
job.TextureRepeat = textureRepeat;
job.VAO = model->VAO;
job.StartIndex = texGroup.StartIndex;
job.EndIndex = texGroup.EndIndex;
job.ModelMatrix = modelMatrix;
job.Color = color;
RenderQueue.Deferred.Add(job);
}
}
void EnqueueSprite(Texture* texture, glm::mat4 modelMatrix, glm::vec4 color)
{
SpriteJob job;
job.TextureID = texture->ResourceID;
job.Texture = *texture;
job.ModelMatrix = modelMatrix;
job.Color = color;
RenderQueue.Forward.Add(job);
}
};
}
#endif // GUI_WorldFrame_h__