From Jeremy Moles, updates to osgWidget
Merged my Robert Osfield from OpenSceneGraph-osgWidget-dev.
This commit is contained in:
@@ -70,7 +70,11 @@ void Window::EmbeddedWindow::parented(Window* parent) {
|
||||
}
|
||||
|
||||
void Window::EmbeddedWindow::unparented(Window*) {
|
||||
// TODO: Figure out what's necessary here...
|
||||
if(_window.valid()) {
|
||||
_window->_parent = 0;
|
||||
|
||||
if(_parent) _parent->removeChild(_window.get());
|
||||
}
|
||||
}
|
||||
|
||||
void Window::EmbeddedWindow::managed(WindowManager* wm) {
|
||||
@@ -95,6 +99,8 @@ void Window::EmbeddedWindow::positioned() {
|
||||
// If the widget is fillable, ask the internal Window to resize itself.
|
||||
// Whether or not the Window honors this reqest will be up to it.
|
||||
_window->setOrigin(x, y);
|
||||
_window->setZ(_calculateZ(getLayer() + 1));
|
||||
_window->setZRange(_calculateZ(LAYER_TOP - (getLayer() + 1)));
|
||||
_window->setVisibleArea(0, 0, static_cast<int>(w), static_cast<int>(h));
|
||||
_window->resize(w, h);
|
||||
}
|
||||
@@ -109,7 +115,6 @@ bool Window::EmbeddedWindow::setWindow(Window* win) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: I need to handle there already being a Window here.
|
||||
_window = win;
|
||||
|
||||
_window->resize();
|
||||
@@ -124,21 +129,27 @@ bool Window::EmbeddedWindow::setWindow(Window* win) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Window::EmbeddedWindow::updateSizeFromWindow() {
|
||||
setSize(_window->getSize());
|
||||
|
||||
if(_parent) _parent->resize();
|
||||
}
|
||||
|
||||
Window::Window(const std::string& name):
|
||||
_parent (0),
|
||||
_wm (0),
|
||||
_index (0),
|
||||
_x (0.0f),
|
||||
_y (0.0f),
|
||||
_z (0.0f),
|
||||
_zRange (0.0f),
|
||||
_strata (STRATA_NONE),
|
||||
_vis (VM_FULL),
|
||||
_r (0.0f),
|
||||
_s (1.0f),
|
||||
_scaleDenom (100.0f),
|
||||
_vAnchor (VA_NONE),
|
||||
_hAnchor (HA_NONE) {
|
||||
_parent (0),
|
||||
_wm (0),
|
||||
_index (0),
|
||||
_x (0.0f),
|
||||
_y (0.0f),
|
||||
_z (0.0f),
|
||||
_zRange (0.0f),
|
||||
_strata (STRATA_NONE),
|
||||
_vis (VM_FULL),
|
||||
_r (0.0f),
|
||||
_s (1.0f),
|
||||
_scaleDenom (100.0f),
|
||||
_vAnchor (VA_NONE),
|
||||
_hAnchor (HA_NONE) {
|
||||
_name = name.size() ? name : generateRandomName("Window");
|
||||
|
||||
// TODO: Fix the "bg" name.
|
||||
@@ -146,7 +157,7 @@ _hAnchor (HA_NONE) {
|
||||
Widget* bg = new Widget(name + "bg", 0.0f, 0.0f);
|
||||
|
||||
bg->setLayer(Widget::LAYER_BG);
|
||||
bg->setColor(0.0f, 0.0f, 0.0f, 0.5f);
|
||||
bg->setColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
_setParented(bg);
|
||||
|
||||
@@ -201,7 +212,14 @@ _visibleArea (window._visibleArea) {
|
||||
for(unsigned int i = 1; i < geode->getNumDrawables(); i++) {
|
||||
Widget* widget = dynamic_cast<Widget*>(geode->getDrawable(i));
|
||||
|
||||
if(!widget || !widget->canClone()) continue;
|
||||
if(!widget) continue;
|
||||
|
||||
// TODO: Properly test this...
|
||||
if(!widget->canClone()) {
|
||||
// geode->removeDrawable(widget);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
_setParented(widget);
|
||||
|
||||
@@ -286,22 +304,11 @@ bool Window::resizePercent(point_type width, point_type height) {
|
||||
}
|
||||
|
||||
void Window::update() {
|
||||
// Update all embedded children; the zRange values continue to decrease in precision
|
||||
// as you add more and more embedded Windows.
|
||||
WindowList wl;
|
||||
|
||||
getEmbeddedList(wl);
|
||||
|
||||
// Each child Window gets half the zRange of it's parent Window. This means the more
|
||||
// you embed Windows into other Windows, the less depth precision you're going to have.
|
||||
for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
|
||||
Window* win = w->get();
|
||||
|
||||
win->_z = _zRange / 2.0f;
|
||||
win->_zRange = _zRange / 2.0f;
|
||||
|
||||
win->update();
|
||||
}
|
||||
for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) w->get()->update();
|
||||
|
||||
matrix_type x = _x;
|
||||
matrix_type y = _y;
|
||||
@@ -319,6 +326,42 @@ void Window::update() {
|
||||
|
||||
xy.set(x, y);
|
||||
}
|
||||
|
||||
matrix_type z = _z;
|
||||
|
||||
// We can't do proper scissoring until we have access to our parent WindowManager, and
|
||||
// we need to determine the sorting method we want to use.
|
||||
if(_wm) {
|
||||
if(_wm->isUsingRenderBins()) {
|
||||
getOrCreateStateSet()->setRenderBinDetails(
|
||||
static_cast<int>((1.0f - fabs(_z)) * OSGWIDGET_RENDERBIN_MOD),
|
||||
"RenderBin"
|
||||
);
|
||||
|
||||
z = 0.0f;
|
||||
}
|
||||
|
||||
int sx = static_cast<int>(xy.x());
|
||||
int sy = static_cast<int>(xy.y());
|
||||
int sw = static_cast<int>(_width.current);
|
||||
int sh = static_cast<int>(_height.current);
|
||||
|
||||
// This sets the Scissor area to some offset defined by the user.
|
||||
if(_vis == VM_PARTIAL) {
|
||||
sw = static_cast<int>(_visibleArea[2]);
|
||||
sh = static_cast<int>(_visibleArea[3]);
|
||||
}
|
||||
|
||||
// Otherwise, use the size of the WindowManager itself.
|
||||
else if(_vis == VM_ENTIRE) {
|
||||
sx = 0;
|
||||
sy = 0;
|
||||
sw = static_cast<int>(_wm->getWidth());
|
||||
sh = static_cast<int>(_wm->getHeight());
|
||||
}
|
||||
|
||||
_scissor()->setScissor(sx, sy, sw, sh);
|
||||
}
|
||||
|
||||
// Update the Window itself, setting it's matrix according to translate, rotate, and
|
||||
// scale values.
|
||||
@@ -326,47 +369,11 @@ void Window::update() {
|
||||
osg::DegreesToRadians(_r),
|
||||
osg::Vec3d(0.0f, 0.0f, 1.0f)
|
||||
);
|
||||
|
||||
|
||||
osg::Matrix s = osg::Matrix::scale(_s, _s, 1.0f);
|
||||
osg::Matrix t = osg::Matrix::translate(x - _visibleArea[0], y - _visibleArea[1], _z);
|
||||
osg::Matrix t = osg::Matrix::translate(x - _visibleArea[0], y - _visibleArea[1], z);
|
||||
|
||||
setMatrix(r * s * t);
|
||||
|
||||
// We can't do proper scissoring until we have access to our parent WindowManager.
|
||||
if(_wm) {
|
||||
int x = static_cast<int>(xy.x());
|
||||
int y = static_cast<int>(xy.y());
|
||||
int w = static_cast<int>(_width.current);
|
||||
int h = static_cast<int>(_height.current);
|
||||
int wmh = static_cast<int>(_wm->getHeight());
|
||||
int nx = x;
|
||||
int ny = y;
|
||||
int nw = w;
|
||||
int nh = h;
|
||||
|
||||
// This sets the Scissor area to the full size of the Window.
|
||||
if(_vis == VM_FULL && _wm->isInvertedY()) ny = wmh - h - y;
|
||||
|
||||
// This sets the Scissor area to some offset defined by the user.
|
||||
else if(_vis == VM_PARTIAL) {
|
||||
if(_wm->isInvertedY()) ny = wmh - y - static_cast<int>(_visibleArea[3]);
|
||||
|
||||
// else ny = static_cast<int>(_visibleArea[3]);
|
||||
|
||||
nw = static_cast<int>(_visibleArea[2]);
|
||||
nh = static_cast<int>(_visibleArea[3]);
|
||||
}
|
||||
|
||||
// Otherwise, use the size of the WindowManager itself.
|
||||
else {
|
||||
nx = 0;
|
||||
ny = 0;
|
||||
nw = static_cast<int>(_wm->getWidth());
|
||||
nh = wmh;
|
||||
}
|
||||
|
||||
_scissor()->setScissor(nx, ny, nw, nh);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::_setWidthAndHeightUnknownSizeError(const std::string& size, point_type val) {
|
||||
@@ -526,9 +533,9 @@ void Window::_setParented(Widget* widget, bool setUnparented) {
|
||||
}
|
||||
|
||||
else {
|
||||
widget->_parent = 0;
|
||||
|
||||
widget->unparented(this);
|
||||
|
||||
widget->_parent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,6 +646,7 @@ void Window::addVisibleArea(int x, int y, int w, int h) {
|
||||
_visibleArea[3] += h;
|
||||
}
|
||||
|
||||
// The topmost Window always has this method called, instead of the embedded window directly.
|
||||
bool Window::setFocused(const Widget* widget) {
|
||||
// TODO: I've turned on the warn() here, but perhaps I shouldn't? I need to define
|
||||
// the conditions under which it's okay to call setFocus() with a NULL widget.
|
||||
@@ -650,7 +658,28 @@ bool Window::setFocused(const Widget* widget) {
|
||||
|
||||
ConstIterator i = std::find(begin(), end(), widget);
|
||||
|
||||
bool found = false;
|
||||
|
||||
if(i == end()) {
|
||||
// We couldn't find the widget in the toplevel, so lets see if one of our
|
||||
// EmbeddedWindow objects has it.
|
||||
WindowList wl;
|
||||
|
||||
getEmbeddedList(wl);
|
||||
|
||||
for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
|
||||
ConstIterator ii = std::find(w->get()->begin(), w->get()->end(), widget);
|
||||
|
||||
if(ii != w->get()->end()) {
|
||||
found = true;
|
||||
i = ii;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else found = true;
|
||||
|
||||
if(!found) {
|
||||
warn()
|
||||
<< "Window [" << _name
|
||||
<< "] couldn't find the Widget [" << widget->getName()
|
||||
@@ -666,9 +695,31 @@ bool Window::setFocused(const Widget* widget) {
|
||||
}
|
||||
|
||||
bool Window::setFocused(const std::string& name) {
|
||||
Widget* w = getByName(name);
|
||||
Widget* w1 = getByName(name);
|
||||
|
||||
if(!w) {
|
||||
bool found = false;
|
||||
|
||||
if(!w1) {
|
||||
// Just like above, we couldn't find the widget in the toplevel, so lets see if
|
||||
// one of our EmbeddedWindow objects has it. The difference here is that we
|
||||
// search by name.
|
||||
WindowList wl;
|
||||
|
||||
getEmbeddedList(wl);
|
||||
|
||||
for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
|
||||
Widget* w2 = w->get()->getByName(name);
|
||||
|
||||
if(w2) {
|
||||
found = true;
|
||||
w1 = w2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else found = true;
|
||||
|
||||
if(!found) {
|
||||
warn()
|
||||
<< "Window [" << _name
|
||||
<< "] couldn't find a Widget named [" << name
|
||||
@@ -678,11 +729,17 @@ bool Window::setFocused(const std::string& name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_setFocused(w);
|
||||
_setFocused(w1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Window::grabFocus() {
|
||||
if(!_wm) return false;
|
||||
|
||||
return _wm->setFocused(this);
|
||||
}
|
||||
|
||||
bool Window::setFirstFocusable() {
|
||||
WidgetList focusList;
|
||||
|
||||
@@ -724,8 +781,6 @@ XYCoord Window::localXY(double absx, double absy) const {
|
||||
double x = absx - xy.x();
|
||||
double y = absy - xy.y();
|
||||
|
||||
if(_wm && _wm->isInvertedY()) y = (_wm->getHeight() - absy) - xy.y();
|
||||
|
||||
return XYCoord(x + _visibleArea[0], y + _visibleArea[1]);
|
||||
}
|
||||
|
||||
@@ -746,13 +801,21 @@ XYCoord Window::getAbsoluteOrigin() const {
|
||||
return xy;
|
||||
}
|
||||
|
||||
Window::EmbeddedWindow* Window::embed() {
|
||||
EmbeddedWindow* ew = new EmbeddedWindow(_name + "Embedded", getWidth(), getHeight());
|
||||
Window::EmbeddedWindow* Window::embed(
|
||||
const std::string& newName,
|
||||
Widget::Layer layer,
|
||||
unsigned int layerOffset
|
||||
) {
|
||||
EmbeddedWindow* ew = new EmbeddedWindow(
|
||||
newName.size() > 0 ? newName : _name + "Embedded",
|
||||
getWidth(),
|
||||
getHeight()
|
||||
);
|
||||
|
||||
ew->setWindow(this);
|
||||
ew->setSize(getWidth(), getHeight());
|
||||
ew->setMinimumSize(getMinWidth(), getMinHeight());
|
||||
ew->setCanFill(true);
|
||||
ew->setLayer(layer, layerOffset);
|
||||
|
||||
return ew;
|
||||
}
|
||||
@@ -779,7 +842,11 @@ bool Window::getEmbeddedList(WindowList& wl) const {
|
||||
|
||||
if(!ew || !ew->getWindow()) continue;
|
||||
|
||||
wl.push_back(ew->getWindow());
|
||||
else {
|
||||
wl.push_back(ew->getWindow());
|
||||
|
||||
ew->getWindow()->getEmbeddedList(wl);
|
||||
}
|
||||
}
|
||||
|
||||
return wl.size() != 0;
|
||||
@@ -852,6 +919,12 @@ unsigned int Window::addDrawableAndGetIndex(osg::Drawable* drawable) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int Window::addChildAndGetIndex(osg::Node* node) {
|
||||
if(addChild(node)) return getChildIndex(node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// All of the subsequent functions are very boring and uninteresting, although hopefully
|
||||
// self-explanatory. They simply wrap calls to _compare<>() with the proper templates, and
|
||||
// forward the optional iteration ranges...
|
||||
@@ -945,7 +1018,7 @@ Window::Sizes Window::_getWidthImplementation() const {
|
||||
|
||||
point_type w = osg::round(bb.xMax() - bb.xMin());
|
||||
|
||||
return Sizes(w, w);
|
||||
return Sizes(w, 0.0f);
|
||||
}
|
||||
|
||||
Window::Sizes Window::_getHeightImplementation() const {
|
||||
@@ -953,7 +1026,7 @@ Window::Sizes Window::_getHeightImplementation() const {
|
||||
|
||||
point_type h = osg::round(bb.yMax() - bb.yMin());
|
||||
|
||||
return Sizes(h, h);
|
||||
return Sizes(h, 0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user