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/.gradle/
android/.externalNativeBuild/ android/.externalNativeBuild/
android/src/main/assets/

View File

@@ -27,6 +27,7 @@ add_library(
src/main/cpp/main.cpp src/main/cpp/main.cpp
../engine/pch.cpp ../engine/pch.cpp
../engine/util.cpp ../engine/util.cpp
../engine/asset.cpp
../engine/image.cpp ../engine/image.cpp
../engine/texture.cpp ../engine/texture.cpp
../engine/font.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' apply plugin: 'android'
android { android {
compileSdkVersion 'android-19' compileSdkVersion 23
buildToolsVersion '24.0.3' buildToolsVersion '23.0.2'
defaultConfig { defaultConfig {
applicationId = 'com.omigamedev'
minSdkVersion 9
targetSdkVersion 23
// This block is different from the one you use to link Gradle // This block is different from the one you use to link Gradle
// to your CMake or ndk-build script. // to your CMake or ndk-build script.
externalNativeBuild { 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" package="com.omigamedev"
android:versionCode="1" android:versionCode="1"
android:versionName="1.0"> 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" <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" <meta-data android:name="android.app.lib_name"
android:value="native-lib" /> android:value="native-lib" />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />

View File

@@ -24,6 +24,7 @@
#include "pch.h" #include "pch.h"
#include "app.h" #include "app.h"
#include "..\..\..\..\engine\asset.h"
/** /**
* Our saved state data. * Our saved state data.
@@ -150,15 +151,13 @@ static int engine_init_display(struct engine* engine) {
//glShadeModel(GL_SMOOTH); //glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
//glEnableClientState(GL_VERTEX_ARRAY); //glEnableClientState(GL_VERTEX_ARRAY);
Asset::m_am = engine->app->activity->assetManager;
App::I.width = w; App::I.width = w;
App::I.height = h; App::I.height = h;
App::I.initShaders(); App::I.init();
if (!plane.create<1>(1,1))
LOG("Failed to create the plane mesh");
LOG("All ready"); LOG("All ready");
engine->animating = 1;
return 0; return 0;
} }
@@ -167,22 +166,10 @@ static int engine_init_display(struct engine* engine) {
* Just the current frame in the display. * Just the current frame in the display.
*/ */
static void engine_draw_frame(struct engine* engine) { static void engine_draw_frame(struct engine* engine) {
if (engine->display == NULL) { if (engine->display == NULL)
// No display.
return; return;
}
// Just fill the screen with a color. App::I.update(0);
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();
eglSwapBuffers(engine->display, engine->surface); 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) { static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
struct engine* engine = (struct engine*)app->userData; struct engine* engine = (struct engine*)app->userData;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { float x = AMotionEvent_getX(event, 0);
engine->animating = 1; float y = AMotionEvent_getY(event, 0);
engine->state.x = AMotionEvent_getX(event, 0); MouseEvent e;
engine->state.y = AMotionEvent_getY(event, 0); int32_t eventType = AInputEvent_getType(event);
return 1; 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; return 0;
} }

View File

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

BIN
data/arial.ttf Normal file

Binary file not shown.

View File

@@ -283,11 +283,8 @@
</border> </border>
</node> </node>
<!-- content panel --> <!-- 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"> <border grow="1" color=".1" pad="10">
<text text="Viewport" font-face="arial" font-size="30" color="0 .1 .1 1"/> <viewport grow="1"></viewport>
<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> </border>
</node> </node>
<!-- status bar --> <!-- status bar -->

View File

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

View File

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

View File

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

View File

@@ -22,6 +22,11 @@ public:
static App I; static App I;
float width; float width;
float height; float height;
#ifdef __ANDROID__
float zoom = 4.0;
#else
float zoom = 1.0;
#endif // __ANDROID__
void init(); void init();
void initShaders(); void initShaders();
void initAssets(); 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 "pch.h"
#include "font.h" #include "font.h"
#include "shader.h" #include "shader.h"
#include "asset.h"
std::map<kFont, Font> FontManager::m_fonts; std::map<kFont, Font> FontManager::m_fonts;
Sampler FontManager::m_sampler; Sampler FontManager::m_sampler;
bool Font::load(const char* ttf, int font_size) bool Font::load(const char* ttf, int font_size)
{ {
FILE* font_file = fopen(ttf, "rb"); Asset file;
if (font_file) LOG("Font::load %s", ttf);
if (file.open(ttf) && file.read_all())
{ {
fseek(font_file, 0, SEEK_END); LOG("Font::load loaded");
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);
auto bitmap = std::make_unique<uint8_t[]>(w*h); auto bitmap = std::make_unique<uint8_t[]>(w*h);
chars.resize(num_chars); chars.resize(num_chars);
int ret = stbtt_BakeFontBitmap(data.get(), 0, (float)font_size, bitmap.get(), w, h, start_char, num_chars, chars.data()); 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_RED, bitmap.get()); font_tex.create(w, h, GL_LUMINANCE, bitmap.get());
fclose(font_file); file.close();
return true; return true;
} }
return false; return false;
@@ -44,8 +41,8 @@ const Font& FontManager::get(kFont id)
bool TextMesh::create() bool TextMesh::create()
{ {
glGenBuffers(2, font_buffers); glGenBuffers(2, font_buffers);
#if USE_VBO
glGenVertexArrays(1, &font_array); glGenVertexArrays(1, &font_array);
glBindVertexArray(font_array); glBindVertexArray(font_array);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
@@ -54,6 +51,7 @@ bool TextMesh::create()
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)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)); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)(sizeof(float)*2));
glBindVertexArray(0); glBindVertexArray(0);
#endif // USE_VBO
return true; return true;
} }
@@ -113,9 +111,21 @@ void TextMesh::draw()
f.font_tex.bind(); f.font_tex.bind();
FontManager::m_sampler.bind(0); FontManager::m_sampler.bind(0);
#if USE_VBO
glBindVertexArray(font_array); glBindVertexArray(font_array);
glDrawElements(GL_TRIANGLES, font_array_count, GL_UNSIGNED_SHORT, 0); glDrawElements(GL_TRIANGLES, font_array_count, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(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(); f.font_tex.unbind();
FontManager::m_sampler.unbind(); FontManager::m_sampler.unbind();

View File

@@ -1,12 +1,20 @@
#include "pch.h" #include "pch.h"
#include "image.h" #include "image.h"
#include "asset.h"
#include <stb/stb_image.h> #include <stb/stb_image.h>
bool Image::load(std::string filename) bool Image::load(std::string filename)
{ {
//stbi_set_flip_vertically_on_load(true); //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; comp = 4;
m_data = std::unique_ptr<uint8_t[]>(buffer); m_data = std::unique_ptr<uint8_t[]>(buffer);
return true; return true;

View File

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

View File

@@ -3,6 +3,7 @@
#include "util.h" #include "util.h"
#include "shader.h" #include "shader.h"
#include "font.h" #include "font.h"
#include "asset.h"
enum class kAttribute : uint16_t enum class kAttribute : uint16_t
{ {
@@ -126,6 +127,7 @@ public:
bool m_flood_events = false; bool m_flood_events = false;
bool m_destroyed = false; bool m_destroyed = false;
float m_zoom = 1.f;
glm::vec2 m_pos; glm::vec2 m_pos;
glm::vec2 m_size; glm::vec2 m_size;
glm::vec4 m_clip; glm::vec4 m_clip;
@@ -148,6 +150,7 @@ public:
m_pos = o.m_pos; m_pos = o.m_pos;
m_size = o.m_size; m_size = o.m_size;
m_clip = o.m_clip; m_clip = o.m_clip;
m_zoom = o.m_zoom;
o.y_node = nullptr; o.y_node = nullptr;
o.parent = nullptr; o.parent = nullptr;
} }
@@ -203,7 +206,7 @@ public:
return o; return o;
} }
void update(float width, float height); void update(float width, float height, float zoom);
void update(); void update();
void update_internal(const glm::vec2& origin, const glm::mat4& proj); void update_internal(const glm::vec2& origin, const glm::mat4& proj);
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr); virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
@@ -220,6 +223,13 @@ public:
c->watch(observer); c->watch(observer);
} }
void destroy() { m_destroyed = true; } 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) template<class T = Node> T* find(const char* ids)
{ {
@@ -726,14 +736,22 @@ public:
// icons: http://www.famfamfam.com/lab/icons/silk/ // 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+ // 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 // 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; int x, y, w, h;
FILE* f = fopen("data/spritesheet.txt", "r"); char* s = strtok(data, "\n");
while (!feof(f) && fscanf(f, "%s %d %d %d %d", str, &w, &h, &x, &y) == 5) 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 Node* clone_instantiate() const override { return new NodeIcon(); }
virtual void clone_copy(Node* dest) const override virtual void clone_copy(Node* dest) const override
@@ -772,11 +790,14 @@ public:
std::unique_ptr<Plane> m_faces; std::unique_ptr<Plane> m_faces;
std::unique_ptr<Sampler> m_sampler; std::unique_ptr<Sampler> m_sampler;
uint16_t m_tex_id; 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 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 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); 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); glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
auto box = m_clip; auto box = m_clip * root()->m_zoom;
glViewport(box.x, (int)(vp[3] - box.y - box.w), box.z, box.w); 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(); TextureManager::get(m_tex_id).bind();
m_sampler->bind(0); m_sampler->bind(0);
glEnable(GL_BLEND); glEnable(GL_BLEND);
@@ -816,4 +838,29 @@ public:
TextureManager::load("data/uvs.jpg"); TextureManager::load("data/uvs.jpg");
m_tex_id = const_hash("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 //#pragma once
#define USE_VBO 0
#define USE_SAMPLER 1
#ifdef __APPLE__ #ifdef __APPLE__
#include <OpenGL/gl3.h> #include <OpenGL/gl3.h>
#include <sys/stat.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); glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog); glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
if (infolen > 0) if (infolen > 0)
printf("VERTEX SHADER:\n%s", infolog); LOG("VERTEX SHADER:\n%s", infolog);
if (status == 0) if (status == 0)
{ {
glDeleteShader(vs); glDeleteShader(vs);
@@ -41,7 +41,7 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetShaderiv(fs, GL_COMPILE_STATUS, &status); glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog); glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
if (infolen > 0) if (infolen > 0)
printf("FRAGMENT SHADER:\n%s", infolog); LOG("FRAGMENT SHADER:\n%s", infolog);
if (status == 0) if (status == 0)
{ {
glDeleteShader(vs); glDeleteShader(vs);
@@ -68,7 +68,7 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetProgramiv(ps, GL_LINK_STATUS, &status); glGetProgramiv(ps, GL_LINK_STATUS, &status);
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog); glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
if (infolen > 0) if (infolen > 0)
printf("LINK SHADER:\n%s", infolog); LOG("LINK SHADER:\n%s", infolog);
if (status == 0) if (status == 0)
{ {
glDeleteProgram(ps); 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_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
#if USE_VBO
glGenVertexArrays(2, arrays); glGenVertexArrays(2, arrays);
if (!(arrays[0] && arrays[1])) if (!(arrays[0] && arrays[1]))
return false; return false;
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
glBindVertexArray(arrays[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(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)); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
} }
glBindVertexArray(0); glBindVertexArray(0);
#endif
return true; return true;
} }
void Shape::draw_fill() const void Shape::draw_fill() const
{ {
#if USE_VBO
glBindVertexArray(arrays[0]); glBindVertexArray(arrays[0]);
glDrawElements(GL_TRIANGLES, count[0], GL_UNSIGNED_SHORT, ioff[0]); glDrawElements(GL_TRIANGLES, count[0], GL_UNSIGNED_SHORT, ioff[0]);
glBindVertexArray(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 void Shape::draw_stroke() const
{ {
#if USE_VBO
glBindVertexArray(arrays[1]); glBindVertexArray(arrays[1]);
glDrawElements(GL_LINES, count[1], GL_UNSIGNED_SHORT, ioff[1]); glDrawElements(GL_LINES, count[1], GL_UNSIGNED_SHORT, ioff[1]);
glBindVertexArray(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_LINES, count[1], GL_UNSIGNED_SHORT, ioff[1]);
#endif // USE_VBO
} }
bool RectShape::create(float w, float h) bool RectShape::create(float w, float h)

View File

@@ -16,7 +16,9 @@ public:
~Shape() ~Shape()
{ {
glDeleteBuffers(2, buffers); glDeleteBuffers(2, buffers);
#if USE_VBO
glDeleteVertexArrays(2, arrays); glDeleteVertexArrays(2, arrays);
#endif // USE_VBO
} }
protected: protected:
glm::vec2 quad_mid_point(glm::vec2 a, glm::vec2 b, glm::vec2 c, glm::vec2 d) 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) 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()); return create(img.width, img.height, formats[img.comp - 1], img.data());
} }
bool Texture2D::load(std::string filename) 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*/) bool Sampler::create(GLint filter /*= GL_LINEAR*/, GLint wrap /*= GL_CLAMP_TO_EDGE*/)
{ {
#if USE_SAMPLER
glGenSamplers(1, &id); glGenSamplers(1, &id);
#endif // USE_SAMPLER
if (id == 0) if (id == 0)
return false; return false;
set(filter, wrap); 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*/) 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_S, wrap);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, wrap); glSamplerParameteri(id, GL_TEXTURE_WRAP_T, wrap);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, filter); glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, filter);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, filter); glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, filter);
#endif // USE_SAMPLER
} }
void Sampler::bind(int unit) void Sampler::bind(int unit)
{ {
current_unit = unit; current_unit = unit;
#if USE_SAMPLER
glBindSampler(unit, id); glBindSampler(unit, id);
#endif // USE_SAMPLER
} }
void Sampler::unbind() void Sampler::unbind()
{ {
#if USE_SAMPLER
glBindSampler(current_unit, 0); glBindSampler(current_unit, 0);
#endif // USE_SAMPLER
} }