mirror of
https://github.com/edubart/otclient.git
synced 2025-09-14 14:53:34 +02:00
Compare commits
36 Commits
multi-grap
...
v0.6.3
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b5911cf1de | ||
![]() |
5fbb71157d | ||
![]() |
0ff36a1a0a | ||
![]() |
4a04a18835 | ||
![]() |
6fa9631d6a | ||
![]() |
261642190b | ||
![]() |
95abf2a1d2 | ||
![]() |
c4adf2d817 | ||
![]() |
c7c259ef80 | ||
![]() |
987c6d6c91 | ||
![]() |
c8185474de | ||
![]() |
be071c7103 | ||
![]() |
2f9e2c3e33 | ||
![]() |
b81590f297 | ||
![]() |
e062562888 | ||
![]() |
18d23653c4 | ||
![]() |
6c119627bb | ||
![]() |
d847a78a4d | ||
![]() |
0dccc870b5 | ||
![]() |
e4c7ca604b | ||
![]() |
d427560b98 | ||
![]() |
cc12db0d1f | ||
![]() |
1ce6df99ac | ||
![]() |
57bb6ff974 | ||
![]() |
9bae1b9e25 | ||
![]() |
1415de222c | ||
![]() |
34ceb3c95e | ||
![]() |
b43a196eac | ||
![]() |
a3a65d40ce | ||
![]() |
6ef3508362 | ||
![]() |
a71e07f063 | ||
![]() |
4bdd1e79fd | ||
![]() |
e9e4dcd71b | ||
![]() |
0891e2b30a | ||
![]() |
24664714bd | ||
![]() |
da51dd467e |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
/modules/.project
|
||||
build*
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
@@ -39,3 +38,4 @@ tags
|
||||
Thumbs.db
|
||||
.directory
|
||||
src/framework/graphics/dx/
|
||||
modules/.project/modules.sublime-workspace
|
||||
|
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
project(otclient)
|
||||
|
||||
set(VERSION "0.6.2")
|
||||
set(VERSION "0.6.3")
|
||||
|
||||
option(FRAMEWORK_SOUND "Use SOUND " ON)
|
||||
option(FRAMEWORK_GRAPHICS "Use GRAPHICS " ON)
|
||||
|
@@ -11,3 +11,9 @@ HorizontalList < UIScrollArea
|
||||
border-width: 1
|
||||
border-color: #1d222b
|
||||
background-color: #222833
|
||||
|
||||
VerticalList < UIScrollArea
|
||||
layout: verticalBox
|
||||
border-width: 1
|
||||
border-color: #1d222b
|
||||
background-color: #222833
|
2
init.lua
2
init.lua
@@ -48,7 +48,7 @@ g_modules.ensureModuleLoaded("game_interface")
|
||||
-- mods 1000-9999
|
||||
g_modules.autoLoadModules(9999)
|
||||
|
||||
local script = '/' .. g_app.getCompactName() .. 'rc.lua'
|
||||
local script = '/' .. g_app.getCompactName() .. 'rc'
|
||||
|
||||
if g_resources.fileExists(script) then
|
||||
dofile(script)
|
||||
|
10
modules/.project/modules.sublime-project
Normal file
10
modules/.project/modules.sublime-project
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": "..",
|
||||
"folder_exclude_patterns": [".*", "*.*~"],
|
||||
"file_exclude_patterns": [".*", "*.*~"]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
local musicFilename = "/sounds/startup"
|
||||
local musicChannel = nil
|
||||
local musicChannel = g_sounds.getChannel(1)
|
||||
|
||||
function setMusic(filename)
|
||||
musicFilename = filename
|
||||
@@ -57,14 +57,11 @@ function init()
|
||||
onExit = exit })
|
||||
|
||||
g_window.setMinimumSize({ width = 600, height = 480 })
|
||||
|
||||
musicChannel = g_sounds.getChannel(1)
|
||||
g_sounds.preload(musicFilename)
|
||||
|
||||
-- initialize in fullscreen mode on mobile devices
|
||||
if g_app.getOs() == "android" then
|
||||
g_window.maximize()
|
||||
--g_window.setFullscreen(true)
|
||||
if g_window.getPlatformType() == "X11-EGL" then
|
||||
g_window.setFullscreen(true)
|
||||
else
|
||||
-- window size
|
||||
local size = { width = 800, height = 600 }
|
||||
@@ -107,11 +104,6 @@ function terminate()
|
||||
g_settings.set('window-size', g_window.getUnmaximizedSize())
|
||||
g_settings.set('window-pos', g_window.getUnmaximizedPos())
|
||||
g_settings.set('window-maximized', g_window.isMaximized())
|
||||
|
||||
local protocolVersion = g_game.getProtocolVersion()
|
||||
if protocolVersion ~= 0 then
|
||||
g_settings.set('protocol-version', protocolVersion)
|
||||
end
|
||||
end
|
||||
|
||||
function exit()
|
||||
|
@@ -19,4 +19,4 @@ Module
|
||||
- client_terminal
|
||||
- client_modulemanager
|
||||
- client_serverlist
|
||||
//- client_stats
|
||||
- client_stats
|
||||
|
@@ -6,7 +6,7 @@ local enterGame
|
||||
local motdWindow
|
||||
local motdButton
|
||||
local enterGameButton
|
||||
local protocolBox
|
||||
local clientBox
|
||||
local protocolLogin
|
||||
local motdEnabled = true
|
||||
|
||||
@@ -73,11 +73,6 @@ local function onCharacterList(protocol, characters, account, otui)
|
||||
end
|
||||
end
|
||||
|
||||
local function onChangeProtocol(combobox, option)
|
||||
local clients = g_game.getSupportedClients(option)
|
||||
protocolBox:setTooltip("Supports Client" .. (#clients > 1 and "s" or "") .. ": " .. table.tostring(clients))
|
||||
end
|
||||
|
||||
local function onUpdateNeeded(protocol, signature)
|
||||
loadBox:destroy()
|
||||
loadBox = nil
|
||||
@@ -109,7 +104,8 @@ function EnterGame.init()
|
||||
local host = g_settings.get('host')
|
||||
local port = g_settings.get('port')
|
||||
local autologin = g_settings.getBoolean('autologin')
|
||||
local protocolVersion = g_settings.getInteger('protocol-version')
|
||||
local clientVersion = g_settings.getInteger('client-version')
|
||||
if clientVersion == 0 then clientVersion = 860 end
|
||||
|
||||
if port == nil or port == 0 then port = 7171 end
|
||||
|
||||
@@ -120,11 +116,11 @@ function EnterGame.init()
|
||||
enterGame:getChildById('serverPortTextEdit'):setText(port)
|
||||
enterGame:getChildById('autoLoginBox'):setChecked(autologin)
|
||||
|
||||
protocolBox = enterGame:getChildById('protocolComboBox')
|
||||
protocolBox.onOptionChange = onChangeProtocol
|
||||
if protocolVersion then
|
||||
protocolBox:setCurrentOption(protocolVersion)
|
||||
clientBox = enterGame:getChildById('clientComboBox')
|
||||
for _, proto in pairs(g_game.getSupportedClients()) do
|
||||
clientBox:addOption(proto)
|
||||
end
|
||||
clientBox:setCurrentOption(clientVersion)
|
||||
|
||||
enterGame:hide()
|
||||
|
||||
@@ -154,7 +150,7 @@ function EnterGame.terminate()
|
||||
enterGame = nil
|
||||
enterGameButton:destroy()
|
||||
enterGameButton = nil
|
||||
protocolBox = nil
|
||||
clientBox = nil
|
||||
if motdWindow then
|
||||
motdWindow:destroy()
|
||||
motdWindow = nil
|
||||
@@ -218,8 +214,7 @@ function EnterGame.doLogin()
|
||||
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
|
||||
G.host = enterGame:getChildById('serverHostTextEdit'):getText()
|
||||
G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
|
||||
local protocolVersion = tonumber(protocolBox:getText())
|
||||
local clientVersions = g_game.getSupportedClients(protocolVersion)
|
||||
local clientVersion = tonumber(clientBox:getText())
|
||||
EnterGame.hide()
|
||||
|
||||
if g_game.isOnline() then
|
||||
@@ -230,6 +225,7 @@ function EnterGame.doLogin()
|
||||
|
||||
g_settings.set('host', G.host)
|
||||
g_settings.set('port', G.port)
|
||||
g_settings.set('client-version', clientVersion)
|
||||
|
||||
protocolLogin = ProtocolLogin.create()
|
||||
protocolLogin.onLoginError = onError
|
||||
@@ -245,10 +241,8 @@ function EnterGame.doLogin()
|
||||
end })
|
||||
|
||||
g_game.chooseRsa(G.host)
|
||||
g_game.setProtocolVersion(protocolVersion)
|
||||
if #clientVersions > 0 then
|
||||
g_game.setClientVersion(clientVersions[#clientVersions])
|
||||
end
|
||||
g_game.setClientVersion(clientVersion)
|
||||
g_game.setProtocolVersion(g_game.getProtocolVersionForClient(clientVersion))
|
||||
|
||||
if modules.game_things.isLoaded() then
|
||||
protocolLogin:login(G.host, G.port, G.account, G.password)
|
||||
@@ -269,14 +263,14 @@ end
|
||||
function EnterGame.setDefaultServer(host, port, protocol)
|
||||
local hostTextEdit = enterGame:getChildById('serverHostTextEdit')
|
||||
local portTextEdit = enterGame:getChildById('serverPortTextEdit')
|
||||
local protocolLabel = enterGame:getChildById('protocolLabel')
|
||||
local clientLabel = enterGame:getChildById('clientLabel')
|
||||
local accountTextEdit = enterGame:getChildById('accountNameTextEdit')
|
||||
local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit')
|
||||
|
||||
if hostTextEdit:getText() ~= host then
|
||||
hostTextEdit:setText(host)
|
||||
portTextEdit:setText(port)
|
||||
protocolBox:setCurrentOption(protocol)
|
||||
clientBox:setCurrentOption(protocol)
|
||||
accountTextEdit:setText('')
|
||||
passwordTextEdit:setText('')
|
||||
end
|
||||
@@ -292,9 +286,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
|
||||
portTextEdit:setVisible(false)
|
||||
portTextEdit:setHeight(0)
|
||||
|
||||
protocolBox:setCurrentOption(protocol)
|
||||
protocolBox:setVisible(false)
|
||||
protocolBox:setHeight(0)
|
||||
clientBox:setCurrentOption(protocol)
|
||||
clientBox:setVisible(false)
|
||||
clientBox:setHeight(0)
|
||||
|
||||
local serverLabel = enterGame:getChildById('serverLabel')
|
||||
serverLabel:setVisible(false)
|
||||
@@ -302,9 +296,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
|
||||
local portLabel = enterGame:getChildById('portLabel')
|
||||
portLabel:setVisible(false)
|
||||
portLabel:setHeight(0)
|
||||
local protocolLabel = enterGame:getChildById('protocolLabel')
|
||||
protocolLabel:setVisible(false)
|
||||
protocolLabel:setHeight(0)
|
||||
local clientLabel = enterGame:getChildById('clientLabel')
|
||||
clientLabel:setVisible(false)
|
||||
clientLabel:setHeight(0)
|
||||
|
||||
local serverListButton = enterGame:getChildById('serverListButton')
|
||||
serverListButton:setVisible(false)
|
||||
|
@@ -68,7 +68,7 @@ EnterGameWindow
|
||||
|
||||
TextEdit
|
||||
id: serverHostTextEdit
|
||||
!tooltip: tr('Make sure that your client uses\nthe correct game protocol version')
|
||||
!tooltip: tr('Make sure that your client uses\nthe correct game client version')
|
||||
anchors.left: parent.left
|
||||
anchors.right: serverListButton.left
|
||||
anchors.top: serverLabel.bottom
|
||||
@@ -76,8 +76,8 @@ EnterGameWindow
|
||||
margin-right: 4
|
||||
|
||||
MenuLabel
|
||||
id: protocolLabel
|
||||
!text: tr('Protocol')
|
||||
id: clientLabel
|
||||
!text: tr('Client Version')
|
||||
anchors.left: parent.left
|
||||
anchors.top: serverHostTextEdit.bottom
|
||||
text-auto-resize: true
|
||||
@@ -85,17 +85,13 @@ EnterGameWindow
|
||||
margin-top: 8
|
||||
|
||||
ComboBox
|
||||
id: protocolComboBox
|
||||
id: clientComboBox
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.top: protocolLabel.bottom
|
||||
anchors.top: clientLabel.bottom
|
||||
margin-top: 2
|
||||
margin-right: 3
|
||||
width: 90
|
||||
@onSetup: |
|
||||
for _, proto in pairs(g_game.getSupportedProtocols()) do
|
||||
self:addOption(proto)
|
||||
end
|
||||
|
||||
MenuLabel
|
||||
id: portLabel
|
||||
@@ -110,7 +106,7 @@ EnterGameWindow
|
||||
text: 7171
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.top: protocolComboBox.top
|
||||
anchors.top: clientComboBox.top
|
||||
margin-left: 3
|
||||
|
||||
CheckBox
|
||||
|
@@ -137,7 +137,7 @@ function unloadCurrentModule()
|
||||
local module = g_modules.getModule(focusedChild:getText())
|
||||
if module then
|
||||
module:unload()
|
||||
if ModuleManager == nil then return end
|
||||
if modules.client_modulemanager == nil then return end
|
||||
updateModuleInfo(module:getName())
|
||||
refreshLoadedModules()
|
||||
end
|
||||
|
@@ -49,7 +49,7 @@ MainWindow
|
||||
anchors.left: protocolLabel.left
|
||||
anchors.right: port.right
|
||||
@onSetup: |
|
||||
for _, proto in pairs(g_game.getSupportedProtocols()) do
|
||||
for _, proto in pairs(g_game.getSupportedClients()) do
|
||||
self:addOption(proto)
|
||||
end
|
||||
|
||||
|
@@ -257,10 +257,13 @@ function flushLines()
|
||||
for _,line in pairs(cachedLines) do
|
||||
-- delete old lines if needed
|
||||
if numLines > MaxLogLines then
|
||||
local len = #terminalBuffer:getChildByIndex(1):getText()
|
||||
terminalBuffer:getChildByIndex(1):destroy()
|
||||
table.remove(allLines, 1)
|
||||
fulltext = string.sub(fulltext, len)
|
||||
local firstChild = terminalBuffer:getChildByIndex(1)
|
||||
if firstChild then
|
||||
local len = #firstChild:getText()
|
||||
firstChild:destroy()
|
||||
table.remove(allLines, 1)
|
||||
fulltext = string.sub(fulltext, len)
|
||||
end
|
||||
end
|
||||
|
||||
local label = g_ui.createWidget('TerminalLabel', terminalBuffer)
|
||||
@@ -285,6 +288,7 @@ function addLine(text, color)
|
||||
flushEvent = scheduleEvent(flushLines, 10)
|
||||
end
|
||||
|
||||
text = string.gsub(text, '\t', ' ')
|
||||
table.insert(cachedLines, {text=text, color=color})
|
||||
end
|
||||
|
||||
|
@@ -20,8 +20,8 @@ function string:starts(start)
|
||||
return string.sub(self, 1, #start) == start
|
||||
end
|
||||
|
||||
function string.ends(s, test)
|
||||
return test =='' or string.sub(s,-string.len(test)) == test
|
||||
function string:ends(test)
|
||||
return test =='' or string.sub(self,-string.len(test)) == test
|
||||
end
|
||||
|
||||
function string:trim()
|
||||
|
@@ -110,7 +110,9 @@ function UITabBar:selectTab(tab)
|
||||
tab:setOn(false)
|
||||
|
||||
local parent = tab:getParent()
|
||||
parent:focusChild(tab, MouseFocusReason)
|
||||
if parent then
|
||||
parent:focusChild(tab, MouseFocusReason)
|
||||
end
|
||||
end
|
||||
|
||||
function UITabBar:selectNextTab()
|
||||
|
@@ -1,11 +1,16 @@
|
||||
battleWindow = nil
|
||||
battleButton = nil
|
||||
battlePanel = nil
|
||||
filterPanel = nil
|
||||
toggleFilterButton = nil
|
||||
lastBattleButtonSwitched = nil
|
||||
battleButtonsByCreaturesList = {}
|
||||
creatureAgeList = {}
|
||||
|
||||
mouseWidget = nil
|
||||
|
||||
sortTypeBox = nil
|
||||
sortOrderBox = nil
|
||||
hidePlayersButton = nil
|
||||
hideNPCsButton = nil
|
||||
hideMonstersButton = nil
|
||||
@@ -25,6 +30,15 @@ function init()
|
||||
|
||||
battlePanel = battleWindow:recursiveGetChildById('battlePanel')
|
||||
|
||||
filterPanel = battleWindow:recursiveGetChildById('filterPanel')
|
||||
toggleFilterButton = battleWindow:recursiveGetChildById('toggleFilterButton')
|
||||
|
||||
if isHidingFilters() then
|
||||
hideFilterPanel()
|
||||
end
|
||||
|
||||
sortTypeBox = battleWindow:recursiveGetChildById('sortTypeBox')
|
||||
sortOrderBox = battleWindow:recursiveGetChildById('sortOrderBox')
|
||||
hidePlayersButton = battleWindow:recursiveGetChildById('hidePlayers')
|
||||
hideNPCsButton = battleWindow:recursiveGetChildById('hideNPCs')
|
||||
hideMonstersButton = battleWindow:recursiveGetChildById('hideMonsters')
|
||||
@@ -38,6 +52,18 @@ function init()
|
||||
|
||||
battleWindow:setContentMinimumHeight(80)
|
||||
|
||||
sortTypeBox:addOption('Name', 'name')
|
||||
sortTypeBox:addOption('Distance', 'distance')
|
||||
sortTypeBox:addOption('Age', 'age')
|
||||
sortTypeBox:addOption('Health', 'health')
|
||||
sortTypeBox:setCurrentOptionByData(getSortType())
|
||||
sortTypeBox.onOptionChange = onChangeSortType
|
||||
|
||||
sortOrderBox:addOption('Asc.', 'asc')
|
||||
sortOrderBox:addOption('Desc.', 'desc')
|
||||
sortOrderBox:setCurrentOptionByData(getSortOrder())
|
||||
sortOrderBox.onOptionChange = onChangeSortOrder
|
||||
|
||||
connect(Creature, {
|
||||
onSkullChange = updateCreatureSkull,
|
||||
onEmblemChange = updateCreatureEmblem,
|
||||
@@ -47,6 +73,10 @@ function init()
|
||||
onAppear = onCreatureAppear,
|
||||
onDisappear = onCreatureDisappear
|
||||
})
|
||||
|
||||
connect(LocalPlayer, {
|
||||
onPositionChange = onCreaturePositionChange
|
||||
})
|
||||
|
||||
connect(g_game, {
|
||||
onAttackingCreatureChange = onAttack,
|
||||
@@ -75,6 +105,10 @@ function terminate()
|
||||
onDisappear = onCreatureDisappear
|
||||
})
|
||||
|
||||
disconnect(LocalPlayer, {
|
||||
onPositionChange = onCreaturePositionChange
|
||||
})
|
||||
|
||||
disconnect(g_game, {
|
||||
onAttackingCreatureChange = onAttack,
|
||||
onFollowingCreatureChange = onFollow,
|
||||
@@ -96,6 +130,93 @@ function onMiniWindowClose()
|
||||
battleButton:setOn(false)
|
||||
end
|
||||
|
||||
function getSortType()
|
||||
local settings = g_settings.getNode('BattleList')
|
||||
if not settings then
|
||||
return 'name'
|
||||
end
|
||||
return settings['sortType']
|
||||
end
|
||||
|
||||
function setSortType(state)
|
||||
settings = {}
|
||||
settings['sortType'] = state
|
||||
g_settings.mergeNode('BattleList', settings)
|
||||
|
||||
checkCreatures()
|
||||
end
|
||||
|
||||
function getSortOrder()
|
||||
local settings = g_settings.getNode('BattleList')
|
||||
if not settings then
|
||||
return 'asc'
|
||||
end
|
||||
return settings['sortOrder']
|
||||
end
|
||||
|
||||
function setSortOrder(state)
|
||||
settings = {}
|
||||
settings['sortOrder'] = state
|
||||
g_settings.mergeNode('BattleList', settings)
|
||||
|
||||
checkCreatures()
|
||||
end
|
||||
|
||||
function isSortAsc()
|
||||
return getSortOrder() == 'asc'
|
||||
end
|
||||
|
||||
function isSortDesc()
|
||||
return getSortOrder() == 'desc'
|
||||
end
|
||||
|
||||
function isHidingFilters()
|
||||
local settings = g_settings.getNode('BattleList')
|
||||
if not settings then
|
||||
return false
|
||||
end
|
||||
return settings['hidingFilters']
|
||||
end
|
||||
|
||||
function setHidingFilters(state)
|
||||
settings = {}
|
||||
settings['hidingFilters'] = state
|
||||
g_settings.mergeNode('BattleList', settings)
|
||||
end
|
||||
|
||||
function hideFilterPanel()
|
||||
filterPanel.originalHeight = filterPanel:getHeight()
|
||||
filterPanel:setHeight(0)
|
||||
toggleFilterButton:getParent():setMarginTop(0)
|
||||
toggleFilterButton:setImageClip(torect("0 0 21 12"))
|
||||
setHidingFilters(true)
|
||||
filterPanel:setVisible(false)
|
||||
end
|
||||
|
||||
function showFilterPanel()
|
||||
toggleFilterButton:getParent():setMarginTop(5)
|
||||
filterPanel:setHeight(filterPanel.originalHeight)
|
||||
toggleFilterButton:setImageClip(torect("21 0 21 12"))
|
||||
setHidingFilters(false)
|
||||
filterPanel:setVisible(true)
|
||||
end
|
||||
|
||||
function toggleFilterPanel()
|
||||
if filterPanel:isVisible() then
|
||||
hideFilterPanel()
|
||||
else
|
||||
showFilterPanel()
|
||||
end
|
||||
end
|
||||
|
||||
function onChangeSortType(comboBox, option)
|
||||
setSortType(option:lower())
|
||||
end
|
||||
|
||||
function onChangeSortOrder(comboBox, option)
|
||||
setSortOrder(option:lower():gsub('[.]', '')) -- Replace dot in option name
|
||||
end
|
||||
|
||||
function checkCreatures()
|
||||
removeAllCreatures()
|
||||
|
||||
@@ -151,15 +272,42 @@ end
|
||||
function onCreatureHealthPercentChange(creature, health)
|
||||
local battleButton = battleButtonsByCreaturesList[creature:getId()]
|
||||
if battleButton then
|
||||
if getSortType() == 'health' then
|
||||
removeCreature(creature)
|
||||
addCreature(creature)
|
||||
return
|
||||
end
|
||||
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
||||
end
|
||||
end
|
||||
|
||||
local function getDistanceBetween(p1, p2)
|
||||
return math.max(math.abs(p1.x - p2.x), math.abs(p1.y - p2.y))
|
||||
end
|
||||
|
||||
function onCreaturePositionChange(creature, newPos, oldPos)
|
||||
if creature:isLocalPlayer() then
|
||||
if oldPos and newPos and newPos.z ~= oldPos.z then
|
||||
checkCreatures()
|
||||
else
|
||||
-- Distance will change when moving, recalculate and move to correct index
|
||||
if getSortType() == 'distance' then
|
||||
local distanceList = {}
|
||||
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
|
||||
table.insert(distanceList, {distance = getDistanceBetween(newPos, creatureButton.creature:getPosition()), widget = creatureButton})
|
||||
end
|
||||
|
||||
if isSortAsc() then
|
||||
table.sort(distanceList, function(a, b) return a.distance < b.distance end)
|
||||
else
|
||||
table.sort(distanceList, function(a, b) return a.distance > b.distance end)
|
||||
end
|
||||
|
||||
for i = 1, #distanceList do
|
||||
battlePanel:moveChildToIndex(distanceList[i].widget, i)
|
||||
end
|
||||
end
|
||||
|
||||
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
|
||||
addCreature(creatureButton.creature)
|
||||
end
|
||||
@@ -170,6 +318,9 @@ function onCreaturePositionChange(creature, newPos, oldPos)
|
||||
if has and not fit then
|
||||
removeCreature(creature)
|
||||
elseif fit then
|
||||
if has and getSortType() == 'distance' then
|
||||
removeCreature(creature)
|
||||
end
|
||||
addCreature(creature)
|
||||
end
|
||||
end
|
||||
@@ -201,8 +352,13 @@ function addCreature(creature)
|
||||
local creatureId = creature:getId()
|
||||
local battleButton = battleButtonsByCreaturesList[creatureId]
|
||||
|
||||
-- Register when creature is added to battlelist for the first time
|
||||
if not creatureAgeList[creatureId] then
|
||||
creatureAgeList[creatureId] = os.time()
|
||||
end
|
||||
|
||||
if not battleButton then
|
||||
battleButton = g_ui.createWidget('BattleButton', battlePanel)
|
||||
battleButton = g_ui.createWidget('BattleButton')
|
||||
battleButton:setup(creature)
|
||||
|
||||
battleButton.onHoverChange = onBattleButtonHoverChange
|
||||
@@ -217,6 +373,77 @@ function addCreature(creature)
|
||||
if creature == g_game.getFollowingCreature() then
|
||||
onFollow(creature)
|
||||
end
|
||||
|
||||
local inserted = false
|
||||
local nameLower = creature:getName():lower()
|
||||
local healthPercent = creature:getHealthPercent()
|
||||
local playerPosition = g_game.getLocalPlayer():getPosition()
|
||||
local distance = getDistanceBetween(playerPosition, creature:getPosition())
|
||||
local age = creatureAgeList[creatureId]
|
||||
|
||||
local childCount = battlePanel:getChildCount()
|
||||
for i = 1, childCount do
|
||||
local child = battlePanel:getChildByIndex(i)
|
||||
local childName = child:getCreature():getName():lower()
|
||||
local equal = false
|
||||
if getSortType() == 'age' then
|
||||
local childAge = creatureAgeList[child:getCreature():getId()]
|
||||
if (age < childAge and isSortAsc()) or (age > childAge and isSortDesc()) then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
break
|
||||
elseif age == childAge then
|
||||
equal = true
|
||||
end
|
||||
elseif getSortType() == 'distance' then
|
||||
local childDistance = getDistanceBetween(child:getCreature():getPosition(), playerPosition)
|
||||
if (distance < childDistance and isSortAsc()) or (distance > childDistance and isSortDesc()) then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
break
|
||||
elseif childDistance == distance then
|
||||
equal = true
|
||||
end
|
||||
elseif getSortType() == 'health' then
|
||||
local childHealth = child:getCreature():getHealthPercent()
|
||||
if (healthPercent < childHealth and isSortAsc()) or (healthPercent > childHealth and isSortDesc()) then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
break
|
||||
elseif healthPercent == childHealth then
|
||||
equal = true
|
||||
end
|
||||
end
|
||||
|
||||
-- If any other sort type is selected and values are equal, sort it by name also
|
||||
if getSortType() == 'name' or equal then
|
||||
local length = math.min(childName:len(), nameLower:len())
|
||||
for j=1,length do
|
||||
if (nameLower:byte(j) < childName:byte(j) and isSortAsc()) or (nameLower:byte(j) > childName:byte(j) and isSortDesc()) then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
break
|
||||
elseif (nameLower:byte(j) > childName:byte(j) and isSortAsc()) or (nameLower:byte(j) < childName:byte(j) and isSortDesc()) then
|
||||
break
|
||||
elseif j == nameLower:len() and isSortAsc() then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
elseif j == childName:len() and isSortDesc() then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if inserted then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Insert at the end if no other place is found
|
||||
if not inserted then
|
||||
battlePanel:insertChild(childCount + 1, battleButton)
|
||||
end
|
||||
else
|
||||
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
||||
end
|
||||
@@ -226,6 +453,7 @@ function addCreature(creature)
|
||||
end
|
||||
|
||||
function removeAllCreatures()
|
||||
creatureAgeList = {}
|
||||
for i, v in pairs(battleButtonsByCreaturesList) do
|
||||
removeCreature(v.creature)
|
||||
end
|
||||
|
@@ -45,11 +45,12 @@ MiniWindow
|
||||
&save: true
|
||||
|
||||
Panel
|
||||
id: filterPanel
|
||||
margin-top: 26
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: miniwindowScrollBar.left
|
||||
height: 20
|
||||
height: 45
|
||||
|
||||
Panel
|
||||
anchors.top: parent.top
|
||||
@@ -85,16 +86,56 @@ MiniWindow
|
||||
!tooltip: tr('Hide party members')
|
||||
@onCheckChange: modules.game_battle.checkCreatures()
|
||||
|
||||
HorizontalSeparator
|
||||
Panel
|
||||
anchors.top: prev.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 20
|
||||
width: 128
|
||||
margin-top: 6
|
||||
|
||||
ComboBox
|
||||
id: sortTypeBox
|
||||
width: 74
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-left: -28
|
||||
|
||||
ComboBox
|
||||
id: sortOrderBox
|
||||
width: 54
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
|
||||
Panel
|
||||
height: 18
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: miniwindowScrollBar.left
|
||||
margin-right: 1
|
||||
margin-top: 4
|
||||
margin-top: 5
|
||||
|
||||
UIWidget
|
||||
id: toggleFilterButton
|
||||
anchors.top: prev.top
|
||||
width: 21
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
image-source: /images/ui/arrow_vertical
|
||||
image-rect: 0 0 21 12
|
||||
image-clip: 21 0 21 12
|
||||
@onClick: modules.game_battle.toggleFilterPanel()
|
||||
phantom: false
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: miniwindowScrollBar.left
|
||||
margin-right: 1
|
||||
margin-top: 11
|
||||
|
||||
MiniWindowContents
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 0
|
||||
margin-top: 6
|
||||
|
||||
Panel
|
||||
id: battlePanel
|
||||
|
206
modules/game_console/communicationwindow.otui
Normal file
206
modules/game_console/communicationwindow.otui
Normal file
@@ -0,0 +1,206 @@
|
||||
IgnoreListLabel < Label
|
||||
font: verdana-11px-monochrome
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
phantom: false
|
||||
|
||||
$focus:
|
||||
background-color: #ffffff22
|
||||
color: #ffffff
|
||||
|
||||
WhiteListLabel < Label
|
||||
font: verdana-11px-monochrome
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
phantom: false
|
||||
|
||||
$focus:
|
||||
background-color: #ffffff22
|
||||
color: #ffffff
|
||||
|
||||
|
||||
MainWindow
|
||||
id: communicationWindow
|
||||
!text: tr('Ignore List')
|
||||
size: 515 410
|
||||
@onEscape: self:destroy()
|
||||
|
||||
CheckBox
|
||||
id: checkboxUseIgnoreList
|
||||
!text: tr('Activate ignorelist')
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
width: 180
|
||||
|
||||
Label
|
||||
!text: tr('Ignored Players:')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
|
||||
TextList
|
||||
id: ignoreList
|
||||
vertical-scrollbar: ignoreListScrollBar
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
height: 150
|
||||
width: 230
|
||||
margin-bottom: 10
|
||||
margin-top: 3
|
||||
padding: 1
|
||||
focusable: false
|
||||
|
||||
TextEdit
|
||||
id: ignoreNameEdit
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
width: 110
|
||||
margin-top: 5
|
||||
|
||||
Button
|
||||
id: buttonIgnoreAdd
|
||||
!text: tr('Add')
|
||||
width: 48
|
||||
height: 20
|
||||
margin-left: 5
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
|
||||
Button
|
||||
id: buttonIgnoreRemove
|
||||
!text: tr('Remove')
|
||||
width: 64
|
||||
height: 20
|
||||
margin-left: 5
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
|
||||
Label
|
||||
!text: tr('Global ignore settings')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 20
|
||||
|
||||
CheckBox
|
||||
id: checkboxIgnorePrivateMessages
|
||||
!text: tr('Ignore Private Messages')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
width: 180
|
||||
margin-top: 5
|
||||
|
||||
CheckBox
|
||||
id: checkboxIgnoreYelling
|
||||
!text: tr('Ignore Yelling')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
width: 180
|
||||
margin-top: 5
|
||||
|
||||
CheckBox
|
||||
id: checkboxUseWhiteList
|
||||
!text: tr('Activate whitelist')
|
||||
anchors.top: parent.top
|
||||
anchors.left: ignoreList.right
|
||||
margin-left: 20
|
||||
width: 180
|
||||
|
||||
Label
|
||||
!text: tr('Allowed Players:')
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 10
|
||||
|
||||
TextList
|
||||
id: whiteList
|
||||
vertical-scrollbar: whiteListScrollBar
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
height: 150
|
||||
width: 230
|
||||
margin-bottom: 10
|
||||
margin-top: 3
|
||||
padding: 1
|
||||
focusable: false
|
||||
|
||||
TextEdit
|
||||
id: whitelistNameEdit
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
width: 110
|
||||
margin-top: 5
|
||||
|
||||
Button
|
||||
id: buttonWhitelistAdd
|
||||
!text: tr('Add')
|
||||
width: 48
|
||||
height: 20
|
||||
margin-left: 5
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
|
||||
Button
|
||||
id: buttonWhitelistRemove
|
||||
!text: tr('Remove')
|
||||
width: 64
|
||||
height: 20
|
||||
margin-left: 5
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
|
||||
Label
|
||||
!text: tr('Global whitelist settings')
|
||||
anchors.left: whiteList.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 20
|
||||
|
||||
CheckBox
|
||||
id: checkboxAllowVIPs
|
||||
!text: tr('Allow VIPs to message you')
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
width: 180
|
||||
margin-top: 5
|
||||
|
||||
Panel
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 30
|
||||
|
||||
Panel
|
||||
size: 160 30
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Button
|
||||
id: buttonSave
|
||||
!text: tr('Save')
|
||||
width: 75
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
||||
Button
|
||||
id: buttonCancel
|
||||
!text: tr('Cancel')
|
||||
width: 75
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
|
||||
VerticalScrollBar
|
||||
id: ignoreListScrollBar
|
||||
anchors.top: ignoreList.top
|
||||
anchors.bottom: ignoreList.bottom
|
||||
anchors.right: ignoreList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
VerticalScrollBar
|
||||
id: whiteListScrollBar
|
||||
anchors.top: whiteList.top
|
||||
anchors.bottom: whiteList.bottom
|
||||
anchors.right: whiteList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
@@ -61,7 +61,7 @@ consoleTabBar = nil
|
||||
consoleTextEdit = nil
|
||||
channels = nil
|
||||
channelsWindow = nil
|
||||
ignoreWindow = nil
|
||||
communicationWindow = nil
|
||||
ownPrivateName = nil
|
||||
messageHistory = {}
|
||||
currentMessageIndex = 0
|
||||
@@ -74,10 +74,14 @@ violationReportTab = nil
|
||||
ignoredChannels = {}
|
||||
filters = {}
|
||||
|
||||
local ignoreSettings = {
|
||||
local communicationSettings = {
|
||||
useIgnoreList = true,
|
||||
useWhiteList = true,
|
||||
privateMessages = false,
|
||||
yelling = false,
|
||||
players = {}
|
||||
allowVIPs = false,
|
||||
ignoredPlayers = {},
|
||||
whitelistedPlayers = {}
|
||||
}
|
||||
|
||||
function init()
|
||||
@@ -139,10 +143,59 @@ function init()
|
||||
g_keyboard.bindKeyDown('Ctrl+O', g_game.requestChannels)
|
||||
g_keyboard.bindKeyDown('Ctrl+E', removeCurrentTab)
|
||||
g_keyboard.bindKeyDown('Ctrl+H', openHelp)
|
||||
|
||||
|
||||
consoleToggleChat = consolePanel:getChildById('toggleChat')
|
||||
load()
|
||||
end
|
||||
|
||||
function toggleChat()
|
||||
if consoleToggleChat:isChecked() then
|
||||
disableChat()
|
||||
else
|
||||
enableChat()
|
||||
end
|
||||
end
|
||||
|
||||
function enableChat()
|
||||
local gameInterface = modules.game_interface
|
||||
|
||||
consoleTextEdit:setVisible(true)
|
||||
consoleTextEdit:setText("")
|
||||
|
||||
g_keyboard.unbindKeyUp("Space")
|
||||
g_keyboard.unbindKeyUp("Enter")
|
||||
|
||||
gameInterface.unbindWalkKey("W")
|
||||
gameInterface.unbindWalkKey("D")
|
||||
gameInterface.unbindWalkKey("S")
|
||||
gameInterface.unbindWalkKey("A")
|
||||
|
||||
consoleToggleChat:setTooltip(tr("Disable chat mode, allow to walk using ASDW"))
|
||||
end
|
||||
|
||||
function disableChat()
|
||||
local gameInterface = modules.game_interface
|
||||
|
||||
consoleTextEdit:setVisible(false)
|
||||
consoleTextEdit:setText("")
|
||||
|
||||
local quickFunc = function()
|
||||
if consoleToggleChat:isChecked() then
|
||||
consoleToggleChat:setChecked(false)
|
||||
end
|
||||
enableChat()
|
||||
end
|
||||
g_keyboard.bindKeyUp("Space", quickFunc)
|
||||
g_keyboard.bindKeyUp("Enter", quickFunc)
|
||||
|
||||
gameInterface.bindWalkKey("W", North)
|
||||
gameInterface.bindWalkKey("D", East)
|
||||
gameInterface.bindWalkKey("S", South)
|
||||
gameInterface.bindWalkKey("A", West)
|
||||
|
||||
consoleToggleChat:setTooltip(tr("Enable chat mode"))
|
||||
end
|
||||
|
||||
function terminate()
|
||||
save()
|
||||
disconnect(g_game, {
|
||||
@@ -166,14 +219,14 @@ function terminate()
|
||||
g_keyboard.unbindKeyDown('Ctrl+E')
|
||||
g_keyboard.unbindKeyDown('Ctrl+H')
|
||||
|
||||
saveIgnoreSettings()
|
||||
saveCommunicationSettings()
|
||||
|
||||
if channelsWindow then
|
||||
channelsWindow:destroy()
|
||||
end
|
||||
|
||||
if ignoreWindow then
|
||||
ignoreWindow:destroy()
|
||||
if communicationWindow then
|
||||
communicationWindow:destroy()
|
||||
end
|
||||
|
||||
if violationWindow then
|
||||
@@ -197,7 +250,7 @@ function load()
|
||||
if settings then
|
||||
messageHistory = settings.messageHistory or {}
|
||||
end
|
||||
loadIgnoreSettings()
|
||||
loadCommunicationSettings()
|
||||
end
|
||||
|
||||
function onTabChange(tabBar, tab)
|
||||
@@ -466,7 +519,7 @@ function addTabText(text, speaktype, tab, creatureName)
|
||||
-- Remove the curly braces
|
||||
for i = 1, #highlightData / 3 do
|
||||
local dataBlock = { _start = highlightData[(i-1)*3+1], _end = highlightData[(i-1)*3+2], words = highlightData[(i-1)*3+3] }
|
||||
text = text:gsub("{"..dataBlock.words.."}", dataBlock.words)
|
||||
text = text:gsub("%{(.-)%}", dataBlock.words, 1)
|
||||
|
||||
-- Recalculate positions as braces are removed
|
||||
highlightData[(i-1)*3+1] = dataBlock._start - ((i-1) * 2)
|
||||
@@ -779,7 +832,11 @@ function onTalk(name, level, mode, message, channelId, creaturePos)
|
||||
return
|
||||
end
|
||||
|
||||
if name ~= g_game.getCharacterName() then
|
||||
local localPlayer = g_game.getLocalPlayer()
|
||||
if name ~= g_game.getCharacterName()
|
||||
and isUsingIgnoreList()
|
||||
and not(isUsingWhiteList()) or (isUsingWhiteList() and not(isWhitelisted(name)) and not(isAllowingVIPs() and localPlayer:hasVip(name))) then
|
||||
|
||||
if mode == MessageModes.Yell and isIgnoringYelling() then
|
||||
return
|
||||
elseif speaktype.private and isIgnoringPrivate() and mode ~= MessageModes.NpcFrom then
|
||||
@@ -957,107 +1014,221 @@ function onChannelList(channelList)
|
||||
end
|
||||
end
|
||||
|
||||
function loadIgnoreSettings()
|
||||
function loadCommunicationSettings()
|
||||
communicationSettings.whitelistedPlayers = {}
|
||||
communicationSettings.ignoredPlayers = {}
|
||||
|
||||
local ignoreNode = g_settings.getNode('IgnorePlayers')
|
||||
if ignoreNode then
|
||||
for i = 1, #ignoreNode do
|
||||
table.insert(ignoreSettings.players, ignoreNode[i])
|
||||
table.insert(communicationSettings.ignoredPlayers, ignoreNode[i])
|
||||
end
|
||||
end
|
||||
ignoreSettings.privateMessages = g_settings.getBoolean('IgnorePrivateMessages')
|
||||
ignoreSettings.yelling = g_settings.getBoolean('IgnoreYelling')
|
||||
end
|
||||
|
||||
function saveIgnoreSettings()
|
||||
local tmpSettings = {}
|
||||
for i = 1, #ignoreSettings.players do
|
||||
table.insert(tmpSettings, ignoreSettings.players[i])
|
||||
local whitelistNode = g_settings.getNode('WhitelistedPlayers')
|
||||
if whitelistNode then
|
||||
for i = 1, #whitelistNode do
|
||||
table.insert(communicationSettings.whitelistedPlayers, whitelistNode[i])
|
||||
end
|
||||
end
|
||||
g_settings.set('IgnorePrivateMessages', ignoreSettings.privateMessages)
|
||||
g_settings.set('IgnoreYelling', ignoreSettings.yelling)
|
||||
g_settings.setNode('IgnorePlayers', tmpSettings)
|
||||
|
||||
communicationSettings.useIgnoreList = g_settings.getBoolean('UseIgnoreList')
|
||||
communicationSettings.useWhiteList = g_settings.getBoolean('UseWhiteList')
|
||||
communicationSettings.privateMessages = g_settings.getBoolean('IgnorePrivateMessages')
|
||||
communicationSettings.yelling = g_settings.getBoolean('IgnoreYelling')
|
||||
communicationSettings.allowVIPs = g_settings.getBoolean('AllowVIPs')
|
||||
end
|
||||
|
||||
function saveCommunicationSettings()
|
||||
local tmpIgnoreList = {}
|
||||
local ignoredPlayers = getIgnoredPlayers()
|
||||
for i = 1, #ignoredPlayers do
|
||||
table.insert(tmpIgnoreList, ignoredPlayers[i])
|
||||
end
|
||||
|
||||
local tmpWhiteList = {}
|
||||
local whitelistedPlayers = getWhitelistedPlayers()
|
||||
for i = 1, #whitelistedPlayers do
|
||||
table.insert(tmpWhiteList, whitelistedPlayers[i])
|
||||
end
|
||||
|
||||
g_settings.set('UseIgnoreList', communicationSettings.useIgnoreList)
|
||||
g_settings.set('UseWhiteList', communicationSettings.useWhiteList)
|
||||
g_settings.set('IgnorePrivateMessages', communicationSettings.privateMessages)
|
||||
g_settings.set('IgnoreYelling', communicationSettings.yelling)
|
||||
g_settings.setNode('IgnorePlayers', tmpIgnoreList)
|
||||
g_settings.setNode('WhitelistedPlayers', tmpWhiteList)
|
||||
end
|
||||
|
||||
function getIgnoredPlayers()
|
||||
return communicationSettings.ignoredPlayers
|
||||
end
|
||||
|
||||
function getWhitelistedPlayers()
|
||||
return communicationSettings.whitelistedPlayers
|
||||
end
|
||||
|
||||
function isUsingIgnoreList()
|
||||
return communicationSettings.useIgnoreList
|
||||
end
|
||||
|
||||
function isUsingWhiteList()
|
||||
return communicationSettings.useWhiteList
|
||||
end
|
||||
function isIgnored(name)
|
||||
return table.find(ignoreSettings.players, name, true)
|
||||
return table.find(communicationSettings.ignoredPlayers, name, true)
|
||||
end
|
||||
|
||||
function addIgnoredPlayer(name)
|
||||
if not isIgnored(name) then
|
||||
table.insert(ignoreSettings.players, name)
|
||||
end
|
||||
if isIgnored(name) then return end
|
||||
table.insert(communicationSettings.ignoredPlayers, name)
|
||||
end
|
||||
|
||||
function removeIgnoredPlayer(name)
|
||||
table.removevalue(ignoreSettings.players, name)
|
||||
table.removevalue(communicationSettings.ignoredPlayers, name)
|
||||
end
|
||||
|
||||
function isWhitelisted(name)
|
||||
return table.find(communicationSettings.whitelistedPlayers, name, true)
|
||||
end
|
||||
|
||||
function addWhitelistedPlayer(name)
|
||||
if isWhitelisted(name) then return end
|
||||
table.insert(communicationSettings.whitelistedPlayers, name)
|
||||
end
|
||||
|
||||
function removeWhitelistedPlayer(name)
|
||||
table.removevalue(communicationSettings.whitelistedPlayers, name)
|
||||
end
|
||||
|
||||
function isIgnoringPrivate()
|
||||
return ignoreSettings.privateMessages
|
||||
return communicationSettings.privateMessages
|
||||
end
|
||||
|
||||
function isIgnoringYelling()
|
||||
return ignoreSettings.yelling
|
||||
return communicationSettings.yelling
|
||||
end
|
||||
|
||||
function isAllowingVIPs()
|
||||
return communicationSettings.allowVIPs
|
||||
end
|
||||
|
||||
function onClickIgnoreButton()
|
||||
if ignoreWindow then return end
|
||||
ignoreWindow = g_ui.displayUI('ignorewindow')
|
||||
local ignoreListPanel = ignoreWindow:getChildById('ignoreList')
|
||||
ignoreWindow.onDestroy = function() ignoreWindow = nil end
|
||||
if communicationWindow then return end
|
||||
communicationWindow = g_ui.displayUI('communicationwindow')
|
||||
local ignoreListPanel = communicationWindow:getChildById('ignoreList')
|
||||
local whiteListPanel = communicationWindow:getChildById('whiteList')
|
||||
communicationWindow.onDestroy = function() communicationWindow = nil end
|
||||
|
||||
local removeButton = ignoreWindow:getChildById('buttonRemove')
|
||||
removeButton:disable()
|
||||
ignoreListPanel.onChildFocusChange = function() removeButton:enable() end
|
||||
removeButton.onClick = function()
|
||||
local useIgnoreListBox = communicationWindow:getChildById('checkboxUseIgnoreList')
|
||||
useIgnoreListBox:setChecked(communicationSettings.useIgnoreList)
|
||||
local useWhiteListBox = communicationWindow:getChildById('checkboxUseWhiteList')
|
||||
useWhiteListBox:setChecked(communicationSettings.useWhiteList)
|
||||
|
||||
local removeIgnoreButton = communicationWindow:getChildById('buttonIgnoreRemove')
|
||||
removeIgnoreButton:disable()
|
||||
ignoreListPanel.onChildFocusChange = function() removeIgnoreButton:enable() end
|
||||
removeIgnoreButton.onClick = function()
|
||||
local selection = ignoreListPanel:getFocusedChild()
|
||||
if selection then
|
||||
ignoreListPanel:removeChild(selection)
|
||||
selection:destroy()
|
||||
ignoreListPanel:removeChild(selection)
|
||||
selection:destroy()
|
||||
end
|
||||
if ignoreListPanel:getChildCount() == 0 then
|
||||
removeButton:disable()
|
||||
removeIgnoreButton:disable()
|
||||
end
|
||||
|
||||
local removeWhitelistButton = communicationWindow:getChildById('buttonWhitelistRemove')
|
||||
removeWhitelistButton:disable()
|
||||
whiteListPanel.onChildFocusChange = function() removeWhitelistButton:enable() end
|
||||
removeWhitelistButton.onClick = function()
|
||||
local selection = whiteListPanel:getFocusedChild()
|
||||
if selection then
|
||||
whiteListPanel:removeChild(selection)
|
||||
selection:destroy()
|
||||
end
|
||||
removeWhitelistButton:disable()
|
||||
end
|
||||
|
||||
local newlyIgnoredPlayers = {}
|
||||
local addName = ignoreWindow:getChildById('ignoreNameEdit')
|
||||
local addButton = ignoreWindow:getChildById('buttonAdd')
|
||||
local addFunction = function()
|
||||
if addName:getText() == '' then return end
|
||||
if table.find(ignoreSettings.players, addName:getText()) then return end
|
||||
if table.find(newlyIgnoredPlayers, addName:getText()) then return end
|
||||
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
||||
label:setText(addName:getText())
|
||||
table.insert(newlyIgnoredPlayers, addName:getText())
|
||||
label:setPhantom(false)
|
||||
addName:setText('')
|
||||
end
|
||||
addButton.onClick = addFunction
|
||||
ignoreWindow.onEnter = addFunction
|
||||
|
||||
local ignorePrivateMessageBox = ignoreWindow:getChildById('checkboxIgnorePrivateMessages')
|
||||
ignorePrivateMessageBox:setChecked(ignoreSettings.privateMessages)
|
||||
local ignoreYellingBox = ignoreWindow:getChildById('checkboxIgnoreYelling')
|
||||
ignoreYellingBox:setChecked(ignoreSettings.yelling)
|
||||
|
||||
local saveButton = ignoreWindow:getChildById('buttonSave')
|
||||
saveButton.onClick = function()
|
||||
ignoreSettings.players = {}
|
||||
for i = 1, ignoreListPanel:getChildCount() do
|
||||
addIgnoredPlayer(ignoreListPanel:getChildByIndex(i):getText())
|
||||
--table.insert(ignoreSettings.players, ignoreListPanel:getChildByIndex(i):getText())
|
||||
end
|
||||
|
||||
ignoreSettings.yelling = ignoreYellingBox:isChecked()
|
||||
ignoreSettings.privateMessages = ignorePrivateMessageBox:isChecked()
|
||||
ignoreWindow:destroy()
|
||||
end
|
||||
|
||||
for _, name in pairs(ignoreSettings.players) do
|
||||
local addIgnoreName = communicationWindow:getChildById('ignoreNameEdit')
|
||||
local addIgnoreButton = communicationWindow:getChildById('buttonIgnoreAdd')
|
||||
local addIgnoreFunction = function()
|
||||
local newEntry = addIgnoreName:getText()
|
||||
if newEntry == '' then return end
|
||||
if table.find(getIgnoredPlayers(), newEntry) then return end
|
||||
if table.find(newlyIgnoredPlayers, newEntry) then return end
|
||||
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
||||
label:setText(name)
|
||||
label:setPhantom(false)
|
||||
label:setText(newEntry)
|
||||
table.insert(newlyIgnoredPlayers, newEntry)
|
||||
addIgnoreName:setText('')
|
||||
end
|
||||
addIgnoreButton.onClick = addIgnoreFunction
|
||||
|
||||
local newlyWhitelistedPlayers = {}
|
||||
local addWhitelistName = communicationWindow:getChildById('whitelistNameEdit')
|
||||
local addWhitelistButton = communicationWindow:getChildById('buttonWhitelistAdd')
|
||||
local addWhitelistFunction = function()
|
||||
local newEntry = addWhitelistName:getText()
|
||||
if newEntry == '' then return end
|
||||
if table.find(getWhitelistedPlayers(), newEntry) then return end
|
||||
if table.find(newlyWhitelistedPlayers, newEntry) then return end
|
||||
local label = g_ui.createWidget('WhiteListLabel', whiteListPanel)
|
||||
label:setText(newEntry)
|
||||
table.insert(newlyWhitelistedPlayers, newEntry)
|
||||
addWhitelistName:setText('')
|
||||
end
|
||||
addWhitelistButton.onClick = addWhitelistFunction
|
||||
|
||||
communicationWindow.onEnter = function()
|
||||
if addWhitelistName:isFocused() then
|
||||
addWhitelistFunction()
|
||||
elseif addIgnoreName:isFocused() then
|
||||
addIgnoreFunction()
|
||||
end
|
||||
end
|
||||
|
||||
local ignorePrivateMessageBox = communicationWindow:getChildById('checkboxIgnorePrivateMessages')
|
||||
ignorePrivateMessageBox:setChecked(communicationSettings.privateMessages)
|
||||
local ignoreYellingBox = communicationWindow:getChildById('checkboxIgnoreYelling')
|
||||
ignoreYellingBox:setChecked(communicationSettings.yelling)
|
||||
local allowVIPsBox = communicationWindow:getChildById('checkboxAllowVIPs')
|
||||
allowVIPsBox:setChecked(communicationSettings.allowVIPs)
|
||||
|
||||
local saveButton = communicationWindow:recursiveGetChildById('buttonSave')
|
||||
saveButton.onClick = function()
|
||||
communicationSettings.ignoredPlayers = {}
|
||||
for i = 1, ignoreListPanel:getChildCount() do
|
||||
addIgnoredPlayer(ignoreListPanel:getChildByIndex(i):getText())
|
||||
end
|
||||
|
||||
communicationSettings.whitelistedPlayers = {}
|
||||
for i = 1, whiteListPanel:getChildCount() do
|
||||
addWhitelistedPlayer(whiteListPanel:getChildByIndex(i):getText())
|
||||
end
|
||||
|
||||
communicationSettings.useIgnoreList = useIgnoreListBox:isChecked()
|
||||
communicationSettings.useWhiteList = useWhiteListBox:isChecked()
|
||||
communicationSettings.yelling = ignoreYellingBox:isChecked()
|
||||
communicationSettings.privateMessages = ignorePrivateMessageBox:isChecked()
|
||||
communicationSettings.allowVIPs = allowVIPsBox:isChecked()
|
||||
communicationWindow:destroy()
|
||||
end
|
||||
|
||||
local cancelButton = communicationWindow:recursiveGetChildById('buttonCancel')
|
||||
cancelButton.onClick = function()
|
||||
communicationWindow:destroy()
|
||||
end
|
||||
|
||||
local ignoredPlayers = getIgnoredPlayers()
|
||||
for i = 1, #ignoredPlayers do
|
||||
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
||||
label:setText(ignoredPlayers[i])
|
||||
end
|
||||
|
||||
local whitelistedPlayers = getWhitelistedPlayers()
|
||||
for i = 1, #whitelistedPlayers do
|
||||
local label = g_ui.createWidget('WhiteListLabel', whiteListPanel)
|
||||
label:setText(whitelistedPlayers[i])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1089,4 +1260,4 @@ function offline()
|
||||
g_keyboard.unbindKeyDown('Ctrl+R')
|
||||
end
|
||||
clear()
|
||||
end
|
||||
end
|
@@ -56,12 +56,21 @@ Panel
|
||||
id: consolePanel
|
||||
anchors.fill: parent
|
||||
|
||||
CheckBox
|
||||
id: toggleChat
|
||||
!tooltip: tr('Disable chat mode, allow to walk using ASDW')
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
margin-left: 13
|
||||
margin-top: 8
|
||||
@onCheckChange: toggleChat()
|
||||
|
||||
TabButton
|
||||
id: prevChannelButton
|
||||
icon: /images/game/console/leftarrow
|
||||
anchors.left: parent.left
|
||||
anchors.left: toggleChat.right
|
||||
anchors.top: parent.top
|
||||
margin-left: 6
|
||||
margin-left: 3
|
||||
margin-top: 6
|
||||
|
||||
ConsoleTabBar
|
||||
|
@@ -1,98 +0,0 @@
|
||||
IgnoreListLabel < Label
|
||||
font: verdana-11px-monochrome
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
|
||||
$focus:
|
||||
background-color: #ffffff22
|
||||
color: #ffffff
|
||||
|
||||
MainWindow
|
||||
id: ignoreWindow
|
||||
!text: tr('Ignore List')
|
||||
size: 500 240
|
||||
@onEscape: self:destroy()
|
||||
|
||||
Label
|
||||
!text: tr('Ignored players:')
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
||||
TextList
|
||||
id: ignoreList
|
||||
vertical-scrollbar: ignoreListScrollBar
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
height: 150
|
||||
width: 230
|
||||
margin-bottom: 10
|
||||
margin-top: 3
|
||||
padding: 1
|
||||
focusable: false
|
||||
|
||||
Button
|
||||
id: buttonRemove
|
||||
!text: tr('Remove')
|
||||
width: 64
|
||||
anchors.right: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
TextEdit
|
||||
id: ignoreNameEdit
|
||||
anchors.left: ignoreList.right
|
||||
anchors.top: ignoreList.top
|
||||
width: 180
|
||||
margin-left: 8
|
||||
margin-right: 3
|
||||
|
||||
Button
|
||||
id: buttonAdd
|
||||
!text: tr('Add')
|
||||
width: 48
|
||||
height: 20
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.top
|
||||
|
||||
CheckBox
|
||||
id: checkboxIgnorePrivateMessages
|
||||
!text: tr('Ignore Private Messages')
|
||||
anchors.left: ignoreList.right
|
||||
anchors.top: ignoreList.top
|
||||
width: 180
|
||||
margin-top: 25
|
||||
margin-left: 8
|
||||
|
||||
CheckBox
|
||||
id: checkboxIgnoreYelling
|
||||
!text: tr('Ignore Yelling')
|
||||
anchors.left: ignoreList.right
|
||||
anchors.top: prev.top
|
||||
width: 180
|
||||
margin-top: 25
|
||||
margin-left: 8
|
||||
|
||||
Button
|
||||
id: buttonSave
|
||||
!text: tr('Save')
|
||||
width: 64
|
||||
anchors.right: next.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 10
|
||||
@onClick: self:getParent():onEnter()
|
||||
|
||||
Button
|
||||
id: buttonCancel
|
||||
!text: tr('Cancel')
|
||||
width: 64
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
@onClick: self:getParent():destroy()
|
||||
|
||||
VerticalScrollBar
|
||||
id: ignoreListScrollBar
|
||||
anchors.top: ignoreList.top
|
||||
anchors.bottom: ignoreList.bottom
|
||||
anchors.right: ignoreList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
@@ -42,7 +42,8 @@ function init()
|
||||
gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel')
|
||||
connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange })
|
||||
|
||||
logoutButton = modules.client_topmenu.addLeftButton('logoutButton', tr('Exit'), '/images/topbuttons/logout', tryLogout, true)
|
||||
logoutButton = modules.client_topmenu.addLeftButton('logoutButton', tr('Exit'),
|
||||
'/images/topbuttons/logout', tryLogout, true)
|
||||
|
||||
setupViewMode(0)
|
||||
|
||||
@@ -56,42 +57,19 @@ end
|
||||
|
||||
function bindKeys()
|
||||
gameRootPanel:setAutoRepeatDelay(250)
|
||||
g_keyboard.bindKeyDown('Up', function() changeWalkDir(North) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Right', function() changeWalkDir(East) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Down', function() changeWalkDir(South) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Left', function() changeWalkDir(West) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad8', function() changeWalkDir(North) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad9', function() changeWalkDir(NorthEast) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad6', function() changeWalkDir(East) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad3', function() changeWalkDir(SouthEast) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad2', function() changeWalkDir(South) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad1', function() changeWalkDir(SouthWest) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad4', function() changeWalkDir(West) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad7', function() changeWalkDir(NorthWest) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Up', function() changeWalkDir(North, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Right', function() changeWalkDir(East, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Down', function() changeWalkDir(South, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Left', function() changeWalkDir(West, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad8', function() changeWalkDir(North, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad9', function() changeWalkDir(NorthEast, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad6', function() changeWalkDir(East, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad3', function() changeWalkDir(SouthEast, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad2', function() changeWalkDir(South, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad1', function() changeWalkDir(SouthWest, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad4', function() changeWalkDir(West, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad7', function() changeWalkDir(NorthWest, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyPress('Up', function() smartWalk(North) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Right', function() smartWalk(East) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Down', function() smartWalk(South) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Left', function() smartWalk(West) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad8', function() smartWalk(North) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad9', function() smartWalk(NorthEast) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad6', function() smartWalk(East) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad3', function() smartWalk(SouthEast) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad2', function() smartWalk(South) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad1', function() smartWalk(SouthWest) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad4', function() smartWalk(West) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad7', function() smartWalk(NorthWest) end, gameRootPanel)
|
||||
|
||||
bindWalkKey('Up', North)
|
||||
bindWalkKey('Right', East)
|
||||
bindWalkKey('Down', South)
|
||||
bindWalkKey('Left', West)
|
||||
bindWalkKey('Numpad8', North)
|
||||
bindWalkKey('Numpad9', NorthEast)
|
||||
bindWalkKey('Numpad6', East)
|
||||
bindWalkKey('Numpad3', SouthEast)
|
||||
bindWalkKey('Numpad2', South)
|
||||
bindWalkKey('Numpad1', SouthWest)
|
||||
bindWalkKey('Numpad4', West)
|
||||
bindWalkKey('Numpad7', NorthWest)
|
||||
|
||||
g_keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Ctrl+Right', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel)
|
||||
@@ -104,12 +82,24 @@ function bindKeys()
|
||||
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+Q', function() tryLogout(false) end, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+L', function() tryLogout(false) end, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
|
||||
end
|
||||
|
||||
function bindWalkKey(key, dir)
|
||||
g_keyboard.bindKeyDown(key, function() changeWalkDir(dir) end)
|
||||
g_keyboard.bindKeyUp(key, function() changeWalkDir(dir, true) end)
|
||||
g_keyboard.bindKeyPress(key, function() smartWalk(dir) end)
|
||||
end
|
||||
|
||||
function unbindWalkKey(key)
|
||||
g_keyboard.unbindKeyDown(key)
|
||||
g_keyboard.unbindKeyUp(key)
|
||||
g_keyboard.unbindKeyPress(key)
|
||||
end
|
||||
|
||||
function terminate()
|
||||
save()
|
||||
hide()
|
||||
@@ -215,8 +205,8 @@ function tryExit()
|
||||
return true
|
||||
end
|
||||
|
||||
local exitFunc = function() logout() forceExit() end
|
||||
local logoutFunc = function() logout() exitWindow:destroy() exitWindow = nil end
|
||||
local exitFunc = function() g_game.safeLogout() forceExit() end
|
||||
local logoutFunc = function() g_game.safeLogout() exitWindow:destroy() exitWindow = nil end
|
||||
local cancelFunc = function() exitWindow:destroy() exitWindow = nil end
|
||||
|
||||
exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."),
|
||||
@@ -228,14 +218,10 @@ function tryExit()
|
||||
return true
|
||||
end
|
||||
|
||||
function logout()
|
||||
if g_game.isOnline() then
|
||||
g_game.safeLogout()
|
||||
return true
|
||||
function tryLogout(prompt)
|
||||
if type(prompt) ~= "boolean" then
|
||||
prompt = true
|
||||
end
|
||||
end
|
||||
|
||||
function tryLogout()
|
||||
if not g_game.isOnline() then
|
||||
exit()
|
||||
return
|
||||
@@ -245,13 +231,42 @@ function tryLogout()
|
||||
return
|
||||
end
|
||||
|
||||
local yesCallback = function() logout() logoutWindow:destroy() logoutWindow=nil end
|
||||
local noCallback = function() logoutWindow:destroy() logoutWindow=nil end
|
||||
local msg, yesCallback
|
||||
if not g_game.isConnectionOk() then
|
||||
msg = 'Your connection is failing, if you logout now your character will be still online, do you want to force logout?'
|
||||
|
||||
logoutWindow = displayGeneralBox(tr('Logout'), tr('Are you sure you want to logout?'), {
|
||||
{ text=tr('Yes'), callback=yesCallback },
|
||||
{ text=tr('No'), callback=noCallback },
|
||||
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
||||
yesCallback = function()
|
||||
g_game.forceLogout()
|
||||
if logoutWindow then
|
||||
logoutWindow:destroy()
|
||||
logoutWindow=nil
|
||||
end
|
||||
end
|
||||
else
|
||||
msg = 'Are you sure you want to logout?'
|
||||
|
||||
yesCallback = function()
|
||||
g_game.safeLogout()
|
||||
if logoutWindow then
|
||||
logoutWindow:destroy()
|
||||
logoutWindow=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local noCallback = function()
|
||||
logoutWindow:destroy()
|
||||
logoutWindow=nil
|
||||
end
|
||||
|
||||
if prompt then
|
||||
logoutWindow = displayGeneralBox(tr('Logout'), tr(msg), {
|
||||
{ text=tr('Yes'), callback=yesCallback },
|
||||
{ text=tr('No'), callback=noCallback },
|
||||
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
||||
else
|
||||
yesCallback()
|
||||
end
|
||||
end
|
||||
|
||||
function stopSmartWalk()
|
||||
@@ -463,17 +478,20 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
end
|
||||
|
||||
else
|
||||
local localPosition = localPlayer:getPosition()
|
||||
if not classic then shortcut = '(Alt)' else shortcut = nil end
|
||||
if g_game.getAttackingCreature() ~= creatureThing then
|
||||
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut)
|
||||
else
|
||||
menu:addOption(tr('Stop Attack'), function() g_game.cancelAttack() end, shortcut)
|
||||
end
|
||||
|
||||
if g_game.getFollowingCreature() ~= creatureThing then
|
||||
menu:addOption(tr('Follow'), function() g_game.follow(creatureThing) end)
|
||||
else
|
||||
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
|
||||
if creatureThing:getPosition().z == localPosition.z then
|
||||
if g_game.getAttackingCreature() ~= creatureThing then
|
||||
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut)
|
||||
else
|
||||
menu:addOption(tr('Stop Attack'), function() g_game.cancelAttack() end, shortcut)
|
||||
end
|
||||
|
||||
if g_game.getFollowingCreature() ~= creatureThing then
|
||||
menu:addOption(tr('Follow'), function() g_game.follow(creatureThing) end)
|
||||
else
|
||||
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
|
||||
end
|
||||
end
|
||||
|
||||
if creatureThing:isPlayer() then
|
||||
@@ -519,7 +537,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
end
|
||||
end
|
||||
|
||||
if modules.game_ruleviolation.hasWindowAccess() then
|
||||
if modules.game_ruleviolation.hasWindowAccess() and creatureThing:isPlayer() then
|
||||
menu:addSeparator()
|
||||
menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end)
|
||||
end
|
||||
@@ -531,7 +549,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
menu:display(menuPosition)
|
||||
end
|
||||
|
||||
function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing)
|
||||
function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, attackCreature)
|
||||
local keyboardModifiers = g_keyboard.getModifiers()
|
||||
|
||||
if not modules.client_options.getOption('classicControl') then
|
||||
@@ -557,7 +575,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
||||
return true
|
||||
end
|
||||
return true
|
||||
elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
elseif attackCreature and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
g_game.attack(attackCreature)
|
||||
return true
|
||||
elseif creatureThing and creatureThing:getPosition().z == autoWalkPos.z and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
g_game.attack(creatureThing)
|
||||
return true
|
||||
end
|
||||
@@ -566,7 +587,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
||||
else
|
||||
if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
|
||||
local player = g_game.getLocalPlayer()
|
||||
if creatureThing and creatureThing ~= player then
|
||||
if attackCreature and attackCreature ~= player then
|
||||
g_game.attack(attackCreature)
|
||||
return true
|
||||
elseif creatureThing and creatureThing ~= player and creatureThing:getPosition().z == autoWalkPos.z then
|
||||
g_game.attack(creatureThing)
|
||||
return true
|
||||
elseif useThing:isContainer() then
|
||||
@@ -594,7 +618,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
||||
elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
return true
|
||||
elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
elseif attackCreature and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
g_game.attack(attackCreature)
|
||||
return true
|
||||
elseif creatureThing and creatureThing:getPosition().z == autoWalkPos.z and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
g_game.attack(creatureThing)
|
||||
return true
|
||||
end
|
||||
@@ -655,6 +682,8 @@ function moveStackableItem(item, toPos)
|
||||
end
|
||||
g_keyboard.bindKeyPress("Up", function() check() spinbox:up() end, spinbox)
|
||||
g_keyboard.bindKeyPress("Down", function() check() spinbox:down() end, spinbox)
|
||||
g_keyboard.bindKeyPress("Right", function() check() spinbox:up() end, spinbox)
|
||||
g_keyboard.bindKeyPress("Left", function() check() spinbox:down() end, spinbox)
|
||||
g_keyboard.bindKeyPress("PageUp", function() check() spinbox:setValue(spinbox:getValue()+10) end, spinbox)
|
||||
g_keyboard.bindKeyPress("PageDown", function() check() spinbox:setValue(spinbox:getValue()-10) end, spinbox)
|
||||
|
||||
@@ -747,7 +776,6 @@ function setupViewMode(mode)
|
||||
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
|
||||
elseif mode == 2 then
|
||||
local limit = limitZoom and not g_game.isGM()
|
||||
gameMapPanel:setKeepAspectRatio(false)
|
||||
gameMapPanel:setLimitVisibleRange(limit)
|
||||
gameMapPanel:setZoom(11)
|
||||
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
|
||||
|
@@ -6,11 +6,11 @@ CountWindow < MainWindow
|
||||
SpinBox
|
||||
id: spinBox
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.bottom
|
||||
width: 0
|
||||
height: 0
|
||||
anchors.top: parent.top
|
||||
width: 1
|
||||
height: 1
|
||||
phantom: true
|
||||
padding-bottom: -40
|
||||
margin-top: 2
|
||||
focusable: true
|
||||
|
||||
Item
|
||||
|
@@ -78,15 +78,21 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton)
|
||||
local useThing
|
||||
local creatureThing
|
||||
local multiUseThing
|
||||
local attackCreature
|
||||
|
||||
local tile = self:getTile(mousePosition)
|
||||
if tile then
|
||||
lookThing = tile:getTopLookThing()
|
||||
useThing = tile:getTopUseThing()
|
||||
creatureThing = tile:getTopCreature()
|
||||
end
|
||||
|
||||
local autoWalkTile = g_map.getTile(autoWalkPos)
|
||||
if autoWalkTile then
|
||||
attackCreature = autoWalkTile:getTopCreature()
|
||||
end
|
||||
|
||||
local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing)
|
||||
local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, attackCreature)
|
||||
if ret then
|
||||
self.allowNextRelease = false
|
||||
end
|
||||
|
@@ -86,7 +86,7 @@ function UIItem:onMouseRelease(mousePosition, mouseButton)
|
||||
g_game.look(item)
|
||||
self.cancelNextRelease = true
|
||||
return true
|
||||
elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, item) then
|
||||
elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, nil) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
|
@@ -151,8 +151,7 @@ function onTradeTypeChange(radioTabs, selected, deselected)
|
||||
ignoreCapacity:setVisible(currentTradeType == BUY)
|
||||
ignoreEquipped:setVisible(currentTradeType == SELL)
|
||||
showAllItems:setVisible(currentTradeType == SELL)
|
||||
sellAllButton:setVisible(false)
|
||||
--sellAllButton:setVisible(currentTradeType == SELL)
|
||||
sellAllButton:setVisible(currentTradeType == SELL)
|
||||
|
||||
refreshTradeItems()
|
||||
refreshPlayerGoods()
|
||||
|
@@ -252,7 +252,6 @@ MainWindow
|
||||
margin-right: 10
|
||||
visible: false
|
||||
@onClick: modules.game_npctrade.sellAll()
|
||||
visible: false
|
||||
|
||||
Button
|
||||
id: tradeButton
|
||||
|
@@ -47,7 +47,7 @@ function openWindow()
|
||||
deathWindow = nil
|
||||
end
|
||||
local cancelFunc = function()
|
||||
modules.game_interface.logout()
|
||||
g_game.safeLogout()
|
||||
cancelButton:getParent():destroy()
|
||||
deathWindow = nil
|
||||
end
|
||||
|
@@ -18,7 +18,7 @@ function isLoaded()
|
||||
end
|
||||
|
||||
function load()
|
||||
local version = g_game.getProtocolVersion()
|
||||
local version = g_game.getClientVersion()
|
||||
|
||||
local datPath, sprPath
|
||||
if filename then
|
||||
|
@@ -88,6 +88,23 @@ function isHiddingOffline()
|
||||
return settings['hideOffline']
|
||||
end
|
||||
|
||||
function getSortedBy()
|
||||
local settings = g_settings.getNode('VipList')
|
||||
if not settings then
|
||||
return 'status'
|
||||
end
|
||||
return settings['sortedBy']
|
||||
end
|
||||
|
||||
function sortBy(state)
|
||||
settings = {}
|
||||
settings['sortedBy'] = state
|
||||
g_settings.mergeNode('VipList', settings)
|
||||
|
||||
refresh()
|
||||
end
|
||||
|
||||
|
||||
function onAddVip(id, name, state)
|
||||
local vipList = vipWindow:getChildById('contentsPanel')
|
||||
|
||||
@@ -118,13 +135,13 @@ function onAddVip(id, name, state)
|
||||
|
||||
for i=1,childrenCount do
|
||||
local child = vipList:getChildByIndex(i)
|
||||
if state == VipState.Online and child.vipState ~= VipState.Online then
|
||||
if state == VipState.Online and child.vipState ~= VipState.Online and getSortedBy() == 'status' then
|
||||
vipList:insertChild(i, label)
|
||||
return
|
||||
end
|
||||
|
||||
if (state ~= VipState.Online and child.vipState ~= VipState.Online)
|
||||
or (state == VipState.Online and child.vipState == VipState.Online) then
|
||||
if ((state ~= VipState.Online and child.vipState ~= VipState.Online)
|
||||
or (state == VipState.Online and child.vipState == VipState.Online)) or getSortedBy() == 'name' then
|
||||
|
||||
local childText = child:getText():lower()
|
||||
local length = math.min(childText:len(), nameLower:len())
|
||||
@@ -167,6 +184,14 @@ function onVipListMousePress(widget, mousePos, mouseButton)
|
||||
else
|
||||
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
||||
end
|
||||
|
||||
if not(getSortedBy() == 'name') then
|
||||
menu:addOption(tr('Sort by name'), function() sortBy('name') end)
|
||||
end
|
||||
|
||||
if not(getSortedBy() == 'status') then
|
||||
menu:addOption(tr('Sort by status'), function() sortBy('status') end)
|
||||
end
|
||||
|
||||
menu:display(mousePos)
|
||||
|
||||
@@ -196,6 +221,15 @@ function onVipListLabelMousePress(widget, mousePos, mouseButton)
|
||||
else
|
||||
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
||||
end
|
||||
|
||||
if not(getSortedBy() == 'name') then
|
||||
menu:addOption(tr('Sort by name'), function() sortBy('name') end)
|
||||
end
|
||||
|
||||
if not(getSortedBy() == 'status') then
|
||||
menu:addOption(tr('Sort by status'), function() sortBy('status') end)
|
||||
end
|
||||
|
||||
menu:display(mousePos)
|
||||
|
||||
return true
|
||||
|
@@ -6,7 +6,7 @@ end
|
||||
|
||||
function g_game.chooseRsa(host)
|
||||
if currentRsa ~= CIPSOFT_RSA and currentRsa ~= OTSERV_RSA then return end
|
||||
if string.ends(host, '.tibia.com') or string.ends(host, '.cipsoft.com') then
|
||||
if host:ends('.tibia.com') or host:ends('.cipsoft.com') then
|
||||
g_game.setRsa(CIPSOFT_RSA)
|
||||
|
||||
if g_app.getOs() == 'windows' then
|
||||
@@ -32,22 +32,29 @@ function g_game.isOfficialTibia()
|
||||
return currentRsa == CIPSOFT_RSA
|
||||
end
|
||||
|
||||
function g_game.getSupportedProtocols()
|
||||
function g_game.getSupportedClients()
|
||||
return {
|
||||
810, 811, 840, 842, 850, 853, 854,
|
||||
860, 861, 862, 870, 910, 940, 944,
|
||||
953, 954, 960, 961, 963, 970, 971,
|
||||
973, 974
|
||||
953, 954, 960, 961, 963, 970, 980,
|
||||
981, 982, 983, 984, 985, 986, 1001,
|
||||
1002, 1010
|
||||
}
|
||||
end
|
||||
|
||||
function g_game.getSupportedClients(protocol)
|
||||
function g_game.getProtocolVersionForClient(client)
|
||||
clients = {
|
||||
[971] = {980},
|
||||
[973] = {981},
|
||||
[974] = {982}
|
||||
[980] = 971,
|
||||
[981] = 973,
|
||||
[982] = 974,
|
||||
[983] = 975,
|
||||
[984] = 976,
|
||||
[985] = 977,
|
||||
[986] = 978,
|
||||
[1001] = 979,
|
||||
[1002] = 980,
|
||||
}
|
||||
return clients[protocol] or {protocol}
|
||||
return clients[client] or client
|
||||
end
|
||||
|
||||
g_game.setRsa(OTSERV_RSA)
|
||||
|
@@ -2,3 +2,4 @@
|
||||
-- you can place any custom user code here
|
||||
|
||||
print 'Startup done :]'
|
||||
|
||||
|
@@ -353,6 +353,8 @@ namespace Otc
|
||||
GameForceFirstAutoWalkStep = 37,
|
||||
GameMinimapRemove = 38,
|
||||
GameDoubleShopSellAmount = 39,
|
||||
GameContainerPagination = 40,
|
||||
GameThingMarks = 41,
|
||||
// 51-100 reserved to be defined in lua
|
||||
LastGameFeature = 101
|
||||
};
|
||||
|
@@ -128,7 +128,7 @@ void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWal
|
||||
dest -= datType->getDisplacement() * scaleFactor;
|
||||
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
|
||||
dest += getDisplacement() * scaleFactor;
|
||||
zPattern = 1;
|
||||
zPattern = std::min(1, getNumPatternZ() - 1);
|
||||
}
|
||||
|
||||
PointF jumpOffset = m_jumpOffset * scaleFactor;
|
||||
|
@@ -99,6 +99,11 @@ void Game::resetGameStates()
|
||||
m_walkEvent = nullptr;
|
||||
}
|
||||
|
||||
if(m_checkConnectionEvent) {
|
||||
m_checkConnectionEvent->cancel();
|
||||
m_checkConnectionEvent = nullptr;
|
||||
}
|
||||
|
||||
m_containers.clear();
|
||||
m_vips.clear();
|
||||
m_gmActions.clear();
|
||||
@@ -183,6 +188,16 @@ void Game::processGameStart()
|
||||
g_game.ping();
|
||||
}, m_pingDelay);
|
||||
}
|
||||
|
||||
m_checkConnectionEvent = g_dispatcher.cycleEvent([this] {
|
||||
if(!g_game.isConnectionOk() && !m_connectionFailWarned) {
|
||||
g_lua.callGlobalField("g_game", "onConnectionFailing", true);
|
||||
m_connectionFailWarned = true;
|
||||
} else if(g_game.isConnectionOk() && m_connectionFailWarned) {
|
||||
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
|
||||
m_connectionFailWarned = false;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
void Game::processGameEnd()
|
||||
@@ -190,6 +205,11 @@ void Game::processGameEnd()
|
||||
m_online = false;
|
||||
g_lua.callGlobalField("g_game", "onGameEnd");
|
||||
|
||||
if(m_connectionFailWarned) {
|
||||
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
|
||||
m_connectionFailWarned = false;
|
||||
}
|
||||
|
||||
// reset game state
|
||||
resetGameStates();
|
||||
|
||||
@@ -554,7 +574,7 @@ bool Game::walk(Otc::Direction direction)
|
||||
if(m_lastWalkDir != direction) {
|
||||
// must add a new walk event
|
||||
float ticks = m_localPlayer->getStepTicksLeft();
|
||||
if(ticks < 0) { ticks = 0; }
|
||||
if(ticks <= 0) { ticks = 1; }
|
||||
|
||||
if(m_walkEvent) {
|
||||
m_walkEvent->cancel();
|
||||
@@ -697,15 +717,16 @@ void Game::autoWalk(std::vector<Otc::Direction> dirs)
|
||||
|
||||
auto it = dirs.begin();
|
||||
Otc::Direction direction = *it;
|
||||
if(m_localPlayer->canWalk(direction)) {
|
||||
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
||||
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
|
||||
m_localPlayer->preWalk(direction);
|
||||
if(!m_localPlayer->canWalk(direction))
|
||||
return;
|
||||
|
||||
if(getFeature(Otc::GameForceFirstAutoWalkStep)) {
|
||||
forceWalk(direction);
|
||||
dirs.erase(it);
|
||||
}
|
||||
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
||||
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
|
||||
m_localPlayer->preWalk(direction);
|
||||
|
||||
if(getFeature(Otc::GameForceFirstAutoWalkStep)) {
|
||||
forceWalk(direction);
|
||||
dirs.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1129,7 +1150,7 @@ void Game::removeVip(int playerId)
|
||||
{
|
||||
if(!canPerformGameAction())
|
||||
return;
|
||||
|
||||
|
||||
auto it = m_vips.find(playerId);
|
||||
if(it == m_vips.end())
|
||||
return;
|
||||
@@ -1379,7 +1400,7 @@ void Game::setProtocolVersion(int version)
|
||||
if(isOnline())
|
||||
stdext::throw_exception("Unable to change protocol version while online");
|
||||
|
||||
if(version != 0 && (version < 810 || version > 974))
|
||||
if(version != 0 && (version < 810 || version > 1010))
|
||||
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
||||
|
||||
m_features.reset();
|
||||
@@ -1443,6 +1464,14 @@ void Game::setProtocolVersion(int version)
|
||||
enableFeature(Otc::GameNewSpeedLaw);
|
||||
}
|
||||
|
||||
if(version >= 976) {
|
||||
enableFeature(Otc::GameContainerPagination);
|
||||
}
|
||||
|
||||
if(version >= 979) {
|
||||
enableFeature(Otc::GameThingMarks);
|
||||
}
|
||||
|
||||
m_protocolVersion = version;
|
||||
|
||||
Proto::buildMessageModesMap(version);
|
||||
@@ -1458,7 +1487,7 @@ void Game::setClientVersion(int version)
|
||||
if(isOnline())
|
||||
stdext::throw_exception("Unable to change client version while online");
|
||||
|
||||
if(version != 0 && (version < 810 || version > 982))
|
||||
if(version != 0 && (version < 810 || version > 1010))
|
||||
stdext::throw_exception(stdext::format("Client version %d not supported", version));
|
||||
|
||||
m_clientVersion = version;
|
||||
|
@@ -231,7 +231,7 @@ public:
|
||||
void openRuleViolation(const std::string& reporter);
|
||||
void closeRuleViolation(const std::string& reporter);
|
||||
void cancelRuleViolation();
|
||||
|
||||
|
||||
// reports
|
||||
void reportBug(const std::string& comment);
|
||||
void reportRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
|
||||
@@ -281,6 +281,7 @@ public:
|
||||
bool isDead() { return m_dead; }
|
||||
bool isAttacking() { return !!m_attackingCreature; }
|
||||
bool isFollowing() { return !!m_followingCreature; }
|
||||
bool isConnectionOk() { return m_protocolGame && m_protocolGame->getElapsedTicksSinceLastRead() < 5000; }
|
||||
|
||||
int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; }
|
||||
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
||||
@@ -340,6 +341,8 @@ private:
|
||||
std::bitset<Otc::LastGameFeature> m_features;
|
||||
ScheduledEventPtr m_pingEvent;
|
||||
ScheduledEventPtr m_walkEvent;
|
||||
ScheduledEventPtr m_checkConnectionEvent;
|
||||
bool m_connectionFailWarned;
|
||||
int m_protocolVersion;
|
||||
int m_clientVersion;
|
||||
std::string m_clientSignature;
|
||||
|
@@ -26,7 +26,6 @@
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <framework/graphics/painter.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/ogl/textureogl.h>
|
||||
|
||||
enum {
|
||||
MAX_LIGHT_INTENSITY = 8,
|
||||
@@ -62,7 +61,7 @@ TexturePtr LightView::generateLightBubble(float centerFactor)
|
||||
}
|
||||
}
|
||||
|
||||
TexturePtr tex = TexturePtr(new TextureOGL(lightImage, true));
|
||||
TexturePtr tex = TexturePtr(new Texture(lightImage, true));
|
||||
tex->setSmooth(true);
|
||||
return tex;
|
||||
}
|
||||
|
@@ -72,7 +72,7 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
|
||||
return false;
|
||||
|
||||
// last walk is not done yet
|
||||
if(m_walkTimer.ticksElapsed() < getStepDuration())
|
||||
if((m_walkTimer.ticksElapsed() < getStepDuration()) && !isAutoWalking())
|
||||
return false;
|
||||
|
||||
// prewalk has a timeout, because for some reason that I don't know yet the server sometimes doesn't answer the prewalk
|
||||
@@ -83,7 +83,7 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
|
||||
return false;
|
||||
|
||||
// cannot walk while already walking
|
||||
if(m_walking && !prewalkTimeouted)
|
||||
if((m_walking && !isAutoWalking()) && (!prewalkTimeouted || m_secondPreWalk))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -95,6 +95,7 @@ void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
|
||||
if(m_preWalking) {
|
||||
// switch to normal walking
|
||||
m_preWalking = false;
|
||||
m_secondPreWalk = false;
|
||||
m_lastPrewalkDone = true;
|
||||
// if is to the last prewalk destination, updates the walk preserving the animation
|
||||
if(newPos == m_lastPrewalkDestination) {
|
||||
@@ -118,7 +119,8 @@ void LocalPlayer::preWalk(Otc::Direction direction)
|
||||
Position newPos = m_position.translatedToDirection(direction);
|
||||
|
||||
// avoid reanimating prewalks
|
||||
if(m_preWalking && m_lastPrewalkDestination == newPos) {
|
||||
if(m_preWalking) {
|
||||
m_secondPreWalk = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -277,6 +279,7 @@ void LocalPlayer::terminateWalk()
|
||||
{
|
||||
Creature::terminateWalk();
|
||||
m_preWalking = false;
|
||||
m_secondPreWalk = false;
|
||||
m_idleTimer.restart();
|
||||
|
||||
auto self = asLocalPlayer();
|
||||
|
@@ -126,6 +126,7 @@ private:
|
||||
ticks_t m_walkLockExpiration;
|
||||
stdext::boolean<false> m_preWalking;
|
||||
stdext::boolean<true> m_lastPrewalkDone;
|
||||
stdext::boolean<false> m_secondPreWalk;
|
||||
stdext::boolean<false> m_serverWalking;
|
||||
stdext::boolean<false> m_knownCompletePath;
|
||||
|
||||
|
@@ -230,6 +230,7 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isConnectionOk", &Game::isConnectionOk, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);
|
||||
|
@@ -608,21 +608,21 @@ int MapView::calcFirstVisibleFloor()
|
||||
Position pos = cameraPosition.translated(ix, iy);
|
||||
|
||||
// process tiles that we can look through, e.g. windows, doors
|
||||
if((ix == 0 && iy == 0) || (/*(std::abs(ix) != std::abs(iy)) && */g_map.isLookPossible(pos))) {
|
||||
if((ix == 0 && iy == 0) || ((std::abs(ix) != std::abs(iy)) && g_map.isLookPossible(pos))) {
|
||||
Position upperPos = pos;
|
||||
Position coveredPos = pos;
|
||||
|
||||
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
|
||||
// check tiles physically above
|
||||
TilePtr tile = g_map.getTile(upperPos);
|
||||
if(tile && tile->limitsFloorsView()) {
|
||||
if(tile && tile->limitsFloorsView(!g_map.isLookPossible(pos))) {
|
||||
firstFloor = upperPos.z + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// check tiles geometrically above
|
||||
tile = g_map.getTile(coveredPos);
|
||||
if(tile && tile->limitsFloorsView()) {
|
||||
if(tile && tile->limitsFloorsView(g_map.isLookPossible(pos))) {
|
||||
firstFloor = coveredPos.z + 1;
|
||||
break;
|
||||
}
|
||||
|
@@ -29,7 +29,6 @@
|
||||
#include <framework/graphics/painter.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <framework/graphics/ogl/textureogl.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <zlib.h>
|
||||
@@ -66,7 +65,7 @@ void MinimapBlock::update()
|
||||
|
||||
if(shouldDraw) {
|
||||
if(!m_texture) {
|
||||
m_texture = TexturePtr(new TextureOGL(image, true));
|
||||
m_texture = TexturePtr(new Texture(image, true));
|
||||
} else {
|
||||
m_texture->uploadPixels(image, true);
|
||||
}
|
||||
|
@@ -603,6 +603,14 @@ void ProtocolGame::parseOpenContainer(const InputMessagePtr& msg)
|
||||
std::string name = msg->getString();
|
||||
int capacity = msg->getU8();
|
||||
bool hasParent = (msg->getU8() != 0);
|
||||
|
||||
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||
msg->getU8(); // drag and drop
|
||||
msg->getU8(); // pagination
|
||||
msg->getU16(); // container size
|
||||
msg->getU16(); // first index
|
||||
}
|
||||
|
||||
int itemCount = msg->getU8();
|
||||
|
||||
std::vector<ItemPtr> items(itemCount);
|
||||
@@ -622,13 +630,21 @@ void ProtocolGame::parseContainerAddItem(const InputMessagePtr& msg)
|
||||
{
|
||||
int containerId = msg->getU8();
|
||||
ItemPtr item = getItem(msg);
|
||||
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||
msg->getU16(); // slot
|
||||
}
|
||||
g_game.processContainerAddItem(containerId, item);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
||||
{
|
||||
int containerId = msg->getU8();
|
||||
int slot = msg->getU8();
|
||||
int slot;
|
||||
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||
slot = msg->getU16();
|
||||
} else {
|
||||
slot = msg->getU8();
|
||||
}
|
||||
ItemPtr item = getItem(msg);
|
||||
g_game.processContainerUpdateItem(containerId, slot, item);
|
||||
}
|
||||
@@ -636,7 +652,13 @@ void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
||||
void ProtocolGame::parseContainerRemoveItem(const InputMessagePtr& msg)
|
||||
{
|
||||
int containerId = msg->getU8();
|
||||
int slot = msg->getU8();
|
||||
int slot;
|
||||
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||
slot = msg->getU16();
|
||||
getItem(msg);
|
||||
} else {
|
||||
slot = msg->getU8();
|
||||
}
|
||||
g_game.processContainerRemoveItem(containerId, slot);
|
||||
}
|
||||
|
||||
@@ -1808,6 +1830,12 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
||||
if(g_game.getFeature(Otc::GameCreatureEmblems) && !known)
|
||||
emblem = msg->getU8();
|
||||
|
||||
if(g_game.getFeature(Otc::GameThingMarks)) {
|
||||
msg->getU8(); // creature type for summons
|
||||
msg->getU8(); // mark
|
||||
msg->getU16(); // helpers
|
||||
}
|
||||
|
||||
if(g_game.getProtocolVersion() >= 854)
|
||||
unpass = msg->getU8();
|
||||
|
||||
@@ -1860,6 +1888,10 @@ ItemPtr ProtocolGame::getItem(const InputMessagePtr& msg, int id)
|
||||
if(item->getId() == 0)
|
||||
stdext::throw_exception(stdext::format("unable to create item with invalid id %d", id));
|
||||
|
||||
if(g_game.getFeature(Otc::GameThingMarks)) {
|
||||
msg->getU8(); // mark
|
||||
}
|
||||
|
||||
if(item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable())
|
||||
item->setCountOrSubType(msg->getU8());
|
||||
|
||||
|
@@ -48,11 +48,9 @@ bool SpriteManager::loadSpr(std::string file)
|
||||
file = g_resources.guessFilePath(file, "spr");
|
||||
|
||||
m_spritesFile = g_resources.openFile(file);
|
||||
|
||||
// cache file buffer to avoid lags from hard drive
|
||||
#ifndef MOBILE
|
||||
m_spritesFile->cache();
|
||||
#endif
|
||||
|
||||
m_signature = m_spritesFile->getU32();
|
||||
m_spritesCount = g_game.getFeature(Otc::GameSpritesU32) ? m_spritesFile->getU32() : m_spritesFile->getU16();
|
||||
m_spritesOffset = m_spritesFile->tell();
|
||||
|
@@ -28,7 +28,6 @@
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/ogl/textureogl.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/otml/otml.h>
|
||||
@@ -68,6 +67,17 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
||||
attr -= 1;
|
||||
}
|
||||
|
||||
if(g_game.getProtocolVersion() >= 1010) {
|
||||
/* In 10.10 all attributes from 16 and up were
|
||||
* incremented by 1 to make space for 16 as
|
||||
* "No Movement Animation" flag.
|
||||
*/
|
||||
if(attr == 16)
|
||||
attr = ThingAttrNoMoveAnimation;
|
||||
else if(attr > 16)
|
||||
attr -= 1;
|
||||
}
|
||||
|
||||
switch(attr) {
|
||||
case ThingAttrDisplacement: {
|
||||
m_displacement.x = fin->getU16();
|
||||
@@ -127,8 +137,8 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
||||
|
||||
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
|
||||
|
||||
if(totalSprites == 0)
|
||||
stdext::throw_exception("a thing type has no sprites");
|
||||
// if(totalSprites == 0)
|
||||
// stdext::throw_exception("a thing type has no sprites");
|
||||
if(totalSprites > 4096)
|
||||
stdext::throw_exception("a thing type has more than 4096 sprites");
|
||||
|
||||
@@ -284,7 +294,7 @@ const TexturePtr& ThingType::getTexture(int animationPhase)
|
||||
}
|
||||
}
|
||||
}
|
||||
animationPhaseTexture = TexturePtr(new TextureOGL(fullImage));
|
||||
animationPhaseTexture = TexturePtr(new Texture(fullImage, true));
|
||||
animationPhaseTexture->setSmooth(true);
|
||||
}
|
||||
return animationPhaseTexture;
|
||||
|
@@ -81,6 +81,7 @@ enum ThingAttr : uint8 {
|
||||
ThingAttrOpacity = 100,
|
||||
ThingAttrNotPreWalkable = 101,
|
||||
|
||||
ThingAttrNoMoveAnimation = 253, // real value is 16, but we need to do this for backwards compatibility
|
||||
ThingAttrChargeable = 254, // deprecated
|
||||
ThingLastAttr = 255
|
||||
};
|
||||
|
@@ -457,7 +457,7 @@ ThingPtr Tile::getTopMultiUseThing()
|
||||
if(thing->isForceUse())
|
||||
return thing;
|
||||
}
|
||||
|
||||
|
||||
for(uint i = 0; i < m_things.size(); ++i) {
|
||||
ThingPtr thing = m_things[i];
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop()) {
|
||||
@@ -590,15 +590,24 @@ bool Tile::hasCreature()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tile::limitsFloorsView()
|
||||
bool Tile::limitsFloorsView(bool isFreeView)
|
||||
{
|
||||
// ground and walls limits the view
|
||||
ThingPtr firstThing = getThing(0);
|
||||
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || firstThing->isOnBottom()))
|
||||
return true;
|
||||
|
||||
if(isFreeView){
|
||||
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || firstThing->isOnBottom()))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || (firstThing->isOnBottom() && firstThing->blockProjectile())))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Tile::canErase()
|
||||
{
|
||||
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty() && m_flags == 0 && m_minimapColor == 0;
|
||||
|
@@ -48,7 +48,7 @@ enum tileflags_t
|
||||
TILESTATE_TRASHHOLDER = 1 << 20,
|
||||
TILESTATE_BED = 1 << 21,
|
||||
TILESTATE_DEPOT = 1 << 22,
|
||||
TILESTATE_TRANSLUECENT_LIGHT = 1 << 23
|
||||
TILESTATE_TRANSLUECENT_LIGHT = 1 << 23
|
||||
};
|
||||
|
||||
class Tile : public LuaObject
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
bool mustHookSouth();
|
||||
bool mustHookEast();
|
||||
bool hasCreature();
|
||||
bool limitsFloorsView();
|
||||
bool limitsFloorsView(bool isFreeView = false);
|
||||
bool canErase();
|
||||
bool hasElevation(int elevation = 1);
|
||||
void overwriteMinimapColor(uint8 color) { m_minimapColor = color; }
|
||||
|
@@ -123,20 +123,15 @@ set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/otml/otmlparser.h
|
||||
|
||||
# crash handler
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/crashhandler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/unixcrashhandler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32crashhandler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32platform.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/unixplatform.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/platform.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/platform.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32platform.cpp
|
||||
)
|
||||
else()
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/unixplatform.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/luafunctions.cpp
|
||||
PROPERTIES LANGUAGE CXX COMPILE_FLAGS "-g0 -Os")
|
||||
|
||||
@@ -263,15 +258,6 @@ if(CRASH_HANDLER)
|
||||
message(STATUS "Crash handler: ON")
|
||||
if(WIN32)
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} imagehlp)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/crashhandler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32crashhandler.cpp
|
||||
)
|
||||
else()
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/crashhandler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/unixcrashhandler.cpp
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Crash handler: OFF")
|
||||
@@ -304,24 +290,18 @@ endif()
|
||||
|
||||
if(FRAMEWORK_GRAPHICS)
|
||||
set(OPENGLES "OFF" CACHE "Use OpenGL ES 1.0 or 2.0 (for mobiles devices)" STRING)
|
||||
if(OPENGLES)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextegl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextegl.h
|
||||
)
|
||||
if(OPENGLES STREQUAL "2.0")
|
||||
find_package(OpenGLES2 REQUIRED)
|
||||
find_package(EGL REQUIRED)
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=2)
|
||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES2_INCLUDE_DIR})
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES2_LIBRARY})
|
||||
elseif(OPENGLES STREQUAL "1.0")
|
||||
find_package(OpenGLES1 REQUIRED)
|
||||
find_package(EGL REQUIRED)
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=1)
|
||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES1_INCLUDE_DIR})
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES1_LIBRARY})
|
||||
endif()
|
||||
if(OPENGLES STREQUAL "2.0")
|
||||
find_package(OpenGLES2 REQUIRED)
|
||||
find_package(EGL REQUIRED)
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=2)
|
||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES2_INCLUDE_DIR})
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES2_LIBRARY})
|
||||
ELSEif(OPENGLES STREQUAL "1.0")
|
||||
find_package(OpenGLES1 REQUIRED)
|
||||
find_package(EGL REQUIRED)
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=1)
|
||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES1_INCLUDE_DIR})
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES1_LIBRARY})
|
||||
else()
|
||||
## TODO: CMake Documentation says that this is not the right
|
||||
# Thing for Mac OS X, but it works for now.
|
||||
@@ -356,8 +336,6 @@ if(FRAMEWORK_GRAPHICS)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/painterdx9.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/painterdx9.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/graphicscontextdx9.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/graphicscontextdx9.h
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -365,44 +343,6 @@ if(FRAMEWORK_GRAPHICS)
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} X11)
|
||||
endif()
|
||||
|
||||
option(SDL "Use SDL 2.0 support" OFF)
|
||||
if(SDL)
|
||||
find_package(SDL2 REQUIRED)
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DSDL)
|
||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${SDL2_INCLUDE_DIR})
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${SDL2_LIBRARY})
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/sdl/paintersdl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/sdl/paintersdl.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/sdlwindow.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/sdlwindow.h
|
||||
)
|
||||
else()
|
||||
if(WIN32)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32window.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32window.h
|
||||
)
|
||||
if(NOT OPENGLES)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextwgl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextwgl.h
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/x11window.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/x11window.h
|
||||
)
|
||||
if(NOT OPENGLES)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextglx.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextglx.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.h
|
||||
@@ -422,8 +362,6 @@ if(FRAMEWORK_GRAPHICS)
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/glutil.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphicscontext.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphicscontext.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/hardwarebuffer.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/hardwarebuffer.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp
|
||||
@@ -459,8 +397,6 @@ if(FRAMEWORK_GRAPHICS)
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/textureogl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/textureogl.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/vertexarray.h
|
||||
@@ -499,6 +435,10 @@ if(FRAMEWORK_GRAPHICS)
|
||||
# platform window
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/platformwindow.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/platformwindow.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32window.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32window.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/x11window.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/x11window.h
|
||||
|
||||
# window input
|
||||
${CMAKE_CURRENT_LIST_DIR}/input/mouse.cpp
|
||||
|
@@ -1,16 +0,0 @@
|
||||
# Try to find the SDL2 library
|
||||
# SDL2_FOUND - system has SDL2
|
||||
# SDL2_INCLUDE_DIR - the SDL2 include directory
|
||||
# SDL2_LIBRARY - the SDL2 library
|
||||
|
||||
FIND_PATH(SDL2_INCLUDE_DIR PATH_SUFFIXES SDL2 SDL NAMES SDL.h)
|
||||
SET(_SDL2_STATIC_LIBS libSDL2.a libSDL.a)
|
||||
SET(_SDL2_SHARED_LIBS libSDL2.dll.a SDL2 SDL libSDL.dll.a SDL)
|
||||
IF(USE_STATIC_LIBS)
|
||||
FIND_LIBRARY(SDL2_LIBRARY NAMES ${_SDL2_STATIC_LIBS} ${_SDL2_SHARED_LIBS})
|
||||
ELSE()
|
||||
FIND_LIBRARY(SDL2_LIBRARY NAMES ${_SDL2_SHARED_LIBS} ${_SDL2_STATIC_LIBS})
|
||||
ENDIF()
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 DEFAULT_MSG SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
||||
MARK_AS_ADVANCED(SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
@@ -33,7 +33,6 @@
|
||||
#include <framework/platform/platform.h>
|
||||
|
||||
#include <locale>
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
#ifdef FW_NET
|
||||
#include <framework/net/connection.h>
|
||||
@@ -164,14 +163,10 @@ void Application::close()
|
||||
|
||||
std::string Application::getOs()
|
||||
{
|
||||
#if defined(ANDROID)
|
||||
return "android";
|
||||
#elif defined(IOS)
|
||||
return "ios";
|
||||
#elif defined(WIN32)
|
||||
#if defined(WIN32)
|
||||
return "windows";
|
||||
#elif defined(__APPLE__)
|
||||
return "macos";
|
||||
return "mac";
|
||||
#elif __linux
|
||||
return "linux";
|
||||
#else
|
||||
|
@@ -24,14 +24,12 @@
|
||||
#include "graphicalapplication.h"
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/input/mouse.h>
|
||||
#include <framework/platform/platformwindow.h>
|
||||
#include <framework/ui/uimanager.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/particlemanager.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include <framework/graphics/painter.h>
|
||||
#include <framework/graphics/ogl/textureogl.h>
|
||||
|
||||
#ifdef FW_SOUND
|
||||
#include <framework/sound/soundmanager.h>
|
||||
@@ -234,7 +232,7 @@ void GraphicalApplication::resize(const Size& size)
|
||||
m_onInputEvent = false;
|
||||
|
||||
if(g_graphics.canCacheBackbuffer()) {
|
||||
m_foreground = TexturePtr(new TextureOGL(size));
|
||||
m_foreground = TexturePtr(new Texture(size));
|
||||
m_foreground->setUpsideDown(true);
|
||||
}
|
||||
m_mustRepaint = true;
|
||||
|
@@ -31,7 +31,7 @@
|
||||
class GraphicalApplication : public Application
|
||||
{
|
||||
enum {
|
||||
POLL_CYCLE_DELAY = 1000
|
||||
POLL_CYCLE_DELAY = 10
|
||||
};
|
||||
|
||||
public:
|
||||
|
@@ -25,30 +25,24 @@
|
||||
|
||||
//#include <boost/regex.hpp>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include "application.h"
|
||||
|
||||
#ifdef FW_GRAPHICS
|
||||
#include <framework/platform/platformwindow.h>
|
||||
#include <framework/platform/platform.h>
|
||||
#include <framework/luaengine/luainterface.h>
|
||||
#endif
|
||||
|
||||
#ifdef MOBILE
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
Logger g_logger;
|
||||
|
||||
void Logger::log(Fw::LogLevel level, const std::string& message)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
/*
|
||||
>>>>>>> Progress in SDL platform
|
||||
#ifdef NDEBUG
|
||||
if(level == Fw::LogDebug)
|
||||
return;
|
||||
#endif
|
||||
*/
|
||||
|
||||
static bool ignoreLogs = false;
|
||||
if(ignoreLogs)
|
||||
return;
|
||||
@@ -73,11 +67,7 @@ void Logger::log(Fw::LogLevel level, const std::string& message)
|
||||
#endif
|
||||
*/
|
||||
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_INFO, g_app.getCompactName().c_str(), outmsg.c_str());
|
||||
#else
|
||||
std::cout << outmsg << std::endl;
|
||||
#endif
|
||||
|
||||
if(m_outFile.good()) {
|
||||
m_outFile << outmsg << std::endl;
|
||||
@@ -115,16 +105,16 @@ void Logger::logFunc(Fw::LogLevel level, const std::string& message, std::string
|
||||
prettyFunction = prettyFunction.substr(prettyFunction.find_last_of(' ') + 1);
|
||||
|
||||
|
||||
std::string out = message;
|
||||
std::stringstream ss;
|
||||
ss << message;
|
||||
|
||||
if(!prettyFunction.empty()) {
|
||||
if(g_lua.isInCppCallback())
|
||||
out = g_lua.traceback(out, 1);
|
||||
else
|
||||
out += "\nat:\t[C++]: " + prettyFunction;
|
||||
ss << g_lua.traceback("", 1);
|
||||
ss << g_platform.traceback(prettyFunction, 1, 8);
|
||||
}
|
||||
|
||||
log(level, out);
|
||||
log(level, ss.str());
|
||||
}
|
||||
|
||||
void Logger::fireOldMessages()
|
||||
|
@@ -29,10 +29,6 @@
|
||||
|
||||
#include <physfs.h>
|
||||
|
||||
#ifdef MOBILE
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
ResourceManager g_resources;
|
||||
|
||||
void ResourceManager::init(const char *argv0)
|
||||
@@ -49,15 +45,10 @@ void ResourceManager::terminate()
|
||||
bool ResourceManager::discoverWorkDir(const std::string& existentFile)
|
||||
{
|
||||
// search for modules directory
|
||||
#ifdef ANDROID
|
||||
std::string possiblePaths[] = { std::string("/sdcard/") + g_app.getCompactName() + "/" };
|
||||
#else
|
||||
std::string possiblePaths[] = { "./",
|
||||
g_platform.getCurrentDir(),
|
||||
std::string possiblePaths[] = { g_platform.getCurrentDir(),
|
||||
g_resources.getBaseDir(),
|
||||
g_resources.getBaseDir() + "../",
|
||||
g_resources.getBaseDir() + "../share/" + g_app.getCompactName() + "/" };
|
||||
#endif
|
||||
|
||||
bool found = false;
|
||||
for(const std::string& dir : possiblePaths) {
|
||||
@@ -318,11 +309,7 @@ std::string ResourceManager::getBaseDir()
|
||||
|
||||
std::string ResourceManager::getUserDir()
|
||||
{
|
||||
#ifdef ANDROID
|
||||
return std::string("/sdcard/");
|
||||
#else
|
||||
return PHYSFS_getUserDir();
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string ResourceManager::guessFilePath(const std::string& filename, const std::string& type)
|
||||
|
@@ -24,15 +24,14 @@
|
||||
#include "graphics.h"
|
||||
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include "ogl/textureogl.h"
|
||||
|
||||
AnimatedTexture::AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps)
|
||||
AnimatedTexture::AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps, bool compress)
|
||||
{
|
||||
if(!setupSize(size, buildMipmaps))
|
||||
return;
|
||||
|
||||
for(uint i=0;i<frames.size();++i) {
|
||||
m_frames.push_back(new TextureOGL(frames[i], buildMipmaps));
|
||||
m_frames.push_back(new Texture(frames[i], buildMipmaps, compress));
|
||||
}
|
||||
|
||||
m_framesDelay = framesDelay;
|
||||
|
@@ -29,7 +29,7 @@
|
||||
class AnimatedTexture : public Texture
|
||||
{
|
||||
public:
|
||||
AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps = false);
|
||||
AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps = false, bool compress = false);
|
||||
virtual ~AnimatedTexture();
|
||||
|
||||
virtual bool buildHardwareMipmaps();
|
||||
|
@@ -33,15 +33,15 @@
|
||||
#include <fstream>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
||||
#define lswap16(data) _byteswap_ushort(data)
|
||||
#define lswap32(data) _byteswap_ulong(data)
|
||||
#define swap16(data) _byteswap_ushort(data)
|
||||
#define swap32(data) _byteswap_ulong(data)
|
||||
#elif __linux__
|
||||
#include <byteswap.h>
|
||||
#define lswap16(data) bswap_16(data)
|
||||
#define lswap32(data) bswap_32(data)
|
||||
#define swap16(data) bswap_16(data)
|
||||
#define swap32(data) bswap_32(data)
|
||||
#else
|
||||
#define lswap16(data) (((data >> 8) & 255) | ((data & 255) << 8))
|
||||
#define lswap32(data) ((swap16(data) << 16) | swap16(data >> 16))
|
||||
#define swap16(data) (((data >> 8) & 255) | ((data & 255) << 8))
|
||||
#define swap32(data) ((swap16(data) << 16) | swap16(data >> 16))
|
||||
#endif
|
||||
|
||||
#define PNG_ZBUF_SIZE 32768
|
||||
@@ -865,7 +865,7 @@ int load_apng(std::stringstream& file, struct apng_data *apng)
|
||||
void write_chunk(std::ostream& f, const char* name, unsigned char* data, unsigned int length)
|
||||
{
|
||||
unsigned int crc = crc32(0, Z_NULL, 0);
|
||||
unsigned int len = lswap32(length);
|
||||
unsigned int len = swap32(length);
|
||||
|
||||
f.write((char*)&len, 4);
|
||||
f.write(name, 4);
|
||||
@@ -876,7 +876,7 @@ void write_chunk(std::ostream& f, const char* name, unsigned char* data, unsigne
|
||||
crc = crc32(crc, data, length);
|
||||
}
|
||||
|
||||
crc = lswap32(crc);
|
||||
crc = swap32(crc);
|
||||
f.write((char*)&crc, 4);
|
||||
}
|
||||
|
||||
@@ -937,7 +937,7 @@ void save_png(std::stringstream& f, unsigned int width, unsigned int height, int
|
||||
unsigned char mCompression;
|
||||
unsigned char mFilterMethod;
|
||||
unsigned char mInterlaceMethod;
|
||||
} ihdr = { lswap32(width), lswap32(height), 8, coltype, 0, 0, 0 };
|
||||
} ihdr = { swap32(width), swap32(height), 8, coltype, 0, 0, 0 };
|
||||
|
||||
z_stream zstream1;
|
||||
z_stream zstream2;
|
||||
|
@@ -34,7 +34,6 @@ class BitmapFont;
|
||||
class CachedText;
|
||||
class FrameBuffer;
|
||||
class FrameBufferManager;
|
||||
class GraphicsContext;
|
||||
class Shader;
|
||||
class ShaderProgram;
|
||||
class PainterShaderProgram;
|
||||
@@ -52,7 +51,6 @@ typedef stdext::shared_object_ptr<AnimatedTexture> AnimatedTexturePtr;
|
||||
typedef stdext::shared_object_ptr<BitmapFont> BitmapFontPtr;
|
||||
typedef stdext::shared_object_ptr<CachedText> CachedTextPtr;
|
||||
typedef stdext::shared_object_ptr<FrameBuffer> FrameBufferPtr;
|
||||
typedef stdext::shared_object_ptr<GraphicsContext> GraphicsContextPtr;
|
||||
typedef stdext::shared_object_ptr<Shader> ShaderPtr;
|
||||
typedef stdext::shared_object_ptr<ShaderProgram> ShaderProgramPtr;
|
||||
typedef stdext::shared_object_ptr<PainterShaderProgram> PainterShaderProgramPtr;
|
||||
|
@@ -26,7 +26,6 @@
|
||||
|
||||
#include <framework/platform/platformwindow.h>
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/graphics/ogl/textureogl.h>
|
||||
|
||||
uint FrameBuffer::boundFbo = 0;
|
||||
|
||||
@@ -62,7 +61,7 @@ void FrameBuffer::resize(const Size& size)
|
||||
if(m_texture && m_texture->getSize() == size)
|
||||
return;
|
||||
|
||||
m_texture = TexturePtr(new TextureOGL(size));
|
||||
m_texture = TexturePtr(new Texture(size));
|
||||
m_texture->setSmooth(m_smooth);
|
||||
m_texture->setUpsideDown(true);
|
||||
|
||||
@@ -76,7 +75,7 @@ void FrameBuffer::resize(const Size& size)
|
||||
internalRelease();
|
||||
} else {
|
||||
if(m_backuping) {
|
||||
m_screenBackup = TexturePtr(new TextureOGL(size));
|
||||
m_screenBackup = TexturePtr(new Texture(size));
|
||||
m_screenBackup->setUpsideDown(true);
|
||||
}
|
||||
}
|
||||
|
@@ -44,7 +44,6 @@
|
||||
typedef char GLchar;
|
||||
|
||||
// define OpenGL ES 2.0 API just to make compile, it wont actually be used
|
||||
inline void glBlendEquation (GLenum mode) { }
|
||||
inline void glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { }
|
||||
inline void glBindFramebuffer (GLenum target, GLuint framebuffer) { }
|
||||
inline void glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) { }
|
||||
|
@@ -184,16 +184,14 @@ bool Graphics::isPainterEngineAvailable(Graphics::PainterEngine painterEngine)
|
||||
|
||||
bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
||||
{
|
||||
// TODO: remove this
|
||||
#ifdef DIRECTX
|
||||
painterEngine = Painter_DirectX9;
|
||||
#endif
|
||||
|
||||
Painter *painter = nullptr;
|
||||
Painter *fallbackPainter = nullptr;
|
||||
PainterEngine fallbackPainterEngine = Painter_Any;
|
||||
|
||||
#ifdef PAINTER_DX9
|
||||
// use this to force directx if its enabled (avoid changes in options module, etc, will be removed)
|
||||
painterEngine = Painter_DirectX9;
|
||||
|
||||
// always prefer DirectX9 on Windows
|
||||
if(g_painterDX9) {
|
||||
if(!painter && (painterEngine == Painter_DirectX9 || painterEngine == Painter_Any)) {
|
||||
@@ -240,7 +238,6 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
||||
if(g_painter)
|
||||
g_painter->unbind();
|
||||
painter->bind();
|
||||
g_window.setGraphicsContext(painter->getGraphicsContext());
|
||||
g_painter = painter;
|
||||
}
|
||||
|
||||
@@ -256,11 +253,6 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
||||
void Graphics::resize(const Size& size)
|
||||
{
|
||||
m_viewportSize = size;
|
||||
#ifdef PAINTER_DX9
|
||||
if(g_painterDX9)
|
||||
g_painterDX9->setResolution(size);
|
||||
#endif
|
||||
|
||||
#ifdef PAINTER_OGL1
|
||||
if(g_painterOGL1)
|
||||
g_painterOGL1->setResolution(size);
|
||||
|
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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 "graphicscontext.h"
|
||||
|
||||
GraphicsContext::GraphicsContext(const std::string& name) :
|
||||
m_name(name)
|
||||
{
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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 GRAPHICSCONTEXT_H
|
||||
#define GRAPHICSCONTEXT_H
|
||||
|
||||
#include "declarations.h"
|
||||
|
||||
class GraphicsContext : public stdext::shared_object
|
||||
{
|
||||
public:
|
||||
GraphicsContext(const std::string& name);
|
||||
virtual ~GraphicsContext() {}
|
||||
|
||||
std::string getName() { return m_name; }
|
||||
|
||||
virtual void create() {}
|
||||
virtual void destroy() {}
|
||||
virtual void restore() {}
|
||||
|
||||
virtual void swapBuffers() {}
|
||||
|
||||
virtual void setVerticalSync(bool enable) {}
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* 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 "graphicscontextegl.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <framework/platform/win32window.h>
|
||||
#else
|
||||
#include <framework/platform/x11window.h>
|
||||
#endif
|
||||
|
||||
GraphicsContextEGL::GraphicsContextEGL() :
|
||||
GraphicsContext("EGL")
|
||||
{
|
||||
m_eglConfig = 0;
|
||||
m_eglContext = 0;
|
||||
m_eglDisplay = 0;
|
||||
m_eglSurface = 0;
|
||||
}
|
||||
|
||||
void GraphicsContextEGL::create()
|
||||
{
|
||||
#ifdef WIN32
|
||||
HDC display = g_win32Window.getDisplay();
|
||||
#else
|
||||
Display *display = g_x11Window.getDisplay();
|
||||
#endif
|
||||
|
||||
m_eglDisplay = eglGetDisplay(display);
|
||||
if(m_eglDisplay == EGL_NO_DISPLAY)
|
||||
g_logger.fatal("EGL not supported");
|
||||
|
||||
if(!eglInitialize(m_eglDisplay, NULL, NULL))
|
||||
g_logger.fatal("Unable to initialize EGL");
|
||||
|
||||
static int configList[] = {
|
||||
#if OPENGL_ES==2
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
#else
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
||||
#endif
|
||||
EGL_RED_SIZE, 4,
|
||||
EGL_GREEN_SIZE, 4,
|
||||
EGL_BLUE_SIZE, 4,
|
||||
EGL_ALPHA_SIZE, 4,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLint numConfig;
|
||||
|
||||
if(!eglChooseConfig(m_eglDisplay, configList, &m_eglConfig, 1, &numConfig))
|
||||
g_logger.fatal("Failed to choose EGL config");
|
||||
|
||||
if(numConfig != 1)
|
||||
g_logger.warning("Didn't got the exact EGL config");
|
||||
|
||||
#ifndef WIN32
|
||||
EGLint vid;
|
||||
if(!eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_NATIVE_VISUAL_ID, &vid))
|
||||
g_logger.fatal("Unable to get visual EGL visual id");
|
||||
|
||||
XVisualInfo visTemplate;
|
||||
int numVisuals;
|
||||
memset(&visTemplate, 0, sizeof(visTemplate));
|
||||
visTemplate.visualid = vid;
|
||||
g_x11Window.setVisual(XGetVisualInfo(display, VisualIDMask, &visTemplate, &numVisuals));
|
||||
if(!g_x11Window.getVisual())
|
||||
g_logger.fatal("Couldn't choose RGBA, double buffered visual");
|
||||
|
||||
g_x11Window.setRootWindow(DefaultRootWindow(display));
|
||||
#endif
|
||||
|
||||
EGLint contextAtrrList[] = {
|
||||
#if OPENGL_ES==2
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
#else
|
||||
EGL_CONTEXT_CLIENT_VERSION, 1,
|
||||
#endif
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
HWND window = g_win32Window.getWindow();
|
||||
m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, window, NULL);
|
||||
if(m_eglSurface == EGL_NO_SURFACE)
|
||||
g_logger.fatal(stdext::format("Unable to create EGL surface: %s", eglGetError()));
|
||||
#endif
|
||||
|
||||
m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAtrrList);
|
||||
if(m_eglContext == EGL_NO_CONTEXT )
|
||||
g_logger.fatal(stdext::format("Unable to create EGL context: %s", eglGetError()));
|
||||
}
|
||||
|
||||
void GraphicsContextEGL::destroy()
|
||||
{
|
||||
if(m_eglDisplay) {
|
||||
if(m_eglContext) {
|
||||
eglDestroyContext(m_eglDisplay, m_eglContext);
|
||||
m_eglContext = 0;
|
||||
}
|
||||
if(m_eglSurface) {
|
||||
eglDestroySurface(m_eglDisplay, m_eglSurface);
|
||||
m_eglSurface = 0;
|
||||
}
|
||||
eglTerminate(m_eglDisplay);
|
||||
m_eglDisplay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsContextEGL::restore()
|
||||
{
|
||||
#ifndef WIN32
|
||||
Window window = g_x11Window.getWindow();
|
||||
m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, window, NULL);
|
||||
if(m_eglSurface == EGL_NO_SURFACE)
|
||||
g_logger.fatal(stdext::format("Unable to create EGL surface: %s", eglGetError()));
|
||||
#endif
|
||||
|
||||
if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))
|
||||
g_logger.fatal("Unable to make current EGL context");
|
||||
}
|
||||
|
||||
void GraphicsContextEGL::swapBuffers()
|
||||
{
|
||||
eglSwapBuffers(m_eglDisplay, m_eglSurface);
|
||||
}
|
||||
|
||||
void GraphicsContextEGL::setVerticalSync(bool enable)
|
||||
{
|
||||
eglSwapInterval(m_eglDisplay, enable ? 1 : 0);
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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 GRAPHICSCONTEXTEGL_H
|
||||
#define GRAPHICSCONTEXTEGL_H
|
||||
|
||||
#include <framework/graphics/graphicscontext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
class GraphicsContextEGL : public GraphicsContext
|
||||
{
|
||||
public:
|
||||
GraphicsContextEGL();
|
||||
|
||||
void create();
|
||||
void destroy();
|
||||
void restore();
|
||||
|
||||
void swapBuffers();
|
||||
|
||||
void setVerticalSync(bool enable);
|
||||
|
||||
private:
|
||||
EGLConfig m_eglConfig;
|
||||
EGLContext m_eglContext;
|
||||
EGLDisplay m_eglDisplay;
|
||||
EGLSurface m_eglSurface;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* 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 "graphicscontextglx.h"
|
||||
|
||||
GraphicsContextGLX::GraphicsContextGLX() :
|
||||
GraphicsContext("GLX"), m_window(dynamic_cast<X11Window&>(g_window))
|
||||
{
|
||||
m_fbConfig = 0;
|
||||
m_glxContext = 0;
|
||||
}
|
||||
|
||||
void GraphicsContextGLX::create()
|
||||
{
|
||||
if(!glXQueryExtension(m_window.getDisplay(), NULL, NULL))
|
||||
g_logger.fatal("GLX not supported");
|
||||
|
||||
static int attrList[] = {
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_DOUBLEBUFFER, True,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
None
|
||||
};
|
||||
|
||||
int nelements;
|
||||
m_fbConfig = glXChooseFBConfig(m_window.getDisplay(), m_window.getScreen(), attrList, &nelements);
|
||||
if(!m_fbConfig)
|
||||
g_logger.fatal("Couldn't choose RGBA, double buffered fbconfig");
|
||||
|
||||
m_window.setVisual(glXGetVisualFromFBConfig(m_window.getDisplay(), *m_fbConfig));
|
||||
if(!m_window.getDisplay())
|
||||
g_logger.fatal("Couldn't choose RGBA, double buffered visual");
|
||||
|
||||
m_window.setRootWindow(RootWindow(m_window.getDisplay(), m_window.getVisual()->screen));
|
||||
|
||||
m_glxContext = glXCreateContext(m_window.getDisplay(), m_window.getVisual(), NULL, True);
|
||||
|
||||
if(!m_glxContext)
|
||||
g_logger.fatal("Unable to create GLX context");
|
||||
|
||||
if(!glXIsDirect(m_window.getDisplay(), m_glxContext))
|
||||
g_logger.warning("GL direct rendering is not possible");
|
||||
}
|
||||
|
||||
void GraphicsContextGLX::destroy()
|
||||
{
|
||||
if(m_glxContext) {
|
||||
glXMakeCurrent(m_window.getDisplay(), None, NULL);
|
||||
glXDestroyContext(m_window.getDisplay(), m_glxContext);
|
||||
m_glxContext = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsContextGLX::restore()
|
||||
{
|
||||
if(!glXMakeCurrent(m_window.getDisplay(), m_window.getWindow(), m_glxContext))
|
||||
g_logger.fatal("Unable to set GLX context on X11 window");
|
||||
}
|
||||
|
||||
bool GraphicsContextGLX::isExtensionSupported(const char *ext)
|
||||
{
|
||||
const char *exts = glXQueryExtensionsString(m_window.getDisplay(), m_window.getScreen());
|
||||
if(strstr(exts, ext))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void *GraphicsContextGLX::getExtensionProcAddress(const char *ext)
|
||||
{
|
||||
return (void *)glXGetProcAddressARB((const GLubyte*)ext);
|
||||
}
|
||||
|
||||
void GraphicsContextGLX::swapBuffers()
|
||||
{
|
||||
glXSwapBuffers(m_window.getDisplay(), m_window.getWindow());
|
||||
}
|
||||
|
||||
void GraphicsContextGLX::setVerticalSync(bool enable)
|
||||
{
|
||||
typedef GLint (*glSwapIntervalProc)(GLint);
|
||||
glSwapIntervalProc glSwapInterval = NULL;
|
||||
|
||||
if(isExtensionSupported("GLX_MESA_swap_control"))
|
||||
glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalMESA");
|
||||
else if(isExtensionSupported("GLX_SGI_swap_control"))
|
||||
glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalSGI");
|
||||
|
||||
if(glSwapInterval)
|
||||
glSwapInterval(enable ? 1 : 0);
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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 GRAPHICSCONTEXTGLX_H
|
||||
#define GRAPHICSCONTEXTGLX_H
|
||||
|
||||
#include <framework/graphics/graphicscontext.h>
|
||||
#include <framework/platform/x11window.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
class GraphicsContextGLX : public GraphicsContext
|
||||
{
|
||||
public:
|
||||
GraphicsContextGLX();
|
||||
|
||||
void create();
|
||||
void destroy();
|
||||
void restore();
|
||||
|
||||
bool isExtensionSupported(const char *ext);
|
||||
void *getExtensionProcAddress(const char *ext);
|
||||
|
||||
void swapBuffers();
|
||||
|
||||
void setVerticalSync(bool enable);
|
||||
|
||||
private:
|
||||
X11Window& m_window;
|
||||
GLXContext m_glxContext;
|
||||
GLXFBConfig *m_fbConfig;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* 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 "graphicscontextwgl.h"
|
||||
#include <framework/platform/win32window.h>
|
||||
|
||||
GraphicsContextWGL::GraphicsContextWGL() :
|
||||
GraphicsContext("WGL")
|
||||
{
|
||||
m_wglContext = 0;
|
||||
}
|
||||
|
||||
void GraphicsContextWGL::create()
|
||||
{
|
||||
HDC display = g_win32Window.getDisplay();
|
||||
|
||||
uint pixelFormat;
|
||||
static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR),
|
||||
1,
|
||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
||||
PFD_TYPE_RGBA,
|
||||
32, // Select Our Color Depth
|
||||
8, 0, 8, 0, 8, 0, // Color Bits Ignored
|
||||
8, // Alpha Buffer Bits
|
||||
0, // Shift Bit Ignored
|
||||
0, // No Accumulation Buffer
|
||||
0, 0, 0, 0, // Accumulation Bits Ignored
|
||||
0, // Z-Buffer (Depth Buffer)
|
||||
0, // No Stencil Buffer
|
||||
0, // No Auxiliary Buffer
|
||||
PFD_MAIN_PLANE, // Main Drawing Layer
|
||||
0, // Reserved
|
||||
0, 0, 0 }; // Layer Masks Ignored
|
||||
|
||||
pixelFormat = ChoosePixelFormat(display, &pfd);
|
||||
if(!pixelFormat)
|
||||
g_logger.fatal("Could not find a suitable pixel format");
|
||||
|
||||
if(!SetPixelFormat(display, pixelFormat, &pfd))
|
||||
g_logger.fatal("Could not set the pixel format");
|
||||
|
||||
if(!(m_wglContext = wglCreateContext(display)))
|
||||
g_logger.fatal("Unable to create GL context");
|
||||
}
|
||||
|
||||
void GraphicsContextWGL::destroy()
|
||||
{
|
||||
if(m_wglContext) {
|
||||
if(!wglMakeCurrent(NULL, NULL))
|
||||
g_logger.error("Release of dc and rc failed.");
|
||||
if(!wglDeleteContext(m_wglContext))
|
||||
g_logger.error("Release rendering context failed.");
|
||||
m_wglContext = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsContextWGL::restore()
|
||||
{
|
||||
if(!wglMakeCurrent(g_win32Window.getDisplay(), m_wglContext))
|
||||
g_logger.fatal("Unable to make current WGL context");
|
||||
}
|
||||
|
||||
bool GraphicsContextWGL::isExtensionSupported(const char *ext)
|
||||
{
|
||||
typedef const char* (WINAPI * wglGetExtensionsStringProc)();
|
||||
wglGetExtensionsStringProc wglGetExtensionsString = (wglGetExtensionsStringProc)getExtensionProcAddress("wglGetExtensionsStringEXT");
|
||||
if(!wglGetExtensionsString)
|
||||
return false;
|
||||
|
||||
const char *exts = wglGetExtensionsString();
|
||||
if(exts && strstr(exts, ext))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void *GraphicsContextWGL::getExtensionProcAddress(const char *ext)
|
||||
{
|
||||
return (void*)wglGetProcAddress(ext);
|
||||
}
|
||||
|
||||
void GraphicsContextWGL::swapBuffers()
|
||||
{
|
||||
SwapBuffers(g_win32Window.getDisplay());
|
||||
}
|
||||
|
||||
void GraphicsContextWGL::setVerticalSync(bool enable)
|
||||
{
|
||||
if(!isExtensionSupported("WGL_EXT_swap_control"))
|
||||
return;
|
||||
|
||||
typedef BOOL (WINAPI * wglSwapIntervalProc)(int);
|
||||
wglSwapIntervalProc wglSwapInterval = (wglSwapIntervalProc)getExtensionProcAddress("wglSwapIntervalEXT");
|
||||
if(!wglSwapInterval)
|
||||
return;
|
||||
|
||||
wglSwapInterval(enable ? 1 : 0);
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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 GRAPHICSCONTEXTWGL_H
|
||||
#define GRAPHICSCONTEXTWGL_H
|
||||
|
||||
#include <framework/graphics/graphicscontext.h>
|
||||
#include <windows.h>
|
||||
|
||||
class GraphicsContextWGL : public GraphicsContext
|
||||
{
|
||||
public:
|
||||
GraphicsContextWGL();
|
||||
|
||||
void create();
|
||||
void destroy();
|
||||
void restore();
|
||||
|
||||
bool isExtensionSupported(const char *ext);
|
||||
void *getExtensionProcAddress(const char *ext);
|
||||
|
||||
void swapBuffers();
|
||||
|
||||
void setVerticalSync(bool enable);
|
||||
|
||||
private:
|
||||
HGLRC m_wglContext;
|
||||
};
|
||||
|
||||
#endif
|
@@ -24,26 +24,8 @@
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/platform/platformwindow.h>
|
||||
|
||||
#ifdef OPENGL_ES
|
||||
#include <framework/graphics/ogl/graphicscontextegl.h>
|
||||
#elif WIN32
|
||||
#include <framework/graphics/ogl/graphicscontextwgl.h>
|
||||
#else
|
||||
#include <framework/graphics/ogl/graphicscontextglx.h>
|
||||
#endif
|
||||
|
||||
PainterOGL::PainterOGL()
|
||||
{
|
||||
#ifdef SDL
|
||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContext("null"));
|
||||
#elif OPENGL_ES
|
||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextEGL);
|
||||
#elif WIN32
|
||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextWGL);
|
||||
#else
|
||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextGLX);
|
||||
#endif
|
||||
|
||||
m_glTextureId = 0;
|
||||
m_oldStateIndex = 0;
|
||||
m_color = Color::white;
|
||||
@@ -53,7 +35,6 @@ PainterOGL::PainterOGL()
|
||||
m_shaderProgram = nullptr;
|
||||
m_texture = nullptr;
|
||||
m_alphaWriting = false;
|
||||
|
||||
setResolution(g_window.getSize());
|
||||
}
|
||||
|
||||
@@ -305,7 +286,6 @@ void PainterOGL::updateGlBlendEquation()
|
||||
{
|
||||
if(!g_graphics.canUseBlendEquation())
|
||||
return;
|
||||
|
||||
if(m_blendEquation == BlendEquation_Add)
|
||||
glBlendEquation(0x8006); // GL_FUNC_ADD
|
||||
else if(m_blendEquation == BlendEquation_Max)
|
||||
|
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* 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 "textureogl.h"
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
|
||||
TextureOGL::TextureOGL()
|
||||
{
|
||||
m_id = 0;
|
||||
}
|
||||
|
||||
TextureOGL::TextureOGL(const Size& size)
|
||||
{
|
||||
m_id = 0;
|
||||
|
||||
if(!setupSize(size))
|
||||
return;
|
||||
|
||||
createTexture();
|
||||
bind();
|
||||
setupPixels(0, m_glSize, nullptr, 4);
|
||||
setupWrap();
|
||||
setupFilters();
|
||||
}
|
||||
|
||||
TextureOGL::TextureOGL(const ImagePtr& image, bool buildMipmaps)
|
||||
{
|
||||
m_id = 0;
|
||||
|
||||
if(!setupSize(image->getSize(), buildMipmaps))
|
||||
return;
|
||||
|
||||
createTexture();
|
||||
|
||||
uploadPixels(image, buildMipmaps);
|
||||
}
|
||||
|
||||
TextureOGL::~TextureOGL()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(!g_app.isTerminated());
|
||||
#endif
|
||||
// free texture from gl memory
|
||||
if(g_graphics.ok() && m_id != 0)
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
void TextureOGL::uploadPixels(const ImagePtr& image, bool buildMipmaps)
|
||||
{
|
||||
ImagePtr glImage = image;
|
||||
if(m_size != m_glSize) {
|
||||
glImage = ImagePtr(new Image(m_glSize, image->getBpp()));
|
||||
glImage->paste(image);
|
||||
} else
|
||||
glImage = image;
|
||||
|
||||
bind();
|
||||
|
||||
if(buildMipmaps) {
|
||||
int level = 0;
|
||||
do {
|
||||
setupPixels(level++, glImage->getSize(), glImage->getPixelData(), glImage->getBpp());
|
||||
} while(glImage->nextMipmap());
|
||||
m_hasMipmaps = true;
|
||||
} else
|
||||
setupPixels(0, glImage->getSize(), glImage->getPixelData(), glImage->getBpp());
|
||||
|
||||
setupWrap();
|
||||
setupFilters();
|
||||
}
|
||||
|
||||
void TextureOGL::bind()
|
||||
{
|
||||
// must reset painter texture state
|
||||
g_painter->setTexture(this);
|
||||
glBindTexture(GL_TEXTURE_2D, m_id);
|
||||
}
|
||||
|
||||
void TextureOGL::copyFromScreen(const Rect& screenRect)
|
||||
{
|
||||
bind();
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height());
|
||||
}
|
||||
|
||||
bool TextureOGL::buildHardwareMipmaps()
|
||||
{
|
||||
if(!g_graphics.canUseHardwareMipmaps())
|
||||
return false;
|
||||
|
||||
bind();
|
||||
|
||||
if(!m_hasMipmaps) {
|
||||
m_hasMipmaps = true;
|
||||
setupFilters();
|
||||
}
|
||||
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextureOGL::setSmooth(bool smooth)
|
||||
{
|
||||
if(smooth && !g_graphics.canUseBilinearFiltering())
|
||||
return;
|
||||
|
||||
if(smooth == m_smooth)
|
||||
return;
|
||||
|
||||
m_smooth = smooth;
|
||||
bind();
|
||||
setupFilters();
|
||||
}
|
||||
|
||||
void TextureOGL::setRepeat(bool repeat)
|
||||
{
|
||||
if(m_repeat == repeat)
|
||||
return;
|
||||
|
||||
m_repeat = repeat;
|
||||
bind();
|
||||
setupWrap();
|
||||
}
|
||||
|
||||
void TextureOGL::setUpsideDown(bool upsideDown)
|
||||
{
|
||||
if(m_upsideDown == upsideDown)
|
||||
return;
|
||||
m_upsideDown = upsideDown;
|
||||
setupTranformMatrix(m_glSize, m_size);
|
||||
}
|
||||
|
||||
void TextureOGL::createTexture()
|
||||
{
|
||||
glGenTextures(1, &m_id);
|
||||
assert(m_id != 0);
|
||||
}
|
||||
|
||||
bool TextureOGL::setupSize(const Size& size, bool forcePowerOfTwo)
|
||||
{
|
||||
Size glSize;
|
||||
if(!g_graphics.canUseNonPowerOfTwoTextures() || forcePowerOfTwo)
|
||||
glSize.resize(stdext::to_power_of_two(size.width()), stdext::to_power_of_two(size.height()));
|
||||
else
|
||||
glSize = size;
|
||||
|
||||
// checks texture max size
|
||||
if(std::max(glSize.width(), glSize.height()) > g_graphics.getMaxTextureSize()) {
|
||||
g_logger.error(stdext::format("loading texture with size %dx%d failed, "
|
||||
"the maximum size allowed by the graphics card is %dx%d,"
|
||||
"to prevent crashes the texture will be displayed as a blank texture",
|
||||
size.width(), size.height(), g_graphics.getMaxTextureSize(), g_graphics.getMaxTextureSize()));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_size = size;
|
||||
m_glSize = glSize;
|
||||
setupTranformMatrix(m_glSize, m_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextureOGL::setupWrap()
|
||||
{
|
||||
int texParam;
|
||||
if(!m_repeat && g_graphics.canUseClampToEdge())
|
||||
texParam = GL_CLAMP_TO_EDGE;
|
||||
else
|
||||
texParam = GL_REPEAT;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParam);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParam);
|
||||
}
|
||||
|
||||
void TextureOGL::setupFilters()
|
||||
{
|
||||
int minFilter;
|
||||
int magFilter;
|
||||
if(m_smooth) {
|
||||
minFilter = m_hasMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
|
||||
magFilter = GL_LINEAR;
|
||||
} else {
|
||||
minFilter = m_hasMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
|
||||
magFilter = GL_NEAREST;
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
|
||||
}
|
||||
|
||||
void TextureOGL::setupPixels(int level, const Size& size, uchar* pixels, int channels)
|
||||
{
|
||||
GLenum format = 0;
|
||||
switch(channels) {
|
||||
case 4:
|
||||
format = GL_RGBA;
|
||||
break;
|
||||
case 3:
|
||||
format = GL_RGB;
|
||||
break;
|
||||
case 2:
|
||||
format = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case 1:
|
||||
format = GL_LUMINANCE;
|
||||
break;
|
||||
}
|
||||
GLenum internalFormat = GL_RGBA;
|
||||
//TODO: compression support
|
||||
glTexImage2D(GL_TEXTURE_2D, level, internalFormat, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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 TEXTUREOGL_H
|
||||
#define TEXTUREOGL_H
|
||||
|
||||
#include <framework/graphics/texture.h>
|
||||
|
||||
class TextureOGL : public Texture
|
||||
{
|
||||
public:
|
||||
TextureOGL();
|
||||
TextureOGL(const Size& size);
|
||||
TextureOGL(const ImagePtr& image, bool buildMipmaps = false);
|
||||
virtual ~TextureOGL();
|
||||
|
||||
void uploadPixels(const ImagePtr& image, bool buildMipmaps = false);
|
||||
void bind();
|
||||
void copyFromScreen(const Rect& screenRect);
|
||||
virtual bool buildHardwareMipmaps();
|
||||
|
||||
virtual void setSmooth(bool smooth);
|
||||
virtual void setRepeat(bool repeat);
|
||||
void setUpsideDown(bool upsideDown);
|
||||
|
||||
protected:
|
||||
void createTexture();
|
||||
bool setupSize(const Size& size, bool forcePowerOfTwo = false);
|
||||
void setupWrap();
|
||||
void setupFilters();
|
||||
void setupPixels(int level, const Size& size, uchar *pixels, int channels = 4);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@@ -25,7 +25,6 @@
|
||||
|
||||
#include <framework/graphics/declarations.h>
|
||||
#include <framework/graphics/coordsbuffer.h>
|
||||
#include <framework/graphics/graphicscontext.h>
|
||||
#include <framework/graphics/paintershaderprogram.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
|
||||
@@ -51,7 +50,7 @@ public:
|
||||
|
||||
|
||||
Painter();
|
||||
virtual ~Painter() {}
|
||||
virtual ~Painter() { }
|
||||
|
||||
virtual void bind() { }
|
||||
virtual void unbind() { }
|
||||
@@ -96,7 +95,6 @@ public:
|
||||
float getOpacity() { return m_opacity; }
|
||||
Rect getClipRect() { return m_clipRect; }
|
||||
CompositionMode getCompositionMode() { return m_compositionMode; }
|
||||
GraphicsContextPtr getGraphicsContext() { return m_graphicsContext; }
|
||||
|
||||
virtual void setCompositionMode(CompositionMode compositionMode) = 0;
|
||||
|
||||
@@ -118,7 +116,6 @@ protected:
|
||||
Size m_resolution;
|
||||
float m_opacity;
|
||||
Rect m_clipRect;
|
||||
GraphicsContextPtr m_graphicsContext;
|
||||
};
|
||||
|
||||
extern Painter *g_painter;
|
||||
|
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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 GRAPHICSCONTEXTEGL_H
|
||||
#define GRAPHICSCONTEXTEGL_H
|
||||
|
||||
#include <framework/graphics/graphicscontext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
class GraphicsContextEGL : public GraphicsContext
|
||||
{
|
||||
public:
|
||||
GraphicsContextEGL();
|
||||
|
||||
void create(WindowType window, DisplayType display);
|
||||
void destroy();
|
||||
void restore();
|
||||
|
||||
void swapBuffers();
|
||||
|
||||
void setVerticalSync(bool enable);
|
||||
|
||||
private:
|
||||
EGLConfig m_eglConfig;
|
||||
EGLContext m_eglContext;
|
||||
EGLDisplay m_eglDisplay;
|
||||
EGLSurface m_eglSurface;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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 PAINTERSDL_H
|
||||
#define PAINTERSDL_H
|
||||
|
||||
#include <framework/graphics/painter.h>
|
||||
|
||||
class PainterSDL: public Painter
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
#endif
|
@@ -33,29 +33,223 @@ Texture::Texture()
|
||||
m_time = 0;
|
||||
}
|
||||
|
||||
Texture::Texture(const Size& size)
|
||||
{
|
||||
m_id = 0;
|
||||
m_time = 0;
|
||||
|
||||
if(!setupSize(size))
|
||||
return;
|
||||
|
||||
createTexture();
|
||||
bind();
|
||||
setupPixels(0, m_glSize, nullptr, 4);
|
||||
setupWrap();
|
||||
setupFilters();
|
||||
}
|
||||
|
||||
Texture::Texture(const ImagePtr& image, bool buildMipmaps, bool compress)
|
||||
{
|
||||
m_id = 0;
|
||||
m_time = 0;
|
||||
|
||||
createTexture();
|
||||
|
||||
uploadPixels(image, buildMipmaps, compress);
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(!g_app.isTerminated());
|
||||
#endif
|
||||
// free texture from gl memory
|
||||
if(g_graphics.ok() && m_id != 0)
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
bool Texture::setupSize(const Size& size, bool)
|
||||
void Texture::uploadPixels(const ImagePtr& image, bool buildMipmaps, bool compress)
|
||||
{
|
||||
m_size = size;
|
||||
setupTranformMatrix(size, size);
|
||||
if(!setupSize(image->getSize(), buildMipmaps))
|
||||
return;
|
||||
|
||||
ImagePtr glImage = image;
|
||||
if(m_size != m_glSize) {
|
||||
glImage = ImagePtr(new Image(m_glSize, image->getBpp()));
|
||||
glImage->paste(image);
|
||||
} else
|
||||
glImage = image;
|
||||
|
||||
bind();
|
||||
|
||||
if(buildMipmaps) {
|
||||
int level = 0;
|
||||
do {
|
||||
setupPixels(level++, glImage->getSize(), glImage->getPixelData(), glImage->getBpp(), compress);
|
||||
} while(glImage->nextMipmap());
|
||||
m_hasMipmaps = true;
|
||||
} else
|
||||
setupPixels(0, glImage->getSize(), glImage->getPixelData(), glImage->getBpp(), compress);
|
||||
|
||||
setupWrap();
|
||||
setupFilters();
|
||||
}
|
||||
|
||||
void Texture::bind()
|
||||
{
|
||||
// must reset painter texture state
|
||||
g_painter->setTexture(this);
|
||||
glBindTexture(GL_TEXTURE_2D, m_id);
|
||||
}
|
||||
|
||||
void Texture::copyFromScreen(const Rect& screenRect)
|
||||
{
|
||||
bind();
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height());
|
||||
}
|
||||
|
||||
bool Texture::buildHardwareMipmaps()
|
||||
{
|
||||
if(!g_graphics.canUseHardwareMipmaps())
|
||||
return false;
|
||||
|
||||
bind();
|
||||
|
||||
if(!m_hasMipmaps) {
|
||||
m_hasMipmaps = true;
|
||||
setupFilters();
|
||||
}
|
||||
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Texture::setupTranformMatrix(const Size& textureSize, const Size& realSize)
|
||||
void Texture::setSmooth(bool smooth)
|
||||
{
|
||||
if(smooth && !g_graphics.canUseBilinearFiltering())
|
||||
return;
|
||||
|
||||
if(smooth == m_smooth)
|
||||
return;
|
||||
|
||||
m_smooth = smooth;
|
||||
bind();
|
||||
setupFilters();
|
||||
}
|
||||
|
||||
void Texture::setRepeat(bool repeat)
|
||||
{
|
||||
if(m_repeat == repeat)
|
||||
return;
|
||||
|
||||
m_repeat = repeat;
|
||||
bind();
|
||||
setupWrap();
|
||||
}
|
||||
|
||||
void Texture::setUpsideDown(bool upsideDown)
|
||||
{
|
||||
if(m_upsideDown == upsideDown)
|
||||
return;
|
||||
m_upsideDown = upsideDown;
|
||||
setupTranformMatrix();
|
||||
}
|
||||
|
||||
void Texture::createTexture()
|
||||
{
|
||||
glGenTextures(1, &m_id);
|
||||
assert(m_id != 0);
|
||||
}
|
||||
|
||||
bool Texture::setupSize(const Size& size, bool forcePowerOfTwo)
|
||||
{
|
||||
Size glSize;
|
||||
if(!g_graphics.canUseNonPowerOfTwoTextures() || forcePowerOfTwo)
|
||||
glSize.resize(stdext::to_power_of_two(size.width()), stdext::to_power_of_two(size.height()));
|
||||
else
|
||||
glSize = size;
|
||||
|
||||
// checks texture max size
|
||||
if(std::max(glSize.width(), glSize.height()) > g_graphics.getMaxTextureSize()) {
|
||||
g_logger.error(stdext::format("loading texture with size %dx%d failed, "
|
||||
"the maximum size allowed by the graphics card is %dx%d,"
|
||||
"to prevent crashes the texture will be displayed as a blank texture",
|
||||
size.width(), size.height(), g_graphics.getMaxTextureSize(), g_graphics.getMaxTextureSize()));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_size = size;
|
||||
m_glSize = glSize;
|
||||
setupTranformMatrix();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Texture::setupWrap()
|
||||
{
|
||||
int texParam;
|
||||
if(!m_repeat && g_graphics.canUseClampToEdge())
|
||||
texParam = GL_CLAMP_TO_EDGE;
|
||||
else
|
||||
texParam = GL_REPEAT;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParam);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParam);
|
||||
}
|
||||
|
||||
void Texture::setupFilters()
|
||||
{
|
||||
int minFilter;
|
||||
int magFilter;
|
||||
if(m_smooth) {
|
||||
minFilter = m_hasMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
|
||||
magFilter = GL_LINEAR;
|
||||
} else {
|
||||
minFilter = m_hasMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
|
||||
magFilter = GL_NEAREST;
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
|
||||
}
|
||||
|
||||
void Texture::setupTranformMatrix()
|
||||
{
|
||||
if(m_upsideDown) {
|
||||
m_transformMatrix = { 1.0f/textureSize.width(), 0.0f, 0.0f,
|
||||
0.0f, -1.0f/textureSize.height(), 0.0f,
|
||||
0.0f, realSize.height()/(float)textureSize.height(), 1.0f };
|
||||
m_transformMatrix = { 1.0f/m_glSize.width(), 0.0f, 0.0f,
|
||||
0.0f, -1.0f/m_glSize.height(), 0.0f,
|
||||
0.0f, m_size.height()/(float)m_glSize.height(), 1.0f };
|
||||
} else {
|
||||
m_transformMatrix = { 1.0f/textureSize.width(), 0.0f, 0.0f,
|
||||
0.0f, 1.0f/textureSize.height(), 0.0f,
|
||||
0.0f, 0.0f, 1.0f };
|
||||
m_transformMatrix = { 1.0f/m_glSize.width(), 0.0f, 0.0f,
|
||||
0.0f, 1.0f/m_glSize.height(), 0.0f,
|
||||
0.0f, 0.0f, 1.0f };
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::setupPixels(int level, const Size& size, uchar* pixels, int channels, bool compress)
|
||||
{
|
||||
GLenum format = 0;
|
||||
switch(channels) {
|
||||
case 4:
|
||||
format = GL_RGBA;
|
||||
break;
|
||||
case 3:
|
||||
format = GL_RGB;
|
||||
break;
|
||||
case 2:
|
||||
format = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case 1:
|
||||
format = GL_LUMINANCE;
|
||||
break;
|
||||
}
|
||||
|
||||
GLenum internalFormat = GL_RGBA;
|
||||
|
||||
#ifdef OPENGL_ES
|
||||
//TODO
|
||||
#else
|
||||
if(compress)
|
||||
internalFormat = GL_COMPRESSED_RGBA;
|
||||
#endif
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, level, internalFormat, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
|
@@ -29,25 +29,26 @@ class Texture : public stdext::shared_object
|
||||
{
|
||||
public:
|
||||
Texture();
|
||||
Texture(const Size& size);
|
||||
Texture(const ImagePtr& image, bool buildMipmaps = false, bool compress = false);
|
||||
virtual ~Texture();
|
||||
|
||||
virtual void setSmooth(bool) {}
|
||||
virtual void setRepeat(bool) {}
|
||||
virtual void setUpsideDown(bool) {}
|
||||
|
||||
virtual bool setupSize(const Size& size, bool);
|
||||
virtual void copyFromScreen(const Rect&) {}
|
||||
virtual bool buildHardwareMipmaps() { return false; }
|
||||
virtual void uploadPixels(const ImagePtr&, bool) {}
|
||||
void uploadPixels(const ImagePtr& image, bool buildMipmaps = false, bool compress = false);
|
||||
void bind();
|
||||
void copyFromScreen(const Rect& screenRect);
|
||||
virtual bool buildHardwareMipmaps();
|
||||
|
||||
virtual void setSmooth(bool smooth);
|
||||
virtual void setRepeat(bool repeat);
|
||||
void setUpsideDown(bool upsideDown);
|
||||
void setTime(ticks_t time) { m_time = time; }
|
||||
void setupTranformMatrix(const Size& textureSize, const Size& realSize);
|
||||
|
||||
uint getId() { return m_id; }
|
||||
ticks_t getTime() { return m_time; }
|
||||
int getWidth() { return m_size.width(); }
|
||||
int getHeight() { return m_size.height(); }
|
||||
const Size& getSize() { return m_size; }
|
||||
const Size& getGlSize() { return m_glSize; }
|
||||
const Matrix3& getTransformMatrix() { return m_transformMatrix; }
|
||||
bool isEmpty() { return m_id == 0; }
|
||||
bool hasRepeat() { return m_repeat; }
|
||||
@@ -55,6 +56,13 @@ public:
|
||||
virtual bool isAnimatedTexture() { return false; }
|
||||
|
||||
protected:
|
||||
void createTexture();
|
||||
bool setupSize(const Size& size, bool forcePowerOfTwo = false);
|
||||
void setupWrap();
|
||||
void setupFilters();
|
||||
void setupTranformMatrix();
|
||||
void setupPixels(int level, const Size& size, uchar *pixels, int channels = 4, bool compress = false);
|
||||
|
||||
uint m_id;
|
||||
ticks_t m_time;
|
||||
Size m_size;
|
||||
|
@@ -29,7 +29,6 @@
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/graphics/apngloader.h>
|
||||
#include "ogl/textureogl.h"
|
||||
|
||||
TextureManager g_textures;
|
||||
|
||||
@@ -147,7 +146,7 @@ TexturePtr TextureManager::loadTexture(std::stringstream& file)
|
||||
texture = animatedTexture;
|
||||
} else {
|
||||
ImagePtr image = ImagePtr(new Image(imageSize, apng.bpp, apng.pdata));
|
||||
texture = TexturePtr(new TextureOGL(image));
|
||||
texture = TexturePtr(new Texture(image));
|
||||
}
|
||||
free_apng(&apng);
|
||||
}
|
||||
|
@@ -20,9 +20,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MOUSE_H
|
||||
#define MOUSE_H
|
||||
|
||||
#include <framework/global.h>
|
||||
|
||||
class Mouse
|
||||
@@ -46,5 +43,3 @@ private:
|
||||
};
|
||||
|
||||
extern Mouse g_mouse;
|
||||
|
||||
#endif
|
||||
|
@@ -577,20 +577,19 @@ int LuaInterface::lua_dofile(lua_State* L)
|
||||
|
||||
int LuaInterface::lua_dofiles(lua_State* L)
|
||||
{
|
||||
std::string directory = g_lua.popString();
|
||||
|
||||
for(const std::string& fileName : g_resources.listDirectoryFiles(directory)) {
|
||||
if(!g_resources.isFileType(fileName, "lua"))
|
||||
continue;
|
||||
|
||||
try {
|
||||
g_lua.loadScript(directory + "/" + fileName);
|
||||
g_lua.call(0, 0);
|
||||
} catch(stdext::exception& e) {
|
||||
g_lua.pushString(e.what());
|
||||
g_lua.error();
|
||||
}
|
||||
std::string contains = "";
|
||||
if(g_lua.getTop() > 2) {
|
||||
contains = g_lua.popString();
|
||||
}
|
||||
|
||||
bool recursive = false;
|
||||
if(g_lua.getTop() > 1) {
|
||||
recursive = g_lua.popBoolean();
|
||||
}
|
||||
|
||||
std::string directory = g_lua.popString();
|
||||
g_lua.loadFiles(directory, recursive, contains);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1247,3 +1246,29 @@ int LuaInterface::getTop()
|
||||
{
|
||||
return lua_gettop(L);
|
||||
}
|
||||
|
||||
void LuaInterface::loadFiles(std::string directory, bool recursive, std::string contains)
|
||||
{
|
||||
for(const std::string& fileName : g_resources.listDirectoryFiles(directory)) {
|
||||
std::string fullPath = directory + "/" + fileName;
|
||||
|
||||
if(recursive && g_resources.directoryExists(fullPath)) {
|
||||
loadFiles(fullPath, true, contains);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!g_resources.isFileType(fileName, "lua"))
|
||||
continue;
|
||||
|
||||
if(!contains.empty() && fileName.find(contains) == std::string::npos)
|
||||
continue;
|
||||
|
||||
try {
|
||||
g_lua.loadScript(fullPath);
|
||||
g_lua.call(0, 0);
|
||||
} catch(stdext::exception& e) {
|
||||
g_lua.pushString(e.what());
|
||||
g_lua.error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -321,6 +321,8 @@ public:
|
||||
void clearStack() { pop(stackSize()); }
|
||||
bool hasIndex(int index) { return (stackSize() >= (index < 0 ? -index : index) && index != 0); }
|
||||
|
||||
void loadFiles(std::string directory, bool recursive = false, std::string contains = "");
|
||||
|
||||
/// Pushes any type onto the stack
|
||||
template<typename T, typename... Args>
|
||||
int polymorphicPush(const T& v, const Args&... args);
|
||||
|
@@ -569,6 +569,7 @@ void Application::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<UIWidget>("setImageFixedRatio", &UIWidget::setImageFixedRatio);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("setImageRepeated", &UIWidget::setImageRepeated);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("setImageSmooth", &UIWidget::setImageSmooth);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("setImageAutoResize", &UIWidget::setImageAutoResize);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderTop", &UIWidget::setImageBorderTop);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderRight", &UIWidget::setImageBorderRight);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderBottom", &UIWidget::setImageBorderBottom);
|
||||
@@ -585,6 +586,7 @@ void Application::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<UIWidget>("getImageColor", &UIWidget::getImageColor);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("isImageFixedRatio", &UIWidget::isImageFixedRatio);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("isImageSmooth", &UIWidget::isImageSmooth);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("isImageAutoResize", &UIWidget::isImageAutoResize);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderTop", &UIWidget::getImageBorderTop);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderRight", &UIWidget::getImageBorderRight);
|
||||
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderBottom", &UIWidget::getImageBorderBottom);
|
||||
|
@@ -27,16 +27,17 @@
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
asio::io_service g_ioService;
|
||||
std::list<std::shared_ptr<asio::streambuf>> Connection::m_outputStreams;
|
||||
|
||||
Connection::Connection() :
|
||||
m_readTimer(g_ioService),
|
||||
m_writeTimer(g_ioService),
|
||||
m_delayedWriteTimer(g_ioService),
|
||||
m_resolver(g_ioService),
|
||||
m_socket(g_ioService)
|
||||
{
|
||||
m_connected = false;
|
||||
m_connecting = false;
|
||||
m_sendBufferSize = 0;
|
||||
}
|
||||
|
||||
Connection::~Connection()
|
||||
@@ -56,34 +57,7 @@ void Connection::poll()
|
||||
void Connection::terminate()
|
||||
{
|
||||
g_ioService.stop();
|
||||
}
|
||||
|
||||
void Connection::connect(const std::string& host, uint16 port, const std::function<void()>& connectCallback)
|
||||
{
|
||||
m_connected = false;
|
||||
m_connecting = true;
|
||||
m_error.clear();
|
||||
m_connectCallback = connectCallback;
|
||||
|
||||
asio::ip::tcp::resolver::query query(host, stdext::unsafe_cast<std::string>(port));
|
||||
|
||||
auto self = asConnection();
|
||||
m_resolver.async_resolve(query, [=](const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator) {
|
||||
if(self.is_unique())
|
||||
return;
|
||||
m_readTimer.cancel();
|
||||
|
||||
if(!error) {
|
||||
m_socket.async_connect(*endpointIterator, std::bind(&Connection::onConnect, asConnection(), std::placeholders::_1));
|
||||
|
||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||
} else
|
||||
handleError(error);
|
||||
});
|
||||
|
||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||
m_outputStreams.clear();
|
||||
}
|
||||
|
||||
void Connection::close()
|
||||
@@ -92,8 +66,8 @@ void Connection::close()
|
||||
return;
|
||||
|
||||
// flush send data before disconnecting on clean connections
|
||||
if(m_connected && !m_error && m_sendBufferSize > 0 && m_sendEvent)
|
||||
m_sendEvent->execute();
|
||||
if(m_connected && !m_error && m_outputStream)
|
||||
internal_write();
|
||||
|
||||
m_connecting = false;
|
||||
m_connected = false;
|
||||
@@ -104,6 +78,7 @@ void Connection::close()
|
||||
m_resolver.cancel();
|
||||
m_readTimer.cancel();
|
||||
m_writeTimer.cancel();
|
||||
m_delayedWriteTimer.cancel();
|
||||
|
||||
if(m_socket.is_open()) {
|
||||
boost::system::error_code ec;
|
||||
@@ -112,94 +87,138 @@ void Connection::close()
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::write(uint8* buffer, uint16 size)
|
||||
void Connection::connect(const std::string& host, uint16 port, const std::function<void()>& connectCallback)
|
||||
{
|
||||
m_connected = false;
|
||||
m_connecting = true;
|
||||
m_error.clear();
|
||||
m_connectCallback = connectCallback;
|
||||
|
||||
asio::ip::tcp::resolver::query query(host, stdext::unsafe_cast<std::string>(port));
|
||||
m_resolver.async_resolve(query, std::bind(&Connection::onResolve, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
m_readTimer.cancel();
|
||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void Connection::internal_connect(asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator)
|
||||
{
|
||||
m_socket.async_connect(*endpointIterator, std::bind(&Connection::onConnect, asConnection(), std::placeholders::_1));
|
||||
|
||||
m_readTimer.cancel();
|
||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void Connection::write(uint8* buffer, size_t size)
|
||||
{
|
||||
if(!m_connected)
|
||||
return;
|
||||
|
||||
// send old buffer if we can't add more data
|
||||
if(m_sendBufferSize + size >= SEND_BUFFER_SIZE && m_sendEvent)
|
||||
m_sendEvent->execute();
|
||||
|
||||
// we can't send the data right away, otherwise we could create tcp congestion
|
||||
memcpy(m_sendBuffer + m_sendBufferSize, buffer, size);
|
||||
m_sendBufferSize += size;
|
||||
if(!m_outputStream) {
|
||||
if(!m_outputStreams.empty()) {
|
||||
m_outputStream = m_outputStreams.front();
|
||||
m_outputStreams.pop_front();
|
||||
} else
|
||||
m_outputStream = std::shared_ptr<asio::streambuf>(new asio::streambuf);
|
||||
|
||||
if(!m_sendEvent || m_sendEvent->isExecuted() || m_sendEvent->isCanceled()) {
|
||||
auto self = asConnection();
|
||||
|
||||
// wait 1 ms to do the real send
|
||||
m_sendEvent = g_dispatcher.scheduleEvent([=] {
|
||||
if(self.is_unique())
|
||||
return;
|
||||
//m_writeTimer.cancel();
|
||||
|
||||
asio::async_write(m_socket,
|
||||
asio::buffer(m_sendBuffer, m_sendBufferSize),
|
||||
std::bind(&Connection::onWrite, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
m_writeTimer.expires_from_now(boost::posix_time::seconds(WRITE_TIMEOUT));
|
||||
m_writeTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||
|
||||
m_sendBufferSize = 0;
|
||||
}, SEND_INTERVAL);
|
||||
m_delayedWriteTimer.cancel();
|
||||
m_delayedWriteTimer.expires_from_now(boost::posix_time::milliseconds(10));
|
||||
m_delayedWriteTimer.async_wait(std::bind(&Connection::onCanWrite, asConnection(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
std::ostream os(m_outputStream.get());
|
||||
os.write((const char*)buffer, size);
|
||||
os.flush();
|
||||
}
|
||||
|
||||
void Connection::internal_write()
|
||||
{
|
||||
if(!m_connected)
|
||||
return;
|
||||
|
||||
std::shared_ptr<asio::streambuf> outputStream = m_outputStream;
|
||||
m_outputStream = nullptr;
|
||||
|
||||
asio::async_write(m_socket,
|
||||
*outputStream,
|
||||
std::bind(&Connection::onWrite, asConnection(), std::placeholders::_1, std::placeholders::_2, outputStream));
|
||||
|
||||
m_writeTimer.cancel();
|
||||
m_writeTimer.expires_from_now(boost::posix_time::seconds(WRITE_TIMEOUT));
|
||||
m_writeTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void Connection::read(uint16 bytes, const RecvCallback& callback)
|
||||
{
|
||||
m_readTimer.cancel();
|
||||
|
||||
if(!m_connected)
|
||||
return;
|
||||
|
||||
m_recvCallback = callback;
|
||||
|
||||
asio::async_read(m_socket,
|
||||
asio::buffer(m_streamBuffer.prepare(bytes)),
|
||||
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, bytes));
|
||||
asio::buffer(m_inputStream.prepare(bytes)),
|
||||
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
m_readTimer.cancel();
|
||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void Connection::read_until(const std::string& what, const RecvCallback& callback)
|
||||
{
|
||||
m_readTimer.cancel();
|
||||
|
||||
if(!m_connected)
|
||||
return;
|
||||
|
||||
m_recvCallback = callback;
|
||||
|
||||
asio::async_read_until(m_socket,
|
||||
m_streamBuffer,
|
||||
m_inputStream,
|
||||
what.c_str(),
|
||||
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
m_readTimer.cancel();
|
||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void Connection::read_some(const RecvCallback& callback)
|
||||
{
|
||||
m_readTimer.cancel();
|
||||
|
||||
if(!m_connected)
|
||||
return;
|
||||
|
||||
m_recvCallback = callback;
|
||||
|
||||
m_socket.async_read_some(asio::buffer(m_streamBuffer.prepare(RECV_BUFFER_SIZE)),
|
||||
m_socket.async_read_some(asio::buffer(m_inputStream.prepare(RECV_BUFFER_SIZE)),
|
||||
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
m_readTimer.cancel();
|
||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void Connection::onResolve(const boost::system::error_code& error, asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator)
|
||||
{
|
||||
m_readTimer.cancel();
|
||||
|
||||
if(error == asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
if(!error)
|
||||
internal_connect(endpointIterator);
|
||||
else
|
||||
handleError(error);
|
||||
}
|
||||
|
||||
void Connection::onConnect(const boost::system::error_code& error)
|
||||
{
|
||||
m_readTimer.cancel();
|
||||
m_activityTimer.restart();
|
||||
|
||||
if(error == asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
if(!error) {
|
||||
m_connected = true;
|
||||
@@ -216,51 +235,72 @@ void Connection::onConnect(const boost::system::error_code& error)
|
||||
m_connecting = false;
|
||||
}
|
||||
|
||||
void Connection::onWrite(const boost::system::error_code& error, size_t)
|
||||
void Connection::onCanWrite(const boost::system::error_code& error)
|
||||
{
|
||||
m_delayedWriteTimer.cancel();
|
||||
|
||||
if(error == asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
if(m_connected)
|
||||
internal_write();
|
||||
}
|
||||
|
||||
void Connection::onWrite(const boost::system::error_code& error, size_t writeSize, std::shared_ptr<asio::streambuf> outputStream)
|
||||
{
|
||||
m_writeTimer.cancel();
|
||||
|
||||
if(!m_connected)
|
||||
if(error == asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
if(error)
|
||||
// free output stream and store for using it again later
|
||||
outputStream->consume(outputStream->size());
|
||||
m_outputStreams.push_back(outputStream);
|
||||
|
||||
if(m_connected && error)
|
||||
handleError(error);
|
||||
}
|
||||
|
||||
void Connection::onRecv(const boost::system::error_code& error, size_t recvSize)
|
||||
{
|
||||
m_readTimer.cancel();
|
||||
m_activityTimer.restart();
|
||||
|
||||
if(!m_connected)
|
||||
if(error == asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
if(!error) {
|
||||
if(m_recvCallback) {
|
||||
const char* header = boost::asio::buffer_cast<const char*>(m_streamBuffer.data());
|
||||
m_recvCallback((uint8*)header, recvSize);
|
||||
}
|
||||
if(m_connected) {
|
||||
if(!error) {
|
||||
if(m_recvCallback) {
|
||||
const char* header = boost::asio::buffer_cast<const char*>(m_inputStream.data());
|
||||
m_recvCallback((uint8*)header, recvSize);
|
||||
}
|
||||
} else
|
||||
handleError(error);
|
||||
}
|
||||
else
|
||||
handleError(error);
|
||||
|
||||
m_streamBuffer.consume(recvSize);
|
||||
if(!error)
|
||||
m_inputStream.consume(recvSize);
|
||||
}
|
||||
|
||||
void Connection::onTimeout(const boost::system::error_code& error)
|
||||
{
|
||||
if(error != asio::error::operation_aborted)
|
||||
handleError(asio::error::timed_out);
|
||||
if(error == asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
handleError(asio::error::timed_out);
|
||||
}
|
||||
|
||||
void Connection::handleError(const boost::system::error_code& error)
|
||||
{
|
||||
if(error != asio::error::operation_aborted) {
|
||||
m_error = error;
|
||||
if(m_errorCallback)
|
||||
m_errorCallback(error);
|
||||
if(m_connected || m_connecting)
|
||||
close();
|
||||
}
|
||||
if(error == asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
m_error = error;
|
||||
if(m_errorCallback)
|
||||
m_errorCallback(error);
|
||||
if(m_connected || m_connecting)
|
||||
close();
|
||||
}
|
||||
|
||||
int Connection::getIp()
|
||||
|
@@ -36,7 +36,6 @@ class Connection : public LuaObject
|
||||
enum {
|
||||
READ_TIMEOUT = 30,
|
||||
WRITE_TIMEOUT = 30,
|
||||
SEND_INTERVAL = 1,
|
||||
SEND_BUFFER_SIZE = 65536,
|
||||
RECV_BUFFER_SIZE = 65536
|
||||
};
|
||||
@@ -51,7 +50,7 @@ public:
|
||||
void connect(const std::string& host, uint16 port, const std::function<void()>& connectCallback);
|
||||
void close();
|
||||
|
||||
void write(uint8* buffer, uint16 size);
|
||||
void write(uint8* buffer, size_t size);
|
||||
void read(uint16 bytes, const RecvCallback& callback);
|
||||
void read_until(const std::string& what, const RecvCallback& callback);
|
||||
void read_some(const RecvCallback& callback);
|
||||
@@ -62,11 +61,17 @@ public:
|
||||
boost::system::error_code getError() { return m_error; }
|
||||
bool isConnecting() { return m_connecting; }
|
||||
bool isConnected() { return m_connected; }
|
||||
ticks_t getElapsedTicksSinceLastRead() { return m_connected ? m_activityTimer.elapsed_millis() : -1; }
|
||||
|
||||
ConnectionPtr asConnection() { return static_self_cast<Connection>(); }
|
||||
|
||||
protected:
|
||||
void internal_connect(asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator);
|
||||
void internal_write();
|
||||
void onResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator);
|
||||
void onConnect(const boost::system::error_code& error);
|
||||
void onWrite(const boost::system::error_code& error, size_t);
|
||||
void onCanWrite(const boost::system::error_code& error);
|
||||
void onWrite(const boost::system::error_code& error, size_t writeSize, std::shared_ptr<asio::streambuf> outputStream);
|
||||
void onRecv(const boost::system::error_code& error, size_t recvSize);
|
||||
void onTimeout(const boost::system::error_code& error);
|
||||
void handleError(const boost::system::error_code& error);
|
||||
@@ -77,17 +82,17 @@ protected:
|
||||
|
||||
asio::deadline_timer m_readTimer;
|
||||
asio::deadline_timer m_writeTimer;
|
||||
asio::deadline_timer m_delayedWriteTimer;
|
||||
asio::ip::tcp::resolver m_resolver;
|
||||
asio::ip::tcp::socket m_socket;
|
||||
|
||||
uint8 m_sendBuffer[SEND_BUFFER_SIZE];
|
||||
asio::streambuf m_streamBuffer;
|
||||
static std::list<std::shared_ptr<asio::streambuf>> m_outputStreams;
|
||||
std::shared_ptr<asio::streambuf> m_outputStream;
|
||||
asio::streambuf m_inputStream;
|
||||
bool m_connected;
|
||||
bool m_connecting;
|
||||
boost::system::error_code m_error;
|
||||
int m_sendBufferSize;
|
||||
Timer m_sendTimer;
|
||||
ScheduledEventPtr m_sendEvent;
|
||||
stdext::timer m_activityTimer;
|
||||
|
||||
friend class Server;
|
||||
};
|
||||
|
@@ -42,6 +42,8 @@ public:
|
||||
|
||||
bool isConnected();
|
||||
bool isConnecting();
|
||||
ticks_t getElapsedTicksSinceLastRead() { return m_connection ? m_connection->getElapsedTicksSinceLastRead() : -1; }
|
||||
|
||||
ConnectionPtr getConnection() { return m_connection; }
|
||||
void setConnection(const ConnectionPtr& connection) { m_connection = connection; }
|
||||
|
||||
|
@@ -23,6 +23,8 @@
|
||||
#ifndef CRASHHANDLER_H
|
||||
#define CRASHHANDLER_H
|
||||
|
||||
#ifdef CRASH_HANDLER
|
||||
void installCrashHandler();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -45,6 +45,7 @@ public:
|
||||
std::string getCPUName();
|
||||
double getTotalSystemMemory();
|
||||
std::string getOSName();
|
||||
std::string traceback(const std::string& where, int level = 1, int maxDepth = 32);
|
||||
};
|
||||
|
||||
extern Platform g_platform;
|
||||
|
@@ -22,20 +22,13 @@
|
||||
|
||||
#include "platformwindow.h"
|
||||
|
||||
#ifdef SDL
|
||||
#include "sdlwindow.h"
|
||||
SDLWindow window;
|
||||
#else
|
||||
#ifdef WIN32
|
||||
#include "win32window.h"
|
||||
WIN32Window window;
|
||||
WIN32Window& g_win32Window = window;
|
||||
#else
|
||||
#include "x11window.h"
|
||||
#include <framework/core/clock.h>
|
||||
X11Window window;
|
||||
X11Window& g_x11Window = window;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <framework/core/clock.h>
|
||||
@@ -65,19 +58,6 @@ int PlatformWindow::loadMouseCursor(const std::string& file, const Point& hotSpo
|
||||
return internalLoadMouseCursor(image, hotSpot);
|
||||
}
|
||||
|
||||
void PlatformWindow::setGraphicsContext(const GraphicsContextPtr& graphicsContext)
|
||||
{
|
||||
if(m_graphicsContext && m_graphicsContext->getName() == graphicsContext->getName())
|
||||
return;
|
||||
|
||||
if(m_graphicsContext)
|
||||
m_graphicsContext->destroy();
|
||||
|
||||
m_graphicsContext = graphicsContext;
|
||||
m_graphicsContext->create();
|
||||
m_graphicsContext->restore();
|
||||
}
|
||||
|
||||
void PlatformWindow::updateUnmaximizedCoords()
|
||||
{
|
||||
if(!isMaximized() && !isFullscreen()) {
|
||||
|
@@ -27,13 +27,12 @@
|
||||
#include <framework/core/inputevent.h>
|
||||
#include <framework/core/timer.h>
|
||||
#include <framework/graphics/declarations.h>
|
||||
#include <framework/graphics/graphicscontext.h>
|
||||
|
||||
//@bindsingleton g_window
|
||||
class PlatformWindow
|
||||
{
|
||||
enum {
|
||||
KEY_PRESS_REPEAT_INTERVAL = 30
|
||||
KEY_PRESS_REPEAT_INTERVAL = 30,
|
||||
};
|
||||
|
||||
typedef std::function<void(const Size&)> OnResizeCallback;
|
||||
@@ -58,16 +57,12 @@ public:
|
||||
virtual void setMouseCursor(int cursorId) = 0;
|
||||
virtual void restoreMouseCursor() = 0;
|
||||
|
||||
virtual void showTextInput() { }
|
||||
virtual void hideTextInput() { }
|
||||
|
||||
virtual void setTitle(const std::string& title) = 0;
|
||||
virtual void setMinimumSize(const Size& minimumSize) = 0;
|
||||
virtual void setFullscreen(bool fullscreen) = 0;
|
||||
virtual void setVerticalSync(bool enable) = 0;
|
||||
virtual void setIcon(const std::string& iconFile) = 0;
|
||||
virtual void setClipboardText(const std::string& text) = 0;
|
||||
void setGraphicsContext(const GraphicsContextPtr& graphicsContext);
|
||||
|
||||
virtual Size getDisplaySize() = 0;
|
||||
virtual std::string getClipboardText() = 0;
|
||||
@@ -132,8 +127,6 @@ protected:
|
||||
std::function<void()> m_onClose;
|
||||
OnResizeCallback m_onResize;
|
||||
OnInputEventCallback m_onInputEvent;
|
||||
|
||||
GraphicsContextPtr m_graphicsContext;
|
||||
};
|
||||
|
||||
extern PlatformWindow& g_window;
|
||||
|
@@ -1,385 +0,0 @@
|
||||
/*
|
||||
* 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 "sdlwindow.h"
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/core/graphicalapplication.h>
|
||||
|
||||
SDLWindow::SDLWindow()
|
||||
{
|
||||
m_window = NULL;
|
||||
m_renderer = NULL;
|
||||
m_minimumSize = Size(600,480);
|
||||
m_size = Size(600,480);
|
||||
}
|
||||
|
||||
void SDLWindow::init()
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 4);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 4);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 4);
|
||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 4);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
|
||||
|
||||
#ifdef OPENGL_ES
|
||||
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 16);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_ES);
|
||||
#endif
|
||||
|
||||
#ifdef MOBILE
|
||||
int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_SHOWN;
|
||||
#else
|
||||
int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN;
|
||||
#endif
|
||||
|
||||
m_window = SDL_CreateWindow(g_app.getName().c_str(),
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
m_size.width(), m_size.height(),
|
||||
flags);
|
||||
|
||||
if(!m_window)
|
||||
g_logger.fatal("Unable to create SDL window");
|
||||
|
||||
int w, h;
|
||||
SDL_GetWindowSize(m_window, &w, &h);
|
||||
m_size = Size(w,h);
|
||||
|
||||
m_context = SDL_GL_CreateContext(m_window);
|
||||
if(!m_context)
|
||||
g_logger.fatal("Unable to create SDL GL context");
|
||||
SDL_GL_MakeCurrent(m_window, m_context);
|
||||
}
|
||||
|
||||
void SDLWindow::terminate()
|
||||
{
|
||||
SDL_GL_DeleteContext(m_context);
|
||||
SDL_DestroyRenderer(m_renderer);
|
||||
SDL_DestroyWindow(m_window);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void SDLWindow::move(const Point& pos)
|
||||
{
|
||||
if(pos.x < 0 || pos.y < 0)
|
||||
return;
|
||||
|
||||
SDL_SetWindowPosition(m_window, pos.x, pos.y);
|
||||
}
|
||||
|
||||
void SDLWindow::resize(const Size& size)
|
||||
{
|
||||
if(!size.isValid())
|
||||
return;
|
||||
m_size = size;
|
||||
SDL_SetWindowSize(m_window, m_size.width(), m_size.height());
|
||||
if(m_onResize)
|
||||
m_onResize(m_size);
|
||||
}
|
||||
|
||||
void SDLWindow::show()
|
||||
{
|
||||
SDL_ShowWindow(m_window);
|
||||
}
|
||||
|
||||
void SDLWindow::hide()
|
||||
{
|
||||
SDL_HideWindow(m_window);
|
||||
}
|
||||
|
||||
void SDLWindow::maximize()
|
||||
{
|
||||
SDL_MaximizeWindow(m_window);
|
||||
}
|
||||
|
||||
Fw::MouseButton translateMouseButton(uint8 sdlButton)
|
||||
{
|
||||
switch(sdlButton) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
return Fw::MouseLeftButton;
|
||||
break;
|
||||
case SDL_BUTTON_MIDDLE:
|
||||
return Fw::MouseMidButton;
|
||||
break;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
return Fw::MouseRightButton;
|
||||
}
|
||||
return Fw::MouseNoButton;
|
||||
}
|
||||
|
||||
void SDLWindow::poll()
|
||||
{
|
||||
SDL_Event event;
|
||||
while(SDL_PollEvent(&event)) {
|
||||
switch(event.type) {
|
||||
case SDL_WINDOWEVENT: {
|
||||
switch(event.window.event) {
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
m_visible = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
m_visible = false;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MOVED:
|
||||
m_position = Point(event.window.data1, event.window.data2);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
g_logger.info(stdext::format("resize %d %d", event.window.data1, event.window.data2));
|
||||
m_size = Size(event.window.data1, event.window.data2);
|
||||
if(m_onResize)
|
||||
m_onResize(m_size);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
m_maximized = false;
|
||||
m_visible = false;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
m_maximized = true;
|
||||
m_visible = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
m_maximized = false;
|
||||
m_visible = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
m_focused = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
m_focused = false;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_KEYDOWN:
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
m_inputEvent.reset(Fw::KeyTextInputEvent);
|
||||
m_inputEvent.keyText = event.text.text;
|
||||
if(m_onInputEvent)
|
||||
m_onInputEvent(m_inputEvent);
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
m_inputEvent.reset();
|
||||
m_inputEvent.type = Fw::MouseMoveInputEvent;
|
||||
m_inputEvent.mouseMoved = Point(event.motion.xrel, event.motion.yrel);
|
||||
m_inputEvent.mousePos = Point(event.motion.x, event.motion.y);
|
||||
if(m_onInputEvent)
|
||||
m_onInputEvent(m_inputEvent);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN: {
|
||||
Fw::MouseButton button = translateMouseButton(event.button.button);
|
||||
if(button != Fw::MouseNoButton) {
|
||||
m_inputEvent.reset();
|
||||
m_inputEvent.type = Fw::MousePressInputEvent;
|
||||
m_inputEvent.mouseButton = button;
|
||||
m_mouseButtonStates[button] = true;
|
||||
if(m_onInputEvent)
|
||||
m_onInputEvent(m_inputEvent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEBUTTONUP: {
|
||||
Fw::MouseButton button = translateMouseButton(event.button.button);
|
||||
if(button == Fw::MouseNoButton)
|
||||
break;
|
||||
m_inputEvent.reset();
|
||||
m_inputEvent.type = Fw::MouseReleaseInputEvent;
|
||||
m_inputEvent.mouseButton = button;
|
||||
m_mouseButtonStates[button] = false;
|
||||
if(m_onInputEvent)
|
||||
m_onInputEvent(m_inputEvent);
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEWHEEL: {
|
||||
m_inputEvent.reset();
|
||||
m_inputEvent.type = Fw::MouseWheelInputEvent;
|
||||
m_inputEvent.mouseButton = Fw::MouseMidButton;
|
||||
if(event.wheel.y > 0)
|
||||
m_inputEvent.wheelDirection = Fw::MouseWheelUp;
|
||||
else if(event.wheel.y < 0)
|
||||
m_inputEvent.wheelDirection = Fw::MouseWheelUp;
|
||||
else
|
||||
break;
|
||||
if(m_onInputEvent)
|
||||
m_onInputEvent(m_inputEvent);
|
||||
break;
|
||||
}
|
||||
case SDL_FINGERDOWN: {
|
||||
Fw::MouseButton button;
|
||||
if(event.tfinger.fingerId == 0)
|
||||
button = Fw::MouseLeftButton;
|
||||
else if(event.tfinger.fingerId == 1)
|
||||
button = Fw::MouseRightButton;
|
||||
else
|
||||
break;
|
||||
m_inputEvent.reset();
|
||||
m_inputEvent.type = Fw::MouseReleaseInputEvent;
|
||||
m_inputEvent.mouseButton = button;
|
||||
m_mouseButtonStates[button] = true;
|
||||
if(m_onInputEvent)
|
||||
m_onInputEvent(m_inputEvent);
|
||||
break;
|
||||
}
|
||||
case SDL_FINGERUP: {
|
||||
Fw::MouseButton button;
|
||||
if(event.tfinger.fingerId == 0)
|
||||
button = Fw::MouseLeftButton;
|
||||
else if(event.tfinger.fingerId == 1)
|
||||
button = Fw::MouseRightButton;
|
||||
else
|
||||
break;
|
||||
m_inputEvent.reset();
|
||||
m_inputEvent.type = Fw::MouseReleaseInputEvent;
|
||||
m_inputEvent.mouseButton = button;
|
||||
m_mouseButtonStates[button] = false;
|
||||
if(m_onInputEvent)
|
||||
m_onInputEvent(m_inputEvent);
|
||||
break;
|
||||
}
|
||||
case SDL_FINGERMOTION: {
|
||||
m_inputEvent.reset();
|
||||
m_inputEvent.type = Fw::MouseMoveInputEvent;
|
||||
m_inputEvent.mouseMoved = Point(event.tfinger.dx, event.tfinger.dy);
|
||||
m_inputEvent.mousePos = Point(event.tfinger.x, event.tfinger.y);
|
||||
//g_logger.info(stdext::format("motion %d %d", event.tfinger.x, event.tfinger.y));
|
||||
if(m_onInputEvent)
|
||||
m_onInputEvent(m_inputEvent);
|
||||
break;
|
||||
}
|
||||
case SDL_QUIT:
|
||||
if(m_onClose)
|
||||
m_onClose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_maximized)
|
||||
updateUnmaximizedCoords();
|
||||
}
|
||||
|
||||
void SDLWindow::swapBuffers()
|
||||
{
|
||||
SDL_GL_SwapWindow(m_window);
|
||||
}
|
||||
|
||||
void SDLWindow::showMouse()
|
||||
{
|
||||
SDL_ShowCursor(1);
|
||||
}
|
||||
|
||||
void SDLWindow::hideMouse()
|
||||
{
|
||||
SDL_ShowCursor(0);
|
||||
}
|
||||
|
||||
void SDLWindow::setMouseCursor(int cursorId)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
void SDLWindow::restoreMouseCursor()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
void SDLWindow::showTextInput()
|
||||
{
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
|
||||
void SDLWindow::hideTextInput()
|
||||
{
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
|
||||
void SDLWindow::setTitle(const std::string& title)
|
||||
{
|
||||
SDL_SetWindowTitle(m_window, title.c_str());
|
||||
}
|
||||
|
||||
void SDLWindow::setMinimumSize(const Size& minimumSize)
|
||||
{
|
||||
SDL_SetWindowMinimumSize(m_window, minimumSize.width(), minimumSize.height());
|
||||
}
|
||||
|
||||
void SDLWindow::setFullscreen(bool fullscreen)
|
||||
{
|
||||
if(m_fullscreen == fullscreen)
|
||||
return;
|
||||
SDL_SetWindowFullscreen(m_window, fullscreen);
|
||||
m_fullscreen = fullscreen;
|
||||
}
|
||||
|
||||
void SDLWindow::setVerticalSync(bool enable)
|
||||
{
|
||||
SDL_GL_SetSwapInterval(enable);
|
||||
}
|
||||
|
||||
void SDLWindow::setIcon(const std::string& file)
|
||||
{
|
||||
ImagePtr image = Image::load(file);
|
||||
|
||||
if(!image) {
|
||||
g_logger.traceError(stdext::format("unable to load icon file %s", file));
|
||||
return;
|
||||
}
|
||||
|
||||
if(image->getBpp() != 4) {
|
||||
g_logger.error("the app icon must have 4 channels");
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(image->getPixelData(), image->getWidth(), image->getHeight(), 32, image->getWidth()*4, 0xff0000, 0xff00, 0xff, 0xff000000);
|
||||
SDL_SetWindowIcon(m_window, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
|
||||
void SDLWindow::setClipboardText(const std::string& text)
|
||||
{
|
||||
SDL_SetClipboardText(text.c_str());
|
||||
}
|
||||
|
||||
Size SDLWindow::getDisplaySize()
|
||||
{
|
||||
//TODO
|
||||
return getSize();
|
||||
}
|
||||
|
||||
std::string SDLWindow::getClipboardText()
|
||||
{
|
||||
return SDL_GetClipboardText();
|
||||
}
|
||||
|
||||
std::string SDLWindow::getPlatformType()
|
||||
{
|
||||
return "SDL";
|
||||
}
|
||||
|
||||
int SDLWindow::internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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 SDLWINDOW_H
|
||||
#define SDLWINDOW_H
|
||||
|
||||
#include "platformwindow.h"
|
||||
#include <SDL.h>
|
||||
#include <framework/graphics/glutil.h>
|
||||
|
||||
class SDLWindow : public PlatformWindow
|
||||
{
|
||||
public:
|
||||
SDLWindow();
|
||||
|
||||
void init();
|
||||
void terminate();
|
||||
|
||||
void move(const Point& pos);
|
||||
void resize(const Size& size);
|
||||
void show();
|
||||
void hide();
|
||||
void maximize();
|
||||
void poll();
|
||||
void swapBuffers();
|
||||
void showMouse();
|
||||
void hideMouse();
|
||||
|
||||
void setMouseCursor(int cursorId);
|
||||
void restoreMouseCursor();
|
||||
|
||||
void showTextInput();
|
||||
void hideTextInput();
|
||||
|
||||
void setTitle(const std::string& title);
|
||||
void setMinimumSize(const Size& minimumSize);
|
||||
void setFullscreen(bool fullscreen);
|
||||
void setVerticalSync(bool enable);
|
||||
void setIcon(const std::string& file);
|
||||
void setClipboardText(const std::string& text);
|
||||
|
||||
Size getDisplaySize();
|
||||
std::string getClipboardText();
|
||||
std::string getPlatformType();
|
||||
|
||||
protected:
|
||||
int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot);
|
||||
|
||||
private:
|
||||
SDL_Window *m_window;
|
||||
SDL_Renderer *m_renderer;
|
||||
SDL_GLContext m_context;
|
||||
};
|
||||
|
||||
#endif
|
@@ -20,6 +20,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(WIN32) && defined(CRASH_HANDLER)
|
||||
|
||||
#include "crashhandler.h"
|
||||
#include <framework/global.h>
|
||||
#include <framework/core/application.h>
|
||||
@@ -131,3 +133,5 @@ void installCrashHandler()
|
||||
sigaction(SIGFPE, &sa, NULL); // floating-point exception
|
||||
sigaction(SIGABRT, &sa, NULL); // process aborted (asserts)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -20,6 +20,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
#include "platform.h"
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
@@ -27,16 +29,17 @@
|
||||
#include <framework/stdext/stdext.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
void Platform::processArgs(std::vector<std::string>& args)
|
||||
{
|
||||
//nothing to do, linux args are already utf8 encoded
|
||||
//nothing todo, linux args are already utf8 encoded
|
||||
}
|
||||
|
||||
bool Platform::spawnProcess(std::string process, const std::vector<std::string>& args)
|
||||
{
|
||||
struct stat sts;
|
||||
if(stat(process.c_str(), &sts) == -1)
|
||||
if(stat(process.c_str(), &sts) == -1 && errno == ENOENT)
|
||||
return false;
|
||||
|
||||
pid_t pid = fork();
|
||||
@@ -165,3 +168,36 @@ std::string Platform::getOSName()
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string Platform::traceback(const std::string& where, int level, int maxDepth)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "\nC++ stack traceback:";
|
||||
if(!where.empty())
|
||||
ss << "\n\t[C++]: " << where;
|
||||
|
||||
void* buffer[maxDepth + level + 1];
|
||||
int numLevels = backtrace(buffer, maxDepth + level + 1);
|
||||
char **tracebackBuffer = backtrace_symbols(buffer, numLevels);
|
||||
if(tracebackBuffer) {
|
||||
for(int i = 1 + level; i < numLevels; i++) {
|
||||
std::string line = tracebackBuffer[i];
|
||||
if(line.find("__libc_start_main") != std::string::npos)
|
||||
break;
|
||||
std::size_t demanglePos = line.find("(_Z");
|
||||
if(demanglePos != std::string::npos) {
|
||||
demanglePos++;
|
||||
int len = std::min(line.find_first_of("+", demanglePos), line.find_first_of(")", demanglePos)) - demanglePos;
|
||||
std::string funcName = line.substr(demanglePos, len);
|
||||
line.replace(demanglePos, len, stdext::demangle_name(funcName.c_str()));
|
||||
}
|
||||
ss << "\n\t" << line;
|
||||
}
|
||||
free(tracebackBuffer);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -20,6 +20,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(WIN32) && defined(CRASH_HANDLER)
|
||||
|
||||
#include "crashhandler.h"
|
||||
#include <framework/global.h>
|
||||
#include <framework/core/application.h>
|
||||
@@ -156,3 +158,5 @@ void installCrashHandler()
|
||||
{
|
||||
SetUnhandledExceptionFilter(ExceptionHandler);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -20,6 +20,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "platform.h"
|
||||
#include <windows.h>
|
||||
#include <framework/stdext/stdext.h>
|
||||
@@ -411,3 +413,14 @@ std::string Platform::getOSName()
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::string Platform::traceback(const std::string& where, int level, int maxDepth)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "\nat:";
|
||||
ss << "\n\t[C++]: " << where;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -20,33 +20,32 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32window.h"
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
|
||||
#ifndef OPENGL_ES
|
||||
#include <framework/graphics/ogl/graphicscontextwgl.h>
|
||||
#else
|
||||
#include <framework/graphics/ogl/graphicscontextegl.h>
|
||||
#endif
|
||||
|
||||
#define HSB_BIT_SET(p, n) (p[(n)/8] |= (128 >>((n)%8)))
|
||||
|
||||
WIN32Window::WIN32Window()
|
||||
{
|
||||
m_window = 0;
|
||||
m_instance = 0;
|
||||
m_deviceContext = 0;
|
||||
m_cursor = 0;
|
||||
m_minimumSize = Size(600,480);
|
||||
m_size = Size(600,480);
|
||||
m_hidden = true;
|
||||
m_deviceContext = 0;
|
||||
|
||||
#ifndef OPENGL_ES
|
||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextWGL);
|
||||
#ifdef OPENGL_ES
|
||||
m_eglConfig = 0;
|
||||
m_eglContext = 0;
|
||||
m_eglDisplay = 0;
|
||||
m_eglSurface = 0;
|
||||
#else
|
||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextEGL);
|
||||
m_wglContext = 0;
|
||||
#endif
|
||||
|
||||
m_keyMap[VK_ESCAPE] = Fw::KeyEscape;
|
||||
@@ -204,9 +203,30 @@ WIN32Window::WIN32Window()
|
||||
void WIN32Window::init()
|
||||
{
|
||||
m_instance = GetModuleHandle(NULL);
|
||||
|
||||
#ifdef DIRECTX
|
||||
m_d3d = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface
|
||||
|
||||
D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information
|
||||
|
||||
ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear out the struct for use
|
||||
d3dpp.Windowed = TRUE; // program windowed, not fullscreen
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames
|
||||
d3dpp.hDeviceWindow = m_window; // set the window to be used by Direct3D
|
||||
|
||||
// create a device class using this information and information from the d3dpp stuct
|
||||
m_d3d->CreateDevice(D3DADAPTER_DEFAULT,
|
||||
D3DDEVTYPE_HAL,
|
||||
m_window,
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
|
||||
&d3dpp,
|
||||
&m_d3ddev);
|
||||
|
||||
#endif
|
||||
|
||||
internalCreateWindow();
|
||||
m_graphicsContext->create();
|
||||
m_graphicsContext->restore();
|
||||
internalCreateGLContext();
|
||||
internalRestoreGLContext();
|
||||
}
|
||||
|
||||
void WIN32Window::terminate()
|
||||
@@ -221,7 +241,7 @@ void WIN32Window::terminate()
|
||||
DestroyCursor(cursor);
|
||||
m_cursors.clear();
|
||||
|
||||
m_graphicsContext->destroy();
|
||||
internalDestroyGLContext();
|
||||
|
||||
if(m_deviceContext) {
|
||||
if(!ReleaseDC(m_window, m_deviceContext))
|
||||
@@ -298,6 +318,154 @@ void WIN32Window::internalCreateWindow()
|
||||
g_logger.fatal("GetDC failed");
|
||||
}
|
||||
|
||||
void WIN32Window::internalCreateGLContext()
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
m_eglDisplay = eglGetDisplay(m_deviceContext);
|
||||
if(m_eglDisplay == EGL_NO_DISPLAY)
|
||||
g_logger.fatal("EGL not supported");
|
||||
|
||||
if(!eglInitialize(m_eglDisplay, NULL, NULL))
|
||||
g_logger.fatal("Unable to initialize EGL");
|
||||
|
||||
static int configList[] = {
|
||||
#if OPENGL_ES==2
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
#else
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
||||
#endif
|
||||
EGL_RED_SIZE, 4,
|
||||
EGL_GREEN_SIZE, 4,
|
||||
EGL_BLUE_SIZE, 4,
|
||||
EGL_ALPHA_SIZE, 4,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLint numConfig;
|
||||
|
||||
if(!eglGetConfigs(m_eglDisplay, NULL, 0, &numConfig))
|
||||
g_logger.fatal("No valid GL configurations");
|
||||
|
||||
if(!eglChooseConfig(m_eglDisplay, configList, &m_eglConfig, 1, &numConfig))
|
||||
g_logger.fatal("Failed to choose EGL config");
|
||||
|
||||
if(numConfig != 1)
|
||||
g_logger.warning("Didn't got the exact EGL config");
|
||||
|
||||
EGLint contextAtrrList[] = {
|
||||
#if OPENGL_ES==2
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
#else
|
||||
EGL_CONTEXT_CLIENT_VERSION, 1,
|
||||
#endif
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_window, NULL);
|
||||
if(m_eglSurface == EGL_NO_SURFACE)
|
||||
g_logger.fatal(stdext::format("Unable to create EGL surface: %s", eglGetError()));
|
||||
|
||||
m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAtrrList);
|
||||
if(m_eglContext == EGL_NO_CONTEXT )
|
||||
g_logger.fatal(stdext::format("Unable to create EGL context: %s", eglGetError()));
|
||||
|
||||
#else
|
||||
uint pixelFormat;
|
||||
static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR),
|
||||
1,
|
||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
||||
PFD_TYPE_RGBA,
|
||||
32, // Select Our Color Depth
|
||||
8, 0, 8, 0, 8, 0, // Color Bits Ignored
|
||||
8, // Alpha Buffer Bits
|
||||
0, // Shift Bit Ignored
|
||||
0, // No Accumulation Buffer
|
||||
0, 0, 0, 0, // Accumulation Bits Ignored
|
||||
0, // Z-Buffer (Depth Buffer)
|
||||
0, // No Stencil Buffer
|
||||
0, // No Auxiliary Buffer
|
||||
PFD_MAIN_PLANE, // Main Drawing Layer
|
||||
0, // Reserved
|
||||
0, 0, 0 }; // Layer Masks Ignored
|
||||
|
||||
pixelFormat = ChoosePixelFormat(m_deviceContext, &pfd);
|
||||
if(!pixelFormat)
|
||||
g_logger.fatal("Could not find a suitable pixel format");
|
||||
|
||||
if(!SetPixelFormat(m_deviceContext, pixelFormat, &pfd))
|
||||
g_logger.fatal("Could not set the pixel format");
|
||||
|
||||
if(!(m_wglContext = wglCreateContext(m_deviceContext)))
|
||||
g_logger.fatal("Unable to create GL context");
|
||||
#endif
|
||||
}
|
||||
|
||||
void WIN32Window::internalDestroyGLContext()
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
if(m_eglDisplay) {
|
||||
if(m_eglContext) {
|
||||
eglDestroyContext(m_eglDisplay, m_eglContext);
|
||||
m_eglContext = 0;
|
||||
}
|
||||
if(m_eglSurface) {
|
||||
eglDestroySurface(m_eglDisplay, m_eglSurface);
|
||||
m_eglSurface = 0;
|
||||
}
|
||||
eglTerminate(m_eglDisplay);
|
||||
m_eglDisplay = 0;
|
||||
}
|
||||
#else
|
||||
if(m_wglContext) {
|
||||
if(!wglMakeCurrent(NULL, NULL))
|
||||
g_logger.error("Release of dc and rc failed.");
|
||||
if(!wglDeleteContext(m_wglContext))
|
||||
g_logger.error("Release rendering context failed.");
|
||||
m_wglContext = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void WIN32Window::internalRestoreGLContext()
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))
|
||||
g_logger.fatal("Unable to make current EGL context");
|
||||
#else
|
||||
if(!wglMakeCurrent(m_deviceContext, m_wglContext))
|
||||
g_logger.fatal("Unable to make current WGL context");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WIN32Window::isExtensionSupported(const char *ext)
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
//TODO
|
||||
return false;
|
||||
#else
|
||||
typedef const char* (WINAPI * wglGetExtensionsStringProc)();
|
||||
wglGetExtensionsStringProc wglGetExtensionsString = (wglGetExtensionsStringProc)getExtensionProcAddress("wglGetExtensionsStringEXT");
|
||||
if(!wglGetExtensionsString)
|
||||
return false;
|
||||
|
||||
const char *exts = wglGetExtensionsString();
|
||||
if(exts && strstr(exts, ext))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void *WIN32Window::getExtensionProcAddress(const char *ext)
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
//TODO
|
||||
return NULL;
|
||||
#else
|
||||
return (void*)wglGetProcAddress(ext);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WIN32Window::move(const Point& pos)
|
||||
{
|
||||
Rect clientRect(pos, getClientRect().size());
|
||||
@@ -456,6 +624,9 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||
break;
|
||||
}
|
||||
case WM_SYSKEYDOWN: {
|
||||
if(wParam == VK_F4 && m_inputEvent.keyboardModifiers & Fw::KeyboardAltModifier)
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
|
||||
processKeyDown(retranslateVirtualKey(wParam, lParam));
|
||||
break;
|
||||
}
|
||||
@@ -571,8 +742,8 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_visible)
|
||||
m_graphicsContext->restore();
|
||||
if(m_visible && m_deviceContext)
|
||||
internalRestoreGLContext();
|
||||
|
||||
Size size = Size(LOWORD(lParam), HIWORD(lParam));
|
||||
size.setWidth(std::max(std::min(size.width(), 7680), 32));
|
||||
@@ -594,7 +765,11 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||
|
||||
void WIN32Window::swapBuffers()
|
||||
{
|
||||
m_graphicsContext->swapBuffers();
|
||||
#ifdef OPENGL_ES
|
||||
eglSwapBuffers(m_eglDisplay, m_eglSurface);
|
||||
#else
|
||||
SwapBuffers(m_deviceContext);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WIN32Window::showMouse()
|
||||
@@ -690,7 +865,19 @@ void WIN32Window::setFullscreen(bool fullscreen)
|
||||
|
||||
void WIN32Window::setVerticalSync(bool enable)
|
||||
{
|
||||
m_graphicsContext->setVerticalSync(enable);
|
||||
#ifdef OPENGL_ES
|
||||
eglSwapInterval(m_eglDisplay, enable ? 1 : 0);
|
||||
#else
|
||||
if(!isExtensionSupported("WGL_EXT_swap_control"))
|
||||
return;
|
||||
|
||||
typedef BOOL (WINAPI * wglSwapIntervalProc)(int);
|
||||
wglSwapIntervalProc wglSwapInterval = (wglSwapIntervalProc)getExtensionProcAddress("wglSwapIntervalEXT");
|
||||
if(!wglSwapInterval)
|
||||
return;
|
||||
|
||||
wglSwapInterval(enable ? 1 : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WIN32Window::setIcon(const std::string& file)
|
||||
@@ -783,7 +970,11 @@ std::string WIN32Window::getClipboardText()
|
||||
|
||||
std::string WIN32Window::getPlatformType()
|
||||
{
|
||||
return stdext::format("WIN32-%s", m_graphicsContext->getName());
|
||||
#ifndef OPENGL_ES
|
||||
return "WIN32-WGL";
|
||||
#else
|
||||
return "WIN32-EGL";
|
||||
#endif
|
||||
}
|
||||
|
||||
Rect WIN32Window::getClientRect()
|
||||
@@ -831,3 +1022,5 @@ Rect WIN32Window::adjustWindowRect(const Rect& clientRect)
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -24,13 +24,28 @@
|
||||
#define WIN32WINDOW_H
|
||||
|
||||
#include "platformwindow.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef OPENGL_ES
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
|
||||
#ifdef DIRECTX
|
||||
#include <d3d9.h>
|
||||
#endif
|
||||
|
||||
struct WindowProcProxy;
|
||||
|
||||
class WIN32Window : public PlatformWindow
|
||||
{
|
||||
void internalCreateWindow();
|
||||
void internalCreateGLContext();
|
||||
void internalDestroyGLContext();
|
||||
void internalRestoreGLContext();
|
||||
|
||||
void *getExtensionProcAddress(const char *ext);
|
||||
bool isExtensionSupported(const char *ext);
|
||||
|
||||
LRESULT windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
friend class WindowProcProxy;
|
||||
@@ -67,8 +82,6 @@ public:
|
||||
Size getDisplaySize();
|
||||
std::string getClipboardText();
|
||||
std::string getPlatformType();
|
||||
HWND getWindow() { return m_window; }
|
||||
HDC getDisplay() { return m_deviceContext; }
|
||||
|
||||
protected:
|
||||
int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot);
|
||||
@@ -79,14 +92,26 @@ private:
|
||||
Rect adjustWindowRect(const Rect& rect);
|
||||
|
||||
std::vector<HCURSOR> m_cursors;
|
||||
HDC m_deviceContext;
|
||||
HWND m_window;
|
||||
HINSTANCE m_instance;
|
||||
HDC m_deviceContext;
|
||||
HCURSOR m_cursor;
|
||||
HCURSOR m_defaultCursor;
|
||||
bool m_hidden;
|
||||
|
||||
#ifdef DIRECTX
|
||||
LPDIRECT3D9 m_d3d; // the pointer to our Direct3D interface
|
||||
LPDIRECT3DDEVICE9 m_d3ddev; // the pointer to the device class
|
||||
#endif
|
||||
|
||||
#ifdef OPENGL_ES
|
||||
EGLConfig m_eglConfig;
|
||||
EGLContext m_eglContext;
|
||||
EGLDisplay m_eglDisplay;
|
||||
EGLSurface m_eglSurface;
|
||||
#else
|
||||
HGLRC m_wglContext;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern WIN32Window& g_win32Window;
|
||||
|
||||
#endif
|
||||
|
@@ -20,17 +20,13 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
#include "x11window.h"
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef OPENGL_ES
|
||||
#include <framework/graphics/ogl/graphicscontextglx.h>
|
||||
#else
|
||||
#include <framework/graphics/ogl/graphicscontextegl.h>
|
||||
#endif
|
||||
|
||||
#define LSB_BIT_SET(p, n) (p[(n)/8] |= (1 <<((n)%8)))
|
||||
|
||||
X11Window::X11Window()
|
||||
@@ -48,10 +44,15 @@ X11Window::X11Window()
|
||||
m_wmDelete = 0;
|
||||
m_minimumSize = Size(600,480);
|
||||
m_size = Size(600,480);
|
||||
#ifndef OPENGL_ES
|
||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextGLX);
|
||||
|
||||
#ifdef OPENGL_ES
|
||||
m_eglConfig = 0;
|
||||
m_eglContext = 0;
|
||||
m_eglDisplay = 0;
|
||||
m_eglSurface = 0;
|
||||
#else
|
||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextEGL);
|
||||
m_fbConfig = 0;
|
||||
m_glxContext = 0;
|
||||
#endif
|
||||
|
||||
m_keyMap[XK_Escape] = Fw::KeyEscape;
|
||||
@@ -210,7 +211,9 @@ X11Window::X11Window()
|
||||
void X11Window::init()
|
||||
{
|
||||
internalOpenDisplay();
|
||||
m_graphicsContext->create();
|
||||
internalCheckGL();
|
||||
internalChooseGLVisual();
|
||||
internalCreateGLContext();
|
||||
internalCreateWindow();
|
||||
}
|
||||
|
||||
@@ -240,7 +243,7 @@ void X11Window::terminate()
|
||||
m_colormap = 0;
|
||||
}
|
||||
|
||||
m_graphicsContext->destroy();
|
||||
internalDestroyGLContext();
|
||||
|
||||
if(m_visual) {
|
||||
XFree(m_visual);
|
||||
@@ -328,7 +331,7 @@ void X11Window::internalCreateWindow()
|
||||
if(!internalSetupWindowInput())
|
||||
g_logger.warning("Input of special keys may be messed up, because window input initialization failed");
|
||||
|
||||
m_graphicsContext->restore();
|
||||
internalConnectGLContext();
|
||||
}
|
||||
|
||||
bool X11Window::internalSetupWindowInput()
|
||||
@@ -355,6 +358,169 @@ bool X11Window::internalSetupWindowInput()
|
||||
return true;
|
||||
}
|
||||
|
||||
void X11Window::internalCheckGL()
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_display);
|
||||
if(m_eglDisplay == EGL_NO_DISPLAY)
|
||||
g_logger.fatal("EGL not supported");
|
||||
|
||||
if(!eglInitialize(m_eglDisplay, NULL, NULL))
|
||||
g_logger.fatal("Unable to initialize EGL");
|
||||
#else
|
||||
if(!glXQueryExtension(m_display, NULL, NULL))
|
||||
g_logger.fatal("GLX not supported");
|
||||
#endif
|
||||
}
|
||||
|
||||
void X11Window::internalChooseGLVisual()
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
static int attrList[] = {
|
||||
#if OPENGL_ES==2
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
#else
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
||||
#endif
|
||||
EGL_RED_SIZE, 4,
|
||||
EGL_GREEN_SIZE, 4,
|
||||
EGL_BLUE_SIZE, 4,
|
||||
EGL_ALPHA_SIZE, 4,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLint numConfig;
|
||||
XVisualInfo visTemplate;
|
||||
int numVisuals;
|
||||
|
||||
if(!eglChooseConfig(m_eglDisplay, attrList, &m_eglConfig, 1, &numConfig))
|
||||
g_logger.fatal("Failed to choose EGL config");
|
||||
|
||||
if(numConfig != 1)
|
||||
g_logger.warning("Didn't got the exact EGL config");
|
||||
|
||||
EGLint vid;
|
||||
if(!eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_NATIVE_VISUAL_ID, &vid))
|
||||
g_logger.fatal("Unable to get visual EGL visual id");
|
||||
|
||||
memset(&visTemplate, 0, sizeof(visTemplate));
|
||||
visTemplate.visualid = vid;
|
||||
m_visual = XGetVisualInfo(m_display, VisualIDMask, &visTemplate, &numVisuals);
|
||||
if(!m_visual)
|
||||
g_logger.fatal("Couldn't choose RGBA, double buffered visual");
|
||||
|
||||
m_rootWindow = DefaultRootWindow(m_display);
|
||||
#else
|
||||
static int attrList[] = {
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_DOUBLEBUFFER, True,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
None
|
||||
};
|
||||
|
||||
int nelements;
|
||||
m_fbConfig = glXChooseFBConfig(m_display, m_screen, attrList, &nelements);
|
||||
if(!m_fbConfig)
|
||||
g_logger.fatal("Couldn't choose RGBA, double buffered fbconfig");
|
||||
|
||||
m_visual = glXGetVisualFromFBConfig(m_display, *m_fbConfig);
|
||||
if(!m_visual)
|
||||
g_logger.fatal("Couldn't choose RGBA, double buffered visual");
|
||||
|
||||
m_rootWindow = RootWindow(m_display, m_visual->screen);
|
||||
#endif
|
||||
}
|
||||
|
||||
void X11Window::internalCreateGLContext()
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
EGLint attrList[] = {
|
||||
#if OPENGL_ES==2
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
#else
|
||||
EGL_CONTEXT_CLIENT_VERSION, 1,
|
||||
#endif
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, attrList);
|
||||
if(m_eglContext == EGL_NO_CONTEXT )
|
||||
g_logger.fatal(stdext::format("Unable to create EGL context: %s", eglGetError()));
|
||||
#else
|
||||
m_glxContext = glXCreateContext(m_display, m_visual, NULL, True);
|
||||
|
||||
if(!m_glxContext)
|
||||
g_logger.fatal("Unable to create GLX context");
|
||||
|
||||
if(!glXIsDirect(m_display, m_glxContext))
|
||||
g_logger.warning("GL direct rendering is not possible");
|
||||
#endif
|
||||
}
|
||||
|
||||
void X11Window::internalDestroyGLContext()
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
if(m_eglDisplay) {
|
||||
if(m_eglContext) {
|
||||
eglDestroyContext(m_eglDisplay, m_eglContext);
|
||||
m_eglContext = 0;
|
||||
}
|
||||
if(m_eglSurface) {
|
||||
eglDestroySurface(m_eglDisplay, m_eglSurface);
|
||||
m_eglSurface = 0;
|
||||
}
|
||||
eglTerminate(m_eglDisplay);
|
||||
m_eglDisplay = 0;
|
||||
}
|
||||
#else
|
||||
if(m_glxContext) {
|
||||
glXMakeCurrent(m_display, None, NULL);
|
||||
glXDestroyContext(m_display, m_glxContext);
|
||||
m_glxContext = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void X11Window::internalConnectGLContext()
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_window, NULL);
|
||||
if(m_eglSurface == EGL_NO_SURFACE)
|
||||
g_logger.fatal(stdext::format("Unable to create EGL surface: %s", eglGetError()));
|
||||
if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))
|
||||
g_logger.fatal("Unable to connect EGL context into X11 window");
|
||||
#else
|
||||
if(!glXMakeCurrent(m_display, m_window, m_glxContext))
|
||||
g_logger.fatal("Unable to set GLX context on X11 window");
|
||||
#endif
|
||||
}
|
||||
|
||||
void *X11Window::getExtensionProcAddress(const char *ext)
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
//TODO
|
||||
return NULL;
|
||||
#else
|
||||
return (void *)glXGetProcAddressARB((const GLubyte*)ext);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool X11Window::isExtensionSupported(const char *ext)
|
||||
{
|
||||
#ifdef OPENGL_ES
|
||||
//TODO
|
||||
return false;
|
||||
#else
|
||||
const char *exts = glXQueryExtensionsString(m_display, m_screen);
|
||||
if(strstr(exts, ext))
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void X11Window::move(const Point& pos)
|
||||
{
|
||||
m_position = pos;
|
||||
@@ -674,7 +840,11 @@ void X11Window::poll()
|
||||
|
||||
void X11Window::swapBuffers()
|
||||
{
|
||||
m_graphicsContext->swapBuffers();
|
||||
#ifdef OPENGL_ES
|
||||
eglSwapBuffers(m_eglDisplay, m_eglSurface);
|
||||
#else
|
||||
glXSwapBuffers(m_display, m_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
void X11Window::showMouse()
|
||||
@@ -798,7 +968,20 @@ void X11Window::setFullscreen(bool fullscreen)
|
||||
|
||||
void X11Window::setVerticalSync(bool enable)
|
||||
{
|
||||
m_graphicsContext->setVerticalSync(enable);
|
||||
#ifdef OPENGL_ES
|
||||
//TODO
|
||||
#else
|
||||
typedef GLint (*glSwapIntervalProc)(GLint);
|
||||
glSwapIntervalProc glSwapInterval = NULL;
|
||||
|
||||
if(isExtensionSupported("GLX_MESA_swap_control"))
|
||||
glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalMESA");
|
||||
else if(isExtensionSupported("GLX_SGI_swap_control"))
|
||||
glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalSGI");
|
||||
|
||||
if(glSwapInterval)
|
||||
glSwapInterval(enable ? 1 : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void X11Window::setIcon(const std::string& file)
|
||||
@@ -886,5 +1069,11 @@ std::string X11Window::getClipboardText()
|
||||
|
||||
std::string X11Window::getPlatformType()
|
||||
{
|
||||
return stdext::format("X11-%s", m_graphicsContext->getName());
|
||||
#ifndef OPENGL_ES
|
||||
return "X11-GLX";
|
||||
#else
|
||||
return "X11-EGL";
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -28,9 +28,12 @@
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
typedef Window WindowType;
|
||||
#ifdef OPENGL_ES
|
||||
#include <EGL/egl.h>
|
||||
#else
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
|
||||
class X11Window : public PlatformWindow
|
||||
{
|
||||
@@ -38,6 +41,15 @@ class X11Window : public PlatformWindow
|
||||
void internalCreateWindow();
|
||||
bool internalSetupWindowInput();
|
||||
|
||||
void internalCheckGL();
|
||||
void internalChooseGLVisual();
|
||||
void internalCreateGLContext();
|
||||
void internalDestroyGLContext();
|
||||
void internalConnectGLContext();
|
||||
|
||||
void *getExtensionProcAddress(const char *ext);
|
||||
bool isExtensionSupported(const char *ext);
|
||||
|
||||
public:
|
||||
X11Window();
|
||||
|
||||
@@ -63,16 +75,10 @@ public:
|
||||
void setVerticalSync(bool enable);
|
||||
void setIcon(const std::string& file);
|
||||
void setClipboardText(const std::string& text);
|
||||
void setVisual(XVisualInfo *visual) { m_visual = visual; }
|
||||
void setRootWindow(const Window& window) { m_rootWindow = window; }
|
||||
|
||||
Size getDisplaySize();
|
||||
std::string getClipboardText();
|
||||
std::string getPlatformType();
|
||||
Window getWindow() { return m_window; }
|
||||
Display *getDisplay() { return m_display; }
|
||||
int getScreen() { return m_screen; }
|
||||
XVisualInfo *getVisual() { return m_visual; }
|
||||
|
||||
protected:
|
||||
int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot);
|
||||
@@ -91,9 +97,17 @@ private:
|
||||
int m_screen;
|
||||
Atom m_wmDelete;
|
||||
std::string m_clipboardText;
|
||||
};
|
||||
|
||||
extern X11Window& g_x11Window;
|
||||
#ifndef OPENGL_ES
|
||||
GLXContext m_glxContext;
|
||||
GLXFBConfig *m_fbConfig;
|
||||
#else
|
||||
EGLConfig m_eglConfig;
|
||||
EGLContext m_eglContext;
|
||||
EGLDisplay m_eglDisplay;
|
||||
EGLSurface m_eglSurface;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user