Files
panopainter/engine/app.cpp

355 lines
12 KiB
C++

#include "pch.h"
#include "app.hpp"
App App::I; // singleton
void App::create()
{
width = 800;
height = 800;
}
void App::update_layout()
{
YGNodeCalculateLayout(y_root, YGUndefined, YGUndefined, YGDirectionLTR);
std::stack<YGNodeRef> y_stack;
y_stack.push(y_root);
auto y_current = y_root;
while (y_current)
{
y_stack.pop();
auto ctx = reinterpret_cast<glm::vec2*>(YGNodeGetContext(y_current));
if (!ctx)
{
float x = YGNodeLayoutGetLeft(y_current);
float y = YGNodeLayoutGetTop(y_current);
ctx = new glm::vec2(x, y);
YGNodeSetContext(y_current, ctx);
}
int n = YGNodeGetChildCount(y_current);
for (int i = 0; i < n; i++)
{
auto y_child = YGNodeGetChild(y_current, i);
auto ctx_child = reinterpret_cast<glm::vec2*>(YGNodeGetContext(y_child));
if (!ctx_child) ctx_child = new glm::vec2();
ctx_child->x = ctx->x + YGNodeLayoutGetLeft(y_child);
ctx_child->y = ctx->y + YGNodeLayoutGetTop(y_child);
YGNodeSetContext(y_child, ctx_child);
y_stack.emplace(y_child);
}
y_current = y_stack.size() ? y_stack.top() : nullptr;
}
}
void App::init()
{
static const char* shader_v =
"#version 150\n"
"uniform mat4 mvp;"
"in vec4 pos;"
"in vec2 uvs;"
"out vec3 uv;"
"void main(){"
" uv = vec3(uvs, pos.w);"
" gl_Position = mvp * vec4(pos.xyz, 1.f);"
"}";
static const char* shader_f =
"#version 150\n"
"uniform sampler2D tex;"
"in vec3 uv;"
"out vec4 frag;"
"void main(){"
//" frag = texture(tex, uv.xy/uv.z);"
" frag = texture(tex, uv.xy);"
"}";
static const char* shader_uv_f =
"#version 150\n"
"uniform sampler2D tex;"
"in vec3 uv;"
"out vec4 frag;"
"void main(){"
" frag = vec4(uv.xy,0,1);"
"}";
static const char* shader_color_v =
"#version 150\n"
"uniform mat4 mvp;"
"in vec4 pos;"
"void main(){"
" gl_Position = mvp * pos;"
"}";
static const char* shader_color_f =
"#version 150\n"
"uniform vec4 col;"
"out vec4 frag;"
"void main(){"
" frag = col;"
"}";
auto w = att::Width(10.f);
printf("type: %d\n", att::value("Height"));
y_root = YGNodeNew();
YGNodeStyleSetWidth(y_root, width);
YGNodeStyleSetHeight(y_root, height);
YGNodeStyleSetFlexDirection(y_root, YGFlexDirectionRow);
YGNodeStyleSetFlexWrap(y_root, YGWrapWrap);
//YGNodeStyleSetJustifyContent(y_root, YGJustifyFlexStart);
using NodePair = std::pair<YGNodeRef, tinyxml2::XMLElement*>;
std::stack<NodePair> stack;
tinyxml2::XMLDocument xml;
auto ret = xml.LoadFile("data\\layout.xml");
auto x_root = xml.RootElement();
NodePair current = { y_root, x_root };
stack.push(current);
while (current.first && current.second)
{
stack.pop();
auto y_root = current.first;
auto child = current.second->FirstChildElement();
YGNodeStyleSetPosition(y_root, YGEdgeAll, 0);
YGNodeStyleSetPadding(y_root, YGEdgeAll, 0);
YGNodeStyleSetMargin(y_root, YGEdgeAll, 0);
YGNodeStyleSetPositionType(y_root, YGPositionTypeRelative);
YGNodeStyleSetPosition(y_root, YGEdgeAll, 0);
YGNodeStyleSetPadding(y_root, YGEdgeAll, 0);
YGNodeStyleSetMargin(y_root, YGEdgeAll, 0);
while (child)
{
printf("Element %s: ", child->Name());
auto y_node = YGNodeNew();
stack.emplace(y_node, child);
auto attr = child->FirstAttribute();
if (strcmp("plane", child->Name()) == 0)
{
auto shape = std::make_unique<Plane>();
shape->create<5>(100.f, 100.f);
shape->y_node = y_node;
shapes_list.push_back(std::move(shape));
YGNodeSetContext(y_node, shape.get());
}
while (attr)
{
const auto ka = att::value(attr->Name());
printf("%s=%s ", attr->Name(), attr->Value());
switch (ka)
{
case att::kAttribute::Width:
if (strchr(attr->Value(), '%'))
YGNodeStyleSetWidthPercent(y_node, attr->FloatValue());
else
YGNodeStyleSetWidth(y_node, attr->FloatValue());
break;
case att::kAttribute::MinWidth:
if (strchr(attr->Value(), '%'))
YGNodeStyleSetMinWidthPercent(y_node, attr->FloatValue());
else
YGNodeStyleSetMinWidth(y_node, attr->FloatValue());
break;
case att::kAttribute::MaxWidth:
YGNodeStyleSetMaxWidth(y_node, attr->FloatValue());
break;
case att::kAttribute::Height:
if (strchr(attr->Value(), '%'))
YGNodeStyleSetHeightPercent(y_node, attr->FloatValue());
else
YGNodeStyleSetHeight(y_node, attr->FloatValue());
break;
case att::kAttribute::MinHeight:
YGNodeStyleSetMinHeight(y_node, attr->FloatValue());
break;
case att::kAttribute::MaxHeight:
YGNodeStyleSetMaxHeight(y_node, attr->FloatValue());
break;
case att::kAttribute::Grow:
YGNodeStyleSetFlexGrow(y_node, attr->FloatValue());
break;
case att::kAttribute::Shrink:
YGNodeStyleSetFlexShrink(y_node, attr->FloatValue());
break;
case att::kAttribute::FlexDir:
{
YGFlexDirection dir = YGFlexDirectionRow;
if (strcmp("col", attr->Value()) == 0)
dir = YGFlexDirectionColumn;
else if (strcmp("col-reverse", attr->Value()) == 0)
dir = YGFlexDirectionColumnReverse;
else if (strcmp("row", attr->Value()) == 0)
dir = YGFlexDirectionRow;
else if (strcmp("row-reverse", attr->Value()) == 0)
dir = YGFlexDirectionRowReverse;
YGNodeStyleSetFlexDirection(y_node, dir);
break;
}
case att::kAttribute::FlexWrap:
YGNodeStyleSetFlexWrap(y_node, attr->IntValue() ? YGWrapWrap : YGWrapNoWrap);
break;
}
attr = attr->Next();
}
int n = YGNodeGetChildCount(y_root);
YGNodeInsertChild(y_root, y_node, n);
child = child->NextSiblingElement();
printf("\n");
}
current = stack.size() ? stack.top() : NodePair{nullptr, nullptr};
}
update_layout();
for (auto& s : shapes_list)
{
float w = YGNodeLayoutGetWidth(s->y_node);
float h = YGNodeLayoutGetHeight(s->y_node);
float x = YGNodeLayoutGetLeft(s->y_node);
float y = YGNodeLayoutGetTop(s->y_node);
printf("layout w=%f h=%f x=%f y=%f\n", w, h, x, y);
}
sampler.create();
shader.create(shader_v, shader_f);
shader_color.create(shader_color_v, shader_color_f);
shader_uv.create(shader_v, shader_uv_f);
plane.create<5>(1, 1);
circle.create<10>(25);
circle2.create<10>(25, Circle::kUVMapping::Tube);
circle3.create<10>(25, 12, Circle::kUVMapping::Tube);
circle4.create<10>(25, 12, Circle::kUVMapping::Planar);
rounded.create<3>(50, 50, 10);
slice.create(50, 50, 10, .3f);
if (!tex.load("data/uvs.jpg"))
printf("error loading image\n");
glEnable(GL_TEXTURE);
glDisable(GL_DEPTH_TEST);
glPointSize(5);
glLineWidth(4);
//int n;
//glGetIntegerv(GL_NUM_EXTENSIONS, &n);
//for (int i = 0; i < n; i++)
//{
// const unsigned char* s = glGetStringi(GL_EXTENSIONS, i);
// printf("GL ext %03d: %s\n", i, s);
//}
printf("GL version: %s\n", glGetString(GL_VERSION));
printf("GL vendor: %s\n", glGetString(GL_VENDOR));
printf("GL renderer: %s\n", glGetString(GL_RENDERER));
GLfloat width_range[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, width_range);
printf("GL line range: %f - %f\n", width_range[0], width_range[1]);
}
void App::update(float dt)
{
glm::mat4 proj = glm::ortho(0.f, width, height, 0.f, -1.f, 1.f);
Shape* shapes[] = { &circle, &circle2, &circle3, &circle4, &plane, &rounded, &slice };
//glClearColor(red, 0, 0, 1);
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
glClear(GL_COLOR_BUFFER_BIT);
/*
auto s = glm::scale(glm::vec3(1.5));
int h = 100;
for (int i = 0; i < sizeof(shapes)/sizeof(Shape*); i++)
{
shader.use();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glActiveTexture(GL_TEXTURE0);
tex.bind();
sampler.bind(0);
shader.u_int("tex", 0);
shader.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 1, 75 + h * i, 0.f}) * s);
shapes[i]->draw_fill();
tex.unbind();
shader_color.use();
shader_color.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 2, 75 + h * i, 0.f}) * s);
shader_color.u_vec4("col", {1, 1, 1, 1});
shapes[i]->draw_stroke();
shader_color.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 0, 75 + h * i, 0.f}) * s);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
shapes[i]->draw_fill();
shader_uv.use();
shader_uv.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 3, 75 + h * i, 0.f}) * s);
shader_uv.u_int("tex", 0);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
shapes[i]->draw_fill();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
shader_uv.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 4, 75 + h * i, 0.f}) * s);
shapes[i]->draw_fill();
tex.unbind();
}
*/
glActiveTexture(GL_TEXTURE0);
tex.bind();
sampler.bind(0);
shader.use();
shader.u_int("tex", 0);
shader_color.use();
shader_color.u_vec4("col", { 0, 0, 1, 1 });
for (auto& s : shapes_list)
{
float w = YGNodeLayoutGetWidth(s->y_node);
float h = YGNodeLayoutGetHeight(s->y_node);
float x = YGNodeLayoutGetLeft(s->y_node);
float y = YGNodeLayoutGetTop(s->y_node);
auto loc = reinterpret_cast<glm::vec2*>(YGNodeGetContext(s->y_node));
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f));
glm::mat4 scale = glm::scale(glm::vec3(w, h, 1.f));
glm::mat4 pos = glm::translate(glm::vec3(*loc, 0));
auto mvp = proj * pos * scale * pivot;
shader_uv.use();
shader.u_mat4("mvp", mvp);
plane.draw_fill();
shader_color.use();
shader_color.u_mat4("mvp", mvp);
plane.draw_stroke();
}
tex.unbind();
sampler.unbind();
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//shader_color.use();
//shader_color.u_mat4("mvp", proj * glm::translate(glm::vec3{width/2, height/2, 0.f}) * glm::scale(glm::vec3(8)));
//shader_color.u_vec4("col", {1, 1, 1, 1});
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//tex.bind();
//shader.use();
//shader.u_mat4("mvp", proj * glm::translate(glm::vec3{ width / 2, height / 2, 0.f }) * glm::scale(glm::vec3(8)));
//shader.u_int("tex", 0);
//circle3.draw_fill();
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//shader_color.use();
//shader_color.u_mat4("mvp", proj * glm::translate(glm::vec3{width/2, height/2, 0.f}) * glm::scale(glm::vec3(8)));
//shader_color.u_vec4("col", {1, 1, 1, 1});
//glLineWidth(2);
//circle3.draw_fill();
}
void App::resize(float w, float h)
{
width = w;
height = h;
YGNodeStyleSetWidth(y_root, width);
YGNodeStyleSetHeight(y_root, height);
update_layout();
}