restore containers
* implemente Container class * restore module containers * add lua bindings for std::map * improve grid layout * fixes in UIItem rendering * changes in miniwindow design
This commit is contained in:
parent
231ba17ba1
commit
90d3acce2a
|
@ -17,8 +17,9 @@ Module
|
|||
- game_skills
|
||||
- game_inventory
|
||||
- game_combatcontrols
|
||||
- game_battle
|
||||
- game_containers
|
||||
- game_viplist
|
||||
- game_battle
|
||||
- game_hotkeys
|
||||
|
||||
@onLoad: |
|
||||
|
|
|
@ -140,10 +140,10 @@ function GameInterface.createThingMenu(menuPosition, lookThing, useThing, creatu
|
|||
if useThing then
|
||||
if useThing:isContainer() then
|
||||
if useThing:getParentContainer() then
|
||||
menu:addOption('Open', function() g_game.open(useThing, useThing:getContainerId()) end)
|
||||
menu:addOption('Open in new window', function() g_game.open(useThing, Containers.getFreeContainerId()) end)
|
||||
menu:addOption('Open', function() g_game.open(useThing, useThing:getParentContainer()) end)
|
||||
menu:addOption('Open in new window', function() g_game.open(useThing, nil) end)
|
||||
else
|
||||
menu:addOption('Open', function() g_game.open(useThing, Containers.getFreeContainerId()) end)
|
||||
menu:addOption('Open', function() g_game.open(useThing, nil) end)
|
||||
end
|
||||
else
|
||||
if useThing:isMultiUse() then
|
||||
|
@ -256,10 +256,10 @@ function GameInterface.processMouseAction(menuPosition, mouseButton, autoWalk, l
|
|||
elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
if useThing:isContainer() then
|
||||
if useThing:getParentContainer() then
|
||||
g_game.open(useThing, useThing:getContainerId())
|
||||
g_game.open(useThing, useThing:getParentContainer())
|
||||
return true
|
||||
else
|
||||
g_game.open(useThing, Containers.getFreeContainerId())
|
||||
g_game.open(useThing, nil)
|
||||
return true
|
||||
end
|
||||
elseif useThing:isMultiUse() then
|
||||
|
@ -281,10 +281,10 @@ function GameInterface.processMouseAction(menuPosition, mouseButton, autoWalk, l
|
|||
return true
|
||||
elseif multiUseThing:isContainer() then
|
||||
if multiUseThing:getParentContainer() then
|
||||
g_game.open(multiUseThing, multiUseThing:getContainerId())
|
||||
g_game.open(multiUseThing, multiUseThing:getParentContainer())
|
||||
return true
|
||||
else
|
||||
g_game.open(multiUseThing, Containers.getFreeContainerId())
|
||||
g_game.open(multiUseThing, nil)
|
||||
return true
|
||||
end
|
||||
elseif multiUseThing:isMultiUse() then
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Binary file not shown.
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 758 B |
|
@ -1,5 +1,6 @@
|
|||
Item < UIItem
|
||||
size: 34 34
|
||||
padding: 1
|
||||
image-source: /core_styles/styles/images/item.png
|
||||
font: verdana-11px-rounded
|
||||
border-color: white
|
||||
|
|
|
@ -3,7 +3,7 @@ MiniWindow < UIMiniWindow
|
|||
icon-rect: 4 4 16 16
|
||||
width: 192
|
||||
height: 200
|
||||
text-offset: 26 5
|
||||
text-offset: 24 5
|
||||
text-align: topLeft
|
||||
margin-bottom: 2
|
||||
move-policy: free updated
|
||||
|
@ -82,7 +82,7 @@ MiniWindowContents < ScrollablePanel
|
|||
id: contentsPanel
|
||||
anchors.fill: parent
|
||||
margin-right: 14
|
||||
padding: 25 6 6 6
|
||||
padding: 24 3 3 5
|
||||
vertical-scrollbar: miniwindowScrollBar
|
||||
|
||||
BorderlessGameWindow < UIWindow
|
||||
|
|
|
@ -36,7 +36,7 @@ table.insert(lifeBarColors, {percentAbove = -1, color = '#4F0000' } )
|
|||
|
||||
-- public functions
|
||||
function Battle.init()
|
||||
battleWindow = displayUI('battle.otui', GameInterface.getRightPanel())
|
||||
battleWindow = displayUI('battle.otui', GameInterface.getLeftPanel())
|
||||
battleButton = TopMenu.addGameToggleButton('battleButton', 'Battle (Ctrl+B)', 'battle.png', Battle.toggle)
|
||||
battleButton:setOn(true)
|
||||
Keyboard.bindKeyDown('Ctrl+B', Battle.toggle)
|
||||
|
|
|
@ -1,11 +1,35 @@
|
|||
MiniWindow
|
||||
size: 200 221
|
||||
ContainerWindow < MiniWindow
|
||||
height: 150
|
||||
|
||||
UIItem
|
||||
id: containerItemWidget
|
||||
virtual: true
|
||||
item-id: 3253
|
||||
size: 32 32
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: -6
|
||||
margin-left: -6
|
||||
|
||||
UIButton
|
||||
id: upButton
|
||||
anchors.top: minimizeButton.top
|
||||
anchors.right: minimizeButton.left
|
||||
margin-right: 3
|
||||
size: 14 14
|
||||
image-source: /game/images/miniwindowbuttons.png
|
||||
image-clip: 42 0 14 14
|
||||
|
||||
$hover:
|
||||
image-clip: 42 14 14 14
|
||||
|
||||
$pressed:
|
||||
image-clip: 42 28 14 14
|
||||
|
||||
MiniWindowContents
|
||||
padding: 27 6 6 8
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 34 34
|
||||
cell-spacing: 5
|
||||
num-columns: 4
|
||||
num-lines: 5
|
||||
|
||||
|
||||
flow: true
|
||||
auto-spacing: true
|
||||
|
|
|
@ -1,138 +1,90 @@
|
|||
Containers = {}
|
||||
|
||||
-- private variables
|
||||
local containers = {}
|
||||
|
||||
-- public functions
|
||||
function Containers.clean()
|
||||
containers = {}
|
||||
local function refreshContainerItems(container)
|
||||
for slot=0,container:getCapacity()-1 do
|
||||
local itemWidget = container.itemsPanel:getChildById('item' .. slot)
|
||||
itemWidget:setItem(container:getItem(slot))
|
||||
end
|
||||
end
|
||||
|
||||
function Containers.getFreeContainerId()
|
||||
for i=0,15 do
|
||||
if not containers[i] then
|
||||
return i
|
||||
local function onContainerOpen(container, previousContainer)
|
||||
local containerWindow
|
||||
if previousContainer then
|
||||
containerWindow = previousContainer.window
|
||||
previousContainer.window = nil
|
||||
previousContainer.itemsPanel = nil
|
||||
else
|
||||
containerWindow = createWidget('ContainerWindow', GameInterface.getRightPanel())
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-- hooked events
|
||||
function Containers.onOpenContainer(containerId, itemId, name, capacity, hasParent, items)
|
||||
local container = containers[containerId]
|
||||
if container then
|
||||
GameInterface.getRightPanel():removeChild(container)
|
||||
containerWindow:setId('container' .. container:getId())
|
||||
local containerPanel = containerWindow:getChildById('contentsPanel')
|
||||
local containerItemWidget = containerWindow:getChildById('containerItemWidget')
|
||||
containerWindow.onClose = function()
|
||||
g_game.close(container)
|
||||
containerWindow:hide()
|
||||
end
|
||||
|
||||
container = displayUI('container.otui', GameInterface.getRightPanel())
|
||||
local upButton = containerWindow:getChildById('upButton')
|
||||
upButton.onClick = function()
|
||||
g_game.openParent(container)
|
||||
end
|
||||
upButton:setVisible(container:hasParent())
|
||||
|
||||
local name = container:getName()
|
||||
name = name:sub(1,1):upper() .. name:sub(2)
|
||||
container:setText(name)
|
||||
containerWindow:setText(name)
|
||||
|
||||
-- set icon, itemid
|
||||
-- closebutton
|
||||
-- resize
|
||||
if hasParent then
|
||||
-- parent button
|
||||
containerItemWidget:setItemId(container:getItemId())
|
||||
|
||||
containerPanel:destroyChildren()
|
||||
for slot=0,container:getCapacity()-1 do
|
||||
local itemWidget = createWidget('Item', containerPanel)
|
||||
itemWidget:setId('item' .. slot)
|
||||
itemWidget:setItem(container:getItem(slot))
|
||||
itemWidget.position = container:getSlotPosition(slot)
|
||||
end
|
||||
|
||||
container.itemCount = #items
|
||||
container.capacity = capacity
|
||||
container.window = containerWindow
|
||||
container.itemsPanel = containerPanel
|
||||
end
|
||||
|
||||
for i=1,capacity do
|
||||
local itemWidget = UIItem.create()
|
||||
itemWidget:setStyle('Item')
|
||||
container:addChild(itemWidget)
|
||||
itemWidget.position = {x=65535, y=containerId+64, z=i-1}
|
||||
local function onContainerClose(container)
|
||||
local containerWindow = container.window
|
||||
if containerWindow then
|
||||
containerWindow:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
if i <= #items then
|
||||
local item = items[i]
|
||||
item:setPosition(itemWidget.position)
|
||||
local function onContainerAddItem(container, slot, item)
|
||||
refreshContainerItems(container)
|
||||
end
|
||||
|
||||
local function onContainerUpdateItem(container, slot, item, oldItem)
|
||||
local itemWidget = container.itemsPanel:getChildById('item' .. slot)
|
||||
itemWidget:setItem(item)
|
||||
end
|
||||
end
|
||||
|
||||
containers[containerId] = container
|
||||
end
|
||||
|
||||
function Containers.onCloseContainer(containerId)
|
||||
local container = containers[containerId]
|
||||
if container then
|
||||
GameInterface.getRightPanel():removeChild(container)
|
||||
end
|
||||
containers[containerId] = nil
|
||||
local function onContainerRemoveItem(container, slot, item)
|
||||
refreshContainerItems(container)
|
||||
end
|
||||
|
||||
function Containers.onContainerAddItem(containerId, item)
|
||||
local container = containers[containerId]
|
||||
if not container or not item or container.itemCount >= container.capacity then return end
|
||||
function Containers.init()
|
||||
importStyle 'container.otui'
|
||||
|
||||
local i = container.itemCount
|
||||
while i >= 1 do
|
||||
local itemWidget = container:getChildByIndex(i)
|
||||
if not itemWidget then return end
|
||||
|
||||
local nextItemWidget = container:getChildByIndex(i+1)
|
||||
if not nextItemWidget then return end
|
||||
|
||||
local swapItem = itemWidget:getItem()
|
||||
if swapItem then
|
||||
swapItem:setPosition(nextItemWidget.position)
|
||||
nextItemWidget:setItem(swapItem)
|
||||
end
|
||||
|
||||
i = i - 1
|
||||
end
|
||||
|
||||
local itemWidget = container:getChildByIndex(1)
|
||||
if not itemWidget then return end
|
||||
item:setPosition(itemWidget.position)
|
||||
itemWidget:setItem(item)
|
||||
|
||||
container.itemCount = container.itemCount + 1
|
||||
connect(Container, { onOpen = onContainerOpen,
|
||||
onClose = onContainerClose,
|
||||
onAddItem = onContainerAddItem,
|
||||
onUpdateItem = onContainerUpdateItem,
|
||||
onRemoveItem = onContainerRemoveItem })
|
||||
end
|
||||
|
||||
function Containers.onContainerUpdateItem(containerId, slot, item)
|
||||
local container = containers[containerId]
|
||||
if not container then return end
|
||||
|
||||
local itemWidget = container:getChildByIndex(slot + 1)
|
||||
if not itemWidget then return end
|
||||
itemWidget:setItem(item)
|
||||
item:setPosition(itemWidget.position)
|
||||
function Containers.terminate()
|
||||
disconnect(Container, { onOpen = onContainerOpen,
|
||||
onClose = onContainerClose,
|
||||
onAddItem = onContainerAddItem,
|
||||
onUpdateItem = onContainerUpdateItem,
|
||||
onRemoveItem = onContainerRemoveItem })
|
||||
end
|
||||
|
||||
function Containers.onContainerRemoveItem(containerId, slot)
|
||||
local container = containers[containerId]
|
||||
if not container then return end
|
||||
function Containers.clean()
|
||||
|
||||
local itemWidget = container:getChildByIndex(slot+1)
|
||||
if not itemWidget then return end
|
||||
itemWidget:setItem(nil)
|
||||
|
||||
for i=slot,container.itemCount-2 do
|
||||
local itemWidget = container:getChildByIndex(i+1)
|
||||
if not itemWidget then return end
|
||||
|
||||
local nextItemWidget = container:getChildByIndex(i+2)
|
||||
if not nextItemWidget then return end
|
||||
|
||||
local item = nextItemWidget:getItem()
|
||||
local pos = item:getPosition()
|
||||
pos.z = pos.z - 1
|
||||
item:setPosition(pos)
|
||||
|
||||
itemWidget:setItem(item)
|
||||
nextItemWidget:setItem(nil)
|
||||
end
|
||||
|
||||
container.itemCount = container.itemCount - 1
|
||||
end
|
||||
|
||||
connect(g_game, { onGameStart = Containers.clean,
|
||||
onGameEnd = Containers.clean,
|
||||
onOpenContainer = Containers.onOpenContainer,
|
||||
onCloseContainer = Containers.onCloseContainer,
|
||||
onContainerAddItem = Containers.onContainerAddItem,
|
||||
onContainerUpdateItem = Containers.onContainerUpdateItem,
|
||||
onContainerRemoveItem = Containers.onContainerRemoveItem })
|
||||
|
||||
|
|
|
@ -4,5 +4,12 @@ Module
|
|||
author: OTClient team
|
||||
website: https://github.com/edubart/otclient
|
||||
|
||||
dependecies:
|
||||
- game
|
||||
|
||||
@onLoad: |
|
||||
dofile 'containers'
|
||||
Containers.init()
|
||||
|
||||
@onUnload: |
|
||||
Containers.terminate()
|
||||
|
|
|
@ -135,6 +135,13 @@ void push_luavalue(const std::deque<T>& vec);
|
|||
template<typename T>
|
||||
bool luavalue_cast(int index, std::deque<T>& vec);
|
||||
|
||||
// map
|
||||
template<class K, class V>
|
||||
void push_luavalue(const std::map<K, V>& map);
|
||||
|
||||
template<class K, class V>
|
||||
bool luavalue_cast(int index, std::map<K, V>& map);
|
||||
|
||||
// tuple
|
||||
template<typename... Args>
|
||||
void push_luavalue(const std::tuple<Args...>& tuple);
|
||||
|
@ -299,6 +306,34 @@ bool luavalue_cast(int index, std::deque<T>& vec)
|
|||
return false;
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void push_luavalue(const std::map<K, V>& map)
|
||||
{
|
||||
g_lua.newTable();
|
||||
for(auto& it : map) {
|
||||
push_luavalue(it.first);
|
||||
push_luavalue(it.second);
|
||||
g_lua.rawSet();
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
bool luavalue_cast(int index, std::map<K, V>& map)
|
||||
{
|
||||
if(g_lua.isTable(index)) {
|
||||
g_lua.pushNil();
|
||||
while(g_lua.next(index < 0 ? index-1 : index)) {
|
||||
K key;
|
||||
V value;
|
||||
if(luavalue_cast(-1, value) && luavalue_cast(-2, key))
|
||||
map[key] = value;
|
||||
g_lua.pop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
struct push_tuple_luavalue {
|
||||
template<typename Tuple>
|
||||
|
|
|
@ -23,12 +23,14 @@
|
|||
#include "uigridlayout.h"
|
||||
#include "uiwidget.h"
|
||||
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
|
||||
UIGridLayout::UIGridLayout(UIWidgetPtr parentWidget): UILayout(parentWidget)
|
||||
{
|
||||
m_cellSize = Size(16,16);
|
||||
m_cellSpacing = 0;
|
||||
m_numColumns = 1;
|
||||
m_numLines = 1;
|
||||
m_numLines = 0;
|
||||
}
|
||||
|
||||
void UIGridLayout::applyStyle(const OTMLNodePtr& styleNode)
|
||||
|
@ -49,6 +51,12 @@ void UIGridLayout::applyStyle(const OTMLNodePtr& styleNode)
|
|||
setNumColumns(node->value<int>());
|
||||
else if(node->tag() == "num-lines")
|
||||
setNumLines(node->value<int>());
|
||||
else if(node->tag() == "fit-children")
|
||||
setFitChildren(node->value<bool>());
|
||||
else if(node->tag() == "auto-spacing")
|
||||
setAutoSpacing(node->value<bool>());
|
||||
else if(node->tag() == "flow")
|
||||
setFlow(node->value<bool>());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,24 +79,42 @@ bool UIGridLayout::internalUpdate()
|
|||
Rect clippingRect = parentWidget->getClippingRect();
|
||||
Point topLeft = clippingRect.topLeft();
|
||||
|
||||
int numColumns = m_numColumns;
|
||||
if(m_flow && m_cellSize.width() > 0)
|
||||
numColumns = clippingRect.width() / (m_cellSize.width() + m_cellSpacing);
|
||||
|
||||
int cellSpacing = m_cellSpacing;
|
||||
if(m_autoSpacing && numColumns > 1)
|
||||
cellSpacing = (clippingRect.width() - numColumns * m_cellSize.width()) / (numColumns - 1);
|
||||
|
||||
int index = 0;
|
||||
int preferredHeight = 0;
|
||||
for(const UIWidgetPtr& widget : widgets) {
|
||||
if(!widget->isExplicitlyVisible())
|
||||
continue;
|
||||
|
||||
int line = index / m_numColumns;
|
||||
int column = index % m_numColumns;
|
||||
Point virtualPos = Point(column * (m_cellSize.width() + m_cellSpacing), line * (m_cellSize.height() + m_cellSpacing));
|
||||
Point pos = topLeft + virtualPos;
|
||||
int line = index / numColumns;
|
||||
int column = index % numColumns;
|
||||
Point virtualPos = Point(column * (m_cellSize.width() + cellSpacing), line * (m_cellSize.height() + cellSpacing));
|
||||
preferredHeight = virtualPos.y + m_cellSize.height();
|
||||
Point pos = topLeft + virtualPos - parentWidget->getVirtualOffset();
|
||||
|
||||
if(widget->setRect(Rect(pos, m_cellSize)))
|
||||
changed = true;
|
||||
|
||||
index++;
|
||||
|
||||
if(index >= m_numColumns * m_numLines)
|
||||
if(m_numLines > 0 && index >= m_numColumns * m_numLines)
|
||||
break;
|
||||
}
|
||||
preferredHeight += parentWidget->getPaddingTop() + parentWidget->getPaddingBottom();
|
||||
|
||||
if(m_fitChildren && preferredHeight != parentWidget->getHeight()) {
|
||||
// must set the preferred height later
|
||||
g_eventDispatcher.addEvent([=] {
|
||||
parentWidget->setHeight(preferredHeight);
|
||||
});
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@ public:
|
|||
void setCellSpacing(int spacing) { m_cellSpacing = spacing; update(); }
|
||||
void setNumColumns(int columns) { m_numColumns = columns; update(); }
|
||||
void setNumLines(int lines) { m_numLines = lines; update(); }
|
||||
void setAutoSpacing(bool enable) { m_autoSpacing = enable; update(); }
|
||||
void setFitChildren(bool enable) { m_fitChildren = enable; update(); }
|
||||
void setFlow(bool enable) { m_flow = enable; update(); }
|
||||
|
||||
virtual UIGridLayoutPtr asUIGridLayout() { return nullptr; }
|
||||
|
||||
|
@ -51,6 +54,9 @@ private:
|
|||
int m_cellSpacing;
|
||||
int m_numColumns;
|
||||
int m_numLines;
|
||||
Boolean<false> m_autoSpacing;
|
||||
Boolean<false> m_fitChildren;
|
||||
Boolean<false> m_flow;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,7 +48,7 @@ bool UIHorizontalLayout::internalUpdate()
|
|||
bool changed = false;
|
||||
Rect clippingRect = parentWidget->getClippingRect();
|
||||
Point pos = (m_alignRight) ? clippingRect.topRight() : clippingRect.topLeft();
|
||||
int prefferedWidth = 0;
|
||||
int preferredWidth = 0;
|
||||
int gap;
|
||||
|
||||
for(const UIWidgetPtr& widget : widgets) {
|
||||
|
@ -59,7 +59,7 @@ bool UIHorizontalLayout::internalUpdate()
|
|||
|
||||
gap = (m_alignRight) ? -(widget->getMarginRight()+widget->getWidth()) : widget->getMarginLeft();
|
||||
pos.x += gap;
|
||||
prefferedWidth += gap;
|
||||
preferredWidth += gap;
|
||||
|
||||
if(widget->isFixedSize()) {
|
||||
// center it
|
||||
|
@ -77,16 +77,16 @@ bool UIHorizontalLayout::internalUpdate()
|
|||
gap = (m_alignRight) ? -widget->getMarginLeft() : (widget->getWidth() + widget->getMarginRight());
|
||||
gap += m_spacing;
|
||||
pos.x += gap;
|
||||
prefferedWidth += gap;
|
||||
preferredWidth += gap;
|
||||
}
|
||||
|
||||
prefferedWidth -= m_spacing;
|
||||
prefferedWidth += parentWidget->getPaddingLeft() + parentWidget->getPaddingRight();
|
||||
preferredWidth -= m_spacing;
|
||||
preferredWidth += parentWidget->getPaddingLeft() + parentWidget->getPaddingRight();
|
||||
|
||||
if(m_fitChildren && prefferedWidth != parentWidget->getWidth()) {
|
||||
// must set the preffered width later
|
||||
if(m_fitChildren && preferredWidth != parentWidget->getWidth()) {
|
||||
// must set the preferred width later
|
||||
g_eventDispatcher.addEvent([=] {
|
||||
parentWidget->setWidth(prefferedWidth);
|
||||
parentWidget->setWidth(preferredWidth);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ bool UIVerticalLayout::internalUpdate()
|
|||
|
||||
Rect clippingRect = parentWidget->getClippingRect();
|
||||
Point pos = (m_alignBottom) ? clippingRect.bottomLeft() : clippingRect.topLeft();
|
||||
int prefferedHeight = 0;
|
||||
int preferredHeight = 0;
|
||||
int gap;
|
||||
|
||||
for(const UIWidgetPtr& widget : widgets) {
|
||||
|
@ -60,7 +60,7 @@ bool UIVerticalLayout::internalUpdate()
|
|||
|
||||
gap = (m_alignBottom) ? -(widget->getMarginBottom()+widget->getHeight()) : widget->getMarginTop();
|
||||
pos.y += gap;
|
||||
prefferedHeight += gap;
|
||||
preferredHeight += gap;
|
||||
|
||||
if(widget->isFixedSize()) {
|
||||
// center it
|
||||
|
@ -78,16 +78,16 @@ bool UIVerticalLayout::internalUpdate()
|
|||
gap = (m_alignBottom) ? -widget->getMarginTop() : (widget->getHeight() + widget->getMarginBottom());
|
||||
gap += m_spacing;
|
||||
pos.y += gap;
|
||||
prefferedHeight += gap;
|
||||
preferredHeight += gap;
|
||||
}
|
||||
|
||||
prefferedHeight -= m_spacing;
|
||||
prefferedHeight += parentWidget->getPaddingTop() + parentWidget->getPaddingBottom();
|
||||
preferredHeight -= m_spacing;
|
||||
preferredHeight += parentWidget->getPaddingTop() + parentWidget->getPaddingBottom();
|
||||
|
||||
if(m_fitChildren && prefferedHeight != parentWidget->getHeight()) {
|
||||
// must set the preffered width later
|
||||
if(m_fitChildren && preferredHeight != parentWidget->getHeight()) {
|
||||
// must set the preferred width later
|
||||
g_eventDispatcher.addEvent([=] {
|
||||
parentWidget->setHeight(prefferedHeight);
|
||||
parentWidget->setHeight(preferredHeight);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1300,10 +1300,10 @@ void UIWidget::onGeometryChange(const Rect& oldRect, const Rect& newRect)
|
|||
updateText();
|
||||
|
||||
// move children that is outside the parent rect to inside again
|
||||
for(const UIWidgetPtr& child : m_children) {
|
||||
if(!child->isAnchored())
|
||||
child->bindRectToParent();
|
||||
}
|
||||
//for(const UIWidgetPtr& child : m_children) {
|
||||
//if(!child->isAnchored())
|
||||
//child->bindRectToParent();
|
||||
//}
|
||||
}
|
||||
|
||||
void UIWidget::onLayoutUpdate()
|
||||
|
|
|
@ -21,3 +21,80 @@
|
|||
*/
|
||||
|
||||
#include "container.h"
|
||||
#include "item.h"
|
||||
|
||||
Container::Container()
|
||||
{
|
||||
m_id = -1;
|
||||
m_itemId = 0;
|
||||
m_capacity = 20;
|
||||
m_name = "Container";
|
||||
m_hasParent = false;
|
||||
}
|
||||
|
||||
void Container::open(const ContainerPtr& previousContainer)
|
||||
{
|
||||
callLuaField("onOpen", previousContainer);
|
||||
}
|
||||
|
||||
void Container::close()
|
||||
{
|
||||
callLuaField("onClose");
|
||||
}
|
||||
|
||||
void Container::addItem(const ItemPtr& item)
|
||||
{
|
||||
m_items.push_front(item);
|
||||
updateItemsPositions();
|
||||
|
||||
callLuaField("onAddItem", 0, item);
|
||||
}
|
||||
|
||||
void Container::addItems(const std::vector<ItemPtr>& items)
|
||||
{
|
||||
for(const ItemPtr& item : items)
|
||||
m_items.push_back(item);
|
||||
updateItemsPositions();
|
||||
}
|
||||
|
||||
void Container::updateItem(int slot, const ItemPtr& item)
|
||||
{
|
||||
if(slot < 0 || slot >= (int)m_items.size()) {
|
||||
logTraceError("slot not found");
|
||||
return;
|
||||
}
|
||||
|
||||
ItemPtr oldItem = m_items[slot];
|
||||
m_items[slot] = item;
|
||||
item->setPosition(getSlotPosition(slot));
|
||||
|
||||
callLuaField("onUpdateItem", slot, item, oldItem);
|
||||
}
|
||||
|
||||
void Container::removeItem(int slot)
|
||||
{
|
||||
if(slot < 0 || slot >= (int)m_items.size()) {
|
||||
logTraceError("slot not found");
|
||||
return;
|
||||
}
|
||||
|
||||
ItemPtr item = m_items[slot];
|
||||
m_items.erase(m_items.begin() + slot);
|
||||
|
||||
updateItemsPositions();
|
||||
|
||||
callLuaField("onRemoveItem", slot, item);
|
||||
}
|
||||
|
||||
ItemPtr Container::getItem(int slot)
|
||||
{
|
||||
if(slot < 0 || slot >= (int)m_items.size())
|
||||
return nullptr;
|
||||
return m_items[slot];
|
||||
}
|
||||
|
||||
void Container::updateItemsPositions()
|
||||
{
|
||||
for(int slot = 0; slot < (int)m_items.size(); ++slot)
|
||||
m_items[slot]->setPosition(getSlotPosition(slot));
|
||||
}
|
||||
|
|
|
@ -32,6 +32,39 @@ class Container : public LuaObject
|
|||
public:
|
||||
Container();
|
||||
|
||||
void open(const ContainerPtr& previousContainer);
|
||||
void close();
|
||||
|
||||
void addItem(const ItemPtr& item);
|
||||
void addItems(const std::vector<ItemPtr>& items);
|
||||
void updateItem(int slot, const ItemPtr& item);
|
||||
void removeItem(int slot);
|
||||
ItemPtr getItem(int slot);
|
||||
|
||||
Position getSlotPosition(int slot) { return Position(0xffff, m_id | 0x40, slot); }
|
||||
|
||||
void setId(int id) { m_id = id; }
|
||||
void setCapacity(int capacity) { m_capacity = capacity; }
|
||||
void setName(std::string name) { m_name = name; }
|
||||
void setItemId(uint16 itemId) { m_itemId = itemId; }
|
||||
void setHasParent(bool hasParent) { m_hasParent = hasParent; }
|
||||
|
||||
std::string getName() { return m_name; }
|
||||
int getId() { return m_id; }
|
||||
int getCapacity() { return m_capacity; }
|
||||
int getItemsCount() { return m_items.size(); }
|
||||
uint16 getItemId() { return m_itemId; }
|
||||
bool hasParent() { return m_hasParent; }
|
||||
|
||||
private:
|
||||
void updateItemsPositions();
|
||||
|
||||
int m_id;
|
||||
int m_capacity;
|
||||
uint16 m_itemId;
|
||||
std::string m_name;
|
||||
bool m_hasParent;
|
||||
std::deque<ItemPtr> m_items;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "creature.h"
|
||||
#include "container.h"
|
||||
#include "statictext.h"
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/ui/uimanager.h>
|
||||
|
@ -166,30 +167,73 @@ void Game::processCreatureSpeak(const std::string& name, int level, Otc::SpeakTy
|
|||
g_lua.callGlobalField("g_game", "onCreatureSpeak", name, level, type, message, channelId, creaturePos);
|
||||
}
|
||||
|
||||
void Game::processOpenContainer(int containerId, int itemId, const std::string& name, int capacity, bool hasParent, const std::vector< ItemPtr >& items)
|
||||
void Game::processOpenContainer(int containerId, int itemId, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items)
|
||||
{
|
||||
g_lua.callGlobalField("g_game", "onOpenContainer", containerId, itemId, name, capacity, hasParent, items);
|
||||
ContainerPtr previousContainer = getContainer(containerId);
|
||||
ContainerPtr container = ContainerPtr(new Container());
|
||||
container->setId(containerId);
|
||||
container->setCapacity(capacity);
|
||||
container->setName(name);
|
||||
container->setItemId(itemId);
|
||||
container->setHasParent(hasParent);
|
||||
m_containers[containerId] = container;
|
||||
container->addItems(items);
|
||||
|
||||
container->open(previousContainer);
|
||||
if(previousContainer)
|
||||
previousContainer->close();
|
||||
}
|
||||
|
||||
void Game::processCloseContainer(int containerId)
|
||||
{
|
||||
g_lua.callGlobalField("g_game", "onCloseContainer", containerId);
|
||||
ContainerPtr container = getContainer(containerId);
|
||||
if(!container) {
|
||||
logTraceError("container not found");
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = m_containers.find(container->getId());
|
||||
if(it == m_containers.end() || it->second != container) {
|
||||
logTraceError("invalid container");
|
||||
return;
|
||||
}
|
||||
|
||||
m_containers.erase(it);
|
||||
|
||||
container->close();
|
||||
}
|
||||
|
||||
void Game::processContainerAddItem(int containerId, const ItemPtr& item)
|
||||
{
|
||||
item->setPosition(Position(65535, containerId + 0x40, 0));
|
||||
g_lua.callGlobalField("g_game", "onContainerAddItem", containerId, item);
|
||||
ContainerPtr container = getContainer(containerId);
|
||||
if(!container) {
|
||||
logTraceError("container not found");
|
||||
return;
|
||||
}
|
||||
|
||||
container->addItem(item);
|
||||
}
|
||||
|
||||
void Game::processContainerUpdateItem(int containerId, int slot, const ItemPtr& item)
|
||||
{
|
||||
g_lua.callGlobalField("g_game", "onContainerUpdateItem", containerId, slot, item);
|
||||
ContainerPtr container = getContainer(containerId);
|
||||
if(!container) {
|
||||
logTraceError("container not found");
|
||||
return;
|
||||
}
|
||||
|
||||
container->updateItem(slot, item);
|
||||
}
|
||||
|
||||
void Game::processContainerRemoveItem(int containerId, int slot)
|
||||
{
|
||||
g_lua.callGlobalField("g_game", "onContainerRemoveItem", containerId, slot);
|
||||
ContainerPtr container = getContainer(containerId);
|
||||
if(!container) {
|
||||
logTraceError("container not found");
|
||||
return;
|
||||
}
|
||||
|
||||
container->removeItem(slot);
|
||||
}
|
||||
|
||||
void Game::processInventoryChange(int slot, const ItemPtr& item)
|
||||
|
@ -542,19 +586,37 @@ void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing)
|
|||
m_protocolGame->sendUseItemWith(pos, itemId, 0, toThing->getPosition(), toThing->getId(), toThing->getStackpos());
|
||||
}
|
||||
|
||||
void Game::open(const ItemPtr& item, int containerId)
|
||||
void Game::open(const ItemPtr& item, const ContainerPtr& previousContainer)
|
||||
{
|
||||
if(!canPerformGameAction() || !item)
|
||||
return;
|
||||
|
||||
m_protocolGame->sendUseItem(item->getPosition(), item->getId(), item->getStackpos(), containerId);
|
||||
int id = 0;
|
||||
if(!previousContainer) {
|
||||
// find a free container id
|
||||
while(m_containers.find(id) != m_containers.end())
|
||||
id++;
|
||||
} else {
|
||||
id = previousContainer->getId();
|
||||
}
|
||||
|
||||
m_protocolGame->sendUseItem(item->getPosition(), item->getId(), item->getStackpos(), id);
|
||||
}
|
||||
|
||||
void Game::upContainer(int containerId)
|
||||
void Game::openParent(const ContainerPtr& container)
|
||||
{
|
||||
if(!canPerformGameAction())
|
||||
return;
|
||||
m_protocolGame->sendUpContainer(containerId);
|
||||
|
||||
m_protocolGame->sendUpContainer(container->getId());
|
||||
}
|
||||
|
||||
void Game::close(const ContainerPtr& container)
|
||||
{
|
||||
if(!canPerformGameAction())
|
||||
return;
|
||||
|
||||
m_protocolGame->sendCloseContainer(container->getId());
|
||||
}
|
||||
|
||||
void Game::refreshContainer()
|
||||
|
|
|
@ -139,8 +139,9 @@ public:
|
|||
void useInventoryItemWith(int itemId, const ThingPtr& toThing);
|
||||
|
||||
// container related
|
||||
void open(const ItemPtr& item, int containerId);
|
||||
void upContainer(int containerId);
|
||||
void open(const ItemPtr& item, const ContainerPtr& previousContainer);
|
||||
void openParent(const ContainerPtr& container);
|
||||
void close(const ContainerPtr& container);
|
||||
void refreshContainer();
|
||||
|
||||
// attack/follow related
|
||||
|
@ -218,6 +219,7 @@ public:
|
|||
bool isFollowing() { return !!m_followingCreature; }
|
||||
|
||||
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
||||
std::map<int, ContainerPtr> getContainers() { return m_containers; }
|
||||
CreaturePtr getAttackingCreature() { return m_attackingCreature; }
|
||||
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
||||
int getServerBeat() { return m_serverBeat; }
|
||||
|
|
|
@ -56,8 +56,10 @@ const TilePtr& Thing::getTile()
|
|||
|
||||
ContainerPtr Thing::getParentContainer()
|
||||
{
|
||||
if(m_position.x == 0xFFFF && m_position.y & 0x40)
|
||||
return g_game.getContainer(m_position.z);
|
||||
if(m_position.x == 0xffff && m_position.y & 0x40) {
|
||||
int containerId = m_position.y ^ 0x40;
|
||||
return g_game.getContainer(containerId);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,8 @@ void OTClient::registerLuaFunctions()
|
|||
g_lua.bindClassStaticFunction("g_game", "useInventoryItem", std::bind(&Game::useInventoryItem, &g_game, _1));
|
||||
g_lua.bindClassStaticFunction("g_game", "useInventoryItemWith", std::bind(&Game::useInventoryItemWith, &g_game, _1, _2));
|
||||
g_lua.bindClassStaticFunction("g_game", "open", std::bind(&Game::open, &g_game, _1, _2));
|
||||
g_lua.bindClassStaticFunction("g_game", "upContainer", std::bind(&Game::upContainer, &g_game, _1));
|
||||
g_lua.bindClassStaticFunction("g_game", "openParent", std::bind(&Game::openParent, &g_game, _1));
|
||||
g_lua.bindClassStaticFunction("g_game", "close", std::bind(&Game::close, &g_game, _1));
|
||||
g_lua.bindClassStaticFunction("g_game", "refreshContainer", std::bind(&Game::refreshContainer, &g_game));
|
||||
g_lua.bindClassStaticFunction("g_game", "attack", std::bind(&Game::attack, &g_game, _1));
|
||||
g_lua.bindClassStaticFunction("g_game", "cancelAttack", std::bind(&Game::cancelAttack, &g_game));
|
||||
|
@ -147,6 +148,8 @@ void OTClient::registerLuaFunctions()
|
|||
g_lua.bindClassStaticFunction("g_game", "isDead", std::bind(&Game::isDead, &g_game));
|
||||
g_lua.bindClassStaticFunction("g_game", "isAttacking", std::bind(&Game::isAttacking, &g_game));
|
||||
g_lua.bindClassStaticFunction("g_game", "isFollowing", std::bind(&Game::isFollowing, &g_game));
|
||||
g_lua.bindClassStaticFunction("g_game", "getContainer", std::bind(&Game::getContainer, &g_game, _1));
|
||||
g_lua.bindClassStaticFunction("g_game", "getContainers", std::bind(&Game::getContainers, &g_game));
|
||||
g_lua.bindClassStaticFunction("g_game", "getAttackingCreature", std::bind(&Game::getAttackingCreature, &g_game));
|
||||
g_lua.bindClassStaticFunction("g_game", "getFollowingCreature", std::bind(&Game::getFollowingCreature, &g_game));
|
||||
g_lua.bindClassStaticFunction("g_game", "getServerBeat", std::bind(&Game::getServerBeat, &g_game));
|
||||
|
@ -165,6 +168,26 @@ void OTClient::registerLuaFunctions()
|
|||
g_lua.registerClass<ProtocolGame, Protocol>();
|
||||
|
||||
g_lua.registerClass<Container>();
|
||||
g_lua.bindClassStaticFunction<Container>("create", []{ return ContainerPtr(new Container); });
|
||||
g_lua.bindClassMemberFunction<Container>("open", &Container::open);
|
||||
g_lua.bindClassMemberFunction<Container>("close", &Container::close);
|
||||
g_lua.bindClassMemberFunction<Container>("addItem", &Container::addItem);
|
||||
g_lua.bindClassMemberFunction<Container>("addItems", &Container::addItems);
|
||||
g_lua.bindClassMemberFunction<Container>("updateItem", &Container::updateItem);
|
||||
g_lua.bindClassMemberFunction<Container>("removeItem", &Container::removeItem);
|
||||
g_lua.bindClassMemberFunction<Container>("getItem", &Container::getItem);
|
||||
g_lua.bindClassMemberFunction<Container>("getSlotPosition", &Container::getSlotPosition);
|
||||
g_lua.bindClassMemberFunction<Container>("setId", &Container::setId);
|
||||
g_lua.bindClassMemberFunction<Container>("setCapacity", &Container::setCapacity);
|
||||
g_lua.bindClassMemberFunction<Container>("setName", &Container::setName);
|
||||
g_lua.bindClassMemberFunction<Container>("setItemId", &Container::setItemId);
|
||||
g_lua.bindClassMemberFunction<Container>("setHasParent", &Container::setHasParent);
|
||||
g_lua.bindClassMemberFunction<Container>("getName", &Container::getName);
|
||||
g_lua.bindClassMemberFunction<Container>("getId", &Container::getId);
|
||||
g_lua.bindClassMemberFunction<Container>("getCapacity", &Container::getCapacity);
|
||||
g_lua.bindClassMemberFunction<Container>("getItemsCount", &Container::getItemsCount);
|
||||
g_lua.bindClassMemberFunction<Container>("getItemId", &Container::getItemId);
|
||||
g_lua.bindClassMemberFunction<Container>("hasParent", &Container::hasParent);
|
||||
|
||||
g_lua.registerClass<Thing>();
|
||||
g_lua.bindClassMemberFunction<Thing>("setId", &Thing::setId);
|
||||
|
|
|
@ -35,18 +35,17 @@ void UIItem::drawSelf()
|
|||
UIWidget::drawSelf();
|
||||
|
||||
if(m_item) {
|
||||
Point topLeft = m_rect.bottomRight() - Point(32, 32) + Point(m_padding.left, m_padding.top);
|
||||
Rect drawRect = getClippingRect();
|
||||
float scaleFactor = std::min(drawRect.width() / 32.0f, drawRect.height() / 32.0f);
|
||||
|
||||
g_painter.setColor(Color::white);
|
||||
m_item->draw(topLeft, 1, true);
|
||||
m_item->draw(drawRect.topLeft(), scaleFactor, true);
|
||||
|
||||
if(m_font && m_item->isStackable() && m_item->getCount() > 1) {
|
||||
std::string count = Fw::tostring(m_item->getCount());
|
||||
g_painter.setColor(Color(231, 231, 231));
|
||||
m_font->drawText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight);
|
||||
}
|
||||
|
||||
//m_font->renderText(Fw::unsafeCast<std::string>(m_item->getId()), m_rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue