added asset loading class, zoom factor, vbo switch, shader version

This commit is contained in:
2017-03-13 01:16:20 +00:00
parent a2a221b17a
commit ee6d352fc6
25 changed files with 345 additions and 108 deletions

1
.gitignore vendored
View File

@@ -10,3 +10,4 @@ android/build/
android/.gradle/
android/.externalNativeBuild/
android/src/main/assets/

View File

@@ -27,6 +27,7 @@ add_library(
src/main/cpp/main.cpp
../engine/pch.cpp
../engine/util.cpp
../engine/asset.cpp
../engine/image.cpp
../engine/texture.cpp
../engine/font.cpp

3
android/build-run.bat Normal file
View File

@@ -0,0 +1,3 @@
call gradlew installDebug
call adb shell am start -n com.omigamedev/android.app.NativeActivity
pause

View File

@@ -9,10 +9,13 @@ buildscript {
apply plugin: 'android'
android {
compileSdkVersion 'android-19'
buildToolsVersion '24.0.3'
compileSdkVersion 23
buildToolsVersion '23.0.2'
defaultConfig {
applicationId = 'com.omigamedev'
minSdkVersion 9
targetSdkVersion 23
// This block is different from the one you use to link Gradle
// to your CMake or ndk-build script.
externalNativeBuild {

View File

@@ -1,11 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
# location of the SDK. This is only used by Ant
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=/Users/omimac/android-sdk-macosx
ndk.dir=/Users/omimac/android-ndk-r13

View File

@@ -3,11 +3,17 @@
package="com.omigamedev"
android:versionCode="1"
android:versionName="1.0">
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:allowBackup="false"
android:hasCode="false"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<activity android:name="android.app.NativeActivity"
android:label="@string/app_name">
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="sensorLandscape">
<meta-data android:name="android.app.lib_name"
android:value="native-lib" />
android:value="native-lib" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

View File

@@ -24,6 +24,7 @@
#include "pch.h"
#include "app.h"
#include "..\..\..\..\engine\asset.h"
/**
* Our saved state data.
@@ -150,15 +151,13 @@ static int engine_init_display(struct engine* engine) {
//glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
//glEnableClientState(GL_VERTEX_ARRAY);
Asset::m_am = engine->app->activity->assetManager;
App::I.width = w;
App::I.height = h;
App::I.initShaders();
if (!plane.create<1>(1,1))
LOG("Failed to create the plane mesh");
App::I.init();
LOG("All ready");
engine->animating = 1;
return 0;
}
@@ -167,22 +166,10 @@ static int engine_init_display(struct engine* engine) {
* Just the current frame in the display.
*/
static void engine_draw_frame(struct engine* engine) {
if (engine->display == NULL) {
// No display.
if (engine->display == NULL)
return;
}
// Just fill the screen with a color.
glClearColor(((float)engine->state.x)/engine->width, engine->state.angle,
((float)engine->state.y)/engine->height, 1);
glClear(GL_COLOR_BUFFER_BIT);
glm::mat4 mvp = glm::ortho<float>(-1, 1, -1, 1, -1, 1);
//App::I.update(now - _prevTime);
ShaderManager::use(kShader::Color);
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
ShaderManager::u_vec4(kShaderUniform::Col, glm::vec4(1, 0, 0, 1));
plane.draw_fill();
App::I.update(0);
eglSwapBuffers(engine->display, engine->surface);
}
@@ -212,12 +199,33 @@ static void engine_term_display(struct engine* engine) {
*/
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
struct engine* engine = (struct engine*)app->userData;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
engine->animating = 1;
engine->state.x = AMotionEvent_getX(event, 0);
engine->state.y = AMotionEvent_getY(event, 0);
return 1;
}
float x = AMotionEvent_getX(event, 0);
float y = AMotionEvent_getY(event, 0);
MouseEvent e;
int32_t eventType = AInputEvent_getType(event);
switch (eventType) {
case AINPUT_EVENT_TYPE_MOTION:
switch (AInputEvent_getSource(event)) {
case AINPUT_SOURCE_TOUCHSCREEN:
int action = AKeyEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK;
switch (action) {
case AMOTION_EVENT_ACTION_DOWN:
App::I.mouse_down(0, x, y);
return 1;
case AMOTION_EVENT_ACTION_UP:
App::I.mouse_up(0, x, y);
return 1;
case AMOTION_EVENT_ACTION_MOVE:
App::I.mouse_move(x, y);
return 1;
}
break;
} // end switch
break;
case AINPUT_EVENT_TYPE_KEY:
// handle key input...
break;
} // end switch
return 0;
}

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">DummyActivity</string>
<string name="app_name">LayoutEngine</string>
</resources>

BIN
data/arial.ttf Normal file

Binary file not shown.

View File

@@ -283,11 +283,8 @@
</border>
</node>
<!-- content panel -->
<border margin="10 0 10 10" border-color=".8" color="1" width="1" grow="1" pad="10" wrap="1" dir="col" justify="center" align="center">
<text text="Viewport" font-face="arial" font-size="30" color="0 .1 .1 1"/>
<text text="Made in C++11 using OpenGL 3.1" font-face="arial" font-size="11" color="0 .1 .1 1"/>
<!--<text text="this is a small description of the useless big text above" font-face="arial" font-size="11" color="0 1 1 1"/>-->
<image id="check" margin="10 0 0 0" path="data/meme/nothing-to-do-here.jpg" width="300" height="200"/>
<border grow="1" color=".1" pad="10">
<viewport grow="1"></viewport>
</border>
</node>
<!-- status bar -->

View File

@@ -151,6 +151,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="engine\app.cpp" />
<ClCompile Include="engine\asset.cpp" />
<ClCompile Include="engine\font.cpp" />
<ClCompile Include="engine\image.cpp" />
<ClCompile Include="engine\layout.cpp" />
@@ -186,6 +187,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="engine\app.h" />
<ClInclude Include="engine\asset.h" />
<ClInclude Include="engine\font.h" />
<ClInclude Include="engine\image.h" />
<ClInclude Include="engine\layout.h" />

View File

@@ -54,6 +54,9 @@
<ClCompile Include="engine\util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="engine\asset.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="engine\app.h">
@@ -83,5 +86,8 @@
<ClInclude Include="engine\util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="engine\asset.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -3,6 +3,15 @@
App App::I; // singleton
#ifdef __APPLE__
#define SHADER_VERSION "#version 300 es\n"
#elif __ANDROID__
#define SHADER_VERSION "#version 300 es\n"
#elif _WIN32
#define SHADER_VERSION "#version 150\n"
#endif
void App::create()
{
width = 800;
@@ -12,7 +21,7 @@ void App::create()
void App::initShaders()
{
static const char* shader_v =
"#version 300 es\n"
SHADER_VERSION
"uniform mat4 mvp;"
"in vec4 pos;"
"in vec2 uvs;"
@@ -22,7 +31,7 @@ void App::initShaders()
" gl_Position = mvp * vec4(pos.xyz, 1.f);"
"}";
static const char* shader_f =
"#version 300 es\n"
SHADER_VERSION
"uniform sampler2D tex;"
"in vec3 uv;"
"out vec4 frag;"
@@ -31,7 +40,7 @@ void App::initShaders()
" frag = texture(tex, uv.xy);"
"}";
static const char* shader_uv_f =
"#version 300 es\n"
SHADER_VERSION
"uniform sampler2D tex;"
"in vec3 uv;"
"out vec4 frag;"
@@ -39,7 +48,7 @@ void App::initShaders()
" frag = vec4(uv.xy,0,1);"
"}";
static const char* shader_atlas_v =
"#version 300 es\n"
SHADER_VERSION
"uniform mat4 mvp;"
"uniform vec2 tof;"
"uniform vec2 tsz;"
@@ -51,7 +60,7 @@ void App::initShaders()
" gl_Position = mvp * vec4(pos, 0, 1);"
"}";
static const char* shader_atlas_f =
"#version 300 es\n"
SHADER_VERSION
"uniform sampler2D tex;"
"in vec2 uv;"
"out vec4 frag;"
@@ -59,21 +68,21 @@ void App::initShaders()
" frag = texture(tex, uv);"
"}";
static const char* shader_color_v =
"#version 300 es\n"
SHADER_VERSION
"uniform mat4 mvp;"
"in vec4 pos;"
"void main(){"
" gl_Position = mvp * pos;"
"}";
static const char* shader_color_f =
"#version 300 es\n"
SHADER_VERSION
"uniform vec4 col;"
"out vec4 frag;"
"void main(){"
" frag = col;"
"}";
static const char* shader_font_v =
"#version 300 es\n"
SHADER_VERSION
"uniform mat4 mvp;"
"in vec2 pos;"
"in vec2 uvs;"
@@ -83,7 +92,7 @@ void App::initShaders()
" gl_Position = mvp * vec4(pos, 0, 1);"
"}";
static const char* shader_font_f =
"#version 300 es\n"
SHADER_VERSION
"uniform sampler2D tex;"
"uniform vec4 col;"
"in vec2 uv;"
@@ -93,6 +102,7 @@ void App::initShaders()
" frag = vec4(col.rgb, a);"
"}";
LOG("initializing shaders");
if (!ShaderManager::create(kShader::Texture, shader_v, shader_f))
LOG("Failed to create shader Texture");
if (!ShaderManager::create(kShader::Color, shader_color_v, shader_color_f))
@@ -103,32 +113,36 @@ void App::initShaders()
LOG("Failed to create shader Font");
if (!ShaderManager::create(kShader::Atlas, shader_atlas_v, shader_atlas_f))
LOG("Failed to create shader Atlas");
LOG("shaders initialized");
}
void App::initAssets()
{
#if _WIN32
const char* ttf = "C:\\Windows\\Fonts\\arial.ttf";
#else
const char* ttf = "/Library/Fonts/Arial.ttf";
#endif
LOG("initializing assets");
FontManager::init();
FontManager::load(kFont::Arial_11, ttf, 15);
FontManager::load(kFont::Arial_30, ttf, 30);
LOG("initializing assets loading fonts");
FontManager::load(kFont::Arial_11, "data/arial.ttf", 15);
FontManager::load(kFont::Arial_30, "data/arial.ttf", 30);
LOG("initializing assets create sampler");
sampler.create(GL_NEAREST);
LOG("initializing assets load uvs texture");
if (!tex.load("data/uvs.jpg"))
LOG("error loading image\n");
LOG("initializing assets completed");
}
void App::initLayout()
{
LOG("initializing layout statics");
NodeBorder::static_init();
NodeImage::static_init();
NodeIcon::static_init();
layout.on_loaded = [&] {
layout[main_id]->update(width, height);
LOG("initializing layout updating after load");
layout[main_id]->update(width, height, zoom);
LOG("initializing layout components");
if (auto* button = layout[main_id]->find<NodeButton>("btn-close"))
{
button->on_click = [] { exit(0); };
@@ -191,7 +205,9 @@ void App::initLayout()
toolbar->m_flood_events = true;
}
};
layout.load("data/layout2.xml");
LOG("initializing layout xml");
layout.load("data/layout.xml");
LOG("initializing layout completed");
}
void App::init()
@@ -219,7 +235,7 @@ void App::init()
initShaders();
initAssets();
initLayout();
initLayout();
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
@@ -243,6 +259,7 @@ void App::init()
GLfloat width_range[2];
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, width_range);
LOG("GL line range: %f - %f\n", width_range[0], width_range[1]);
LOG("Screen Size: %f %f", width, height);
}
void App::update(float dt)
@@ -251,14 +268,17 @@ void App::update(float dt)
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
glClear(GL_COLOR_BUFFER_BIT);
layout.reload();
//layout.reload();
if (auto* main = layout[main_id])
main->update(width, height, zoom);
auto observer = [this](Node* n)
{
if (n && n->m_display)
{
auto box = n->m_clip;
glScissor((int)box.x-1, (int)(height - box.y - box.w)-1, (int)box.z+2, (int)box.w+2);
glm::vec4 c = glm::vec4((int)box.x - 1, (int)(height / zoom - box.y - box.w) - 1, (int)box.z + 2, (int)box.w + 2) * zoom;
glScissor(c.x, c.y, c.z, c.w);
n->draw();
}
};
@@ -275,16 +295,16 @@ void App::resize(float w, float h)
width = w;
height = h;
if (auto* main = layout[main_id])
main->update(w, h);
main->update(w, h, zoom);
}
void App::mouse_down(int button, float x, float y)
{
MouseEvent e;
e.m_type = button ? kEventType::MouseDownR : kEventType::MouseDownL;
e.m_pos = { x, y };
e.m_pos = { x / zoom, y / zoom };
layout[main_id]->on_event(&e);
LOG("mouse click %f %f\n", x, y);
LOG("mouse click button%d pos %f %f\n", button, x, y);
if (popup)
{
@@ -295,7 +315,7 @@ void App::mouse_down(int button, float x, float y)
{
popup = (NodePopupMenu*)layout[const_hash("popup-menu")]->m_children[0]->clone();
popup->SetPositioning(YGPositionTypeAbsolute);
popup->SetPosition(x, y);
popup->SetPosition(x / zoom, y / zoom);
layout[main_id]->add_child(popup);
}
layout[main_id]->update();
@@ -304,7 +324,7 @@ void App::mouse_move(float x, float y)
{
MouseEvent e;
e.m_type = kEventType::MouseMove;
e.m_pos = { x, y };
e.m_pos = { x / zoom, y / zoom };
if (auto* main = layout[main_id])
main->on_event(&e);
}
@@ -312,7 +332,7 @@ void App::mouse_up(int button, float x, float y)
{
MouseEvent e;
e.m_type = button ? kEventType::MouseUpR : kEventType::MouseUpL;
e.m_pos = { x, y };
e.m_pos = { x / zoom, y / zoom };
layout[main_id]->on_event(&e);
layout[main_id]->update();
}

View File

@@ -22,6 +22,11 @@ public:
static App I;
float width;
float height;
#ifdef __ANDROID__
float zoom = 4.0;
#else
float zoom = 1.0;
#endif // __ANDROID__
void init();
void initShaders();
void initAssets();

59
engine/asset.cpp Normal file
View File

@@ -0,0 +1,59 @@
#include "pch.h"
#include "asset.h"
#ifdef __ANDROID__
AAssetManager* Asset::m_am;
#endif
bool Asset::open(const char* path)
{
LOG("Asset::open %s", path);
m_current_path = path;
#ifdef __ANDROID__
if (!(m_asset = AAssetManager_open(m_am, path, AASSET_MODE_RANDOM)))
{
LOG("AAssetManager_open failed");
return false;
}
m_len = (int)AAsset_getLength(m_asset);
m_data = (uint8_t*)AAsset_getBuffer(m_asset);
#else
if (!(m_fp = fopen(path, "rb")))
return false;
fseek(m_fp, 0, SEEK_END);
m_len = (int)ftell(m_fp);
fseek(m_fp, 0, SEEK_SET);
#endif
return true;
}
glm::uint8_t* Asset::read_all()
{
#ifdef __ANDROID__
return m_data;
#else
if (!m_data)
{
m_data = new uint8_t[m_len];
if (m_len != fread(m_data, 1, m_len, m_fp))
{
LOG("ASSET READ FAILED for %s", m_current_path.c_str());
delete m_data;
m_data = nullptr;
}
}
return m_data;
#endif
}
void Asset::close()
{
#ifdef __ANDROID__
AAsset_close(m_asset);
#else
fclose(m_fp);
if (m_data)
delete m_data;
m_data = nullptr;
#endif
}

18
engine/asset.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
class Asset
{
public:
#ifdef __ANDROID__
static AAssetManager* m_am;
AAsset* m_asset = nullptr;
#endif
std::string m_current_path;
FILE* m_fp = nullptr;
int m_len = 0;
uint8_t* m_data = nullptr;
bool open(const char* path);
uint8_t* read_all();
void close();
};

View File

@@ -1,26 +1,23 @@
#include "pch.h"
#include "font.h"
#include "shader.h"
#include "asset.h"
std::map<kFont, Font> FontManager::m_fonts;
Sampler FontManager::m_sampler;
bool Font::load(const char* ttf, int font_size)
{
FILE* font_file = fopen(ttf, "rb");
if (font_file)
Asset file;
LOG("Font::load %s", ttf);
if (file.open(ttf) && file.read_all())
{
fseek(font_file, 0, SEEK_END);
long sz = ftell(font_file);
auto data = std::make_unique<uint8_t[]>(sz);
fseek(font_file, 0, SEEK_SET);
auto bytes = fread(data.get(), 1, sz, font_file);
assert(bytes==sz);
LOG("Font::load loaded");
auto bitmap = std::make_unique<uint8_t[]>(w*h);
chars.resize(num_chars);
int ret = stbtt_BakeFontBitmap(data.get(), 0, (float)font_size, bitmap.get(), w, h, start_char, num_chars, chars.data());
font_tex.create(w, h, GL_RED, bitmap.get());
fclose(font_file);
int ret = stbtt_BakeFontBitmap(file.m_data, 0, (float)font_size, bitmap.get(), w, h, start_char, num_chars, chars.data());
font_tex.create(w, h, GL_LUMINANCE, bitmap.get());
file.close();
return true;
}
return false;
@@ -44,8 +41,8 @@ const Font& FontManager::get(kFont id)
bool TextMesh::create()
{
glGenBuffers(2, font_buffers);
#if USE_VBO
glGenVertexArrays(1, &font_array);
glBindVertexArray(font_array);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
@@ -54,6 +51,7 @@ bool TextMesh::create()
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)(sizeof(float)*2));
glBindVertexArray(0);
#endif // USE_VBO
return true;
}
@@ -113,9 +111,21 @@ void TextMesh::draw()
f.font_tex.bind();
FontManager::m_sampler.bind(0);
#if USE_VBO
glBindVertexArray(font_array);
glDrawElements(GL_TRIANGLES, font_array_count, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
#else
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)(sizeof(float) * 2));
glDrawElements(GL_TRIANGLES, font_array_count, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#endif // USE_VBO
f.font_tex.unbind();
FontManager::m_sampler.unbind();

View File

@@ -1,12 +1,20 @@
#include "pch.h"
#include "image.h"
#include "asset.h"
#include <stb/stb_image.h>
bool Image::load(std::string filename)
{
//stbi_set_flip_vertically_on_load(true);
uint8_t* buffer = stbi_load(filename.c_str(), &width, &height, nullptr, 4);
Asset file;
if (!(file.open(filename.c_str()) && file.read_all()))
{
file.close();
return false;
}
uint8_t* buffer = stbi_load_from_memory(file.m_data, file.m_len, &width, &height, nullptr, 4);
file.close();
comp = 4;
m_data = std::unique_ptr<uint8_t[]>(buffer);
return true;

View File

@@ -1,6 +1,7 @@
#include "pch.h"
#include "layout.h"
#include "util.h"
#include "asset.h"
Plane NodeBorder::m_plane;
Plane NodeImage::m_plane;
@@ -11,11 +12,19 @@ kEventResult Node::on_event(Event* e)
{
kEventResult ret = kEventResult::Available;
for (auto it = m_children.rbegin(); it != m_children.rend(); ++it)
{
if ((*it)->on_event(e) == kEventResult::Consumed)
{
if (m_flood_events)
{
ret = kEventResult::Consumed;
}
else
{
return kEventResult::Consumed;
}
}
}
if (ret == kEventResult::Consumed)
return ret;
switch (e->m_cat)
@@ -51,6 +60,8 @@ kEventResult Node::on_event(Event* e)
handle_event(&e2);
}
break;
default:
break;
}
break;
}
@@ -80,12 +91,13 @@ void Node::remove_child(Node* n)
}
}
void Node::update(float width, float height)
void Node::update(float width, float height, float zoom)
{
YGNodeStyleSetWidth(y_node, width);
YGNodeStyleSetHeight(y_node, height);
m_zoom = zoom;
YGNodeStyleSetWidth(y_node, width / zoom);
YGNodeStyleSetHeight(y_node, height / zoom);
YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR);
m_proj = glm::ortho(0.f, width, height, 0.f, -1.f, 1.f);
m_proj = glm::ortho(0.f, width / zoom, height / zoom, 0.f, -1.f, 1.f);
update_internal({ 0, 0 }, m_proj);
}
@@ -462,18 +474,25 @@ void Node::clone_children(Node* dest) const
bool LayoutManager::load(const char* path)
{
#ifndef __ANDROID__
struct stat tmp_info;
if (stat(path, &tmp_info) != 0)
return false;
if (tmp_info.st_mtime <= m_file_info.st_mtime)
return false;
m_file_info = tmp_info;
#endif // __ANDROID__
m_path = path;
auto old = std::move(m_layouts);
Asset file;
if (!(file.open(path) && file.read_all()))
return false;
tinyxml2::XMLDocument xml;
auto ret = xml.LoadFile(path);
auto ret = xml.Parse((char*)file.m_data, file.m_len);
file.close();
if (ret != tinyxml2::XMLError::XML_SUCCESS)
return false;

View File

@@ -3,6 +3,7 @@
#include "util.h"
#include "shader.h"
#include "font.h"
#include "asset.h"
enum class kAttribute : uint16_t
{
@@ -126,6 +127,7 @@ public:
bool m_flood_events = false;
bool m_destroyed = false;
float m_zoom = 1.f;
glm::vec2 m_pos;
glm::vec2 m_size;
glm::vec4 m_clip;
@@ -148,6 +150,7 @@ public:
m_pos = o.m_pos;
m_size = o.m_size;
m_clip = o.m_clip;
m_zoom = o.m_zoom;
o.y_node = nullptr;
o.parent = nullptr;
}
@@ -203,7 +206,7 @@ public:
return o;
}
void update(float width, float height);
void update(float width, float height, float zoom);
void update();
void update_internal(const glm::vec2& origin, const glm::mat4& proj);
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
@@ -220,6 +223,13 @@ public:
c->watch(observer);
}
void destroy() { m_destroyed = true; }
Node* root()
{
Node* ret = this;
while (ret->parent)
ret = ret->parent;
return ret;
}
template<class T = Node> T* find(const char* ids)
{
@@ -726,14 +736,22 @@ public:
// icons: http://www.famfamfam.com/lab/icons/silk/
// regex css -> spritesheet.txt: \.([^{]+) {\s+width: (\d+)px;\s+height: (\d+)px;\s+.*: -(\d+)px -(\d+)px;\s+}\s+
// to: "\1",\2,\3,\4,\5\n
static char str[256];
Asset file;
if (!(file.open("data/spritesheet.txt") && file.read_all()))
return;
char* data = (char*)file.m_data;
int size = file.m_len;
static char name[256];
int x, y, w, h;
FILE* f = fopen("data/spritesheet.txt", "r");
while (!feof(f) && fscanf(f, "%s %d %d %d %d", str, &w, &h, &x, &y) == 5)
char* s = strtok(data, "\n");
int i = strlen(s) + 1;
while (i < size && sscanf(s, "%s %d %d %d %d", name, &w, &h, &x, &y) == 5)
{
m_icons[str] = glm::vec4(x, y, x+w, y+h);
m_icons[name] = glm::vec4(x, y, x + w, y + h);
s = strtok(nullptr, "\n");
i += strlen(s) + 1;
}
fclose(f);
file.close();
}
virtual Node* clone_instantiate() const override { return new NodeIcon(); }
virtual void clone_copy(Node* dest) const override
@@ -772,11 +790,14 @@ public:
std::unique_ptr<Plane> m_faces;
std::unique_ptr<Sampler> m_sampler;
uint16_t m_tex_id;
glm::vec2 drag_start;
glm::vec2 drag_end;
bool dragging = false;
float angle = 0.0f;
float angle_old;
virtual void draw() override
{
static float angle = 0;
angle += 0.05;
glm::mat4 cam = glm::lookAt(glm::vec3(sinf(angle)*10, 0, -10), glm::vec3(0, 0, 0), glm::vec3(0, -1, 0));
glm::mat4 proj = glm::perspective<float>(glm::radians(45.f), m_clip.z / m_clip.w, .1f, 100);
@@ -787,8 +808,9 @@ public:
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
auto box = m_clip;
glViewport(box.x, (int)(vp[3] - box.y - box.w), box.z, box.w);
auto box = m_clip * root()->m_zoom;
auto c = glm::vec4(box.x, (int)(vp[3] - box.y - box.w), box.z, box.w);
glViewport(c.x, c.y, c.z, c.w);
TextureManager::get(m_tex_id).bind();
m_sampler->bind(0);
glEnable(GL_BLEND);
@@ -816,4 +838,29 @@ public:
TextureManager::load("data/uvs.jpg");
m_tex_id = const_hash("data/uvs.jpg");
}
virtual kEventResult handle_event(Event* e) override
{
Node::handle_event(e);
switch (e->m_type)
{
case kEventType::MouseDownL:
dragging = true;
drag_end = drag_start = ((MouseEvent*)e)->m_pos;
angle_old = angle;
break;
case kEventType::MouseUpL:
dragging = false;
break;
case kEventType::MouseMove:
if (dragging)
{
drag_end = ((MouseEvent*)e)->m_pos;
angle = angle_old + (drag_end - drag_start).x * .01f;
}
break;
default:
break;
}
return kEventResult::Consumed;
}
};

View File

@@ -1,5 +1,8 @@
//#pragma once
#define USE_VBO 0
#define USE_SAMPLER 1
#ifdef __APPLE__
#include <OpenGL/gl3.h>
#include <sys/stat.h>

View File

@@ -22,7 +22,7 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
printf("VERTEX SHADER:\n%s", infolog);
LOG("VERTEX SHADER:\n%s", infolog);
if (status == 0)
{
glDeleteShader(vs);
@@ -41,7 +41,7 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
printf("FRAGMENT SHADER:\n%s", infolog);
LOG("FRAGMENT SHADER:\n%s", infolog);
if (status == 0)
{
glDeleteShader(vs);
@@ -68,7 +68,7 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetProgramiv(ps, GL_LINK_STATUS, &status);
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
printf("LINK SHADER:\n%s", infolog);
LOG("LINK SHADER:\n%s", infolog);
if (status == 0)
{
glDeleteProgram(ps);

View File

@@ -14,10 +14,10 @@ bool Shape::create_buffers(GLvoid* idx, GLvoid* vertices, int isize, int vsize)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
#if USE_VBO
glGenVertexArrays(2, arrays);
if (!(arrays[0] && arrays[1]))
return false;
for (int i = 0; i < 2; i++)
{
glBindVertexArray(arrays[i]);
@@ -28,21 +28,43 @@ bool Shape::create_buffers(GLvoid* idx, GLvoid* vertices, int isize, int vsize)
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
}
glBindVertexArray(0);
#endif
return true;
}
void Shape::draw_fill() const
{
#if USE_VBO
glBindVertexArray(arrays[0]);
glDrawElements(GL_TRIANGLES, count[0], GL_UNSIGNED_SHORT, ioff[0]);
glBindVertexArray(0);
#else
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glDrawElements(GL_TRIANGLES, count[0], GL_UNSIGNED_SHORT, ioff[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#endif // USE_VBO
}
void Shape::draw_stroke() const
{
#if USE_VBO
glBindVertexArray(arrays[1]);
glDrawElements(GL_LINES, count[1], GL_UNSIGNED_SHORT, ioff[1]);
glBindVertexArray(0);
#else
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glDrawElements(GL_LINES, count[1], GL_UNSIGNED_SHORT, ioff[1]);
#endif // USE_VBO
}
bool RectShape::create(float w, float h)

View File

@@ -16,7 +16,9 @@ public:
~Shape()
{
glDeleteBuffers(2, buffers);
#if USE_VBO
glDeleteVertexArrays(2, arrays);
#endif // USE_VBO
}
protected:
glm::vec2 quad_mid_point(glm::vec2 a, glm::vec2 b, glm::vec2 c, glm::vec2 d)

View File

@@ -33,7 +33,7 @@ bool Texture2D::create(int width, int height, GLint format, const uint8_t* data)
}
bool Texture2D::create(const Image& img)
{
static GLint formats[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA };
static GLint formats[] = { 0, 0, GL_RGB, GL_RGBA };
return create(img.width, img.height, formats[img.comp - 1], img.data());
}
bool Texture2D::load(std::string filename)
@@ -56,7 +56,9 @@ glm::vec2 Texture2D::size() const
bool Sampler::create(GLint filter /*= GL_LINEAR*/, GLint wrap /*= GL_CLAMP_TO_EDGE*/)
{
#if USE_SAMPLER
glGenSamplers(1, &id);
#endif // USE_SAMPLER
if (id == 0)
return false;
set(filter, wrap);
@@ -64,18 +66,24 @@ bool Sampler::create(GLint filter /*= GL_LINEAR*/, GLint wrap /*= GL_CLAMP_TO_ED
}
void Sampler::set(GLint filter /*= GL_LINEAR*/, GLint wrap /*= GL_CLAMP_TO_EDGE*/)
{
#if USE_SAMPLER
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, wrap);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, wrap);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, filter);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, filter);
#endif // USE_SAMPLER
}
void Sampler::bind(int unit)
{
current_unit = unit;
#if USE_SAMPLER
glBindSampler(unit, id);
#endif // USE_SAMPLER
}
void Sampler::unbind()
{
#if USE_SAMPLER
glBindSampler(current_unit, 0);
#endif // USE_SAMPLER
}