X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2F3d%2Foverlay.cpp;fp=source%2F3d%2Foverlay.cpp;h=5f07ac81a6d04ad97bb81ee696b629f8ab965c8a;hb=a861c2729a356173059177a0b800de2b31c9b49c;hp=0000000000000000000000000000000000000000;hpb=e07c0d862a4d43b2585c93e79d25380d00675309;p=r2c2.git diff --git a/source/3d/overlay.cpp b/source/3d/overlay.cpp new file mode 100644 index 0000000..5f07ac8 --- /dev/null +++ b/source/3d/overlay.cpp @@ -0,0 +1,202 @@ +/* $Id$ + +This file is part of the MSP Märklin suite +Copyright © 2010 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#include +#include +#include +#include +#include +#include +#include "overlay.h" +#include "track.h" +#include "tracktype.h" + +using namespace std; +using namespace Msp; + +namespace Marklin { + +Overlay3D::Overlay3D(const Graphics::Window &w, const GL::Camera &c, const GL::Font &f): + window(w), + camera(c), + font(f) +{ } + +Overlay3D::~Overlay3D() +{ + for(map::iterator i=graphics.begin(); i!=graphics.end(); ++i) + delete i->second; +} + +void Overlay3D::set_label(const Track3D &track, const string &label) +{ + get_icon(track).label = label; + update_icon(get_icon(track)); +} + +void Overlay3D::add_graphic(const Track3D &track, const string &grf_name) +{ + const GL::Mesh *grf = get_graphic(grf_name); + if(!grf) + return; + + Icon &icon = get_icon(track); + if(find(icon.graphics.begin(), icon.graphics.end(), grf)==icon.graphics.end()) + icon.graphics.push_back(grf); + + update_icon(icon); +} + +void Overlay3D::remove_graphic(const Track3D &track, const string &grf_name) +{ + const GL::Mesh *grf = get_graphic(grf_name); + Icon &icon = get_icon(track); + icon.graphics.erase(remove(icon.graphics.begin(), icon.graphics.end(), grf), icon.graphics.end()); + + update_icon(icon); +} + +void Overlay3D::clear_graphics(const Track3D &track) +{ + get_icon(track).graphics.clear(); + update_icon(get_icon(track)); +} + +void Overlay3D::clear(const Track3D &track) +{ + map::iterator i = icons.find(&track); + if(i!=icons.end()) + { + delete i->second; + icons.erase(i); + } +} + +void Overlay3D::render(const GL::Tag &tag) const +{ + if(tag==0) + { + GL::matrix_mode(GL::PROJECTION); + GL::push_matrix(); + GL::load_identity(); + GL::scale(2.0/window.get_width(), 2.0/window.get_height(), 1.0); + GL::matrix_mode(GL::MODELVIEW); + GL::push_matrix(); + GL::load_identity(); + + glLineWidth(1); + + int size = int(font.get_default_size()+0.5); + float spacing = round(size*1.1)/size; + float baseline = round((0.5-font.get_ascent()*0.5-font.get_descent()*0.5)*size)/size; + + for(map::const_iterator i=icons.begin(); i!=icons.end(); ++i) + { + const Icon &icon = *i->second; + + const Point &pos = i->first->get_track().get_position(); + Point minp; + Point maxp; + i->first->get_type().get_bounds(0, minp, maxp); + float rot = i->first->get_track().get_rotation(); + float c = cos(rot); + float s = sin(rot); + + GL::Vector3 p((minp.x+maxp.x)/2, (minp.y+maxp.y)/2, 0); + p = GL::Vector3(pos.x+c*p.x-s*p.y, pos.y+s*p.x+c*p.y, pos.z+0.02); + p = camera.project(p); + + GL::PushMatrix push_mat; + p.x = int(p.x*0.5*window.get_width()-icon.width*size/2); + p.y = int(p.y*0.5*window.get_height()); + GL::translate(p.x, p.y, p.z); + GL::scale_uniform(size); + + icon.background.draw(); + + glColor3f(0.0, 1.0, 0.0); + for(vector::const_iterator j=icon.graphics.begin(); j!=icon.graphics.end(); ++j) + { + (*j)->draw(); + GL::translate(spacing, 0, 0); + } + + GL::translate(0, baseline, 0); + font.draw_string(icon.label); + GL::Texture::unbind(); + } + + GL::matrix_mode(GL::PROJECTION); + GL::pop_matrix(); + GL::matrix_mode(GL::MODELVIEW); + GL::pop_matrix(); + } +} + +Overlay3D::Icon &Overlay3D::get_icon(const Track3D &track) +{ + Icon *&icon = icons[&track]; + if(!icon) + icon = new Icon; + + return *icon; +} + +const GL::Mesh *Overlay3D::get_graphic(const string &name) +{ + GL::Mesh *&grf = graphics[name]; + if(!grf) + { + grf = new GL::Mesh; + try + { + DataFile::load(*grf, (FS::Path("icons")/(name+".mesh")).str()); + } + catch(const Exception &e) + { + IO::print("Error loading overlay graphic '%s': %s\n", name, e.what()); + delete grf; + grf = 0; + } + } + + return grf; +} + +void Overlay3D::update_icon(Icon &icon) +{ + icon.background.clear(); + + icon.width = max(icon.graphics.size()*1.1+font.get_string_width(icon.label), 1.0); + + GL::MeshBuilder bld(icon.background); + bld.color(0.2f, 0.2f, 0.2f, 0.7f); + + bld.begin(GL::TRIANGLE_FAN); + bld.vertex(0.4, 0.5); + bld.vertex(icon.width-0.4, 0.5); + bld.vertex(icon.width-0.4, 1.2); + for(int i=4; i<=12; ++i) + bld.vertex(0.4+cos(i*M_PI/8)*0.7, 0.5+sin(i*M_PI/8)*0.7); + bld.end(); + + bld.begin(GL::TRIANGLE_FAN); + bld.vertex(icon.width-0.4, 0.5); + bld.vertex(0.4, 0.5); + bld.vertex(0.4, -0.2); + for(int i=-4; i<=4; ++i) + bld.vertex(icon.width-0.4+cos(i*M_PI/8)*0.7, 0.5+sin(i*M_PI/8)*0.7); + bld.end(); +} + + +Overlay3D::Icon::Icon(): + width(1.0), + background((GL::COLOR4_UBYTE, GL::VERTEX2)) +{ } + +} // namespace Marklin