Merge with 'master'

This commit is contained in:
Túlio Henrique 2015-07-07 10:43:18 -03:00
commit 2d65a0a3ed
22 changed files with 427 additions and 79 deletions

View File

@ -1,4 +1,4 @@
[![Build Status](https://secure.travis-ci.org/edubart/otclient.svg?branch=mobile_port)](http://travis-ci.org/edubart/otclient) [![Build Status](https://secure.travis-ci.org/edubart/otclient.svg?branch=mobile_port)](http://travis-ci.org/edubart/otclient) [![Join the chat at https://gitter.im/edubart/otclient](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/edubart/otclient?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
### What is otclient? ### What is otclient?
Otclient is an alternative Tibia client for usage with otserv. It aims to be complete and flexible, Otclient is an alternative Tibia client for usage with otserv. It aims to be complete and flexible,

View File

@ -78,7 +78,7 @@ local function onCharacterList(protocol, characters, account, otui)
if motdEnabled then if motdEnabled then
local lastMotdNumber = g_settings.getNumber("motd") local lastMotdNumber = g_settings.getNumber("motd")
if G.motdNumber and G.motdNumber ~= lastMotdNumber then if G.motdNumber and G.motdNumber ~= lastMotdNumber then
g_settings.set("motd", motdNumber) g_settings.set("motd", G.motdNumber)
motdWindow = displayInfoBox(tr('Message of the day'), G.motdMessage) motdWindow = displayInfoBox(tr('Message of the day'), G.motdMessage)
connect(motdWindow, { onOk = function() CharacterList.show() motdWindow = nil end }) connect(motdWindow, { onOk = function() CharacterList.show() motdWindow = nil end })
CharacterList.hide() CharacterList.hide()

View File

@ -10,6 +10,7 @@ Module
dofile 'string' dofile 'string'
dofile 'table' dofile 'table'
dofile 'bitwise' dofile 'bitwise'
dofile 'struct'
dofile 'const' dofile 'const'
dofile 'util' dofile 'util'

173
modules/corelib/struct.lua Normal file
View File

@ -0,0 +1,173 @@
Struct = {}
function Struct.pack(format, ...)
local stream = {}
local vars = {...}
local endianness = true
for i = 1, format:len() do
local opt = format:sub(i, i)
if opt == '>' then
endianness = false
elseif opt:find('[bBhHiIlL]') then
local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
local val = tonumber(table.remove(vars, 1))
if val < 0 then
val = val + 2 ^ (n * 8 - 1)
end
local bytes = {}
for j = 1, n do
table.insert(bytes, string.char(val % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
if not endianness then
table.insert(stream, string.reverse(table.concat(bytes)))
else
table.insert(stream, table.concat(bytes))
end
elseif opt:find('[fd]') then
local val = tonumber(table.remove(vars, 1))
local sign = 0
if val < 0 then
sign = 1
val = -val
end
local mantissa, exponent = math.frexp(val)
if val == 0 then
mantissa = 0
exponent = 0
else
mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, (opt == 'd') and 53 or 24)
exponent = exponent + ((opt == 'd') and 1022 or 126)
end
local bytes = {}
if opt == 'd' then
val = mantissa
for i = 1, 6 do
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
else
table.insert(bytes, string.char(math.floor(mantissa) % (2 ^ 8)))
val = math.floor(mantissa / (2 ^ 8))
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
table.insert(bytes, string.char(math.floor(exponent * ((opt == 'd') and 16 or 128) + val) % (2 ^ 8)))
val = math.floor((exponent * ((opt == 'd') and 16 or 128) + val) / (2 ^ 8))
table.insert(bytes, string.char(math.floor(sign * 128 + val) % (2 ^ 8)))
val = math.floor((sign * 128 + val) / (2 ^ 8))
if not endianness then
table.insert(stream, string.reverse(table.concat(bytes)))
else
table.insert(stream, table.concat(bytes))
end
elseif opt == 's' then
table.insert(stream, tostring(table.remove(vars, 1)))
table.insert(stream, string.char(0))
elseif opt == 'c' then
local n = format:sub(i + 1):match('%d+')
local length = tonumber(n)
if length > 0 then
local str = tostring(table.remove(vars, 1))
if length - str:len() > 0 then
str = str .. string.rep(' ', length - str:len())
end
table.insert(stream, str:sub(1, length))
end
i = i + n:len()
end
end
return table.concat(stream)
end
function Struct.unpack(format, stream)
local vars = {}
local iterator = 1
local endianness = true
for i = 1, format:len() do
local opt = format:sub(i, i)
if opt == '>' then
endianness = false
elseif opt:find('[bBhHiIlL]') then
local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
local signed = opt:lower() == opt
local val = 0
for j = 1, n do
local byte = string.byte(stream:sub(iterator, iterator))
if endianness then
val = val + byte * (2 ^ ((j - 1) * 8))
else
val = val + byte * (2 ^ ((n - j) * 8))
end
iterator = iterator + 1
end
if signed then
val = val - 2 ^ (n * 8 - 1)
end
table.insert(vars, val)
elseif opt:find('[fd]') then
local n = (opt == 'd') and 8 or 4
local x = stream:sub(iterator, iterator + n - 1)
iterator = iterator + n
if not endianness then
x = string.reverse(x)
end
local sign = 1
local mantissa = string.byte(x, (opt == 'd') and 7 or 3) % ((opt == 'd') and 16 or 128)
for i = n - 2, 1, -1 do
mantissa = mantissa * (2 ^ 8) + string.byte(x, i)
end
if string.byte(x, n) > 127 then
sign = -1
end
local exponent = (string.byte(x, n) % 128) * ((opt == 'd') and 16 or 2) + math.floor(string.byte(x, n - 1) / ((opt == 'd') and 16 or 128))
if exponent == 0 then
table.insert(vars, 0.0)
else
mantissa = (math.ldexp(mantissa, (opt == 'd') and -52 or -23) + 1) * sign
table.insert(vars, math.ldexp(mantissa, exponent - ((opt == 'd') and 1023 or 127)))
end
elseif opt == 's' then
local bytes = {}
for j = iterator, stream:len() do
if stream:sub(j, j) == string.char(0) then
break
end
table.insert(bytes, stream:sub(j, j))
end
local str = table.concat(bytes)
iterator = iterator + str:len() + 1
table.insert(vars, str)
elseif opt == 'c' then
local n = format:sub(i + 1):match('%d+')
table.insert(vars, stream:sub(iterator, iterator + tonumber(n)))
iterator = iterator + tonumber(n)
i = i + n:len()
end
end
return unpack(vars)
end

View File

@ -296,6 +296,16 @@ function numbertoboolean(number)
end end
end end
function protectedcall(func, ...)
local status, ret = pcall(func, ...)
if status then
return ret
end
perror(ret)
return false
end
function signalcall(param, ...) function signalcall(param, ...)
if type(param) == 'function' then if type(param) == 'function' then
local status, ret = pcall(param, ...) local status, ret = pcall(param, ...)

View File

@ -113,13 +113,10 @@ function init()
local tab = consoleTabBar:getCurrentTab() local tab = consoleTabBar:getCurrentTab()
if not tab then return false end if not tab then return false end
local consoleBuffer = tab.tabPanel:getChildById('consoleBuffer') local selection = tab.tabPanel:getChildById('consoleBuffer').selectionText
if not consoleBuffer then return false end if not selection then return false end
local consoleLabel = consoleBuffer:getFocusedChild() g_window.setClipboardText(selection)
if not consoleLabel or not consoleLabel:hasSelection() then return false end
g_window.setClipboardText(consoleLabel:getSelection())
return true return true
end end
@ -147,6 +144,27 @@ function init()
end end
end end
function clearSelection(consoleBuffer)
for _,label in pairs(consoleBuffer:getChildren()) do
label:clearSelection()
end
consoleBuffer.selectionText = nil
consoleBuffer.selection = nil
end
function selectAll(consoleBuffer)
clearSelection(consoleBuffer)
if consoleBuffer:getChildCount() > 0 then
local text = {}
for _,label in pairs(consoleBuffer:getChildren()) do
label:selectAll()
table.insert(text, label:getSelection())
end
consoleBuffer.selectionText = table.concat(text, '\n')
consoleBuffer.selection = { first = consoleBuffer:getChildIndex(consoleBuffer:getFirstChild()), last = consoleBuffer:getChildIndex(consoleBuffer:getLastChild()) }
end
end
function toggleChat() function toggleChat()
if consoleToggleChat:isChecked() then if consoleToggleChat:isChecked() then
disableChat() disableChat()
@ -577,12 +595,102 @@ function addTabText(text, speaktype, tab, creatureName)
end end
label.name = creatureName label.name = creatureName
consoleBuffer.onMouseRelease = function(self, mousePos, mouseButton)
processMessageMenu(mousePos, mouseButton, nil, nil, nil, tab)
end
label.onMouseRelease = function(self, mousePos, mouseButton) label.onMouseRelease = function(self, mousePos, mouseButton)
processMessageMenu(mousePos, mouseButton, creatureName, text, self, tab) processMessageMenu(mousePos, mouseButton, creatureName, text, self, tab)
end end
label.onMousePress = function(self, mousePos, button)
if button == MouseLeftButton then clearSelection(consoleBuffer) end
end
label.onDragEnter = function(self, mousePos)
clearSelection(consoleBuffer)
return true
end
label.onDragLeave = function(self, droppedWidget, mousePos)
local text = {}
for selectionChild = consoleBuffer.selection.first, consoleBuffer.selection.last do
local label = self:getParent():getChildByIndex(selectionChild)
table.insert(text, label:getSelection())
end
consoleBuffer.selectionText = table.concat(text, '\n')
return true
end
label.onDragMove = function(self, mousePos, mouseMoved)
local parent = self:getParent()
local parentRect = parent:getPaddingRect()
local selfIndex = parent:getChildIndex(self)
local child = parent:getChildByPos(mousePos)
-- find bonding children
if not child then
if mousePos.y < self:getY() then
for index = selfIndex - 1, 1, -1 do
local label = parent:getChildByIndex(index)
if label:getY() + label:getHeight() > parentRect.y then
if (mousePos.y >= label:getY() and mousePos.y <= label:getY() + label:getHeight()) or index == 1 then
child = label
break
end
else
child = parent:getChildByIndex(index + 1)
break
end
end
elseif mousePos.y > self:getY() + self:getHeight() then
for index = selfIndex + 1, parent:getChildCount(), 1 do
local label = parent:getChildByIndex(index)
if label:getY() < parentRect.y + parentRect.height then
if (mousePos.y >= label:getY() and mousePos.y <= label:getY() + label:getHeight()) or index == parent:getChildCount() then
child = label
break
end
else
child = parent:getChildByIndex(index - 1)
break
end
end
else
child = self
end
end
if not child then return false end
local childIndex = parent:getChildIndex(child)
-- remove old selection
clearSelection(consoleBuffer)
-- update self selection
local textBegin = self:getTextPos(self:getLastClickPosition())
local textPos = self:getTextPos(mousePos)
self:setSelection(textBegin, textPos)
consoleBuffer.selection = { first = math.min(selfIndex, childIndex), last = math.max(selfIndex, childIndex) }
-- update siblings selection
if child ~= self then
for selectionChild = consoleBuffer.selection.first + 1, consoleBuffer.selection.last - 1 do
parent:getChildByIndex(selectionChild):selectAll()
end
local textPos = child:getTextPos(mousePos)
if childIndex > selfIndex then
child:setSelection(0, textPos)
else
child:setSelection(string.len(child:getText()), textPos)
end
end
return true
end
if consoleBuffer:getChildCount() > MAX_LINES then if consoleBuffer:getChildCount() > MAX_LINES then
consoleBuffer:getFirstChild():destroy() local child = consoleBuffer:getFirstChild()
clearSelection(consoleBuffer)
child:destroy()
end end
end end
@ -609,8 +717,28 @@ function processChannelTabMenu(tab, mousePos, mouseButton)
if consoleTabBar:getCurrentTab() == tab then if consoleTabBar:getCurrentTab() == tab then
menu:addOption(tr('Clear Messages'), function() clearChannel(consoleTabBar) end) menu:addOption(tr('Clear Messages'), function() clearChannel(consoleTabBar) end)
menu:addOption(tr('Save Messages'), function()
local panel = consoleTabBar:getTabPanel(tab)
local consoleBuffer = panel:getChildById('consoleBuffer')
local lines = {}
for _,label in pairs(consoleBuffer:getChildren()) do
table.insert(lines, label:getText())
end
local filename = channelName .. '.txt'
local filepath = '/' .. filename
-- extra information at the beginning
table.insert(lines, 1, os.date('\nChannel saved at %a %b %d %H:%M:%S %Y'))
if g_resources.fileExists(filepath) then
table.insert(lines, 1, protectedcall(g_resources.readFileContents, filepath) or '')
end
g_resources.writeFileContents(filepath, table.concat(lines, '\n'))
modules.game_textmessage.displayStatusMessage(tr('Channel appended to %s', filename))
end)
end end
--menu:addOption(tr('Save Messages'), function() --[[TODO]] end)
menu:display(mousePos) menu:display(mousePos)
end end
@ -644,12 +772,15 @@ function processMessageMenu(mousePos, mouseButton, creatureName, text, label, ta
menu:addOption(tr('Copy name'), function () g_window.setClipboardText(creatureName) end) menu:addOption(tr('Copy name'), function () g_window.setClipboardText(creatureName) end)
end end
if label:hasSelection() then local selection = tab.tabPanel:getChildById('consoleBuffer').selectionText
menu:addOption(tr('Copy'), function() g_window.setClipboardText(label:getSelection()) end, '(Ctrl+C)') if selection and #selection > 0 then
menu:addOption(tr('Copy'), function() g_window.setClipboardText(selection) end, '(Ctrl+C)')
end end
if text then
menu:addOption(tr('Copy message'), function() g_window.setClipboardText(text) end) menu:addOption(tr('Copy message'), function() g_window.setClipboardText(text) end)
menu:addOption(tr('Select all'), function() label:selectAll() end) end
if tab.violations then menu:addOption(tr('Select all'), function() selectAll(tab.tabPanel:getChildById('consoleBuffer')) end)
if tab.violations and creatureName then
menu:addSeparator() menu:addSeparator()
menu:addOption(tr('Process') .. ' ' .. creatureName, function() processViolation(creatureName, text) end) menu:addOption(tr('Process') .. ' ' .. creatureName, function() processViolation(creatureName, text) end)
menu:addOption(tr('Remove') .. ' ' .. creatureName, function() g_game.closeRuleViolation(creatureName) end) menu:addOption(tr('Remove') .. ' ' .. creatureName, function() g_game.closeRuleViolation(creatureName) end)

View File

@ -10,6 +10,9 @@ ConsoleLabel < UITextEdit
change-cursor-image: false change-cursor-image: false
cursor-visible: false cursor-visible: false
editable: false editable: false
draggable: true
selectable: false
focusable: false
ConsolePhantomLabel < UILabel ConsolePhantomLabel < UILabel
font: verdana-11px-antialised font: verdana-11px-antialised

View File

@ -200,28 +200,23 @@ void Creature::drawOutfit(const Rect& destRect, bool resize)
else else
exactSize = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory())->getExactSize(); exactSize = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory())->getExactSize();
int frameSize;
if(!resize)
frameSize = std::max<int>(exactSize * 0.75f, 2 * Otc::TILE_PIXELS * 0.75f);
else if(!(frameSize = exactSize))
return;
if(g_graphics.canUseFBO()) { if(g_graphics.canUseFBO()) {
const FrameBufferPtr& outfitBuffer = g_framebuffers.getTemporaryFrameBuffer(); const FrameBufferPtr& outfitBuffer = g_framebuffers.getTemporaryFrameBuffer();
outfitBuffer->resize(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS)); outfitBuffer->resize(Size(frameSize, frameSize));
outfitBuffer->bind(); outfitBuffer->bind();
g_painter->setAlphaWriting(true); g_painter->setAlphaWriting(true);
g_painter->clear(Color::alpha); g_painter->clear(Color::alpha);
internalDrawOutfit(Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South); internalDrawOutfit(Point(frameSize - Otc::TILE_PIXELS, frameSize - Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South);
outfitBuffer->release(); outfitBuffer->release();
outfitBuffer->draw(destRect, Rect(0,0,frameSize,frameSize));
Rect srcRect;
if(resize)
srcRect.resize(exactSize, exactSize);
else
srcRect.resize(2*Otc::TILE_PIXELS*0.75f, 2*Otc::TILE_PIXELS*0.75f);
srcRect.moveBottomRight(Point(2*Otc::TILE_PIXELS - 1, 2*Otc::TILE_PIXELS - 1));
outfitBuffer->draw(destRect, srcRect);
} else { } else {
float scaleFactor; float scaleFactor = destRect.width() / (float)frameSize;
if(resize)
scaleFactor = destRect.width() / (float)exactSize;
else
scaleFactor = destRect.width() / (float)(2*Otc::TILE_PIXELS*0.75f);
Point dest = destRect.bottomRight() - (Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) - getDisplacement()) * scaleFactor; Point dest = destRect.bottomRight() - (Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) - getDisplacement()) * scaleFactor;
internalDrawOutfit(dest, scaleFactor, false, true, Otc::South); internalDrawOutfit(dest, scaleFactor, false, true, Otc::South);
} }

View File

@ -394,6 +394,14 @@ void Map::setZoneColor(tileflags_t zone, const Color& color)
m_zoneColors[zone] = color; m_zoneColors[zone] = color;
} }
Color Map::getZoneColor(tileflags_t flag)
{
auto it = m_zoneColors.find(flag);
if(it == m_zoneColors.end())
return Color::alpha;
return it->second;
}
void Map::setForceShowAnimations(bool force) void Map::setForceShowAnimations(bool force)
{ {
if(force) { if(force) {

View File

@ -196,7 +196,7 @@ public:
void setZoneOpacity(float opacity) { m_zoneOpacity = opacity; } void setZoneOpacity(float opacity) { m_zoneOpacity = opacity; }
float getZoneOpacity() { return m_zoneOpacity; } float getZoneOpacity() { return m_zoneOpacity; }
Color getZoneColor(tileflags_t flag) { return m_zoneColors[flag]; } Color getZoneColor(tileflags_t flag);
tileflags_t getZoneFlags() { return (tileflags_t)m_zoneFlags; } tileflags_t getZoneFlags() { return (tileflags_t)m_zoneFlags; }
bool showZones() { return m_zoneFlags != 0; } bool showZones() { return m_zoneFlags != 0; }
bool showZone(tileflags_t zone) { return (m_zoneFlags & zone) == zone; } bool showZone(tileflags_t zone) { return (m_zoneFlags & zone) == zone; }
@ -257,7 +257,7 @@ private:
uint8 m_animationFlags; uint8 m_animationFlags;
uint32 m_zoneFlags; uint32 m_zoneFlags;
std::array<Color, TILESTATE_LAST> m_zoneColors; std::map<uint32, Color> m_zoneColors;
float m_zoneOpacity; float m_zoneOpacity;
Light m_light; Light m_light;
@ -272,5 +272,3 @@ private:
extern Map g_map; extern Map g_map;
#endif #endif
/* vim: set ts=4 sw=4 et: */

View File

@ -333,6 +333,7 @@ bool Minimap::loadOtmm(const std::string& fileName)
uint blockSize = MMBLOCK_SIZE * MMBLOCK_SIZE * sizeof(MinimapTile); uint blockSize = MMBLOCK_SIZE * MMBLOCK_SIZE * sizeof(MinimapTile);
std::vector<uchar> compressBuffer(compressBound(blockSize)); std::vector<uchar> compressBuffer(compressBound(blockSize));
std::vector<uchar> decompressBuffer(blockSize);
while(true) { while(true) {
Position pos; Position pos;
@ -340,17 +341,19 @@ bool Minimap::loadOtmm(const std::string& fileName)
pos.y = fin->getU16(); pos.y = fin->getU16();
pos.z = fin->getU8(); pos.z = fin->getU8();
// end of file // end of file or file is corrupted
if(!pos.isValid()) if(!pos.isValid() || pos.z >= Otc::MAX_Z+1)
break; break;
MinimapBlock& block = getBlock(pos); MinimapBlock& block = getBlock(pos);
ulong len = fin->getU16(); ulong len = fin->getU16();
ulong destLen = blockSize; ulong destLen = blockSize;
fin->read(compressBuffer.data(), len); fin->read(compressBuffer.data(), len);
int ret = uncompress((uchar*)&block.getTiles(), &destLen, compressBuffer.data(), len); int ret = uncompress(decompressBuffer.data(), &destLen, compressBuffer.data(), len);
assert(ret == Z_OK); if(ret != Z_OK || destLen != blockSize)
assert(destLen == blockSize); break;
memcpy((uchar*)&block.getTiles(), decompressBuffer.data(), blockSize);
block.mustUpdate(); block.mustUpdate();
block.justSaw(); block.justSaw();
} }

View File

@ -583,10 +583,8 @@ void ProtocolGame::sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseMod
msg->addU8(fightMode); msg->addU8(fightMode);
msg->addU8(chaseMode); msg->addU8(chaseMode);
msg->addU8(safeFight ? 0x01: 0x00); msg->addU8(safeFight ? 0x01: 0x00);
if(g_game.getFeature(Otc::GamePVPMode)) if(g_game.getFeature(Otc::GamePVPMode))
msg->addU8(pvpMode); msg->addU8(pvpMode);
send(msg); send(msg);
} }
@ -595,6 +593,7 @@ void ProtocolGame::sendAttack(uint creatureId, uint seq)
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientAttack); msg->addU8(Proto::ClientAttack);
msg->addU32(creatureId); msg->addU32(creatureId);
if(g_game.getFeature(Otc::GameAttackSeq))
msg->addU32(seq); msg->addU32(seq);
send(msg); send(msg);
} }
@ -604,6 +603,7 @@ void ProtocolGame::sendFollow(uint creatureId, uint seq)
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientFollow); msg->addU8(Proto::ClientFollow);
msg->addU32(creatureId); msg->addU32(creatureId);
if(g_game.getFeature(Otc::GameAttackSeq))
msg->addU32(seq); msg->addU32(seq);
send(msg); send(msg);
} }
@ -652,10 +652,8 @@ void ProtocolGame::sendShareExperience(bool active)
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientShareExperience); msg->addU8(Proto::ClientShareExperience);
msg->addU8(active ? 0x01 : 0x00); msg->addU8(active ? 0x01 : 0x00);
if(g_game.getClientVersion() < 910) if(g_game.getClientVersion() < 910)
msg->addU8(0); msg->addU8(0);
send(msg); send(msg);
} }

View File

@ -244,12 +244,12 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
m_attribs.set(attr, market); m_attribs.set(attr, market);
break; break;
} }
case ThingAttrUsable:
case ThingAttrElevation: { case ThingAttrElevation: {
m_elevation = fin->getU16(); m_elevation = fin->getU16();
m_attribs.set(attr, m_elevation); m_attribs.set(attr, m_elevation);
break; break;
} }
case ThingAttrUsable:
case ThingAttrGround: case ThingAttrGround:
case ThingAttrWritable: case ThingAttrWritable:
case ThingAttrWritableOnce: case ThingAttrWritableOnce:

View File

@ -174,7 +174,7 @@ set(CMAKE_CXX_FLAGS_COMPILESPEED "-O0")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O1 -g -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O1 -g -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS_RELEASE "-O2") set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS_PERFORMANCE "-Ofast -mmmx -msse -msse2") set(CMAKE_CXX_FLAGS_PERFORMANCE "-Ofast -march=native")
if(USE_LTO) if(USE_LTO)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fwhole-program -flto") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fwhole-program -flto")

View File

@ -135,6 +135,12 @@ void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
#endif #endif
} }
void PainterOGL1::drawFillCoords(CoordsBuffer& coordsBuffer)
{
setTexture(nullptr);
drawCoords(coordsBuffer);
}
void PainterOGL1::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) void PainterOGL1::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
{ {
if(texture->isEmpty()) if(texture->isEmpty())

View File

@ -50,6 +50,7 @@ public:
void refreshState(); void refreshState();
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
void drawFillCoords(CoordsBuffer& coordsBuffer);
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);

View File

@ -120,6 +120,13 @@ void PainterOGL2::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
PainterShaderProgram::enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR); PainterShaderProgram::enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR);
} }
void PainterOGL2::drawFillCoords(CoordsBuffer& coordsBuffer)
{
setDrawProgram(m_shaderProgram ? m_shaderProgram : m_drawSolidColorProgram.get());
setTexture(nullptr);
drawCoords(coordsBuffer);
}
void PainterOGL2::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) void PainterOGL2::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
{ {
if(texture && texture->isEmpty()) if(texture && texture->isEmpty())

View File

@ -41,6 +41,7 @@ public:
void unbind(); void unbind();
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
void drawFillCoords(CoordsBuffer& coordsBuffer);
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);

View File

@ -62,6 +62,7 @@ public:
virtual void clear(const Color& color) = 0; virtual void clear(const Color& color) = 0;
virtual void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles) = 0; virtual void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles) = 0;
virtual void drawFillCoords(CoordsBuffer& coordsBuffer) = 0;
virtual void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) = 0; virtual void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) = 0;
virtual void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0; virtual void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0;
void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); } void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); }

View File

@ -49,6 +49,9 @@ UITextEdit::UITextEdit()
m_updatesEnabled = true; m_updatesEnabled = true;
m_selectionColor = Color::white; m_selectionColor = Color::white;
m_selectionBackgroundColor = Color::black; m_selectionBackgroundColor = Color::black;
m_glyphsTextCoordsBuffer.enableHardwareCaching();
m_glyphsSelectCoordsBuffer.enableHardwareCaching();
m_glyphsMustRecache = true;
blinkCursor(); blinkCursor();
} }
@ -62,38 +65,36 @@ void UITextEdit::drawSelf(Fw::DrawPane drawPane)
drawImage(m_rect); drawImage(m_rect);
drawIcon(m_rect); drawIcon(m_rect);
//TODO: text rendering could be much optimized by using vertex buffer or caching the render into a texture
int textLength = m_text.length(); int textLength = m_text.length();
const TexturePtr& texture = m_font->getTexture(); const TexturePtr& texture = m_font->getTexture();
if(!texture) if(!texture)
return; return;
if(hasSelection()) { bool glyphsMustRecache = m_glyphsMustRecache;
if(m_color != Color::alpha) { if(glyphsMustRecache)
g_painter->setColor(m_color); m_glyphsMustRecache = false;
for(int i=0;i<m_selectionStart;++i)
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
}
for(int i=m_selectionStart;i<m_selectionEnd;++i) {
g_painter->setColor(m_selectionBackgroundColor);
g_painter->drawFilledRect(m_glyphsCoords[i]);
g_painter->setColor(m_selectionColor);
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
}
if(m_color != Color::alpha) { if(m_color != Color::alpha) {
g_painter->setColor(m_color); if(glyphsMustRecache) {
for(int i=m_selectionEnd;i<textLength;++i) m_glyphsTextCoordsBuffer.clear();
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
}
} else if(m_color != Color::alpha) {
g_painter->setColor(m_color);
for(int i=0;i<textLength;++i) for(int i=0;i<textLength;++i)
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]); m_glyphsTextCoordsBuffer.addRect(m_glyphsCoords[i], m_glyphsTexCoords[i]);
}
g_painter->setColor(m_color);
g_painter->drawTextureCoords(m_glyphsTextCoordsBuffer, texture);
} }
if(hasSelection()) {
if(glyphsMustRecache) {
m_glyphsSelectCoordsBuffer.clear();
for(int i=m_selectionStart;i<m_selectionEnd;++i)
m_glyphsSelectCoordsBuffer.addRect(m_glyphsCoords[i], m_glyphsTexCoords[i]);
}
g_painter->setColor(m_selectionBackgroundColor);
g_painter->drawFillCoords(m_glyphsSelectCoordsBuffer);
g_painter->setColor(m_selectionColor);
g_painter->drawTextureCoords(m_glyphsSelectCoordsBuffer, texture);
}
// render cursor // render cursor
if(isExplicitlyEnabled() && m_cursorVisible && m_cursorInRange && isActive() && m_cursorPos >= 0) { if(isExplicitlyEnabled() && m_cursorVisible && m_cursorInRange && isActive() && m_cursorPos >= 0) {
@ -136,6 +137,9 @@ void UITextEdit::update(bool focusCursor)
if(m_rect.isEmpty()) if(m_rect.isEmpty())
return; return;
// recache coords buffers
recacheGlyphs();
// map glyphs positions // map glyphs positions
Size textBoxSize; Size textBoxSize;
const std::vector<Point>& glyphsPositions = m_font->calculateGlyphsPositions(text, m_textAlign, &textBoxSize); const std::vector<Point>& glyphsPositions = m_font->calculateGlyphsPositions(text, m_textAlign, &textBoxSize);
@ -360,6 +364,7 @@ void UITextEdit::setSelection(int start, int end)
m_selectionStart = stdext::clamp<int>(start, 0, (int)m_text.length()); m_selectionStart = stdext::clamp<int>(start, 0, (int)m_text.length());
m_selectionEnd = stdext::clamp<int>(end, 0, (int)m_text.length()); m_selectionEnd = stdext::clamp<int>(end, 0, (int)m_text.length());
recacheGlyphs();
} }
void UITextEdit::setTextHidden(bool hidden) void UITextEdit::setTextHidden(bool hidden)
@ -654,7 +659,7 @@ void UITextEdit::onFocusChange(bool focused, Fw::FocusReason reason)
else else
blinkCursor(); blinkCursor();
update(true); update(true);
} else } else if(m_selectable)
clearSelection(); clearSelection();
UIWidget::onFocusChange(focused, reason); UIWidget::onFocusChange(focused, reason);
} }
@ -796,7 +801,6 @@ bool UITextEdit::onMousePress(const Point& mousePos, Fw::MouseButton button)
} }
return true; return true;
} }
return false; return false;
} }
@ -807,6 +811,9 @@ bool UITextEdit::onMouseRelease(const Point& mousePos, Fw::MouseButton button)
bool UITextEdit::onMouseMove(const Point& mousePos, const Point& mouseMoved) bool UITextEdit::onMouseMove(const Point& mousePos, const Point& mouseMoved)
{ {
if(UIWidget::onMouseMove(mousePos, mouseMoved))
return true;
if(m_selectable && isPressed()) { if(m_selectable && isPressed()) {
int pos = getTextPos(mousePos); int pos = getTextPos(mousePos);
if(pos >= 0) { if(pos >= 0) {
@ -815,7 +822,7 @@ bool UITextEdit::onMouseMove(const Point& mousePos, const Point& mouseMoved)
} }
return true; return true;
} }
return UIWidget::onMouseMove(mousePos, mouseMoved); return false;
} }
bool UITextEdit::onDoubleClick(const Point& mousePos) bool UITextEdit::onDoubleClick(const Point& mousePos)

View File

@ -108,6 +108,7 @@ protected:
private: private:
void disableUpdates() { m_updatesEnabled = false; } void disableUpdates() { m_updatesEnabled = false; }
void enableUpdates() { m_updatesEnabled = true; } void enableUpdates() { m_updatesEnabled = true; }
void recacheGlyphs() { m_glyphsMustRecache = true; }
Rect m_drawArea; Rect m_drawArea;
int m_cursorPos; int m_cursorPos;
@ -137,6 +138,10 @@ private:
std::vector<Rect> m_glyphsCoords; std::vector<Rect> m_glyphsCoords;
std::vector<Rect> m_glyphsTexCoords; std::vector<Rect> m_glyphsTexCoords;
CoordsBuffer m_glyphsTextCoordsBuffer;
CoordsBuffer m_glyphsSelectCoordsBuffer;
bool m_glyphsMustRecache;
}; };
#endif #endif

View File

@ -66,19 +66,19 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;$(IncludePath)</IncludePath> <IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;..\src;$(IncludePath)</IncludePath>
<LibraryPath>D:\otclient-msvc13-libs\libogg-1.3.1\lib;D:\otclient-msvc13-libs\libvorbis-1.3.3\lib;D:\otclient-msvc13-libs\physfs-2.0.3\lib;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;D:\otclient-msvc13-libs\zlib-1.2.5\lib;D:\otclient-msvc13-libs\OpenAL\lib;D:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;D:\otclient-msvc13-libs\glew-1.10.0\lib;D:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath> <LibraryPath>D:\otclient-msvc13-libs\libogg-1.3.1\lib;D:\otclient-msvc13-libs\libvorbis-1.3.3\lib;D:\otclient-msvc13-libs\physfs-2.0.3\lib;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;D:\otclient-msvc13-libs\zlib-1.2.5\lib;D:\otclient-msvc13-libs\OpenAL\lib;D:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;D:\otclient-msvc13-libs\glew-1.10.0\lib;D:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;$(IncludePath)</IncludePath> <IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;..\src;$(IncludePath)</IncludePath>
<LibraryPath>D:\otclient-msvc13-libs\libogg-1.3.1\lib;D:\otclient-msvc13-libs\libvorbis-1.3.3\lib;D:\otclient-msvc13-libs\physfs-2.0.3\lib;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;D:\otclient-msvc13-libs\zlib-1.2.5\lib;D:\otclient-msvc13-libs\OpenAL\lib;D:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;D:\otclient-msvc13-libs\glew-1.10.0\lib;D:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath> <LibraryPath>D:\otclient-msvc13-libs\libogg-1.3.1\lib;D:\otclient-msvc13-libs\libvorbis-1.3.3\lib;D:\otclient-msvc13-libs\physfs-2.0.3\lib;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;D:\otclient-msvc13-libs\zlib-1.2.5\lib;D:\otclient-msvc13-libs\OpenAL\lib;D:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;D:\otclient-msvc13-libs\glew-1.10.0\lib;D:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>C:\otclient-msvc13-libs\libogg-1.3.1\include;C:\otclient-msvc13-libs\libvorbis-1.3.3\include;C:\otclient-msvc13-libs\physfs-2.0.3\include;C:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;C:\otclient-msvc13-libs\zlib-1.2.5\include;C:\Users\Pedro\Documents\GitHub\otclient\src;C:\otclient-msvc13-libs\OpenAL\include\AL;C:\otclient-msvc13-libs\glew-1.10.0\include;C:\otclient-msvc13-libs\LuaJIT-2.0.2\include;C:\otclient-msvc13-libs\boost_1_55_0\include;$(IncludePath)</IncludePath> <IncludePath>C:\otclient-msvc13-libs\libogg-1.3.1\include;C:\otclient-msvc13-libs\libvorbis-1.3.3\include;C:\otclient-msvc13-libs\physfs-2.0.3\include;C:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;C:\otclient-msvc13-libs\zlib-1.2.5\include;C:\otclient-msvc13-libs\OpenAL\include\AL;C:\otclient-msvc13-libs\glew-1.10.0\include;C:\otclient-msvc13-libs\LuaJIT-2.0.2\include;C:\otclient-msvc13-libs\boost_1_55_0\include;..\src;$(IncludePath)</IncludePath>
<LibraryPath>C:\otclient-msvc13-libs\libogg-1.3.1\lib;C:\otclient-msvc13-libs\libvorbis-1.3.3\lib;C:\otclient-msvc13-libs\physfs-2.0.3\lib;C:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;C:\otclient-msvc13-libs\zlib-1.2.5\lib;C:\otclient-msvc13-libs\OpenAL\lib;C:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;C:\otclient-msvc13-libs\glew-1.10.0\lib;C:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath> <LibraryPath>C:\otclient-msvc13-libs\libogg-1.3.1\lib;C:\otclient-msvc13-libs\libvorbis-1.3.3\lib;C:\otclient-msvc13-libs\physfs-2.0.3\lib;C:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;C:\otclient-msvc13-libs\zlib-1.2.5\lib;C:\otclient-msvc13-libs\OpenAL\lib;C:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;C:\otclient-msvc13-libs\glew-1.10.0\lib;C:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;$(IncludePath)</IncludePath> <IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;..\src;$(IncludePath)</IncludePath>
<LibraryPath>D:\otclient-msvc13-libs\libogg-1.3.1\lib;D:\otclient-msvc13-libs\libvorbis-1.3.3\lib;D:\otclient-msvc13-libs\physfs-2.0.3\lib;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;D:\otclient-msvc13-libs\zlib-1.2.5\lib;D:\otclient-msvc13-libs\OpenAL\lib;D:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;D:\otclient-msvc13-libs\glew-1.10.0\lib;D:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath> <LibraryPath>D:\otclient-msvc13-libs\libogg-1.3.1\lib;D:\otclient-msvc13-libs\libvorbis-1.3.3\lib;D:\otclient-msvc13-libs\physfs-2.0.3\lib;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;D:\otclient-msvc13-libs\zlib-1.2.5\lib;D:\otclient-msvc13-libs\OpenAL\lib;D:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;D:\otclient-msvc13-libs\glew-1.10.0\lib;D:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">