void Interface::Draw(const Information &info, const Point &offset) const { Point corner(Screen::Width() * position.X(), Screen::Height() * position.Y()); corner += offset; for(const SpriteSpec &sprite : sprites) { if(!info.HasCondition(sprite.condition)) continue; const Sprite *s = sprite.sprite; if(!s) s = info.GetSprite(sprite.name); if(!s) continue; Point offset( s->Width() * position.X(), s->Height() * position.Y()); double zoom = 1.; if(sprite.size.X() && sprite.size.Y()) zoom = min(1., min(sprite.size.X() / s->Width(), sprite.size.Y() / s->Height())); SpriteShader::Draw(s, sprite.position + corner - offset, zoom); } for(const SpriteSpec &outline : outlines) { if(!info.HasCondition(outline.condition)) continue; const Sprite *s = outline.sprite; if(!s) s = info.GetSprite(outline.name); if(!s) continue; Point size(s->Width(), s->Height()); if(outline.size.X() && outline.size.Y()) size *= min(outline.size.X() / s->Width(), outline.size.Y() / s->Height()); Point pos = outline.position + corner - outline.size * position; OutlineShader::Draw(s, pos, size, outline.isColored ? info.GetOutlineColor() : Color(1., 1.), info.GetSpriteUnit(outline.name)); } double defaultAlign = position.X() + .5; for(const StringSpec &spec : labels) { if(!info.HasCondition(spec.condition) || !spec.color) continue; const string &str = spec.str; const Font &font = FontSet::Get(spec.size); double a = (spec.align >= 0.) ? spec.align : defaultAlign; Point align(font.Width(str) * a, 0.); font.Draw(str, corner - align + spec.position, *spec.color); } for(const StringSpec &spec : strings) { if(!info.HasCondition(spec.condition) || !spec.color) continue; const string &str = info.GetString(spec.str); const Font &font = FontSet::Get(spec.size); double a = (spec.align >= 0.) ? spec.align : defaultAlign; Point align(font.Width(str) * a, 0.); font.Draw(str, corner - align + spec.position, *spec.color); } for(const BarSpec &spec : bars) { if(!info.HasCondition(spec.condition) || !spec.color) continue; double length = spec.size.Length(); if(!length || !spec.width) continue; double value = info.BarValue(spec.name); double segments = info.BarSegments(spec.name); if(!value) continue; // We will have (segments - 1) gaps between the segments. double empty = segments ? (spec.width / length) : 0.; double filled = segments ? (1. - empty * (segments - 1.)) / segments : 1.; double v = 0.; Point start = spec.position + corner; while(v < value) { Point from = start + v * spec.size; v += filled; Point to = start + min(v, value) * spec.size; v += empty; LineShader::Draw(from, to, spec.width, *spec.color); } } for(const BarSpec &spec : rings) { if(!info.HasCondition(spec.condition) || !spec.color) continue; if(!spec.size.X() || !spec.size.Y() || !spec.width) continue; double value = info.BarValue(spec.name); double segments = info.BarSegments(spec.name); if(!value) continue; if(segments <= 1.) segments = 0.; Point center = spec.position + corner - spec.size * position; RingShader::Draw(center, .5 * spec.size.X(), spec.width, value, *spec.color, segments); } }