From de0008caf162eb2ab44b466a89ff53bb308684f5 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Sat, 24 Mar 2012 12:22:40 -0300 Subject: [PATCH] ui and graphics changes * implement draw clipping using opengl stencil buffers * allow to create Widgets by style name with g_ui.createWidgetByStyle * styles can now have children widgets * make proper use of the isNotPathable in pathfinding * add scrollbar skin --- modules/client_entergame/characterlist.otui | 8 ++- modules/core_lib/core_lib.otmod | 1 + modules/core_lib/globals.lua | 25 ++----- modules/core_lib/widgets/uiscrollbar.lua | 30 ++++++++ modules/core_lib/widgets/uisplitter.lua | 7 +- modules/core_styles/core_styles.otmod | 1 + .../core_styles/styles/images/panel_flat.png | Bin 179 -> 197 bytes .../core_styles/styles/images/vscrollbar.png | Bin 0 -> 350 bytes modules/core_styles/styles/scrollbars.otui | 30 ++++++++ src/framework/graphics/graphics.cpp | 24 +++++++ src/framework/graphics/graphics.h | 3 + src/framework/luafunctions.cpp | 2 + src/framework/otml/otmldocument.cpp | 5 +- src/framework/platform/win32window.cpp | 4 +- src/framework/platform/x11window.cpp | 2 + src/framework/ui/uianchorlayout.cpp | 1 + src/framework/ui/uiframecounter.cpp | 4 +- src/framework/ui/uiframecounter.h | 2 +- src/framework/ui/uimanager.cpp | 25 ++++--- src/framework/ui/uimanager.h | 5 +- src/framework/ui/uiwidget.cpp | 68 ++++++++++++------ src/framework/ui/uiwidget.h | 7 +- src/framework/ui/uiwidgetbasestyle.cpp | 4 +- src/framework/ui/uiwidgetimage.cpp | 2 +- src/otclient/core/map.cpp | 2 +- src/otclient/core/thing.h | 1 + src/otclient/core/tile.cpp | 13 ++++ src/otclient/core/tile.h | 1 + src/otclient/ui/uicreature.cpp | 6 +- src/otclient/ui/uicreature.h | 2 +- src/otclient/ui/uiitem.cpp | 7 +- src/otclient/ui/uiitem.h | 2 +- src/otclient/ui/uimap.cpp | 6 +- src/otclient/ui/uimap.h | 2 +- 34 files changed, 213 insertions(+), 89 deletions(-) create mode 100644 modules/core_lib/widgets/uiscrollbar.lua create mode 100644 modules/core_styles/styles/images/vscrollbar.png create mode 100644 modules/core_styles/styles/scrollbars.otui diff --git a/modules/client_entergame/characterlist.otui b/modules/client_entergame/characterlist.otui index 00f4cf9c..268d9cf8 100644 --- a/modules/client_entergame/characterlist.otui +++ b/modules/client_entergame/characterlist.otui @@ -18,11 +18,17 @@ MainWindow TextList id: characterList anchors.fill: parent - anchors.bottom: next.top + anchors.bottom: accountStatusLabel.top margin-bottom: 5 padding: 1 focusable: false + VerticalScrollBar + attached-to: characterList + anchors.top: characterList.top + anchors.bottom: characterList.bottom + anchors.right: characterList.right + Label id: accountStatusLabel text: |- diff --git a/modules/core_lib/core_lib.otmod b/modules/core_lib/core_lib.otmod index cabea4f1..30d773cf 100644 --- a/modules/core_lib/core_lib.otmod +++ b/modules/core_lib/core_lib.otmod @@ -40,4 +40,5 @@ Module dofile 'widgets/uiwindow' dofile 'widgets/uimessagebox' dofile 'widgets/uisplitter' + dofile 'widgets/uiscrollbar' diff --git a/modules/core_lib/globals.lua b/modules/core_lib/globals.lua index 592fe6ed..a1e24a5d 100644 --- a/modules/core_lib/globals.lua +++ b/modules/core_lib/globals.lua @@ -12,27 +12,12 @@ function displayUI(otui, parent) return g_ui.loadUI(otuiFilePath, parent) end -function createWidget(style, parent) - local className = g_ui.getStyleClass(style) - if className == "" then - error('could not find style ' .. style) - return +function createWidget(stylename, parent) + if type(parent) == 'string' then + parent = rootWidget:recursiveGetChildById(parent) end - - local class = _G[className] - if not class then - error('could not find widget class ' .. className) - return - end - - local widget = class.create() - if parent then - if type(parent) == 'string' then - parent = rootWidget:recursiveGetChildById(parent) - end - parent:addChild(widget) - end - widget:setStyle(style) + local widget = g_ui.createWidgetFromStyle(stylename, parent) + --widget:setStyle(stylename) return widget end diff --git a/modules/core_lib/widgets/uiscrollbar.lua b/modules/core_lib/widgets/uiscrollbar.lua new file mode 100644 index 00000000..8448eddd --- /dev/null +++ b/modules/core_lib/widgets/uiscrollbar.lua @@ -0,0 +1,30 @@ +UIScrollBar = extends(UIWidget) + +function UIScrollBar.create() + local scrollbar = UIScrollBar.internalCreate() + scrollbar:setFocusable(false) + return scrollbar +end + +function UIScrollBar:onSetup() + --self.getChildById('upButton').onClick = function() self.navigateUp() end + --self.getChildById('upButton').onClick = function() self.navigateDown() end +end + +function UIScrollBar:attachWidget(widget) + self.attachedWidget = widget +end + +function UIScrollBar:onStyleApply(styleName, styleNode) + if styleNode['attached-to'] then + local id = styleNode['attached-to'] + local parent = self:getParent() + local widget + if id == 'parent' then + widget = parent + elseif parent then + widget = parent:getChildById(id) + end + self:attachWidget(widget) + end +end diff --git a/modules/core_lib/widgets/uisplitter.lua b/modules/core_lib/widgets/uisplitter.lua index 2be622a3..4c6e257f 100644 --- a/modules/core_lib/widgets/uisplitter.lua +++ b/modules/core_lib/widgets/uisplitter.lua @@ -50,9 +50,10 @@ function UISplitter:onMouseRelease(mousePos, mouseButton) end function UISplitter:onStyleApply(styleName, styleNode) - if styleNode['relative-margin'] then - self.relativeMargin = styleNode['relative-margin'] - end + --TODO: relative margins + --if styleNode['relative-margin'] then + --- self.relativeMargin = styleNode['relative-margin'] + --end end function UISplitter:canUpdateMargin(newMargin) diff --git a/modules/core_styles/core_styles.otmod b/modules/core_styles/core_styles.otmod index 19755499..42f70d46 100644 --- a/modules/core_styles/core_styles.otmod +++ b/modules/core_styles/core_styles.otmod @@ -28,3 +28,4 @@ Module importStyle 'styles/comboboxes.otui' importStyle 'styles/spinboxes.otui' importStyle 'styles/messageboxes.otui' + importStyle 'styles/scrollbars.otui' diff --git a/modules/core_styles/styles/images/panel_flat.png b/modules/core_styles/styles/images/panel_flat.png index 1651075651c86f6f813db43e7aa2359aba94fb76..64a7b6aab68f20fce95bf12401002a83cf32c72e 100644 GIT binary patch delta 39 vcmdnYc$9I1AwOG^x4R3241)rL`auz+@`-wKTz8lyc%==yMYWet42uN-$b1S{ delta 23 ecmX@gxS4T+;Y4R?uG{Q_f=o&xQV#7CGhzW$6$YpP diff --git a/modules/core_styles/styles/images/vscrollbar.png b/modules/core_styles/styles/images/vscrollbar.png new file mode 100644 index 0000000000000000000000000000000000000000..41f01e199d785757e19d88da456bfc4459c773c1 GIT binary patch literal 350 zcmeAS@N?(olHy`uVBq!ia0vp@K!L<6uCjv9zw6b^#kV_c@o2H~aCtFzXV+ilm<7%c<(Q6pZ`!oVn#abHAtJoP@%3zV zriN;cq>K+o6EFTOk!e$Uu)y=KgQGL=n{Vyc-4EXLEu8S1y$&VN6!!lrD463Azsu6{1-oD!MgetVirtualOffset()); widget->setRect(newRect); anchorGroup.setUpdated(true); } diff --git a/src/framework/ui/uiframecounter.cpp b/src/framework/ui/uiframecounter.cpp index a188ddbc..390008a3 100644 --- a/src/framework/ui/uiframecounter.cpp +++ b/src/framework/ui/uiframecounter.cpp @@ -36,9 +36,9 @@ UIFrameCounter::UIFrameCounter() m_frameCount = 0; } -void UIFrameCounter::draw() +void UIFrameCounter::drawSelf() { - UIWidget::draw(); + UIWidget::drawSelf(); if(g_clock.ticksElapsed(m_lastFrameTicks) >= 1000) { m_fpsText = Fw::formatString("FPS: %d", m_frameCount); diff --git a/src/framework/ui/uiframecounter.h b/src/framework/ui/uiframecounter.h index d6890543..a7ca06af 100644 --- a/src/framework/ui/uiframecounter.h +++ b/src/framework/ui/uiframecounter.h @@ -29,7 +29,7 @@ class UIFrameCounter : public UIWidget { public: UIFrameCounter(); - virtual void draw(); + void drawSelf(); void setAlign(Fw::AlignmentFlag align) { m_align = align; } Fw::AlignmentFlag getAlign() { return m_align; } diff --git a/src/framework/ui/uimanager.cpp b/src/framework/ui/uimanager.cpp index d49d76a7..0fd802a0 100644 --- a/src/framework/ui/uimanager.cpp +++ b/src/framework/ui/uimanager.cpp @@ -53,7 +53,7 @@ void UIManager::terminate() void UIManager::render() { - m_rootWidget->draw(); + m_rootWidget->draw(m_rootWidget->getRect()); } void UIManager::resize(const Size& size) @@ -349,23 +349,24 @@ UIWidgetPtr UIManager::loadUI(const std::string& file, const UIWidgetPtr& parent else { if(widget) Fw::throwException("cannot have multiple main widgets in otui files"); - widget = loadWidgetFromOTML(node, parent); + widget = createWidgetFromOTML(node, parent); } } return widget; } catch(Exception& e) { - logError("Failed to load UI from '", file, "': ", e.what()); + logError("failed to load UI from '", file, "': ", e.what()); return nullptr; } } -/* -UIWidgetPtr UIManager::loadWidgetFromStyle() -{ +UIWidgetPtr UIManager::createWidgetFromStyle(const std::string& styleName, const UIWidgetPtr& parent) +{ + OTMLNodePtr node = OTMLNode::create(styleName); + return createWidgetFromOTML(node, parent); } -*/ -UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent) + +UIWidgetPtr UIManager::createWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent) { OTMLNodePtr originalStyleNode = getStyle(widgetNode->tag()); if(!originalStyleNode) @@ -384,9 +385,11 @@ UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode, const U if(widget) { widget->setStyleFromNode(styleNode); - for(const OTMLNodePtr& childNode : widgetNode->children()) { - if(!childNode->isUnique()) - loadWidgetFromOTML(childNode, widget); + for(const OTMLNodePtr& childNode : styleNode->children()) { + if(!childNode->isUnique()) { + createWidgetFromOTML(childNode, widget); + styleNode->removeChild(childNode); + } } } else Fw::throwException("unable to create widget of type '", widgetType, "'"); diff --git a/src/framework/ui/uimanager.h b/src/framework/ui/uimanager.h index 4d25b16a..4f912df8 100644 --- a/src/framework/ui/uimanager.h +++ b/src/framework/ui/uimanager.h @@ -46,8 +46,9 @@ public: OTMLNodePtr getStyle(const std::string& styleName); std::string getStyleClass(const std::string& styleName); - UIWidgetPtr loadUI(const std::string& file, const UIWidgetPtr& parent = nullptr); - UIWidgetPtr loadWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent); + UIWidgetPtr loadUI(const std::string& file, const UIWidgetPtr& parent); + UIWidgetPtr createWidgetFromStyle(const std::string& styleName, const UIWidgetPtr& parent); + UIWidgetPtr createWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent); void setMouseReceiver(const UIWidgetPtr& widget) { m_mouseReceiver = widget; } void setKeyboardReceiver(const UIWidgetPtr& widget) { m_keyboardReceiver = widget; } diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 47945911..a41fd1d4 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -51,10 +51,22 @@ UIWidget::~UIWidget() #endif } -void UIWidget::draw() +void UIWidget::draw(const Rect& visibleRect) { drawSelf(); - drawChildren(); + if(m_children.size() > 0) { + bool clip = true; + if(this == g_ui.getRootWidget().get()) + clip = false; + + if(clip) + g_graphics.beginClipping(visibleRect); + + drawChildren(visibleRect); + + if(clip) + g_graphics.endClipping(); + } } void UIWidget::drawSelf() @@ -72,33 +84,35 @@ void UIWidget::drawSelf() drawText(m_rect); } -void UIWidget::drawChildren() +void UIWidget::drawChildren(const Rect& visibleRect) { // draw children for(const UIWidgetPtr& child : m_children) { // render only visible children with a valid rect inside parent rect - if(child->isExplicitlyVisible() && - child->getRect().isValid() && - child->getOpacity() > 0.0f && - child->getRect().intersects(m_rect)) { - // store current graphics opacity - float oldOpacity = g_painter.getOpacity(); - - // decrease to self opacity - if(child->getOpacity() < oldOpacity) - g_painter.setOpacity(child->getOpacity()); - - child->draw(); - - // debug draw box - if(g_ui.isDrawingDebugBoxes()) { - g_painter.setColor(Color::green); - g_painter.drawBoundingRect(child->getRect()); - } - //g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Color::red); + if(!child->isExplicitlyVisible() || !child->getRect().isValid() || child->getOpacity() == 0.0f) + continue; + + Rect childVisibleRect = visibleRect.intersection(child->getRect()); + if(!childVisibleRect.isValid()) + continue; + + // store current graphics opacity + float oldOpacity = g_painter.getOpacity(); - g_painter.setOpacity(oldOpacity); + // decrease to self opacity + if(child->getOpacity() < oldOpacity) + g_painter.setOpacity(child->getOpacity()); + + child->draw(childVisibleRect); + + // debug draw box + if(g_ui.isDrawingDebugBoxes()) { + g_painter.setColor(Color::green); + g_painter.drawBoundingRect(child->getRect()); } + //g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Color::red); + + g_painter.setOpacity(oldOpacity); } } @@ -747,6 +761,7 @@ void UIWidget::setStyle(const std::string& styleName) logTraceError("unable to retrive style '", styleName, "': not a defined style"); return; } + styleNode = styleNode->clone(); applyStyle(styleNode); m_style = styleNode; updateStyle(); @@ -839,6 +854,13 @@ void UIWidget::setLastFocusReason(Fw::FocusReason reason) m_lastFocusReason = reason; } +void UIWidget::setVirtualOffset(const Point& offset) +{ + m_virtualOffset = offset; + if(m_layout) + m_layout->update(); +} + bool UIWidget::isVisible() { if(!m_visible) diff --git a/src/framework/ui/uiwidget.h b/src/framework/ui/uiwidget.h index 883d9361..5fc3893c 100644 --- a/src/framework/ui/uiwidget.h +++ b/src/framework/ui/uiwidget.h @@ -49,14 +49,15 @@ public: virtual ~UIWidget(); protected: - virtual void draw(); + virtual void draw(const Rect& visibleRect); virtual void drawSelf(); - virtual void drawChildren(); + virtual void drawChildren(const Rect& visibleRect); friend class UIManager; std::string m_id; Rect m_rect; + Point m_virtualOffset; Boolean m_enabled; Boolean m_visible; Boolean m_focusable; @@ -121,6 +122,7 @@ public: void setFixedSize(bool fixed); void setLastFocusReason(Fw::FocusReason reason); void setAutoRepeatDelay(int delay) { m_autoRepeatDelay = delay; } + void setVirtualOffset(const Point& offset); bool isVisible(); bool isChildLocked(const UIWidgetPtr& child); @@ -240,6 +242,7 @@ public: int getChildCount() { return m_children.size(); } Fw::FocusReason getLastFocusReason() { return m_lastFocusReason; } int getAutoRepeatDelay() { return m_autoRepeatDelay; } + Point getVirtualOffset() { return m_virtualOffset; } std::string getStyleName() { return m_style->tag(); } diff --git a/src/framework/ui/uiwidgetbasestyle.cpp b/src/framework/ui/uiwidgetbasestyle.cpp index a9c180d8..bee1d1d4 100644 --- a/src/framework/ui/uiwidgetbasestyle.cpp +++ b/src/framework/ui/uiwidgetbasestyle.cpp @@ -81,9 +81,9 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode) else if(node->tag() == "background-rect") setBackgroundRect(node->value()); else if(node->tag() == "icon") - setIcon(node->value()); + setIcon(Fw::resolvePath(node->value(), node->source())); else if(node->tag() == "icon-source") - setIcon(node->value()); + setIcon(Fw::resolvePath(node->value(), node->source())); else if(node->tag() == "icon-color") setIconColor(node->value()); else if(node->tag() == "icon-offset-x") diff --git a/src/framework/ui/uiwidgetimage.cpp b/src/framework/ui/uiwidgetimage.cpp index a6c14342..d0306d6f 100644 --- a/src/framework/ui/uiwidgetimage.cpp +++ b/src/framework/ui/uiwidgetimage.cpp @@ -35,7 +35,7 @@ void UIWidget::parseImageStyle(const OTMLNodePtr& styleNode) { for(const OTMLNodePtr& node : styleNode->children()) { if(node->tag() == "image-source") - setImageSource(Fw::resolvePath(node->value(), styleNode->source())); + setImageSource(Fw::resolvePath(node->value(), node->source())); else if(node->tag() == "image-offset-x") setImageOffsetX(node->value()); else if(node->tag() == "image-offset-y") diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 72706055..ec4f6976 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -459,7 +459,7 @@ std::vector Map::findPath(const Position& startPos, const Positi Position neighborPos = currentNode->pos.translated(i, j); const TilePtr& tile = getTile(neighborPos); - if(!tile || !tile->isWalkable()) + if(!tile || (!tile->isPathable() && neighborPos != goalPos) || (!tile->isWalkable() && neighborPos == goalPos)) continue; float walkFactor; diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 8b197c7d..2f8e8608 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -79,6 +79,7 @@ public: bool isNotMoveable() { return m_type->properties[ThingType::IsNotMovable]; } bool isNotWalkable() { return m_type->properties[ThingType::NotWalkable]; } bool isPickupable() { return m_type->properties[ThingType::IsPickupable]; } + bool isNotPathable() { return m_type->properties[ThingType::NotPathable]; } bool isIgnoreLook() { return m_type->properties[ThingType::IgnoreLook]; } bool isHangable() { return m_type->properties[ThingType::IsHangable]; } bool isHookSouth() { return m_type->properties[ThingType::HookSouth]; } diff --git a/src/otclient/core/tile.cpp b/src/otclient/core/tile.cpp index e63c7b72..a3b1f412 100644 --- a/src/otclient/core/tile.cpp +++ b/src/otclient/core/tile.cpp @@ -358,6 +358,19 @@ bool Tile::isWalkable() return true; } +bool Tile::isPathable() +{ + if(!isWalkable()) + return false; + + for(const ThingPtr& thing : m_things) { + if(thing->isNotPathable()) + return false; + } + + return true; +} + bool Tile::isFullGround() { ItemPtr ground = getGround(); diff --git a/src/otclient/core/tile.h b/src/otclient/core/tile.h index cc8dddbb..3771ec44 100644 --- a/src/otclient/core/tile.h +++ b/src/otclient/core/tile.h @@ -58,6 +58,7 @@ public: ItemPtr getGround(); int getGroundSpeed(); int getThingCount() { return m_things.size() + m_effects.size(); } + bool isPathable(); bool isWalkable(); bool isFullGround(); bool isFullyOpaque(); diff --git a/src/otclient/ui/uicreature.cpp b/src/otclient/ui/uicreature.cpp index d1b67270..b9929747 100644 --- a/src/otclient/ui/uicreature.cpp +++ b/src/otclient/ui/uicreature.cpp @@ -24,17 +24,15 @@ #include #include -void UICreature::draw() +void UICreature::drawSelf() { - drawSelf(); + UIWidget::drawSelf(); if(m_creature) { g_painter.setColor(Color::white); Rect drawRect = getChildrenRect(); m_creature->drawOutfit(drawRect, !m_fixedCreatureSize); } - - drawChildren(); } void UICreature::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode) diff --git a/src/otclient/ui/uicreature.h b/src/otclient/ui/uicreature.h index 10478de0..2a98e0dc 100644 --- a/src/otclient/ui/uicreature.h +++ b/src/otclient/ui/uicreature.h @@ -30,7 +30,7 @@ class UICreature : public UIWidget { public: - void draw(); + void drawSelf(); void setCreature(const CreaturePtr& creature) { m_creature = creature; } void setFixedCreatureSize(bool fixed) { m_fixedCreatureSize = fixed; } diff --git a/src/otclient/ui/uiitem.cpp b/src/otclient/ui/uiitem.cpp index eb102c55..dab5a786 100644 --- a/src/otclient/ui/uiitem.cpp +++ b/src/otclient/ui/uiitem.cpp @@ -30,9 +30,9 @@ UIItem::UIItem() m_dragable = true; } -void UIItem::draw() +void UIItem::drawSelf() { - drawSelf(); + UIWidget::drawSelf(); if(m_item) { Point topLeft = m_rect.bottomRight() - Point(32, 32) + Point(m_padding.left, m_padding.top); @@ -48,9 +48,6 @@ void UIItem::draw() //m_font->renderText(Fw::unsafeCast(m_item->getId()), m_rect); } - - - drawChildren(); } void UIItem::setItemId(int id) diff --git a/src/otclient/ui/uiitem.h b/src/otclient/ui/uiitem.h index b0d575e9..a4108048 100644 --- a/src/otclient/ui/uiitem.h +++ b/src/otclient/ui/uiitem.h @@ -31,7 +31,7 @@ class UIItem : public UIWidget { public: UIItem(); - void draw(); + void drawSelf(); void setItemId(int id); void setItemCount(int count) { if(m_item) m_item->setCount(count); } diff --git a/src/otclient/ui/uimap.cpp b/src/otclient/ui/uimap.cpp index 3e655507..12974d0a 100644 --- a/src/otclient/ui/uimap.cpp +++ b/src/otclient/ui/uimap.cpp @@ -40,17 +40,15 @@ UIMap::~UIMap() g_map.removeMapView(m_mapView); } -void UIMap::draw() +void UIMap::drawSelf() { - drawSelf(); + UIWidget::drawSelf(); // draw map border g_painter.setColor(Color::black); g_painter.drawBoundingRect(m_mapRect.expanded(1)); m_mapView->draw(m_mapRect); - - drawChildren(); } void UIMap::zoomIn() diff --git a/src/otclient/ui/uimap.h b/src/otclient/ui/uimap.h index 074976c2..c5e512a5 100644 --- a/src/otclient/ui/uimap.h +++ b/src/otclient/ui/uimap.h @@ -33,7 +33,7 @@ public: UIMap(); ~UIMap(); - void draw(); + void drawSelf(); void zoomIn(); void zoomOut();