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*
|
build*
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
CMakeFiles
|
CMakeFiles
|
||||||
@@ -39,3 +38,4 @@ tags
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
.directory
|
.directory
|
||||||
src/framework/graphics/dx/
|
src/framework/graphics/dx/
|
||||||
|
modules/.project/modules.sublime-workspace
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
project(otclient)
|
project(otclient)
|
||||||
|
|
||||||
set(VERSION "0.6.2")
|
set(VERSION "0.6.3")
|
||||||
|
|
||||||
option(FRAMEWORK_SOUND "Use SOUND " ON)
|
option(FRAMEWORK_SOUND "Use SOUND " ON)
|
||||||
option(FRAMEWORK_GRAPHICS "Use GRAPHICS " ON)
|
option(FRAMEWORK_GRAPHICS "Use GRAPHICS " ON)
|
||||||
|
@@ -11,3 +11,9 @@ HorizontalList < UIScrollArea
|
|||||||
border-width: 1
|
border-width: 1
|
||||||
border-color: #1d222b
|
border-color: #1d222b
|
||||||
background-color: #222833
|
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
|
-- mods 1000-9999
|
||||||
g_modules.autoLoadModules(9999)
|
g_modules.autoLoadModules(9999)
|
||||||
|
|
||||||
local script = '/' .. g_app.getCompactName() .. 'rc.lua'
|
local script = '/' .. g_app.getCompactName() .. 'rc'
|
||||||
|
|
||||||
if g_resources.fileExists(script) then
|
if g_resources.fileExists(script) then
|
||||||
dofile(script)
|
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 musicFilename = "/sounds/startup"
|
||||||
local musicChannel = nil
|
local musicChannel = g_sounds.getChannel(1)
|
||||||
|
|
||||||
function setMusic(filename)
|
function setMusic(filename)
|
||||||
musicFilename = filename
|
musicFilename = filename
|
||||||
@@ -57,14 +57,11 @@ function init()
|
|||||||
onExit = exit })
|
onExit = exit })
|
||||||
|
|
||||||
g_window.setMinimumSize({ width = 600, height = 480 })
|
g_window.setMinimumSize({ width = 600, height = 480 })
|
||||||
|
|
||||||
musicChannel = g_sounds.getChannel(1)
|
|
||||||
g_sounds.preload(musicFilename)
|
g_sounds.preload(musicFilename)
|
||||||
|
|
||||||
-- initialize in fullscreen mode on mobile devices
|
-- initialize in fullscreen mode on mobile devices
|
||||||
if g_app.getOs() == "android" then
|
if g_window.getPlatformType() == "X11-EGL" then
|
||||||
g_window.maximize()
|
g_window.setFullscreen(true)
|
||||||
--g_window.setFullscreen(true)
|
|
||||||
else
|
else
|
||||||
-- window size
|
-- window size
|
||||||
local size = { width = 800, height = 600 }
|
local size = { width = 800, height = 600 }
|
||||||
@@ -107,11 +104,6 @@ function terminate()
|
|||||||
g_settings.set('window-size', g_window.getUnmaximizedSize())
|
g_settings.set('window-size', g_window.getUnmaximizedSize())
|
||||||
g_settings.set('window-pos', g_window.getUnmaximizedPos())
|
g_settings.set('window-pos', g_window.getUnmaximizedPos())
|
||||||
g_settings.set('window-maximized', g_window.isMaximized())
|
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
|
end
|
||||||
|
|
||||||
function exit()
|
function exit()
|
||||||
|
@@ -19,4 +19,4 @@ Module
|
|||||||
- client_terminal
|
- client_terminal
|
||||||
- client_modulemanager
|
- client_modulemanager
|
||||||
- client_serverlist
|
- client_serverlist
|
||||||
//- client_stats
|
- client_stats
|
||||||
|
@@ -6,7 +6,7 @@ local enterGame
|
|||||||
local motdWindow
|
local motdWindow
|
||||||
local motdButton
|
local motdButton
|
||||||
local enterGameButton
|
local enterGameButton
|
||||||
local protocolBox
|
local clientBox
|
||||||
local protocolLogin
|
local protocolLogin
|
||||||
local motdEnabled = true
|
local motdEnabled = true
|
||||||
|
|
||||||
@@ -73,11 +73,6 @@ local function onCharacterList(protocol, characters, account, otui)
|
|||||||
end
|
end
|
||||||
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)
|
local function onUpdateNeeded(protocol, signature)
|
||||||
loadBox:destroy()
|
loadBox:destroy()
|
||||||
loadBox = nil
|
loadBox = nil
|
||||||
@@ -109,7 +104,8 @@ function EnterGame.init()
|
|||||||
local host = g_settings.get('host')
|
local host = g_settings.get('host')
|
||||||
local port = g_settings.get('port')
|
local port = g_settings.get('port')
|
||||||
local autologin = g_settings.getBoolean('autologin')
|
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
|
if port == nil or port == 0 then port = 7171 end
|
||||||
|
|
||||||
@@ -120,11 +116,11 @@ function EnterGame.init()
|
|||||||
enterGame:getChildById('serverPortTextEdit'):setText(port)
|
enterGame:getChildById('serverPortTextEdit'):setText(port)
|
||||||
enterGame:getChildById('autoLoginBox'):setChecked(autologin)
|
enterGame:getChildById('autoLoginBox'):setChecked(autologin)
|
||||||
|
|
||||||
protocolBox = enterGame:getChildById('protocolComboBox')
|
clientBox = enterGame:getChildById('clientComboBox')
|
||||||
protocolBox.onOptionChange = onChangeProtocol
|
for _, proto in pairs(g_game.getSupportedClients()) do
|
||||||
if protocolVersion then
|
clientBox:addOption(proto)
|
||||||
protocolBox:setCurrentOption(protocolVersion)
|
|
||||||
end
|
end
|
||||||
|
clientBox:setCurrentOption(clientVersion)
|
||||||
|
|
||||||
enterGame:hide()
|
enterGame:hide()
|
||||||
|
|
||||||
@@ -154,7 +150,7 @@ function EnterGame.terminate()
|
|||||||
enterGame = nil
|
enterGame = nil
|
||||||
enterGameButton:destroy()
|
enterGameButton:destroy()
|
||||||
enterGameButton = nil
|
enterGameButton = nil
|
||||||
protocolBox = nil
|
clientBox = nil
|
||||||
if motdWindow then
|
if motdWindow then
|
||||||
motdWindow:destroy()
|
motdWindow:destroy()
|
||||||
motdWindow = nil
|
motdWindow = nil
|
||||||
@@ -218,8 +214,7 @@ function EnterGame.doLogin()
|
|||||||
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
|
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
|
||||||
G.host = enterGame:getChildById('serverHostTextEdit'):getText()
|
G.host = enterGame:getChildById('serverHostTextEdit'):getText()
|
||||||
G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
|
G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
|
||||||
local protocolVersion = tonumber(protocolBox:getText())
|
local clientVersion = tonumber(clientBox:getText())
|
||||||
local clientVersions = g_game.getSupportedClients(protocolVersion)
|
|
||||||
EnterGame.hide()
|
EnterGame.hide()
|
||||||
|
|
||||||
if g_game.isOnline() then
|
if g_game.isOnline() then
|
||||||
@@ -230,6 +225,7 @@ function EnterGame.doLogin()
|
|||||||
|
|
||||||
g_settings.set('host', G.host)
|
g_settings.set('host', G.host)
|
||||||
g_settings.set('port', G.port)
|
g_settings.set('port', G.port)
|
||||||
|
g_settings.set('client-version', clientVersion)
|
||||||
|
|
||||||
protocolLogin = ProtocolLogin.create()
|
protocolLogin = ProtocolLogin.create()
|
||||||
protocolLogin.onLoginError = onError
|
protocolLogin.onLoginError = onError
|
||||||
@@ -245,10 +241,8 @@ function EnterGame.doLogin()
|
|||||||
end })
|
end })
|
||||||
|
|
||||||
g_game.chooseRsa(G.host)
|
g_game.chooseRsa(G.host)
|
||||||
g_game.setProtocolVersion(protocolVersion)
|
g_game.setClientVersion(clientVersion)
|
||||||
if #clientVersions > 0 then
|
g_game.setProtocolVersion(g_game.getProtocolVersionForClient(clientVersion))
|
||||||
g_game.setClientVersion(clientVersions[#clientVersions])
|
|
||||||
end
|
|
||||||
|
|
||||||
if modules.game_things.isLoaded() then
|
if modules.game_things.isLoaded() then
|
||||||
protocolLogin:login(G.host, G.port, G.account, G.password)
|
protocolLogin:login(G.host, G.port, G.account, G.password)
|
||||||
@@ -269,14 +263,14 @@ end
|
|||||||
function EnterGame.setDefaultServer(host, port, protocol)
|
function EnterGame.setDefaultServer(host, port, protocol)
|
||||||
local hostTextEdit = enterGame:getChildById('serverHostTextEdit')
|
local hostTextEdit = enterGame:getChildById('serverHostTextEdit')
|
||||||
local portTextEdit = enterGame:getChildById('serverPortTextEdit')
|
local portTextEdit = enterGame:getChildById('serverPortTextEdit')
|
||||||
local protocolLabel = enterGame:getChildById('protocolLabel')
|
local clientLabel = enterGame:getChildById('clientLabel')
|
||||||
local accountTextEdit = enterGame:getChildById('accountNameTextEdit')
|
local accountTextEdit = enterGame:getChildById('accountNameTextEdit')
|
||||||
local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit')
|
local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit')
|
||||||
|
|
||||||
if hostTextEdit:getText() ~= host then
|
if hostTextEdit:getText() ~= host then
|
||||||
hostTextEdit:setText(host)
|
hostTextEdit:setText(host)
|
||||||
portTextEdit:setText(port)
|
portTextEdit:setText(port)
|
||||||
protocolBox:setCurrentOption(protocol)
|
clientBox:setCurrentOption(protocol)
|
||||||
accountTextEdit:setText('')
|
accountTextEdit:setText('')
|
||||||
passwordTextEdit:setText('')
|
passwordTextEdit:setText('')
|
||||||
end
|
end
|
||||||
@@ -292,9 +286,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
|
|||||||
portTextEdit:setVisible(false)
|
portTextEdit:setVisible(false)
|
||||||
portTextEdit:setHeight(0)
|
portTextEdit:setHeight(0)
|
||||||
|
|
||||||
protocolBox:setCurrentOption(protocol)
|
clientBox:setCurrentOption(protocol)
|
||||||
protocolBox:setVisible(false)
|
clientBox:setVisible(false)
|
||||||
protocolBox:setHeight(0)
|
clientBox:setHeight(0)
|
||||||
|
|
||||||
local serverLabel = enterGame:getChildById('serverLabel')
|
local serverLabel = enterGame:getChildById('serverLabel')
|
||||||
serverLabel:setVisible(false)
|
serverLabel:setVisible(false)
|
||||||
@@ -302,9 +296,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
|
|||||||
local portLabel = enterGame:getChildById('portLabel')
|
local portLabel = enterGame:getChildById('portLabel')
|
||||||
portLabel:setVisible(false)
|
portLabel:setVisible(false)
|
||||||
portLabel:setHeight(0)
|
portLabel:setHeight(0)
|
||||||
local protocolLabel = enterGame:getChildById('protocolLabel')
|
local clientLabel = enterGame:getChildById('clientLabel')
|
||||||
protocolLabel:setVisible(false)
|
clientLabel:setVisible(false)
|
||||||
protocolLabel:setHeight(0)
|
clientLabel:setHeight(0)
|
||||||
|
|
||||||
local serverListButton = enterGame:getChildById('serverListButton')
|
local serverListButton = enterGame:getChildById('serverListButton')
|
||||||
serverListButton:setVisible(false)
|
serverListButton:setVisible(false)
|
||||||
|
@@ -68,7 +68,7 @@ EnterGameWindow
|
|||||||
|
|
||||||
TextEdit
|
TextEdit
|
||||||
id: serverHostTextEdit
|
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.left: parent.left
|
||||||
anchors.right: serverListButton.left
|
anchors.right: serverListButton.left
|
||||||
anchors.top: serverLabel.bottom
|
anchors.top: serverLabel.bottom
|
||||||
@@ -76,8 +76,8 @@ EnterGameWindow
|
|||||||
margin-right: 4
|
margin-right: 4
|
||||||
|
|
||||||
MenuLabel
|
MenuLabel
|
||||||
id: protocolLabel
|
id: clientLabel
|
||||||
!text: tr('Protocol')
|
!text: tr('Client Version')
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: serverHostTextEdit.bottom
|
anchors.top: serverHostTextEdit.bottom
|
||||||
text-auto-resize: true
|
text-auto-resize: true
|
||||||
@@ -85,17 +85,13 @@ EnterGameWindow
|
|||||||
margin-top: 8
|
margin-top: 8
|
||||||
|
|
||||||
ComboBox
|
ComboBox
|
||||||
id: protocolComboBox
|
id: clientComboBox
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.horizontalCenter
|
anchors.right: parent.horizontalCenter
|
||||||
anchors.top: protocolLabel.bottom
|
anchors.top: clientLabel.bottom
|
||||||
margin-top: 2
|
margin-top: 2
|
||||||
margin-right: 3
|
margin-right: 3
|
||||||
width: 90
|
width: 90
|
||||||
@onSetup: |
|
|
||||||
for _, proto in pairs(g_game.getSupportedProtocols()) do
|
|
||||||
self:addOption(proto)
|
|
||||||
end
|
|
||||||
|
|
||||||
MenuLabel
|
MenuLabel
|
||||||
id: portLabel
|
id: portLabel
|
||||||
@@ -110,7 +106,7 @@ EnterGameWindow
|
|||||||
text: 7171
|
text: 7171
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.left: parent.horizontalCenter
|
anchors.left: parent.horizontalCenter
|
||||||
anchors.top: protocolComboBox.top
|
anchors.top: clientComboBox.top
|
||||||
margin-left: 3
|
margin-left: 3
|
||||||
|
|
||||||
CheckBox
|
CheckBox
|
||||||
|
@@ -137,7 +137,7 @@ function unloadCurrentModule()
|
|||||||
local module = g_modules.getModule(focusedChild:getText())
|
local module = g_modules.getModule(focusedChild:getText())
|
||||||
if module then
|
if module then
|
||||||
module:unload()
|
module:unload()
|
||||||
if ModuleManager == nil then return end
|
if modules.client_modulemanager == nil then return end
|
||||||
updateModuleInfo(module:getName())
|
updateModuleInfo(module:getName())
|
||||||
refreshLoadedModules()
|
refreshLoadedModules()
|
||||||
end
|
end
|
||||||
|
@@ -49,7 +49,7 @@ MainWindow
|
|||||||
anchors.left: protocolLabel.left
|
anchors.left: protocolLabel.left
|
||||||
anchors.right: port.right
|
anchors.right: port.right
|
||||||
@onSetup: |
|
@onSetup: |
|
||||||
for _, proto in pairs(g_game.getSupportedProtocols()) do
|
for _, proto in pairs(g_game.getSupportedClients()) do
|
||||||
self:addOption(proto)
|
self:addOption(proto)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -257,11 +257,14 @@ function flushLines()
|
|||||||
for _,line in pairs(cachedLines) do
|
for _,line in pairs(cachedLines) do
|
||||||
-- delete old lines if needed
|
-- delete old lines if needed
|
||||||
if numLines > MaxLogLines then
|
if numLines > MaxLogLines then
|
||||||
local len = #terminalBuffer:getChildByIndex(1):getText()
|
local firstChild = terminalBuffer:getChildByIndex(1)
|
||||||
terminalBuffer:getChildByIndex(1):destroy()
|
if firstChild then
|
||||||
|
local len = #firstChild:getText()
|
||||||
|
firstChild:destroy()
|
||||||
table.remove(allLines, 1)
|
table.remove(allLines, 1)
|
||||||
fulltext = string.sub(fulltext, len)
|
fulltext = string.sub(fulltext, len)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local label = g_ui.createWidget('TerminalLabel', terminalBuffer)
|
local label = g_ui.createWidget('TerminalLabel', terminalBuffer)
|
||||||
label:setId('terminalLabel' .. numLines)
|
label:setId('terminalLabel' .. numLines)
|
||||||
@@ -285,6 +288,7 @@ function addLine(text, color)
|
|||||||
flushEvent = scheduleEvent(flushLines, 10)
|
flushEvent = scheduleEvent(flushLines, 10)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
text = string.gsub(text, '\t', ' ')
|
||||||
table.insert(cachedLines, {text=text, color=color})
|
table.insert(cachedLines, {text=text, color=color})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -20,8 +20,8 @@ function string:starts(start)
|
|||||||
return string.sub(self, 1, #start) == start
|
return string.sub(self, 1, #start) == start
|
||||||
end
|
end
|
||||||
|
|
||||||
function string.ends(s, test)
|
function string:ends(test)
|
||||||
return test =='' or string.sub(s,-string.len(test)) == test
|
return test =='' or string.sub(self,-string.len(test)) == test
|
||||||
end
|
end
|
||||||
|
|
||||||
function string:trim()
|
function string:trim()
|
||||||
|
@@ -110,8 +110,10 @@ function UITabBar:selectTab(tab)
|
|||||||
tab:setOn(false)
|
tab:setOn(false)
|
||||||
|
|
||||||
local parent = tab:getParent()
|
local parent = tab:getParent()
|
||||||
|
if parent then
|
||||||
parent:focusChild(tab, MouseFocusReason)
|
parent:focusChild(tab, MouseFocusReason)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function UITabBar:selectNextTab()
|
function UITabBar:selectNextTab()
|
||||||
if self.currentTab == nil then return end
|
if self.currentTab == nil then return end
|
||||||
|
@@ -1,11 +1,16 @@
|
|||||||
battleWindow = nil
|
battleWindow = nil
|
||||||
battleButton = nil
|
battleButton = nil
|
||||||
battlePanel = nil
|
battlePanel = nil
|
||||||
|
filterPanel = nil
|
||||||
|
toggleFilterButton = nil
|
||||||
lastBattleButtonSwitched = nil
|
lastBattleButtonSwitched = nil
|
||||||
battleButtonsByCreaturesList = {}
|
battleButtonsByCreaturesList = {}
|
||||||
|
creatureAgeList = {}
|
||||||
|
|
||||||
mouseWidget = nil
|
mouseWidget = nil
|
||||||
|
|
||||||
|
sortTypeBox = nil
|
||||||
|
sortOrderBox = nil
|
||||||
hidePlayersButton = nil
|
hidePlayersButton = nil
|
||||||
hideNPCsButton = nil
|
hideNPCsButton = nil
|
||||||
hideMonstersButton = nil
|
hideMonstersButton = nil
|
||||||
@@ -25,6 +30,15 @@ function init()
|
|||||||
|
|
||||||
battlePanel = battleWindow:recursiveGetChildById('battlePanel')
|
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')
|
hidePlayersButton = battleWindow:recursiveGetChildById('hidePlayers')
|
||||||
hideNPCsButton = battleWindow:recursiveGetChildById('hideNPCs')
|
hideNPCsButton = battleWindow:recursiveGetChildById('hideNPCs')
|
||||||
hideMonstersButton = battleWindow:recursiveGetChildById('hideMonsters')
|
hideMonstersButton = battleWindow:recursiveGetChildById('hideMonsters')
|
||||||
@@ -38,6 +52,18 @@ function init()
|
|||||||
|
|
||||||
battleWindow:setContentMinimumHeight(80)
|
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, {
|
connect(Creature, {
|
||||||
onSkullChange = updateCreatureSkull,
|
onSkullChange = updateCreatureSkull,
|
||||||
onEmblemChange = updateCreatureEmblem,
|
onEmblemChange = updateCreatureEmblem,
|
||||||
@@ -48,6 +74,10 @@ function init()
|
|||||||
onDisappear = onCreatureDisappear
|
onDisappear = onCreatureDisappear
|
||||||
})
|
})
|
||||||
|
|
||||||
|
connect(LocalPlayer, {
|
||||||
|
onPositionChange = onCreaturePositionChange
|
||||||
|
})
|
||||||
|
|
||||||
connect(g_game, {
|
connect(g_game, {
|
||||||
onAttackingCreatureChange = onAttack,
|
onAttackingCreatureChange = onAttack,
|
||||||
onFollowingCreatureChange = onFollow,
|
onFollowingCreatureChange = onFollow,
|
||||||
@@ -75,6 +105,10 @@ function terminate()
|
|||||||
onDisappear = onCreatureDisappear
|
onDisappear = onCreatureDisappear
|
||||||
})
|
})
|
||||||
|
|
||||||
|
disconnect(LocalPlayer, {
|
||||||
|
onPositionChange = onCreaturePositionChange
|
||||||
|
})
|
||||||
|
|
||||||
disconnect(g_game, {
|
disconnect(g_game, {
|
||||||
onAttackingCreatureChange = onAttack,
|
onAttackingCreatureChange = onAttack,
|
||||||
onFollowingCreatureChange = onFollow,
|
onFollowingCreatureChange = onFollow,
|
||||||
@@ -96,6 +130,93 @@ function onMiniWindowClose()
|
|||||||
battleButton:setOn(false)
|
battleButton:setOn(false)
|
||||||
end
|
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()
|
function checkCreatures()
|
||||||
removeAllCreatures()
|
removeAllCreatures()
|
||||||
|
|
||||||
@@ -151,15 +272,42 @@ end
|
|||||||
function onCreatureHealthPercentChange(creature, health)
|
function onCreatureHealthPercentChange(creature, health)
|
||||||
local battleButton = battleButtonsByCreaturesList[creature:getId()]
|
local battleButton = battleButtonsByCreaturesList[creature:getId()]
|
||||||
if battleButton then
|
if battleButton then
|
||||||
|
if getSortType() == 'health' then
|
||||||
|
removeCreature(creature)
|
||||||
|
addCreature(creature)
|
||||||
|
return
|
||||||
|
end
|
||||||
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
||||||
end
|
end
|
||||||
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)
|
function onCreaturePositionChange(creature, newPos, oldPos)
|
||||||
if creature:isLocalPlayer() then
|
if creature:isLocalPlayer() then
|
||||||
if oldPos and newPos and newPos.z ~= oldPos.z then
|
if oldPos and newPos and newPos.z ~= oldPos.z then
|
||||||
checkCreatures()
|
checkCreatures()
|
||||||
else
|
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
|
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
|
||||||
addCreature(creatureButton.creature)
|
addCreature(creatureButton.creature)
|
||||||
end
|
end
|
||||||
@@ -170,6 +318,9 @@ function onCreaturePositionChange(creature, newPos, oldPos)
|
|||||||
if has and not fit then
|
if has and not fit then
|
||||||
removeCreature(creature)
|
removeCreature(creature)
|
||||||
elseif fit then
|
elseif fit then
|
||||||
|
if has and getSortType() == 'distance' then
|
||||||
|
removeCreature(creature)
|
||||||
|
end
|
||||||
addCreature(creature)
|
addCreature(creature)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -201,8 +352,13 @@ function addCreature(creature)
|
|||||||
local creatureId = creature:getId()
|
local creatureId = creature:getId()
|
||||||
local battleButton = battleButtonsByCreaturesList[creatureId]
|
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
|
if not battleButton then
|
||||||
battleButton = g_ui.createWidget('BattleButton', battlePanel)
|
battleButton = g_ui.createWidget('BattleButton')
|
||||||
battleButton:setup(creature)
|
battleButton:setup(creature)
|
||||||
|
|
||||||
battleButton.onHoverChange = onBattleButtonHoverChange
|
battleButton.onHoverChange = onBattleButtonHoverChange
|
||||||
@@ -217,6 +373,77 @@ function addCreature(creature)
|
|||||||
if creature == g_game.getFollowingCreature() then
|
if creature == g_game.getFollowingCreature() then
|
||||||
onFollow(creature)
|
onFollow(creature)
|
||||||
end
|
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
|
else
|
||||||
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
||||||
end
|
end
|
||||||
@@ -226,6 +453,7 @@ function addCreature(creature)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function removeAllCreatures()
|
function removeAllCreatures()
|
||||||
|
creatureAgeList = {}
|
||||||
for i, v in pairs(battleButtonsByCreaturesList) do
|
for i, v in pairs(battleButtonsByCreaturesList) do
|
||||||
removeCreature(v.creature)
|
removeCreature(v.creature)
|
||||||
end
|
end
|
||||||
|
@@ -45,11 +45,12 @@ MiniWindow
|
|||||||
&save: true
|
&save: true
|
||||||
|
|
||||||
Panel
|
Panel
|
||||||
|
id: filterPanel
|
||||||
margin-top: 26
|
margin-top: 26
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: miniwindowScrollBar.left
|
anchors.right: miniwindowScrollBar.left
|
||||||
height: 20
|
height: 45
|
||||||
|
|
||||||
Panel
|
Panel
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
@@ -85,16 +86,56 @@ MiniWindow
|
|||||||
!tooltip: tr('Hide party members')
|
!tooltip: tr('Hide party members')
|
||||||
@onCheckChange: modules.game_battle.checkCreatures()
|
@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.top: prev.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: miniwindowScrollBar.left
|
anchors.right: miniwindowScrollBar.left
|
||||||
|
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-right: 1
|
||||||
margin-top: 4
|
margin-top: 11
|
||||||
|
|
||||||
MiniWindowContents
|
MiniWindowContents
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
margin-top: 0
|
margin-top: 6
|
||||||
|
|
||||||
Panel
|
Panel
|
||||||
id: battlePanel
|
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
|
consoleTextEdit = nil
|
||||||
channels = nil
|
channels = nil
|
||||||
channelsWindow = nil
|
channelsWindow = nil
|
||||||
ignoreWindow = nil
|
communicationWindow = nil
|
||||||
ownPrivateName = nil
|
ownPrivateName = nil
|
||||||
messageHistory = {}
|
messageHistory = {}
|
||||||
currentMessageIndex = 0
|
currentMessageIndex = 0
|
||||||
@@ -74,10 +74,14 @@ violationReportTab = nil
|
|||||||
ignoredChannels = {}
|
ignoredChannels = {}
|
||||||
filters = {}
|
filters = {}
|
||||||
|
|
||||||
local ignoreSettings = {
|
local communicationSettings = {
|
||||||
|
useIgnoreList = true,
|
||||||
|
useWhiteList = true,
|
||||||
privateMessages = false,
|
privateMessages = false,
|
||||||
yelling = false,
|
yelling = false,
|
||||||
players = {}
|
allowVIPs = false,
|
||||||
|
ignoredPlayers = {},
|
||||||
|
whitelistedPlayers = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function init()
|
function init()
|
||||||
@@ -140,9 +144,58 @@ function init()
|
|||||||
g_keyboard.bindKeyDown('Ctrl+E', removeCurrentTab)
|
g_keyboard.bindKeyDown('Ctrl+E', removeCurrentTab)
|
||||||
g_keyboard.bindKeyDown('Ctrl+H', openHelp)
|
g_keyboard.bindKeyDown('Ctrl+H', openHelp)
|
||||||
|
|
||||||
|
consoleToggleChat = consolePanel:getChildById('toggleChat')
|
||||||
load()
|
load()
|
||||||
end
|
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()
|
function terminate()
|
||||||
save()
|
save()
|
||||||
disconnect(g_game, {
|
disconnect(g_game, {
|
||||||
@@ -166,14 +219,14 @@ function terminate()
|
|||||||
g_keyboard.unbindKeyDown('Ctrl+E')
|
g_keyboard.unbindKeyDown('Ctrl+E')
|
||||||
g_keyboard.unbindKeyDown('Ctrl+H')
|
g_keyboard.unbindKeyDown('Ctrl+H')
|
||||||
|
|
||||||
saveIgnoreSettings()
|
saveCommunicationSettings()
|
||||||
|
|
||||||
if channelsWindow then
|
if channelsWindow then
|
||||||
channelsWindow:destroy()
|
channelsWindow:destroy()
|
||||||
end
|
end
|
||||||
|
|
||||||
if ignoreWindow then
|
if communicationWindow then
|
||||||
ignoreWindow:destroy()
|
communicationWindow:destroy()
|
||||||
end
|
end
|
||||||
|
|
||||||
if violationWindow then
|
if violationWindow then
|
||||||
@@ -197,7 +250,7 @@ function load()
|
|||||||
if settings then
|
if settings then
|
||||||
messageHistory = settings.messageHistory or {}
|
messageHistory = settings.messageHistory or {}
|
||||||
end
|
end
|
||||||
loadIgnoreSettings()
|
loadCommunicationSettings()
|
||||||
end
|
end
|
||||||
|
|
||||||
function onTabChange(tabBar, tab)
|
function onTabChange(tabBar, tab)
|
||||||
@@ -466,7 +519,7 @@ function addTabText(text, speaktype, tab, creatureName)
|
|||||||
-- Remove the curly braces
|
-- Remove the curly braces
|
||||||
for i = 1, #highlightData / 3 do
|
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] }
|
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
|
-- Recalculate positions as braces are removed
|
||||||
highlightData[(i-1)*3+1] = dataBlock._start - ((i-1) * 2)
|
highlightData[(i-1)*3+1] = dataBlock._start - ((i-1) * 2)
|
||||||
@@ -779,7 +832,11 @@ function onTalk(name, level, mode, message, channelId, creaturePos)
|
|||||||
return
|
return
|
||||||
end
|
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
|
if mode == MessageModes.Yell and isIgnoringYelling() then
|
||||||
return
|
return
|
||||||
elseif speaktype.private and isIgnoringPrivate() and mode ~= MessageModes.NpcFrom then
|
elseif speaktype.private and isIgnoringPrivate() and mode ~= MessageModes.NpcFrom then
|
||||||
@@ -957,107 +1014,221 @@ function onChannelList(channelList)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function loadIgnoreSettings()
|
function loadCommunicationSettings()
|
||||||
|
communicationSettings.whitelistedPlayers = {}
|
||||||
|
communicationSettings.ignoredPlayers = {}
|
||||||
|
|
||||||
local ignoreNode = g_settings.getNode('IgnorePlayers')
|
local ignoreNode = g_settings.getNode('IgnorePlayers')
|
||||||
if ignoreNode then
|
if ignoreNode then
|
||||||
for i = 1, #ignoreNode do
|
for i = 1, #ignoreNode do
|
||||||
table.insert(ignoreSettings.players, ignoreNode[i])
|
table.insert(communicationSettings.ignoredPlayers, ignoreNode[i])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ignoreSettings.privateMessages = g_settings.getBoolean('IgnorePrivateMessages')
|
|
||||||
ignoreSettings.yelling = g_settings.getBoolean('IgnoreYelling')
|
|
||||||
end
|
|
||||||
|
|
||||||
function saveIgnoreSettings()
|
local whitelistNode = g_settings.getNode('WhitelistedPlayers')
|
||||||
local tmpSettings = {}
|
if whitelistNode then
|
||||||
for i = 1, #ignoreSettings.players do
|
for i = 1, #whitelistNode do
|
||||||
table.insert(tmpSettings, ignoreSettings.players[i])
|
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)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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)
|
function isIgnored(name)
|
||||||
return table.find(ignoreSettings.players, name, true)
|
return table.find(communicationSettings.ignoredPlayers, name, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
function addIgnoredPlayer(name)
|
function addIgnoredPlayer(name)
|
||||||
if not isIgnored(name) then
|
if isIgnored(name) then return end
|
||||||
table.insert(ignoreSettings.players, name)
|
table.insert(communicationSettings.ignoredPlayers, name)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function removeIgnoredPlayer(name)
|
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
|
end
|
||||||
|
|
||||||
function isIgnoringPrivate()
|
function isIgnoringPrivate()
|
||||||
return ignoreSettings.privateMessages
|
return communicationSettings.privateMessages
|
||||||
end
|
end
|
||||||
|
|
||||||
function isIgnoringYelling()
|
function isIgnoringYelling()
|
||||||
return ignoreSettings.yelling
|
return communicationSettings.yelling
|
||||||
|
end
|
||||||
|
|
||||||
|
function isAllowingVIPs()
|
||||||
|
return communicationSettings.allowVIPs
|
||||||
end
|
end
|
||||||
|
|
||||||
function onClickIgnoreButton()
|
function onClickIgnoreButton()
|
||||||
if ignoreWindow then return end
|
if communicationWindow then return end
|
||||||
ignoreWindow = g_ui.displayUI('ignorewindow')
|
communicationWindow = g_ui.displayUI('communicationwindow')
|
||||||
local ignoreListPanel = ignoreWindow:getChildById('ignoreList')
|
local ignoreListPanel = communicationWindow:getChildById('ignoreList')
|
||||||
ignoreWindow.onDestroy = function() ignoreWindow = nil end
|
local whiteListPanel = communicationWindow:getChildById('whiteList')
|
||||||
|
communicationWindow.onDestroy = function() communicationWindow = nil end
|
||||||
|
|
||||||
local removeButton = ignoreWindow:getChildById('buttonRemove')
|
local useIgnoreListBox = communicationWindow:getChildById('checkboxUseIgnoreList')
|
||||||
removeButton:disable()
|
useIgnoreListBox:setChecked(communicationSettings.useIgnoreList)
|
||||||
ignoreListPanel.onChildFocusChange = function() removeButton:enable() end
|
local useWhiteListBox = communicationWindow:getChildById('checkboxUseWhiteList')
|
||||||
removeButton.onClick = function()
|
useWhiteListBox:setChecked(communicationSettings.useWhiteList)
|
||||||
|
|
||||||
|
local removeIgnoreButton = communicationWindow:getChildById('buttonIgnoreRemove')
|
||||||
|
removeIgnoreButton:disable()
|
||||||
|
ignoreListPanel.onChildFocusChange = function() removeIgnoreButton:enable() end
|
||||||
|
removeIgnoreButton.onClick = function()
|
||||||
local selection = ignoreListPanel:getFocusedChild()
|
local selection = ignoreListPanel:getFocusedChild()
|
||||||
if selection then
|
if selection then
|
||||||
ignoreListPanel:removeChild(selection)
|
ignoreListPanel:removeChild(selection)
|
||||||
selection:destroy()
|
selection:destroy()
|
||||||
end
|
end
|
||||||
if ignoreListPanel:getChildCount() == 0 then
|
removeIgnoreButton:disable()
|
||||||
removeButton:disable()
|
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
local newlyIgnoredPlayers = {}
|
local newlyIgnoredPlayers = {}
|
||||||
local addName = ignoreWindow:getChildById('ignoreNameEdit')
|
local addIgnoreName = communicationWindow:getChildById('ignoreNameEdit')
|
||||||
local addButton = ignoreWindow:getChildById('buttonAdd')
|
local addIgnoreButton = communicationWindow:getChildById('buttonIgnoreAdd')
|
||||||
local addFunction = function()
|
local addIgnoreFunction = function()
|
||||||
if addName:getText() == '' then return end
|
local newEntry = addIgnoreName:getText()
|
||||||
if table.find(ignoreSettings.players, addName:getText()) then return end
|
if newEntry == '' then return end
|
||||||
if table.find(newlyIgnoredPlayers, addName:getText()) 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)
|
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
||||||
label:setText(addName:getText())
|
label:setText(newEntry)
|
||||||
table.insert(newlyIgnoredPlayers, addName:getText())
|
table.insert(newlyIgnoredPlayers, newEntry)
|
||||||
label:setPhantom(false)
|
addIgnoreName:setText('')
|
||||||
addName:setText('')
|
|
||||||
end
|
end
|
||||||
addButton.onClick = addFunction
|
addIgnoreButton.onClick = addIgnoreFunction
|
||||||
ignoreWindow.onEnter = addFunction
|
|
||||||
|
|
||||||
local ignorePrivateMessageBox = ignoreWindow:getChildById('checkboxIgnorePrivateMessages')
|
local newlyWhitelistedPlayers = {}
|
||||||
ignorePrivateMessageBox:setChecked(ignoreSettings.privateMessages)
|
local addWhitelistName = communicationWindow:getChildById('whitelistNameEdit')
|
||||||
local ignoreYellingBox = ignoreWindow:getChildById('checkboxIgnoreYelling')
|
local addWhitelistButton = communicationWindow:getChildById('buttonWhitelistAdd')
|
||||||
ignoreYellingBox:setChecked(ignoreSettings.yelling)
|
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
|
||||||
|
|
||||||
local saveButton = ignoreWindow:getChildById('buttonSave')
|
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()
|
saveButton.onClick = function()
|
||||||
ignoreSettings.players = {}
|
communicationSettings.ignoredPlayers = {}
|
||||||
for i = 1, ignoreListPanel:getChildCount() do
|
for i = 1, ignoreListPanel:getChildCount() do
|
||||||
addIgnoredPlayer(ignoreListPanel:getChildByIndex(i):getText())
|
addIgnoredPlayer(ignoreListPanel:getChildByIndex(i):getText())
|
||||||
--table.insert(ignoreSettings.players, ignoreListPanel:getChildByIndex(i):getText())
|
|
||||||
end
|
end
|
||||||
|
|
||||||
ignoreSettings.yelling = ignoreYellingBox:isChecked()
|
communicationSettings.whitelistedPlayers = {}
|
||||||
ignoreSettings.privateMessages = ignorePrivateMessageBox:isChecked()
|
for i = 1, whiteListPanel:getChildCount() do
|
||||||
ignoreWindow:destroy()
|
addWhitelistedPlayer(whiteListPanel:getChildByIndex(i):getText())
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, name in pairs(ignoreSettings.players) do
|
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)
|
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
||||||
label:setText(name)
|
label:setText(ignoredPlayers[i])
|
||||||
label:setPhantom(false)
|
end
|
||||||
|
|
||||||
|
local whitelistedPlayers = getWhitelistedPlayers()
|
||||||
|
for i = 1, #whitelistedPlayers do
|
||||||
|
local label = g_ui.createWidget('WhiteListLabel', whiteListPanel)
|
||||||
|
label:setText(whitelistedPlayers[i])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -56,12 +56,21 @@ Panel
|
|||||||
id: consolePanel
|
id: consolePanel
|
||||||
anchors.fill: parent
|
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
|
TabButton
|
||||||
id: prevChannelButton
|
id: prevChannelButton
|
||||||
icon: /images/game/console/leftarrow
|
icon: /images/game/console/leftarrow
|
||||||
anchors.left: parent.left
|
anchors.left: toggleChat.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
margin-left: 6
|
margin-left: 3
|
||||||
margin-top: 6
|
margin-top: 6
|
||||||
|
|
||||||
ConsoleTabBar
|
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')
|
gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel')
|
||||||
connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange })
|
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)
|
setupViewMode(0)
|
||||||
|
|
||||||
@@ -56,42 +57,19 @@ end
|
|||||||
|
|
||||||
function bindKeys()
|
function bindKeys()
|
||||||
gameRootPanel:setAutoRepeatDelay(250)
|
gameRootPanel:setAutoRepeatDelay(250)
|
||||||
g_keyboard.bindKeyDown('Up', function() changeWalkDir(North) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyDown('Right', function() changeWalkDir(East) end, gameRootPanel, true)
|
bindWalkKey('Up', North)
|
||||||
g_keyboard.bindKeyDown('Down', function() changeWalkDir(South) end, gameRootPanel, true)
|
bindWalkKey('Right', East)
|
||||||
g_keyboard.bindKeyDown('Left', function() changeWalkDir(West) end, gameRootPanel, true)
|
bindWalkKey('Down', South)
|
||||||
g_keyboard.bindKeyDown('Numpad8', function() changeWalkDir(North) end, gameRootPanel, true)
|
bindWalkKey('Left', West)
|
||||||
g_keyboard.bindKeyDown('Numpad9', function() changeWalkDir(NorthEast) end, gameRootPanel, true)
|
bindWalkKey('Numpad8', North)
|
||||||
g_keyboard.bindKeyDown('Numpad6', function() changeWalkDir(East) end, gameRootPanel, true)
|
bindWalkKey('Numpad9', NorthEast)
|
||||||
g_keyboard.bindKeyDown('Numpad3', function() changeWalkDir(SouthEast) end, gameRootPanel, true)
|
bindWalkKey('Numpad6', East)
|
||||||
g_keyboard.bindKeyDown('Numpad2', function() changeWalkDir(South) end, gameRootPanel, true)
|
bindWalkKey('Numpad3', SouthEast)
|
||||||
g_keyboard.bindKeyDown('Numpad1', function() changeWalkDir(SouthWest) end, gameRootPanel, true)
|
bindWalkKey('Numpad2', South)
|
||||||
g_keyboard.bindKeyDown('Numpad4', function() changeWalkDir(West) end, gameRootPanel, true)
|
bindWalkKey('Numpad1', SouthWest)
|
||||||
g_keyboard.bindKeyDown('Numpad7', function() changeWalkDir(NorthWest) end, gameRootPanel, true)
|
bindWalkKey('Numpad4', West)
|
||||||
g_keyboard.bindKeyUp('Up', function() changeWalkDir(North, true) end, gameRootPanel, true)
|
bindWalkKey('Numpad7', NorthWest)
|
||||||
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)
|
|
||||||
|
|
||||||
g_keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel)
|
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)
|
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('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
|
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
|
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+Q', function() tryLogout(false) end, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+L', logout, 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+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
|
||||||
end
|
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()
|
function terminate()
|
||||||
save()
|
save()
|
||||||
hide()
|
hide()
|
||||||
@@ -215,8 +205,8 @@ function tryExit()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local exitFunc = function() logout() forceExit() end
|
local exitFunc = function() g_game.safeLogout() forceExit() end
|
||||||
local logoutFunc = function() logout() exitWindow:destroy() exitWindow = nil end
|
local logoutFunc = function() g_game.safeLogout() exitWindow:destroy() exitWindow = nil end
|
||||||
local cancelFunc = function() 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."),
|
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
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function logout()
|
function tryLogout(prompt)
|
||||||
if g_game.isOnline() then
|
if type(prompt) ~= "boolean" then
|
||||||
g_game.safeLogout()
|
prompt = true
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function tryLogout()
|
|
||||||
if not g_game.isOnline() then
|
if not g_game.isOnline() then
|
||||||
exit()
|
exit()
|
||||||
return
|
return
|
||||||
@@ -245,13 +231,42 @@ function tryLogout()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local yesCallback = function() logout() logoutWindow:destroy() logoutWindow=nil end
|
local msg, yesCallback
|
||||||
local noCallback = function() logoutWindow:destroy() logoutWindow=nil end
|
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?'), {
|
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('Yes'), callback=yesCallback },
|
||||||
{ text=tr('No'), callback=noCallback },
|
{ text=tr('No'), callback=noCallback },
|
||||||
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
||||||
|
else
|
||||||
|
yesCallback()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function stopSmartWalk()
|
function stopSmartWalk()
|
||||||
@@ -463,7 +478,9 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
|||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
local localPosition = localPlayer:getPosition()
|
||||||
if not classic then shortcut = '(Alt)' else shortcut = nil end
|
if not classic then shortcut = '(Alt)' else shortcut = nil end
|
||||||
|
if creatureThing:getPosition().z == localPosition.z then
|
||||||
if g_game.getAttackingCreature() ~= creatureThing then
|
if g_game.getAttackingCreature() ~= creatureThing then
|
||||||
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut)
|
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut)
|
||||||
else
|
else
|
||||||
@@ -475,6 +492,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
|||||||
else
|
else
|
||||||
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
|
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if creatureThing:isPlayer() then
|
if creatureThing:isPlayer() then
|
||||||
menu:addSeparator()
|
menu:addSeparator()
|
||||||
@@ -519,7 +537,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if modules.game_ruleviolation.hasWindowAccess() then
|
if modules.game_ruleviolation.hasWindowAccess() and creatureThing:isPlayer() then
|
||||||
menu:addSeparator()
|
menu:addSeparator()
|
||||||
menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end)
|
menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end)
|
||||||
end
|
end
|
||||||
@@ -531,7 +549,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
|||||||
menu:display(menuPosition)
|
menu:display(menuPosition)
|
||||||
end
|
end
|
||||||
|
|
||||||
function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing)
|
function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, attackCreature)
|
||||||
local keyboardModifiers = g_keyboard.getModifiers()
|
local keyboardModifiers = g_keyboard.getModifiers()
|
||||||
|
|
||||||
if not modules.client_options.getOption('classicControl') then
|
if not modules.client_options.getOption('classicControl') then
|
||||||
@@ -557,7 +575,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return true
|
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)
|
g_game.attack(creatureThing)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -566,7 +587,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
|||||||
else
|
else
|
||||||
if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
|
if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
|
||||||
local player = g_game.getLocalPlayer()
|
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)
|
g_game.attack(creatureThing)
|
||||||
return true
|
return true
|
||||||
elseif useThing:isContainer() then
|
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
|
elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||||
createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||||
return true
|
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)
|
g_game.attack(creatureThing)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -655,6 +682,8 @@ function moveStackableItem(item, toPos)
|
|||||||
end
|
end
|
||||||
g_keyboard.bindKeyPress("Up", function() check() spinbox:up() end, spinbox)
|
g_keyboard.bindKeyPress("Up", function() check() spinbox:up() end, spinbox)
|
||||||
g_keyboard.bindKeyPress("Down", function() check() spinbox:down() 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("PageUp", function() check() spinbox:setValue(spinbox:getValue()+10) end, spinbox)
|
||||||
g_keyboard.bindKeyPress("PageDown", 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 })
|
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
|
||||||
elseif mode == 2 then
|
elseif mode == 2 then
|
||||||
local limit = limitZoom and not g_game.isGM()
|
local limit = limitZoom and not g_game.isGM()
|
||||||
gameMapPanel:setKeepAspectRatio(false)
|
|
||||||
gameMapPanel:setLimitVisibleRange(limit)
|
gameMapPanel:setLimitVisibleRange(limit)
|
||||||
gameMapPanel:setZoom(11)
|
gameMapPanel:setZoom(11)
|
||||||
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
|
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
|
||||||
|
@@ -6,11 +6,11 @@ CountWindow < MainWindow
|
|||||||
SpinBox
|
SpinBox
|
||||||
id: spinBox
|
id: spinBox
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.bottom
|
anchors.top: parent.top
|
||||||
width: 0
|
width: 1
|
||||||
height: 0
|
height: 1
|
||||||
phantom: true
|
phantom: true
|
||||||
padding-bottom: -40
|
margin-top: 2
|
||||||
focusable: true
|
focusable: true
|
||||||
|
|
||||||
Item
|
Item
|
||||||
|
@@ -78,6 +78,7 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton)
|
|||||||
local useThing
|
local useThing
|
||||||
local creatureThing
|
local creatureThing
|
||||||
local multiUseThing
|
local multiUseThing
|
||||||
|
local attackCreature
|
||||||
|
|
||||||
local tile = self:getTile(mousePosition)
|
local tile = self:getTile(mousePosition)
|
||||||
if tile then
|
if tile then
|
||||||
@@ -86,7 +87,12 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton)
|
|||||||
creatureThing = tile:getTopCreature()
|
creatureThing = tile:getTopCreature()
|
||||||
end
|
end
|
||||||
|
|
||||||
local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing)
|
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, attackCreature)
|
||||||
if ret then
|
if ret then
|
||||||
self.allowNextRelease = false
|
self.allowNextRelease = false
|
||||||
end
|
end
|
||||||
|
@@ -86,7 +86,7 @@ function UIItem:onMouseRelease(mousePosition, mouseButton)
|
|||||||
g_game.look(item)
|
g_game.look(item)
|
||||||
self.cancelNextRelease = true
|
self.cancelNextRelease = true
|
||||||
return 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
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
|
@@ -151,8 +151,7 @@ function onTradeTypeChange(radioTabs, selected, deselected)
|
|||||||
ignoreCapacity:setVisible(currentTradeType == BUY)
|
ignoreCapacity:setVisible(currentTradeType == BUY)
|
||||||
ignoreEquipped:setVisible(currentTradeType == SELL)
|
ignoreEquipped:setVisible(currentTradeType == SELL)
|
||||||
showAllItems:setVisible(currentTradeType == SELL)
|
showAllItems:setVisible(currentTradeType == SELL)
|
||||||
sellAllButton:setVisible(false)
|
sellAllButton:setVisible(currentTradeType == SELL)
|
||||||
--sellAllButton:setVisible(currentTradeType == SELL)
|
|
||||||
|
|
||||||
refreshTradeItems()
|
refreshTradeItems()
|
||||||
refreshPlayerGoods()
|
refreshPlayerGoods()
|
||||||
|
@@ -252,7 +252,6 @@ MainWindow
|
|||||||
margin-right: 10
|
margin-right: 10
|
||||||
visible: false
|
visible: false
|
||||||
@onClick: modules.game_npctrade.sellAll()
|
@onClick: modules.game_npctrade.sellAll()
|
||||||
visible: false
|
|
||||||
|
|
||||||
Button
|
Button
|
||||||
id: tradeButton
|
id: tradeButton
|
||||||
|
@@ -47,7 +47,7 @@ function openWindow()
|
|||||||
deathWindow = nil
|
deathWindow = nil
|
||||||
end
|
end
|
||||||
local cancelFunc = function()
|
local cancelFunc = function()
|
||||||
modules.game_interface.logout()
|
g_game.safeLogout()
|
||||||
cancelButton:getParent():destroy()
|
cancelButton:getParent():destroy()
|
||||||
deathWindow = nil
|
deathWindow = nil
|
||||||
end
|
end
|
||||||
|
@@ -18,7 +18,7 @@ function isLoaded()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function load()
|
function load()
|
||||||
local version = g_game.getProtocolVersion()
|
local version = g_game.getClientVersion()
|
||||||
|
|
||||||
local datPath, sprPath
|
local datPath, sprPath
|
||||||
if filename then
|
if filename then
|
||||||
|
@@ -88,6 +88,23 @@ function isHiddingOffline()
|
|||||||
return settings['hideOffline']
|
return settings['hideOffline']
|
||||||
end
|
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)
|
function onAddVip(id, name, state)
|
||||||
local vipList = vipWindow:getChildById('contentsPanel')
|
local vipList = vipWindow:getChildById('contentsPanel')
|
||||||
|
|
||||||
@@ -118,13 +135,13 @@ function onAddVip(id, name, state)
|
|||||||
|
|
||||||
for i=1,childrenCount do
|
for i=1,childrenCount do
|
||||||
local child = vipList:getChildByIndex(i)
|
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)
|
vipList:insertChild(i, label)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if (state ~= VipState.Online and child.vipState ~= VipState.Online)
|
if ((state ~= VipState.Online and child.vipState ~= VipState.Online)
|
||||||
or (state == VipState.Online and child.vipState == VipState.Online) then
|
or (state == VipState.Online and child.vipState == VipState.Online)) or getSortedBy() == 'name' then
|
||||||
|
|
||||||
local childText = child:getText():lower()
|
local childText = child:getText():lower()
|
||||||
local length = math.min(childText:len(), nameLower:len())
|
local length = math.min(childText:len(), nameLower:len())
|
||||||
@@ -168,6 +185,14 @@ function onVipListMousePress(widget, mousePos, mouseButton)
|
|||||||
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
||||||
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)
|
menu:display(mousePos)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -196,6 +221,15 @@ function onVipListLabelMousePress(widget, mousePos, mouseButton)
|
|||||||
else
|
else
|
||||||
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
||||||
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)
|
menu:display(mousePos)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@@ -6,7 +6,7 @@ end
|
|||||||
|
|
||||||
function g_game.chooseRsa(host)
|
function g_game.chooseRsa(host)
|
||||||
if currentRsa ~= CIPSOFT_RSA and currentRsa ~= OTSERV_RSA then return end
|
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)
|
g_game.setRsa(CIPSOFT_RSA)
|
||||||
|
|
||||||
if g_app.getOs() == 'windows' then
|
if g_app.getOs() == 'windows' then
|
||||||
@@ -32,22 +32,29 @@ function g_game.isOfficialTibia()
|
|||||||
return currentRsa == CIPSOFT_RSA
|
return currentRsa == CIPSOFT_RSA
|
||||||
end
|
end
|
||||||
|
|
||||||
function g_game.getSupportedProtocols()
|
function g_game.getSupportedClients()
|
||||||
return {
|
return {
|
||||||
810, 811, 840, 842, 850, 853, 854,
|
810, 811, 840, 842, 850, 853, 854,
|
||||||
860, 861, 862, 870, 910, 940, 944,
|
860, 861, 862, 870, 910, 940, 944,
|
||||||
953, 954, 960, 961, 963, 970, 971,
|
953, 954, 960, 961, 963, 970, 980,
|
||||||
973, 974
|
981, 982, 983, 984, 985, 986, 1001,
|
||||||
|
1002, 1010
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function g_game.getSupportedClients(protocol)
|
function g_game.getProtocolVersionForClient(client)
|
||||||
clients = {
|
clients = {
|
||||||
[971] = {980},
|
[980] = 971,
|
||||||
[973] = {981},
|
[981] = 973,
|
||||||
[974] = {982}
|
[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
|
end
|
||||||
|
|
||||||
g_game.setRsa(OTSERV_RSA)
|
g_game.setRsa(OTSERV_RSA)
|
||||||
|
@@ -2,3 +2,4 @@
|
|||||||
-- you can place any custom user code here
|
-- you can place any custom user code here
|
||||||
|
|
||||||
print 'Startup done :]'
|
print 'Startup done :]'
|
||||||
|
|
||||||
|
@@ -353,6 +353,8 @@ namespace Otc
|
|||||||
GameForceFirstAutoWalkStep = 37,
|
GameForceFirstAutoWalkStep = 37,
|
||||||
GameMinimapRemove = 38,
|
GameMinimapRemove = 38,
|
||||||
GameDoubleShopSellAmount = 39,
|
GameDoubleShopSellAmount = 39,
|
||||||
|
GameContainerPagination = 40,
|
||||||
|
GameThingMarks = 41,
|
||||||
// 51-100 reserved to be defined in lua
|
// 51-100 reserved to be defined in lua
|
||||||
LastGameFeature = 101
|
LastGameFeature = 101
|
||||||
};
|
};
|
||||||
|
@@ -128,7 +128,7 @@ void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWal
|
|||||||
dest -= datType->getDisplacement() * scaleFactor;
|
dest -= datType->getDisplacement() * scaleFactor;
|
||||||
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
|
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
|
||||||
dest += getDisplacement() * scaleFactor;
|
dest += getDisplacement() * scaleFactor;
|
||||||
zPattern = 1;
|
zPattern = std::min(1, getNumPatternZ() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
PointF jumpOffset = m_jumpOffset * scaleFactor;
|
PointF jumpOffset = m_jumpOffset * scaleFactor;
|
||||||
|
@@ -99,6 +99,11 @@ void Game::resetGameStates()
|
|||||||
m_walkEvent = nullptr;
|
m_walkEvent = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_checkConnectionEvent) {
|
||||||
|
m_checkConnectionEvent->cancel();
|
||||||
|
m_checkConnectionEvent = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
m_containers.clear();
|
m_containers.clear();
|
||||||
m_vips.clear();
|
m_vips.clear();
|
||||||
m_gmActions.clear();
|
m_gmActions.clear();
|
||||||
@@ -183,6 +188,16 @@ void Game::processGameStart()
|
|||||||
g_game.ping();
|
g_game.ping();
|
||||||
}, m_pingDelay);
|
}, 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()
|
void Game::processGameEnd()
|
||||||
@@ -190,6 +205,11 @@ void Game::processGameEnd()
|
|||||||
m_online = false;
|
m_online = false;
|
||||||
g_lua.callGlobalField("g_game", "onGameEnd");
|
g_lua.callGlobalField("g_game", "onGameEnd");
|
||||||
|
|
||||||
|
if(m_connectionFailWarned) {
|
||||||
|
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
|
||||||
|
m_connectionFailWarned = false;
|
||||||
|
}
|
||||||
|
|
||||||
// reset game state
|
// reset game state
|
||||||
resetGameStates();
|
resetGameStates();
|
||||||
|
|
||||||
@@ -554,7 +574,7 @@ bool Game::walk(Otc::Direction direction)
|
|||||||
if(m_lastWalkDir != direction) {
|
if(m_lastWalkDir != direction) {
|
||||||
// must add a new walk event
|
// must add a new walk event
|
||||||
float ticks = m_localPlayer->getStepTicksLeft();
|
float ticks = m_localPlayer->getStepTicksLeft();
|
||||||
if(ticks < 0) { ticks = 0; }
|
if(ticks <= 0) { ticks = 1; }
|
||||||
|
|
||||||
if(m_walkEvent) {
|
if(m_walkEvent) {
|
||||||
m_walkEvent->cancel();
|
m_walkEvent->cancel();
|
||||||
@@ -697,7 +717,9 @@ void Game::autoWalk(std::vector<Otc::Direction> dirs)
|
|||||||
|
|
||||||
auto it = dirs.begin();
|
auto it = dirs.begin();
|
||||||
Otc::Direction direction = *it;
|
Otc::Direction direction = *it;
|
||||||
if(m_localPlayer->canWalk(direction)) {
|
if(!m_localPlayer->canWalk(direction))
|
||||||
|
return;
|
||||||
|
|
||||||
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
||||||
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
|
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
|
||||||
m_localPlayer->preWalk(direction);
|
m_localPlayer->preWalk(direction);
|
||||||
@@ -707,7 +729,6 @@ void Game::autoWalk(std::vector<Otc::Direction> dirs)
|
|||||||
dirs.erase(it);
|
dirs.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
g_lua.callGlobalField("g_game", "onAutoWalk", dirs);
|
g_lua.callGlobalField("g_game", "onAutoWalk", dirs);
|
||||||
|
|
||||||
@@ -1379,7 +1400,7 @@ void Game::setProtocolVersion(int version)
|
|||||||
if(isOnline())
|
if(isOnline())
|
||||||
stdext::throw_exception("Unable to change protocol version while online");
|
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));
|
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
||||||
|
|
||||||
m_features.reset();
|
m_features.reset();
|
||||||
@@ -1443,6 +1464,14 @@ void Game::setProtocolVersion(int version)
|
|||||||
enableFeature(Otc::GameNewSpeedLaw);
|
enableFeature(Otc::GameNewSpeedLaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(version >= 976) {
|
||||||
|
enableFeature(Otc::GameContainerPagination);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(version >= 979) {
|
||||||
|
enableFeature(Otc::GameThingMarks);
|
||||||
|
}
|
||||||
|
|
||||||
m_protocolVersion = version;
|
m_protocolVersion = version;
|
||||||
|
|
||||||
Proto::buildMessageModesMap(version);
|
Proto::buildMessageModesMap(version);
|
||||||
@@ -1458,7 +1487,7 @@ void Game::setClientVersion(int version)
|
|||||||
if(isOnline())
|
if(isOnline())
|
||||||
stdext::throw_exception("Unable to change client version while online");
|
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));
|
stdext::throw_exception(stdext::format("Client version %d not supported", version));
|
||||||
|
|
||||||
m_clientVersion = version;
|
m_clientVersion = version;
|
||||||
|
@@ -281,6 +281,7 @@ public:
|
|||||||
bool isDead() { return m_dead; }
|
bool isDead() { return m_dead; }
|
||||||
bool isAttacking() { return !!m_attackingCreature; }
|
bool isAttacking() { return !!m_attackingCreature; }
|
||||||
bool isFollowing() { return !!m_followingCreature; }
|
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; }
|
int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; }
|
||||||
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
||||||
@@ -340,6 +341,8 @@ private:
|
|||||||
std::bitset<Otc::LastGameFeature> m_features;
|
std::bitset<Otc::LastGameFeature> m_features;
|
||||||
ScheduledEventPtr m_pingEvent;
|
ScheduledEventPtr m_pingEvent;
|
||||||
ScheduledEventPtr m_walkEvent;
|
ScheduledEventPtr m_walkEvent;
|
||||||
|
ScheduledEventPtr m_checkConnectionEvent;
|
||||||
|
bool m_connectionFailWarned;
|
||||||
int m_protocolVersion;
|
int m_protocolVersion;
|
||||||
int m_clientVersion;
|
int m_clientVersion;
|
||||||
std::string m_clientSignature;
|
std::string m_clientSignature;
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
#include <framework/graphics/framebuffermanager.h>
|
#include <framework/graphics/framebuffermanager.h>
|
||||||
#include <framework/graphics/painter.h>
|
#include <framework/graphics/painter.h>
|
||||||
#include <framework/graphics/image.h>
|
#include <framework/graphics/image.h>
|
||||||
#include <framework/graphics/ogl/textureogl.h>
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MAX_LIGHT_INTENSITY = 8,
|
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);
|
tex->setSmooth(true);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
@@ -72,7 +72,7 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// last walk is not done yet
|
// last walk is not done yet
|
||||||
if(m_walkTimer.ticksElapsed() < getStepDuration())
|
if((m_walkTimer.ticksElapsed() < getStepDuration()) && !isAutoWalking())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// prewalk has a timeout, because for some reason that I don't know yet the server sometimes doesn't answer the prewalk
|
// 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;
|
return false;
|
||||||
|
|
||||||
// cannot walk while already walking
|
// cannot walk while already walking
|
||||||
if(m_walking && !prewalkTimeouted)
|
if((m_walking && !isAutoWalking()) && (!prewalkTimeouted || m_secondPreWalk))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -95,6 +95,7 @@ void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
|
|||||||
if(m_preWalking) {
|
if(m_preWalking) {
|
||||||
// switch to normal walking
|
// switch to normal walking
|
||||||
m_preWalking = false;
|
m_preWalking = false;
|
||||||
|
m_secondPreWalk = false;
|
||||||
m_lastPrewalkDone = true;
|
m_lastPrewalkDone = true;
|
||||||
// if is to the last prewalk destination, updates the walk preserving the animation
|
// if is to the last prewalk destination, updates the walk preserving the animation
|
||||||
if(newPos == m_lastPrewalkDestination) {
|
if(newPos == m_lastPrewalkDestination) {
|
||||||
@@ -118,7 +119,8 @@ void LocalPlayer::preWalk(Otc::Direction direction)
|
|||||||
Position newPos = m_position.translatedToDirection(direction);
|
Position newPos = m_position.translatedToDirection(direction);
|
||||||
|
|
||||||
// avoid reanimating prewalks
|
// avoid reanimating prewalks
|
||||||
if(m_preWalking && m_lastPrewalkDestination == newPos) {
|
if(m_preWalking) {
|
||||||
|
m_secondPreWalk = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,6 +279,7 @@ void LocalPlayer::terminateWalk()
|
|||||||
{
|
{
|
||||||
Creature::terminateWalk();
|
Creature::terminateWalk();
|
||||||
m_preWalking = false;
|
m_preWalking = false;
|
||||||
|
m_secondPreWalk = false;
|
||||||
m_idleTimer.restart();
|
m_idleTimer.restart();
|
||||||
|
|
||||||
auto self = asLocalPlayer();
|
auto self = asLocalPlayer();
|
||||||
|
@@ -126,6 +126,7 @@ private:
|
|||||||
ticks_t m_walkLockExpiration;
|
ticks_t m_walkLockExpiration;
|
||||||
stdext::boolean<false> m_preWalking;
|
stdext::boolean<false> m_preWalking;
|
||||||
stdext::boolean<true> m_lastPrewalkDone;
|
stdext::boolean<true> m_lastPrewalkDone;
|
||||||
|
stdext::boolean<false> m_secondPreWalk;
|
||||||
stdext::boolean<false> m_serverWalking;
|
stdext::boolean<false> m_serverWalking;
|
||||||
stdext::boolean<false> m_knownCompletePath;
|
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", "isDead", &Game::isDead, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &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", "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", "getPing", &Game::getPing, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
|
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &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);
|
Position pos = cameraPosition.translated(ix, iy);
|
||||||
|
|
||||||
// process tiles that we can look through, e.g. windows, doors
|
// 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 upperPos = pos;
|
||||||
Position coveredPos = pos;
|
Position coveredPos = pos;
|
||||||
|
|
||||||
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
|
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
|
||||||
// check tiles physically above
|
// check tiles physically above
|
||||||
TilePtr tile = g_map.getTile(upperPos);
|
TilePtr tile = g_map.getTile(upperPos);
|
||||||
if(tile && tile->limitsFloorsView()) {
|
if(tile && tile->limitsFloorsView(!g_map.isLookPossible(pos))) {
|
||||||
firstFloor = upperPos.z + 1;
|
firstFloor = upperPos.z + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check tiles geometrically above
|
// check tiles geometrically above
|
||||||
tile = g_map.getTile(coveredPos);
|
tile = g_map.getTile(coveredPos);
|
||||||
if(tile && tile->limitsFloorsView()) {
|
if(tile && tile->limitsFloorsView(g_map.isLookPossible(pos))) {
|
||||||
firstFloor = coveredPos.z + 1;
|
firstFloor = coveredPos.z + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,6 @@
|
|||||||
#include <framework/graphics/painter.h>
|
#include <framework/graphics/painter.h>
|
||||||
#include <framework/graphics/image.h>
|
#include <framework/graphics/image.h>
|
||||||
#include <framework/graphics/framebuffermanager.h>
|
#include <framework/graphics/framebuffermanager.h>
|
||||||
#include <framework/graphics/ogl/textureogl.h>
|
|
||||||
#include <framework/core/resourcemanager.h>
|
#include <framework/core/resourcemanager.h>
|
||||||
#include <framework/core/filestream.h>
|
#include <framework/core/filestream.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
@@ -66,7 +65,7 @@ void MinimapBlock::update()
|
|||||||
|
|
||||||
if(shouldDraw) {
|
if(shouldDraw) {
|
||||||
if(!m_texture) {
|
if(!m_texture) {
|
||||||
m_texture = TexturePtr(new TextureOGL(image, true));
|
m_texture = TexturePtr(new Texture(image, true));
|
||||||
} else {
|
} else {
|
||||||
m_texture->uploadPixels(image, true);
|
m_texture->uploadPixels(image, true);
|
||||||
}
|
}
|
||||||
|
@@ -603,6 +603,14 @@ void ProtocolGame::parseOpenContainer(const InputMessagePtr& msg)
|
|||||||
std::string name = msg->getString();
|
std::string name = msg->getString();
|
||||||
int capacity = msg->getU8();
|
int capacity = msg->getU8();
|
||||||
bool hasParent = (msg->getU8() != 0);
|
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();
|
int itemCount = msg->getU8();
|
||||||
|
|
||||||
std::vector<ItemPtr> items(itemCount);
|
std::vector<ItemPtr> items(itemCount);
|
||||||
@@ -622,13 +630,21 @@ void ProtocolGame::parseContainerAddItem(const InputMessagePtr& msg)
|
|||||||
{
|
{
|
||||||
int containerId = msg->getU8();
|
int containerId = msg->getU8();
|
||||||
ItemPtr item = getItem(msg);
|
ItemPtr item = getItem(msg);
|
||||||
|
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||||
|
msg->getU16(); // slot
|
||||||
|
}
|
||||||
g_game.processContainerAddItem(containerId, item);
|
g_game.processContainerAddItem(containerId, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
int containerId = msg->getU8();
|
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);
|
ItemPtr item = getItem(msg);
|
||||||
g_game.processContainerUpdateItem(containerId, slot, item);
|
g_game.processContainerUpdateItem(containerId, slot, item);
|
||||||
}
|
}
|
||||||
@@ -636,7 +652,13 @@ void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
|||||||
void ProtocolGame::parseContainerRemoveItem(const InputMessagePtr& msg)
|
void ProtocolGame::parseContainerRemoveItem(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
int containerId = msg->getU8();
|
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);
|
g_game.processContainerRemoveItem(containerId, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1808,6 +1830,12 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
|||||||
if(g_game.getFeature(Otc::GameCreatureEmblems) && !known)
|
if(g_game.getFeature(Otc::GameCreatureEmblems) && !known)
|
||||||
emblem = msg->getU8();
|
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)
|
if(g_game.getProtocolVersion() >= 854)
|
||||||
unpass = msg->getU8();
|
unpass = msg->getU8();
|
||||||
|
|
||||||
@@ -1860,6 +1888,10 @@ ItemPtr ProtocolGame::getItem(const InputMessagePtr& msg, int id)
|
|||||||
if(item->getId() == 0)
|
if(item->getId() == 0)
|
||||||
stdext::throw_exception(stdext::format("unable to create item with invalid id %d", id));
|
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())
|
if(item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable())
|
||||||
item->setCountOrSubType(msg->getU8());
|
item->setCountOrSubType(msg->getU8());
|
||||||
|
|
||||||
|
@@ -48,11 +48,9 @@ bool SpriteManager::loadSpr(std::string file)
|
|||||||
file = g_resources.guessFilePath(file, "spr");
|
file = g_resources.guessFilePath(file, "spr");
|
||||||
|
|
||||||
m_spritesFile = g_resources.openFile(file);
|
m_spritesFile = g_resources.openFile(file);
|
||||||
|
|
||||||
// cache file buffer to avoid lags from hard drive
|
// cache file buffer to avoid lags from hard drive
|
||||||
#ifndef MOBILE
|
|
||||||
m_spritesFile->cache();
|
m_spritesFile->cache();
|
||||||
#endif
|
|
||||||
m_signature = m_spritesFile->getU32();
|
m_signature = m_spritesFile->getU32();
|
||||||
m_spritesCount = g_game.getFeature(Otc::GameSpritesU32) ? m_spritesFile->getU32() : m_spritesFile->getU16();
|
m_spritesCount = g_game.getFeature(Otc::GameSpritesU32) ? m_spritesFile->getU32() : m_spritesFile->getU16();
|
||||||
m_spritesOffset = m_spritesFile->tell();
|
m_spritesOffset = m_spritesFile->tell();
|
||||||
|
@@ -28,7 +28,6 @@
|
|||||||
#include <framework/graphics/graphics.h>
|
#include <framework/graphics/graphics.h>
|
||||||
#include <framework/graphics/texture.h>
|
#include <framework/graphics/texture.h>
|
||||||
#include <framework/graphics/image.h>
|
#include <framework/graphics/image.h>
|
||||||
#include <framework/graphics/ogl/textureogl.h>
|
|
||||||
#include <framework/graphics/texturemanager.h>
|
#include <framework/graphics/texturemanager.h>
|
||||||
#include <framework/core/filestream.h>
|
#include <framework/core/filestream.h>
|
||||||
#include <framework/otml/otml.h>
|
#include <framework/otml/otml.h>
|
||||||
@@ -68,6 +67,17 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
|||||||
attr -= 1;
|
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) {
|
switch(attr) {
|
||||||
case ThingAttrDisplacement: {
|
case ThingAttrDisplacement: {
|
||||||
m_displacement.x = fin->getU16();
|
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;
|
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
|
||||||
|
|
||||||
if(totalSprites == 0)
|
// if(totalSprites == 0)
|
||||||
stdext::throw_exception("a thing type has no sprites");
|
// stdext::throw_exception("a thing type has no sprites");
|
||||||
if(totalSprites > 4096)
|
if(totalSprites > 4096)
|
||||||
stdext::throw_exception("a thing type has more than 4096 sprites");
|
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);
|
animationPhaseTexture->setSmooth(true);
|
||||||
}
|
}
|
||||||
return animationPhaseTexture;
|
return animationPhaseTexture;
|
||||||
|
@@ -81,6 +81,7 @@ enum ThingAttr : uint8 {
|
|||||||
ThingAttrOpacity = 100,
|
ThingAttrOpacity = 100,
|
||||||
ThingAttrNotPreWalkable = 101,
|
ThingAttrNotPreWalkable = 101,
|
||||||
|
|
||||||
|
ThingAttrNoMoveAnimation = 253, // real value is 16, but we need to do this for backwards compatibility
|
||||||
ThingAttrChargeable = 254, // deprecated
|
ThingAttrChargeable = 254, // deprecated
|
||||||
ThingLastAttr = 255
|
ThingLastAttr = 255
|
||||||
};
|
};
|
||||||
|
@@ -590,15 +590,24 @@ bool Tile::hasCreature()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tile::limitsFloorsView()
|
bool Tile::limitsFloorsView(bool isFreeView)
|
||||||
{
|
{
|
||||||
// ground and walls limits the view
|
// ground and walls limits the view
|
||||||
ThingPtr firstThing = getThing(0);
|
ThingPtr firstThing = getThing(0);
|
||||||
|
|
||||||
|
if(isFreeView){
|
||||||
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || firstThing->isOnBottom()))
|
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || firstThing->isOnBottom()))
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || (firstThing->isOnBottom() && firstThing->blockProjectile())))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Tile::canErase()
|
bool Tile::canErase()
|
||||||
{
|
{
|
||||||
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty() && m_flags == 0 && m_minimapColor == 0;
|
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty() && m_flags == 0 && m_minimapColor == 0;
|
||||||
|
@@ -105,7 +105,7 @@ public:
|
|||||||
bool mustHookSouth();
|
bool mustHookSouth();
|
||||||
bool mustHookEast();
|
bool mustHookEast();
|
||||||
bool hasCreature();
|
bool hasCreature();
|
||||||
bool limitsFloorsView();
|
bool limitsFloorsView(bool isFreeView = false);
|
||||||
bool canErase();
|
bool canErase();
|
||||||
bool hasElevation(int elevation = 1);
|
bool hasElevation(int elevation = 1);
|
||||||
void overwriteMinimapColor(uint8 color) { m_minimapColor = color; }
|
void overwriteMinimapColor(uint8 color) { m_minimapColor = color; }
|
||||||
|
@@ -123,20 +123,15 @@ set(framework_SOURCES ${framework_SOURCES}
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/otml/otmlparser.h
|
${CMAKE_CURRENT_LIST_DIR}/otml/otmlparser.h
|
||||||
|
|
||||||
# crash handler
|
# 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.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/platform/platform.h
|
${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
|
set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/luafunctions.cpp
|
||||||
PROPERTIES LANGUAGE CXX COMPILE_FLAGS "-g0 -Os")
|
PROPERTIES LANGUAGE CXX COMPILE_FLAGS "-g0 -Os")
|
||||||
|
|
||||||
@@ -263,15 +258,6 @@ if(CRASH_HANDLER)
|
|||||||
message(STATUS "Crash handler: ON")
|
message(STATUS "Crash handler: ON")
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(framework_LIBRARIES ${framework_LIBRARIES} imagehlp)
|
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()
|
endif()
|
||||||
else()
|
else()
|
||||||
message(STATUS "Crash handler: OFF")
|
message(STATUS "Crash handler: OFF")
|
||||||
@@ -304,24 +290,18 @@ endif()
|
|||||||
|
|
||||||
if(FRAMEWORK_GRAPHICS)
|
if(FRAMEWORK_GRAPHICS)
|
||||||
set(OPENGLES "OFF" CACHE "Use OpenGL ES 1.0 or 2.0 (for mobiles devices)" STRING)
|
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")
|
if(OPENGLES STREQUAL "2.0")
|
||||||
find_package(OpenGLES2 REQUIRED)
|
find_package(OpenGLES2 REQUIRED)
|
||||||
find_package(EGL REQUIRED)
|
find_package(EGL REQUIRED)
|
||||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=2)
|
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=2)
|
||||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES2_INCLUDE_DIR})
|
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES2_INCLUDE_DIR})
|
||||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES2_LIBRARY})
|
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES2_LIBRARY})
|
||||||
elseif(OPENGLES STREQUAL "1.0")
|
ELSEif(OPENGLES STREQUAL "1.0")
|
||||||
find_package(OpenGLES1 REQUIRED)
|
find_package(OpenGLES1 REQUIRED)
|
||||||
find_package(EGL REQUIRED)
|
find_package(EGL REQUIRED)
|
||||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=1)
|
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=1)
|
||||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES1_INCLUDE_DIR})
|
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES1_INCLUDE_DIR})
|
||||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES1_LIBRARY})
|
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES1_LIBRARY})
|
||||||
endif()
|
|
||||||
else()
|
else()
|
||||||
## TODO: CMake Documentation says that this is not the right
|
## TODO: CMake Documentation says that this is not the right
|
||||||
# Thing for Mac OS X, but it works for now.
|
# Thing for Mac OS X, but it works for now.
|
||||||
@@ -356,8 +336,6 @@ if(FRAMEWORK_GRAPHICS)
|
|||||||
set(framework_SOURCES ${framework_SOURCES}
|
set(framework_SOURCES ${framework_SOURCES}
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/painterdx9.cpp
|
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/painterdx9.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/painterdx9.h
|
${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()
|
endif()
|
||||||
|
|
||||||
@@ -365,44 +343,6 @@ if(FRAMEWORK_GRAPHICS)
|
|||||||
set(framework_LIBRARIES ${framework_LIBRARIES} X11)
|
set(framework_LIBRARIES ${framework_LIBRARIES} X11)
|
||||||
endif()
|
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}
|
set(framework_SOURCES ${framework_SOURCES}
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp
|
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.h
|
${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/glutil.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
|
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.h
|
${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.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/hardwarebuffer.h
|
${CMAKE_CURRENT_LIST_DIR}/graphics/hardwarebuffer.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp
|
${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/shaderprogram.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp
|
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.h
|
${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.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.h
|
${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/vertexarray.h
|
${CMAKE_CURRENT_LIST_DIR}/graphics/vertexarray.h
|
||||||
@@ -499,6 +435,10 @@ if(FRAMEWORK_GRAPHICS)
|
|||||||
# platform window
|
# platform window
|
||||||
${CMAKE_CURRENT_LIST_DIR}/platform/platformwindow.cpp
|
${CMAKE_CURRENT_LIST_DIR}/platform/platformwindow.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/platform/platformwindow.h
|
${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
|
# window input
|
||||||
${CMAKE_CURRENT_LIST_DIR}/input/mouse.cpp
|
${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 <framework/platform/platform.h>
|
||||||
|
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <boost/concept_check.hpp>
|
|
||||||
|
|
||||||
#ifdef FW_NET
|
#ifdef FW_NET
|
||||||
#include <framework/net/connection.h>
|
#include <framework/net/connection.h>
|
||||||
@@ -164,14 +163,10 @@ void Application::close()
|
|||||||
|
|
||||||
std::string Application::getOs()
|
std::string Application::getOs()
|
||||||
{
|
{
|
||||||
#if defined(ANDROID)
|
#if defined(WIN32)
|
||||||
return "android";
|
|
||||||
#elif defined(IOS)
|
|
||||||
return "ios";
|
|
||||||
#elif defined(WIN32)
|
|
||||||
return "windows";
|
return "windows";
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
return "macos";
|
return "mac";
|
||||||
#elif __linux
|
#elif __linux
|
||||||
return "linux";
|
return "linux";
|
||||||
#else
|
#else
|
||||||
|
@@ -24,14 +24,12 @@
|
|||||||
#include "graphicalapplication.h"
|
#include "graphicalapplication.h"
|
||||||
#include <framework/core/clock.h>
|
#include <framework/core/clock.h>
|
||||||
#include <framework/core/eventdispatcher.h>
|
#include <framework/core/eventdispatcher.h>
|
||||||
#include <framework/input/mouse.h>
|
|
||||||
#include <framework/platform/platformwindow.h>
|
#include <framework/platform/platformwindow.h>
|
||||||
#include <framework/ui/uimanager.h>
|
#include <framework/ui/uimanager.h>
|
||||||
#include <framework/graphics/graphics.h>
|
#include <framework/graphics/graphics.h>
|
||||||
#include <framework/graphics/particlemanager.h>
|
#include <framework/graphics/particlemanager.h>
|
||||||
#include <framework/graphics/texturemanager.h>
|
#include <framework/graphics/texturemanager.h>
|
||||||
#include <framework/graphics/painter.h>
|
#include <framework/graphics/painter.h>
|
||||||
#include <framework/graphics/ogl/textureogl.h>
|
|
||||||
|
|
||||||
#ifdef FW_SOUND
|
#ifdef FW_SOUND
|
||||||
#include <framework/sound/soundmanager.h>
|
#include <framework/sound/soundmanager.h>
|
||||||
@@ -234,7 +232,7 @@ void GraphicalApplication::resize(const Size& size)
|
|||||||
m_onInputEvent = false;
|
m_onInputEvent = false;
|
||||||
|
|
||||||
if(g_graphics.canCacheBackbuffer()) {
|
if(g_graphics.canCacheBackbuffer()) {
|
||||||
m_foreground = TexturePtr(new TextureOGL(size));
|
m_foreground = TexturePtr(new Texture(size));
|
||||||
m_foreground->setUpsideDown(true);
|
m_foreground->setUpsideDown(true);
|
||||||
}
|
}
|
||||||
m_mustRepaint = true;
|
m_mustRepaint = true;
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
class GraphicalApplication : public Application
|
class GraphicalApplication : public Application
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
POLL_CYCLE_DELAY = 1000
|
POLL_CYCLE_DELAY = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@@ -25,30 +25,24 @@
|
|||||||
|
|
||||||
//#include <boost/regex.hpp>
|
//#include <boost/regex.hpp>
|
||||||
#include <framework/core/resourcemanager.h>
|
#include <framework/core/resourcemanager.h>
|
||||||
#include "application.h"
|
|
||||||
|
|
||||||
#ifdef FW_GRAPHICS
|
#ifdef FW_GRAPHICS
|
||||||
#include <framework/platform/platformwindow.h>
|
#include <framework/platform/platformwindow.h>
|
||||||
|
#include <framework/platform/platform.h>
|
||||||
#include <framework/luaengine/luainterface.h>
|
#include <framework/luaengine/luainterface.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOBILE
|
|
||||||
#include <android/log.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Logger g_logger;
|
Logger g_logger;
|
||||||
|
|
||||||
void Logger::log(Fw::LogLevel level, const std::string& message)
|
void Logger::log(Fw::LogLevel level, const std::string& message)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
/*
|
|
||||||
>>>>>>> Progress in SDL platform
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
if(level == Fw::LogDebug)
|
if(level == Fw::LogDebug)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
*/
|
|
||||||
static bool ignoreLogs = false;
|
static bool ignoreLogs = false;
|
||||||
if(ignoreLogs)
|
if(ignoreLogs)
|
||||||
return;
|
return;
|
||||||
@@ -73,11 +67,7 @@ void Logger::log(Fw::LogLevel level, const std::string& message)
|
|||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef ANDROID
|
|
||||||
__android_log_print(ANDROID_LOG_INFO, g_app.getCompactName().c_str(), outmsg.c_str());
|
|
||||||
#else
|
|
||||||
std::cout << outmsg << std::endl;
|
std::cout << outmsg << std::endl;
|
||||||
#endif
|
|
||||||
|
|
||||||
if(m_outFile.good()) {
|
if(m_outFile.good()) {
|
||||||
m_outFile << outmsg << std::endl;
|
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);
|
prettyFunction = prettyFunction.substr(prettyFunction.find_last_of(' ') + 1);
|
||||||
|
|
||||||
|
|
||||||
std::string out = message;
|
std::stringstream ss;
|
||||||
|
ss << message;
|
||||||
|
|
||||||
if(!prettyFunction.empty()) {
|
if(!prettyFunction.empty()) {
|
||||||
if(g_lua.isInCppCallback())
|
if(g_lua.isInCppCallback())
|
||||||
out = g_lua.traceback(out, 1);
|
ss << g_lua.traceback("", 1);
|
||||||
else
|
ss << g_platform.traceback(prettyFunction, 1, 8);
|
||||||
out += "\nat:\t[C++]: " + prettyFunction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log(level, out);
|
log(level, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::fireOldMessages()
|
void Logger::fireOldMessages()
|
||||||
|
@@ -29,10 +29,6 @@
|
|||||||
|
|
||||||
#include <physfs.h>
|
#include <physfs.h>
|
||||||
|
|
||||||
#ifdef MOBILE
|
|
||||||
#include <SDL.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ResourceManager g_resources;
|
ResourceManager g_resources;
|
||||||
|
|
||||||
void ResourceManager::init(const char *argv0)
|
void ResourceManager::init(const char *argv0)
|
||||||
@@ -49,15 +45,10 @@ void ResourceManager::terminate()
|
|||||||
bool ResourceManager::discoverWorkDir(const std::string& existentFile)
|
bool ResourceManager::discoverWorkDir(const std::string& existentFile)
|
||||||
{
|
{
|
||||||
// search for modules directory
|
// search for modules directory
|
||||||
#ifdef ANDROID
|
std::string possiblePaths[] = { g_platform.getCurrentDir(),
|
||||||
std::string possiblePaths[] = { std::string("/sdcard/") + g_app.getCompactName() + "/" };
|
|
||||||
#else
|
|
||||||
std::string possiblePaths[] = { "./",
|
|
||||||
g_platform.getCurrentDir(),
|
|
||||||
g_resources.getBaseDir(),
|
g_resources.getBaseDir(),
|
||||||
g_resources.getBaseDir() + "../",
|
g_resources.getBaseDir() + "../",
|
||||||
g_resources.getBaseDir() + "../share/" + g_app.getCompactName() + "/" };
|
g_resources.getBaseDir() + "../share/" + g_app.getCompactName() + "/" };
|
||||||
#endif
|
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for(const std::string& dir : possiblePaths) {
|
for(const std::string& dir : possiblePaths) {
|
||||||
@@ -318,11 +309,7 @@ std::string ResourceManager::getBaseDir()
|
|||||||
|
|
||||||
std::string ResourceManager::getUserDir()
|
std::string ResourceManager::getUserDir()
|
||||||
{
|
{
|
||||||
#ifdef ANDROID
|
|
||||||
return std::string("/sdcard/");
|
|
||||||
#else
|
|
||||||
return PHYSFS_getUserDir();
|
return PHYSFS_getUserDir();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ResourceManager::guessFilePath(const std::string& filename, const std::string& type)
|
std::string ResourceManager::guessFilePath(const std::string& filename, const std::string& type)
|
||||||
|
@@ -24,15 +24,14 @@
|
|||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
|
|
||||||
#include <framework/core/eventdispatcher.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))
|
if(!setupSize(size, buildMipmaps))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for(uint i=0;i<frames.size();++i) {
|
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;
|
m_framesDelay = framesDelay;
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
class AnimatedTexture : public Texture
|
class AnimatedTexture : public Texture
|
||||||
{
|
{
|
||||||
public:
|
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 ~AnimatedTexture();
|
||||||
|
|
||||||
virtual bool buildHardwareMipmaps();
|
virtual bool buildHardwareMipmaps();
|
||||||
|
@@ -33,15 +33,15 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
||||||
#define lswap16(data) _byteswap_ushort(data)
|
#define swap16(data) _byteswap_ushort(data)
|
||||||
#define lswap32(data) _byteswap_ulong(data)
|
#define swap32(data) _byteswap_ulong(data)
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
#define lswap16(data) bswap_16(data)
|
#define swap16(data) bswap_16(data)
|
||||||
#define lswap32(data) bswap_32(data)
|
#define swap32(data) bswap_32(data)
|
||||||
#else
|
#else
|
||||||
#define lswap16(data) (((data >> 8) & 255) | ((data & 255) << 8))
|
#define swap16(data) (((data >> 8) & 255) | ((data & 255) << 8))
|
||||||
#define lswap32(data) ((swap16(data) << 16) | swap16(data >> 16))
|
#define swap32(data) ((swap16(data) << 16) | swap16(data >> 16))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PNG_ZBUF_SIZE 32768
|
#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)
|
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 crc = crc32(0, Z_NULL, 0);
|
||||||
unsigned int len = lswap32(length);
|
unsigned int len = swap32(length);
|
||||||
|
|
||||||
f.write((char*)&len, 4);
|
f.write((char*)&len, 4);
|
||||||
f.write(name, 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 = crc32(crc, data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
crc = lswap32(crc);
|
crc = swap32(crc);
|
||||||
f.write((char*)&crc, 4);
|
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 mCompression;
|
||||||
unsigned char mFilterMethod;
|
unsigned char mFilterMethod;
|
||||||
unsigned char mInterlaceMethod;
|
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 zstream1;
|
||||||
z_stream zstream2;
|
z_stream zstream2;
|
||||||
|
@@ -34,7 +34,6 @@ class BitmapFont;
|
|||||||
class CachedText;
|
class CachedText;
|
||||||
class FrameBuffer;
|
class FrameBuffer;
|
||||||
class FrameBufferManager;
|
class FrameBufferManager;
|
||||||
class GraphicsContext;
|
|
||||||
class Shader;
|
class Shader;
|
||||||
class ShaderProgram;
|
class ShaderProgram;
|
||||||
class PainterShaderProgram;
|
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<BitmapFont> BitmapFontPtr;
|
||||||
typedef stdext::shared_object_ptr<CachedText> CachedTextPtr;
|
typedef stdext::shared_object_ptr<CachedText> CachedTextPtr;
|
||||||
typedef stdext::shared_object_ptr<FrameBuffer> FrameBufferPtr;
|
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<Shader> ShaderPtr;
|
||||||
typedef stdext::shared_object_ptr<ShaderProgram> ShaderProgramPtr;
|
typedef stdext::shared_object_ptr<ShaderProgram> ShaderProgramPtr;
|
||||||
typedef stdext::shared_object_ptr<PainterShaderProgram> PainterShaderProgramPtr;
|
typedef stdext::shared_object_ptr<PainterShaderProgram> PainterShaderProgramPtr;
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include <framework/platform/platformwindow.h>
|
#include <framework/platform/platformwindow.h>
|
||||||
#include <framework/core/application.h>
|
#include <framework/core/application.h>
|
||||||
#include <framework/graphics/ogl/textureogl.h>
|
|
||||||
|
|
||||||
uint FrameBuffer::boundFbo = 0;
|
uint FrameBuffer::boundFbo = 0;
|
||||||
|
|
||||||
@@ -62,7 +61,7 @@ void FrameBuffer::resize(const Size& size)
|
|||||||
if(m_texture && m_texture->getSize() == size)
|
if(m_texture && m_texture->getSize() == size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_texture = TexturePtr(new TextureOGL(size));
|
m_texture = TexturePtr(new Texture(size));
|
||||||
m_texture->setSmooth(m_smooth);
|
m_texture->setSmooth(m_smooth);
|
||||||
m_texture->setUpsideDown(true);
|
m_texture->setUpsideDown(true);
|
||||||
|
|
||||||
@@ -76,7 +75,7 @@ void FrameBuffer::resize(const Size& size)
|
|||||||
internalRelease();
|
internalRelease();
|
||||||
} else {
|
} else {
|
||||||
if(m_backuping) {
|
if(m_backuping) {
|
||||||
m_screenBackup = TexturePtr(new TextureOGL(size));
|
m_screenBackup = TexturePtr(new Texture(size));
|
||||||
m_screenBackup->setUpsideDown(true);
|
m_screenBackup->setUpsideDown(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,7 +44,6 @@
|
|||||||
typedef char GLchar;
|
typedef char GLchar;
|
||||||
|
|
||||||
// define OpenGL ES 2.0 API just to make compile, it wont actually be used
|
// 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 glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { }
|
||||||
inline void glBindFramebuffer (GLenum target, GLuint framebuffer) { }
|
inline void glBindFramebuffer (GLenum target, GLuint framebuffer) { }
|
||||||
inline void glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) { }
|
inline void glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) { }
|
||||||
|
@@ -184,16 +184,14 @@ bool Graphics::isPainterEngineAvailable(Graphics::PainterEngine painterEngine)
|
|||||||
|
|
||||||
bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
||||||
{
|
{
|
||||||
// TODO: remove this
|
|
||||||
#ifdef DIRECTX
|
|
||||||
painterEngine = Painter_DirectX9;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Painter *painter = nullptr;
|
Painter *painter = nullptr;
|
||||||
Painter *fallbackPainter = nullptr;
|
Painter *fallbackPainter = nullptr;
|
||||||
PainterEngine fallbackPainterEngine = Painter_Any;
|
PainterEngine fallbackPainterEngine = Painter_Any;
|
||||||
|
|
||||||
#ifdef PAINTER_DX9
|
#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
|
// always prefer DirectX9 on Windows
|
||||||
if(g_painterDX9) {
|
if(g_painterDX9) {
|
||||||
if(!painter && (painterEngine == Painter_DirectX9 || painterEngine == Painter_Any)) {
|
if(!painter && (painterEngine == Painter_DirectX9 || painterEngine == Painter_Any)) {
|
||||||
@@ -240,7 +238,6 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
|||||||
if(g_painter)
|
if(g_painter)
|
||||||
g_painter->unbind();
|
g_painter->unbind();
|
||||||
painter->bind();
|
painter->bind();
|
||||||
g_window.setGraphicsContext(painter->getGraphicsContext());
|
|
||||||
g_painter = painter;
|
g_painter = painter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,11 +253,6 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine)
|
|||||||
void Graphics::resize(const Size& size)
|
void Graphics::resize(const Size& size)
|
||||||
{
|
{
|
||||||
m_viewportSize = size;
|
m_viewportSize = size;
|
||||||
#ifdef PAINTER_DX9
|
|
||||||
if(g_painterDX9)
|
|
||||||
g_painterDX9->setResolution(size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PAINTER_OGL1
|
#ifdef PAINTER_OGL1
|
||||||
if(g_painterOGL1)
|
if(g_painterOGL1)
|
||||||
g_painterOGL1->setResolution(size);
|
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/graphics/graphics.h>
|
||||||
#include <framework/platform/platformwindow.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()
|
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_glTextureId = 0;
|
||||||
m_oldStateIndex = 0;
|
m_oldStateIndex = 0;
|
||||||
m_color = Color::white;
|
m_color = Color::white;
|
||||||
@@ -53,7 +35,6 @@ PainterOGL::PainterOGL()
|
|||||||
m_shaderProgram = nullptr;
|
m_shaderProgram = nullptr;
|
||||||
m_texture = nullptr;
|
m_texture = nullptr;
|
||||||
m_alphaWriting = false;
|
m_alphaWriting = false;
|
||||||
|
|
||||||
setResolution(g_window.getSize());
|
setResolution(g_window.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +286,6 @@ void PainterOGL::updateGlBlendEquation()
|
|||||||
{
|
{
|
||||||
if(!g_graphics.canUseBlendEquation())
|
if(!g_graphics.canUseBlendEquation())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(m_blendEquation == BlendEquation_Add)
|
if(m_blendEquation == BlendEquation_Add)
|
||||||
glBlendEquation(0x8006); // GL_FUNC_ADD
|
glBlendEquation(0x8006); // GL_FUNC_ADD
|
||||||
else if(m_blendEquation == BlendEquation_Max)
|
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/declarations.h>
|
||||||
#include <framework/graphics/coordsbuffer.h>
|
#include <framework/graphics/coordsbuffer.h>
|
||||||
#include <framework/graphics/graphicscontext.h>
|
|
||||||
#include <framework/graphics/paintershaderprogram.h>
|
#include <framework/graphics/paintershaderprogram.h>
|
||||||
#include <framework/graphics/texture.h>
|
#include <framework/graphics/texture.h>
|
||||||
|
|
||||||
@@ -96,7 +95,6 @@ public:
|
|||||||
float getOpacity() { return m_opacity; }
|
float getOpacity() { return m_opacity; }
|
||||||
Rect getClipRect() { return m_clipRect; }
|
Rect getClipRect() { return m_clipRect; }
|
||||||
CompositionMode getCompositionMode() { return m_compositionMode; }
|
CompositionMode getCompositionMode() { return m_compositionMode; }
|
||||||
GraphicsContextPtr getGraphicsContext() { return m_graphicsContext; }
|
|
||||||
|
|
||||||
virtual void setCompositionMode(CompositionMode compositionMode) = 0;
|
virtual void setCompositionMode(CompositionMode compositionMode) = 0;
|
||||||
|
|
||||||
@@ -118,7 +116,6 @@ protected:
|
|||||||
Size m_resolution;
|
Size m_resolution;
|
||||||
float m_opacity;
|
float m_opacity;
|
||||||
Rect m_clipRect;
|
Rect m_clipRect;
|
||||||
GraphicsContextPtr m_graphicsContext;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Painter *g_painter;
|
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;
|
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()
|
Texture::~Texture()
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
assert(!g_app.isTerminated());
|
assert(!g_app.isTerminated());
|
||||||
#endif
|
#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;
|
if(!setupSize(image->getSize(), buildMipmaps))
|
||||||
setupTranformMatrix(size, size);
|
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;
|
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) {
|
if(m_upsideDown) {
|
||||||
m_transformMatrix = { 1.0f/textureSize.width(), 0.0f, 0.0f,
|
m_transformMatrix = { 1.0f/m_glSize.width(), 0.0f, 0.0f,
|
||||||
0.0f, -1.0f/textureSize.height(), 0.0f,
|
0.0f, -1.0f/m_glSize.height(), 0.0f,
|
||||||
0.0f, realSize.height()/(float)textureSize.height(), 1.0f };
|
0.0f, m_size.height()/(float)m_glSize.height(), 1.0f };
|
||||||
} else {
|
} else {
|
||||||
m_transformMatrix = { 1.0f/textureSize.width(), 0.0f, 0.0f,
|
m_transformMatrix = { 1.0f/m_glSize.width(), 0.0f, 0.0f,
|
||||||
0.0f, 1.0f/textureSize.height(), 0.0f,
|
0.0f, 1.0f/m_glSize.height(), 0.0f,
|
||||||
0.0f, 0.0f, 1.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:
|
public:
|
||||||
Texture();
|
Texture();
|
||||||
|
Texture(const Size& size);
|
||||||
|
Texture(const ImagePtr& image, bool buildMipmaps = false, bool compress = false);
|
||||||
virtual ~Texture();
|
virtual ~Texture();
|
||||||
|
|
||||||
virtual void setSmooth(bool) {}
|
void uploadPixels(const ImagePtr& image, bool buildMipmaps = false, bool compress = false);
|
||||||
virtual void setRepeat(bool) {}
|
void bind();
|
||||||
virtual void setUpsideDown(bool) {}
|
void copyFromScreen(const Rect& screenRect);
|
||||||
|
virtual bool buildHardwareMipmaps();
|
||||||
virtual bool setupSize(const Size& size, bool);
|
|
||||||
virtual void copyFromScreen(const Rect&) {}
|
|
||||||
virtual bool buildHardwareMipmaps() { return false; }
|
|
||||||
virtual void uploadPixels(const ImagePtr&, bool) {}
|
|
||||||
|
|
||||||
|
virtual void setSmooth(bool smooth);
|
||||||
|
virtual void setRepeat(bool repeat);
|
||||||
|
void setUpsideDown(bool upsideDown);
|
||||||
void setTime(ticks_t time) { m_time = time; }
|
void setTime(ticks_t time) { m_time = time; }
|
||||||
void setupTranformMatrix(const Size& textureSize, const Size& realSize);
|
|
||||||
|
|
||||||
uint getId() { return m_id; }
|
uint getId() { return m_id; }
|
||||||
ticks_t getTime() { return m_time; }
|
ticks_t getTime() { return m_time; }
|
||||||
int getWidth() { return m_size.width(); }
|
int getWidth() { return m_size.width(); }
|
||||||
int getHeight() { return m_size.height(); }
|
int getHeight() { return m_size.height(); }
|
||||||
const Size& getSize() { return m_size; }
|
const Size& getSize() { return m_size; }
|
||||||
|
const Size& getGlSize() { return m_glSize; }
|
||||||
const Matrix3& getTransformMatrix() { return m_transformMatrix; }
|
const Matrix3& getTransformMatrix() { return m_transformMatrix; }
|
||||||
bool isEmpty() { return m_id == 0; }
|
bool isEmpty() { return m_id == 0; }
|
||||||
bool hasRepeat() { return m_repeat; }
|
bool hasRepeat() { return m_repeat; }
|
||||||
@@ -55,6 +56,13 @@ public:
|
|||||||
virtual bool isAnimatedTexture() { return false; }
|
virtual bool isAnimatedTexture() { return false; }
|
||||||
|
|
||||||
protected:
|
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;
|
uint m_id;
|
||||||
ticks_t m_time;
|
ticks_t m_time;
|
||||||
Size m_size;
|
Size m_size;
|
||||||
|
@@ -29,7 +29,6 @@
|
|||||||
#include <framework/core/clock.h>
|
#include <framework/core/clock.h>
|
||||||
#include <framework/core/eventdispatcher.h>
|
#include <framework/core/eventdispatcher.h>
|
||||||
#include <framework/graphics/apngloader.h>
|
#include <framework/graphics/apngloader.h>
|
||||||
#include "ogl/textureogl.h"
|
|
||||||
|
|
||||||
TextureManager g_textures;
|
TextureManager g_textures;
|
||||||
|
|
||||||
@@ -147,7 +146,7 @@ TexturePtr TextureManager::loadTexture(std::stringstream& file)
|
|||||||
texture = animatedTexture;
|
texture = animatedTexture;
|
||||||
} else {
|
} else {
|
||||||
ImagePtr image = ImagePtr(new Image(imageSize, apng.bpp, apng.pdata));
|
ImagePtr image = ImagePtr(new Image(imageSize, apng.bpp, apng.pdata));
|
||||||
texture = TexturePtr(new TextureOGL(image));
|
texture = TexturePtr(new Texture(image));
|
||||||
}
|
}
|
||||||
free_apng(&apng);
|
free_apng(&apng);
|
||||||
}
|
}
|
||||||
|
@@ -20,9 +20,6 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MOUSE_H
|
|
||||||
#define MOUSE_H
|
|
||||||
|
|
||||||
#include <framework/global.h>
|
#include <framework/global.h>
|
||||||
|
|
||||||
class Mouse
|
class Mouse
|
||||||
@@ -46,5 +43,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern Mouse g_mouse;
|
extern Mouse g_mouse;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@@ -577,20 +577,19 @@ int LuaInterface::lua_dofile(lua_State* L)
|
|||||||
|
|
||||||
int LuaInterface::lua_dofiles(lua_State* L)
|
int LuaInterface::lua_dofiles(lua_State* L)
|
||||||
{
|
{
|
||||||
|
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();
|
std::string directory = g_lua.popString();
|
||||||
|
g_lua.loadFiles(directory, recursive, contains);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1247,3 +1246,29 @@ int LuaInterface::getTop()
|
|||||||
{
|
{
|
||||||
return lua_gettop(L);
|
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()); }
|
void clearStack() { pop(stackSize()); }
|
||||||
bool hasIndex(int index) { return (stackSize() >= (index < 0 ? -index : index) && index != 0); }
|
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
|
/// Pushes any type onto the stack
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
int polymorphicPush(const T& v, const Args&... 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>("setImageFixedRatio", &UIWidget::setImageFixedRatio);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageRepeated", &UIWidget::setImageRepeated);
|
g_lua.bindClassMemberFunction<UIWidget>("setImageRepeated", &UIWidget::setImageRepeated);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageSmooth", &UIWidget::setImageSmooth);
|
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>("setImageBorderTop", &UIWidget::setImageBorderTop);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderRight", &UIWidget::setImageBorderRight);
|
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderRight", &UIWidget::setImageBorderRight);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderBottom", &UIWidget::setImageBorderBottom);
|
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>("getImageColor", &UIWidget::getImageColor);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("isImageFixedRatio", &UIWidget::isImageFixedRatio);
|
g_lua.bindClassMemberFunction<UIWidget>("isImageFixedRatio", &UIWidget::isImageFixedRatio);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("isImageSmooth", &UIWidget::isImageSmooth);
|
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>("getImageBorderTop", &UIWidget::getImageBorderTop);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderRight", &UIWidget::getImageBorderRight);
|
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderRight", &UIWidget::getImageBorderRight);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderBottom", &UIWidget::getImageBorderBottom);
|
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderBottom", &UIWidget::getImageBorderBottom);
|
||||||
|
@@ -27,16 +27,17 @@
|
|||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
asio::io_service g_ioService;
|
asio::io_service g_ioService;
|
||||||
|
std::list<std::shared_ptr<asio::streambuf>> Connection::m_outputStreams;
|
||||||
|
|
||||||
Connection::Connection() :
|
Connection::Connection() :
|
||||||
m_readTimer(g_ioService),
|
m_readTimer(g_ioService),
|
||||||
m_writeTimer(g_ioService),
|
m_writeTimer(g_ioService),
|
||||||
|
m_delayedWriteTimer(g_ioService),
|
||||||
m_resolver(g_ioService),
|
m_resolver(g_ioService),
|
||||||
m_socket(g_ioService)
|
m_socket(g_ioService)
|
||||||
{
|
{
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
m_connecting = false;
|
m_connecting = false;
|
||||||
m_sendBufferSize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::~Connection()
|
Connection::~Connection()
|
||||||
@@ -56,34 +57,7 @@ void Connection::poll()
|
|||||||
void Connection::terminate()
|
void Connection::terminate()
|
||||||
{
|
{
|
||||||
g_ioService.stop();
|
g_ioService.stop();
|
||||||
}
|
m_outputStreams.clear();
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::close()
|
void Connection::close()
|
||||||
@@ -92,8 +66,8 @@ void Connection::close()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// flush send data before disconnecting on clean connections
|
// flush send data before disconnecting on clean connections
|
||||||
if(m_connected && !m_error && m_sendBufferSize > 0 && m_sendEvent)
|
if(m_connected && !m_error && m_outputStream)
|
||||||
m_sendEvent->execute();
|
internal_write();
|
||||||
|
|
||||||
m_connecting = false;
|
m_connecting = false;
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
@@ -104,6 +78,7 @@ void Connection::close()
|
|||||||
m_resolver.cancel();
|
m_resolver.cancel();
|
||||||
m_readTimer.cancel();
|
m_readTimer.cancel();
|
||||||
m_writeTimer.cancel();
|
m_writeTimer.cancel();
|
||||||
|
m_delayedWriteTimer.cancel();
|
||||||
|
|
||||||
if(m_socket.is_open()) {
|
if(m_socket.is_open()) {
|
||||||
boost::system::error_code ec;
|
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)
|
if(!m_connected)
|
||||||
return;
|
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
|
// we can't send the data right away, otherwise we could create tcp congestion
|
||||||
memcpy(m_sendBuffer + m_sendBufferSize, buffer, size);
|
if(!m_outputStream) {
|
||||||
m_sendBufferSize += size;
|
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()) {
|
m_delayedWriteTimer.cancel();
|
||||||
auto self = asConnection();
|
m_delayedWriteTimer.expires_from_now(boost::posix_time::milliseconds(10));
|
||||||
|
m_delayedWriteTimer.async_wait(std::bind(&Connection::onCanWrite, asConnection(), std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
// wait 1 ms to do the real send
|
std::ostream os(m_outputStream.get());
|
||||||
m_sendEvent = g_dispatcher.scheduleEvent([=] {
|
os.write((const char*)buffer, size);
|
||||||
if(self.is_unique())
|
os.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::internal_write()
|
||||||
|
{
|
||||||
|
if(!m_connected)
|
||||||
return;
|
return;
|
||||||
//m_writeTimer.cancel();
|
|
||||||
|
std::shared_ptr<asio::streambuf> outputStream = m_outputStream;
|
||||||
|
m_outputStream = nullptr;
|
||||||
|
|
||||||
asio::async_write(m_socket,
|
asio::async_write(m_socket,
|
||||||
asio::buffer(m_sendBuffer, m_sendBufferSize),
|
*outputStream,
|
||||||
std::bind(&Connection::onWrite, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
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.expires_from_now(boost::posix_time::seconds(WRITE_TIMEOUT));
|
||||||
m_writeTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
m_writeTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||||
|
|
||||||
m_sendBufferSize = 0;
|
|
||||||
}, SEND_INTERVAL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::read(uint16 bytes, const RecvCallback& callback)
|
void Connection::read(uint16 bytes, const RecvCallback& callback)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
|
||||||
|
|
||||||
if(!m_connected)
|
if(!m_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_recvCallback = callback;
|
m_recvCallback = callback;
|
||||||
|
|
||||||
asio::async_read(m_socket,
|
asio::async_read(m_socket,
|
||||||
asio::buffer(m_streamBuffer.prepare(bytes)),
|
asio::buffer(m_inputStream.prepare(bytes)),
|
||||||
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, 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.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::read_until(const std::string& what, const RecvCallback& callback)
|
void Connection::read_until(const std::string& what, const RecvCallback& callback)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
|
||||||
|
|
||||||
if(!m_connected)
|
if(!m_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_recvCallback = callback;
|
m_recvCallback = callback;
|
||||||
|
|
||||||
asio::async_read_until(m_socket,
|
asio::async_read_until(m_socket,
|
||||||
m_streamBuffer,
|
m_inputStream,
|
||||||
what.c_str(),
|
what.c_str(),
|
||||||
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
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.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::read_some(const RecvCallback& callback)
|
void Connection::read_some(const RecvCallback& callback)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
|
||||||
|
|
||||||
if(!m_connected)
|
if(!m_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_recvCallback = callback;
|
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));
|
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.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
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)
|
void Connection::onConnect(const boost::system::error_code& error)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
m_readTimer.cancel();
|
||||||
|
m_activityTimer.restart();
|
||||||
|
|
||||||
|
if(error == asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
if(!error) {
|
if(!error) {
|
||||||
m_connected = true;
|
m_connected = true;
|
||||||
@@ -216,52 +235,73 @@ void Connection::onConnect(const boost::system::error_code& error)
|
|||||||
m_connecting = false;
|
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();
|
m_writeTimer.cancel();
|
||||||
|
|
||||||
if(!m_connected)
|
if(error == asio::error::operation_aborted)
|
||||||
return;
|
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);
|
handleError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::onRecv(const boost::system::error_code& error, size_t recvSize)
|
void Connection::onRecv(const boost::system::error_code& error, size_t recvSize)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
m_readTimer.cancel();
|
||||||
|
m_activityTimer.restart();
|
||||||
|
|
||||||
if(!m_connected)
|
if(error == asio::error::operation_aborted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(m_connected) {
|
||||||
if(!error) {
|
if(!error) {
|
||||||
if(m_recvCallback) {
|
if(m_recvCallback) {
|
||||||
const char* header = boost::asio::buffer_cast<const char*>(m_streamBuffer.data());
|
const char* header = boost::asio::buffer_cast<const char*>(m_inputStream.data());
|
||||||
m_recvCallback((uint8*)header, recvSize);
|
m_recvCallback((uint8*)header, recvSize);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
handleError(error);
|
handleError(error);
|
||||||
|
}
|
||||||
|
|
||||||
m_streamBuffer.consume(recvSize);
|
if(!error)
|
||||||
|
m_inputStream.consume(recvSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::onTimeout(const boost::system::error_code& error)
|
void Connection::onTimeout(const boost::system::error_code& error)
|
||||||
{
|
{
|
||||||
if(error != asio::error::operation_aborted)
|
if(error == asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
handleError(asio::error::timed_out);
|
handleError(asio::error::timed_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::handleError(const boost::system::error_code& error)
|
void Connection::handleError(const boost::system::error_code& error)
|
||||||
{
|
{
|
||||||
if(error != asio::error::operation_aborted) {
|
if(error == asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
m_error = error;
|
m_error = error;
|
||||||
if(m_errorCallback)
|
if(m_errorCallback)
|
||||||
m_errorCallback(error);
|
m_errorCallback(error);
|
||||||
if(m_connected || m_connecting)
|
if(m_connected || m_connecting)
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int Connection::getIp()
|
int Connection::getIp()
|
||||||
{
|
{
|
||||||
|
@@ -36,7 +36,6 @@ class Connection : public LuaObject
|
|||||||
enum {
|
enum {
|
||||||
READ_TIMEOUT = 30,
|
READ_TIMEOUT = 30,
|
||||||
WRITE_TIMEOUT = 30,
|
WRITE_TIMEOUT = 30,
|
||||||
SEND_INTERVAL = 1,
|
|
||||||
SEND_BUFFER_SIZE = 65536,
|
SEND_BUFFER_SIZE = 65536,
|
||||||
RECV_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 connect(const std::string& host, uint16 port, const std::function<void()>& connectCallback);
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
void write(uint8* buffer, uint16 size);
|
void write(uint8* buffer, size_t size);
|
||||||
void read(uint16 bytes, const RecvCallback& callback);
|
void read(uint16 bytes, const RecvCallback& callback);
|
||||||
void read_until(const std::string& what, const RecvCallback& callback);
|
void read_until(const std::string& what, const RecvCallback& callback);
|
||||||
void read_some(const RecvCallback& callback);
|
void read_some(const RecvCallback& callback);
|
||||||
@@ -62,11 +61,17 @@ public:
|
|||||||
boost::system::error_code getError() { return m_error; }
|
boost::system::error_code getError() { return m_error; }
|
||||||
bool isConnecting() { return m_connecting; }
|
bool isConnecting() { return m_connecting; }
|
||||||
bool isConnected() { return m_connected; }
|
bool isConnected() { return m_connected; }
|
||||||
|
ticks_t getElapsedTicksSinceLastRead() { return m_connected ? m_activityTimer.elapsed_millis() : -1; }
|
||||||
|
|
||||||
ConnectionPtr asConnection() { return static_self_cast<Connection>(); }
|
ConnectionPtr asConnection() { return static_self_cast<Connection>(); }
|
||||||
|
|
||||||
protected:
|
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 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 onRecv(const boost::system::error_code& error, size_t recvSize);
|
||||||
void onTimeout(const boost::system::error_code& error);
|
void onTimeout(const boost::system::error_code& error);
|
||||||
void handleError(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_readTimer;
|
||||||
asio::deadline_timer m_writeTimer;
|
asio::deadline_timer m_writeTimer;
|
||||||
|
asio::deadline_timer m_delayedWriteTimer;
|
||||||
asio::ip::tcp::resolver m_resolver;
|
asio::ip::tcp::resolver m_resolver;
|
||||||
asio::ip::tcp::socket m_socket;
|
asio::ip::tcp::socket m_socket;
|
||||||
|
|
||||||
uint8 m_sendBuffer[SEND_BUFFER_SIZE];
|
static std::list<std::shared_ptr<asio::streambuf>> m_outputStreams;
|
||||||
asio::streambuf m_streamBuffer;
|
std::shared_ptr<asio::streambuf> m_outputStream;
|
||||||
|
asio::streambuf m_inputStream;
|
||||||
bool m_connected;
|
bool m_connected;
|
||||||
bool m_connecting;
|
bool m_connecting;
|
||||||
boost::system::error_code m_error;
|
boost::system::error_code m_error;
|
||||||
int m_sendBufferSize;
|
stdext::timer m_activityTimer;
|
||||||
Timer m_sendTimer;
|
|
||||||
ScheduledEventPtr m_sendEvent;
|
|
||||||
|
|
||||||
friend class Server;
|
friend class Server;
|
||||||
};
|
};
|
||||||
|
@@ -42,6 +42,8 @@ public:
|
|||||||
|
|
||||||
bool isConnected();
|
bool isConnected();
|
||||||
bool isConnecting();
|
bool isConnecting();
|
||||||
|
ticks_t getElapsedTicksSinceLastRead() { return m_connection ? m_connection->getElapsedTicksSinceLastRead() : -1; }
|
||||||
|
|
||||||
ConnectionPtr getConnection() { return m_connection; }
|
ConnectionPtr getConnection() { return m_connection; }
|
||||||
void setConnection(const ConnectionPtr& connection) { m_connection = connection; }
|
void setConnection(const ConnectionPtr& connection) { m_connection = connection; }
|
||||||
|
|
||||||
|
@@ -23,6 +23,8 @@
|
|||||||
#ifndef CRASHHANDLER_H
|
#ifndef CRASHHANDLER_H
|
||||||
#define CRASHHANDLER_H
|
#define CRASHHANDLER_H
|
||||||
|
|
||||||
|
#ifdef CRASH_HANDLER
|
||||||
void installCrashHandler();
|
void installCrashHandler();
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -45,6 +45,7 @@ public:
|
|||||||
std::string getCPUName();
|
std::string getCPUName();
|
||||||
double getTotalSystemMemory();
|
double getTotalSystemMemory();
|
||||||
std::string getOSName();
|
std::string getOSName();
|
||||||
|
std::string traceback(const std::string& where, int level = 1, int maxDepth = 32);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Platform g_platform;
|
extern Platform g_platform;
|
||||||
|
@@ -22,20 +22,13 @@
|
|||||||
|
|
||||||
#include "platformwindow.h"
|
#include "platformwindow.h"
|
||||||
|
|
||||||
#ifdef SDL
|
|
||||||
#include "sdlwindow.h"
|
|
||||||
SDLWindow window;
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include "win32window.h"
|
#include "win32window.h"
|
||||||
WIN32Window window;
|
WIN32Window window;
|
||||||
WIN32Window& g_win32Window = window;
|
|
||||||
#else
|
#else
|
||||||
#include "x11window.h"
|
#include "x11window.h"
|
||||||
#include <framework/core/clock.h>
|
#include <framework/core/clock.h>
|
||||||
X11Window window;
|
X11Window window;
|
||||||
X11Window& g_x11Window = window;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <framework/core/clock.h>
|
#include <framework/core/clock.h>
|
||||||
@@ -65,19 +58,6 @@ int PlatformWindow::loadMouseCursor(const std::string& file, const Point& hotSpo
|
|||||||
return internalLoadMouseCursor(image, hotSpot);
|
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()
|
void PlatformWindow::updateUnmaximizedCoords()
|
||||||
{
|
{
|
||||||
if(!isMaximized() && !isFullscreen()) {
|
if(!isMaximized() && !isFullscreen()) {
|
||||||
|
@@ -27,13 +27,12 @@
|
|||||||
#include <framework/core/inputevent.h>
|
#include <framework/core/inputevent.h>
|
||||||
#include <framework/core/timer.h>
|
#include <framework/core/timer.h>
|
||||||
#include <framework/graphics/declarations.h>
|
#include <framework/graphics/declarations.h>
|
||||||
#include <framework/graphics/graphicscontext.h>
|
|
||||||
|
|
||||||
//@bindsingleton g_window
|
//@bindsingleton g_window
|
||||||
class PlatformWindow
|
class PlatformWindow
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
KEY_PRESS_REPEAT_INTERVAL = 30
|
KEY_PRESS_REPEAT_INTERVAL = 30,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::function<void(const Size&)> OnResizeCallback;
|
typedef std::function<void(const Size&)> OnResizeCallback;
|
||||||
@@ -58,16 +57,12 @@ public:
|
|||||||
virtual void setMouseCursor(int cursorId) = 0;
|
virtual void setMouseCursor(int cursorId) = 0;
|
||||||
virtual void restoreMouseCursor() = 0;
|
virtual void restoreMouseCursor() = 0;
|
||||||
|
|
||||||
virtual void showTextInput() { }
|
|
||||||
virtual void hideTextInput() { }
|
|
||||||
|
|
||||||
virtual void setTitle(const std::string& title) = 0;
|
virtual void setTitle(const std::string& title) = 0;
|
||||||
virtual void setMinimumSize(const Size& minimumSize) = 0;
|
virtual void setMinimumSize(const Size& minimumSize) = 0;
|
||||||
virtual void setFullscreen(bool fullscreen) = 0;
|
virtual void setFullscreen(bool fullscreen) = 0;
|
||||||
virtual void setVerticalSync(bool enable) = 0;
|
virtual void setVerticalSync(bool enable) = 0;
|
||||||
virtual void setIcon(const std::string& iconFile) = 0;
|
virtual void setIcon(const std::string& iconFile) = 0;
|
||||||
virtual void setClipboardText(const std::string& text) = 0;
|
virtual void setClipboardText(const std::string& text) = 0;
|
||||||
void setGraphicsContext(const GraphicsContextPtr& graphicsContext);
|
|
||||||
|
|
||||||
virtual Size getDisplaySize() = 0;
|
virtual Size getDisplaySize() = 0;
|
||||||
virtual std::string getClipboardText() = 0;
|
virtual std::string getClipboardText() = 0;
|
||||||
@@ -132,8 +127,6 @@ protected:
|
|||||||
std::function<void()> m_onClose;
|
std::function<void()> m_onClose;
|
||||||
OnResizeCallback m_onResize;
|
OnResizeCallback m_onResize;
|
||||||
OnInputEventCallback m_onInputEvent;
|
OnInputEventCallback m_onInputEvent;
|
||||||
|
|
||||||
GraphicsContextPtr m_graphicsContext;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern PlatformWindow& g_window;
|
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.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if !defined(WIN32) && defined(CRASH_HANDLER)
|
||||||
|
|
||||||
#include "crashhandler.h"
|
#include "crashhandler.h"
|
||||||
#include <framework/global.h>
|
#include <framework/global.h>
|
||||||
#include <framework/core/application.h>
|
#include <framework/core/application.h>
|
||||||
@@ -131,3 +133,5 @@ void installCrashHandler()
|
|||||||
sigaction(SIGFPE, &sa, NULL); // floating-point exception
|
sigaction(SIGFPE, &sa, NULL); // floating-point exception
|
||||||
sigaction(SIGABRT, &sa, NULL); // process aborted (asserts)
|
sigaction(SIGABRT, &sa, NULL); // process aborted (asserts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -27,6 +29,7 @@
|
|||||||
#include <framework/stdext/stdext.h>
|
#include <framework/stdext/stdext.h>
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <execinfo.h>
|
||||||
|
|
||||||
void Platform::processArgs(std::vector<std::string>& args)
|
void Platform::processArgs(std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
@@ -36,7 +39,7 @@ void Platform::processArgs(std::vector<std::string>& args)
|
|||||||
bool Platform::spawnProcess(std::string process, const std::vector<std::string>& args)
|
bool Platform::spawnProcess(std::string process, const std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
struct stat sts;
|
struct stat sts;
|
||||||
if(stat(process.c_str(), &sts) == -1)
|
if(stat(process.c_str(), &sts) == -1 && errno == ENOENT)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
@@ -165,3 +168,36 @@ std::string Platform::getOSName()
|
|||||||
}
|
}
|
||||||
return std::string();
|
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.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(WIN32) && defined(CRASH_HANDLER)
|
||||||
|
|
||||||
#include "crashhandler.h"
|
#include "crashhandler.h"
|
||||||
#include <framework/global.h>
|
#include <framework/global.h>
|
||||||
#include <framework/core/application.h>
|
#include <framework/core/application.h>
|
||||||
@@ -156,3 +158,5 @@ void installCrashHandler()
|
|||||||
{
|
{
|
||||||
SetUnhandledExceptionFilter(ExceptionHandler);
|
SetUnhandledExceptionFilter(ExceptionHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <framework/stdext/stdext.h>
|
#include <framework/stdext/stdext.h>
|
||||||
@@ -411,3 +413,14 @@ std::string Platform::getOSName()
|
|||||||
}
|
}
|
||||||
return ret;
|
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.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
#include "win32window.h"
|
#include "win32window.h"
|
||||||
#include <framework/graphics/image.h>
|
#include <framework/graphics/image.h>
|
||||||
#include <framework/core/application.h>
|
#include <framework/core/application.h>
|
||||||
#include <framework/core/resourcemanager.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)))
|
#define HSB_BIT_SET(p, n) (p[(n)/8] |= (128 >>((n)%8)))
|
||||||
|
|
||||||
WIN32Window::WIN32Window()
|
WIN32Window::WIN32Window()
|
||||||
{
|
{
|
||||||
m_window = 0;
|
m_window = 0;
|
||||||
m_instance = 0;
|
m_instance = 0;
|
||||||
|
m_deviceContext = 0;
|
||||||
m_cursor = 0;
|
m_cursor = 0;
|
||||||
m_minimumSize = Size(600,480);
|
m_minimumSize = Size(600,480);
|
||||||
m_size = Size(600,480);
|
m_size = Size(600,480);
|
||||||
m_hidden = true;
|
m_hidden = true;
|
||||||
m_deviceContext = 0;
|
|
||||||
|
|
||||||
#ifndef OPENGL_ES
|
#ifdef OPENGL_ES
|
||||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextWGL);
|
m_eglConfig = 0;
|
||||||
|
m_eglContext = 0;
|
||||||
|
m_eglDisplay = 0;
|
||||||
|
m_eglSurface = 0;
|
||||||
#else
|
#else
|
||||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextEGL);
|
m_wglContext = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_keyMap[VK_ESCAPE] = Fw::KeyEscape;
|
m_keyMap[VK_ESCAPE] = Fw::KeyEscape;
|
||||||
@@ -204,9 +203,30 @@ WIN32Window::WIN32Window()
|
|||||||
void WIN32Window::init()
|
void WIN32Window::init()
|
||||||
{
|
{
|
||||||
m_instance = GetModuleHandle(NULL);
|
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();
|
internalCreateWindow();
|
||||||
m_graphicsContext->create();
|
internalCreateGLContext();
|
||||||
m_graphicsContext->restore();
|
internalRestoreGLContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN32Window::terminate()
|
void WIN32Window::terminate()
|
||||||
@@ -221,7 +241,7 @@ void WIN32Window::terminate()
|
|||||||
DestroyCursor(cursor);
|
DestroyCursor(cursor);
|
||||||
m_cursors.clear();
|
m_cursors.clear();
|
||||||
|
|
||||||
m_graphicsContext->destroy();
|
internalDestroyGLContext();
|
||||||
|
|
||||||
if(m_deviceContext) {
|
if(m_deviceContext) {
|
||||||
if(!ReleaseDC(m_window, m_deviceContext))
|
if(!ReleaseDC(m_window, m_deviceContext))
|
||||||
@@ -298,6 +318,154 @@ void WIN32Window::internalCreateWindow()
|
|||||||
g_logger.fatal("GetDC failed");
|
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)
|
void WIN32Window::move(const Point& pos)
|
||||||
{
|
{
|
||||||
Rect clientRect(pos, getClientRect().size());
|
Rect clientRect(pos, getClientRect().size());
|
||||||
@@ -456,6 +624,9 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_SYSKEYDOWN: {
|
case WM_SYSKEYDOWN: {
|
||||||
|
if(wParam == VK_F4 && m_inputEvent.keyboardModifiers & Fw::KeyboardAltModifier)
|
||||||
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
|
|
||||||
processKeyDown(retranslateVirtualKey(wParam, lParam));
|
processKeyDown(retranslateVirtualKey(wParam, lParam));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -571,8 +742,8 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_visible)
|
if(m_visible && m_deviceContext)
|
||||||
m_graphicsContext->restore();
|
internalRestoreGLContext();
|
||||||
|
|
||||||
Size size = Size(LOWORD(lParam), HIWORD(lParam));
|
Size size = Size(LOWORD(lParam), HIWORD(lParam));
|
||||||
size.setWidth(std::max(std::min(size.width(), 7680), 32));
|
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()
|
void WIN32Window::swapBuffers()
|
||||||
{
|
{
|
||||||
m_graphicsContext->swapBuffers();
|
#ifdef OPENGL_ES
|
||||||
|
eglSwapBuffers(m_eglDisplay, m_eglSurface);
|
||||||
|
#else
|
||||||
|
SwapBuffers(m_deviceContext);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN32Window::showMouse()
|
void WIN32Window::showMouse()
|
||||||
@@ -690,7 +865,19 @@ void WIN32Window::setFullscreen(bool fullscreen)
|
|||||||
|
|
||||||
void WIN32Window::setVerticalSync(bool enable)
|
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)
|
void WIN32Window::setIcon(const std::string& file)
|
||||||
@@ -783,7 +970,11 @@ std::string WIN32Window::getClipboardText()
|
|||||||
|
|
||||||
std::string WIN32Window::getPlatformType()
|
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()
|
Rect WIN32Window::getClientRect()
|
||||||
@@ -831,3 +1022,5 @@ Rect WIN32Window::adjustWindowRect(const Rect& clientRect)
|
|||||||
}
|
}
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@@ -24,13 +24,28 @@
|
|||||||
#define WIN32WINDOW_H
|
#define WIN32WINDOW_H
|
||||||
|
|
||||||
#include "platformwindow.h"
|
#include "platformwindow.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
#ifdef OPENGL_ES
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DIRECTX
|
||||||
|
#include <d3d9.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct WindowProcProxy;
|
struct WindowProcProxy;
|
||||||
|
|
||||||
class WIN32Window : public PlatformWindow
|
class WIN32Window : public PlatformWindow
|
||||||
{
|
{
|
||||||
void internalCreateWindow();
|
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);
|
LRESULT windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
friend class WindowProcProxy;
|
friend class WindowProcProxy;
|
||||||
@@ -67,8 +82,6 @@ public:
|
|||||||
Size getDisplaySize();
|
Size getDisplaySize();
|
||||||
std::string getClipboardText();
|
std::string getClipboardText();
|
||||||
std::string getPlatformType();
|
std::string getPlatformType();
|
||||||
HWND getWindow() { return m_window; }
|
|
||||||
HDC getDisplay() { return m_deviceContext; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot);
|
int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot);
|
||||||
@@ -79,14 +92,26 @@ private:
|
|||||||
Rect adjustWindowRect(const Rect& rect);
|
Rect adjustWindowRect(const Rect& rect);
|
||||||
|
|
||||||
std::vector<HCURSOR> m_cursors;
|
std::vector<HCURSOR> m_cursors;
|
||||||
HDC m_deviceContext;
|
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
HINSTANCE m_instance;
|
HINSTANCE m_instance;
|
||||||
|
HDC m_deviceContext;
|
||||||
HCURSOR m_cursor;
|
HCURSOR m_cursor;
|
||||||
HCURSOR m_defaultCursor;
|
HCURSOR m_defaultCursor;
|
||||||
bool m_hidden;
|
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
|
#endif
|
||||||
|
@@ -20,17 +20,13 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
|
||||||
#include "x11window.h"
|
#include "x11window.h"
|
||||||
#include <framework/core/resourcemanager.h>
|
#include <framework/core/resourcemanager.h>
|
||||||
#include <framework/graphics/image.h>
|
#include <framework/graphics/image.h>
|
||||||
#include <unistd.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)))
|
#define LSB_BIT_SET(p, n) (p[(n)/8] |= (1 <<((n)%8)))
|
||||||
|
|
||||||
X11Window::X11Window()
|
X11Window::X11Window()
|
||||||
@@ -48,10 +44,15 @@ X11Window::X11Window()
|
|||||||
m_wmDelete = 0;
|
m_wmDelete = 0;
|
||||||
m_minimumSize = Size(600,480);
|
m_minimumSize = Size(600,480);
|
||||||
m_size = 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
|
#else
|
||||||
m_graphicsContext = GraphicsContextPtr(new GraphicsContextEGL);
|
m_fbConfig = 0;
|
||||||
|
m_glxContext = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_keyMap[XK_Escape] = Fw::KeyEscape;
|
m_keyMap[XK_Escape] = Fw::KeyEscape;
|
||||||
@@ -210,7 +211,9 @@ X11Window::X11Window()
|
|||||||
void X11Window::init()
|
void X11Window::init()
|
||||||
{
|
{
|
||||||
internalOpenDisplay();
|
internalOpenDisplay();
|
||||||
m_graphicsContext->create();
|
internalCheckGL();
|
||||||
|
internalChooseGLVisual();
|
||||||
|
internalCreateGLContext();
|
||||||
internalCreateWindow();
|
internalCreateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +243,7 @@ void X11Window::terminate()
|
|||||||
m_colormap = 0;
|
m_colormap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_graphicsContext->destroy();
|
internalDestroyGLContext();
|
||||||
|
|
||||||
if(m_visual) {
|
if(m_visual) {
|
||||||
XFree(m_visual);
|
XFree(m_visual);
|
||||||
@@ -328,7 +331,7 @@ void X11Window::internalCreateWindow()
|
|||||||
if(!internalSetupWindowInput())
|
if(!internalSetupWindowInput())
|
||||||
g_logger.warning("Input of special keys may be messed up, because window input initialization failed");
|
g_logger.warning("Input of special keys may be messed up, because window input initialization failed");
|
||||||
|
|
||||||
m_graphicsContext->restore();
|
internalConnectGLContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool X11Window::internalSetupWindowInput()
|
bool X11Window::internalSetupWindowInput()
|
||||||
@@ -355,6 +358,169 @@ bool X11Window::internalSetupWindowInput()
|
|||||||
return true;
|
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)
|
void X11Window::move(const Point& pos)
|
||||||
{
|
{
|
||||||
m_position = pos;
|
m_position = pos;
|
||||||
@@ -674,7 +840,11 @@ void X11Window::poll()
|
|||||||
|
|
||||||
void X11Window::swapBuffers()
|
void X11Window::swapBuffers()
|
||||||
{
|
{
|
||||||
m_graphicsContext->swapBuffers();
|
#ifdef OPENGL_ES
|
||||||
|
eglSwapBuffers(m_eglDisplay, m_eglSurface);
|
||||||
|
#else
|
||||||
|
glXSwapBuffers(m_display, m_window);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11Window::showMouse()
|
void X11Window::showMouse()
|
||||||
@@ -798,7 +968,20 @@ void X11Window::setFullscreen(bool fullscreen)
|
|||||||
|
|
||||||
void X11Window::setVerticalSync(bool enable)
|
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)
|
void X11Window::setIcon(const std::string& file)
|
||||||
@@ -886,5 +1069,11 @@ std::string X11Window::getClipboardText()
|
|||||||
|
|
||||||
std::string X11Window::getPlatformType()
|
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/Xlib.h>
|
||||||
#include <X11/Xatom.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
|
class X11Window : public PlatformWindow
|
||||||
{
|
{
|
||||||
@@ -38,6 +41,15 @@ class X11Window : public PlatformWindow
|
|||||||
void internalCreateWindow();
|
void internalCreateWindow();
|
||||||
bool internalSetupWindowInput();
|
bool internalSetupWindowInput();
|
||||||
|
|
||||||
|
void internalCheckGL();
|
||||||
|
void internalChooseGLVisual();
|
||||||
|
void internalCreateGLContext();
|
||||||
|
void internalDestroyGLContext();
|
||||||
|
void internalConnectGLContext();
|
||||||
|
|
||||||
|
void *getExtensionProcAddress(const char *ext);
|
||||||
|
bool isExtensionSupported(const char *ext);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
X11Window();
|
X11Window();
|
||||||
|
|
||||||
@@ -63,16 +75,10 @@ public:
|
|||||||
void setVerticalSync(bool enable);
|
void setVerticalSync(bool enable);
|
||||||
void setIcon(const std::string& file);
|
void setIcon(const std::string& file);
|
||||||
void setClipboardText(const std::string& text);
|
void setClipboardText(const std::string& text);
|
||||||
void setVisual(XVisualInfo *visual) { m_visual = visual; }
|
|
||||||
void setRootWindow(const Window& window) { m_rootWindow = window; }
|
|
||||||
|
|
||||||
Size getDisplaySize();
|
Size getDisplaySize();
|
||||||
std::string getClipboardText();
|
std::string getClipboardText();
|
||||||
std::string getPlatformType();
|
std::string getPlatformType();
|
||||||
Window getWindow() { return m_window; }
|
|
||||||
Display *getDisplay() { return m_display; }
|
|
||||||
int getScreen() { return m_screen; }
|
|
||||||
XVisualInfo *getVisual() { return m_visual; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot);
|
int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot);
|
||||||
@@ -91,9 +97,17 @@ private:
|
|||||||
int m_screen;
|
int m_screen;
|
||||||
Atom m_wmDelete;
|
Atom m_wmDelete;
|
||||||
std::string m_clipboardText;
|
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
|
#endif
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user