OOBase::SharedPtr<Indigo::Render::SGNode> Indigo::SGQuad::on_render_create(Render::SGGroup* parent) { OOBase::SharedPtr<Render::SGNode> node; bool cached = true; OOBase::SharedPtr<OOGL::Texture> texture = m_image->make_texture(GL_RGBA8,cached); if (!texture) return node; if (!cached) { texture->parameter(GL_TEXTURE_MAG_FILTER,GL_LINEAR); texture->parameter(GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); texture->parameter(GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); texture->parameter(GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); } OOBase::SharedPtr< ::SGQuad> quad = OOBase::allocate_shared< ::SGQuad>(AABB(glm::vec3(0.5f,0.5f,0),glm::vec3(0.5f,0.5f,0)),texture,m_transparent,m_colour); if (!quad) LOG_ERROR_RETURN(("Failed to allocate: %s\n",OOBase::system_error_text()),node); node = OOBase::allocate_shared<Render::SGNode>(parent,OOBase::static_pointer_cast<Render::SGDrawable>(quad),visible(),transform()); if (!node) LOG_ERROR_RETURN(("Failed to allocate: %s\n",OOBase::system_error_text()),node); return node; }
OOBase::SharedPtr<Indigo::Render::UIDrawable> Indigo::NinePatch::make_drawable(const glm::vec4& colour, bool visible, const glm::ivec2& position, const glm::uvec2& size) const { ASSERT_RENDER_THREAD(); if (!valid()) LOG_ERROR_RETURN(("NinePatch::make_drawable called when invalid!"),OOBase::SharedPtr<Indigo::Render::UIDrawable>()); bool is_9 = (m_info->m_borders != glm::uvec4(0)); bool cached = true; OOBase::SharedPtr<OOGL::Texture> texture = make_texture(GL_RGBA8,cached,is_9 ? 1 : 0); if (!texture) return OOBase::SharedPtr<Indigo::Render::UIDrawable>(); if (cached) { texture->parameter(GL_TEXTURE_MAG_FILTER,GL_LINEAR); texture->parameter(GL_TEXTURE_MIN_FILTER,is_9 ? GL_LINEAR : GL_LINEAR_MIPMAP_LINEAR); texture->parameter(GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); texture->parameter(GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); } if (is_9) return OOBase::allocate_shared<Render::UINinePatch,OOBase::ThreadLocalAllocator>(texture,colour,m_info,visible,position,size); else return OOBase::allocate_shared<Render::UIImage,OOBase::ThreadLocalAllocator>(texture,colour,visible,position,size); }
void NinePatchFactory::layout_patch(GLsizei patch, const glm::uvec2& size, const glm::uvec4& borders, const glm::uvec2& tex_size) { static const unsigned int ushort_max = 0xFFFF; OOBase::SharedPtr<vertex_data> attribs = m_ptrVertices->auto_map<vertex_data>(GL_MAP_WRITE_BIT,patch * vertices_per_patch * sizeof(vertex_data),vertices_per_patch * sizeof(vertex_data)); vertex_data* a = attribs.get(); a[0].x = 0.f; a[1].x = static_cast<float>(borders.x); a[3].x = static_cast<float>(size.x); a[2].x = a[3].x - borders.z; a[0].u = 0; a[1].u = static_cast<GLushort>(static_cast<float>(borders.x) / tex_size.x * ushort_max); a[2].u = static_cast<GLushort>(static_cast<float>(tex_size.x - borders.z) / tex_size.x * ushort_max); a[3].u = ushort_max; for (size_t i=0;i<4;++i) { a[i+12].x = a[i+8].x = a[i+4].x = a[i].x; a[i].y = static_cast<float>(size.y); a[i+4].y = a[i].y - borders.y; a[i+8].y = static_cast<float>(borders.w); a[i+12].y = 0.f; a[i+12].u = a[i+8].u = a[i+4].u = a[i].u; a[i].v = 0; a[i+4].v = static_cast<GLushort>(static_cast<float>(borders.w) / tex_size.y * ushort_max); a[i+8].v = static_cast<GLushort>(static_cast<float>(tex_size.y - borders.y) / tex_size.y * ushort_max); a[i+12].v = ushort_max; } }
bool Indigo::UIPanel::on_render_create(Indigo::Render::UIGroup* group) { if (m_background) { OOBase::SharedPtr<Render::UIDrawable> bk = m_background->make_drawable(m_colour,true,glm::ivec2(),size()); if (!bk) return false; if (!group->add_drawable(bk)) return false; m_render_background = bk.get(); } OOBase::SharedPtr<Indigo::Render::UIGroup> subgroup = OOBase::allocate_shared<Indigo::Render::UIGroup,OOBase::ThreadLocalAllocator>(true,glm::ivec2(),size()) ; if (!subgroup) LOG_ERROR_RETURN(("Failed to allocate: %s",OOBase::system_error_text()),false); if (!group->add_drawable(subgroup)) return false; m_render_parent = subgroup.get(); return UIGroup::on_render_create(group); }
bool Indigo::run(const char* name, void (*fn)(void*), void* param) { // Create render comms pipe PIPE_RACK::instance().m_render_pipe = OOBase::allocate_shared<Indigo::Pipe,OOBase::ThreadLocalAllocator>("render"); if (!PIPE_RACK::instance().m_render_pipe) LOG_ERROR_RETURN(("Failed to allocate render pipe: %s",OOBase::system_error_text()),false); render_init(PIPE_RACK::instance().m_render_pipe.get()); // Not sure if we need to set this first... glfwSetErrorCallback(&on_glfw_error); if (!glfwInit()) LOG_ERROR_RETURN(("glfwInit failed"),false); // Set defaults glfwDefaultWindowHints(); bool ret = false; OOBase::SharedPtr<OOBase::Thread> thread; PIPE_RACK::instance().m_logic_pipe = Indigo::start_thread(name,thread); if (PIPE_RACK::instance().m_logic_pipe) { ret = PIPE_RACK::instance().m_logic_pipe->call(OOBase::make_delegate<OOBase::ThreadLocalAllocator>(fn),param); if (ret) thread->join(); } glfwTerminate(); return ret; }
bool Indigo::NinePatch::load(const ResourceBundle& resource, const char* name, int components) { OOBase::SharedPtr<const unsigned char> buffer = resource.load<unsigned char>(name); if (!buffer) return false; return this->load(buffer.get(),resource.size(name),components); }
void Indigo::Render::UILayer::on_losecursor() { for (OOBase::Vector<OOBase::WeakPtr<UIDrawable>,OOBase::ThreadLocalAllocator>::iterator i=m_cursor_hits.begin();i;++i) { OOBase::SharedPtr<UIDrawable> d = i->lock(); if (d) d->on_cursorenter(false); } m_cursor_hits.clear(); }
void Indigo::Render::UILayer::on_mousebutton(const OOGL::Window::mouse_click_t& click) { bool handled = false; for (OOBase::Vector<OOBase::WeakPtr<UIDrawable>,OOBase::ThreadLocalAllocator>::iterator i=m_cursor_hits.begin();!handled && i;++i) { OOBase::SharedPtr<UIDrawable> d = i->lock(); if (d) handled = d->on_mousebutton(click); } }
glm::vec4 Indigo::ImageLayer::colour(const glm::vec4& colour) { glm::vec4 prev_colour = m_colour; if (colour != prev_colour) { OOBase::SharedPtr< ::ImageLayer> layer = OOBase::static_pointer_cast< ::ImageLayer>(render_layer()); if (layer) render_pipe()->post(OOBase::make_delegate<OOBase::ThreadLocalAllocator>(layer.get(),&::ImageLayer::colour),colour); } return prev_colour; }
bool Indigo::ZipResource::open(const char* filename) { OOBase::SharedPtr<detail::ZipFile> zip = OOBase::allocate_shared<detail::ZipFile>(); if (!zip) LOG_ERROR_RETURN(("Failed to allocate: %s",OOBase::system_error_text()),false); bool r = zip->open(filename); if (r) zip.swap(m_zip); return r; }
void Indigo::Render::UIGroup::add_subgroup(UIWidget* widget, bool* ret) { *ret = false; OOBase::SharedPtr<Render::UIGroup> group = OOBase::allocate_shared<Render::UIGroup,OOBase::ThreadLocalAllocator>((widget->state() & Indigo::UIWidget::eWS_visible) != 0,widget->position(),widget->size()); if (!group) LOG_ERROR(("Failed to allocate group: %s",OOBase::system_error_text())); else if (!m_children.push_back(group)) LOG_ERROR(("Failed to insert group: %s",OOBase::system_error_text())); else if (!widget->on_render_create(group.get())) m_children.pop_back(); else { widget->m_render_group = group.get(); *ret = true; } }
OOBase::SharedPtr<Indigo::Render::Layer> Indigo::UILayer::create_render_layer(Indigo::Render::Window* window) { glm::uvec2 sz(window->window()->size()); if (sz != size()) Indigo::logic_pipe()->call(OOBase::make_delegate<OOBase::ThreadLocalAllocator>(this,&Indigo::UILayer::on_layout),sz); OOBase::SharedPtr<Indigo::Render::UILayer> group = OOBase::allocate_shared<Indigo::Render::UILayer,OOBase::ThreadLocalAllocator>(window,this,visible(),position(),size()); if (!group) LOG_ERROR(("Failed to allocate group: %s",OOBase::system_error_text())); else if (!on_render_create(group.get())) group.reset(); m_render_parent = group.get(); return OOBase::static_pointer_cast<Indigo::Render::Layer>(group); }
OOBase::SharedPtr<Indigo::Render::Layer> Indigo::ImageLayer::create_render_layer(Render::Window* window) { OOBase::SharedPtr< ::ImageLayer> layer; bool cached = true; OOBase::SharedPtr<OOGL::Texture> texture = m_image->make_texture(GL_RGBA8,cached,1); if (!texture) return layer; if (!cached) { texture->parameter(GL_TEXTURE_MAG_FILTER,GL_LINEAR); texture->parameter(GL_TEXTURE_MIN_FILTER,GL_LINEAR); texture->parameter(GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); texture->parameter(GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); } layer = OOBase::allocate_shared< ::ImageLayer,OOBase::ThreadLocalAllocator>(texture,window,m_colour); if (!layer) LOG_ERROR(("Failed to allocate layer: %s",OOBase::system_error_text())); return layer; }
void Indigo::UIDialog::internal_do_modal(Window& wnd, const OOBase::SharedPtr<UILayer>& layer) { if (!layer) LOG_WARNING(("No layer assigned to dialog!")); else { OOBase::Delegate0<void,OOBase::ThreadLocalAllocator> prev_close = layer->on_close(OOBase::make_delegate<OOBase::ThreadLocalAllocator>(this,&UIDialog::on_window_close)); if (wnd.add_layer(layer)) { layer->show(true); wnd.show(); for (m_live = true; m_live;) thread_pipe()->get(); layer->show(false); wnd.remove_layer(layer); } layer->on_close(prev_close); } }
void OOGL::VertexArrayObject::attribute(GLuint index, const OOBase::SharedPtr<BufferObject>& buffer, GLint components, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset) { m_state->bind(shared_from_this()); assert(buffer->target() == GL_ARRAY_BUFFER); m_state->bind(buffer); m_state_fns->glVertexAttribPointer(index,components,type,normalized ? GL_TRUE : GL_FALSE,stride,reinterpret_cast<const GLvoid*>(offset)); OOBase::Table<GLuint,OOBase::SharedPtr<BufferObject>,OOBase::Less<GLuint>,OOBase::ThreadLocalAllocator>::iterator i = m_attributes.find(index); if (i) i->second = buffer; else m_attributes.insert(index,buffer); }
static OOBase::SharedPtr<Indigo::detail::IPC::Queue> register_queue(const char* name) { OOBase::SharedPtr<Indigo::detail::IPC::Queue> queue; PipeTable::table_t::iterator i = PIPE_TABLE::instance().m_queues.find(name); if (i == PIPE_TABLE::instance().m_queues.end()) { OOBase::String str; if (!str.assign(name)) LOG_ERROR_RETURN(("Failed to assign string: %s",OOBase::system_error_text()),queue); queue = OOBase::allocate_shared<Indigo::detail::IPC::Queue>(); if (!queue) LOG_ERROR_RETURN(("Failed to allocate queue: %s",OOBase::system_error_text()),queue); i = PIPE_TABLE::instance().m_queues.insert(str,queue); if (i == PIPE_TABLE::instance().m_queues.end()) { LOG_ERROR(("Failed to insert queue: %s",OOBase::system_error_text())); queue.reset(); } } return i->second; }
bool Indigo::Render::UILayer::on_cursormove(const glm::dvec2& pos) { if (!visible()) return false; const glm::uvec2& sz = size(); glm::ivec2 ipos = glm::clamp(glm::ivec2(glm::floor(pos)),glm::ivec2(0),glm::ivec2(sz.x-1,sz.y-1)); OOBase::Vector<OOBase::WeakPtr<UIDrawable>,OOBase::ThreadLocalAllocator> hits; hit_test(hits,ipos); for (OOBase::Vector<OOBase::WeakPtr<UIDrawable>,OOBase::ThreadLocalAllocator>::iterator i=m_cursor_hits.begin();i;) { if (hits.find(*i)) ++i; else { OOBase::SharedPtr<UIDrawable> d = i->lock(); i = m_cursor_hits.erase(i); if (d && d->on_cursorenter(false)) break; } } for (OOBase::Vector<OOBase::WeakPtr<UIDrawable>,OOBase::ThreadLocalAllocator>::iterator i=hits.begin();i;++i) { if (m_cursor_hits.remove(*i) == 0) { OOBase::SharedPtr<UIDrawable> d = i->lock(); if (d && d->on_cursorenter(true)) break; } } m_cursor_hits.swap(hits); bool handled = false; for (OOBase::Vector<OOBase::WeakPtr<UIDrawable>,OOBase::ThreadLocalAllocator>::iterator i=m_cursor_hits.begin();!handled && i;) { OOBase::SharedPtr<UIDrawable> d = i->lock(); if (!d) m_cursor_hits.erase(i); else { handled = d->on_cursormove(); ++i; } } return m_owner->m_modal || handled; }
bool operator ()(const OOBase::SharedPtr<wchar_t>& s1, const OOBase::SharedPtr<wchar_t>& s2) const { return (_wcsicmp(s1.get(),s2.get()) < 0); }
GLsizei NinePatchFactory::alloc_patch(const glm::uvec2& size, const glm::uvec4& borders, const glm::uvec2& tex_size) { GLsizei patch = -1; for (free_list_t::iterator i=m_listFree.begin(); i; ++i) { if (i->second == 1) { patch = i->first; m_listFree.erase(i); break; } else if (i->second > 1) { patch = i->first; i->first += 1; i->second -= 1; break; } } if (patch == -1) { if (!m_ptrProgram && !create_program()) return patch; if (!m_ptrVAO) { m_ptrVAO = OOBase::allocate_shared<OOGL::VertexArrayObject,OOBase::ThreadLocalAllocator>(); if (!m_ptrVAO) LOG_ERROR_RETURN(("Failed to allocate VAO: %s",OOBase::system_error_text(ERROR_OUTOFMEMORY)),patch); } m_ptrVAO->bind(); GLsizei new_size = 16; while (new_size < m_allocated + 1) new_size *= 2; OOBase::SharedPtr<OOGL::BufferObject> ptrNewVertices = OOBase::allocate_shared<OOGL::BufferObject,OOBase::ThreadLocalAllocator>(GL_ARRAY_BUFFER,GL_DYNAMIC_DRAW,new_size * vertices_per_patch * sizeof(vertex_data)); OOBase::SharedPtr<OOGL::BufferObject> ptrNewElements = OOBase::allocate_shared<OOGL::BufferObject,OOBase::ThreadLocalAllocator>(GL_ELEMENT_ARRAY_BUFFER,GL_DYNAMIC_DRAW,new_size * elements_per_patch * sizeof(GLuint)); if (!ptrNewVertices || !ptrNewElements) LOG_ERROR_RETURN(("Failed to allocate VBO: %s",OOBase::system_error_text(ERROR_OUTOFMEMORY)),patch); if (m_ptrVertices) ptrNewVertices->copy(0,m_ptrVertices,0,m_allocated * vertices_per_patch * sizeof(vertex_data)); if (m_ptrElements) ptrNewElements->copy(0,m_ptrElements,0,m_allocated * elements_per_patch * sizeof(GLuint)); m_ptrVertices.swap(ptrNewVertices); m_ptrElements.swap(ptrNewElements); free_list_t::iterator last = m_listFree.back(); if (last) last->second += new_size - m_allocated; else last = m_listFree.insert(m_allocated,new_size - m_allocated); m_allocated = new_size; patch = last->first; last->first += 1; last->second -= 1; GLint a = m_ptrProgram->attribute_location("in_Position"); m_ptrVAO->attribute(a,m_ptrVertices,2,GL_FLOAT,false,sizeof(vertex_data),offsetof(vertex_data,x)); m_ptrVAO->enable_attribute(a); a = m_ptrProgram->attribute_location("in_TexCoord"); if (a != -1) { m_ptrVAO->attribute(a,m_ptrVertices,2,GL_UNSIGNED_SHORT,true,sizeof(vertex_data),offsetof(vertex_data,u)); m_ptrVAO->enable_attribute(a); } m_ptrVAO->element_array(m_ptrElements); m_ptrVAO->unbind(); } OOBase::SharedPtr<GLuint> ei = m_ptrElements->auto_map<GLuint>(GL_MAP_WRITE_BIT,patch * elements_per_patch * sizeof(GLuint),elements_per_patch * sizeof(GLuint)); GLuint* e = ei.get(); GLuint idx = patch * vertices_per_patch; for (size_t i=0;i<12;++i) { e[i*2] = static_cast<GLuint>(idx + i); e[i*2 + 1] = static_cast<GLuint>(idx + i + 4); } layout_patch(patch,size,borders,tex_size); return patch; }
bool Indigo::UIGroup::add_widget(const OOBase::SharedPtr<UIWidget>& widget, const char* name, size_t len) { if (!m_children.push_back(widget)) LOG_ERROR_RETURN(("Failed to insert widget: %s",OOBase::system_error_text()),false); if (name && len && !add_named_widget(widget,name,len)) { m_children.pop_back(); return false; } if (!m_render_group) return true; bool ret = false; if (!render_pipe()->call(OOBase::make_delegate<OOBase::ThreadLocalAllocator>(m_render_parent,&Render::UIGroup::add_subgroup),widget.get(),&ret) || !ret) m_children.pop_back(); return ret; }
OOBase::SharedPtr<const char> Indigo::detail::ZipFile::load(const OOBase::String& prefix, const char* name) { OOBase::SharedPtr<const char> ret; OOBase::String filename(prefix); if (!filename.append(name)) LOG_ERROR_RETURN(("Failed to append string: %s",OOBase::system_error_text()),ret); OOBase::Table<OOBase::String,Info>::iterator i=m_mapFiles.find(filename); if (!i) return ret; // Read the local file header if (m_file.seek(i->second.m_offset,OOBase::File::seek_begin) == OOBase::uint64_t(-1)) LOG_ERROR_RETURN(("Failed to get seek in file: %s",OOBase::system_error_text()),ret); OOBase::uint8_t header[30]; if (m_file.read(header,30) != 30) LOG_ERROR_RETURN(("Failed to read local file header header in zip"),ret); static const OOBase::uint8_t LFR_HEADER[4] = { 0x50, 0x4b, 0x03, 0x04 }; if (memcmp(header,LFR_HEADER,4) != 0) LOG_ERROR_RETURN(("Invalid local file header header in zip"),ret); OOBase::uint16_t compression = read_uint16(header,8); OOBase::uint32_t compressed_size = read_uint32(header,18); size_t offset = 30 + read_uint16(header,26) + read_uint16(header,28); OOBase::SharedPtr<const char> mapping = m_file.auto_map<const char>(false,i->second.m_offset + offset,compressed_size); if (!mapping) LOG_ERROR_RETURN(("Failed to map file content: %s",OOBase::system_error_text()),ret); if (compression == 0) { ret = mapping; } else if (compression == 8) { void* p = OOBase::CrtAllocator::allocate(i->second.m_length,1); if (!p) LOG_ERROR_RETURN(("Failed to allocate: %s",OOBase::system_error_text()),ret); if (stbi_zlib_decode_noheader_buffer(static_cast<char*>(p),(int)i->second.m_length,mapping.get(),(int)compressed_size) == -1) { LOG_ERROR(("Failed to inflate file: %s",stbi_failure_reason())); OOBase::CrtAllocator::free(p); } else { ret = OOBase::const_pointer_cast<const char>(OOBase::make_shared<char>(static_cast<char*>(p))); if (!ret) { LOG_ERROR(("Failed to allocate: %s",OOBase::system_error_text())); OOBase::CrtAllocator::free(p); } } } else LOG_ERROR(("Unsupported zip compression method: %u",compression)); return ret; }