16 using std::shared_ptr;
21 static void intersect(
int xa,
int ya,
int wa,
int ha,
22 int xb,
int yb,
int wb,
int hb,
23 int& x,
int& y,
int& w,
int& h)
25 int x1 = std::max<int>(xa, xb);
26 int y1 = std::max<int>(ya, yb);
27 int x2 = std::min<int>(xa + wa, xb + wb);
28 int y2 = std::min<int>(ya + ha, yb + hb);
31 w = std::max(0, x2 - x1);
32 h = std::max(0, y2 - y1);
37 static void normalize(
int& x,
int& w)
57 : surface(output.getSDLWorkSurface())
59 normalize(x, w); normalize(y, h);
60 SDL_GetClipRect(surface, &origClip);
63 intersect(origClip.x, origClip.y, origClip.w, origClip.h,
66 SDL_Rect newClip = { Sint16(xn), Sint16(yn), Uint16(wn), Uint16(hn) };
67 SDL_SetClipRect(surface, &newClip);
72 SDL_SetClipRect(surface, &origClip);
92 normalize(x, w); normalize(y, h);
95 wasEnabled = glIsEnabled(GL_SCISSOR_TEST);
96 if (wasEnabled == GL_TRUE) {
97 glGetIntegerv(GL_SCISSOR_BOX, &xo);
99 intersect(xo, yo, wo, ho,
102 glScissor(xn, yn, wn, hn);
104 glScissor(x, y, w, h);
105 glEnable(GL_SCISSOR_TEST);
111 if (wasEnabled == GL_TRUE) {
112 glScissor(xo, yo, wo, ho);
114 glDisable(GL_SCISSOR_TEST);
125 , x(0.0), y(0.0), z(0.0)
126 , relx(0.0), rely(0.0)
129 , suppressErrors(false)
152 void OSDWidget::setParent(
OSDWidget* parent_)
164 auto it = subWidgetsMap.
find(first);
165 return it == subWidgetsMap.
end() ?
nullptr : it->
second->findSubWidget(last);
175 widget->setParent(
this);
176 subWidgetsMap[widget->getName()] = widget.get();
186 double z = widget->getZ();
187 if (subWidgets.empty() || (subWidgets.back()->getZ() <= z)) {
188 subWidgets.push_back(widget);
190 auto it = subWidgets.begin();
191 while ((*it)->getZ() <= z) ++it;
192 subWidgets.insert(it, widget);
199 string widgetName = widget.
getName();
200 for (
auto it = subWidgets.begin(); it != subWidgets.end(); ++it) {
201 if (it->get() == &widget) {
202 subWidgets.erase(it);
203 auto existed = subWidgetsMap.
erase(widgetName);
204 assert(existed); (void)existed;
213 bool operator()(
const shared_ptr<OSDWidget>& lhs,
214 const shared_ptr<OSDWidget>& rhs)
const {
215 return lhs->getZ() < rhs->getZ();
219 void OSDWidget::resortUp(OSDWidget* elem)
222 auto it1 = subWidgets.begin();
223 while (it1->get() != elem) ++it1;
225 double z = elem->getZ();
228 while ((it2 != subWidgets.end()) && ((*it2)->getZ() < z)) ++it2;
230 rotate(it1, it1 + 1, it2);
232 assert(std::is_sorted(subWidgets.begin(), subWidgets.end(), AscendingZ()));
235 void OSDWidget::resortDown(OSDWidget* elem)
238 auto it1 = subWidgets.begin();
239 double z = elem->getZ();
240 while ((*it1)->getZ() <= z) {
242 if (it1 == subWidgets.end())
return;
246 if ((it2 != subWidgets.begin()) && ((it2 - 1)->get() == elem))
return;
247 while (it2->get() != elem) ++it2;
249 rotate(it1, it2, it2 + 1);
251 assert(std::is_sorted(subWidgets.begin(), subWidgets.end(), AscendingZ()));
257 static const char*
const vals[] = {
258 "-type",
"-x",
"-y",
"-z",
"-relx",
"-rely",
"-scaled",
259 "-clip",
"-mousecoord",
"-suppressErrors",
261 return vector<string_ref>(std::begin(vals), std::end(vals));
266 if (name ==
"-type") {
268 }
else if (name ==
"-mousecoord") {
270 }
else if (name ==
"-x") {
272 }
else if (name ==
"-y") {
274 }
else if (name ==
"-z") {
282 parent->resortUp(
this);
284 parent->resortDown(
this);
288 }
else if (name ==
"-relx") {
290 }
else if (name ==
"-rely") {
292 }
else if (name ==
"-scaled") {
294 if (scaled != scaled2) {
298 }
else if (name ==
"-clip") {
300 }
else if (name ==
"-suppressErrors") {
309 if (name ==
"-type") {
311 }
else if (name ==
"-x") {
313 }
else if (name ==
"-y") {
315 }
else if (name ==
"-z") {
317 }
else if (name ==
"-relx") {
319 }
else if (name ==
"-rely") {
321 }
else if (name ==
"-scaled") {
323 }
else if (name ==
"-clip") {
325 }
else if (name ==
"-mousecoord") {
330 }
else if (name ==
"-suppressErrors") {
350 for (
auto& s : subWidgets) {
351 s->invalidateRecursive();
357 if (suppressErrors)
return true;
368 std::unique_ptr<SDLScopedClip> scopedClip;
372 scopedClip = make_unique<SDLScopedClip>(output, x, y, w, h);
379 auto copy = subWidgets;
380 for (
auto& s : copy) {
381 s->paintSDLRecursive(output);
391 std::unique_ptr<GLScopedClip> scopedClip;
395 scopedClip = make_unique<GLScopedClip>(output, x, y, w, h);
398 auto copy = subWidgets;
399 for (
auto& s : copy) {
400 s->paintGLRecursive(output);
417 double x,
double y,
double relx,
double rely,
418 double& outx,
double& outy)
const
420 double width, height;
423 outx = x + factor *
getX() + relx * width;
424 outy = y + factor *
getY() + rely * height;
431 void OSDWidget::transformReverse(
433 double& outx,
double& outy)
const
436 parent->transformReverse(output, x, y, x, y);
437 double width, height;
440 outx = x - (
getRelX() * width ) - (
getX() * factor);
441 outy = y - (
getRelY() * height) - (
getY() * factor);
448 void OSDWidget::getMouseCoord(
double& outx,
double& outy)
const
450 if (SDL_ShowCursor(SDL_QUERY) == SDL_DISABLE) {
466 outx = std::numeric_limits<double>::infinity();
467 outy = std::numeric_limits<double>::infinity();
471 SDL_Surface* surface = SDL_GetVideoSurface();
473 throw CommandException(
474 "Can't get mouse coordinates: no window visible");
476 DummyOutputRectangle output(surface->w, surface->h);
479 SDL_GetMouseState(&mouseX, &mouseY);
481 transformReverse(output, mouseX, mouseY, outx, outy);
483 double width, height;
485 if ((width == 0) || (height == 0)) {
486 throw CommandException(
487 "-can't get mouse coordinates: "
488 "widget has zero width or height");
495 int& x,
int& y,
int& w,
int& h)
497 double x1, y1, x2, y2;
502 w = int(x2 - x1 + 0.5);
503 h = int(y2 - y1 + 0.5);
506 void OSDWidget::listWidgetNames(
const string& parentName, vector<string>& result)
const
508 string pname = parentName;
509 if (!pname.empty()) pname +=
'.';
510 for (
auto& s : subWidgets) {
511 string name = pname + s->getName();
512 result.push_back(name);
513 s->listWidgetNames(name, result);