Add Chromium-only Blender WebEngine parity work
This commit is contained in:
589
blender-5.2.0/extern/opensubdiv-source/examples/common/hud.cpp
vendored
Normal file
589
blender-5.2.0/extern/opensubdiv-source/examples/common/hud.cpp
vendored
Normal file
@@ -0,0 +1,589 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include "hud.h"
|
||||
#include "font_image.h"
|
||||
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
Hud::Hud() : _visible(true), _windowWidth(0), _windowHeight(0),
|
||||
_framebufferWidth(0), _framebufferHeight(0),
|
||||
_requiresRebuildStatic(true)
|
||||
{
|
||||
_capturedSlider = -1;
|
||||
}
|
||||
|
||||
Hud::~Hud()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Hud::Init(int width, int height, int framebufferWidth, int framebufferHeight)
|
||||
{
|
||||
_windowWidth = width;
|
||||
_windowHeight = height;
|
||||
_framebufferWidth = framebufferWidth;
|
||||
_framebufferHeight = framebufferHeight;
|
||||
}
|
||||
|
||||
int
|
||||
Hud::GetWidth() const
|
||||
{
|
||||
return _windowWidth;
|
||||
}
|
||||
|
||||
int
|
||||
Hud::GetHeight() const
|
||||
{
|
||||
return _windowHeight;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::Clear()
|
||||
{
|
||||
_radioButtons.clear();
|
||||
_checkBoxes.clear();
|
||||
_sliders.clear();
|
||||
_vboSource.clear();
|
||||
_requiresRebuildStatic = true;
|
||||
}
|
||||
|
||||
bool
|
||||
Hud::KeyDown(int key)
|
||||
{
|
||||
for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
|
||||
it != _radioButtons.end(); ++it) {
|
||||
if (key == it->shortcut) {
|
||||
int nextLocalIndex = it->localIndex;
|
||||
if (it->sharedShortcut) {
|
||||
// find checked radio button in this group
|
||||
int maxLocalIndex = 0;
|
||||
for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
|
||||
it2 != _radioButtons.end(); ++it2) {
|
||||
|
||||
if (it2->group == it->group) {
|
||||
maxLocalIndex = std::max(maxLocalIndex, it2->localIndex);
|
||||
if (it2->checked) {
|
||||
nextLocalIndex = it2->localIndex+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nextLocalIndex > maxLocalIndex) nextLocalIndex = 0;
|
||||
}
|
||||
for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
|
||||
it2 != _radioButtons.end(); ++it2) {
|
||||
if (it2->group == it->group) {
|
||||
if (it2->localIndex == nextLocalIndex) {
|
||||
it2->checked = true;
|
||||
it2->callback(it2->callbackData);
|
||||
} else {
|
||||
it2->checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (std::vector<CheckBox>::iterator it = _checkBoxes.begin();
|
||||
it != _checkBoxes.end(); ++it) {
|
||||
|
||||
if (key == it->shortcut) {
|
||||
it->checked = !it->checked;
|
||||
it->callback(it->checked, it->callbackData);
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (std::vector<PullDown>::iterator it = _pulldowns.begin();
|
||||
it != _pulldowns.end(); ++it) {
|
||||
if (key==it->shortcut) {
|
||||
// cycle through selections
|
||||
++it->selected;
|
||||
if (it->selected>=(int)it->labels.size()) {
|
||||
it->selected=0;
|
||||
}
|
||||
it->callback(it->values[it->selected]);
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Hud::MouseClick(int x, int y)
|
||||
{
|
||||
if (!IsVisible()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
|
||||
it != _radioButtons.end(); ++it) {
|
||||
if (hitTest(*it, x, y)) {
|
||||
for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
|
||||
it2 != _radioButtons.end(); ++it2) {
|
||||
|
||||
if (it2->group == it->group && it != it2) it2->checked = false;
|
||||
}
|
||||
it->checked = true;
|
||||
it->callback(it->callbackData);
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (std::vector<CheckBox>::iterator it = _checkBoxes.begin();
|
||||
it != _checkBoxes.end(); ++it) {
|
||||
if (hitTest(*it, x, y)) {
|
||||
it->checked = !it->checked;
|
||||
it->callback(it->checked, it->callbackData);
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (std::vector<Slider>::iterator it = _sliders.begin();
|
||||
it != _sliders.end(); ++it) {
|
||||
if (hitTest(*it, x, y)) {
|
||||
int bx = 0, by = 0;
|
||||
getWindowPos(*it, &bx, &by);
|
||||
it->SetValue(((x-bx-FONT_CHAR_WIDTH/2)/float(it->w))*(it->max - it->min) + it->min);
|
||||
it->callback(it->value, it->callbackData);
|
||||
_capturedSlider = (int)(it - _sliders.begin());
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (std::vector<PullDown>::iterator it = _pulldowns.begin();
|
||||
it != _pulldowns.end(); ++it) {
|
||||
if (hitTest(*it, x, y)) {
|
||||
if (! it->open) {
|
||||
it->h = FONT_CHAR_HEIGHT;
|
||||
it->h *= (int)it->labels.size();
|
||||
it->open=true;
|
||||
} else {
|
||||
int label_width = (3+(int)it->label.size()) * FONT_CHAR_WIDTH;
|
||||
int bx = 0, by = 0;
|
||||
getWindowPos(*it, &bx, &by);
|
||||
if (x > (bx+label_width)) {
|
||||
int sel = it->selected;
|
||||
it->SetSelected((y-by)/FONT_CHAR_HEIGHT);
|
||||
if (it->selected!=sel) {
|
||||
it->callback(it->values[it->selected]);
|
||||
}
|
||||
} else {
|
||||
it->open=! it->open;
|
||||
}
|
||||
}
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::MouseMotion(int x, int /* y */)
|
||||
{
|
||||
if (_capturedSlider != -1) {
|
||||
std::vector<Slider>::iterator it = _sliders.begin() + _capturedSlider;
|
||||
|
||||
int bx = it->x > 0 ? it->x : _windowWidth + it->x;
|
||||
it->SetValue(((x-bx-FONT_CHAR_WIDTH/2)/float(it->w))*(it->max - it->min) + it->min);
|
||||
it->callback(it->value, it->callbackData);
|
||||
_requiresRebuildStatic = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Hud::MouseCapture() const
|
||||
{
|
||||
return _capturedSlider != -1;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::MouseRelease()
|
||||
{
|
||||
_capturedSlider = -1;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::AddLabel(const char *label, int x, int y)
|
||||
{
|
||||
Item l;
|
||||
l.label = label;
|
||||
l.x = x;
|
||||
l.y = y;
|
||||
|
||||
_labels.push_back(l);
|
||||
_requiresRebuildStatic = true;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::AddCheckBox(const char *label, bool checked, int x, int y,
|
||||
CheckBoxCallback callback, int data, int shortcut)
|
||||
{
|
||||
CheckBox cb;
|
||||
cb.label = label;
|
||||
cb.checked = checked;
|
||||
cb.x = x;
|
||||
cb.y = y;
|
||||
cb.w = (int)(strlen(label)+1) * FONT_CHAR_WIDTH;
|
||||
cb.h = FONT_CHAR_HEIGHT;
|
||||
cb.callback = callback;
|
||||
cb.callbackData = data;
|
||||
cb.shortcut = shortcut;
|
||||
|
||||
_checkBoxes.push_back(cb);
|
||||
_requiresRebuildStatic = true;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::AddRadioButton(int group, const char *label, bool checked, int x, int y,
|
||||
RadioButtonCallback callback, int data, int shortcut)
|
||||
{
|
||||
RadioButton rb;
|
||||
rb.group = group;
|
||||
rb.label = label;
|
||||
rb.checked = checked;
|
||||
rb.x = x;
|
||||
rb.y = y;
|
||||
rb.w = (int)(strlen(label)+1) * FONT_CHAR_WIDTH;
|
||||
rb.h = FONT_CHAR_HEIGHT;
|
||||
rb.callback = callback;
|
||||
rb.callbackData = data;
|
||||
rb.shortcut = shortcut;
|
||||
rb.sharedShortcut = false;
|
||||
rb.localIndex = 0;
|
||||
|
||||
for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
|
||||
it != _radioButtons.end(); ++it) {
|
||||
if (it->group == group) {
|
||||
rb.localIndex = it->localIndex+1;
|
||||
if (it->shortcut == shortcut) {
|
||||
it->sharedShortcut = true;
|
||||
rb.sharedShortcut = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_radioButtons.push_back(rb);
|
||||
_requiresRebuildStatic = true;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::AddSlider(const char *label, float min, float max, float value,
|
||||
int x, int y, int width, bool intStep, SliderCallback callback, int data)
|
||||
{
|
||||
Slider slider;
|
||||
slider.label = label;
|
||||
slider.x = x;
|
||||
slider.y = y;
|
||||
slider.w = width * FONT_CHAR_WIDTH;
|
||||
slider.h = FONT_CHAR_HEIGHT * 2;
|
||||
slider.min = min;
|
||||
slider.max = max;
|
||||
slider.value = value;
|
||||
slider.callback = callback;
|
||||
slider.callbackData = data;
|
||||
slider.intStep = intStep;
|
||||
|
||||
_sliders.push_back(slider);
|
||||
_requiresRebuildStatic = true;
|
||||
}
|
||||
|
||||
int
|
||||
Hud::AddPullDown(const char *label, int x, int y, int width,
|
||||
PullDownCallback callback, int shortcut)
|
||||
{
|
||||
|
||||
PullDown pd;
|
||||
pd.label = label;
|
||||
pd.x = x;
|
||||
pd.y = y;
|
||||
pd.w = width;
|
||||
pd.h = FONT_CHAR_HEIGHT;
|
||||
pd.open = false;
|
||||
pd.selected = 0;
|
||||
pd.callback = callback;
|
||||
pd.shortcut = shortcut;
|
||||
|
||||
_pulldowns.push_back(pd);
|
||||
_requiresRebuildStatic = true;
|
||||
|
||||
return (int)_pulldowns.size()-1;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::AddPullDownButton(int handle, const char *label, int value, bool checked)
|
||||
{
|
||||
if (handle < (int)_pulldowns.size()) {
|
||||
|
||||
PullDown & pulldown = _pulldowns[handle];
|
||||
|
||||
pulldown.labels.push_back(label);
|
||||
pulldown.values.push_back(value);
|
||||
if (checked) {
|
||||
pulldown.selected = (int)pulldown.labels.size()-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
Hud::drawChar(std::vector<float> &vboSource,
|
||||
int x, int y, float r, float g, float b, char ch)
|
||||
{
|
||||
const float w = 1.0f/FONT_TEXTURE_COLUMNS;
|
||||
const float h = 1.0f/FONT_TEXTURE_ROWS;
|
||||
|
||||
float u = (ch%FONT_TEXTURE_COLUMNS)/(float)FONT_TEXTURE_COLUMNS;
|
||||
float v = (ch/FONT_TEXTURE_COLUMNS)/(float)FONT_TEXTURE_ROWS;
|
||||
|
||||
vboSource.push_back(float(x));
|
||||
vboSource.push_back(float(y));
|
||||
vboSource.push_back(r);
|
||||
vboSource.push_back(g);
|
||||
vboSource.push_back(b);
|
||||
vboSource.push_back(u);
|
||||
vboSource.push_back(v);
|
||||
|
||||
vboSource.push_back(float(x));
|
||||
vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
|
||||
vboSource.push_back(r);
|
||||
vboSource.push_back(g);
|
||||
vboSource.push_back(b);
|
||||
vboSource.push_back(u);
|
||||
vboSource.push_back(v+h);
|
||||
|
||||
vboSource.push_back(float(x+FONT_CHAR_WIDTH));
|
||||
vboSource.push_back(float(y));
|
||||
vboSource.push_back(r);
|
||||
vboSource.push_back(g);
|
||||
vboSource.push_back(b);
|
||||
vboSource.push_back(u+w);
|
||||
vboSource.push_back(v);
|
||||
|
||||
vboSource.push_back(float(x+FONT_CHAR_WIDTH));
|
||||
vboSource.push_back(float(y));
|
||||
vboSource.push_back(r);
|
||||
vboSource.push_back(g);
|
||||
vboSource.push_back(b);
|
||||
vboSource.push_back(u+w);
|
||||
vboSource.push_back(v);
|
||||
|
||||
vboSource.push_back(float(x));
|
||||
vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
|
||||
vboSource.push_back(r);
|
||||
vboSource.push_back(g);
|
||||
vboSource.push_back(b);
|
||||
vboSource.push_back(u);
|
||||
vboSource.push_back(v+h);
|
||||
|
||||
vboSource.push_back(float(x+FONT_CHAR_WIDTH));
|
||||
vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
|
||||
vboSource.push_back(r);
|
||||
vboSource.push_back(g);
|
||||
vboSource.push_back(b);
|
||||
vboSource.push_back(u+w);
|
||||
vboSource.push_back(v+h);
|
||||
|
||||
return x + FONT_CHAR_WIDTH;
|
||||
}
|
||||
|
||||
int
|
||||
Hud::drawString(std::vector<float> &vboSource,
|
||||
int x, int y, float r, float g, float b, const char *c)
|
||||
{
|
||||
while (*c) {
|
||||
char ch = (char)((*c) & 0x7f);
|
||||
x = drawChar(vboSource, x, y, r, g, b, ch);
|
||||
c++;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::DrawString(int x, int y, const char *fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
x = x > 0 ? x : _windowWidth + x;
|
||||
y = y > 0 ? y : _windowHeight + y;
|
||||
|
||||
drawString(_vboSource, x, y, 1, 1, 1, buf);
|
||||
}
|
||||
|
||||
void
|
||||
Hud::DrawString(int x, int y, float r, float g, float b, const char *fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
x = x > 0 ? x : _windowWidth + x;
|
||||
y = y > 0 ? y : _windowHeight + y;
|
||||
|
||||
drawString(_vboSource, x, y, r, g, b, buf);
|
||||
}
|
||||
|
||||
void
|
||||
Hud::Rebuild(int width, int height, int framebufferWidth, int framebufferHeight)
|
||||
{
|
||||
_requiresRebuildStatic = false;
|
||||
_windowWidth = width;
|
||||
_windowHeight = height;
|
||||
_framebufferWidth = framebufferWidth;
|
||||
_framebufferHeight = framebufferHeight;
|
||||
|
||||
_staticVboSource.clear();
|
||||
|
||||
int x, y;
|
||||
// add UI elements
|
||||
for (std::vector<Item>::const_iterator it = _labels.begin();
|
||||
it != _labels.end(); ++it) {
|
||||
getWindowPos(*it, &x, &y);
|
||||
drawString(_staticVboSource, x, y, 1, 1, 1, it->label.c_str());
|
||||
}
|
||||
// draw radio buttons
|
||||
for (std::vector<RadioButton>::const_iterator it = _radioButtons.begin();
|
||||
it != _radioButtons.end(); ++it) {
|
||||
getWindowPos(*it, &x, &y);
|
||||
if (it->checked) {
|
||||
x = drawChar(_staticVboSource, x, y, 1, 1, 1, FONT_RADIO_BUTTON_ON);
|
||||
drawString(_staticVboSource, x, y, 1, 1, 0, it->label.c_str());
|
||||
} else {
|
||||
x = drawChar(_staticVboSource, x, y, 1, 1, 1, FONT_RADIO_BUTTON_OFF);
|
||||
drawString(_staticVboSource, x, y, .5f, .5f, .5f, it->label.c_str());
|
||||
}
|
||||
}
|
||||
// draw checkboxes
|
||||
for (std::vector<CheckBox>::const_iterator it = _checkBoxes.begin();
|
||||
it != _checkBoxes.end(); ++it) {
|
||||
getWindowPos(*it, &x, &y);
|
||||
if (it->checked) {
|
||||
x = drawChar(_staticVboSource, x, y, 1, 1, 1, FONT_CHECK_BOX_ON);
|
||||
drawString(_staticVboSource, x, y, 1, 1, 0, it->label.c_str());
|
||||
} else {
|
||||
x = drawChar(_staticVboSource, x, y, 1, 1, 1, FONT_CHECK_BOX_OFF);
|
||||
drawString(_staticVboSource, x, y, .5f, .5f, .5f, it->label.c_str());
|
||||
}
|
||||
}
|
||||
// draw sliders
|
||||
for (std::vector<Slider>::const_iterator it = _sliders.begin();
|
||||
it != _sliders.end(); ++it) {
|
||||
getWindowPos(*it, &x, &y);
|
||||
int sx = x;
|
||||
x = drawString(_staticVboSource, x, y, 1, 1, 1, it->label.c_str());
|
||||
char value[16];
|
||||
if (it->intStep) {
|
||||
snprintf(value, 16, " : %d", (int)it->value);
|
||||
} else {
|
||||
snprintf(value, 16, " : %.2f", it->value);
|
||||
}
|
||||
drawString(_staticVboSource, x, y, 1, 1, 1, value);
|
||||
|
||||
// new line
|
||||
y += FONT_CHAR_HEIGHT;
|
||||
x = sx;
|
||||
|
||||
x = drawChar(_staticVboSource, x, y, 1, 1, 1, FONT_SLIDER_LEFT);
|
||||
int nw = it->w / FONT_CHAR_WIDTH;
|
||||
for (int i = 1; i < nw; ++i) {
|
||||
x = drawChar(_staticVboSource, x, y, 1, 1, 1, FONT_SLIDER_MIDDLE);
|
||||
}
|
||||
drawChar(_staticVboSource, x, y, 1, 1, 1, FONT_SLIDER_RIGHT);
|
||||
int pos = int(((it->value-it->min)/(it->max-it->min))*float(it->w));
|
||||
drawChar(_staticVboSource, sx+pos, y, 1, 1, 0, FONT_SLIDER_CURSOR);
|
||||
}
|
||||
// draw pulldowns
|
||||
for (std::vector<PullDown>::const_iterator it = _pulldowns.begin();
|
||||
it != _pulldowns.end(); ++it) {
|
||||
getWindowPos(*it, &x, &y);
|
||||
|
||||
x = drawString(_staticVboSource, x, y, .5f, .5f, .5f, it->label.c_str());
|
||||
x += FONT_CHAR_WIDTH;
|
||||
|
||||
if (it->open) {
|
||||
x = drawChar(_staticVboSource, x, y, 1, 1, 0, FONT_ARROW_DOWN);
|
||||
x += FONT_CHAR_WIDTH;
|
||||
for (int i=0; i<(int)it->labels.size(); ++i, y+=FONT_CHAR_HEIGHT) {
|
||||
if (i==it->selected) {
|
||||
drawString(_staticVboSource, x, y, 1, 1, 0, it->labels[i]);
|
||||
} else {
|
||||
drawString(_staticVboSource, x, y, 0.5f, 0.5f, 0.5f, it->labels[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
x = drawChar(_staticVboSource, x, y, .5f, .5f, .5f, FONT_ARROW_RIGHT);
|
||||
x += FONT_CHAR_WIDTH;
|
||||
drawString(_staticVboSource, x, y, 1, 1, 0, it->labels[it->selected]);
|
||||
}
|
||||
}
|
||||
|
||||
// draw the character cells corresponding to the logo
|
||||
drawString(_staticVboSource, _windowWidth-128, _windowHeight-44, .5, .5, .5,
|
||||
"\x06\x07\x08\x09");
|
||||
drawString(_staticVboSource, _windowWidth-128, _windowHeight-28, .5, .5, .5,
|
||||
"\x16\x17\x18\x19");
|
||||
drawString(_staticVboSource, _windowWidth-92, _windowHeight-36, .5, .5, .5,
|
||||
"\x0a\x0b\x0c\x0d");
|
||||
drawString(_staticVboSource, _windowWidth-58, _windowHeight-36, .5, .5, .5,
|
||||
"\x1a\x1b\x1c\x1d\x1e\x1f");
|
||||
}
|
||||
|
||||
bool
|
||||
Hud::Flush()
|
||||
{
|
||||
if (!_visible) {
|
||||
_vboSource.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_requiresRebuildStatic)
|
||||
this->Rebuild(_windowWidth, _windowHeight, _framebufferWidth, _framebufferHeight);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Hud::IsVisible() const
|
||||
{
|
||||
return _visible;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::SetVisible(bool visible)
|
||||
{
|
||||
_visible = visible;
|
||||
}
|
||||
|
||||
std::vector<float> &
|
||||
Hud::getVboSource()
|
||||
{
|
||||
return _vboSource;
|
||||
}
|
||||
|
||||
std::vector<float> &
|
||||
Hud::getStaticVboSource()
|
||||
{
|
||||
return _staticVboSource;
|
||||
}
|
||||
Reference in New Issue
Block a user