#include "pch.h" #include "app.hpp" App App::I; // singleton void App::create() { width = 500; height = 500; } glm::vec4 rect_intersection(glm::vec4 a, glm::vec4 b) { // convert from [x,y,w,h] to [x1,y1,x2,y1] a = glm::vec4(a.xy(), a.xy() + a.zw()); b = glm::vec4(b.xy(), b.xy() + b.zw()); auto o = glm::vec4(glm::max(a.xy(), b.xy()), glm::min(a.zw(), b.zw())); o = glm::vec4(o.xy(), glm::max({ 0, 0 }, o.zw() - o.xy())); return o; } class Node { const Node* parent{ nullptr }; YGNodeRef y_node{ nullptr }; struct stat m_file_info { 0 }; public: std::vector children; glm::vec4 color; glm::vec2 m_pos; glm::vec2 m_size; glm::vec4 m_clip; Node(const Node&) = delete; Node& operator=(const Node&) = delete; Node& operator=(Node&& o) { return Node(std::forward(o)); } Node(Node&& o) { children = std::move(o.children); parent = o.parent; y_node = o.y_node; m_pos = o.m_pos; m_size = o.m_size; m_clip = o.m_clip; color = o.color; m_file_info = o.m_file_info; o.y_node = nullptr; o.parent = nullptr; } Node() { y_node = YGNodeNew(); } ~Node() { // children.clear(); if (y_node) YGNodeFree(y_node); } void SetWidth(float value) { YGNodeStyleSetWidth(y_node, value); } void SetWidthP(float value) { YGNodeStyleSetWidthPercent(y_node, value); } void SetHeight(float value) { YGNodeStyleSetHeight(y_node, value); } void SetHeightP(float value) { YGNodeStyleSetHeightPercent(y_node, value); } void SetPadding(float t, float r, float b, float l) { YGNodeStyleSetPadding(y_node, YGEdgeTop, t); YGNodeStyleSetPadding(y_node, YGEdgeRight, r); YGNodeStyleSetPadding(y_node, YGEdgeBottom, b); YGNodeStyleSetPadding(y_node, YGEdgeLeft, l); } void SetFlexGrow(float value) { YGNodeStyleSetFlexGrow(y_node, value); } void SetFlexShrink(float value) { YGNodeStyleSetFlexShrink(y_node, value); } void SetFlexDir(YGFlexDirection value) { YGNodeStyleSetFlexDirection(y_node, value); } void SetFlexWrap(YGWrap value) { YGNodeStyleSetFlexWrap(y_node, value); } void update(float width, float height) { YGNodeStyleSetWidth(y_node, width); YGNodeStyleSetHeight(y_node, height); YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR); update_internal({ 0, 0 }); } void update_internal(glm::vec2 origin) { float x = YGNodeLayoutGetLeft(y_node); float y = YGNodeLayoutGetTop(y_node); float w = YGNodeLayoutGetWidth(y_node); float h = YGNodeLayoutGetHeight(y_node); m_pos = origin + glm::vec2(x, y); m_size = glm::vec2(w, h); if (!parent) m_clip = glm::vec4(m_pos, m_size); else m_clip = rect_intersection(glm::vec4(m_pos, m_size), parent->m_clip); for (auto& c : children) c.update_internal(m_pos); } void parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* attr) { switch (ka) { case att::kAttribute::Width: if (strcmp(attr->Value(), "auto") == 0) { YGNodeStyleSetWidth(y_node, YGUndefined); YGNodeStyleSetWidthPercent(y_node, YGUndefined); } else { 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 (strcmp(attr->Value(), "auto") == 0) { YGNodeStyleSetHeight(y_node, YGUndefined); YGNodeStyleSetHeightPercent(y_node, YGUndefined); } else { 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; case att::kAttribute::Padding: { glm::vec4 pad; int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); if (n == 1) { YGNodeStyleSetPadding(y_node, YGEdgeTop, pad.x); YGNodeStyleSetPadding(y_node, YGEdgeRight, pad.x); YGNodeStyleSetPadding(y_node, YGEdgeBottom, pad.x); YGNodeStyleSetPadding(y_node, YGEdgeLeft, pad.x); } else { YGNodeStyleSetPadding(y_node, YGEdgeTop, pad.x); YGNodeStyleSetPadding(y_node, YGEdgeRight, pad.y); YGNodeStyleSetPadding(y_node, YGEdgeBottom, pad.z); YGNodeStyleSetPadding(y_node, YGEdgeLeft, pad.w); } break; } case att::kAttribute::Margin: { glm::vec4 pad; int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); if (n == 1) { YGNodeStyleSetMargin(y_node, YGEdgeTop, pad.x); YGNodeStyleSetMargin(y_node, YGEdgeRight, pad.x); YGNodeStyleSetMargin(y_node, YGEdgeBottom, pad.x); YGNodeStyleSetMargin(y_node, YGEdgeLeft, pad.x); } else { YGNodeStyleSetMargin(y_node, YGEdgeTop, pad.x); YGNodeStyleSetMargin(y_node, YGEdgeRight, pad.y); YGNodeStyleSetMargin(y_node, YGEdgeBottom, pad.z); YGNodeStyleSetMargin(y_node, YGEdgeLeft, pad.w); } break; } case att::kAttribute::Color: { glm::vec4 pad; int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); if (n == 1) { color = glm::vec4(pad.x); } else { color = pad; } break; } default: // other_attributes_handler() break; } } void load(const char* path) { struct stat tmp_info; if (stat("data/layout.xml", &tmp_info) != 0) return; if (tmp_info.st_mtime <= m_file_info.st_mtime) return; m_file_info = tmp_info; children.clear(); YGNodeReset(y_node); using NodePair = std::pair; std::stack stack; tinyxml2::XMLDocument xml; auto ret = xml.LoadFile(path); load_internal(xml.RootElement()); } void load_internal(const tinyxml2::XMLElement* x_node) { auto attr = x_node->FirstAttribute(); while (attr) { parse_attributes(att::value(attr->Name()), attr); attr = attr->Next(); } auto x_child = x_node->FirstChildElement(); while (x_child) { //Node n; children.emplace_back(); auto& n = children.back(); n.parent = this; YGNodeInsertChild(y_node, n.y_node, YGNodeGetChildCount(y_node)); n.load_internal(x_child); x_child = x_child->NextSiblingElement(); } } }; void App::update_layout() { YGNodeCalculateLayout(y_root, YGUndefined, YGUndefined, YGDirectionLTR); std::stack y_stack; y_stack.push(y_root); auto y_current = y_root; while (y_current) { y_stack.pop(); auto ctx = reinterpret_cast(YGNodeGetContext(y_current)); if (!ctx) { ctx = new glm::vec4(); YGNodeSetContext(y_current, ctx); } if (y_current == y_root) { ctx->x = YGNodeLayoutGetLeft(y_current); ctx->y = YGNodeLayoutGetTop(y_current); ctx->z = YGNodeLayoutGetWidth(y_current); ctx->w = YGNodeLayoutGetHeight(y_current); } int n = YGNodeGetChildCount(y_current); for (int i = 0; i < n; i++) { auto y_child = YGNodeGetChild(y_current, i); auto ctx_child = reinterpret_cast(YGNodeGetContext(y_child)); if (!ctx_child) ctx_child = new glm::vec4(); float x = YGNodeLayoutGetLeft(y_child); float y = YGNodeLayoutGetTop(y_child); float w = YGNodeLayoutGetWidth(y_child); float h = YGNodeLayoutGetHeight(y_child); ctx_child->x = ctx->x + x; ctx_child->y = ctx->y + y; ctx_child->z = w; ctx_child->w = h; *ctx_child = rect_intersection(*ctx_child, *ctx); YGNodeSetContext(y_child, ctx_child); y_stack.emplace(y_child); } y_current = y_stack.size() ? y_stack.top() : nullptr; } } void App::load_layout() { struct stat tmp_info; if (stat("data/layout.xml", &tmp_info) != 0) return; if (tmp_info.st_mtime <= g_file_info.st_mtime) return; g_file_info = tmp_info; if (y_root) YGNodeFreeRecursive(y_root); shapes_list.clear(); y_root = YGNodeNew(); YGNodeStyleSetWidth(y_root, width); //YGNodeStyleSetWidthPercent(y_root, 100); YGNodeStyleSetHeight(y_root, height); //YGNodeStyleSetHeightPercent(y_root, 100); //YGNodeStyleSetFlexDirection(y_root, YGFlexDirectionRow); //YGNodeStyleSetFlexWrap(y_root, YGWrapWrap); //YGNodeStyleSetPadding(y_root, YGEdgeAll, 0); //YGNodeStyleSetPadding(y_root, YGEdgeTop, 0); //YGNodeStyleSetPadding(y_root, YGEdgeRight, 0); //YGNodeStyleSetPadding(y_root, YGEdgeBottom, 0); //YGNodeStyleSetPadding(y_root, YGEdgeLeft, 0); //YGNodeStyleSetJustifyContent(y_root, YGJustifyFlexStart); using NodePair = std::pair; std::stack 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); //YGNodeStyleSetPositionType(y_root, YGPositionTypeRelative); while (child) { auto y_node = YGNodeNew(); stack.emplace(y_node, child); auto attr = child->FirstAttribute(); std::unique_ptr shape; if (strcmp("plane", child->Name()) == 0) { shape = std::make_unique(); shape->create<5>(100.f, 100.f); shape->y_node = y_node; YGNodeSetContext(y_node, shape.get()); } printf("Element %s: ", child->Name()); //YGNodeStyleSetWidth(y_node, 0); //YGNodeStyleSetWidthPercent(y_node, 100); //YGNodeStyleSetHeight(y_node, 0); //YGNodeStyleSetHeightPercent(y_node, 100); //YGNodeStyleSetPadding(y_node, YGEdgeAll, 0); //YGNodeStyleSetPadding(y_node, YGEdgeTop, 0); //YGNodeStyleSetPadding(y_node, YGEdgeRight, 0); //YGNodeStyleSetPadding(y_node, YGEdgeBottom, 0); //YGNodeStyleSetPadding(y_node, YGEdgeLeft, 0); //YGNodeStyleSetPosition(y_node, YGEdgeAll, 0); //YGNodeStyleSetPosition(y_node, YGEdgeTop, 0); //YGNodeStyleSetPosition(y_node, YGEdgeRight, 0); //YGNodeStyleSetPosition(y_node, YGEdgeBottom, 0); //YGNodeStyleSetPosition(y_node, YGEdgeLeft, 0); // //YGNodeStyleSetOverflow(y_node, YGOverflowHidden); while (attr) { const auto ka = att::value(attr->Name()); printf("%s=%s ", attr->Name(), attr->Value()); switch (ka) { case att::kAttribute::Width: if (strcmp(attr->Value(), "auto") == 0) { YGNodeStyleSetWidth(y_node, YGUndefined); YGNodeStyleSetWidthPercent(y_node, YGUndefined); } else { 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 (strcmp(attr->Value(), "auto") == 0) { YGNodeStyleSetHeight(y_node, YGUndefined); YGNodeStyleSetHeightPercent(y_node, YGUndefined); } else { 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; case att::kAttribute::Padding: { glm::vec4 pad; int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); if (n == 1) { YGNodeStyleSetPadding(y_node, YGEdgeTop, pad.x); YGNodeStyleSetPadding(y_node, YGEdgeRight, pad.x); YGNodeStyleSetPadding(y_node, YGEdgeBottom, pad.x); YGNodeStyleSetPadding(y_node, YGEdgeLeft, pad.x); } else { YGNodeStyleSetPadding(y_node, YGEdgeTop, pad.x); YGNodeStyleSetPadding(y_node, YGEdgeRight, pad.y); YGNodeStyleSetPadding(y_node, YGEdgeBottom, pad.z); YGNodeStyleSetPadding(y_node, YGEdgeLeft, pad.w); } break; } case att::kAttribute::Margin: { glm::vec4 pad; int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); if (n == 1) { YGNodeStyleSetMargin(y_node, YGEdgeTop, pad.x); YGNodeStyleSetMargin(y_node, YGEdgeRight, pad.x); YGNodeStyleSetMargin(y_node, YGEdgeBottom, pad.x); YGNodeStyleSetMargin(y_node, YGEdgeLeft, pad.x); } else { YGNodeStyleSetMargin(y_node, YGEdgeTop, pad.x); YGNodeStyleSetMargin(y_node, YGEdgeRight, pad.y); YGNodeStyleSetMargin(y_node, YGEdgeBottom, pad.z); YGNodeStyleSetMargin(y_node, YGEdgeLeft, pad.w); } break; } case att::kAttribute::Color: { glm::vec4 pad; int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); if (n == 1) { if (shape) shape->color = glm::vec4(pad.x); } else { if (shape) shape->color = pad; } break; } default: break; } attr = attr->Next(); } int n = YGNodeGetChildCount(y_root); YGNodeInsertChild(y_root, y_node, n); if (shape) shapes_list.push_back(std::move(shape)); child = child->NextSiblingElement(); printf("\n"); } current = stack.size() ? stack.top() : NodePair{ nullptr, nullptr }; } update_layout(); } Node nn; 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;" "}"; #ifdef _WIN32 static CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info); // colors: http://stackoverflow.com/questions/4053837/colorizing-text-in-the-console-with-c glDebugMessageCallback([](GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { static std::map colors = { { GL_DEBUG_SEVERITY_NOTIFICATION, 8 }, { GL_DEBUG_SEVERITY_LOW, 8 }, { GL_DEBUG_SEVERITY_MEDIUM, FOREGROUND_GREEN | FOREGROUND_INTENSITY }, { GL_DEBUG_SEVERITY_HIGH, FOREGROUND_RED | FOREGROUND_INTENSITY }, }; SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors[severity]); printf("%.*s\n", length, message); FlushConsoleInputBuffer(GetStdHandle(STD_OUTPUT_HANDLE)); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), info.wAttributes); }, nullptr); glEnable(GL_DEBUG_OUTPUT); #endif load_layout(); nn.load("data/layout.xml"); nn.update(width, height); 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_2D); glDisable(GL_DEPTH_TEST); glPointSize(5); glLineWidth(2); //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(.1f, .1f, .1f, 1.f); glViewport(0, 0, (GLsizei)width, (GLsizei)height); glClear(GL_COLOR_BUFFER_BIT); load_layout(); /* 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", { .3f, .3f, .3f, 1 }); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // for (auto& s : shapes_list) // { // auto layout = *reinterpret_cast(YGNodeGetContext(s->y_node)); // auto y_parent = YGNodeGetParent(s->y_node); // if (y_parent && YGNodeGetContext(y_parent)) // { // auto box = *reinterpret_cast(YGNodeGetContext(y_parent)); // glEnable(GL_SCISSOR_TEST); // glScissor(box.x, height - box.y - 1 - box.w, box.z, box.w); // } // //glScissor(10, height - 10 - 1 - 50, 480, 50); // // glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f)); // glm::mat4 scale = glm::scale(glm::vec3(layout.zw(), 1.f)); // glm::mat4 pos = glm::translate(glm::vec3(layout.xy(), 0)); // auto mvp = proj * pos * scale * pivot; // // //shader_uv.use(); // //shader_uv.u_mat4("mvp", mvp); // //plane.draw_fill(); // // shader_color.u_vec4("col", s->color); // shader_color.use(); // shader_color.u_mat4("mvp", mvp); // plane.draw_fill(); // // shader_color.u_vec4("col", { 1, 1, 1, 1 }); // shader_color.use(); // shader_color.u_mat4("mvp", mvp); // plane.draw_stroke(); // glDisable(GL_SCISSOR_TEST); // } std::stack nodes; Node* current = &nn; nodes.push(current); //glEnable(GL_SCISSOR_TEST); while (current) { nodes.pop(); glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f)); glm::mat4 scale = glm::scale(glm::vec3(current->m_size, 1.f)); glm::mat4 pos = glm::translate(glm::vec3(current->m_pos, 0)); auto mvp = proj * pos * scale * pivot; auto box = current->m_clip; glScissor(box.x, height - box.y - 1 - box.w, box.z, box.w); shader_color.u_vec4("col", current->color); shader_color.use(); shader_color.u_mat4("mvp", mvp); plane.draw_fill(); shader_color.u_vec4("col", { 1, 1, 1, 1 }); shader_color.use(); shader_color.u_mat4("mvp", mvp); plane.draw_stroke(); for (auto& c : current->children) nodes.push(&c); current = nodes.size() ? nodes.top() : nullptr; } glDisable(GL_SCISSOR_TEST); 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(); nn.update(width, height); } void App::mouse_down(int button, float x, float y) { printf("mouse click %f %f\n", x, y); } void App::mouse_move(float x, float y) { } void App::mouse_up(int button, float x, float y) { }