Yoga layout working

This commit is contained in:
Antoine Pilote
2021-05-31 23:03:29 -04:00
parent 0db30d7379
commit 39aaa4cd2c
16 changed files with 605 additions and 117 deletions

View File

@@ -12,6 +12,7 @@ void Logger::Log(std::string log)
time_t now = time(0);
strftime(buff, 100, "%Y-%m-%d %H:%M:%S.000", localtime(&now));
std::string msg = "["+ std::string(buff) + "]" + std::string(" - ") + log;
printf((msg + "\n").c_str());
logs.push_back(msg);
}

View File

@@ -5,7 +5,6 @@
enum LOG_TYPE
{
VERBOSE,
DEBUG,
WARNING,
CRITICAL
};

View File

@@ -1,6 +1,6 @@
#include "Renderer2D.h"
#include "GL/glew.h"
#include "../Core/Maths.h"
Ref<Shader> Renderer2D::UIShader;
unsigned int Renderer2D::VAO;
unsigned int Renderer2D::VBO;
@@ -10,7 +10,7 @@ Matrix4 Renderer2D::Projection;
void Renderer2D::Init()
{
UIShader = CreateRef<Shader>("resources/Shaders/ui.shader");
Projection = glm::ortho(0.f, 1920.f, 0.0f, 1080.f, -0.5f, 100.0f);
Projection = glm::ortho(0.f, 1920.f, 1080.f, 0.f, -0.5f, 100.0f);
float quad_Vertices[] = {
// positions // texture Coords
@@ -35,8 +35,10 @@ void Renderer2D::Init()
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
}
void Renderer2D::BeginDraw()
void Renderer2D::BeginDraw(Vector2 size)
{
glDisable(GL_DEPTH_TEST);
Projection = glm::ortho(0.f, size.x, size.y, 0.f, -0.5f, 1000.0f);
UIShader->Bind();
UIShader->SetUniformMat4f("projection", Projection);
}

View File

@@ -12,7 +12,7 @@ public:
static Matrix4 Projection;
static void Init();
static void BeginDraw();
static void BeginDraw(Vector2 size);
static void DrawRect();
static void EndDraw();
};

View File

@@ -143,12 +143,20 @@ void Scene::Update(Timestep ts)
auto [transform, rb] = ccGroup.get<TransformComponent, CharacterControllerComponent>(e);
rb.SyncWithTransform(m_Registry.get<TransformComponent>(e));
}
}
void Scene::EditorUpdate(Timestep ts)
{
m_EditorCamera->Update(ts);
for (auto i : m_Interfaces)
{
//i->Calculate(1280,720);
}
}
@@ -209,6 +217,14 @@ void Scene::DrawShadows()
}
}
void Scene::DrawInterface(Vector2 screensize)
{
for (auto i : m_Interfaces)
{
i->Draw(screensize);
}
}
void Scene::Draw()
{
@@ -339,10 +355,7 @@ void Scene::Draw()
PhysicsManager::Get()->DrawDebug();
}
for (auto i : m_Interfaces)
{
i->Draw();
}
}
void Scene::EditorDraw()
@@ -355,10 +368,7 @@ void Scene::EditorDraw()
// env->ProceduralSkybox->Draw(m_EditorCamera);
//}
for (auto i : m_Interfaces)
{
i->Draw();
}
@@ -510,10 +520,7 @@ void Scene::EditorDraw()
}
}*/
for (auto i : m_Interfaces)
{
i->Draw();
}
}
std::vector<Entity> Scene::GetAllEntities() {
@@ -619,6 +626,12 @@ bool Scene::SaveAs(const std::string& path)
return true;
}
void Scene::ReloadInterfaces()
{
for (auto& i : m_Interfaces)
i->Reload();
}
void Scene::AddInterface(Ref<UI::UserInterface> interface)
{
this->m_Interfaces.push_back(interface);

View File

@@ -10,7 +10,7 @@
#include "EditorCamera.h"
#include "../Resource/Serializable.h"
#include "src/UI/UserInterface.h"
#include "../Core/Maths.h"
class Entity;
class Scene : public ISerializable
{
@@ -43,6 +43,7 @@ public:
// TODO: Maybe move this to Renderer::DrawScene() ?
void DrawShadows();
void DrawInterface(Vector2 screensize);
void Draw();
void EditorDraw();
@@ -64,6 +65,7 @@ public:
bool Save();
bool SaveAs(const std::string& path);
void ReloadInterfaces();
void AddInterface(Ref<UI::UserInterface> interface);
json Serialize() override;

View File

@@ -1,6 +1,223 @@
#pragma once
#include <src/Vendors/pugixml/pugixml.hpp>
#include <iostream>
#include <src/UI/Canvas.h>
#include <src/UI/Rect.h>
#include <regex>
#include<iostream>
#include <src/Core/Logger.h>
class InterfaceParser
{
static Ref<Canvas> Root;
private:
public:
static Ref<Canvas> Parse(const std::string path)
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(path.c_str());
std::string name = doc.first_child().name();
if (name != "Canvas")
{
Logger::Log("InterfaceParser error: First child should be a canvas - " + path);
return nullptr;
}
Root = CreateCanvas(doc.first_child());
Iterate(doc.first_child(), Root);
return Root;
}
static void Iterate(const pugi::xml_node& xml_node, Ref<Node> node)
{
for (auto& e : xml_node.children())
{
std::string type = e.name();
if (type == "Canvas")
{
Ref<Canvas> canvas = CreateCanvas(e);
node->Childrens.push_back(canvas);
Iterate(e, canvas);
}
else if (type == "Rect")
{
Ref<Node> newNode = CreateNode(e);
node->Childrens.push_back(newNode);
Iterate(e, newNode);
}
}
}
static Ref<Node> CreateNode(const pugi::xml_node& xml_node)
{
Ref<Node> node = CreateRef<Node>();
for (auto& a : xml_node.attributes())
{
std::string name = a.name();
if (name == "height")
node->Height = GetUnit(a.value());
if (name == "width")
node->Width = GetUnit(a.value());
if (name == "margin")
node->Margin = GetVec4Unit(a.value());
if (name == "padding")
node->Padding = GetVec4Unit(a.value());
if (name == "border")
node->Border = GetVec4Unit(a.value());
if (name == "position")
node->Position = GetVec4Unit(a.value());
if (name == "color")
node->BackgroundColor = GetColor(a.value());
}
return node;
}
static Layout::LayoutUnit GetUnit(const std::string& value)
{
std::regex only_number("[0-9]+");
std::regex not_number("[^0-9]+");
// is percentage
std::smatch match_value;
if (std::regex_search(value.begin(), value.end(), match_value, only_number))
{
std::smatch match_type;
if (std::regex_search(value.begin(), value.end(), match_type, not_number))
{
float value = std::stof(match_value[0]);
if (match_type[0] == "%")
{
return Layout::LayoutUnit{
value,
Layout::Unit::PERCENT
};
}
else if (match_type[0] == "px")
{
return Layout::LayoutUnit{
value,
Layout::Unit::PIXEL
};
}
}
}
}
static std::vector<std::string> split(std::string const& str, const char delim)
{
std::vector<std::string> result;
size_t start;
size_t end = 0;
while ((start = str.find_first_not_of(delim, end)) != std::string::npos)
{
end = str.find(delim, start);
result.push_back(str.substr(start, end - start));
}
return result;
}
static Layout::LayoutVec4 GetVec4Unit(const std::string& value)
{
std::regex regex("[0-9]+[^ ]+");
std::smatch match_value;
Layout::LayoutVec4 result;
std::vector<std::string> splits = split(value, ' ');
int idx = 0;
for (auto& s : splits)
{
if (std::regex_search(value.begin(), value.end(), match_value, regex))
{
if (idx == 0)
{
result.Left = GetUnit(s);
}
else if (idx == 1)
{
result.Right = GetUnit(s);
}
else if (idx == 2)
{
result.Top = GetUnit(s);
}
else
{
result.Bottom = GetUnit(s);
}
idx++;
}
}
return result;
}
static Color GetColor(const std::string& value)
{
std::regex regex("[0-9]+[^ ]+");
std::smatch match_value;
Color result;
std::vector<std::string> splits = split(value, ' ');
int idx = 0;
for (auto& s : splits)
{
if (std::regex_search(value.begin(), value.end(), match_value, regex))
{
if (idx == 0)
{
result.r = std::stof(s);
}
else if (idx == 1)
{
result.g = std::stof(s);
}
else if (idx == 2)
{
result.b = std::stof(s);
}
else
{
result.a = std::stof(s);
}
idx++;
}
}
return result;
}
static Ref<Canvas> CreateCanvas(const pugi::xml_node& xml_node)
{
Ref<Canvas> node = CreateRef<Canvas>();
for (auto& a : xml_node.attributes())
{
std::string name = a.name();
if (name == "height")
node->Height = GetUnit(a.value());
if (name == "width")
node->Width = GetUnit(a.value());
if (name == "margin")
node->Margin = GetVec4Unit(a.value());
if (name == "padding")
node->Padding = GetVec4Unit(a.value());
if (name == "border")
node->Border = GetVec4Unit(a.value());
if (name == "position")
node->Position = GetVec4Unit(a.value());
if (name == "color")
node->BackgroundColor = GetColor(a.value());
}
return node;
}
};

View File

@@ -12,9 +12,9 @@ Node::Node()
FlexDirection = Layout::FlexDirection::ROW;
FlexWrap = Layout::FlexWrap::WRAP;
FlexGrow = 0.f;
FlexShrink = 0.f;
FlexBasis = 0.f;
AspectRatio = 0.f;
FlexShrink = 1.f;
FlexBasis = 10.f;
AspectRatio = 1.f;
AlignItems = Layout::AlignItems::FLEX_START;
SelfAlign = Layout::AlignItems::FLEX_START;
}

View File

@@ -1,11 +1,14 @@
#pragma once
#include <vector>
#include "../Core/Core.h"
#include "yoga/Yoga.h"
#include "../Rendering/Renderer2D.h"
#include "../Core/Logger.h"
namespace Layout
{
enum class LayoutDirection
{
LTR, RTL
LTR = 2, RTL = 3
};
enum class FlexWrap
@@ -35,7 +38,7 @@ namespace Layout
enum class PositionType
{
RELATIVE, ABSOLUTE
STATIC, RELATIVE, ABSOLUTE
};
enum Unit
@@ -63,20 +66,25 @@ namespace Layout
class Node
{
public:
std::vector<Ref<Node>> Childrens;
Ref<Node*> Parent;
YGNodeRef YogaNode;
std::vector<Ref<Node>> Childrens = std::vector<Ref<Node>>();
Layout::PositionType PositionType;
Layout::LayoutVec4 Position;
Layout::LayoutUnit With, MaxWidth, MinWidth;
Layout::LayoutUnit Width, MaxWidth, MinWidth;
Layout::LayoutUnit Height, MaxHeight, MinHeight;
Layout::LayoutVec4 Margin;
Layout::LayoutVec4 Padding;
Layout::LayoutVec4 Border;
Color BackgroundColor;
Layout::LayoutDirection Direction;
Layout::FlexDirection FlexDirection;
Layout::FlexDirection FlexDirection = Layout::FlexDirection::ROW;
Layout::FlexWrap FlexWrap;
float FlexGrow;
@@ -88,5 +96,220 @@ public:
Layout::AlignItems SelfAlign;
Node();
};
void SetMargin()
{
switch (Margin.Left.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetMargin(YogaNode, YGEdgeLeft, Margin.Left.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetMarginPercent(YogaNode, YGEdgeLeft, Margin.Left.Value);
break;
case Layout::Unit::AUTO:
YGNodeStyleSetMarginAuto(YogaNode, YGEdgeLeft);
break;
}
switch (Margin.Right.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetMargin(YogaNode, YGEdgeRight, Margin.Right.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetMarginPercent(YogaNode, YGEdgeRight, Margin.Right.Value);
break;
case Layout::Unit::AUTO:
YGNodeStyleSetMarginAuto(YogaNode, YGEdgeRight);
break;
}
switch (Margin.Top.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetMargin(YogaNode, YGEdgeTop, Margin.Top.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetMarginPercent(YogaNode, YGEdgeTop, Margin.Top.Value);
break;
case Layout::Unit::AUTO:
YGNodeStyleSetMarginAuto(YogaNode, YGEdgeTop);
break;
}
switch (Margin.Bottom.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetMargin(YogaNode, YGEdgeBottom, Margin.Bottom.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetMarginPercent(YogaNode, YGEdgeBottom, Margin.Bottom.Value);
break;
case Layout::Unit::AUTO:
YGNodeStyleSetMarginAuto(YogaNode, YGEdgeTop);
break;
}
}
void SetPadding()
{
switch (Padding.Left.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetPadding(YogaNode, YGEdgeLeft, Padding.Left.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetPaddingPercent(YogaNode, YGEdgeLeft, Padding.Left.Value);
break;
}
switch (Padding.Right.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetPadding(YogaNode, YGEdgeRight, Padding.Right.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetPaddingPercent(YogaNode, YGEdgeRight, Padding.Right.Value);
break;
}
switch (Padding.Top.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetPadding(YogaNode, YGEdgeTop, Padding.Top.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetPaddingPercent(YogaNode, YGEdgeTop, Padding.Top.Value);
break;
}
switch (Padding.Bottom.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetPadding(YogaNode, YGEdgeBottom, Padding.Bottom.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetPaddingPercent(YogaNode, YGEdgeBottom, Padding.Bottom.Value);
break;
}
}
void SetBorder()
{
switch (Border.Left.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetBorder(YogaNode, YGEdgeLeft, Border.Left.Value);
break;
}
switch (Border.Right.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetBorder(YogaNode, YGEdgeRight, Border.Right.Value);
break;
}
switch (Border.Top.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetBorder(YogaNode, YGEdgeTop, Border.Top.Value);
break;
}
switch (Border.Bottom.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetBorder(YogaNode, YGEdgeBottom, Border.Bottom.Value);
break;
}
}
void SetYogaLayout()
{
switch (Width.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetWidth(YogaNode, Width.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetWidthPercent(YogaNode, Width.Value);
break;
case Layout::Unit::AUTO:
YGNodeStyleSetWidthAuto(YogaNode);
break;
}
switch (Height.Unit)
{
case Layout::Unit::PIXEL:
YGNodeStyleSetHeight(YogaNode, Height.Value);
break;
case Layout::Unit::PERCENT:
YGNodeStyleSetHeightPercent(YogaNode, Height.Value);
break;
case Layout::Unit::AUTO:
YGNodeStyleSetHeightAuto(YogaNode);
break;
}
SetMargin();
SetPadding();
SetBorder();
YGNodeStyleSetFlexWrap(YogaNode, YGWrapWrap);
YGNodeStyleSetFlexDirection(YogaNode, YGFlexDirectionRow);
YGNodeStyleSetJustifyContent(YogaNode, YGJustifyFlexStart);
}
void Draw(float z, Vector2 offset)
{
Color color = this->BackgroundColor;
Renderer2D::UIShader->SetUniform4f("background_color",
color.r / 255.f,
color.g / 255.f,
color.b / 255.f,
color.a / 255.f);
// Get transform
Matrix4 transform = Matrix4(1.0f);
float width = YGNodeLayoutGetWidth(YogaNode);
float height = YGNodeLayoutGetHeight(YogaNode);
float padding = YGNodeLayoutGetPadding(YogaNode, YGEdgeLeft);
float left = YGNodeLayoutGetLeft(YogaNode); //+ offset.x;
float top = YGNodeLayoutGetTop(YogaNode);// +offset.y;
float parentLeft = 0.0f;
float parentTop = 0.0f;
auto parent = YGNodeGetParent(YogaNode);
if (parent)
{
parentLeft = YGNodeLayoutGetLeft(YGNodeGetParent(YogaNode));
parentTop = YGNodeLayoutGetTop(YGNodeGetParent(YogaNode));
float parentPaddingTop = YGNodeLayoutGetPadding(parent, YGEdgeTop);
float parentPaddingLeft = YGNodeLayoutGetPadding(parent, YGEdgeTop);
// Overflow hidden.
float parentwidth = YGNodeLayoutGetWidth(parent);
if (parentwidth - YGNodeLayoutGetMargin(YogaNode, YGEdgeLeft) < width )
width = parentwidth - parentPaddingLeft;
float parentHeight = YGNodeLayoutGetHeight(parent);
if (parentHeight < height)
height = parentHeight - YGNodeLayoutGetMargin(YogaNode, YGEdgeTop) - parentPaddingTop;
}
transform = glm::translate(transform, Vector3(left + parentLeft, top + parentTop, 0.f));
Vector3 scale = Vector3(width, height, 0);
transform = glm::scale(transform, scale);
//Logger::Log("Left: " + std::to_string(left) + " Top:" + std::to_string(top));
Renderer2D::UIShader->SetUniformMat4f("model", transform);
Renderer2D::DrawRect();
}
};

View File

@@ -1,55 +1,45 @@
#include "UserInterface.h"
#include "yoga/Yoga.h"
#include <src/Vendors/pugixml/pugixml.hpp>
#include "Stylesheet.h"
#include "yoga/YGConfig.h"
#include "InterfaceParser.h"
namespace UI
{
struct simple_walker : pugi::xml_tree_walker
{
virtual bool for_each(pugi::xml_node& node)
{
for (int i = 0; i < depth(); ++i) std::cout << " "; // indentation
std::cout << node.type() << ": name='" << node.name() << "', value='" << node.value() << "'\n";
return true; // continue traversal
}
};
UserInterface::UserInterface(const std::string& name)
{
m_Name = name;
pugi::xml_document doc;
// Parse xml document
pugi::xml_parse_result result = doc.load_file("resources/Interface/Testing.interface");
std::cout << "Load result: " << result.description() << ", mesh name: " << doc.child("Canvas").attribute("size").value() << std::endl;
auto childrends = doc.child("Canvas").children();
simple_walker walker;
doc.traverse(walker);
Logger::Log("Hello");
Root = InterfaceParser::Parse("resources/Interface/Testing.interface");
// Create engine structure from document
if (!Root)
{
Logger::Log("Failed to generate interface structure");
}
yoga_config = YGConfigNew();
yoga_config->useWebDefaults = true;
CreateYogaLayout();
}
// Convert engine structure to yoga
UserInterface::~UserInterface()
{
YGConfigFree(yoga_config);
if (yoga_root)
YGNodeFreeRecursive(yoga_root);
}
void UserInterface::Reload()
{
Root = InterfaceParser::Parse("resources/Interface/Testing.interface");
if (!Root)
{
Logger::Log("Failed to generate interface structure");
}
// Calculate layout
// Load css styling
//Ref<StyleSheet> stylesheet = StyleSheet::New("resources/Interface/Testing.css");
// Iterate through css file
// Create style sheet data structure
// When rendering load styles to shader
// Render
yoga_config = YGConfigNew();
yoga_config->useWebDefaults = true;
CreateYogaLayout();
}
Ref<UserInterface> UserInterface::New(const std::string& name)
@@ -57,17 +47,68 @@ namespace UI
return CreateRef<UserInterface>(name);
}
void UserInterface::Calculate()
void UserInterface::Calculate(int available_width, int available_height)
{
YGNodeRef root = Root->YogaNode;
YGNodeCalculateLayout(root, available_width, available_height, YGDirectionLTR);
}
void UserInterface::Draw()
void UserInterface::CreateYogaLayout()
{
Renderer2D::BeginDraw();
for (auto r : m_Rects)
yoga_root = YGNodeNewWithConfig(yoga_config);
Root->YogaNode = yoga_root;
Root->SetYogaLayout();
CreateYogaLayoutRecursive(Root, yoga_root);
}
void UserInterface::CreateYogaLayoutRecursive(Ref<Node> node, YGNodeRef yoga_node)
{
if(node->Childrens.size() > 0)
YGNodeCalculateLayout(yoga_node, YGNodeLayoutGetWidth(yoga_node), YGNodeLayoutGetHeight(yoga_node), YGDirectionLTR);
int index = 0;
for (auto& n : node->Childrens)
{
r->Draw();
YGNodeRef newYogaNode = YGNodeNew();
n->YogaNode = newYogaNode;
n->SetYogaLayout();
YGNodeInsertChild(yoga_node, newYogaNode, index);
CreateYogaLayoutRecursive(n, newYogaNode);
index++;
}
Logger::Log(std::to_string(YGNodeGetChildCount(yoga_node)));
}
void UserInterface::Draw(Vector2 size)
{
Calculate(size.x, size.y);
Renderer2D::BeginDraw(size);
float leftOffset = YGNodeLayoutGetLeft(Root->YogaNode);
float topOffset = YGNodeLayoutGetTop(Root->YogaNode);
DrawRecursive(Root, 0, Vector2(leftOffset, topOffset));
}
void UserInterface::DrawRecursive(Ref<Node> node, float z, Vector2 offset)
{
if (!node)
return;
node->Draw(z, offset);
if (node->Childrens.size() <= 0)
return;
offset.x += YGNodeLayoutGetLeft(Root->YogaNode);
if(!YGNodeLayoutGetHadOverflow(Root->YogaNode))
offset.y += YGNodeLayoutGetTop(Root->YogaNode);
for (auto& c : node->Childrens)
{
DrawRecursive(c, z + 1, offset);
}
}

View File

@@ -2,57 +2,36 @@
#include <src/Core/Timestep.h>
#include <src/Rendering/Framebuffer.h>
#include <src/UI/Rect.h>
#include "yoga/Yoga.h"
#include "Node.h"
#include <src/UI/Canvas.h>
#include "../Core/Maths.h"
namespace UI
{
class UserInterface
{
private:
std::vector<Ref<Rect>> m_Rects;
Ref<FrameBuffer> m_Framebuffer; // Texture of the interface.
std::string m_Name;
Ref<Canvas> Root;
YGConfigRef yoga_config;
YGNodeRef yoga_root;
public:
const int Width = 1920;
const int Height = 1080;
UserInterface(const std::string& name);
~UserInterface();
void Reload();
static Ref<UserInterface> New(const std::string& name);
void Calculate();
void Draw();
void Calculate(int available_width, int available_height);
void CreateYogaLayout();
void CreateYogaLayoutRecursive(Ref<Node> node, YGNodeRef yoga_node);
void Draw(Vector2 size);
void DrawRecursive(Ref<Node> node, float z, Vector2 offset);
void Update(Timestep ts);
std::vector<Ref<Rect>> GetRects()
{
return m_Rects;
}
void AddRect(Ref<Rect> rect)
{
m_Rects.push_back(rect);
}
Ref<Rect> GetRectByID(const std::string& id)
{
for (auto r : m_Rects)
{
if (r->GetID() == id)
return r;
}
return nullptr;
}
std::vector<Ref<Rect>> GetRectsByGroup(const std::string& group)
{
std::vector<Ref<Rect>> rects = std::vector<Ref<Rect>>();
for (auto r : m_Rects)
{
if(r->HasGroup(group))
rects.push_back(r);
}
return rects;
}
};
}

View File

@@ -360,7 +360,6 @@ WIN_EXPORT float YGRoundValueToPixelGrid(
YG_EXTERN_C_END
#ifdef __cplusplus
#include <functional>
#include <vector>

View File

@@ -244,6 +244,8 @@ void Window::Draw()
m_Scene->Draw();
else
m_Scene->EditorDraw();
m_Scene->DrawInterface(m_Framebuffer->GetSize());
}
m_Framebuffer->Unbind();
}