diff --git a/.gitignore b/.gitignore index 347bb45..2a7d08a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ android/build/ android/.gradle/ android/.externalNativeBuild/ +android/src/main/assets/ diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 4d9dce4..615a87f 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -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 diff --git a/android/build-run.bat b/android/build-run.bat new file mode 100644 index 0000000..87c7a75 --- /dev/null +++ b/android/build-run.bat @@ -0,0 +1,3 @@ +call gradlew installDebug +call adb shell am start -n com.omigamedev/android.app.NativeActivity +pause \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 3118270..f7915f8 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -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 { diff --git a/android/local.properties b/android/local.properties deleted file mode 100644 index 04083c5..0000000 --- a/android/local.properties +++ /dev/null @@ -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 diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 117a040..413a44f 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -3,11 +3,17 @@ package="com.omigamedev" android:versionCode="1" android:versionName="1.0"> - + + android:label="@string/app_name" + android:configChanges="orientation|keyboardHidden" + android:screenOrientation="sensorLandscape"> + android:value="native-lib" /> diff --git a/android/src/main/cpp/main.cpp b/android/src/main/cpp/main.cpp index cb915fc..8c869a1 100755 --- a/android/src/main/cpp/main.cpp +++ b/android/src/main/cpp/main.cpp @@ -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(-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; } diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml index 47e960d..bafe393 100644 --- a/android/src/main/res/values/strings.xml +++ b/android/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ - DummyActivity + LayoutEngine diff --git a/data/arial.ttf b/data/arial.ttf new file mode 100644 index 0000000..ad7d8ea Binary files /dev/null and b/data/arial.ttf differ diff --git a/data/layout.xml b/data/layout.xml index 38c4048..96cfbaa 100644 --- a/data/layout.xml +++ b/data/layout.xml @@ -283,11 +283,8 @@ - - - - - + + diff --git a/engine.vcxproj b/engine.vcxproj index 9a1b73d..86a22f3 100644 --- a/engine.vcxproj +++ b/engine.vcxproj @@ -151,6 +151,7 @@ + @@ -186,6 +187,7 @@ + diff --git a/engine.vcxproj.filters b/engine.vcxproj.filters index 52fdc9e..7edc68e 100644 --- a/engine.vcxproj.filters +++ b/engine.vcxproj.filters @@ -54,6 +54,9 @@ Source Files + + Source Files + @@ -83,5 +86,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/engine/app.cpp b/engine/app.cpp index f14c62e..faa966c 100644 --- a/engine/app.cpp +++ b/engine/app.cpp @@ -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("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(); } diff --git a/engine/app.h b/engine/app.h index d935660..7a739dd 100644 --- a/engine/app.h +++ b/engine/app.h @@ -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(); diff --git a/engine/asset.cpp b/engine/asset.cpp new file mode 100644 index 0000000..c1eead5 --- /dev/null +++ b/engine/asset.cpp @@ -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 +} diff --git a/engine/asset.h b/engine/asset.h new file mode 100644 index 0000000..269707d --- /dev/null +++ b/engine/asset.h @@ -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(); +}; + diff --git a/engine/font.cpp b/engine/font.cpp index 9fc2407..49b1664 100644 --- a/engine/font.cpp +++ b/engine/font.cpp @@ -1,26 +1,23 @@ #include "pch.h" #include "font.h" #include "shader.h" +#include "asset.h" std::map 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(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(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(); diff --git a/engine/image.cpp b/engine/image.cpp index 2a9f860..50355d4 100644 --- a/engine/image.cpp +++ b/engine/image.cpp @@ -1,12 +1,20 @@ #include "pch.h" #include "image.h" +#include "asset.h" #include 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(buffer); return true; diff --git a/engine/layout.cpp b/engine/layout.cpp index 5d86f09..8939c90 100644 --- a/engine/layout.cpp +++ b/engine/layout.cpp @@ -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; diff --git a/engine/layout.h b/engine/layout.h index a5122c0..303330e 100644 --- a/engine/layout.h +++ b/engine/layout.h @@ -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 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 m_faces; std::unique_ptr 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(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; + } }; diff --git a/engine/pch.h b/engine/pch.h index 032be19..6c01c82 100644 --- a/engine/pch.h +++ b/engine/pch.h @@ -1,5 +1,8 @@ //#pragma once +#define USE_VBO 0 +#define USE_SAMPLER 1 + #ifdef __APPLE__ #include #include diff --git a/engine/shader.cpp b/engine/shader.cpp index 44632aa..02b85f5 100644 --- a/engine/shader.cpp +++ b/engine/shader.cpp @@ -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); diff --git a/engine/shape.cpp b/engine/shape.cpp index 114d47f..678b09b 100644 --- a/engine/shape.cpp +++ b/engine/shape.cpp @@ -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) diff --git a/engine/shape.h b/engine/shape.h index 617e120..2fd7674 100644 --- a/engine/shape.h +++ b/engine/shape.h @@ -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) diff --git a/engine/texture.cpp b/engine/texture.cpp index 807cb2a..f8fe33b 100644 --- a/engine/texture.cpp +++ b/engine/texture.cpp @@ -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 }