add newline feature to the text node, add about window with credits, add about menu with submenus
This commit is contained in:
@@ -187,6 +187,7 @@
|
||||
<ClCompile Include="src\log.cpp" />
|
||||
<ClCompile Include="src\main.cpp" />
|
||||
<ClCompile Include="src\node.cpp" />
|
||||
<ClCompile Include="src\node_about.cpp" />
|
||||
<ClCompile Include="src\node_border.cpp" />
|
||||
<ClCompile Include="src\node_button.cpp" />
|
||||
<ClCompile Include="src\node_button_custom.cpp" />
|
||||
@@ -302,6 +303,7 @@
|
||||
<ClInclude Include="src\layout.h" />
|
||||
<ClInclude Include="src\log.h" />
|
||||
<ClInclude Include="src\node.h" />
|
||||
<ClInclude Include="src\node_about.h" />
|
||||
<ClInclude Include="src\node_border.h" />
|
||||
<ClInclude Include="src\node_button.h" />
|
||||
<ClInclude Include="src\node_button_custom.h" />
|
||||
|
||||
@@ -252,6 +252,9 @@
|
||||
<ClCompile Include="src\version.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\node_about.cpp">
|
||||
<Filter>Source Files\ui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\app.h">
|
||||
@@ -449,6 +452,9 @@
|
||||
<ClInclude Include="src\version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\node_about.h">
|
||||
<Filter>Header Files\ui</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="PanoPainter.rc">
|
||||
|
||||
@@ -56,6 +56,7 @@ add_library(
|
||||
../src/layout.cpp
|
||||
../src/version.cpp
|
||||
../src/node.cpp
|
||||
../src/node_about.cpp
|
||||
../src/node_border.cpp
|
||||
../src/node_button.cpp
|
||||
../src/node_button_custom.cpp
|
||||
|
||||
102
data/layout.xml
102
data/layout.xml
@@ -583,6 +583,67 @@
|
||||
</border>
|
||||
</layout>
|
||||
|
||||
<!--About window-->
|
||||
<layout id="about">
|
||||
<border positioning="absolute" position="0 0" color=".4 .4 .4 .8" width="100%" height="100%" align="center" justify="center">
|
||||
<border thickness="1" border-color=".2" pad="3" max-width="650">
|
||||
<border width="100%" height="30" color=".2 .2 .2 .9" dir="row" align="center" justify="center">
|
||||
<text text="About PanoPainter" font-face="arial" font-size="11"></text>
|
||||
</border>
|
||||
<border width="100%" color="0 0 0 .9" pad="10" dir="col">
|
||||
<!--window content-->
|
||||
<border color=".2" width="100%" height="300">
|
||||
<scroll pad="10" margin="5" color=".3 .3 .3 .4" height="100%" dir="col" wrap="0" shrink="1">
|
||||
<text margin="0 0 0 5" font-face="arial" font-size="11" text=
|
||||
"
|
||||
--------------------------------------------------- ABOUT PANOPAINTER -----------------------------------------------------
|
||||
PanoPainter - Copyright 2018 OmixLab Ltd
|
||||
Thanks for using PanoPainter.
|
||||
My name is Omar Mohamed Ali Mudhir and I'm the developer of this unique application.
|
||||
In the late 2016 Facebook started to make it possible for users to post 360 content
|
||||
captured from the first 360 cameras born after the advent of the VR to the market.
|
||||
|
||||
That's where me and a bounch or artists started to wonder about making art in 360.
|
||||
I then started coding in my spare time to create something that would have helped
|
||||
artists in the long process of creating a panoramic painting (panopainting).
|
||||
|
||||
Today this software has evolved a lot and reached a mature version ready for early
|
||||
adopters that want to break the rules of traditional digital art and get into the
|
||||
future of immersive painting.
|
||||
|
||||
Feel free to follow me on:
|
||||
- Instagram: @panopainter
|
||||
- Twitter: @panopainter
|
||||
- Facebook: fb.me/panopainter
|
||||
|
||||
|
||||
------------------------------------------------- FREE SOFTWARE LICENSES -------------------------------------------------
|
||||
Free brushes:
|
||||
The free brushes are provided by the freely available Brush Pack v3 from Fenris31
|
||||
Link: https://www.deviantart.com/fenris31/art/Brush-Pack-v3-549566626
|
||||
|
||||
Roboto Font License:
|
||||
Copyright 2018 OmixLab Ltd
|
||||
Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License."/>
|
||||
</scroll>
|
||||
</border>
|
||||
<!--footer buttons-->
|
||||
<node height="40" grow="1" dir="row" align="flex-end" justify="flex-end">
|
||||
<button id="btn-ok" text="Ok" width="100" height="30" margin="0 10 0 0"/>
|
||||
</node>
|
||||
</border>
|
||||
</border>
|
||||
</border>
|
||||
</layout>
|
||||
|
||||
<!--popup menu-->
|
||||
<layout id="popup-menu">
|
||||
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
@@ -611,7 +672,7 @@
|
||||
|
||||
<!--file menu-->
|
||||
<layout id="file-menu">
|
||||
<popup-menu positioning="absolute" position="100 100" width="200" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
<popup-menu positioning="absolute" position="100 100" width="210" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
<!--
|
||||
<button-custom height="30" align="center" color=".2" pad="0 20 0 10" dir="row">
|
||||
<checkbox width="20" height="20"/>
|
||||
@@ -678,10 +739,10 @@
|
||||
<icon icon="weather_clouds" width="20"/>
|
||||
<text text="Cloud Browse" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<!--<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon width="20"/>
|
||||
<text text="Quit" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
</button-custom>-->
|
||||
</popup-menu>
|
||||
</layout>
|
||||
|
||||
@@ -705,13 +766,13 @@
|
||||
|
||||
<!--layers menu-->
|
||||
<layout id="layers-menu">
|
||||
<popup-menu positioning="absolute" position="100 100" width="250" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
<popup-menu positioning="absolute" position="100 100" width="270" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
<button-custom id="layer-clear" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="cancel" width="20"/>
|
||||
<text id="menu-label" text="Clear layer" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="clear-grids" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="add" width="20"/>
|
||||
<icon icon="bin" width="20"/>
|
||||
<text text="Clear grids" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="layer-rename" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
@@ -729,20 +790,39 @@
|
||||
<layout id="timelapse-menu">
|
||||
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
<button-custom id="timelapse-start" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="cancel" width="20"/>
|
||||
<icon icon="camera" width="20"/>
|
||||
<text id="menu-label" text="Start Recording" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="timelapse-clear" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="cancel" width="20"/>
|
||||
<icon icon="bin" width="20"/>
|
||||
<text id="menu-label" text="Clear Frames" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="timelapse-export" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="cancel" width="20"/>
|
||||
<icon icon="film_save" width="20"/>
|
||||
<text id="menu-label" text="Export MP4" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
</popup-menu>
|
||||
</layout>
|
||||
|
||||
|
||||
<!-- about menu -->
|
||||
<layout id="about-menu">
|
||||
<popup-menu positioning="absolute" position="100 100" width="200" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
<button-custom id="about-doc" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="help" width="20"/>
|
||||
<text id="menu-label" text="Help Guide" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="about-app" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="application_view_gallery" width="20"/>
|
||||
<text id="menu-label" text="About PanoPainter" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="about-news" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="bug" width="20"/>
|
||||
<text id="menu-label" text="What's new?" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
</popup-menu>
|
||||
</layout>
|
||||
|
||||
<!--main-->
|
||||
<layout id="main">
|
||||
<node dir="col" wrap="0" width="100%" height="100%" pad="0">
|
||||
@@ -768,7 +848,7 @@
|
||||
<text id="txt-rec" text="" font-face="arial" font-size="11" margin="0 10 0 0" color=".6 .6 .6 1"/>
|
||||
<text id="txt-memory" text="History memory: 0.00 Mb" font-face="arial" font-size="11" margin="0 5 0 0" color=".6 .6 .6 1"/>
|
||||
<button-custom id="btn-clean-memory" margin="0 20 0 0">
|
||||
<icon icon="delete" width="20"/>
|
||||
<icon icon="cancel" width="20"/>
|
||||
</button-custom>
|
||||
<text id="version" text="PanoPainter" font-face="arial" font-size="11" margin="0 10 0 0" color=".2 .5 1 1"/>
|
||||
</node>
|
||||
@@ -795,12 +875,10 @@
|
||||
<button-custom id="menu-timelapse" width="80" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
|
||||
<text text="Timelapse" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<!--
|
||||
<button-custom id="menu-about" width="60" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
|
||||
<text text="About" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button id="btn-anim" width="70" height="100%" margin="1 0 0 10" text="Animate"/>
|
||||
-->
|
||||
<!--<button id="btn-anim" width="70" height="100%" margin="1 0 0 10" text="Animate"/>-->
|
||||
<node dir="row" justify="center" grow="1">
|
||||
<button-custom id="btn-pen" width="50" height="100%" margin="0 0 0 5" thickness="1" border-color="0 0 0 1" pad="2">
|
||||
<image path="data/ui/pen.png" width="100%" height="100%" align="center" justify="flex-end"/>
|
||||
|
||||
@@ -139,6 +139,8 @@ public:
|
||||
void init_menu_edit();
|
||||
void init_menu_layer();
|
||||
void init_menu_timelapse();
|
||||
void init_menu_about();
|
||||
void dialog_about();
|
||||
void dialog_newdoc();
|
||||
void dialog_save();
|
||||
void dialog_save_ver();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "node_dialog_open.h"
|
||||
#include "node_dialog_browse.h"
|
||||
#include "node_dialog_cloud.h"
|
||||
#include "node_about.h"
|
||||
|
||||
std::shared_ptr<NodeProgressBar> App::show_progress(const std::string& title)
|
||||
{
|
||||
@@ -17,6 +18,17 @@ std::shared_ptr<NodeProgressBar> App::show_progress(const std::string& title)
|
||||
return pb;
|
||||
}
|
||||
|
||||
void App::dialog_about()
|
||||
{
|
||||
auto dialog = std::make_shared<NodeAbout>();
|
||||
dialog->m_manager = &layout;
|
||||
dialog->init();
|
||||
dialog->create();
|
||||
dialog->loaded();
|
||||
|
||||
layout[main_id]->add_child(dialog);
|
||||
layout[main_id]->update();
|
||||
}
|
||||
void App::dialog_newdoc()
|
||||
{
|
||||
auto show_dialog = [this] {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "node_text.h"
|
||||
#include "node_progress_bar.h"
|
||||
#include "node_dialog_picker.h"
|
||||
#include "node_about.h"
|
||||
|
||||
using namespace ui;
|
||||
|
||||
@@ -520,6 +521,53 @@ void App::init_menu_timelapse()
|
||||
}
|
||||
}
|
||||
|
||||
void App::init_menu_about()
|
||||
{
|
||||
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-about"))
|
||||
{
|
||||
menu_file->on_click = [=](Node*) {
|
||||
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
|
||||
popup = (NodePopupMenu*)layout[const_hash("about-menu")]->m_children[0]->clone();
|
||||
popup->update();
|
||||
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
|
||||
pos.x = pos.x - popup->m_size.x + menu_file->m_size.x;
|
||||
popup->SetPositioning(YGPositionTypeAbsolute);
|
||||
popup->SetPosition(pos.x, pos.y);
|
||||
layout[main_id]->add_child(popup);
|
||||
layout[main_id]->update();
|
||||
popup->mouse_capture();
|
||||
popup->m_mouse_ignore = false;
|
||||
popup->m_flood_events = true;
|
||||
popup->m_capture_children = false;
|
||||
|
||||
popup->find<NodeButtonCustom>("about-app")->on_click = [this](Node*) {
|
||||
dialog_about();
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
|
||||
popup->find<NodeButtonCustom>("about-doc")->on_click = [this](Node*) {
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
|
||||
if (auto item = popup->find<NodeButtonCustom>("about-news"))
|
||||
{
|
||||
if (auto text = item->find<NodeText>("menu-label"))
|
||||
{
|
||||
static char label[128];
|
||||
sprintf(label, "What's new in %d.%d.%d?", g_version_major, g_version_minor, g_version_fix);
|
||||
text->set_text(label);
|
||||
}
|
||||
item->on_click = [this](Node*) {
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void App::brush_update()
|
||||
{
|
||||
// brushes->select_brush(canvas->m_brush.id);
|
||||
@@ -643,6 +691,7 @@ void App::initLayout()
|
||||
init_menu_edit();
|
||||
init_menu_layer();
|
||||
init_menu_timelapse();
|
||||
init_menu_about();
|
||||
|
||||
// set version string
|
||||
if (auto* version_label = layout[main_id]->find<NodeText>("version"))
|
||||
@@ -650,15 +699,6 @@ void App::initLayout()
|
||||
version_label->set_text(g_version);
|
||||
}
|
||||
|
||||
|
||||
if (auto* menu_entry = layout[main_id]->find<NodeButtonCustom>("menu-about"))
|
||||
{
|
||||
menu_entry->on_click = [=](Node*) {
|
||||
// int x = 0;
|
||||
// sin(time(0) / x);
|
||||
};
|
||||
}
|
||||
|
||||
Brush b;
|
||||
int br_idx = brushes->find_brush("Round-Hard");
|
||||
b.m_tex_id = brushes->get_texture_id(br_idx);
|
||||
|
||||
13
src/font.cpp
13
src/font.cpp
@@ -19,6 +19,7 @@ bool Font::load(const char* ttf, int font_size)
|
||||
stbtt_BakeFontBitmap(file.m_data, 0, (float)font_size*2, bitmap.get(), w, h, start_char, num_chars, chars.data());
|
||||
font_tex.create(w, h, GL_R8, GL_RED, bitmap.get());
|
||||
file.close();
|
||||
size = font_size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -71,6 +72,12 @@ void TextMesh::update(kFont id, const char* text)
|
||||
glm::vec2 bbmax(-FLT_MAX);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (text[i] == '\n')
|
||||
{
|
||||
x = 0;
|
||||
y += f.size *2;
|
||||
continue;
|
||||
}
|
||||
int c = text[i] - f.start_char;
|
||||
stbtt_aligned_quad q;
|
||||
stbtt_GetBakedQuad((stbtt_bakedchar*)f.chars.data(), f.w, f.h, c, &x, &y, &q, true);
|
||||
@@ -88,10 +95,8 @@ void TextMesh::update(kFont id, const char* text)
|
||||
bbmin = glm::min(bbmin, { q.x0/2.f, q.y0/2.f });
|
||||
bbmax = glm::max(bbmax, { q.x1/2.f, q.y1/2.f });
|
||||
}
|
||||
for (int i = 0; i < len*4; i++)
|
||||
{
|
||||
v[i] -= glm::vec4(bbmin, 0, 0);
|
||||
}
|
||||
for (auto& vi : v)
|
||||
vi -= glm::vec4(bbmin, 0, 0);
|
||||
bb = bbmax - bbmin;
|
||||
font_array_count = (int)idx.size();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
|
||||
|
||||
@@ -16,6 +16,7 @@ public:
|
||||
const int h = 512;
|
||||
const int num_chars = 96;
|
||||
const int start_char = 32;
|
||||
int size = 0;
|
||||
stbtt_fontinfo font;
|
||||
Texture2D font_tex;
|
||||
std::vector<stbtt_bakedchar> chars;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "node_colorwheel.h"
|
||||
#include "node_dialog_picker.h"
|
||||
#include "node_panel_grid.h"
|
||||
#include "node_about.h"
|
||||
|
||||
void Node::async_start()
|
||||
{
|
||||
@@ -897,6 +898,7 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
|
||||
CASE(kWidget::DialogCloudItem, NodeDialogCloudItem);
|
||||
CASE(kWidget::ColorWheel, NodeColorWheel);
|
||||
CASE(kWidget::ColorPicker, NodeColorPicker);
|
||||
CASE(kWidget::About, NodeAbout);
|
||||
#undef CASE
|
||||
case kWidget::Ref:
|
||||
{
|
||||
|
||||
@@ -81,6 +81,7 @@ enum class kWidget : uint16_t
|
||||
DialogCloudItem = const_hash("dialog-cloud-item"),
|
||||
ColorWheel = const_hash("colorwheel"),
|
||||
ColorPicker = const_hash("color-picker"),
|
||||
About = const_hash("about"),
|
||||
};
|
||||
|
||||
class Node
|
||||
|
||||
26
src/node_about.cpp
Normal file
26
src/node_about.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "pch.h"
|
||||
#include "log.h"
|
||||
#include "node_about.h"
|
||||
#include "layout.h"
|
||||
|
||||
Node* NodeAbout::clone_instantiate() const
|
||||
{
|
||||
return new NodeAbout();
|
||||
}
|
||||
|
||||
void NodeAbout::init()
|
||||
{
|
||||
SetPosition(0, 0);
|
||||
SetWidthP(100);
|
||||
SetHeightP(100);
|
||||
SetPositioning(YGPositionTypeAbsolute);
|
||||
m_template = (*m_manager)[const_hash("about")]->m_children[0]->clone();
|
||||
add_child(m_template);
|
||||
btn_ok = m_template->find<NodeButton>("btn-ok");
|
||||
btn_ok->on_click = [&](Node*) { destroy(); };
|
||||
}
|
||||
|
||||
kEventResult NodeAbout::handle_event(Event* e)
|
||||
{
|
||||
return kEventResult::Consumed;
|
||||
}
|
||||
13
src/node_about.h
Normal file
13
src/node_about.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "node.h"
|
||||
#include "node_button.h"
|
||||
|
||||
class NodeAbout : public Node
|
||||
{
|
||||
Node* m_template;
|
||||
NodeButton* btn_ok;
|
||||
public:
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void init() override;
|
||||
virtual kEventResult handle_event(Event* e) override;
|
||||
};
|
||||
@@ -3,6 +3,14 @@
|
||||
#include "node_scroll.h"
|
||||
#include "event.h"
|
||||
|
||||
NodeScroll::NodeScroll()
|
||||
{
|
||||
m_drag_start = glm::vec2(0);
|
||||
m_offset_start = glm::vec2(0);
|
||||
m_offset = glm::vec2(0);
|
||||
m_mask = glm::vec2(0, 1);
|
||||
}
|
||||
|
||||
Node* NodeScroll::clone_instantiate() const
|
||||
{
|
||||
return new NodeScroll;
|
||||
@@ -43,7 +51,7 @@ kEventResult NodeScroll::handle_event(Event* e)
|
||||
m_dragging = false;
|
||||
break;
|
||||
case kEventType::MouseScroll:
|
||||
m_offset += me->m_scroll_delta * 50;
|
||||
m_offset += me->m_scroll_delta * 50 * m_mask;
|
||||
fix_scroll();
|
||||
break;
|
||||
case kEventType::GestureStart:
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
class NodeScroll : public NodeBorder
|
||||
{
|
||||
bool m_dragging = false;
|
||||
glm::vec2 m_drag_start;
|
||||
glm::vec2 m_offset_start;
|
||||
glm::vec2 m_offset;
|
||||
glm::vec2 m_mask{ 0, 1 };
|
||||
glm::vec2 m_drag_start = glm::vec2(0);
|
||||
glm::vec2 m_offset_start = glm::vec2(0);
|
||||
glm::vec2 m_offset = glm::vec2(0);
|
||||
glm::vec2 m_mask = glm::vec2(1, 0);
|
||||
public:
|
||||
NodeScroll();
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual kEventResult handle_event(Event* e) override;
|
||||
void fix_scroll();
|
||||
|
||||
@@ -54,7 +54,7 @@ void NodeText::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* att
|
||||
switch (ka)
|
||||
{
|
||||
case kAttribute::Text:
|
||||
m_text = attr->Value();
|
||||
m_text = unescape(attr->Value());
|
||||
break;
|
||||
case kAttribute::FontFace:
|
||||
m_font = attr->Value();
|
||||
|
||||
25
src/util.cpp
25
src/util.cpp
@@ -105,6 +105,31 @@ std::vector<std::string> split(const std::string& subject, char d, int max_split
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string unescape(const std::string& s)
|
||||
{
|
||||
std::string res;
|
||||
std::string::const_iterator it = s.begin();
|
||||
while (it != s.end())
|
||||
{
|
||||
char c = *it++;
|
||||
if (c == '\\' && it != s.end())
|
||||
{
|
||||
switch (*it++) {
|
||||
case '\\': c = '\\'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 't': c = '\t'; break;
|
||||
// all other escapes
|
||||
default:
|
||||
// invalid escape sequence - skip it. alternatively you can copy it as is, throw an exception...
|
||||
continue;
|
||||
}
|
||||
}
|
||||
res += c;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static const char* gl2str(GLenum err)
|
||||
{
|
||||
switch (err)
|
||||
|
||||
@@ -16,6 +16,7 @@ glm::vec4 rand_color();
|
||||
glm::vec3 convert_hsv2rgb(const glm::vec3 c);
|
||||
glm::vec3 convert_rgb2hsv(const glm::vec3 c);
|
||||
std::vector<std::string> split(const std::string& subject, char d, int max_split = 0);
|
||||
std::string unescape(const std::string& s);
|
||||
|
||||
size_t curl_data_handler(void *contents, size_t size, size_t nmemb, void *userp);
|
||||
size_t curl_data_write(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
@@ -26,7 +27,6 @@ inline glm::vec2 zw(const glm::vec4& v) { return glm::vec2(v.z, v.w); }
|
||||
inline glm::ivec2 xy(const glm::ivec4& v) { return glm::ivec2(v.x, v.y); }
|
||||
inline glm::ivec3 xyz(const glm::ivec4& v) { return glm::ivec3(v.x, v.y, v.z); }
|
||||
inline glm::ivec2 zw(const glm::ivec4& v) { return glm::ivec2(v.z, v.w); }
|
||||
|
||||
inline glm::vec2 xy(const glm::vec3& v) { return glm::vec2(v.x, v.y); }
|
||||
|
||||
template<typename T, int N> struct cbuffer
|
||||
|
||||
Reference in New Issue
Block a user