mirror of
https://github.com/edubart/otclient.git
synced 2025-10-15 12:04:55 +02:00
Minimap, hotkeys and lot of other changes
* Begin working on a new layout system for UIMinimap and later UIMap, this new layout system allows to add widgets to the minimap * Add option to disable motd * Rework hotkey binding * Lots of fixes in hotkeys manager * Add fullmap view using Ctrl+Shift+M * Prevent some crashs in ThingType draw * Add function to load minimap from PNG files * Fixes in minimap saving * Fixes in Tile::isClickable * Add UIMapAnchorLayout, new layout for maps * Fix freezes in win32 when pressing alt key
This commit is contained in:
@@ -98,6 +98,8 @@ set(client_SOURCES ${client_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiminimap.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uimapanchorlayout.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uimapanchorlayout.h
|
||||
|
||||
# util
|
||||
${CMAKE_CURRENT_LIST_DIR}/position.h
|
||||
|
@@ -94,11 +94,15 @@ class UICreature;
|
||||
class UIMap;
|
||||
class UIMinimap;
|
||||
class UIProgressRect;
|
||||
class UIMapAnchorLayout;
|
||||
class UIPositionAnchor;
|
||||
|
||||
typedef stdext::shared_object_ptr<UIItem> UIItemPtr;
|
||||
typedef stdext::shared_object_ptr<UICreature> UICreaturePtr;
|
||||
typedef stdext::shared_object_ptr<UIMap> UIMapPtr;
|
||||
typedef stdext::shared_object_ptr<UIMinimap> UIMinimapPtr;
|
||||
typedef stdext::shared_object_ptr<UIProgressRect> UIProgressRectPtr;
|
||||
typedef stdext::shared_object_ptr<UIMapAnchorLayout> UIMapAnchorLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIPositionAnchor> UIPositionAnchorPtr;
|
||||
|
||||
#endif
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#include "uicreature.h"
|
||||
#include "uimap.h"
|
||||
#include "uiminimap.h"
|
||||
#include "uimapanchorlayout.h"
|
||||
#include "uiprogressrect.h"
|
||||
#include "outfit.h"
|
||||
|
||||
@@ -121,6 +122,8 @@ void Client::registerLuaFunctions()
|
||||
|
||||
g_lua.registerSingletonClass("g_minimap");
|
||||
g_lua.bindSingletonFunction("g_minimap", "clean", &Minimap::clean, &g_minimap);
|
||||
g_lua.bindSingletonFunction("g_minimap", "loadImage", &Minimap::loadImage, &g_minimap);
|
||||
g_lua.bindSingletonFunction("g_minimap", "saveImage", &Minimap::saveImage, &g_minimap);
|
||||
g_lua.bindSingletonFunction("g_minimap", "loadOtmm", &Minimap::loadOtmm, &g_minimap);
|
||||
g_lua.bindSingletonFunction("g_minimap", "saveOtmm", &Minimap::saveOtmm, &g_minimap);
|
||||
|
||||
@@ -597,20 +600,24 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("setMixZoom", &UIMinimap::setMinZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("setMaxZoom", &UIMinimap::setMaxZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("setCameraPosition", &UIMinimap::setCameraPosition);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("setCross", &UIMinimap::setCross);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("followCreature", &UIMinimap::followCreature);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getPoint", &UIMinimap::getPoint);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getPosition", &UIMinimap::getPosition);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("floorUp", &UIMinimap::floorUp);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("floorDown", &UIMinimap::floorDown);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getTilePoint", &UIMinimap::getTilePoint);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getTilePosition", &UIMinimap::getTilePosition);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getTileRect", &UIMinimap::getTileRect);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getCameraPosition", &UIMinimap::getCameraPosition);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getFollowingCreature", &UIMinimap::getFollowingCreature);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getMinZoom", &UIMinimap::getMinZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getMaxZoom", &UIMinimap::getMaxZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getZoom", &UIMinimap::getZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getCross", &UIMinimap::getCross);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getScale", &UIMinimap::getScale);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getScale", &UIMinimap::getScale);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("anchorPosition", &UIMinimap::anchorPosition);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("fillPosition", &UIMinimap::fillPosition);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("centerInPosition", &UIMinimap::centerInPosition);
|
||||
|
||||
g_lua.registerClass<UIProgressRect, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UIProgressRect>("create", []{ return UIProgressRectPtr(new UIProgressRect); } );
|
||||
g_lua.bindClassMemberFunction<UIProgressRect>("setPercent", &UIProgressRect::setPercent);
|
||||
g_lua.bindClassMemberFunction<UIProgressRect>("getPercent", &UIProgressRect::getPercent);
|
||||
|
||||
g_lua.registerClass<UIMapAnchorLayout, UIAnchorLayout>();
|
||||
}
|
||||
|
@@ -621,6 +621,8 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
|
||||
wasSeen = mtile.hasFlag(MinimapTileWasSeen);
|
||||
isNotWalkable = mtile.hasFlag(MinimapTileNotWalkable);
|
||||
isNotPathable = mtile.hasFlag(MinimapTileNotPathable);
|
||||
if(isNotWalkable || isNotPathable)
|
||||
wasSeen = true;
|
||||
speed = mtile.getSpeed();
|
||||
}
|
||||
|
||||
|
@@ -23,13 +23,14 @@
|
||||
|
||||
#include "minimap.h"
|
||||
#include "tile.h"
|
||||
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
#include <framework/graphics/painter.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <zlib.h>
|
||||
|
||||
Minimap g_minimap;
|
||||
@@ -51,10 +52,14 @@ void MinimapBlock::update()
|
||||
bool shouldDraw = false;
|
||||
for(int x=0;x<MMBLOCK_SIZE;++x) {
|
||||
for(int y=0;y<MMBLOCK_SIZE;++y) {
|
||||
uint32 col = Color::from8bit(getTile(x, y).color).rgba();
|
||||
image->setPixel(x, y, col);
|
||||
if(col != 0)
|
||||
uint8 c = getTile(x, y).color;
|
||||
uint32 col;
|
||||
if(c != 255) {
|
||||
col = Color::from8bit(c).rgba();
|
||||
shouldDraw = true;
|
||||
} else
|
||||
col = Color::alpha.rgba();
|
||||
image->setPixel(x, y, col);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,14 +98,14 @@ void Minimap::clean()
|
||||
m_tileBlocks[i].clear();
|
||||
}
|
||||
|
||||
void Minimap::draw(const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
void Minimap::draw(const Rect& screenRect, const Position& mapCenter, float scale, const Color& color)
|
||||
{
|
||||
if(screenRect.isEmpty())
|
||||
return;
|
||||
|
||||
Rect mapRect = calcMapRect(screenRect, mapCenter, scale);
|
||||
g_painter->saveState();
|
||||
g_painter->setColor(Color::black);
|
||||
g_painter->setColor(color);
|
||||
g_painter->drawFilledRect(screenRect);
|
||||
g_painter->resetColor();
|
||||
g_painter->setClipRect(screenRect);
|
||||
@@ -137,15 +142,16 @@ void Minimap::draw(const Rect& screenRect, const Position& mapCenter, float scal
|
||||
tex->setSmooth(scale < 1.0f);
|
||||
g_painter->drawTexturedRect(dest, tex, src);
|
||||
}
|
||||
//g_painter->drawBoundingRect(Rect(xs,ys, MMBLOCK_SIZE * scale, MMBLOCK_SIZE * scale));
|
||||
}
|
||||
}
|
||||
|
||||
g_painter->restoreSavedState();
|
||||
}
|
||||
|
||||
Point Minimap::getPoint(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
Point Minimap::getTilePoint(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
if(screenRect.isEmpty() || MMBLOCK_SIZE*scale <= 1 || !mapCenter.isMapPosition())
|
||||
if(screenRect.isEmpty() || pos.z != mapCenter.z)
|
||||
return Point(-1,-1);
|
||||
|
||||
Rect mapRect = calcMapRect(screenRect, mapCenter, scale);
|
||||
@@ -154,9 +160,9 @@ Point Minimap::getPoint(const Position& pos, const Rect& screenRect, const Posit
|
||||
return posoff + screenRect.topLeft() - off + (Point(1,1)*scale)/2;
|
||||
}
|
||||
|
||||
Position Minimap::getPosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
Position Minimap::getTilePosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
if(screenRect.isEmpty() || MMBLOCK_SIZE*scale <= 1 || !mapCenter.isMapPosition())
|
||||
if(screenRect.isEmpty())
|
||||
return Position();
|
||||
|
||||
Rect mapRect = calcMapRect(screenRect, mapCenter, scale);
|
||||
@@ -165,24 +171,25 @@ Position Minimap::getPosition(const Point& point, const Rect& screenRect, const
|
||||
return Position(pos2d.x, pos2d.y, mapCenter.z);
|
||||
}
|
||||
|
||||
Rect Minimap::getTileRect(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
if(screenRect.isEmpty() || pos.z != mapCenter.z)
|
||||
return Rect();
|
||||
|
||||
int tileSize = 32 * scale;
|
||||
Rect tileRect(0,0,tileSize, tileSize);
|
||||
tileRect.moveCenter(getTilePoint(pos, screenRect, mapCenter, scale));
|
||||
return tileRect;
|
||||
}
|
||||
|
||||
Rect Minimap::calcMapRect(const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
int w, h;
|
||||
do {
|
||||
w = std::ceil(screenRect.width() / scale);
|
||||
h = std::ceil(screenRect.height() / scale);
|
||||
if(w % 2 == 0)
|
||||
w++;
|
||||
if(h % 2 == 0)
|
||||
h++;
|
||||
scale *= 2;
|
||||
} while(w > 8192 || h > 8192);
|
||||
int w = screenRect.width() / scale, h = std::ceil(screenRect.height() / scale);
|
||||
Rect mapRect(0,0,w,h);
|
||||
mapRect.moveCenter(Point(mapCenter.x, mapCenter.y));
|
||||
return mapRect;
|
||||
}
|
||||
|
||||
|
||||
void Minimap::updateTile(const Position& pos, const TilePtr& tile)
|
||||
{
|
||||
MinimapTile minimapTile;
|
||||
@@ -200,6 +207,7 @@ void Minimap::updateTile(const Position& pos, const TilePtr& tile)
|
||||
MinimapBlock& block = getBlock(pos);
|
||||
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
|
||||
block.updateTile(pos.x - offsetPos.x, pos.y - offsetPos.y, minimapTile);
|
||||
block.justSaw();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +222,87 @@ const MinimapTile& Minimap::getTile(const Position& pos)
|
||||
return nulltile;
|
||||
}
|
||||
|
||||
bool Minimap::loadImage(const std::string& fileName, const Position& topLeft, float colorFactor)
|
||||
{
|
||||
if(colorFactor <= 0.01f)
|
||||
colorFactor = 1.0f;
|
||||
|
||||
try {
|
||||
ImagePtr image = Image::load(fileName);
|
||||
|
||||
uint8 waterc = Color::to8bit(std::string("#3300cc"));
|
||||
|
||||
// non pathable colors
|
||||
Color nonPathableColors[] = {
|
||||
std::string("#ffff00"), // yellow
|
||||
};
|
||||
|
||||
// non walkable colors
|
||||
Color nonWalkableColors[] = {
|
||||
std::string("#000000"), // oil, black
|
||||
std::string("#006600"), // trees, dark green
|
||||
std::string("#ff3300"), // walls, red
|
||||
std::string("#666666"), // mountain, grey
|
||||
std::string("#ff6600"), // lava, orange
|
||||
std::string("#00ff00"), // positon
|
||||
std::string("#ccffff"), // ice, very light blue
|
||||
};
|
||||
|
||||
for(int y=0;y<image->getHeight();++y) {
|
||||
for(int x=0;x<image->getWidth();++x) {
|
||||
Color color = *(uint32*)image->getPixel(x,y);
|
||||
uint8 c = Color::to8bit(color * colorFactor);
|
||||
int flags = 0;
|
||||
|
||||
if(c == waterc || color.a() == 0) {
|
||||
flags |= MinimapTileNotWalkable;
|
||||
c = 255; // alpha
|
||||
}
|
||||
|
||||
if(flags != 0) {
|
||||
for(Color &col : nonWalkableColors) {
|
||||
if(col == color) {
|
||||
flags |= MinimapTileNotWalkable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(flags != 0) {
|
||||
for(Color &col : nonPathableColors) {
|
||||
if(col == color) {
|
||||
flags |= MinimapTileNotPathable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(c == 255)
|
||||
continue;
|
||||
|
||||
Position pos(topLeft.x + x, topLeft.y + y, topLeft.z);
|
||||
MinimapBlock& block = getBlock(pos);
|
||||
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
|
||||
MinimapTile& tile = block.getTile(pos.x - offsetPos.x, pos.y - offsetPos.y);
|
||||
if(!(tile.flags & MinimapTileWasSeen)) {
|
||||
tile.color = c;
|
||||
tile.flags = flags;
|
||||
block.mustUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("failed to load OTMM minimap: %s", e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Minimap::saveImage(const std::string& fileName, const Rect& mapRect)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
bool Minimap::loadOtmm(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
@@ -263,6 +352,7 @@ bool Minimap::loadOtmm(const std::string& fileName)
|
||||
assert(ret == Z_OK);
|
||||
assert(destLen == blockSize);
|
||||
block.mustUpdate();
|
||||
block.justSaw();
|
||||
}
|
||||
|
||||
fin->close();
|
||||
@@ -307,6 +397,9 @@ void Minimap::saveOtmm(const std::string& fileName)
|
||||
for(auto& it : m_tileBlocks[z]) {
|
||||
int index = it.first;
|
||||
MinimapBlock& block = it.second;
|
||||
if(!block.wasSeen())
|
||||
continue;
|
||||
|
||||
Position pos = getIndexPosition(index, z);
|
||||
fin->addU16(pos.x);
|
||||
fin->addU16(pos.y);
|
||||
@@ -319,7 +412,7 @@ void Minimap::saveOtmm(const std::string& fileName)
|
||||
fin->write(compressBuffer.data(), len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// end of file
|
||||
Position invalidPos;
|
||||
fin->addU16(invalidPos.x);
|
||||
|
@@ -42,7 +42,7 @@ enum MinimapTileFlags {
|
||||
#pragma pack(push,1) // disable memory alignment
|
||||
struct MinimapTile
|
||||
{
|
||||
MinimapTile() : flags(0), color(0), speed(10) { }
|
||||
MinimapTile() : flags(0), color(255), speed(10) { }
|
||||
uint8 flags;
|
||||
uint8 color;
|
||||
uint8 speed;
|
||||
@@ -64,10 +64,13 @@ public:
|
||||
const TexturePtr& getTexture() { return m_texture; }
|
||||
std::array<MinimapTile, MMBLOCK_SIZE *MMBLOCK_SIZE>& getTiles() { return m_tiles; }
|
||||
void mustUpdate() { m_mustUpdate = true; }
|
||||
void justSaw() { m_wasSeen = true; }
|
||||
bool wasSeen() { return m_wasSeen; }
|
||||
private:
|
||||
TexturePtr m_texture;
|
||||
std::array<MinimapTile, MMBLOCK_SIZE *MMBLOCK_SIZE> m_tiles;
|
||||
stdext::boolean<true> m_mustUpdate;
|
||||
stdext::boolean<false> m_wasSeen;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
@@ -81,13 +84,16 @@ public:
|
||||
|
||||
void clean();
|
||||
|
||||
void draw(const Rect& screenRect, const Position& mapCenter, float scale);
|
||||
Point getPoint(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale);
|
||||
Position getPosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale);
|
||||
void draw(const Rect& screenRect, const Position& mapCenter, float scale, const Color& color);
|
||||
Point getTilePoint(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale);
|
||||
Position getTilePosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale);
|
||||
Rect getTileRect(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale);
|
||||
|
||||
void updateTile(const Position& pos, const TilePtr& tile);
|
||||
const MinimapTile& getTile(const Position& pos);
|
||||
|
||||
bool loadImage(const std::string& fileName, const Position& topLeft, float colorFactor);
|
||||
void saveImage(const std::string& fileName, const Rect& mapRect);
|
||||
bool loadOtmm(const std::string& fileName);
|
||||
void saveOtmm(const std::string& fileName);
|
||||
|
||||
|
@@ -763,6 +763,9 @@ void ProtocolGame::parseMagicEffect(const InputMessagePtr& msg)
|
||||
else
|
||||
effectId = msg->getU8();
|
||||
|
||||
if(!g_things.isValidDatId(effectId, ThingCategoryEffect))
|
||||
g_logger.traceError("invalid effect id");
|
||||
|
||||
EffectPtr effect = EffectPtr(new Effect());
|
||||
effect->setId(effectId);
|
||||
g_map.addThing(effect, pos);
|
||||
@@ -786,6 +789,9 @@ void ProtocolGame::parseDistanceMissile(const InputMessagePtr& msg)
|
||||
Position toPos = getPosition(msg);
|
||||
int shotId = msg->getU8();
|
||||
|
||||
if(!g_things.isValidDatId(shotId, ThingCategoryMissile))
|
||||
g_logger.traceError("invalid effect id");
|
||||
|
||||
MissilePtr missile = MissilePtr(new Missile());
|
||||
missile->setId(shotId);
|
||||
missile->setPath(fromPos, toPos);
|
||||
@@ -1642,6 +1648,9 @@ Outfit ProtocolGame::getOutfit(const InputMessagePtr& msg)
|
||||
int feet = msg->getU8();
|
||||
int addons = msg->getU8();
|
||||
|
||||
if(!g_things.isValidDatId(lookType, ThingCategoryCreature))
|
||||
lookType = 0;
|
||||
|
||||
outfit.setId(lookType);
|
||||
outfit.setHead(head);
|
||||
outfit.setBody(body);
|
||||
@@ -1653,9 +1662,11 @@ Outfit ProtocolGame::getOutfit(const InputMessagePtr& msg)
|
||||
int lookTypeEx = msg->getU16();
|
||||
if(lookTypeEx == 0) {
|
||||
outfit.setCategory(ThingCategoryEffect);
|
||||
outfit.setAuxId(13);
|
||||
outfit.setAuxId(13); // invisible effect id
|
||||
}
|
||||
else {
|
||||
if(!g_things.isValidDatId(lookTypeEx, ThingCategoryItem))
|
||||
lookTypeEx = 0;
|
||||
outfit.setCategory(ThingCategoryItem);
|
||||
outfit.setAuxId(lookTypeEx);
|
||||
}
|
||||
|
@@ -164,9 +164,17 @@ void ThingType::draw(const Point& dest, float scaleFactor, int layer, int xPatte
|
||||
if(m_null)
|
||||
return;
|
||||
|
||||
const TexturePtr& texture = getTexture(animationPhase); // texture might not exists, neither its rects.
|
||||
if(animationPhase >= m_animationPhases)
|
||||
return;
|
||||
|
||||
const TexturePtr& texture = getTexture(animationPhase); // texture might not exists, neither its rects.
|
||||
if(!texture)
|
||||
return;
|
||||
|
||||
uint frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
|
||||
if(frameIndex >= m_texturesFramesRects[animationPhase].size())
|
||||
return;
|
||||
|
||||
int frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
|
||||
Point textureOffset;
|
||||
Rect textureRect;
|
||||
|
||||
|
@@ -338,7 +338,7 @@ int Tile::getGroundSpeed()
|
||||
|
||||
uint8 Tile::getMinimapColorByte()
|
||||
{
|
||||
uint8 color = 0;
|
||||
uint8 color = 255; // alpha
|
||||
if(m_minimapColor != 0) {
|
||||
return m_minimapColor;
|
||||
}
|
||||
@@ -542,18 +542,8 @@ bool Tile::isLookPossible()
|
||||
|
||||
bool Tile::isClickable()
|
||||
{
|
||||
bool hasGround = false;
|
||||
bool hasOnBottom = false;
|
||||
bool hasIgnoreLook = false;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isGround())
|
||||
hasGround = true;
|
||||
if(thing->isOnBottom())
|
||||
hasOnBottom = true;
|
||||
if(thing->isIgnoreLook())
|
||||
hasIgnoreLook = true;
|
||||
|
||||
if((hasGround || hasOnBottom) && !hasIgnoreLook)
|
||||
if(!thing->isOnTop() && !thing->isIgnoreLook())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
92
src/client/uimapanchorlayout.cpp
Normal file
92
src/client/uimapanchorlayout.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "declarations.h"
|
||||
#include "uimapanchorlayout.h"
|
||||
#include "uiminimap.h"
|
||||
#include <framework/ui/uiwidget.h>
|
||||
|
||||
int UIPositionAnchor::getHookedPoint(const UIWidgetPtr& hookedWidget, const UIWidgetPtr& parentWidget)
|
||||
{
|
||||
UIMinimapPtr minimap = hookedWidget->static_self_cast<UIMinimap>();
|
||||
Rect hookedRect = minimap->getTileRect(m_hookedPosition);
|
||||
int point = 0;
|
||||
if(hookedRect.isValid()) {
|
||||
switch(m_hookedEdge) {
|
||||
case Fw::AnchorLeft:
|
||||
point = hookedRect.left();
|
||||
break;
|
||||
case Fw::AnchorRight:
|
||||
point = hookedRect.right();
|
||||
break;
|
||||
case Fw::AnchorTop:
|
||||
point = hookedRect.top();
|
||||
break;
|
||||
case Fw::AnchorBottom:
|
||||
point = hookedRect.bottom();
|
||||
break;
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
point = hookedRect.horizontalCenter();
|
||||
break;
|
||||
case Fw::AnchorVerticalCenter:
|
||||
point = hookedRect.verticalCenter();
|
||||
break;
|
||||
default:
|
||||
// must never happens
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
void UIMapAnchorLayout::addPositionAnchor(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge anchoredEdge, const Position& hookedPosition, Fw::AnchorEdge hookedEdge)
|
||||
{
|
||||
if(!anchoredWidget)
|
||||
return;
|
||||
|
||||
assert(anchoredWidget != getParentWidget());
|
||||
|
||||
UIPositionAnchorPtr anchor(new UIPositionAnchor(anchoredEdge, hookedPosition, hookedEdge));
|
||||
UIAnchorGroupPtr& anchorGroup = m_anchorsGroups[anchoredWidget];
|
||||
if(!anchorGroup)
|
||||
anchorGroup = UIAnchorGroupPtr(new UIAnchorGroup);
|
||||
|
||||
anchorGroup->addAnchor(anchor);
|
||||
|
||||
// layout must be updated because a new anchor got in
|
||||
update();
|
||||
}
|
||||
|
||||
void UIMapAnchorLayout::centerInPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition)
|
||||
{
|
||||
addPositionAnchor(anchoredWidget, Fw::AnchorHorizontalCenter, hookedPosition, Fw::AnchorHorizontalCenter);
|
||||
addPositionAnchor(anchoredWidget, Fw::AnchorVerticalCenter, hookedPosition, Fw::AnchorVerticalCenter);
|
||||
}
|
||||
|
||||
void UIMapAnchorLayout::fillPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition)
|
||||
{
|
||||
addPositionAnchor(anchoredWidget, Fw::AnchorLeft, hookedPosition, Fw::AnchorLeft);
|
||||
addPositionAnchor(anchoredWidget, Fw::AnchorRight, hookedPosition, Fw::AnchorRight);
|
||||
addPositionAnchor(anchoredWidget, Fw::AnchorTop, hookedPosition, Fw::AnchorTop);
|
||||
addPositionAnchor(anchoredWidget, Fw::AnchorBottom, hookedPosition, Fw::AnchorBottom);
|
||||
}
|
55
src/client/uimapanchorlayout.h
Normal file
55
src/client/uimapanchorlayout.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UIMAPANCHORLAYOUT_H
|
||||
#define UIMAPANCHORLAYOUT_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/ui/uianchorlayout.h>
|
||||
|
||||
class UIPositionAnchor : public UIAnchor
|
||||
{
|
||||
public:
|
||||
UIPositionAnchor(Fw::AnchorEdge anchoredEdge, const Position& hookedPosition, Fw::AnchorEdge hookedEdge) :
|
||||
UIAnchor(anchoredEdge, std::string(), hookedEdge), m_hookedPosition(hookedPosition) { }
|
||||
|
||||
UIWidgetPtr getHookedWidget(const UIWidgetPtr& widget, const UIWidgetPtr& parentWidget) { return parentWidget; }
|
||||
int getHookedPoint(const UIWidgetPtr& hookedWidget, const UIWidgetPtr& parentWidget);
|
||||
|
||||
private:
|
||||
Position m_hookedPosition;
|
||||
};
|
||||
|
||||
class UIMapAnchorLayout : public UIAnchorLayout
|
||||
{
|
||||
public:
|
||||
UIMapAnchorLayout(UIWidgetPtr parentWidget) : UIAnchorLayout(parentWidget) { }
|
||||
|
||||
void addPositionAnchor(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge anchoredEdge,
|
||||
const Position& hookedPosition, Fw::AnchorEdge hookedEdge);
|
||||
void centerInPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition);
|
||||
void fillPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif
|
@@ -23,16 +23,19 @@
|
||||
#include "uiminimap.h"
|
||||
#include "minimap.h"
|
||||
#include "game.h"
|
||||
#include "uimapanchorlayout.h"
|
||||
#include "luavaluecasts.h"
|
||||
|
||||
#include <framework/graphics/painter.h>
|
||||
#include "uimapanchorlayout.h"
|
||||
|
||||
UIMinimap::UIMinimap()
|
||||
{
|
||||
m_crossEnabled = true;
|
||||
m_zoom = 0;
|
||||
m_scale = 1.0f;
|
||||
m_minZoom = -5;
|
||||
m_maxZoom = 5;
|
||||
m_layout = UIMapAnchorLayoutPtr(new UIMapAnchorLayout(static_self_cast<UIWidget>()));
|
||||
}
|
||||
|
||||
void UIMinimap::drawSelf(Fw::DrawPane drawPane)
|
||||
@@ -42,22 +45,18 @@ void UIMinimap::drawSelf(Fw::DrawPane drawPane)
|
||||
if((drawPane & Fw::ForegroundPane) == 0)
|
||||
return;
|
||||
|
||||
g_minimap.draw(getPaddingRect(), getCameraPosition(), m_scale);
|
||||
|
||||
// draw a cross in the center
|
||||
Rect vRect(0, 0, 2, 10);
|
||||
Rect hRect(0, 0, 10, 2);
|
||||
vRect.moveCenter(m_rect.center());
|
||||
hRect.moveCenter(m_rect.center());
|
||||
g_painter->setColor(Color::white);
|
||||
g_painter->drawFilledRect(vRect);
|
||||
g_painter->drawFilledRect(hRect);
|
||||
g_minimap.draw(getPaddingRect(), getCameraPosition(), m_scale, m_color);
|
||||
}
|
||||
|
||||
bool UIMinimap::setZoom(int zoom)
|
||||
{
|
||||
if(zoom == m_zoom)
|
||||
return true;
|
||||
|
||||
if(zoom < m_minZoom || zoom > m_maxZoom)
|
||||
return false;
|
||||
|
||||
int oldZoom = m_zoom;
|
||||
m_zoom = zoom;
|
||||
if(m_zoom < 0)
|
||||
m_scale = 1.0f / (1 << std::abs(zoom));
|
||||
@@ -65,37 +64,83 @@ bool UIMinimap::setZoom(int zoom)
|
||||
m_scale = 1.0f * (1 << std::abs(zoom));
|
||||
else
|
||||
m_scale = 1;
|
||||
m_layout->update();
|
||||
|
||||
onZoomChange(zoom, oldZoom);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIMinimap::followCreature(const CreaturePtr& creature)
|
||||
{
|
||||
m_followingCreature = creature;
|
||||
m_cameraPosition = Position();
|
||||
}
|
||||
|
||||
void UIMinimap::setCameraPosition(const Position& pos)
|
||||
{
|
||||
m_followingCreature = nullptr;
|
||||
Position oldPos = m_cameraPosition;
|
||||
m_cameraPosition = pos;
|
||||
m_layout->update();
|
||||
|
||||
onCameraPositionChange(pos, oldPos);
|
||||
}
|
||||
|
||||
Point UIMinimap::getPoint(const Position& pos)
|
||||
bool UIMinimap::floorUp()
|
||||
{
|
||||
return g_minimap.getPoint(pos, getPaddingRect(), getCameraPosition(), m_scale);
|
||||
Position pos = getCameraPosition();
|
||||
if(!pos.up())
|
||||
return false;
|
||||
setCameraPosition(pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
Position UIMinimap::getPosition(const Point& mousePos)
|
||||
bool UIMinimap::floorDown()
|
||||
{
|
||||
return g_minimap.getPosition(mousePos, getPaddingRect(), getCameraPosition(), m_scale);
|
||||
Position pos = getCameraPosition();
|
||||
if(!pos.down())
|
||||
return false;
|
||||
setCameraPosition(pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
Position UIMinimap::getCameraPosition()
|
||||
Point UIMinimap::getTilePoint(const Position& pos)
|
||||
{
|
||||
if(m_followingCreature)
|
||||
return m_followingCreature->getPosition();
|
||||
else
|
||||
return m_cameraPosition;
|
||||
return g_minimap.getTilePoint(pos, getPaddingRect(), getCameraPosition(), m_scale);
|
||||
}
|
||||
|
||||
Rect UIMinimap::getTileRect(const Position& pos)
|
||||
{
|
||||
return g_minimap.getTileRect(pos, getPaddingRect(), getCameraPosition(), m_scale);
|
||||
}
|
||||
|
||||
Position UIMinimap::getTilePosition(const Point& mousePos)
|
||||
{
|
||||
return g_minimap.getTilePosition(mousePos, getPaddingRect(), getCameraPosition(), m_scale);
|
||||
}
|
||||
|
||||
void UIMinimap::anchorPosition(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge anchoredEdge, const Position& hookedPosition, Fw::AnchorEdge hookedEdge)
|
||||
{
|
||||
UIMapAnchorLayoutPtr layout = m_layout->static_self_cast<UIMapAnchorLayout>();
|
||||
assert(layout);
|
||||
layout->addPositionAnchor(anchoredWidget, anchoredEdge, hookedPosition, hookedEdge);
|
||||
}
|
||||
|
||||
void UIMinimap::fillPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition)
|
||||
{
|
||||
UIMapAnchorLayoutPtr layout = m_layout->static_self_cast<UIMapAnchorLayout>();
|
||||
assert(layout);
|
||||
layout->fillPosition(anchoredWidget, hookedPosition);
|
||||
}
|
||||
|
||||
void UIMinimap::centerInPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition)
|
||||
{
|
||||
UIMapAnchorLayoutPtr layout = m_layout->static_self_cast<UIMapAnchorLayout>();
|
||||
assert(layout);
|
||||
layout->centerInPosition(anchoredWidget, hookedPosition);
|
||||
}
|
||||
|
||||
void UIMinimap::onZoomChange(int zoom, int oldZoom)
|
||||
{
|
||||
callLuaField("onZoomChange", zoom, oldZoom);
|
||||
}
|
||||
|
||||
void UIMinimap::onCameraPositionChange(const Position& position, const Position& oldPosition)
|
||||
{
|
||||
callLuaField("onCameraPositionChange", position, oldPosition);
|
||||
}
|
||||
|
||||
void UIMinimap::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
|
||||
@@ -108,7 +153,5 @@ void UIMinimap::onStyleApply(const std::string& styleName, const OTMLNodePtr& st
|
||||
setMaxZoom(node->value<int>());
|
||||
else if(node->tag() == "min-zoom")
|
||||
setMinZoom(node->value<int>());
|
||||
else if(node->tag() == "cross")
|
||||
setCross(node->value<bool>());
|
||||
}
|
||||
}
|
||||
|
@@ -40,26 +40,32 @@ public:
|
||||
void setMinZoom(int minZoom) { m_minZoom = minZoom; }
|
||||
void setMaxZoom(int maxZoom) { m_maxZoom = maxZoom; }
|
||||
void setCameraPosition(const Position& pos);
|
||||
void setCross(bool enable) { m_crossEnabled = enable; }
|
||||
void followCreature(const CreaturePtr& creature);
|
||||
bool floorUp();
|
||||
bool floorDown();
|
||||
|
||||
Point getPoint(const Position& pos);
|
||||
Position getPosition(const Point& mousePos);
|
||||
Position getCameraPosition();
|
||||
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
||||
Point getTilePoint(const Position& pos);
|
||||
Rect getTileRect(const Position& pos);
|
||||
Position getTilePosition(const Point& mousePos);
|
||||
|
||||
Position getCameraPosition() { return m_cameraPosition; }
|
||||
int getMinZoom() { return m_minZoom; }
|
||||
int getMaxZoom() { return m_maxZoom; }
|
||||
int getZoom() { return m_zoom; }
|
||||
bool getCross() { return m_crossEnabled; }
|
||||
float getScale() { return m_scale; }
|
||||
|
||||
void anchorPosition(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge anchoredEdge, const Position& hookedPosition, Fw::AnchorEdge hookedEdge);
|
||||
void fillPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition);
|
||||
void centerInPosition(const UIWidgetPtr& anchoredWidget, const Position& hookedPosition);
|
||||
|
||||
protected:
|
||||
virtual void onZoomChange(int zoom, int oldZoom);
|
||||
virtual void onCameraPositionChange(const Position& position, const Position& oldPosition);
|
||||
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
|
||||
private:
|
||||
void update();
|
||||
|
||||
Rect m_mapArea;
|
||||
bool m_crossEnabled;
|
||||
CreaturePtr m_followingCreature;
|
||||
Position m_cameraPosition;
|
||||
float m_scale;
|
||||
int m_zoom;
|
||||
|
@@ -289,8 +289,12 @@ bool luavalue_cast(int index, OTMLNodePtr& node)
|
||||
g_lua.pushNil();
|
||||
while(g_lua.next(index < 0 ? index-1 : index)) {
|
||||
std::string cnodeName;
|
||||
if(!g_lua.isNumber(-2))
|
||||
cnodeName = g_lua.toString(-2);
|
||||
if(g_lua.isString(-2)) {
|
||||
g_lua.pushValue(-2);
|
||||
cnodeName = g_lua.toString();
|
||||
g_lua.pop();
|
||||
} else
|
||||
assert(g_lua.isNumber());
|
||||
if(g_lua.isTable()) {
|
||||
OTMLNodePtr cnode;
|
||||
if(luavalue_cast(-1, cnode)) {
|
||||
|
@@ -26,6 +26,7 @@
|
||||
// common C headers
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
@@ -42,5 +43,8 @@
|
||||
#include <functional>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <tuple>
|
||||
#include <iomanip>
|
||||
#include <typeinfo>
|
||||
|
||||
#endif
|
||||
|
@@ -618,9 +618,12 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||
case WM_SYSKEYUP:
|
||||
case WM_SYSKEYDOWN: {
|
||||
// F10 is the shortcut key to enter a windows menu, this is a workaround to get F10 working
|
||||
if(wParam != VK_F10)
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
else {
|
||||
if(wParam != VK_F10) {
|
||||
if(wParam != VK_MENU && wParam != VK_LMENU && wParam != VK_RMENU)
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
else
|
||||
return 0;
|
||||
} else {
|
||||
if(uMsg == WM_SYSKEYUP)
|
||||
processKeyUp(retranslateVirtualKey(wParam, lParam));
|
||||
else
|
||||
|
@@ -33,6 +33,8 @@ class UIBoxLayout;
|
||||
class UIHorizontalLayout;
|
||||
class UIVerticalLayout;
|
||||
class UIGridLayout;
|
||||
class UIAnchor;
|
||||
class UIAnchorGroup;
|
||||
class UIAnchorLayout;
|
||||
class UIParticles;
|
||||
|
||||
@@ -44,8 +46,11 @@ typedef stdext::shared_object_ptr<UIBoxLayout> UIBoxLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIHorizontalLayout> UIHorizontalLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIVerticalLayout> UIVerticalLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIGridLayout> UIGridLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIAnchor> UIAnchorPtr;
|
||||
typedef stdext::shared_object_ptr<UIAnchorGroup> UIAnchorGroupPtr;
|
||||
typedef stdext::shared_object_ptr<UIAnchorLayout> UIAnchorLayoutPtr;
|
||||
|
||||
typedef std::deque<UIWidgetPtr> UIWidgetList;
|
||||
typedef std::vector<UIAnchorPtr> UIAnchorList;
|
||||
|
||||
#endif
|
||||
|
@@ -23,11 +23,81 @@
|
||||
#include "uianchorlayout.h"
|
||||
#include "uiwidget.h"
|
||||
|
||||
void UIAnchorGroup::addAnchor(const UIAnchor& anchor)
|
||||
UIWidgetPtr UIAnchor::getHookedWidget(const UIWidgetPtr& widget, const UIWidgetPtr& parentWidget)
|
||||
{
|
||||
// determine hooked widget
|
||||
UIWidgetPtr hookedWidget;
|
||||
if(parentWidget) {
|
||||
if(m_hookedWidgetId == "parent")
|
||||
hookedWidget = parentWidget;
|
||||
else if(m_hookedWidgetId == "next")
|
||||
hookedWidget = parentWidget->getChildAfter(widget);
|
||||
else if(m_hookedWidgetId == "prev")
|
||||
hookedWidget = parentWidget->getChildBefore(widget);
|
||||
else
|
||||
hookedWidget = parentWidget->getChildById(m_hookedWidgetId);
|
||||
}
|
||||
return hookedWidget;
|
||||
}
|
||||
|
||||
int UIAnchor::getHookedPoint(const UIWidgetPtr& hookedWidget, const UIWidgetPtr& parentWidget)
|
||||
{
|
||||
// determine hooked widget edge point
|
||||
Rect hookedWidgetRect = hookedWidget->getRect();
|
||||
if(hookedWidget == parentWidget)
|
||||
hookedWidgetRect = parentWidget->getPaddingRect();
|
||||
|
||||
int point = 0;
|
||||
switch(m_hookedEdge) {
|
||||
case Fw::AnchorLeft:
|
||||
point = hookedWidgetRect.left();
|
||||
break;
|
||||
case Fw::AnchorRight:
|
||||
point = hookedWidgetRect.right();
|
||||
break;
|
||||
case Fw::AnchorTop:
|
||||
point = hookedWidgetRect.top();
|
||||
break;
|
||||
case Fw::AnchorBottom:
|
||||
point = hookedWidgetRect.bottom();
|
||||
break;
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
point = hookedWidgetRect.horizontalCenter();
|
||||
break;
|
||||
case Fw::AnchorVerticalCenter:
|
||||
point = hookedWidgetRect.verticalCenter();
|
||||
break;
|
||||
default:
|
||||
// must never happens
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(hookedWidget == parentWidget) {
|
||||
switch(m_hookedEdge) {
|
||||
case Fw::AnchorLeft:
|
||||
case Fw::AnchorRight:
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
point -= parentWidget->getVirtualOffset().x;
|
||||
break;
|
||||
case Fw::AnchorBottom:
|
||||
case Fw::AnchorTop:
|
||||
case Fw::AnchorVerticalCenter:
|
||||
point -= parentWidget->getVirtualOffset().y;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
void UIAnchorGroup::addAnchor(const UIAnchorPtr& anchor)
|
||||
{
|
||||
// duplicated anchors must be replaced
|
||||
for(UIAnchor& other : m_anchors) {
|
||||
if(other.getAnchoredEdge() == anchor.getAnchoredEdge()) {
|
||||
for(UIAnchorPtr& other : m_anchors) {
|
||||
if(other->getAnchoredEdge() == anchor->getAnchoredEdge()) {
|
||||
other = anchor;
|
||||
return;
|
||||
}
|
||||
@@ -43,9 +113,12 @@ void UIAnchorLayout::addAnchor(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge
|
||||
|
||||
assert(anchoredWidget != getParentWidget());
|
||||
|
||||
UIAnchor anchor(anchoredEdge, hookedWidgetId, hookedEdge);
|
||||
UIAnchorGroup& anchorGroup = m_anchorsGroups[anchoredWidget];
|
||||
anchorGroup.addAnchor(anchor);
|
||||
UIAnchorPtr anchor(new UIAnchor(anchoredEdge, hookedWidgetId, hookedEdge));
|
||||
UIAnchorGroupPtr& anchorGroup = m_anchorsGroups[anchoredWidget];
|
||||
if(!anchorGroup)
|
||||
anchorGroup = UIAnchorGroupPtr(new UIAnchorGroup);
|
||||
|
||||
anchorGroup->addAnchor(anchor);
|
||||
|
||||
// layout must be updated because a new anchor got in
|
||||
update();
|
||||
@@ -86,7 +159,7 @@ void UIAnchorLayout::removeWidget(const UIWidgetPtr& widget)
|
||||
removeAnchors(widget);
|
||||
}
|
||||
|
||||
bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anchorGroup, UIWidgetPtr first)
|
||||
bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, const UIAnchorGroupPtr& anchorGroup, UIWidgetPtr first)
|
||||
{
|
||||
UIWidgetPtr parentWidget = getParentWidget();
|
||||
if(!parentWidget)
|
||||
@@ -105,23 +178,13 @@ bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anch
|
||||
bool horizontalMoved = false;
|
||||
|
||||
// calculates new rect based on anchors
|
||||
for(const UIAnchor& anchor : anchorGroup.getAnchors()) {
|
||||
for(const UIAnchorPtr& anchor : anchorGroup->getAnchors()) {
|
||||
// skip invalid anchors
|
||||
if(anchor.getHookedEdge() == Fw::AnchorNone)
|
||||
if(anchor->getHookedEdge() == Fw::AnchorNone)
|
||||
continue;
|
||||
|
||||
// determine hooked widget
|
||||
UIWidgetPtr hookedWidget;
|
||||
if(parentWidget) {
|
||||
if(anchor.getHookedWidgetId() == "parent")
|
||||
hookedWidget = parentWidget;
|
||||
else if(anchor.getHookedWidgetId() == "next")
|
||||
hookedWidget = parentWidget->getChildAfter(widget);
|
||||
else if(anchor.getHookedWidgetId() == "prev")
|
||||
hookedWidget = parentWidget->getChildBefore(widget);
|
||||
else
|
||||
hookedWidget = parentWidget->getChildById(anchor.getHookedWidgetId());
|
||||
}
|
||||
UIWidgetPtr hookedWidget = anchor->getHookedWidget(widget, parentWidget);
|
||||
|
||||
// skip invalid anchors
|
||||
if(!hookedWidget)
|
||||
@@ -131,61 +194,15 @@ bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anch
|
||||
// update this hooked widget anchors
|
||||
auto it = m_anchorsGroups.find(hookedWidget);
|
||||
if(it != m_anchorsGroups.end()) {
|
||||
UIAnchorGroup& hookedAnchorGroup = it->second;
|
||||
if(!hookedAnchorGroup.isUpdated())
|
||||
const UIAnchorGroupPtr& hookedAnchorGroup = it->second;
|
||||
if(!hookedAnchorGroup->isUpdated())
|
||||
updateWidget(hookedWidget, hookedAnchorGroup, first);
|
||||
}
|
||||
}
|
||||
|
||||
// determine hooked widget edge point
|
||||
Rect hookedWidgetRect = hookedWidget->getRect();
|
||||
if(hookedWidget == parentWidget)
|
||||
hookedWidgetRect = parentWidget->getPaddingRect();
|
||||
int point = anchor->getHookedPoint(hookedWidget, parentWidget);
|
||||
|
||||
int point = 0;
|
||||
switch(anchor.getHookedEdge()) {
|
||||
case Fw::AnchorLeft:
|
||||
point = hookedWidgetRect.left();
|
||||
break;
|
||||
case Fw::AnchorRight:
|
||||
point = hookedWidgetRect.right();
|
||||
break;
|
||||
case Fw::AnchorTop:
|
||||
point = hookedWidgetRect.top();
|
||||
break;
|
||||
case Fw::AnchorBottom:
|
||||
point = hookedWidgetRect.bottom();
|
||||
break;
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
point = hookedWidgetRect.horizontalCenter();
|
||||
break;
|
||||
case Fw::AnchorVerticalCenter:
|
||||
point = hookedWidgetRect.verticalCenter();
|
||||
break;
|
||||
default:
|
||||
// must never happens
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(hookedWidget == parentWidget) {
|
||||
switch(anchor.getHookedEdge()) {
|
||||
case Fw::AnchorLeft:
|
||||
case Fw::AnchorRight:
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
point -= parentWidget->getVirtualOffset().x;
|
||||
break;
|
||||
case Fw::AnchorBottom:
|
||||
case Fw::AnchorTop:
|
||||
case Fw::AnchorVerticalCenter:
|
||||
point -= parentWidget->getVirtualOffset().y;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(anchor.getAnchoredEdge()) {
|
||||
switch(anchor->getAnchoredEdge()) {
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
newRect.moveHorizontalCenter(point + widget->getMarginLeft() - widget->getMarginRight());
|
||||
horizontalMoved = true;
|
||||
@@ -230,7 +247,7 @@ bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anch
|
||||
bool changed = false;
|
||||
if(widget->setRect(newRect))
|
||||
changed = true;
|
||||
anchorGroup.setUpdated(true);
|
||||
anchorGroup->setUpdated(true);
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -240,15 +257,15 @@ bool UIAnchorLayout::internalUpdate()
|
||||
|
||||
// reset all anchors groups update state
|
||||
for(auto& it : m_anchorsGroups) {
|
||||
UIAnchorGroup& anchorGroup = it.second;
|
||||
anchorGroup.setUpdated(false);
|
||||
const UIAnchorGroupPtr& anchorGroup = it.second;
|
||||
anchorGroup->setUpdated(false);
|
||||
}
|
||||
|
||||
// update all anchors
|
||||
for(auto& it : m_anchorsGroups) {
|
||||
const UIWidgetPtr& widget = it.first;
|
||||
UIAnchorGroup& anchorGroup = it.second;
|
||||
if(!anchorGroup.isUpdated()) {
|
||||
const UIAnchorGroupPtr& anchorGroup = it.second;
|
||||
if(!anchorGroup->isUpdated()) {
|
||||
if(updateWidget(widget, anchorGroup))
|
||||
changed = true;
|
||||
}
|
||||
|
@@ -25,30 +25,30 @@
|
||||
|
||||
#include "uilayout.h"
|
||||
|
||||
class UIAnchor
|
||||
class UIAnchor : public stdext::shared_object
|
||||
{
|
||||
public:
|
||||
UIAnchor(Fw::AnchorEdge anchoredEdge, const std::string& hookedWidgetId, Fw::AnchorEdge hookedEdge) :
|
||||
m_anchoredEdge(anchoredEdge), m_hookedEdge(hookedEdge), m_hookedWidgetId(hookedWidgetId) { }
|
||||
|
||||
Fw::AnchorEdge getAnchoredEdge() const { return m_anchoredEdge; }
|
||||
std::string getHookedWidgetId() const { return m_hookedWidgetId; }
|
||||
Fw::AnchorEdge getHookedEdge() const { return m_hookedEdge; }
|
||||
|
||||
private:
|
||||
virtual UIWidgetPtr getHookedWidget(const UIWidgetPtr& widget, const UIWidgetPtr& parentWidget);
|
||||
virtual int getHookedPoint(const UIWidgetPtr& hookedWidget, const UIWidgetPtr& parentWidget);
|
||||
|
||||
protected:
|
||||
Fw::AnchorEdge m_anchoredEdge;
|
||||
Fw::AnchorEdge m_hookedEdge;
|
||||
std::string m_hookedWidgetId;
|
||||
};
|
||||
|
||||
typedef std::vector<UIAnchor> UIAnchorList;
|
||||
|
||||
class UIAnchorGroup
|
||||
class UIAnchorGroup : public stdext::shared_object
|
||||
{
|
||||
public:
|
||||
UIAnchorGroup() : m_updated(true) { }
|
||||
|
||||
void addAnchor(const UIAnchor& anchor);
|
||||
void addAnchor(const UIAnchorPtr& anchor);
|
||||
const UIAnchorList& getAnchors() { return m_anchors; }
|
||||
bool isUpdated() { return m_updated; }
|
||||
void setUpdated(bool updated) { m_updated = updated; }
|
||||
@@ -77,11 +77,9 @@ public:
|
||||
bool isUIAnchorLayout() { return true; }
|
||||
|
||||
protected:
|
||||
bool internalUpdate();
|
||||
|
||||
private:
|
||||
bool updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anchorGroup, UIWidgetPtr first = nullptr);
|
||||
std::unordered_map<UIWidgetPtr, UIAnchorGroup> m_anchorsGroups;
|
||||
virtual bool internalUpdate();
|
||||
virtual bool updateWidget(const UIWidgetPtr& widget, const UIAnchorGroupPtr& anchorGroup, UIWidgetPtr first = nullptr);
|
||||
std::unordered_map<UIWidgetPtr, UIAnchorGroupPtr> m_anchorsGroups;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <framework/platform/platformwindow.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/luaengine/luainterface.h>
|
||||
|
||||
UIWidget::UIWidget()
|
||||
{
|
||||
|
@@ -407,4 +407,4 @@ void UIWidget::setIcon(const std::string& iconFile)
|
||||
m_icon = g_textures.getTexture(iconFile);
|
||||
if(m_icon && !m_iconClipRect.isValid())
|
||||
m_iconClipRect = Rect(0, 0, m_icon->getSize());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user