Compare commits

..

5 Commits

Author SHA1 Message Date
Deve fe5495288e
macOS: use SDL2 (#90) 2022-09-02 00:26:24 +03:00
Maksym H 6e76ef4320
HUD: use the HUD API directly (#92)
Co-authored-by: luk3yx <luk3yx@users.noreply.github.com>
2022-08-29 21:20:56 +03:00
Maksim 7624c29d96 Improve HUD text scaling 2022-08-20 22:12:54 +03:00
Maksim ee2ebbfb91 Improve Pause menu 2022-08-20 22:03:42 +03:00
luk3yx a6299e1cb5 Remove C++ wielded item status text
This clashes with the status text in some games that implement the same 
thing in Lua
2022-08-14 10:11:50 +12:00
28 changed files with 453 additions and 294 deletions

View File

@ -124,6 +124,13 @@
847C6D4B25D6F483008F5FC8 /* lutf8lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 847C6D4A25D6F483008F5FC8 /* lutf8lib.c */; }; 847C6D4B25D6F483008F5FC8 /* lutf8lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 847C6D4A25D6F483008F5FC8 /* lutf8lib.c */; };
848ADEF427BD68AE001C60F3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 848ADEF627BD68AE001C60F3 /* Localizable.strings */; }; 848ADEF427BD68AE001C60F3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 848ADEF627BD68AE001C60F3 /* Localizable.strings */; };
848CE6E527778E38001D3E0F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 848CE6E427778E30001D3E0F /* libz.tbd */; }; 848CE6E527778E38001D3E0F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 848CE6E427778E30001D3E0F /* libz.tbd */; };
8495BD1628B80B14009FCF4D /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8495BD1528B80B00009FCF4D /* libSDL2.a */; };
8495BD1E28B80F0B009FCF4D /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8495BD1D28B80F0B009FCF4D /* ForceFeedback.framework */; };
8495BD2028B80F21009FCF4D /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8495BD1F28B80F21009FCF4D /* Metal.framework */; };
8495BD2228B80F4D009FCF4D /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8495BD2128B80F4D009FCF4D /* AudioToolbox.framework */; };
8495BD2628B80FD1009FCF4D /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8495BD2528B80FD1009FCF4D /* CoreAudio.framework */; };
8495BD2828B810AD009FCF4D /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8495BD2728B810AD009FCF4D /* CoreVideo.framework */; };
8495BD2A28B81170009FCF4D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8495BD2928B81170009FCF4D /* Carbon.framework */; };
849D0847278AC1B200471354 /* lchacha.c in Sources */ = {isa = PBXBuildFile; fileRef = 849D0845278AC1B200471354 /* lchacha.c */; }; 849D0847278AC1B200471354 /* lchacha.c in Sources */ = {isa = PBXBuildFile; fileRef = 849D0845278AC1B200471354 /* lchacha.c */; };
849D0848278AC1B200471354 /* chacha.c in Sources */ = {isa = PBXBuildFile; fileRef = 849D0846278AC1B200471354 /* chacha.c */; }; 849D0848278AC1B200471354 /* chacha.c in Sources */ = {isa = PBXBuildFile; fileRef = 849D0846278AC1B200471354 /* chacha.c */; };
84A1F9B2252E616B00000717 /* semaphore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A1F9AC252E616B00000717 /* semaphore.cpp */; }; 84A1F9B2252E616B00000717 /* semaphore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A1F9AC252E616B00000717 /* semaphore.cpp */; };
@ -565,6 +572,13 @@
848ADF0927BD69C8001C60F3 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; }; 848ADF0927BD69C8001C60F3 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
848ADF0A27BD69CB001C60F3 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; }; 848ADF0A27BD69CB001C60F3 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
848CE6E427778E30001D3E0F /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 848CE6E427778E30001D3E0F /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
8495BD1528B80B00009FCF4D /* libSDL2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libSDL2.a; path = ../deps/SDL2/libSDL2.a; sourceTree = "<group>"; };
8495BD1D28B80F0B009FCF4D /* ForceFeedback.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ForceFeedback.framework; path = System/Library/Frameworks/ForceFeedback.framework; sourceTree = SDKROOT; };
8495BD1F28B80F21009FCF4D /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
8495BD2128B80F4D009FCF4D /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
8495BD2528B80FD1009FCF4D /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
8495BD2728B810AD009FCF4D /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
8495BD2928B81170009FCF4D /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
849D0841278AC1B200471354 /* ecrypt-config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ecrypt-config.h"; path = "../../../../lib/luachacha/ecrypt-config.h"; sourceTree = "<group>"; }; 849D0841278AC1B200471354 /* ecrypt-config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ecrypt-config.h"; path = "../../../../lib/luachacha/ecrypt-config.h"; sourceTree = "<group>"; };
849D0842278AC1B200471354 /* ecrypt-sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ecrypt-sync.h"; path = "../../../../lib/luachacha/ecrypt-sync.h"; sourceTree = "<group>"; }; 849D0842278AC1B200471354 /* ecrypt-sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ecrypt-sync.h"; path = "../../../../lib/luachacha/ecrypt-sync.h"; sourceTree = "<group>"; };
849D0843278AC1B200471354 /* ecrypt-portable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ecrypt-portable.h"; path = "../../../../lib/luachacha/ecrypt-portable.h"; sourceTree = "<group>"; }; 849D0843278AC1B200471354 /* ecrypt-portable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ecrypt-portable.h"; path = "../../../../lib/luachacha/ecrypt-portable.h"; sourceTree = "<group>"; };
@ -896,6 +910,8 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
8495BD2628B80FD1009FCF4D /* CoreAudio.framework in Frameworks */,
8495BD2228B80F4D009FCF4D /* AudioToolbox.framework in Frameworks */,
84585C0724B134900040BA4F /* libcurl.tbd in Frameworks */, 84585C0724B134900040BA4F /* libcurl.tbd in Frameworks */,
848CE6E527778E38001D3E0F /* libz.tbd in Frameworks */, 848CE6E527778E38001D3E0F /* libz.tbd in Frameworks */,
84EEE5E72782729B00F61929 /* libintl.a in Frameworks */, 84EEE5E72782729B00F61929 /* libintl.a in Frameworks */,
@ -906,9 +922,14 @@
8458616924B1B7DC0040BA4F /* libfreetype.a in Frameworks */, 8458616924B1B7DC0040BA4F /* libfreetype.a in Frameworks */,
84C8E20B257804A200C1E5D0 /* libopenal.1.dylib in Frameworks */, 84C8E20B257804A200C1E5D0 /* libopenal.1.dylib in Frameworks */,
84463B9924B258B50099DFBD /* OpenGL.framework in Frameworks */, 84463B9924B258B50099DFBD /* OpenGL.framework in Frameworks */,
8495BD1628B80B14009FCF4D /* libSDL2.a in Frameworks */,
8495BD2A28B81170009FCF4D /* Carbon.framework in Frameworks */,
8458616A24B1B7E20040BA4F /* libIrrlicht.a in Frameworks */, 8458616A24B1B7E20040BA4F /* libIrrlicht.a in Frameworks */,
84463B9324B258B00099DFBD /* IOKit.framework in Frameworks */, 84463B9324B258B00099DFBD /* IOKit.framework in Frameworks */,
8495BD2828B810AD009FCF4D /* CoreVideo.framework in Frameworks */,
846F883B27A59704007B6210 /* libluajit.a in Frameworks */, 846F883B27A59704007B6210 /* libluajit.a in Frameworks */,
8495BD2028B80F21009FCF4D /* Metal.framework in Frameworks */,
8495BD1E28B80F0B009FCF4D /* ForceFeedback.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -1100,6 +1121,13 @@
84585BFF24B1347B0040BA4F /* Frameworks */ = { 84585BFF24B1347B0040BA4F /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
8495BD2928B81170009FCF4D /* Carbon.framework */,
8495BD2728B810AD009FCF4D /* CoreVideo.framework */,
8495BD2528B80FD1009FCF4D /* CoreAudio.framework */,
8495BD2128B80F4D009FCF4D /* AudioToolbox.framework */,
8495BD1F28B80F21009FCF4D /* Metal.framework */,
8495BD1D28B80F0B009FCF4D /* ForceFeedback.framework */,
8495BD1528B80B00009FCF4D /* libSDL2.a */,
846F883A27A596F9007B6210 /* libluajit.a */, 846F883A27A596F9007B6210 /* libluajit.a */,
84EEE5E62782728E00F61929 /* libintl.a */, 84EEE5E62782728E00F61929 /* libintl.a */,
848CE6E427778E30001D3E0F /* libz.tbd */, 848CE6E427778E30001D3E0F /* libz.tbd */,
@ -2243,6 +2271,7 @@
"${SRCROOT}/../deps/freetype/include/freetype2", "${SRCROOT}/../deps/freetype/include/freetype2",
"${SRCROOT}/../deps/gettext/include", "${SRCROOT}/../deps/gettext/include",
"${SRCROOT}/../deps/irrlicht/include", "${SRCROOT}/../deps/irrlicht/include",
"${SRCROOT}/../deps/SDL2/include",
"${SRCROOT}/../deps/luajit/include", "${SRCROOT}/../deps/luajit/include",
); );
INFOPLIST_FILE = MultiCraft/Info.plist; INFOPLIST_FILE = MultiCraft/Info.plist;
@ -2252,6 +2281,10 @@
); );
MACOSX_DEPLOYMENT_TARGET = 10.11; MACOSX_DEPLOYMENT_TARGET = 10.11;
MARKETING_VERSION = 2.0.1; MARKETING_VERSION = 2.0.1;
OTHER_CFLAGS = (
"$(inherited)",
"-D_IRR_COMPILE_WITH_SDL_DEVICE_",
);
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-L${SRCROOT}/../deps/freetype/lib", "-L${SRCROOT}/../deps/freetype/lib",
@ -2259,6 +2292,7 @@
"-L${SRCROOT}/../deps/irrlicht", "-L${SRCROOT}/../deps/irrlicht",
"-L${SRCROOT}/../deps/luajit/lib", "-L${SRCROOT}/../deps/luajit/lib",
"-L${SRCROOT}/../deps/openal", "-L${SRCROOT}/../deps/openal",
"-L${SRCROOT}/../deps/SDL2",
"-Wl,-dead_strip", "-Wl,-dead_strip",
); );
PRODUCT_BUNDLE_IDENTIFIER = mobi.MultiCraft; PRODUCT_BUNDLE_IDENTIFIER = mobi.MultiCraft;
@ -2307,6 +2341,7 @@
"${SRCROOT}/../deps/freetype/include/freetype2", "${SRCROOT}/../deps/freetype/include/freetype2",
"${SRCROOT}/../deps/gettext/include", "${SRCROOT}/../deps/gettext/include",
"${SRCROOT}/../deps/irrlicht/include", "${SRCROOT}/../deps/irrlicht/include",
"${SRCROOT}/../deps/SDL2/include",
"${SRCROOT}/../deps/luajit/include", "${SRCROOT}/../deps/luajit/include",
); );
INFOPLIST_FILE = MultiCraft/Info.plist; INFOPLIST_FILE = MultiCraft/Info.plist;
@ -2316,6 +2351,10 @@
); );
MACOSX_DEPLOYMENT_TARGET = 10.11; MACOSX_DEPLOYMENT_TARGET = 10.11;
MARKETING_VERSION = 2.0.1; MARKETING_VERSION = 2.0.1;
OTHER_CFLAGS = (
"$(inherited)",
"-D_IRR_COMPILE_WITH_SDL_DEVICE_",
);
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-L${SRCROOT}/../deps/freetype/lib", "-L${SRCROOT}/../deps/freetype/lib",
@ -2323,6 +2362,7 @@
"-L${SRCROOT}/../deps/irrlicht", "-L${SRCROOT}/../deps/irrlicht",
"-L${SRCROOT}/../deps/luajit/lib", "-L${SRCROOT}/../deps/luajit/lib",
"-L${SRCROOT}/../deps/openal", "-L${SRCROOT}/../deps/openal",
"-L${SRCROOT}/../deps/SDL2",
"-Wl,-dead_strip", "-Wl,-dead_strip",
); );
PRODUCT_BUNDLE_IDENTIFIER = mobi.MultiCraft; PRODUCT_BUNDLE_IDENTIFIER = mobi.MultiCraft;

View File

@ -8,6 +8,8 @@
<true/> <true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key> <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/> <true/>
<key>com.apple.security.device.usb</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key> <key>com.apple.security.files.user-selected.read-only</key>
<true/> <true/>
<key>com.apple.security.network.client</key> <key>com.apple.security.network.client</key>

16
build/macOS/deps/SDL2.diff Executable file
View File

@ -0,0 +1,16 @@
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index bca8eb4dd..2e444947d 100644
--- a/SDL2-src/src/video/cocoa/SDL_cocoawindow.m
+++ b/SDL2-src/src/video/cocoa/SDL_cocoawindow.m
@@ -764,6 +764,11 @@ - (void)windowDidResize:(NSNotification *)aNotification
return;
}
+ if (focusClickPending) {
+ focusClickPending = 0;
+ [self onMovingOrFocusClickPendingStateCleared];
+ }
+
SDL_Window *window = _data->window;
NSWindow *nswindow = _data->nswindow;
int x, y, w, h;

34
build/macOS/deps/SDL2.sh Executable file
View File

@ -0,0 +1,34 @@
#!/bin/bash -e
. sdk.sh
SDL2_VERSION=2.0.22
if [ ! -d SDL2-src ]; then
wget https://github.com/libsdl-org/SDL/archive/release-$SDL2_VERSION.tar.gz
tar -xzvf release-$SDL2_VERSION.tar.gz
mv SDL-release-$SDL2_VERSION SDL2-src
rm release-$SDL2_VERSION.tar.gz
# patch SDL2
patch -p1 < SDL2.diff
fi
cd SDL2-src
xcodebuild build \
ARCHS="$OSX_ARCHES" \
-project Xcode/SDL/SDL.xcodeproj \
-configuration Release \
-scheme "Static Library"
BUILD_FOLDER=$(xcodebuild \
-project Xcode/SDL/SDL.xcodeproj \
-configuration Release \
-scheme "Static Library" \
-showBuildSettings | \
grep TARGET_BUILD_DIR | sed -n -e 's/^.*TARGET_BUILD_DIR = //p')
mkdir -p ../SDL2
cp -a "${BUILD_FOLDER}/libSDL2.a" ../SDL2
cp -a include ../SDL2
echo "SDL2 build successful"

View File

@ -3,7 +3,7 @@
. sdk.sh . sdk.sh
[ ! -d irrlicht-src ] && \ [ ! -d irrlicht-src ] && \
git clone --depth 1 -b ogl-es https://github.com/MoNTE48/Irrlicht irrlicht-src git clone --depth 1 -b SDL2 https://github.com/MoNTE48/Irrlicht irrlicht-src
cd irrlicht-src/source/Irrlicht cd irrlicht-src/source/Irrlicht
xcodebuild build \ xcodebuild build \

View File

@ -1,5 +1,6 @@
#!/bin/bash -e #!/bin/bash -e
sh SDL2.sh
sh irrlicht.sh sh irrlicht.sh
sh gettext.sh sh gettext.sh
sh freetype.sh sh freetype.sh

View File

@ -5,12 +5,12 @@ if [ ! -d MultiCraft/MultiCraft.xcodeproj ]; then
exit 1 exit 1
fi fi
DEST=$(pwd) DEST=$(pwd)/locale
pushd ../../po pushd ../../po
for lang in *; do for lang in *; do
[ ${#lang} -ne 2 ] && continue [ ${#lang} -ne 2 ] && continue
mopath=$DEST/locale/$lang/LC_MESSAGES mopath=$DEST/$lang/LC_MESSAGES
mkdir -p $mopath mkdir -p $mopath
pushd $lang pushd $lang
for fn in *.po; do for fn in *.po; do
@ -21,10 +21,9 @@ for lang in *; do
done done
popd popd
find $DEST -type d -name '.git' -print0 | xargs -0 -- rm -rf find $DEST -type d,f -name '.*' -print0 | xargs -0 -- rm -rf
find $DEST -type f -name '.*' -delete
# remove broken languages # remove broken languages
for broken_lang in ar he hi ky ms_Arab th; do for broken_lang in ar he hi ky ms_Arab th; do
find $DEST -type d -name $broken_lang -print0 | xargs -0 -- rm -rf rm -rf $DEST/$broken_lang
done done

View File

@ -1,167 +0,0 @@
--[[
From Better HUD mod
Copyright (C) BlockMen (2013-2016)
Copyright (C) MultiCraft Development Team (2019-2020)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3.0 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
]]
hud, hud_id = {}, {}
local items, sb_bg = {}, {}
local function throw_error(msg)
core.log("error", "HUD: " .. msg)
end
--
-- API
--
function hud.register(name, def)
if not name or not def then
throw_error("Not enough parameters given")
return false
end
if items[name] then
throw_error("A statbar with name " .. name .. " already exists")
return false
end
-- actually register
-- add background first since draworder is based on id
if def.hud_elem_type == "statbar" and def.background then
sb_bg[name] = table.copy(def)
sb_bg[name].text = def.background
if not def.autohide_bg and def.max then
sb_bg[name].number = def.max
end
end
-- add item itself
items[name] = def
return true
end
function hud.change_item(player, name, def)
if not player or not player:is_player() then
return false
end
if not name or not def then
throw_error("Not enough parameters given")
return false
end
local i_name = player:get_player_name() .. "_" .. name
local elem = hud_id[i_name]
local item = items[name]
if not elem then
-- throw_error("Given HUD element " .. dump(name) .. " does not exist")
return false
end
if def.number then
if item.hud_elem_type ~= "statbar" then
throw_error("Attempted to change an statbar HUD parameter for text HUD element " .. dump(name))
return false
end
if item.max and def.number > item.max then
def.number = item.max
end
player:hud_change(elem.id, "number", def.number)
-- hide background when set
if item.autohide_bg then
local bg = hud_id[i_name .. "_bg"]
if not bg then
throw_error("Given HUD element " .. dump(name) .. "_bg does not exist")
return false
end
local num = def.number ~= 0 and (item.max or item.number) or 0
player:hud_change(bg.id, "number", num)
end
elseif def.text then
player:hud_change(elem.id, "text", def.text)
elseif def.offset then
player:hud_change(elem.id, "offset", def.offset)
end
return true
end
function hud.remove_item(player, name)
if not player or not player:is_player() then
return false
end
if not name then
throw_error("Not enough parameters given")
return false
end
local i_name = player:get_player_name() .. "_" .. name
local elem = hud_id[i_name]
if not elem then
throw_error("Given HUD element " .. dump(name) .. " does not exist")
return false
end
player:hud_remove(elem.id)
return true
end
--
-- Add registered HUD items to joining players
--
-- Following code is placed here to keep HUD ids internal
local function add_hud_item(player, name, def)
if not player or not name or not def then
throw_error("Not enough parameters given")
return false
end
local i_name = player:get_player_name() .. "_" .. name
hud_id[i_name] = {}
hud_id[i_name].id = player:hud_add(def)
end
core.register_on_joinplayer(function(player)
-- add the backgrounds for statbars
for name, item in pairs(sb_bg) do
add_hud_item(player, name .. "_bg", item)
end
-- and finally the actual HUD items
for name, item in pairs(items) do
add_hud_item(player, name, item)
end
end)
core.register_on_leaveplayer(function(player)
local player_name = player:get_player_name()
for name, _ in pairs(sb_bg) do
sb_bg[player_name .. "_" .. name] = nil
end
for name, _ in pairs(items) do
hud_id[player_name .. "_" .. name] = nil
end
end)

View File

@ -25,7 +25,9 @@ or not core.settings:get_bool("enable_hunger") then
return return
end end
hunger = {} hunger = {
hud = {}
}
local function get_setting(key, default) local function get_setting(key, default)
local setting = core.settings:get("hunger." .. key) local setting = core.settings:get("hunger." .. key)
@ -57,6 +59,7 @@ local settings = hunger.settings
local min, max = math.min, math.max local min, max = math.min, math.max
local vlength = vector.length local vlength = vector.length
local tcopy = table.copy
local attribute = { local attribute = {
saturation = "hunger:level", saturation = "hunger:level",
@ -83,9 +86,18 @@ function hunger.get_saturation(player)
return tonumber(player:get_meta():get_string(attribute.saturation)) return tonumber(player:get_meta():get_string(attribute.saturation))
end end
function hunger.set_hud_level(player, level)
if not is_player(player) then
return
end
local hud = hunger.hud[player:get_player_name()]
player:hud_change(hud, "number", min(settings.visual_max, level))
end
function hunger.set_saturation(player, level) function hunger.set_saturation(player, level)
player:get_meta():set_int(attribute.saturation, level) player:get_meta():set_int(attribute.saturation, level)
hud.change_item(player, "hunger", {number = min(settings.visual_max, level)}) hunger.set_hud_level(player, level)
end end
hunger.registered_on_update_saturations = {} hunger.registered_on_update_saturations = {}
@ -145,14 +157,23 @@ function hunger.is_poisoned(player)
return poisoned and poisoned == "yes" return poisoned and poisoned == "yes"
end end
function hunger.set_hud_poisoned(player, poisoned)
if not is_player(player) then
return
end
local hud = hunger.hud[player:get_player_name()]
local texture = poisoned and "hunger_poisen.png" or "hunger.png"
player:hud_change(hud, "text", texture)
end
function hunger.set_poisoned(player, poisoned) function hunger.set_poisoned(player, poisoned)
if not is_player(player) then if not is_player(player) then
return return
end end
local texture = poisoned and "hunger_poisen.png" or "hunger.png" hunger.set_hud_poisoned(player, poisoned)
local attr = poisoned and "yes" or "no" local attr = poisoned and "yes" or "no"
hud.change_item(player, "hunger", {text = texture})
player:get_meta():set_string(attribute.poisoned, attr) player:get_meta():set_string(attribute.poisoned, attr)
end end
@ -298,9 +319,9 @@ local function health_tick()
player:set_hp(hp + settings.heal) player:set_hp(hp + settings.heal)
elseif is_starving then elseif is_starving then
player:set_hp(hp - settings.starve) player:set_hp(hp - settings.starve)
hud.change_item(player, "hunger", {number = 0}) hunger.set_hud_level(player, 0)
core.after(0.5, function() core.after(0.5, function()
hud.change_item(player, "hunger", {number = min(settings.visual_max, saturation)}) hunger.set_hud_level(player, min(settings.visual_max, saturation))
end) end)
end end
end end
@ -341,30 +362,37 @@ function hunger.item_eat(hp_change, user, poison)
end end
end end
hud.register("hunger", { hunger.bar_definition = {
hud_elem_type = "statbar", hud_elem_type = "statbar",
position = {x = 0.5, y = 1}, position = {x = 0.5, y = 1},
offset = {x = 8, y = -94}, text = "hunger.png",
size = {x = 24, y = 24}, text2 = "hunger_gone.png",
text = "hunger.png", number = settings.visual_max,
background = "hunger_gone.png", item = settings.visual_max,
number = settings.visual_max size = {x = 24, y = 24},
}) offset = {x = -265, y = -126}
}
core.register_on_joinplayer(function(player) core.register_on_joinplayer(function(player)
local level = hunger.get_saturation(player) or settings.level_max local level = hunger.get_saturation(player)
if not level then
level = settings.level_max
player:get_meta():set_int(attribute.saturation, level)
end
-- add HUD
if hunger.bar_definition then
local def = tcopy(hunger.bar_definition)
def.number = min(settings.visual_max, level)
hunger.hud[player:get_player_name()] = player:hud_add(def)
end
-- reset poisoned -- reset poisoned
hunger.set_poisoned(player, false) hunger.set_poisoned(player, false)
-- set saturation end)
player:get_meta():set_int(attribute.saturation, level)
-- we must manually update the HUD core.register_on_leaveplayer(function(player)
if level < settings.visual_max then hunger.hud[player:get_player_name()] = nil
core.after(1, function()
hud.change_item(player, "hunger", {number = min(settings.visual_max, level)})
end)
end
end) end)
local exhaust = hunger.exhaust_player local exhaust = hunger.exhaust_player

View File

@ -31,7 +31,6 @@ assert(loadfile(gamepath .. "falling.lua"))(builtin_shared)
dofile(gamepath .. "features.lua") dofile(gamepath .. "features.lua")
dofile(gamepath .. "voxelarea.lua") dofile(gamepath .. "voxelarea.lua")
dofile(gamepath .. "forceloading.lua") dofile(gamepath .. "forceloading.lua")
dofile(gamepath .. "hud.lua")
dofile(gamepath .. "statbars.lua") dofile(gamepath .. "statbars.lua")
dofile(gamepath .. "knockback.lua") dofile(gamepath .. "knockback.lua")
dofile(gamepath .. "hunger.lua") dofile(gamepath .. "hunger.lua")

View File

@ -1,28 +1,44 @@
-- cache setting -- cache setting
local enable_damage = core.settings:get_bool("enable_damage") local enable_damage = core.settings:get_bool("enable_damage")
local disable_health = false
local max = math.max
local tcopy = table.copy
local health_bar_definition = { local health_bar_definition = {
hud_elem_type = "statbar", hud_elem_type = "statbar",
position = {x = 0.5, y = 1}, position = {x = 0.5, y = 1},
offset = {x = -247, y = -94}, text = "heart.png",
size = {x = 24, y = 24}, text2 = "heart_gone.png",
text = "heart.png", number = core.PLAYER_MAX_HP_DEFAULT,
background = "heart_gone.png", item = core.PLAYER_MAX_HP_DEFAULT,
number = 20 direction = 0,
size = {x = 24, y = 24},
offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 16)},
} }
local breath_bar_definition = { local breath_bar_definition = {
hud_elem_type = "statbar", hud_elem_type = "statbar",
position = {x = 0.5, y = 1}, position = {x = 0.5, y = 1},
offset = {x = 8, y = -120}, text = "bubble.png",
size = {x = 24, y = 24}, text2 = "bubble_gone.png",
text = "bubble.png", number = core.PLAYER_MAX_BREATH_DEFAULT,
number = 20 item = core.PLAYER_MAX_BREATH_DEFAULT * 2,
direction = 0,
size = {x = 24, y = 24},
offset = {x = 25, y= -(48 + 24 + 16)},
} }
local hud_ids = {} local hud_ids = {}
local function scaleToDefault(player, field)
-- Scale "hp" or "breath" to the default dimensions
local current = player["get_" .. field](player)
local nominal = core["PLAYER_MAX_" .. field:upper() .. "_DEFAULT"]
local max_display = max(nominal,
max(player:get_properties()[field .. "_max"], current))
return current / max_display * nominal
end
local function update_builtin_statbars(player) local function update_builtin_statbars(player)
local name = player:get_player_name() local name = player:get_player_name()
@ -37,24 +53,45 @@ local function update_builtin_statbars(player)
-- our current flags are transmitted by sending them actively -- our current flags are transmitted by sending them actively
player:hud_set_flags(flags) player:hud_set_flags(flags)
end end
local hud_id = hud_ids[name] local hud = hud_ids[name]
if flags.healthbar and not disable_health then if flags.healthbar and enable_damage then
hud.change_item(player, "health", {number = player:get_hp()}) local number = scaleToDefault(player, "hp")
end if hud.id_healthbar == nil then
local hud_def = tcopy(health_bar_definition)
if flags.breathbar and player:get_breath() < 10 then
local number = player:get_breath() * 2
if hud_id.id_breathbar == nil then
local hud_def = table.copy(breath_bar_definition)
hud_def.number = number hud_def.number = number
hud_id.id_breathbar = player:hud_add(hud_def) hud.id_healthbar = player:hud_add(hud_def)
else else
player:hud_change(hud_id.id_breathbar, "number", number) player:hud_change(hud.id_healthbar, "number", number)
end
elseif hud.id_healthbar then
player:hud_remove(hud.id_healthbar)
hud.id_healthbar = nil
end end
elseif hud_id.id_breathbar then
player:hud_remove(hud_id.id_breathbar) local show_breathbar = flags.breathbar and enable_damage
hud_id.id_breathbar = nil
local breath = player:get_breath()
local breath_max = player:get_properties().breath_max
if show_breathbar and breath <= breath_max then
local number = 2 * scaleToDefault(player, "breath")
if not hud.id_breathbar and breath < breath_max then
local hud_def = tcopy(breath_bar_definition)
hud_def.number = number
hud.id_breathbar = player:hud_add(hud_def)
elseif hud.id_breathbar then
player:hud_change(hud.id_breathbar, "number", number)
end
end
if hud.id_breathbar and (not show_breathbar or breath == breath_max) then
core.after(1, function(player_name, breath_bar)
local player = core.get_player_by_name(player_name)
if player then
player:hud_remove(breath_bar)
end
end, name, hud.id_breathbar)
hud.id_breathbar = nil
end end
end end
@ -73,7 +110,7 @@ local function player_event_handler(player,eventname)
local name = player:get_player_name() local name = player:get_player_name()
if name == "" then if name == "" or not hud_ids[name] then
return return
end end
@ -102,16 +139,25 @@ local function player_event_handler(player,eventname)
end end
function core.hud_replace_builtin(hud_name, definition) function core.hud_replace_builtin(hud_name, definition)
if hud_name == "health" then
disable_health = true
return true
end
if type(definition) ~= "table" or if type(definition) ~= "table" or
definition.hud_elem_type ~= "statbar" then definition.hud_elem_type ~= "statbar" then
return false return false
end end
if hud_name == "health" then
health_bar_definition = definition
for name, ids in pairs(hud_ids) do
local player = core.get_player_by_name(name)
if player and ids.id_healthbar then
player:hud_remove(ids.id_healthbar)
ids.id_healthbar = nil
update_builtin_statbars(player)
end
end
return true
end
if hud_name == "breath" then if hud_name == "breath" then
breath_bar_definition = definition breath_bar_definition = definition
@ -131,13 +177,8 @@ end
-- Append "update_builtin_statbars" as late as possible -- Append "update_builtin_statbars" as late as possible
-- This ensures that the HUD is hidden when the flags are updated in this callback -- This ensures that the HUD is hidden when the flags are updated in this callback
if enable_damage then core.register_on_mods_loaded(function()
core.register_on_mods_loaded(function() core.register_on_joinplayer(update_builtin_statbars)
if not disable_health then end)
hud.register("health", health_bar_definition) core.register_on_leaveplayer(cleanup_builtin_statbars)
core.register_on_joinplayer(update_builtin_statbars) core.register_playerevent(player_event_handler)
end
end)
core.register_on_leaveplayer(cleanup_builtin_statbars)
core.register_playerevent(player_event_handler)
end

View File

@ -914,7 +914,6 @@ private:
scene::ISceneManager *smgr; scene::ISceneManager *smgr;
bool *kill; bool *kill;
std::string *error_message; std::string *error_message;
std::string wield_name;
bool *reconnect_requested; bool *reconnect_requested;
scene::ISceneNode *skybox; scene::ISceneNode *skybox;
PausedNodesList paused_animated_nodes; PausedNodesList paused_animated_nodes;
@ -2023,7 +2022,7 @@ void Game::processKeyInput()
toggleDebug(); toggleDebug();
} else if (wasKeyDown(KeyType::TOGGLE_PROFILER)) { } else if (wasKeyDown(KeyType::TOGGLE_PROFILER)) {
m_game_ui->toggleProfiler(); m_game_ui->toggleProfiler();
} else if (wasKeyDown(KeyType::INCREASE_VIEWING_RANGE) || wasKeyDown(KeyType::INCREASE_VIEWING_RANGE2)) { } else if (wasKeyDown(KeyType::INCREASE_VIEWING_RANGE)) {
increaseViewRange(); increaseViewRange();
} else if (wasKeyDown(KeyType::DECREASE_VIEWING_RANGE)) { } else if (wasKeyDown(KeyType::DECREASE_VIEWING_RANGE)) {
decreaseViewRange(); decreaseViewRange();
@ -3951,12 +3950,6 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
ItemStack selected_item, hand_item; ItemStack selected_item, hand_item;
ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item);
camera->wield(tool_item); camera->wield(tool_item);
std::string item_desc = selected_item.getDefinition(itemdef_manager).description;
if (wield_name != item_desc) {
m_game_ui->showStatusText(utf8_to_wide(item_desc));
wield_name = item_desc;
}
} }
/* /*
@ -4369,29 +4362,34 @@ void Game::showPauseMenu()
os << "formspec_version[1]" << SIZE_TAG os << "formspec_version[1]" << SIZE_TAG
<< "no_prepend[]" << "no_prepend[]"
<< "bgcolor[#00000060;true]" << "bgcolor[#00000060;true]"
<< "button_exit[3.5," << (ypos++) << ";4,0.5;btn_continue;"
<< strgettext("Continue") << "]"; << "style_type[image_button_exit,image_button;bgimg=gui_button.png;bgimg_middle=20;padding=-5]"
<< "style_type[image_button_exit,image_button:hovered;bgimg=gui_button_hovered.png;bgimg_middle=20]"
<< "style_type[image_button_exit,image_button:pressed;bgimg=gui_button_pressed.png;bgimg_middle=20]"
<< "image_button_exit[3.5," << (ypos++) << ";4,0.9;;btn_continue;"
<< strgettext("Continue") << ";;false]";
if (!simple_singleplayer_mode) { if (!simple_singleplayer_mode) {
os << "button[3.5," << (ypos++) << ";4,0.5;btn_change_password;" os << "image_button[3.5," << (ypos++) << ";4,0.9;;btn_change_password;"
<< strgettext("Change Password") << "]"; << strgettext("Change Password") << ";;false]";
} }
#if !defined(__ANDROID__) && !defined(__IOS__) #if !defined(__ANDROID__) && !defined(__IOS__)
#if USE_SOUND #if USE_SOUND
if (g_settings->getBool("enable_sound")) { if (g_settings->getBool("enable_sound")) {
os << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_sound;" os << "image_button_exit[3.5," << (ypos++) << ";4,0.9;;btn_sound;"
<< strgettext("Sound Volume") << "]"; << strgettext("Sound Volume") << ";;false]";
} }
#endif #endif
os << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_key_config;" os << "image_button_exit[3.5," << (ypos++) << ";4,0.9;;btn_key_config;"
<< strgettext("Change Keys") << "]"; << strgettext("Change Keys") << ";;false]";
#endif #endif
os << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_exit_menu;" os << "image_button_exit[3.5," << (ypos++) << ";4,0.9;;btn_exit_menu;"
<< strgettext("Exit to Menu") << "]"; << strgettext("Exit to Menu") << ";;false]";
#ifndef __IOS__ #ifndef __IOS__
os << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_exit_os;" os << "image_button_exit[3.5," << (ypos++) << ";4,0.9;;btn_exit_os;"
<< strgettext("Exit to OS") << "]" << strgettext("Exit to OS") << ";;false]";
#endif #endif
/* << "textarea[7.5,0.25;3.9,6.25;;" << control_text << ";]" /* << "textarea[7.5,0.25;3.9,6.25;;" << control_text << ";]"
<< "textarea[0.4,0.25;3.9,6.25;;" << PROJECT_NAME_C " " VERSION_STRING "\n" << "textarea[0.4,0.25;3.9,6.25;;" << PROJECT_NAME_C " " VERSION_STRING "\n"

View File

@ -359,10 +359,12 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
switch (e->type) { switch (e->type) {
case HUD_ELEM_TEXT: { case HUD_ELEM_TEXT: {
irr::gui::IGUIFont *textfont = font; irr::gui::IGUIFont *textfont = font;
unsigned int font_size = g_fontengine->getDefaultFontSize(); float font_size = g_fontengine->getDefaultFontSize();
if (e->size.X > 0) if (e->size.X > 0)
font_size *= e->size.X; font_size *= e->size.X;
else if (e->size.Y > 0)
font_size = MYMAX(font_size * (float) e->size.Y / 100, 1.0f);
if (font_size != g_fontengine->getDefaultFontSize()) if (font_size != g_fontengine->getDefaultFontSize())
textfont = g_fontengine->getFont(font_size); textfont = g_fontengine->getFont(font_size);
@ -372,12 +374,17 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
(e->number >> 0) & 0xFF); (e->number >> 0) & 0xFF);
std::wstring text = unescape_translate(utf8_to_wide(e->text)); std::wstring text = unescape_translate(utf8_to_wide(e->text));
core::dimension2d<u32> textsize = textfont->getDimension(text.c_str()); core::dimension2d<u32> textsize = textfont->getDimension(text.c_str());
bool below_center = ((e->scale.Y * m_scale_factor + pos.Y +
(e->align.Y - 1.0) * (textsize.Height / 2) +
e->offset.Y * m_scale_factor) > m_displaycenter.Y);
#if defined(__ANDROID__) || defined(__IOS__) #if defined(__ANDROID__) || defined(__IOS__)
// The text size on Android is not proportional with the actual scaling // The text size on Android is not proportional with the actual scaling
auto small_font_size = font_size * 0.9f; if (below_center) {
irr::gui::IGUIFont *font_scaled = small_font_size < 1 ? font_size = MYMAX(font_size * 0.9f, 1.0f);
textfont : g_fontengine->getFont(small_font_size); textfont = g_fontengine->getFont(font_size);
textsize = font_scaled->getDimension(text.c_str()); textsize = textfont->getDimension(text.c_str());
}
#endif #endif
v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2), v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
(e->align.Y - 1.0) * (textsize.Height / 2)); (e->align.Y - 1.0) * (textsize.Height / 2));
@ -385,13 +392,9 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
text_height * e->scale.Y * m_scale_factor); text_height * e->scale.Y * m_scale_factor);
v2s32 offs(e->offset.X * m_scale_factor, v2s32 offs(e->offset.X * m_scale_factor,
e->offset.Y * m_scale_factor); e->offset.Y * m_scale_factor);
if (e->offset.Y < -50) if (below_center)
pos.Y -= m_hud_move_upwards; pos.Y -= m_hud_move_upwards;
#if defined(__ANDROID__) || defined(__IOS__)
font_scaled->draw(text.c_str(), size + pos + offset + offs, color);
#else
textfont->draw(text.c_str(), size + pos + offset + offs, color); textfont->draw(text.c_str(), size + pos + offset + offs, color);
#endif
break; } break; }
case HUD_ELEM_STATBAR: { case HUD_ELEM_STATBAR: {
v2s32 offs(e->offset.X, e->offset.Y); v2s32 offs(e->offset.X, e->offset.Y);
@ -453,7 +456,9 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
dstsize.Y *= m_scale_factor; dstsize.Y *= m_scale_factor;
v2s32 offset((e->align.X - 1.0) * dstsize.X / 2, v2s32 offset((e->align.X - 1.0) * dstsize.X / 2,
(e->align.Y - 1.0) * dstsize.Y / 2); (e->align.Y - 1.0) * dstsize.Y / 2);
offset.Y -= m_hud_move_upwards;
if ((dstsize.Y + pos.Y + offset.Y + e->offset.Y * m_scale_factor) > m_displaycenter.Y)
offset.Y -= m_hud_move_upwards;
core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y); core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
rect += pos + offset + v2s32(e->offset.X * m_scale_factor, rect += pos + offset + v2s32(e->offset.X * m_scale_factor,
e->offset.Y * m_scale_factor); e->offset.Y * m_scale_factor);
@ -636,7 +641,8 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
p += offset; p += offset;
p.Y -= m_hud_move_upwards; if ((pos.Y + offset.Y) > m_displaycenter.Y)
p.Y -= m_hud_move_upwards;
v2s32 steppos; v2s32 steppos;
switch (drawdir) { switch (drawdir) {

View File

@ -74,9 +74,6 @@ void KeyCache::populate()
key[KeyType::CAMERA_MODE] = getKeySetting("keymap_camera_mode"); key[KeyType::CAMERA_MODE] = getKeySetting("keymap_camera_mode");
key[KeyType::INCREASE_VIEWING_RANGE] = key[KeyType::INCREASE_VIEWING_RANGE] =
getKeySetting("keymap_increase_viewing_range_min"); getKeySetting("keymap_increase_viewing_range_min");
#if defined(__MACH__) && defined(__APPLE__)
key[KeyType::INCREASE_VIEWING_RANGE2] = "=";
#endif
key[KeyType::DECREASE_VIEWING_RANGE] = key[KeyType::DECREASE_VIEWING_RANGE] =
getKeySetting("keymap_decrease_viewing_range_min"); getKeySetting("keymap_decrease_viewing_range_min");
key[KeyType::RANGESELECT] = getKeySetting("keymap_rangeselect"); key[KeyType::RANGESELECT] = getKeySetting("keymap_rangeselect");

View File

@ -67,7 +67,6 @@ public:
TOGGLE_PROFILER, TOGGLE_PROFILER,
CAMERA_MODE, CAMERA_MODE,
INCREASE_VIEWING_RANGE, INCREASE_VIEWING_RANGE,
INCREASE_VIEWING_RANGE2,
DECREASE_VIEWING_RANGE, DECREASE_VIEWING_RANGE,
RANGESELECT, RANGESELECT,
ZOOM, ZOOM,

View File

@ -508,7 +508,6 @@ void set_default_settings()
#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) #if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__)
settings->setDefault("screen_w", "0"); settings->setDefault("screen_w", "0");
settings->setDefault("screen_h", "0"); settings->setDefault("screen_h", "0");
settings->setDefault("keymap_sneak", "KEY_SHIFT");
settings->setDefault("keymap_camera_mode", "KEY_KEY_C"); settings->setDefault("keymap_camera_mode", "KEY_KEY_C");
settings->setDefault("vsync", "true"); settings->setDefault("vsync", "true");

View File

@ -26,6 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h" #include "log.h"
#include "porting.h" #include "porting.h"
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
#include <SDL.h>
#endif
#ifdef __APPLE__ #ifdef __APPLE__
#ifdef __IOS__ #ifdef __IOS__
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@ -216,12 +220,23 @@ void init_gettext(const char *path, const std::string &configured_language,
} }
else { else {
/* set current system default locale */ /* set current system default locale */
#ifdef __ANDROID__ #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
SDL_Locale* locale = SDL_GetPreferredLocales();
if (locale) {
if (locale[0].language) {
char lang[3] = {0};
strncpy(lang, locale[0].language, 2);
setenv("LANG", lang, 1);
}
SDL_free(locale);
}
#elif defined(__ANDROID__)
char lang[3] = {0}; char lang[3] = {0};
AConfiguration_getLanguage(porting::app_global->config, lang); AConfiguration_getLanguage(porting::app_global->config, lang);
setenv("LANG", lang, 1); setenv("LANG", lang, 1);
#endif #elif defined(__IOS__)
#ifdef __APPLE__
char lang[3] = {0}; char lang[3] = {0};
NSString *syslang = [[NSLocale preferredLanguages] firstObject]; NSString *syslang = [[NSLocale preferredLanguages] firstObject];
[syslang getBytes:lang maxLength:2 usedLength:nil encoding:NSASCIIStringEncoding options:0 range:NSMakeRange(0, 2) remainingRange:nil]; [syslang getBytes:lang maxLength:2 usedLength:nil encoding:NSASCIIStringEncoding options:0 range:NSMakeRange(0, 2) remainingRange:nil];

View File

@ -36,6 +36,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlicht_changes/CGUITTFont.h" #include "irrlicht_changes/CGUITTFont.h"
#endif #endif
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
#include <SDL.h>
#endif
inline u32 clamp_u8(s32 value) inline u32 clamp_u8(s32 value)
{ {
return (u32) MYMIN(MYMAX(value, 0), 255); return (u32) MYMIN(MYMAX(value, 0), 255);
@ -95,6 +99,11 @@ GUIChatConsole::GUIChatConsole(
GUIChatConsole::~GUIChatConsole() GUIChatConsole::~GUIChatConsole()
{ {
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
if (porting::hasRealKeyboard() && SDL_IsTextInputActive())
SDL_StopTextInput();
#endif
if (m_font) if (m_font)
m_font->drop(); m_font->drop();
} }
@ -111,6 +120,11 @@ void GUIChatConsole::openConsole(f32 scale)
IGUIElement::setVisible(true); IGUIElement::setVisible(true);
Environment->setFocus(this); Environment->setFocus(this);
m_menumgr->createdMenu(this); m_menumgr->createdMenu(this);
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
if (porting::hasRealKeyboard())
SDL_StartTextInput();
#endif
} }
bool GUIChatConsole::isOpen() const bool GUIChatConsole::isOpen() const
@ -128,6 +142,11 @@ void GUIChatConsole::closeConsole()
m_open = false; m_open = false;
Environment->removeFocus(this); Environment->removeFocus(this);
m_menumgr->deletingMenu(this); m_menumgr->deletingMenu(this);
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
if (porting::hasRealKeyboard() && SDL_IsTextInputActive())
SDL_StopTextInput();
#endif
} }
void GUIChatConsole::closeConsoleAtOnce() void GUIChatConsole::closeConsoleAtOnce()
@ -620,6 +639,20 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
return true; return true;
} }
} }
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
else if(event.EventType == EET_SDL_TEXT_EVENT)
{
if (event.SDLTextEvent.Type == ESDLET_TEXTINPUT)
{
std::wstring text = utf8_to_wide(event.SDLTextEvent.Text);
for (u32 i = 0; i < text.size(); i++)
prompt.input(text[i]);
return true;
}
}
#endif
else if(event.EventType == EET_MOUSE_INPUT_EVENT) else if(event.EventType == EET_MOUSE_INPUT_EVENT)
{ {
if(event.MouseInput.Event == EMIE_MOUSE_WHEEL) if(event.MouseInput.Event == EMIE_MOUSE_WHEEL)

View File

@ -26,6 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h" #include "porting.h"
#include "util/string.h" #include "util/string.h"
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
#include <SDL.h>
#endif
GUIEditBox::~GUIEditBox() GUIEditBox::~GUIEditBox()
{ {
if (m_override_font) if (m_override_font)
@ -209,6 +213,19 @@ bool GUIEditBox::OnEvent(const SEvent &event)
} }
} }
break; break;
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
case EET_SDL_TEXT_EVENT:
if (event.SDLTextEvent.Type == irr::ESDLET_TEXTINPUT) {
core::stringw text =
utf8_to_stringw(event.SDLTextEvent.Text);
for (size_t i = 0; i < text.size(); i++)
inputChar(text[i]);
return true;
}
break;
#endif
case EET_KEY_INPUT_EVENT: { case EET_KEY_INPUT_EVENT: {
#if (defined(__linux__) || defined(__FreeBSD__)) || defined(__DragonFly__) #if (defined(__linux__) || defined(__FreeBSD__)) || defined(__DragonFly__)
// ################################################################ // ################################################################
@ -259,8 +276,18 @@ bool GUIEditBox::processKey(const SEvent &event)
s32 new_mark_begin = m_mark_begin; s32 new_mark_begin = m_mark_begin;
s32 new_mark_end = m_mark_end; s32 new_mark_end = m_mark_end;
// On Windows right alt simulates additional control press/release events.
// It causes unexpected bahavior, for example right alt + A would clear text
// in the edit box. At least for SDL we can easily check if alt key is
// pressed
bool altPressed = false;
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
SDL_Keymod keymod = SDL_GetModState();
altPressed = keymod & KMOD_ALT;
#endif
// control shortcut handling // control shortcut handling
if (event.KeyInput.Control) { if (event.KeyInput.Control && !altPressed) {
// german backlash '\' entered with control + '?' // german backlash '\' entered with control + '?'
if (event.KeyInput.Char == '\\') { if (event.KeyInput.Char == '\\') {

View File

@ -94,6 +94,10 @@ void GUIEditBoxWithScrollBar::draw()
default_bg_color = m_writable ? skin->getColor(EGDC_WINDOW) : video::SColor(0); default_bg_color = m_writable ? skin->getColor(EGDC_WINDOW) : video::SColor(0);
bg_color = m_bg_color_used ? m_bg_color : default_bg_color; bg_color = m_bg_color_used ? m_bg_color : default_bg_color;
if (IsEnabled && m_writable) {
bg_color = focus ? skin->getColor(EGDC_FOCUSED_EDITABLE) : skin->getColor(EGDC_EDITABLE);
}
if (!m_border && m_background) { if (!m_border && m_background) {
skin->draw2DRectangle(this, bg_color, AbsoluteRect, &AbsoluteClippingRect); skin->draw2DRectangle(this, bg_color, AbsoluteRect, &AbsoluteClippingRect);
} }

View File

@ -69,6 +69,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiHyperText.h" #include "guiHyperText.h"
#include "guiScene.h" #include "guiScene.h"
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
#include <SDL.h>
#endif
#define MY_CHECKPOS(a,b) \ #define MY_CHECKPOS(a,b) \
if (v_pos.size() != 2) { \ if (v_pos.size() != 2) { \
errorstream<< "Invalid pos for element " << a << " specified: \"" \ errorstream<< "Invalid pos for element " << a << " specified: \"" \
@ -211,6 +215,10 @@ void GUIFormSpecMenu::setInitialFocus()
if (it->getType() == gui::EGUIET_EDIT_BOX if (it->getType() == gui::EGUIET_EDIT_BOX
&& it->getText()[0] == 0) { && it->getText()[0] == 0) {
Environment->setFocus(it); Environment->setFocus(it);
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
if (porting::hasRealKeyboard())
SDL_StartTextInput();
#endif
return; return;
} }
} }
@ -219,6 +227,10 @@ void GUIFormSpecMenu::setInitialFocus()
for (gui::IGUIElement *it : children) { for (gui::IGUIElement *it : children) {
if (it->getType() == gui::EGUIET_EDIT_BOX) { if (it->getType() == gui::EGUIET_EDIT_BOX) {
Environment->setFocus(it); Environment->setFocus(it);
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
if (porting::hasRealKeyboard())
SDL_StartTextInput();
#endif
return; return;
} }
} }

View File

@ -29,6 +29,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/renderingengine.h" #include "client/renderingengine.h"
#endif #endif
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
#include <SDL.h>
#endif
// clang-format off // clang-format off
GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent,
s32 id, IMenuManager *menumgr, bool remap_dbl_click) : s32 id, IMenuManager *menumgr, bool remap_dbl_click) :
@ -59,6 +63,10 @@ GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent,
GUIModalMenu::~GUIModalMenu() GUIModalMenu::~GUIModalMenu()
{ {
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
if (porting::hasRealKeyboard() && SDL_IsTextInputActive())
SDL_StopTextInput();
#endif
m_menumgr->deletingMenu(this); m_menumgr->deletingMenu(this);
} }
@ -242,8 +250,26 @@ void GUIModalMenu::leave()
bool GUIModalMenu::preprocessEvent(const SEvent &event) bool GUIModalMenu::preprocessEvent(const SEvent &event)
{ {
#if defined(__ANDROID__) || defined(__IOS__)
// clang-format off // clang-format off
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
// Enable text input events when edit box is focused
if (event.EventType == EET_GUI_EVENT) {
if (event.GUIEvent.EventType == irr::gui::EGET_ELEMENT_FOCUSED &&
event.GUIEvent.Caller &&
event.GUIEvent.Caller->getType() == irr::gui::EGUIET_EDIT_BOX) {
if (porting::hasRealKeyboard())
SDL_StartTextInput();
}
else if (event.GUIEvent.EventType == irr::gui::EGET_ELEMENT_FOCUS_LOST &&
event.GUIEvent.Caller &&
event.GUIEvent.Caller->getType() == irr::gui::EGUIET_EDIT_BOX) {
if (porting::hasRealKeyboard() && SDL_IsTextInputActive())
SDL_StopTextInput();
}
}
#endif
#if defined(__ANDROID__) || defined(__IOS__)
// display software keyboard when clicking edit boxes // display software keyboard when clicking edit boxes
if (event.EventType == EET_MOUSE_INPUT_EVENT && if (event.EventType == EET_MOUSE_INPUT_EVENT &&
event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {

View File

@ -623,11 +623,11 @@ void initializePaths()
#endif // USE_GETTEXT #endif // USE_GETTEXT
} }
#ifndef __ANDROID__ #if !defined(__ANDROID__) && !defined(__IOS__)
// Dummy for other OS with a touchscreen // Dummy for other OS
bool hasRealKeyboard() bool hasRealKeyboard()
{ {
return false; return true;
} }
#endif #endif

View File

@ -40,6 +40,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h" #include "constants.h"
#include "gettime.h" #include "gettime.h"
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
#include <SDL.h>
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#define SWPRINTF_CHARSTRING L"%S" #define SWPRINTF_CHARSTRING L"%S"
#else #else
@ -95,7 +99,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
defined(__APPLE__) || \ defined(__APPLE__) || \
defined(__sun) || defined(sun) || \ defined(__sun) || defined(sun) || \
defined(__QNX__) || defined(__QNXNTO__) defined(__QNX__) || defined(__QNXNTO__)
#define HAVE_STRLCPY #ifndef HAVE_STRLCPY
#define HAVE_STRLCPY
#endif
#endif #endif
// So we need to define our own. // So we need to define our own.

View File

@ -32,7 +32,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <iomanip> #include <iomanip>
#include <map> #include <map>
#ifndef _WIN32 #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
#include <SDL.h>
#elif !defined(_WIN32)
#include <iconv.h> #include <iconv.h>
#else #else
#define _WIN32_WINNT 0x0501 #define _WIN32_WINNT 0x0501
@ -48,7 +50,56 @@ static bool parseHexColorString(const std::string &value, video::SColor &color,
unsigned char default_alpha = 0xff); unsigned char default_alpha = 0xff);
static bool parseNamedColorString(const std::string &value, video::SColor &color); static bool parseNamedColorString(const std::string &value, video::SColor &color);
#ifndef _WIN32 #if defined(__ANDROID__) || defined(__APPLE__)
// Android need manual caring to support the full character set possible with wchar_t
const char *DEFAULT_ENCODING = "UTF-32LE";
#else
const char *DEFAULT_ENCODING = "WCHAR_T";
#endif
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
std::wstring utf8_to_wide(const std::string &input)
{
#if defined(__ANDROID__) || defined(__APPLE__)
SANITY_CHECK(sizeof(wchar_t) == 4);
#endif
const char *inbuf = input.c_str();
size_t inbuf_size = input.size() + 1;
char *outbuf = SDL_iconv_string(DEFAULT_ENCODING, "UTF-8", inbuf, inbuf_size);
if (!outbuf)
return L"";
std::wstring out((wchar_t*)outbuf);
SDL_free(outbuf);
return out;
}
std::string wide_to_utf8(const std::wstring &input)
{
#if defined(__ANDROID__) || defined(__APPLE__)
SANITY_CHECK(sizeof(wchar_t) == 4);
#endif
const char *inbuf = (const char*)(input.c_str());
size_t inbuf_size = (input.size() + 1) * sizeof(wchar_t);
char *outbuf = SDL_iconv_string("UTF-8", DEFAULT_ENCODING, inbuf, inbuf_size);
if (!outbuf)
return "";
std::string out(outbuf);
SDL_free(outbuf);
return out;
}
#elif !defined(_WIN32)
static bool convert(const char *to, const char *from, char *outbuf, static bool convert(const char *to, const char *from, char *outbuf,
size_t *outbuf_size, char *inbuf, size_t inbuf_size) size_t *outbuf_size, char *inbuf, size_t inbuf_size)
@ -80,13 +131,6 @@ static bool convert(const char *to, const char *from, char *outbuf,
return true; return true;
} }
#if defined(__ANDROID__) || defined(__APPLE__)
// Android need manual caring to support the full character set possible with wchar_t
const char *DEFAULT_ENCODING = "UTF-32LE";
#else
const char *DEFAULT_ENCODING = "WCHAR_T";
#endif
std::wstring utf8_to_wide(const std::string &input) std::wstring utf8_to_wide(const std::string &input)
{ {
const size_t inbuf_size = input.length(); const size_t inbuf_size = input.length();

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B