Merge branch 'master' of https://github.com/minetest/minetest
This commit is contained in:
commit
cca4254f7c
25
.github/workflows/build.yml
vendored
25
.github/workflows/build.yml
vendored
@ -33,9 +33,8 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get install g++-6 gcc-6 -qyy
|
||||
source ./util/ci/common.sh
|
||||
install_linux_deps
|
||||
install_linux_deps g++-6
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@ -55,9 +54,8 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get install g++-8 gcc-8 -qyy
|
||||
source ./util/ci/common.sh
|
||||
install_linux_deps
|
||||
install_linux_deps g++-8
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@ -77,9 +75,8 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get install clang-3.9 -qyy
|
||||
source ./util/ci/common.sh
|
||||
install_linux_deps
|
||||
install_linux_deps clang-3.9
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@ -99,11 +96,8 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get install clang-9 valgrind -qyy
|
||||
source ./util/ci/common.sh
|
||||
install_linux_deps
|
||||
env:
|
||||
WITH_LUAJIT: 1
|
||||
install_linux_deps clang-9 valgrind libluajit-5.1-dev
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@ -111,6 +105,7 @@ jobs:
|
||||
env:
|
||||
CC: clang-9
|
||||
CXX: clang++-9
|
||||
CMAKE_FLAGS: "-DREQUIRE_LUAJIT=1"
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
@ -128,9 +123,8 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get install clang-9 -qyy
|
||||
source ./util/ci/common.sh
|
||||
install_linux_deps
|
||||
install_linux_deps clang-9
|
||||
|
||||
- name: Build prometheus-cpp
|
||||
run: |
|
||||
@ -156,9 +150,8 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get install clang-9 -qyy
|
||||
source ./util/ci/common.sh
|
||||
install_linux_deps
|
||||
install_linux_deps clang-9
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@ -188,7 +181,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install compiler
|
||||
run: |
|
||||
sudo apt-get install gettext -qyy
|
||||
sudo apt-get update -q && sudo apt-get install gettext -qyy
|
||||
wget http://minetest.kitsunemimi.pw/mingw-w64-i686_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz
|
||||
sudo tar -xaf mingw.tar.xz -C /usr
|
||||
|
||||
@ -206,7 +199,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install compiler
|
||||
run: |
|
||||
sudo apt-get install gettext -qyy
|
||||
sudo apt-get update -q && sudo apt-get install gettext -qyy
|
||||
wget http://minetest.kitsunemimi.pw/mingw-w64-x86_64_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz
|
||||
sudo tar -xaf mingw.tar.xz -C /usr
|
||||
|
||||
|
131
.gitlab-ci.yml
131
.gitlab-ci.yml
@ -18,12 +18,12 @@ variables:
|
||||
- mkdir cmakebuild
|
||||
- mkdir -p artifact/minetest/usr/
|
||||
- cd cmakebuild
|
||||
- cmake -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DCMAKE_BUILD_TYPE=Release -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DBUILD_SERVER=TRUE ..
|
||||
- cmake -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DCMAKE_BUILD_TYPE=Release -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DENABLE_SYSTEM_JSONCPP=TRUE -DBUILD_SERVER=TRUE ..
|
||||
- make -j2
|
||||
- make install
|
||||
artifacts:
|
||||
when: on_success
|
||||
expire_in: 2h
|
||||
expire_in: 1h
|
||||
paths:
|
||||
- artifact/*
|
||||
|
||||
@ -34,15 +34,14 @@ variables:
|
||||
- apt-get install -y git
|
||||
- mkdir -p build/deb/minetest/DEBIAN/
|
||||
- cp misc/debpkg-control build/deb/minetest/DEBIAN/control
|
||||
- cp -Rp artifact/minetest/usr build/deb/minetest/
|
||||
- cp -a artifact/minetest/usr build/deb/minetest/
|
||||
script:
|
||||
- git clone $MINETEST_GAME_REPO build/deb/minetest/usr/share/minetest/games/minetest_game
|
||||
- rm -Rf build/deb/minetest/usr/share/minetest/games/minetest/.git
|
||||
- rm -rf build/deb/minetest/usr/share/minetest/games/minetest/.git
|
||||
- sed -i 's/DATEPLACEHOLDER/'$(date +%y.%m.%d)'/g' build/deb/minetest/DEBIAN/control
|
||||
- sed -i 's/LEVELDB_PLACEHOLDER/'$LEVELDB_PKG'/g' build/deb/minetest/DEBIAN/control
|
||||
- cd build/deb/ && dpkg-deb -b minetest/ && mv minetest.deb ../../
|
||||
artifacts:
|
||||
when: on_success
|
||||
expire_in: 90 day
|
||||
paths:
|
||||
- ./*.deb
|
||||
@ -51,44 +50,14 @@ variables:
|
||||
stage: deploy
|
||||
before_script:
|
||||
- apt-get update -y
|
||||
- apt-get install -y libc6 libcurl3-gnutls libfreetype6 libirrlicht1.8 $LEVELDB_PKG liblua5.1-0 libluajit-5.1-2 libopenal1 libstdc++6 libvorbisfile3 libx11-6 zlib1g
|
||||
script:
|
||||
- dpkg -i ./*.deb
|
||||
- apt-get install -y ./*.deb
|
||||
- minetest --version
|
||||
|
||||
##
|
||||
## Debian
|
||||
##
|
||||
|
||||
# Jessie
|
||||
|
||||
build:debian-8:
|
||||
extends: .build_template
|
||||
image: debian:8
|
||||
before_script:
|
||||
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu trusty main" > /etc/apt/sources.list.d/uptodate-toolchain.list
|
||||
- apt-key adv --keyserver keyserver.ubuntu.com --recv BA9EF27F
|
||||
- apt-get update -y
|
||||
- apt-get -y install build-essential gcc-6 g++-6 libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
|
||||
variables:
|
||||
CC: gcc-6
|
||||
CXX: g++-6
|
||||
|
||||
package:debian-8:
|
||||
extends: .debpkg_template
|
||||
image: debian:8
|
||||
dependencies:
|
||||
- build:debian-8
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1
|
||||
|
||||
deploy:debian-8:
|
||||
extends: .debpkg_install
|
||||
image: debian:8
|
||||
dependencies:
|
||||
- package:debian-8
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1
|
||||
|
||||
# Stretch
|
||||
|
||||
build:debian-9:
|
||||
@ -101,7 +70,7 @@ build:debian-9:
|
||||
package:debian-9:
|
||||
extends: .debpkg_template
|
||||
image: debian:9
|
||||
dependencies:
|
||||
needs:
|
||||
- build:debian-9
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1v5
|
||||
@ -109,12 +78,10 @@ package:debian-9:
|
||||
deploy:debian-9:
|
||||
extends: .debpkg_install
|
||||
image: debian:9
|
||||
dependencies:
|
||||
needs:
|
||||
- package:debian-9
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1v5
|
||||
|
||||
# Stretch
|
||||
# Buster
|
||||
|
||||
build:debian-10:
|
||||
extends: .build_template
|
||||
@ -126,7 +93,7 @@ build:debian-10:
|
||||
package:debian-10:
|
||||
extends: .debpkg_template
|
||||
image: debian:10
|
||||
dependencies:
|
||||
needs:
|
||||
- build:debian-10
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1d
|
||||
@ -134,10 +101,9 @@ package:debian-10:
|
||||
deploy:debian-10:
|
||||
extends: .debpkg_install
|
||||
image: debian:10
|
||||
dependencies:
|
||||
needs:
|
||||
- package:debian-10
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1d
|
||||
|
||||
##
|
||||
## Ubuntu
|
||||
##
|
||||
@ -154,7 +120,7 @@ build:ubuntu-16.04:
|
||||
package:ubuntu-16.04:
|
||||
extends: .debpkg_template
|
||||
image: ubuntu:xenial
|
||||
dependencies:
|
||||
needs:
|
||||
- build:ubuntu-16.04
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1v5
|
||||
@ -162,10 +128,8 @@ package:ubuntu-16.04:
|
||||
deploy:ubuntu-16.04:
|
||||
extends: .debpkg_install
|
||||
image: ubuntu:xenial
|
||||
dependencies:
|
||||
needs:
|
||||
- package:ubuntu-16.04
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1v5
|
||||
|
||||
# Bionic
|
||||
|
||||
@ -179,7 +143,7 @@ build:ubuntu-18.04:
|
||||
package:ubuntu-18.04:
|
||||
extends: .debpkg_template
|
||||
image: ubuntu:bionic
|
||||
dependencies:
|
||||
needs:
|
||||
- build:ubuntu-18.04
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1v5
|
||||
@ -187,25 +151,22 @@ package:ubuntu-18.04:
|
||||
deploy:ubuntu-18.04:
|
||||
extends: .debpkg_install
|
||||
image: ubuntu:bionic
|
||||
dependencies:
|
||||
needs:
|
||||
- package:ubuntu-18.04
|
||||
variables:
|
||||
LEVELDB_PKG: libleveldb1v5
|
||||
|
||||
##
|
||||
## Fedora
|
||||
##
|
||||
|
||||
# Do we need to support this old version ?
|
||||
build:fedora-24:
|
||||
# Fedora 28 <-> RHEL 8
|
||||
build:fedora-28:
|
||||
extends: .build_template
|
||||
image: fedora:24
|
||||
image: fedora:28
|
||||
before_script:
|
||||
- dnf -y install make automake gcc gcc-c++ kernel-devel cmake libcurl* openal* libvorbis* libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel bzip2-libs gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel doxygen spatialindex-devel bzip2-devel
|
||||
|
||||
- dnf -y install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel spatialindex-devel
|
||||
|
||||
##
|
||||
## Mingw for Windows
|
||||
## MinGW for Windows
|
||||
##
|
||||
|
||||
.generic_win_template:
|
||||
@ -213,68 +174,63 @@ build:fedora-24:
|
||||
before_script:
|
||||
- apt-get update -y
|
||||
- apt-get install -y wget xz-utils unzip git cmake gettext
|
||||
- wget -q http://minetest.kitsunemimi.pw/mingw-w64-${WIN_ARCH}_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz
|
||||
- wget -nv http://minetest.kitsunemimi.pw/mingw-w64-${WIN_ARCH}_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz
|
||||
- tar -xaf mingw.tar.xz -C /usr
|
||||
|
||||
.build_win_template:
|
||||
extends: .generic_win_template
|
||||
stage: build
|
||||
artifacts:
|
||||
when: on_success
|
||||
expire_in: 2h
|
||||
expire_in: 1h
|
||||
paths:
|
||||
- build/*
|
||||
- build/minetest/_build/*
|
||||
|
||||
.package_win_template:
|
||||
extends: .generic_win_template
|
||||
stage: package
|
||||
script:
|
||||
- cd build/minetest/_build
|
||||
- make package
|
||||
- cd ../../../
|
||||
- mkdir minetest-win-${WIN_ARCH}
|
||||
- unzip build/minetest/_build/minetest-*-win*.zip -d minetest-win-${WIN_ARCH}
|
||||
- cp /usr/${WIN_ARCH}-w64-mingw32/bin/libgcc*.dll minetest-win-${WIN_ARCH}/minetest-*-win*/bin
|
||||
- cp /usr/${WIN_ARCH}-w64-mingw32/bin/libstdc++*.dll minetest-win-${WIN_ARCH}/minetest-*-win*/bin
|
||||
- cp /usr/${WIN_ARCH}-w64-mingw32/bin/libwinpthread*.dll minetest-win-${WIN_ARCH}/minetest-*-win*/bin
|
||||
- unzip build/minetest/_build/minetest-*.zip
|
||||
- cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libgcc*.dll minetest-*-win*/bin/
|
||||
- cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libstdc++*.dll minetest-*-win*/bin/
|
||||
- cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libwinpthread*.dll minetest-*-win*/bin/
|
||||
artifacts:
|
||||
when: on_success
|
||||
expire_in: 90 day
|
||||
paths:
|
||||
- minetest-win-*/*
|
||||
- minetest-*-win*/*
|
||||
|
||||
build:win32:
|
||||
extends: .build_win_template
|
||||
script:
|
||||
- ./util/buildbot/buildwin32.sh build
|
||||
variables:
|
||||
NO_PACKAGE: "1"
|
||||
WIN_ARCH: "i686"
|
||||
|
||||
package:win32:
|
||||
extends: .package_win_template
|
||||
dependencies:
|
||||
needs:
|
||||
- build:win32
|
||||
variables:
|
||||
NO_PACKAGE: "1"
|
||||
WIN_ARCH: "i686"
|
||||
|
||||
|
||||
build:win64:
|
||||
extends: .build_win_template
|
||||
script:
|
||||
- ./util/buildbot/buildwin64.sh build
|
||||
variables:
|
||||
NO_PACKAGE: "1"
|
||||
WIN_ARCH: "x86_64"
|
||||
|
||||
package:win64:
|
||||
extends: .package_win_template
|
||||
dependencies:
|
||||
needs:
|
||||
- build:win64
|
||||
variables:
|
||||
NO_PACKAGE: "1"
|
||||
WIN_ARCH: "x86_64"
|
||||
|
||||
##
|
||||
## Docker
|
||||
##
|
||||
|
||||
package:docker:
|
||||
stage: package
|
||||
image: docker:stable
|
||||
@ -288,6 +244,10 @@ package:docker:
|
||||
- docker push ${CONTAINER_IMAGE}/server:$CI_COMMIT_REF_NAME
|
||||
- docker push ${CONTAINER_IMAGE}/server:latest
|
||||
|
||||
##
|
||||
## Gitlab Pages (Lua API documentation)
|
||||
##
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
image: python:3.8
|
||||
@ -303,10 +263,14 @@ pages:
|
||||
only:
|
||||
- master
|
||||
|
||||
##
|
||||
## AppImage
|
||||
##
|
||||
|
||||
package:appimage-client:
|
||||
stage: package
|
||||
image: appimagecrafters/appimage-builder
|
||||
dependencies:
|
||||
needs:
|
||||
- build:ubuntu-18.04
|
||||
before_script:
|
||||
- apt-get update -y
|
||||
@ -315,16 +279,15 @@ package:appimage-client:
|
||||
- mkdir AppDir
|
||||
- cp -a artifact/minetest/usr/ AppDir/usr/
|
||||
- rm AppDir/usr/bin/minetestserver
|
||||
- cp -R clientmods AppDir/usr/share/minetest
|
||||
- cp -a clientmods AppDir/usr/share/minetest
|
||||
script:
|
||||
- git clone $MINETEST_GAME_REPO AppDir/usr/share/minetest/games/minetest_game
|
||||
- rm -Rf AppDir/usr/share/minetest/games/minetest/.git
|
||||
- rm -rf AppDir/usr/share/minetest/games/minetest/.git
|
||||
- export VERSION=$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA
|
||||
# Remove PrefersNonDefaultGPU property due to validation errors
|
||||
- sed -i '/PrefersNonDefaultGPU/d' AppDir/usr/share/applications/net.minetest.minetest.desktop
|
||||
- appimage-builder --skip-test
|
||||
artifacts:
|
||||
when: on_success
|
||||
expire_in: 90 day
|
||||
paths:
|
||||
- ./*.AppImage
|
||||
|
@ -1,15 +1,9 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
if(${CMAKE_VERSION} STREQUAL "2.8.2")
|
||||
# Bug http://vtk.org/Bug/view.php?id=11020
|
||||
message(WARNING "CMake/CPack version 2.8.2 will not create working .deb packages!")
|
||||
endif()
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# This can be read from ${PROJECT_NAME} after project() is called
|
||||
project(minetest)
|
||||
set(PROJECT_NAME_CAPITALIZED "Dragonfire")
|
||||
|
||||
# Works only for cmake 3.1 and greater
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(GCC_MINIMUM_VERSION "4.8")
|
||||
set(CLANG_MINIMUM_VERSION "3.4")
|
||||
@ -278,11 +272,12 @@ if(WIN32)
|
||||
set(CPACK_GENERATOR ZIP)
|
||||
|
||||
else()
|
||||
set(CPACK_GENERATOR WIX ZIP)
|
||||
set(CPACK_GENERATOR WIX)
|
||||
set(CPACK_PACKAGE_NAME "${PROJECT_NAME_CAPITALIZED}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME_CAPITALIZED}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ".")
|
||||
set(CPACK_PACKAGE_EXECUTABLES ${PROJECT_NAME} "${PROJECT_NAME_CAPITALIZED}")
|
||||
set(CPACK_CREATE_DESKTOP_LINKS ${PROJECT_NAME})
|
||||
set(CPACK_PACKAGING_INSTALL_PREFIX "/${PROJECT_NAME_CAPITALIZED}")
|
||||
|
||||
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/misc/minetest-icon.ico")
|
||||
# Supported languages can be found at
|
||||
|
13
LICENSE.txt
13
LICENSE.txt
@ -11,6 +11,9 @@ http://creativecommons.org/licenses/by-sa/3.0/
|
||||
textures/base/pack/refresh.png is under the Apache 2 license
|
||||
https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
Textures by Zughy are under CC BY-SA 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
Authors of media files
|
||||
-----------------------
|
||||
Everything not listed in here:
|
||||
@ -23,6 +26,8 @@ paramat:
|
||||
textures/base/pack/menu_header.png
|
||||
textures/base/pack/next_icon.png
|
||||
textures/base/pack/prev_icon.png
|
||||
textures/base/pack/clear.png
|
||||
textures/base/pack/search.png
|
||||
|
||||
rubenwardy, paramat:
|
||||
textures/base/pack/start_icon.png
|
||||
@ -45,6 +50,14 @@ srifqi
|
||||
textures/base/pack/joystick_off.png
|
||||
textures/base/pack/minimap_btn.png
|
||||
|
||||
Zughy:
|
||||
textures/base/pack/cdb_add.png
|
||||
textures/base/pack/cdb_clear.png
|
||||
textures/base/pack/cdb_downloading.png
|
||||
textures/base/pack/cdb_queued.png
|
||||
textures/base/pack/cdb_update.png
|
||||
textures/base/pack/cdb_viewonline.png
|
||||
|
||||
License of Minetest source code
|
||||
-------------------------------
|
||||
|
||||
|
@ -142,8 +142,8 @@ public class GameActivity extends NativeActivity {
|
||||
return getResources().getDisplayMetrics().widthPixels;
|
||||
}
|
||||
|
||||
public void openURL(String url) {
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
public void openURI(String uri) {
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
|
||||
startActivity(browserIntent);
|
||||
}
|
||||
}
|
||||
|
@ -781,3 +781,7 @@ function core.privs_to_string(privs, delim)
|
||||
end
|
||||
return table.concat(list, delim)
|
||||
end
|
||||
|
||||
function core.is_nan(number)
|
||||
return number ~= number
|
||||
end
|
||||
|
@ -152,8 +152,8 @@ core.register_entity(":__builtin:falling_node", {
|
||||
else
|
||||
self.object:set_yaw(-math.pi*0.25)
|
||||
end
|
||||
elseif (node.param2 ~= 0 and (def.wield_image == ""
|
||||
or def.wield_image == nil))
|
||||
elseif ((node.param2 ~= 0 or def.drawtype == "nodebox" or def.drawtype == "mesh")
|
||||
and (def.wield_image == "" or def.wield_image == nil))
|
||||
or def.drawtype == "signlike"
|
||||
or def.drawtype == "mesh"
|
||||
or def.drawtype == "normal"
|
||||
@ -168,16 +168,30 @@ core.register_entity(":__builtin:falling_node", {
|
||||
elseif (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted") then
|
||||
local rot = node.param2 % 8
|
||||
local pitch, yaw, roll = 0, 0, 0
|
||||
if rot == 1 then
|
||||
pitch, yaw = math.pi, math.pi
|
||||
elseif rot == 2 then
|
||||
pitch, yaw = math.pi/2, math.pi/2
|
||||
elseif rot == 3 then
|
||||
pitch, yaw = math.pi/2, -math.pi/2
|
||||
elseif rot == 4 then
|
||||
pitch, yaw = math.pi/2, math.pi
|
||||
elseif rot == 5 then
|
||||
pitch, yaw = math.pi/2, 0
|
||||
if def.drawtype == "nodebox" or def.drawtype == "mesh" then
|
||||
if rot == 0 then
|
||||
pitch, yaw = math.pi/2, 0
|
||||
elseif rot == 1 then
|
||||
pitch, yaw = -math.pi/2, math.pi
|
||||
elseif rot == 2 then
|
||||
pitch, yaw = 0, math.pi/2
|
||||
elseif rot == 3 then
|
||||
pitch, yaw = 0, -math.pi/2
|
||||
elseif rot == 4 then
|
||||
pitch, yaw = 0, math.pi
|
||||
end
|
||||
else
|
||||
if rot == 1 then
|
||||
pitch, yaw = math.pi, math.pi
|
||||
elseif rot == 2 then
|
||||
pitch, yaw = math.pi/2, math.pi/2
|
||||
elseif rot == 3 then
|
||||
pitch, yaw = math.pi/2, -math.pi/2
|
||||
elseif rot == 4 then
|
||||
pitch, yaw = math.pi/2, math.pi
|
||||
elseif rot == 5 then
|
||||
pitch, yaw = math.pi/2, 0
|
||||
end
|
||||
end
|
||||
if def.drawtype == "signlike" then
|
||||
pitch = pitch - math.pi/2
|
||||
@ -186,7 +200,7 @@ core.register_entity(":__builtin:falling_node", {
|
||||
elseif rot == 1 then
|
||||
yaw = yaw - math.pi/2
|
||||
end
|
||||
elseif def.drawtype == "mesh" or def.drawtype == "normal" then
|
||||
elseif def.drawtype == "mesh" or def.drawtype == "normal" or def.drawtype == "nodebox" then
|
||||
if rot >= 0 and rot <= 1 then
|
||||
roll = roll + math.pi
|
||||
else
|
||||
|
@ -159,6 +159,331 @@ local function queue_download(package)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_raw_dependencies(package)
|
||||
if package.raw_deps then
|
||||
return package.raw_deps
|
||||
end
|
||||
|
||||
local url_fmt = "/api/packages/%s/dependencies/?only_hard=1&protocol_version=%s&engine_version=%s"
|
||||
local version = core.get_version()
|
||||
local base_url = core.settings:get("contentdb_url")
|
||||
local url = base_url .. url_fmt:format(package.id, core.get_max_supp_proto(), version.string)
|
||||
|
||||
local response = http.fetch_sync({ url = url })
|
||||
if not response.succeeded then
|
||||
return
|
||||
end
|
||||
|
||||
local data = core.parse_json(response.data) or {}
|
||||
|
||||
local content_lookup = {}
|
||||
for _, pkg in pairs(store.packages_full) do
|
||||
content_lookup[pkg.id] = pkg
|
||||
end
|
||||
|
||||
for id, raw_deps in pairs(data) do
|
||||
local package2 = content_lookup[id:lower()]
|
||||
if package2 and not package2.raw_deps then
|
||||
package2.raw_deps = raw_deps
|
||||
|
||||
for _, dep in pairs(raw_deps) do
|
||||
local packages = {}
|
||||
for i=1, #dep.packages do
|
||||
packages[#packages + 1] = content_lookup[dep.packages[i]:lower()]
|
||||
end
|
||||
dep.packages = packages
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return package.raw_deps
|
||||
end
|
||||
|
||||
local function has_hard_deps(raw_deps)
|
||||
for i=1, #raw_deps do
|
||||
if not raw_deps[i].is_optional then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- Recursively resolve dependencies, given the installed mods
|
||||
local function resolve_dependencies_2(raw_deps, installed_mods, out)
|
||||
local function resolve_dep(dep)
|
||||
-- Check whether it's already installed
|
||||
if installed_mods[dep.name] then
|
||||
return {
|
||||
is_optional = dep.is_optional,
|
||||
name = dep.name,
|
||||
installed = true,
|
||||
}
|
||||
end
|
||||
|
||||
-- Find exact name matches
|
||||
local fallback
|
||||
for _, package in pairs(dep.packages) do
|
||||
if package.type ~= "game" then
|
||||
if package.name == dep.name then
|
||||
return {
|
||||
is_optional = dep.is_optional,
|
||||
name = dep.name,
|
||||
installed = false,
|
||||
package = package,
|
||||
}
|
||||
elseif not fallback then
|
||||
fallback = package
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Otherwise, find the first mod that fulfils it
|
||||
if fallback then
|
||||
return {
|
||||
is_optional = dep.is_optional,
|
||||
name = dep.name,
|
||||
installed = false,
|
||||
package = fallback,
|
||||
}
|
||||
end
|
||||
|
||||
return {
|
||||
is_optional = dep.is_optional,
|
||||
name = dep.name,
|
||||
installed = false,
|
||||
}
|
||||
end
|
||||
|
||||
for _, dep in pairs(raw_deps) do
|
||||
if not dep.is_optional and not out[dep.name] then
|
||||
local result = resolve_dep(dep)
|
||||
out[dep.name] = result
|
||||
if result and result.package and not result.installed then
|
||||
local raw_deps2 = get_raw_dependencies(result.package)
|
||||
if raw_deps2 then
|
||||
resolve_dependencies_2(raw_deps2, installed_mods, out)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Resolve dependencies for a package, calls the recursive version.
|
||||
local function resolve_dependencies(raw_deps, game)
|
||||
assert(game)
|
||||
|
||||
local installed_mods = {}
|
||||
|
||||
local mods = {}
|
||||
pkgmgr.get_game_mods(game, mods)
|
||||
for _, mod in pairs(mods) do
|
||||
installed_mods[mod.name] = true
|
||||
end
|
||||
|
||||
for _, mod in pairs(pkgmgr.global_mods:get_list()) do
|
||||
installed_mods[mod.name] = true
|
||||
end
|
||||
|
||||
local out = {}
|
||||
if not resolve_dependencies_2(raw_deps, installed_mods, out) then
|
||||
return nil
|
||||
end
|
||||
|
||||
local retval = {}
|
||||
for _, dep in pairs(out) do
|
||||
retval[#retval + 1] = dep
|
||||
end
|
||||
|
||||
table.sort(retval, function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
||||
return retval
|
||||
end
|
||||
|
||||
local install_dialog = {}
|
||||
function install_dialog.get_formspec()
|
||||
local package = install_dialog.package
|
||||
local raw_deps = install_dialog.raw_deps
|
||||
local will_install_deps = install_dialog.will_install_deps
|
||||
|
||||
local selected_game_idx = 1
|
||||
local selected_gameid = core.settings:get("menu_last_game")
|
||||
local games = table.copy(pkgmgr.games)
|
||||
for i=1, #games do
|
||||
if selected_gameid and games[i].id == selected_gameid then
|
||||
selected_game_idx = i
|
||||
end
|
||||
|
||||
games[i] = minetest.formspec_escape(games[i].name)
|
||||
end
|
||||
|
||||
local selected_game = pkgmgr.games[selected_game_idx]
|
||||
local deps_to_install = 0
|
||||
local deps_not_found = 0
|
||||
|
||||
install_dialog.dependencies = resolve_dependencies(raw_deps, selected_game)
|
||||
local formatted_deps = {}
|
||||
for _, dep in pairs(install_dialog.dependencies) do
|
||||
formatted_deps[#formatted_deps + 1] = "#fff"
|
||||
formatted_deps[#formatted_deps + 1] = minetest.formspec_escape(dep.name)
|
||||
if dep.installed then
|
||||
formatted_deps[#formatted_deps + 1] = "#ccf"
|
||||
formatted_deps[#formatted_deps + 1] = fgettext("Already installed")
|
||||
elseif dep.package then
|
||||
formatted_deps[#formatted_deps + 1] = "#cfc"
|
||||
formatted_deps[#formatted_deps + 1] = fgettext("$1 by $2", dep.package.title, dep.package.author)
|
||||
deps_to_install = deps_to_install + 1
|
||||
else
|
||||
formatted_deps[#formatted_deps + 1] = "#f00"
|
||||
formatted_deps[#formatted_deps + 1] = fgettext("Not found")
|
||||
deps_not_found = deps_not_found + 1
|
||||
end
|
||||
end
|
||||
|
||||
local message_bg = "#3333"
|
||||
local message
|
||||
if will_install_deps then
|
||||
message = fgettext("$1 and $2 dependencies will be installed.", package.title, deps_to_install)
|
||||
else
|
||||
message = fgettext("$1 will be installed, and $2 dependencies will be skipped.", package.title, deps_to_install)
|
||||
end
|
||||
if deps_not_found > 0 then
|
||||
message = fgettext("$1 required dependencies could not be found.", deps_not_found) ..
|
||||
" " .. fgettext("Please check that the base game is correct.", deps_not_found) ..
|
||||
"\n" .. message
|
||||
message_bg = mt_color_orange
|
||||
end
|
||||
|
||||
local formspec = {
|
||||
"formspec_version[3]",
|
||||
"size[7,7.85]",
|
||||
"style[title;border=false]",
|
||||
"box[0,0;7,0.5;#3333]",
|
||||
"button[0,0;7,0.5;title;", fgettext("Install $1", package.title) , "]",
|
||||
|
||||
"container[0.375,0.70]",
|
||||
|
||||
"label[0,0.25;", fgettext("Base Game:"), "]",
|
||||
"dropdown[2,0;4.25,0.5;gameid;", table.concat(games, ","), ";", selected_game_idx, "]",
|
||||
|
||||
"label[0,0.8;", fgettext("Dependencies:"), "]",
|
||||
|
||||
"tablecolumns[color;text;color;text]",
|
||||
"table[0,1.1;6.25,3;packages;", table.concat(formatted_deps, ","), "]",
|
||||
|
||||
"container_end[]",
|
||||
|
||||
"checkbox[0.375,5.1;will_install_deps;",
|
||||
fgettext("Install missing dependencies"), ";",
|
||||
will_install_deps and "true" or "false", "]",
|
||||
|
||||
"box[0,5.4;7,1.2;", message_bg, "]",
|
||||
"textarea[0.375,5.5;6.25,1;;;", message, "]",
|
||||
|
||||
"container[1.375,6.85]",
|
||||
"button[0,0;2,0.8;install_all;", fgettext("Install"), "]",
|
||||
"button[2.25,0;2,0.8;cancel;", fgettext("Cancel"), "]",
|
||||
"container_end[]",
|
||||
}
|
||||
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
|
||||
function install_dialog.handle_submit(this, fields)
|
||||
if fields.cancel then
|
||||
this:delete()
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.will_install_deps ~= nil then
|
||||
install_dialog.will_install_deps = minetest.is_yes(fields.will_install_deps)
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.install_all then
|
||||
queue_download(install_dialog.package)
|
||||
|
||||
if install_dialog.will_install_deps then
|
||||
for _, dep in pairs(install_dialog.dependencies) do
|
||||
if not dep.is_optional and not dep.installed and dep.package then
|
||||
queue_download(dep.package)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
this:delete()
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.gameid then
|
||||
for _, game in pairs(pkgmgr.games) do
|
||||
if game.name == fields.gameid then
|
||||
core.settings:set("menu_last_game", game.id)
|
||||
break
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function install_dialog.create(package, raw_deps)
|
||||
install_dialog.dependencies = nil
|
||||
install_dialog.package = package
|
||||
install_dialog.raw_deps = raw_deps
|
||||
install_dialog.will_install_deps = true
|
||||
return dialog_create("install_dialog",
|
||||
install_dialog.get_formspec,
|
||||
install_dialog.handle_submit,
|
||||
nil)
|
||||
end
|
||||
|
||||
|
||||
local confirm_overwrite = {}
|
||||
function confirm_overwrite.get_formspec()
|
||||
local package = confirm_overwrite.package
|
||||
|
||||
return "size[11.5,4.5,true]" ..
|
||||
"label[2,2;" ..
|
||||
fgettext("\"$1\" already exists. Would you like to overwrite it?", package.name) .. "]"..
|
||||
"style[install;bgcolor=red]" ..
|
||||
"button[3.25,3.5;2.5,0.5;install;" .. fgettext("Overwrite") .. "]" ..
|
||||
"button[5.75,3.5;2.5,0.5;cancel;" .. fgettext("Cancel") .. "]"
|
||||
end
|
||||
|
||||
function confirm_overwrite.handle_submit(this, fields)
|
||||
if fields.cancel then
|
||||
this:delete()
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.install then
|
||||
this:delete()
|
||||
confirm_overwrite.callback()
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function confirm_overwrite.create(package, callback)
|
||||
assert(type(package) == "table")
|
||||
assert(type(callback) == "function")
|
||||
|
||||
confirm_overwrite.package = package
|
||||
confirm_overwrite.callback = callback
|
||||
return dialog_create("confirm_overwrite",
|
||||
confirm_overwrite.get_formspec,
|
||||
confirm_overwrite.handle_submit,
|
||||
nil)
|
||||
end
|
||||
|
||||
|
||||
local function get_file_extension(path)
|
||||
local parts = path:split(".")
|
||||
return parts[#parts]
|
||||
@ -340,7 +665,6 @@ function store.get_formspec(dlgdata)
|
||||
|
||||
local W = 15.75
|
||||
local H = 9.5
|
||||
|
||||
local formspec
|
||||
if #store.packages_full > 0 then
|
||||
formspec = {
|
||||
@ -348,12 +672,13 @@ function store.get_formspec(dlgdata)
|
||||
"size[15.75,9.5]",
|
||||
"position[0.5,0.55]",
|
||||
|
||||
"style[status;border=false]",
|
||||
"style[status,downloading,queued;border=false]",
|
||||
|
||||
"container[0.375,0.375]",
|
||||
"field[0,0;7.225,0.8;search_string;;", core.formspec_escape(search_string), "]",
|
||||
"field_close_on_enter[search_string;false]",
|
||||
"button[7.225,0;2,0.8;search;", fgettext("Search"), "]",
|
||||
"image_button[7.3,0;0.8,0.8;", core.formspec_escape(defaulttexturedir .. "search.png"), ";search;]",
|
||||
"image_button[8.125,0;0.8,0.8;", core.formspec_escape(defaulttexturedir .. "clear.png"), ";clear;]",
|
||||
"dropdown[9.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]",
|
||||
"container_end[]",
|
||||
|
||||
@ -374,7 +699,7 @@ function store.get_formspec(dlgdata)
|
||||
}
|
||||
|
||||
if number_downloading > 0 then
|
||||
formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;status;"
|
||||
formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;downloading;"
|
||||
if #download_queue > 0 then
|
||||
formspec[#formspec + 1] = fgettext("$1 downloading,\n$2 queued", number_downloading, #download_queue)
|
||||
else
|
||||
@ -418,11 +743,17 @@ function store.get_formspec(dlgdata)
|
||||
}
|
||||
end
|
||||
|
||||
-- download/queued tooltips always have the same message
|
||||
local tooltip_colors = ";#dff6f5;#302c2e]"
|
||||
formspec[#formspec + 1] = "tooltip[downloading;" .. fgettext("Downloading...") .. tooltip_colors
|
||||
formspec[#formspec + 1] = "tooltip[queued;" .. fgettext("Queued") .. tooltip_colors
|
||||
|
||||
local start_idx = (cur_page - 1) * num_per_page + 1
|
||||
for i=start_idx, math.min(#store.packages, start_idx+num_per_page-1) do
|
||||
local package = store.packages[i]
|
||||
local container_y = (i - start_idx) * 1.375 + (2*0.375 + 0.8)
|
||||
formspec[#formspec + 1] = "container[0.375,"
|
||||
formspec[#formspec + 1] = (i - start_idx) * 1.375 + (2*0.375 + 0.8)
|
||||
formspec[#formspec + 1] = container_y
|
||||
formspec[#formspec + 1] = "]"
|
||||
|
||||
-- image
|
||||
@ -438,52 +769,50 @@ function store.get_formspec(dlgdata)
|
||||
formspec[#formspec + 1] = "]"
|
||||
|
||||
-- buttons
|
||||
local description_width = W - 0.375*5 - 1 - 2*1.5
|
||||
local left_base = "image_button[-1.55,0;0.7,0.7;" .. core.formspec_escape(defaulttexturedir)
|
||||
formspec[#formspec + 1] = "container["
|
||||
formspec[#formspec + 1] = W - 0.375*2
|
||||
formspec[#formspec + 1] = ",0.1]"
|
||||
|
||||
if package.downloading then
|
||||
formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;"
|
||||
formspec[#formspec + 1] = fgettext("Downloading...")
|
||||
formspec[#formspec + 1] = "]"
|
||||
formspec[#formspec + 1] = "animated_image[-1.7,-0.15;1,1;downloading;"
|
||||
formspec[#formspec + 1] = core.formspec_escape(defaulttexturedir)
|
||||
formspec[#formspec + 1] = "cdb_downloading.png;3;400;]"
|
||||
elseif package.queued then
|
||||
formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;"
|
||||
formspec[#formspec + 1] = fgettext("Queued")
|
||||
formspec[#formspec + 1] = "]"
|
||||
formspec[#formspec + 1] = left_base
|
||||
formspec[#formspec + 1] = core.formspec_escape(defaulttexturedir)
|
||||
formspec[#formspec + 1] = "cdb_queued.png;queued]"
|
||||
elseif not package.path then
|
||||
formspec[#formspec + 1] = "button[-3,0;1.5,0.8;install_"
|
||||
formspec[#formspec + 1] = tostring(i)
|
||||
formspec[#formspec + 1] = ";"
|
||||
formspec[#formspec + 1] = fgettext("Install")
|
||||
formspec[#formspec + 1] = "]"
|
||||
local elem_name = "install_" .. i .. ";"
|
||||
formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#71aa34]"
|
||||
formspec[#formspec + 1] = left_base .. "cdb_add.png;" .. elem_name .. "]"
|
||||
formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Install") .. tooltip_colors
|
||||
else
|
||||
if package.installed_release < package.release then
|
||||
description_width = description_width - 1.5
|
||||
|
||||
-- The install_ action also handles updating
|
||||
formspec[#formspec + 1] = "button[-4.5,0;1.5,0.8;install_"
|
||||
formspec[#formspec + 1] = tostring(i)
|
||||
formspec[#formspec + 1] = ";"
|
||||
formspec[#formspec + 1] = fgettext("Update")
|
||||
formspec[#formspec + 1] = "]"
|
||||
end
|
||||
local elem_name = "install_" .. i .. ";"
|
||||
formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#28ccdf]"
|
||||
formspec[#formspec + 1] = left_base .. "cdb_update.png;" .. elem_name .. "]"
|
||||
formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Update") .. tooltip_colors
|
||||
else
|
||||
|
||||
formspec[#formspec + 1] = "button[-3,0;1.5,0.8;uninstall_"
|
||||
formspec[#formspec + 1] = tostring(i)
|
||||
formspec[#formspec + 1] = ";"
|
||||
formspec[#formspec + 1] = fgettext("Uninstall")
|
||||
formspec[#formspec + 1] = "]"
|
||||
local elem_name = "uninstall_" .. i .. ";"
|
||||
formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#a93b3b]"
|
||||
formspec[#formspec + 1] = left_base .. "cdb_clear.png;" .. elem_name .. "]"
|
||||
formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Uninstall") .. tooltip_colors
|
||||
end
|
||||
end
|
||||
|
||||
formspec[#formspec + 1] = "button[-1.5,0;1.5,0.8;view_"
|
||||
formspec[#formspec + 1] = tostring(i)
|
||||
formspec[#formspec + 1] = ";"
|
||||
formspec[#formspec + 1] = fgettext("View")
|
||||
formspec[#formspec + 1] = "]"
|
||||
local web_elem_name = "view_" .. i .. ";"
|
||||
formspec[#formspec + 1] = "image_button[-0.7,0;0.7,0.7;" ..
|
||||
core.formspec_escape(defaulttexturedir) .. "cdb_viewonline.png;" .. web_elem_name .. "]"
|
||||
formspec[#formspec + 1] = "tooltip[" .. web_elem_name ..
|
||||
fgettext("View more information in a web browser") .. tooltip_colors
|
||||
formspec[#formspec + 1] = "container_end[]"
|
||||
|
||||
-- description
|
||||
local description_width = W - 0.375*5 - 0.85 - 2*0.7
|
||||
formspec[#formspec + 1] = "textarea[1.855,0.3;"
|
||||
formspec[#formspec + 1] = tostring(description_width)
|
||||
formspec[#formspec + 1] = ",0.8;;;"
|
||||
@ -504,6 +833,13 @@ function store.handle_submit(this, fields)
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.clear then
|
||||
search_string = ""
|
||||
cur_page = 1
|
||||
store.filter_packages("")
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.back then
|
||||
this:delete()
|
||||
return true
|
||||
@ -563,15 +899,47 @@ function store.handle_submit(this, fields)
|
||||
assert(package)
|
||||
|
||||
if fields["install_" .. i] then
|
||||
queue_download(package)
|
||||
local install_parent
|
||||
if package.type == "mod" then
|
||||
install_parent = core.get_modpath()
|
||||
elseif package.type == "game" then
|
||||
install_parent = core.get_gamepath()
|
||||
elseif package.type == "txp" then
|
||||
install_parent = core.get_texturepath()
|
||||
else
|
||||
error("Unknown package type: " .. package.type)
|
||||
end
|
||||
|
||||
|
||||
local function on_confirm()
|
||||
local deps = get_raw_dependencies(package)
|
||||
if deps and has_hard_deps(deps) then
|
||||
local dlg = install_dialog.create(package, deps)
|
||||
dlg:set_parent(this)
|
||||
this:hide()
|
||||
dlg:show()
|
||||
else
|
||||
queue_download(package)
|
||||
end
|
||||
end
|
||||
|
||||
if not package.path and core.is_dir(install_parent .. DIR_DELIM .. package.name) then
|
||||
local dlg = confirm_overwrite.create(package, on_confirm)
|
||||
dlg:set_parent(this)
|
||||
this:hide()
|
||||
dlg:show()
|
||||
else
|
||||
on_confirm()
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if fields["uninstall_" .. i] then
|
||||
local dlg_delmod = create_delete_content_dlg(package)
|
||||
dlg_delmod:set_parent(this)
|
||||
local dlg = create_delete_content_dlg(package)
|
||||
dlg:set_parent(this)
|
||||
this:hide()
|
||||
dlg_delmod:show()
|
||||
dlg:show()
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -98,7 +98,7 @@ local function create_world_formspec(dialogdata)
|
||||
-- Error out when no games found
|
||||
if #pkgmgr.games == 0 then
|
||||
return "size[12.25,3,true]" ..
|
||||
"box[0,0;12,2;#ff8800]" ..
|
||||
"box[0,0;12,2;" .. mt_color_orange .. "]" ..
|
||||
"textarea[0.3,0;11.7,2;;;"..
|
||||
fgettext("You have no games installed.") .. "\n" ..
|
||||
fgettext("Download one from minetest.net") .. "]" ..
|
||||
|
@ -19,6 +19,7 @@ mt_color_grey = "#AAAAAA"
|
||||
mt_color_blue = "#6389FF"
|
||||
mt_color_green = "#72FF63"
|
||||
mt_color_dark_green = "#25C191"
|
||||
mt_color_orange = "#FF8800"
|
||||
|
||||
local menupath = core.get_mainmenu_path()
|
||||
local basepath = core.get_builtin_path()
|
||||
@ -105,6 +106,16 @@ local function init_globals()
|
||||
if last_tab and tv_main.current_tab ~= last_tab then
|
||||
tv_main:set_tab(last_tab)
|
||||
end
|
||||
|
||||
-- In case the folder of the last selected game has been deleted,
|
||||
-- display "Minetest" as a header
|
||||
if tv_main.current_tab == "local" then
|
||||
local game = pkgmgr.find_by_gameid(core.settings:get("menu_last_game"))
|
||||
if game == nil then
|
||||
mm_texture.reset()
|
||||
end
|
||||
end
|
||||
|
||||
ui.set_default("maintab")
|
||||
tv_main:show()
|
||||
|
||||
|
@ -109,9 +109,10 @@ return {
|
||||
cbf_formspec = function(tabview, name, tabdata)
|
||||
local logofile = defaulttexturedir .. "logo.png"
|
||||
local version = core.get_version()
|
||||
return "image[0.5,1;" .. core.formspec_escape(logofile) .. "]" ..
|
||||
"label[0.5,2.8;" .. version.project .. " " .. version.string .. "]" ..
|
||||
"button[0.5,3;2,2;homepage;minetest.net]" ..
|
||||
local fs = "image[0.75,0.5;2.2,2.2;" .. core.formspec_escape(logofile) .. "]" ..
|
||||
"style[label_button;border=false]" ..
|
||||
"button[0.5,2;2.5,2;label_button;" .. version.project .. " " .. version.string .. "]" ..
|
||||
"button[0.75,2.75;2,2;homepage;minetest.net]" ..
|
||||
"tablecolumns[color;text]" ..
|
||||
"tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
|
||||
"table[3.5,-0.25;8.5,6.05;list_credits;" ..
|
||||
@ -126,10 +127,23 @@ return {
|
||||
"#FFFF00," .. fgettext("Previous Contributors") .. ",," ..
|
||||
buildCreditList(previous_contributors) .. "," ..
|
||||
";1]"
|
||||
|
||||
if PLATFORM ~= "Android" then
|
||||
fs = fs .. "tooltip[userdata;" ..
|
||||
fgettext("Opens the directory that contains user-provided worlds, games, mods,\n" ..
|
||||
"and texture packs in a file manager / explorer.") .. "]"
|
||||
fs = fs .. "button[0,4.75;3.5,1;userdata;" .. fgettext("Open User Data Directory") .. "]"
|
||||
end
|
||||
|
||||
return fs
|
||||
end,
|
||||
cbf_button_handler = function(this, fields, name, tabdata)
|
||||
if fields.homepage then
|
||||
core.open_url("https://www.minetest.net")
|
||||
end
|
||||
|
||||
if fields.userdata then
|
||||
core.open_dir(core.get_user_path())
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
local enable_gamebar = PLATFORM ~= "Android"
|
||||
local current_game, singleplayer_refresh_gamebar
|
||||
|
||||
if enable_gamebar then
|
||||
function current_game()
|
||||
local last_game_id = core.settings:get("menu_last_game")
|
||||
|
@ -34,7 +34,8 @@ local function get_formspec(tabview, name, tabdata)
|
||||
local retval =
|
||||
-- Search
|
||||
"field[0.15,0.075;5.91,1;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" ..
|
||||
"button[5.62,-0.25;1.5,1;btn_mp_search;" .. fgettext("Search") .. "]" ..
|
||||
"image_button[5.63,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "search.png") .. ";btn_mp_search;]" ..
|
||||
"image_button[6.3,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "clear.png") .. ";btn_mp_clear;]" ..
|
||||
"image_button[6.97,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "refresh.png")
|
||||
.. ";btn_mp_refresh;]" ..
|
||||
|
||||
@ -243,6 +244,12 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.btn_mp_clear then
|
||||
tabdata.search_for = ""
|
||||
menudata.search_result = nil
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.btn_mp_search or fields.key_enter_field == "te_search" then
|
||||
tabdata.fav_selected = 1
|
||||
local input = fields.te_search:lower()
|
||||
|
@ -160,6 +160,7 @@ local function init()
|
||||
-- Simple iteration would ignore lookup via __index.
|
||||
local entity_instrumentation = {
|
||||
"on_activate",
|
||||
"on_deactivate",
|
||||
"on_step",
|
||||
"on_punch",
|
||||
"on_rightclick",
|
||||
|
@ -152,6 +152,9 @@ joystick_type (Joystick type) enum auto auto,generic,xbox
|
||||
# when holding down a joystick button combination.
|
||||
repeat_joystick_button_time (Joystick button repetition interval) float 0.17 0.001
|
||||
|
||||
# The deadzone of the joystick
|
||||
joystick_deadzone (Joystick deadzone) int 2048
|
||||
|
||||
# The sensitivity of the joystick axes for moving the
|
||||
# ingame view frustum around.
|
||||
joystick_frustum_sensitivity (Joystick frustum sensitivity) float 170
|
||||
@ -1060,6 +1063,13 @@ full_block_send_enable_min_time_from_building (Delay in sending blocks after bui
|
||||
# client number.
|
||||
max_packets_per_iteration (Max. packets per iteration) int 1024
|
||||
|
||||
# ZLib compression level to use when sending mapblocks to the client.
|
||||
# -1 - Zlib's default compression level
|
||||
# 0 - no compresson, fastest
|
||||
# 9 - best compression, slowest
|
||||
# (levels 1-3 use Zlib's "fast" method, 4-9 use the normal method)
|
||||
map_compression_level_net (Map Compression Level for Network Transfer) int -1 -1 9
|
||||
|
||||
[*Game]
|
||||
|
||||
# Default game when creating a new world.
|
||||
@ -1252,6 +1262,13 @@ max_objects_per_block (Maximum objects per block) int 64
|
||||
# See https://www.sqlite.org/pragma.html#pragma_synchronous
|
||||
sqlite_synchronous (Synchronous SQLite) enum 2 0,1,2
|
||||
|
||||
# ZLib compression level to use when saving mapblocks to disk.
|
||||
# -1 - Zlib's default compression level
|
||||
# 0 - no compresson, fastest
|
||||
# 9 - best compression, slowest
|
||||
# (levels 1-3 use Zlib's "fast" method, 4-9 use the normal method)
|
||||
map_compression_level_disk (Map Compression Level for Disk Storage) int 3 -1 9
|
||||
|
||||
# Length of a server tick and the interval at which objects are generally updated over
|
||||
# network.
|
||||
dedicated_server_step (Dedicated server step) float 0.09
|
||||
@ -2200,6 +2217,7 @@ contentdb_url (ContentDB URL) string https://content.minetest.net
|
||||
contentdb_flag_blacklist (ContentDB Flag Blacklist) string nonfree, desktop_default
|
||||
|
||||
# Maximum number of concurrent downloads. Downloads exceeding this limit will be queued.
|
||||
# This should be lower than curl_parallel_limit.
|
||||
contentdb_max_concurrent_downloads (ContentDB Max Concurrent Downloads) int 3
|
||||
|
||||
[Cheat Menu]
|
||||
|
@ -16,13 +16,17 @@ varying vec3 vPosition;
|
||||
// precision must be considered).
|
||||
varying vec3 worldPosition;
|
||||
varying lowp vec4 varColor;
|
||||
centroid varying mediump vec2 varTexCoord;
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
varying vec3 eyeVec;
|
||||
|
||||
const float fogStart = FOG_START;
|
||||
const float fogShadingParameter = 1.0 / ( 1.0 - fogStart);
|
||||
|
||||
#ifdef ENABLE_TONE_MAPPING
|
||||
#if ENABLE_TONE_MAPPING
|
||||
|
||||
/* Hable's UC2 Tone mapping parameters
|
||||
A = 0.22;
|
||||
@ -73,7 +77,7 @@ void main(void)
|
||||
|
||||
vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
|
||||
|
||||
#ifdef ENABLE_TONE_MAPPING
|
||||
#if ENABLE_TONE_MAPPING
|
||||
col = applyToneMapping(col);
|
||||
#endif
|
||||
|
||||
|
@ -19,7 +19,11 @@ varying lowp vec4 varColor;
|
||||
// The centroid keyword ensures that after interpolation the texture coordinates
|
||||
// lie within the same bounds when MSAA is en- and disabled.
|
||||
// This fixes the stripes problem with nearest-neighbour textures and MSAA.
|
||||
centroid varying mediump vec2 varTexCoord;
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
varying vec3 eyeVec;
|
||||
|
||||
// Color of the light emitted by the light sources.
|
||||
|
@ -9,7 +9,11 @@ varying vec3 vNormal;
|
||||
varying vec3 vPosition;
|
||||
varying vec3 worldPosition;
|
||||
varying lowp vec4 varColor;
|
||||
centroid varying mediump vec2 varTexCoord;
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
|
||||
varying vec3 eyeVec;
|
||||
varying float vIDiff;
|
||||
@ -19,7 +23,7 @@ const float BS = 10.0;
|
||||
const float fogStart = FOG_START;
|
||||
const float fogShadingParameter = 1.0 / (1.0 - fogStart);
|
||||
|
||||
#ifdef ENABLE_TONE_MAPPING
|
||||
#if ENABLE_TONE_MAPPING
|
||||
|
||||
/* Hable's UC2 Tone mapping parameters
|
||||
A = 0.22;
|
||||
@ -75,7 +79,7 @@ void main(void)
|
||||
|
||||
col.rgb *= emissiveColor.rgb * vIDiff;
|
||||
|
||||
#ifdef ENABLE_TONE_MAPPING
|
||||
#if ENABLE_TONE_MAPPING
|
||||
col = applyToneMapping(col);
|
||||
#endif
|
||||
|
||||
|
@ -7,7 +7,11 @@ varying vec3 vNormal;
|
||||
varying vec3 vPosition;
|
||||
varying vec3 worldPosition;
|
||||
varying lowp vec4 varColor;
|
||||
centroid varying mediump vec2 varTexCoord;
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
centroid varying vec2 varTexCoord;
|
||||
#endif
|
||||
|
||||
varying vec3 eyeVec;
|
||||
varying float vIDiff;
|
||||
|
@ -2114,6 +2114,22 @@ Examples
|
||||
list[current_player;craft;3,0;3,3;]
|
||||
list[current_player;craftpreview;7,1;1,1;]
|
||||
|
||||
Version History
|
||||
---------------
|
||||
|
||||
* FORMSPEC VERSION 1:
|
||||
* (too much)
|
||||
* FORMSPEC VERSION 2:
|
||||
* Forced real coordinates
|
||||
* background9[]: 9-slice scaling parameters
|
||||
* FORMSPEC VERSION 3:
|
||||
* Formspec elements are drawn in the order of definition
|
||||
* bgcolor[]: use 3 parameters (bgcolor, formspec (now an enum), fbgcolor)
|
||||
* box[] and image[] elements enable clipping by default
|
||||
* new element: scroll_container[]
|
||||
* FORMSPEC VERSION 4:
|
||||
* Allow dropdown indexing events
|
||||
|
||||
Elements
|
||||
--------
|
||||
|
||||
@ -2125,6 +2141,7 @@ Elements
|
||||
* Clients older than this version can neither show newer elements nor display
|
||||
elements with new arguments correctly.
|
||||
* Available since feature `formspec_version_element`.
|
||||
* See also: [Version History]
|
||||
|
||||
### `size[<W>,<H>,<fixed_size>]`
|
||||
|
||||
@ -2277,7 +2294,7 @@ Elements
|
||||
* `frame duration`: Milliseconds between each frame. `0` means the frames don't advance.
|
||||
* `frame start` (Optional): The index of the frame to start on. Default `1`.
|
||||
|
||||
### `model[<X>,<Y>;<W>,<H>;<name>;<mesh>;<textures>;<rotation X,Y>;<continuous>;<mouse control>]`
|
||||
### `model[<X>,<Y>;<W>,<H>;<name>;<mesh>;<textures>;<rotation X,Y>;<continuous>;<mouse control>;<frame loop range>]`
|
||||
|
||||
* Show a mesh model.
|
||||
* `name`: Element name that can be used for styling
|
||||
@ -2288,6 +2305,9 @@ Elements
|
||||
The axes are euler angles in degrees.
|
||||
* `continuous` (Optional): Whether the rotation is continuous. Default `false`.
|
||||
* `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`.
|
||||
* `frame loop range` (Optional): Range of the animation frames.
|
||||
* Defaults to the full range of all available frames.
|
||||
* Syntax: `<begin>,<end>`
|
||||
|
||||
### `item_image[<X>,<Y>;<W>,<H>;<item name>]`
|
||||
|
||||
@ -2789,6 +2809,7 @@ Some types may inherit styles from parent types.
|
||||
* image_button
|
||||
* item_image_button
|
||||
* label
|
||||
* model
|
||||
* pwdfield, inherits from field
|
||||
* scrollbar
|
||||
* tabheader
|
||||
@ -4188,6 +4209,8 @@ Callbacks:
|
||||
* Called when the object is instantiated.
|
||||
* `dtime_s` is the time passed since the object was unloaded, which can be
|
||||
used for updating the entity state.
|
||||
* `on_deactivate(self)
|
||||
* Called when the object is about to get removed or unloaded.
|
||||
* `on_step(self, dtime)`
|
||||
* Called on every server tick, after movement and collision processing.
|
||||
`dtime` is usually 0.1 seconds, as per the `dedicated_server_step` setting
|
||||
@ -4308,11 +4331,14 @@ Utilities
|
||||
|
||||
* `minetest.get_current_modname()`: returns the currently loading mod's name,
|
||||
when loading a mod.
|
||||
* `minetest.get_modpath(modname)`: returns e.g.
|
||||
`"/home/user/.minetest/usermods/modname"`.
|
||||
* Useful for loading additional `.lua` modules or static data from mod
|
||||
* `minetest.get_modnames()`: returns a list of installed mods
|
||||
* Return a list of installed mods, sorted alphabetically
|
||||
* `minetest.get_modpath(modname)`: returns the directory path for a mod,
|
||||
e.g. `"/home/user/.minetest/usermods/modname"`.
|
||||
* Returns nil if the mod is not enabled or does not exist (not installed).
|
||||
* Works regardless of whether the mod has been loaded yet.
|
||||
* Useful for loading additional `.lua` modules or static data from a mod,
|
||||
or checking if a mod is enabled.
|
||||
* `minetest.get_modnames()`: returns a list of enabled mods, sorted alphabetically.
|
||||
* Does not include disabled mods, even if they are installed.
|
||||
* `minetest.get_worldpath()`: returns e.g. `"/home/user/.minetest/world"`
|
||||
* Useful for storing custom data
|
||||
* `minetest.is_singleplayer()`
|
||||
@ -4872,6 +4898,9 @@ Environment access
|
||||
* `minetest.get_objects_inside_radius(pos, radius)`: returns a list of
|
||||
ObjectRefs.
|
||||
* `radius`: using an euclidean metric
|
||||
* `minetest.get_objects_in_area(pos1, pos2)`: returns a list of
|
||||
ObjectRefs.
|
||||
* `pos1` and `pos2` are the min and max positions of the area to search.
|
||||
* `minetest.set_timeofday(val)`
|
||||
* `val` is between `0` and `1`; `0` for midnight, `0.5` for midday
|
||||
* `minetest.get_timeofday()`
|
||||
@ -7614,6 +7643,13 @@ Used by `minetest.register_node`.
|
||||
-- intensity: 1.0 = mid range of regular TNT.
|
||||
-- If defined, called when an explosion touches the node, instead of
|
||||
-- removing the node.
|
||||
|
||||
mod_origin = "modname",
|
||||
-- stores which mod actually registered a node
|
||||
-- if it can not find a source, returns "??"
|
||||
-- useful for getting what mod truly registered something
|
||||
-- example: if a node is registered as ":othermodname:nodename",
|
||||
-- nodename will show "othermodname", but mod_orgin will say "modname"
|
||||
}
|
||||
|
||||
Crafting recipes
|
||||
|
@ -43,10 +43,14 @@ core.get_max_supp_proto()
|
||||
core.open_url(url)
|
||||
^ opens the URL in a web browser, returns false on failure.
|
||||
^ Must begin with http:// or https://
|
||||
core.open_dir(path)
|
||||
^ opens the path in the system file browser/explorer, returns false on failure.
|
||||
^ Must be an existing directory.
|
||||
core.get_version() (possible in async calls)
|
||||
^ returns current core version
|
||||
|
||||
|
||||
|
||||
Filesystem
|
||||
----------
|
||||
|
||||
@ -63,6 +67,8 @@ core.copy_dir(source,destination,keep_soure) (possible in async calls)
|
||||
^ destination folder
|
||||
^ keep_source DEFAULT true --> if set to false source is deleted after copying
|
||||
^ returns true/false
|
||||
core.is_dir(path) (possible in async calls)
|
||||
^ returns true if path is a valid dir
|
||||
core.extract_zip(zipfile,destination) [unzip within path required]
|
||||
^ zipfile to extract
|
||||
^ destination folder to extract to
|
||||
@ -207,6 +213,9 @@ Content and Packages
|
||||
Content - an installed mod, modpack, game, or texture pack (txt)
|
||||
Package - content which is downloadable from the content db, may or may not be installed.
|
||||
|
||||
* core.get_user_path() (possible in async calls)
|
||||
* returns path to global user data,
|
||||
the directory that contains user-provided mods, worlds, games, and texture packs.
|
||||
* core.get_modpath() (possible in async calls)
|
||||
* returns path to global modpath
|
||||
* core.get_clientmodpath() (possible in async calls)
|
||||
|
@ -31,6 +31,9 @@ minetest.register_entity("testentities:callback", {
|
||||
on_activate = function(self, staticdata, dtime_s)
|
||||
message("Callback entity: on_activate! pos="..spos(self).."; dtime_s="..dtime_s)
|
||||
end,
|
||||
on_deactivate = function(self)
|
||||
message("Callback entity: on_deactivate! pos="..spos(self))
|
||||
end,
|
||||
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
|
||||
local name = get_object_name(puncher)
|
||||
message(
|
||||
|
@ -94,3 +94,32 @@ minetest.register_entity("testentities:upright_animated", {
|
||||
self.object:set_sprite({x=0, y=0}, 4, 1.0, false)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_entity("testentities:nametag", {
|
||||
initial_properties = {
|
||||
visual = "sprite",
|
||||
textures = { "testentities_sprite.png" },
|
||||
},
|
||||
|
||||
on_activate = function(self, staticdata)
|
||||
if staticdata ~= "" then
|
||||
self.color = minetest.deserialize(staticdata).color
|
||||
else
|
||||
self.color = {
|
||||
r = math.random(0, 255),
|
||||
g = math.random(0, 255),
|
||||
b = math.random(0, 255),
|
||||
}
|
||||
end
|
||||
|
||||
assert(self.color)
|
||||
self.object:set_properties({
|
||||
nametag = tostring(math.random(1000, 10000)),
|
||||
nametag_color = self.color,
|
||||
})
|
||||
end,
|
||||
|
||||
get_staticdata = function(self)
|
||||
return minetest.serialize({ color = self.color })
|
||||
end,
|
||||
})
|
||||
|
@ -22,3 +22,10 @@ minetest.register_craftitem("testfood:bad5", {
|
||||
on_use = minetest.item_eat(-5),
|
||||
})
|
||||
|
||||
minetest.register_craftitem("testfood:replace1", {
|
||||
description = S("Replacing Food (+1)").."\n"..
|
||||
S("Replaced with 'Good Food (+1)' when eaten"),
|
||||
inventory_image = "testfood_replace.png",
|
||||
on_use = minetest.item_eat(1, "testfood:good1"),
|
||||
})
|
||||
|
||||
|
BIN
games/devtest/mods/testfood/textures/testfood_replace.png
Normal file
BIN
games/devtest/mods/testfood/textures/testfood_replace.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 135 B |
@ -1,5 +1,3 @@
|
||||
cmake_minimum_required(VERSION 2.4 FATAL_ERROR)
|
||||
|
||||
project(lua C)
|
||||
|
||||
set(LUA_VERSION_MAJOR 5)
|
||||
@ -15,9 +13,8 @@ set(LIBS)
|
||||
|
||||
if(APPLE)
|
||||
set(DEFAULT_POSIX TRUE)
|
||||
set(DEFAULT_DLOPEN ON)
|
||||
# use this on Mac OS X 10.3-
|
||||
option(LUA_USE_MACOSX "Mac OS X 10.3-" OFF)
|
||||
set(DEFAULT_DLOPEN OFF)
|
||||
set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_USE_MACOSX")
|
||||
elseif(UNIX OR CYGWIN)
|
||||
set(DEFAULT_POSIX TRUE)
|
||||
elseif(WIN32)
|
||||
@ -32,12 +29,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(DEFAULT_DLOPEN ON)
|
||||
endif()
|
||||
|
||||
# For "Mac OS X 10.3-"
|
||||
if(LUA_USE_MACOSX)
|
||||
set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_USE_MACOSX")
|
||||
set(LUA_USE_DLOPEN FALSE)
|
||||
endif(LUA_USE_MACOSX)
|
||||
|
||||
option(LUA_USE_DLOPEN "Enable dlopen support." ${DEFAULT_DLOPEN})
|
||||
mark_as_advanced(LUA_USE_DLOPEN)
|
||||
|
||||
|
@ -129,6 +129,9 @@
|
||||
# type: float min: 0.001
|
||||
# repeat_joystick_button_time = 0.17
|
||||
|
||||
# The deadzone of the joystick
|
||||
# joystick_deadzone = 2048
|
||||
|
||||
# The sensitivity of the joystick axes for moving the
|
||||
# ingame view frustum around.
|
||||
# type: float
|
||||
|
@ -3,9 +3,9 @@ Priority: extra
|
||||
Standards-Version: 3.6.2
|
||||
Package: minetest-staging
|
||||
Version: 0.4.15-DATEPLACEHOLDER
|
||||
Depends: libc6, libcurl3-gnutls, libfreetype6, libirrlicht1.8, LEVELDB_PLACEHOLDER, liblua5.1-0, libluajit-5.1-2, libopenal1, libstdc++6, libvorbisfile3, libx11-6, zlib1g
|
||||
Depends: libc6, libcurl3-gnutls, libfreetype6, libirrlicht1.8, libjsoncpp1, LEVELDB_PLACEHOLDER, liblua5.1-0, libluajit-5.1-2, libopenal1, libsqlite3-0, libstdc++6, libvorbisfile3, libx11-6, zlib1g
|
||||
Maintainer: Loic Blot <loic.blot@unix-experience.fr>
|
||||
Homepage: http://minetest.net/
|
||||
Homepage: https://www.minetest.net/
|
||||
Vcs-Git: https://github.com/minetest/minetest.git
|
||||
Vcs-Browser: https://github.com/minetest/minetest.git
|
||||
Architecture: amd64
|
||||
|
@ -1,5 +1,3 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
project(minetest)
|
||||
|
||||
INCLUDE(CheckIncludeFiles)
|
||||
@ -124,27 +122,6 @@ option(ENABLE_FREETYPE "Enable FreeType2 (TrueType fonts and basic unicode suppo
|
||||
set(USE_FREETYPE FALSE)
|
||||
|
||||
if(ENABLE_FREETYPE)
|
||||
##
|
||||
## Note: FindFreetype.cmake seems to have been fixed in recent versions of
|
||||
## CMake. If issues persist, re-enable this workaround specificially for the
|
||||
## failing platforms.
|
||||
##
|
||||
# if(UNIX)
|
||||
# include(FindPkgConfig)
|
||||
# if(PKG_CONFIG_FOUND)
|
||||
# pkg_check_modules(FREETYPE QUIET freetype2)
|
||||
# if(FREETYPE_FOUND)
|
||||
# SET(FREETYPE_PKGCONFIG_FOUND TRUE)
|
||||
# SET(FREETYPE_LIBRARY ${FREETYPE_LIBRARIES})
|
||||
# # Because CMake is idiotic
|
||||
# string(REPLACE ";" " " FREETYPE_CFLAGS_STR ${FREETYPE_CFLAGS})
|
||||
# string(REPLACE ";" " " FREETYPE_LDFLAGS_STR ${FREETYPE_LDFLAGS})
|
||||
# endif(FREETYPE_FOUND)
|
||||
# endif(PKG_CONFIG_FOUND)
|
||||
# endif(UNIX)
|
||||
# if(NOT FREETYPE_FOUND)
|
||||
# find_package(Freetype)
|
||||
# endif()
|
||||
find_package(Freetype)
|
||||
if(FREETYPE_FOUND)
|
||||
message(STATUS "Freetype enabled.")
|
||||
|
@ -691,10 +691,11 @@ void Camera::drawNametags()
|
||||
core::matrix4 trans = m_cameranode->getProjectionMatrix();
|
||||
trans *= m_cameranode->getViewMatrix();
|
||||
|
||||
for (std::list<Nametag *>::const_iterator
|
||||
i = m_nametags.begin();
|
||||
i != m_nametags.end(); ++i) {
|
||||
Nametag *nametag = *i;
|
||||
gui::IGUIFont *font = g_fontengine->getFont();
|
||||
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
||||
v2u32 screensize = driver->getScreenSize();
|
||||
|
||||
for (const Nametag *nametag : m_nametags) {
|
||||
if (nametag->nametag_color.getAlpha() == 0) {
|
||||
// Enforce hiding nametag,
|
||||
// because if freetype is enabled, a grey
|
||||
@ -707,21 +708,29 @@ void Camera::drawNametags()
|
||||
if (transformed_pos[3] > 0) {
|
||||
std::wstring nametag_colorless =
|
||||
unescape_translate(utf8_to_wide(nametag->nametag_text));
|
||||
core::dimension2d<u32> textsize =
|
||||
g_fontengine->getFont()->getDimension(
|
||||
core::dimension2d<u32> textsize = font->getDimension(
|
||||
nametag_colorless.c_str());
|
||||
f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f :
|
||||
core::reciprocal(transformed_pos[3]);
|
||||
v2u32 screensize = RenderingEngine::get_video_driver()->getScreenSize();
|
||||
v2s32 screen_pos;
|
||||
screen_pos.X = screensize.X *
|
||||
(0.5 * transformed_pos[0] * zDiv + 0.5) - textsize.Width / 2;
|
||||
screen_pos.Y = screensize.Y *
|
||||
(0.5 - transformed_pos[1] * zDiv * 0.5) - textsize.Height / 2;
|
||||
core::rect<s32> size(0, 0, textsize.Width, textsize.Height);
|
||||
g_fontengine->getFont()->draw(
|
||||
core::rect<s32> bg_size(-2, 0, textsize.Width+2, textsize.Height);
|
||||
|
||||
video::SColor textColor = nametag->nametag_color;
|
||||
|
||||
bool darkBackground = textColor.getLuminance() > 186;
|
||||
video::SColor backgroundColor = darkBackground
|
||||
? video::SColor(50, 50, 50, 50)
|
||||
: video::SColor(50, 255, 255, 255);
|
||||
driver->draw2DRectangle(backgroundColor, bg_size + screen_pos);
|
||||
|
||||
font->draw(
|
||||
translate_string(utf8_to_wide(nametag->nametag_text)).c_str(),
|
||||
size + screen_pos, nametag->nametag_color);
|
||||
size + screen_pos, textColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,12 +51,8 @@ public:
|
||||
|
||||
~CAOShaderConstantSetter() override = default;
|
||||
|
||||
void onSetConstants(video::IMaterialRendererServices *services,
|
||||
bool is_highlevel) override
|
||||
void onSetConstants(video::IMaterialRendererServices *services) override
|
||||
{
|
||||
if (!is_highlevel)
|
||||
return;
|
||||
|
||||
// Ambient color
|
||||
video::SColorf emissive_color(m_emissive_color);
|
||||
|
||||
|
@ -290,6 +290,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
*/
|
||||
|
||||
u32 vertex_count = 0;
|
||||
u32 drawcall_count = 0;
|
||||
|
||||
// For limiting number of mesh animations per frame
|
||||
u32 mesh_animate_count = 0;
|
||||
@ -391,6 +392,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
}
|
||||
driver->setMaterial(list.m);
|
||||
|
||||
drawcall_count += list.bufs.size();
|
||||
for (auto &pair : list.bufs) {
|
||||
scene::IMeshBuffer *buf = pair.second;
|
||||
|
||||
@ -411,6 +413,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
}
|
||||
|
||||
g_profiler->avg(prefix + "vertices drawn [#]", vertex_count);
|
||||
g_profiler->avg(prefix + "drawcalls [#]", drawcall_count);
|
||||
}
|
||||
|
||||
static bool getVisibleBrightness(Map *map, const v3f &p0, v3f dir, float step,
|
||||
|
@ -1173,7 +1173,7 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
|
||||
}
|
||||
}
|
||||
|
||||
if (!getParent() && std::fabs(m_prop.automatic_rotate) > 0.001) {
|
||||
if (!getParent() && node && fabs(m_prop.automatic_rotate) > 0.001f) {
|
||||
// This is the child node's rotation. It is only used for automatic_rotate.
|
||||
v3f local_rot = node->getRotation();
|
||||
local_rot.Y = modulo360f(local_rot.Y - dtime * core::RADTODEG *
|
||||
@ -1182,7 +1182,7 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
|
||||
}
|
||||
|
||||
if (!getParent() && m_prop.automatic_face_movement_dir &&
|
||||
(fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)) {
|
||||
(fabs(m_velocity.Z) > 0.001f || fabs(m_velocity.X) > 0.001f)) {
|
||||
float target_yaw = atan2(m_velocity.Z, m_velocity.X) * 180 / M_PI
|
||||
+ m_prop.automatic_face_movement_dir_offset;
|
||||
float max_rotation_per_sec =
|
||||
|
@ -519,7 +519,7 @@ bool Game::createClient(const GameStartData &start_data)
|
||||
return false;
|
||||
}
|
||||
|
||||
GameGlobalShaderConstantSetterFactory *scsf = new GameGlobalShaderConstantSetterFactory(
|
||||
auto *scsf = new GameGlobalShaderConstantSetterFactory(
|
||||
&m_flags.force_fog_off, &runData.fog_range, client);
|
||||
shader_src->addShaderConstantSetterFactory(scsf);
|
||||
|
||||
@ -529,20 +529,14 @@ bool Game::createClient(const GameStartData &start_data)
|
||||
/* Camera
|
||||
*/
|
||||
camera = new Camera(*draw_control, client);
|
||||
if (!camera || !camera->successfullyCreated(*error_message))
|
||||
if (!camera->successfullyCreated(*error_message))
|
||||
return false;
|
||||
client->setCamera(camera);
|
||||
|
||||
/* Clouds
|
||||
*/
|
||||
if (m_cache_enable_clouds) {
|
||||
if (m_cache_enable_clouds)
|
||||
clouds = new Clouds(smgr, -1, time(0));
|
||||
if (!clouds) {
|
||||
*error_message = "Memory allocation error (clouds)";
|
||||
errorstream << *error_message << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skybox
|
||||
*/
|
||||
@ -550,12 +544,6 @@ bool Game::createClient(const GameStartData &start_data)
|
||||
scsf->setSky(sky);
|
||||
skybox = NULL; // This is used/set later on in the main run loop
|
||||
|
||||
if (!sky) {
|
||||
*error_message = "Memory allocation error sky";
|
||||
errorstream << *error_message << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Pre-calculated values
|
||||
*/
|
||||
video::ITexture *t = texture_src->getTexture("crack_anylength.png");
|
||||
@ -585,12 +573,6 @@ bool Game::createClient(const GameStartData &start_data)
|
||||
|
||||
hud = new Hud(guienv, client, player, &player->inventory);
|
||||
|
||||
if (!hud) {
|
||||
*error_message = "Memory error: could not create HUD";
|
||||
errorstream << *error_message << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
mapper = client->getMinimap();
|
||||
|
||||
if (mapper && client->modsLoaded())
|
||||
@ -682,9 +664,6 @@ bool Game::connectToServer(const GameStartData &start_data,
|
||||
itemdef_manager, nodedef_manager, sound, eventmgr,
|
||||
connect_address.isIPv6(), m_game_ui.get());
|
||||
|
||||
if (!client)
|
||||
return false;
|
||||
|
||||
client->m_simple_singleplayer_mode = simple_singleplayer_mode;
|
||||
|
||||
infostream << "Connecting to server at ";
|
||||
@ -2415,8 +2394,8 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug)
|
||||
wasKeyDown(KeyType::DIG);
|
||||
wasKeyDown(KeyType::PLACE);
|
||||
|
||||
input->joystick.clearWasKeyDown(KeyType::DIG);
|
||||
input->joystick.clearWasKeyDown(KeyType::PLACE);
|
||||
input->joystick.clearWasKeyPressed(KeyType::DIG);
|
||||
input->joystick.clearWasKeyPressed(KeyType::PLACE);
|
||||
|
||||
input->joystick.clearWasKeyReleased(KeyType::DIG);
|
||||
input->joystick.clearWasKeyReleased(KeyType::PLACE);
|
||||
|
@ -203,7 +203,7 @@ struct LocalFormspecHandler : public TextDest
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_client && m_client->modsLoaded())
|
||||
if (m_client->modsLoaded())
|
||||
m_client->getScript()->on_formspec_input(m_formname, fields);
|
||||
}
|
||||
|
||||
@ -492,12 +492,8 @@ public:
|
||||
g_settings->deregisterChangedCallback("enable_fog", settingsCallback, this);
|
||||
}
|
||||
|
||||
virtual void onSetConstants(video::IMaterialRendererServices *services,
|
||||
bool is_highlevel)
|
||||
void onSetConstants(video::IMaterialRendererServices *services) override
|
||||
{
|
||||
if (!is_highlevel)
|
||||
return;
|
||||
|
||||
// Background color
|
||||
video::SColor bgcolor = m_sky->getBgColor();
|
||||
video::SColorf bgcolorf(bgcolor);
|
||||
@ -604,7 +600,7 @@ public:
|
||||
|
||||
virtual IShaderConstantSetter* create()
|
||||
{
|
||||
GameGlobalShaderConstantSetter *scs = new GameGlobalShaderConstantSetter(
|
||||
auto *scs = new GameGlobalShaderConstantSetter(
|
||||
m_sky, m_force_fog_off, m_fog_range, m_client);
|
||||
if (!m_sky)
|
||||
created_nosky.push_back(scs);
|
||||
@ -643,7 +639,6 @@ struct GameRunData {
|
||||
bool btn_down_for_dig;
|
||||
bool dig_instantly;
|
||||
bool digging_blocked;
|
||||
bool left_punch;
|
||||
bool reset_jump_timer;
|
||||
float nodig_delay_timer;
|
||||
float dig_time;
|
||||
|
@ -100,7 +100,7 @@ Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player,
|
||||
if (g_settings->getBool("enable_shaders")) {
|
||||
IShaderSource *shdrsrc = client->getShaderSource();
|
||||
u16 shader_id = shdrsrc->getShader(
|
||||
m_mode == HIGHLIGHT_HALO ? "selection_shader" : "default_shader", 1, 1);
|
||||
m_mode == HIGHLIGHT_HALO ? "selection_shader" : "default_shader", TILE_MATERIAL_ALPHA);
|
||||
m_selection_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material;
|
||||
} else {
|
||||
m_selection_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
@ -1055,9 +1055,9 @@ void drawItemStack(
|
||||
|
||||
if (def.type == ITEM_TOOL && item.wear != 0) {
|
||||
// Draw a progressbar
|
||||
float barheight = rect.getHeight() / 16;
|
||||
float barpad_x = rect.getWidth() / 16;
|
||||
float barpad_y = rect.getHeight() / 16;
|
||||
float barheight = static_cast<float>(rect.getHeight()) / 16;
|
||||
float barpad_x = static_cast<float>(rect.getWidth()) / 16;
|
||||
float barpad_y = static_cast<float>(rect.getHeight()) / 16;
|
||||
|
||||
core::rect<s32> progressrect(
|
||||
rect.UpperLeftCorner.X + barpad_x,
|
||||
|
@ -290,7 +290,7 @@ public:
|
||||
}
|
||||
virtual bool wasKeyPressed(GameKeyType k)
|
||||
{
|
||||
return m_receiver->WasKeyPressed(keycache.key[k]) || joystick.wasKeyReleased(k);
|
||||
return m_receiver->WasKeyPressed(keycache.key[k]) || joystick.wasKeyPressed(k);
|
||||
}
|
||||
virtual bool wasKeyReleased(GameKeyType k)
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ bool JoystickAxisCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const
|
||||
{
|
||||
s16 ax_val = ev.Axis[axis_to_compare];
|
||||
|
||||
return (ax_val * direction < 0) && (thresh * direction > ax_val * direction);
|
||||
return (ax_val * direction < -thresh);
|
||||
}
|
||||
|
||||
// spares many characters
|
||||
@ -48,7 +48,7 @@ JoystickLayout create_default_layout()
|
||||
{
|
||||
JoystickLayout jlo;
|
||||
|
||||
jlo.axes_dead_border = 1024;
|
||||
jlo.axes_deadzone = g_settings->getU16("joystick_deadzone");
|
||||
|
||||
const JoystickAxisLayout axes[JA_COUNT] = {
|
||||
{0, 1}, // JA_SIDEWARD_MOVE
|
||||
@ -93,14 +93,14 @@ JoystickLayout create_default_layout()
|
||||
// Now about the buttons simulated by the axes
|
||||
|
||||
// Movement buttons, important for vessels
|
||||
JLO_A_PB(KeyType::FORWARD, 1, 1, 1024);
|
||||
JLO_A_PB(KeyType::BACKWARD, 1, -1, 1024);
|
||||
JLO_A_PB(KeyType::LEFT, 0, 1, 1024);
|
||||
JLO_A_PB(KeyType::RIGHT, 0, -1, 1024);
|
||||
JLO_A_PB(KeyType::FORWARD, 1, 1, jlo.axes_deadzone);
|
||||
JLO_A_PB(KeyType::BACKWARD, 1, -1, jlo.axes_deadzone);
|
||||
JLO_A_PB(KeyType::LEFT, 0, 1, jlo.axes_deadzone);
|
||||
JLO_A_PB(KeyType::RIGHT, 0, -1, jlo.axes_deadzone);
|
||||
|
||||
// Scroll buttons
|
||||
JLO_A_PB(KeyType::HOTBAR_PREV, 2, -1, 1024);
|
||||
JLO_A_PB(KeyType::HOTBAR_NEXT, 5, -1, 1024);
|
||||
JLO_A_PB(KeyType::HOTBAR_PREV, 2, -1, jlo.axes_deadzone);
|
||||
JLO_A_PB(KeyType::HOTBAR_NEXT, 5, -1, jlo.axes_deadzone);
|
||||
|
||||
return jlo;
|
||||
}
|
||||
@ -109,7 +109,7 @@ JoystickLayout create_xbox_layout()
|
||||
{
|
||||
JoystickLayout jlo;
|
||||
|
||||
jlo.axes_dead_border = 7000;
|
||||
jlo.axes_deadzone = 7000;
|
||||
|
||||
const JoystickAxisLayout axes[JA_COUNT] = {
|
||||
{0, 1}, // JA_SIDEWARD_MOVE
|
||||
@ -146,10 +146,10 @@ JoystickLayout create_xbox_layout()
|
||||
JLO_B_PB(KeyType::FREEMOVE, 1 << 16, 1 << 16); // down
|
||||
|
||||
// Movement buttons, important for vessels
|
||||
JLO_A_PB(KeyType::FORWARD, 1, 1, 1024);
|
||||
JLO_A_PB(KeyType::BACKWARD, 1, -1, 1024);
|
||||
JLO_A_PB(KeyType::LEFT, 0, 1, 1024);
|
||||
JLO_A_PB(KeyType::RIGHT, 0, -1, 1024);
|
||||
JLO_A_PB(KeyType::FORWARD, 1, 1, jlo.axes_deadzone);
|
||||
JLO_A_PB(KeyType::BACKWARD, 1, -1, jlo.axes_deadzone);
|
||||
JLO_A_PB(KeyType::LEFT, 0, 1, jlo.axes_deadzone);
|
||||
JLO_A_PB(KeyType::RIGHT, 0, -1, jlo.axes_deadzone);
|
||||
|
||||
return jlo;
|
||||
}
|
||||
@ -219,16 +219,19 @@ bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev)
|
||||
|
||||
for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) {
|
||||
if (keys_pressed[i]) {
|
||||
if (!m_past_pressed_keys[i] &&
|
||||
if (!m_past_keys_pressed[i] &&
|
||||
m_past_pressed_time[i] < m_internal_time - doubling_dtime) {
|
||||
m_past_pressed_keys[i] = true;
|
||||
m_past_keys_pressed[i] = true;
|
||||
m_past_pressed_time[i] = m_internal_time;
|
||||
}
|
||||
} else if (m_pressed_keys[i]) {
|
||||
m_past_released_keys[i] = true;
|
||||
} else if (m_keys_down[i]) {
|
||||
m_keys_released[i] = true;
|
||||
}
|
||||
|
||||
m_pressed_keys[i] = keys_pressed[i];
|
||||
if (keys_pressed[i] && !(m_keys_down[i]))
|
||||
m_keys_pressed[i] = true;
|
||||
|
||||
m_keys_down[i] = keys_pressed[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < JA_COUNT; i++) {
|
||||
@ -236,23 +239,22 @@ bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev)
|
||||
m_axes_vals[i] = ax_la.invert * ev.Axis[ax_la.axis_id];
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JoystickController::clear()
|
||||
{
|
||||
m_pressed_keys.reset();
|
||||
m_past_pressed_keys.reset();
|
||||
m_past_released_keys.reset();
|
||||
m_keys_pressed.reset();
|
||||
m_keys_down.reset();
|
||||
m_past_keys_pressed.reset();
|
||||
m_keys_released.reset();
|
||||
memset(m_axes_vals, 0, sizeof(m_axes_vals));
|
||||
}
|
||||
|
||||
s16 JoystickController::getAxisWithoutDead(JoystickAxis axis)
|
||||
{
|
||||
s16 v = m_axes_vals[axis];
|
||||
if (((v > 0) && (v < m_layout.axes_dead_border)) ||
|
||||
((v < 0) && (v > -m_layout.axes_dead_border)))
|
||||
if (abs(v) < m_layout.axes_deadzone)
|
||||
return 0;
|
||||
return v;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ struct JoystickLayout {
|
||||
std::vector<JoystickButtonCmb> button_keys;
|
||||
std::vector<JoystickAxisCmb> axis_keys;
|
||||
JoystickAxisLayout axes[JA_COUNT];
|
||||
s16 axes_dead_border;
|
||||
s16 axes_deadzone;
|
||||
};
|
||||
|
||||
class JoystickController {
|
||||
@ -111,37 +111,32 @@ public:
|
||||
|
||||
bool wasKeyDown(GameKeyType b)
|
||||
{
|
||||
bool r = m_past_pressed_keys[b];
|
||||
m_past_pressed_keys[b] = false;
|
||||
bool r = m_past_keys_pressed[b];
|
||||
m_past_keys_pressed[b] = false;
|
||||
return r;
|
||||
}
|
||||
bool getWasKeyDown(GameKeyType b)
|
||||
{
|
||||
return m_past_pressed_keys[b];
|
||||
}
|
||||
void clearWasKeyDown(GameKeyType b)
|
||||
{
|
||||
m_past_pressed_keys[b] = false;
|
||||
}
|
||||
|
||||
bool wasKeyReleased(GameKeyType b)
|
||||
{
|
||||
bool r = m_past_released_keys[b];
|
||||
m_past_released_keys[b] = false;
|
||||
return r;
|
||||
}
|
||||
bool getWasKeyReleased(GameKeyType b)
|
||||
{
|
||||
return m_past_pressed_keys[b];
|
||||
return m_keys_released[b];
|
||||
}
|
||||
void clearWasKeyReleased(GameKeyType b)
|
||||
{
|
||||
m_past_pressed_keys[b] = false;
|
||||
m_keys_released[b] = false;
|
||||
}
|
||||
|
||||
bool wasKeyPressed(GameKeyType b)
|
||||
{
|
||||
return m_keys_pressed[b];
|
||||
}
|
||||
void clearWasKeyPressed(GameKeyType b)
|
||||
{
|
||||
m_keys_pressed[b] = false;
|
||||
}
|
||||
|
||||
bool isKeyDown(GameKeyType b)
|
||||
{
|
||||
return m_pressed_keys[b];
|
||||
return m_keys_down[b];
|
||||
}
|
||||
|
||||
s16 getAxis(JoystickAxis axis)
|
||||
@ -162,12 +157,13 @@ private:
|
||||
|
||||
u8 m_joystick_id = 0;
|
||||
|
||||
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_pressed_keys;
|
||||
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_keys_down;
|
||||
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_keys_pressed;
|
||||
|
||||
f32 m_internal_time;
|
||||
|
||||
f32 m_past_pressed_time[KeyType::INTERNAL_ENUM_COUNT];
|
||||
|
||||
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_past_pressed_keys;
|
||||
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_past_released_keys;
|
||||
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_past_keys_pressed;
|
||||
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_keys_released;
|
||||
};
|
||||
|
@ -1269,13 +1269,13 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
|
||||
MapBlockMesh::~MapBlockMesh()
|
||||
{
|
||||
for (scene::IMesh *m : m_mesh) {
|
||||
if (m_enable_vbo && m)
|
||||
if (m_enable_vbo) {
|
||||
for (u32 i = 0; i < m->getMeshBufferCount(); i++) {
|
||||
scene::IMeshBuffer *buf = m->getMeshBuffer(i);
|
||||
RenderingEngine::get_video_driver()->removeHardwareBuffer(buf);
|
||||
}
|
||||
}
|
||||
m->drop();
|
||||
m = NULL;
|
||||
}
|
||||
delete m_minimap_mapblock;
|
||||
}
|
||||
|
@ -612,7 +612,7 @@ void Minimap::drawMinimap(core::rect<s32> rect) {
|
||||
material.TextureLayer[1].Texture = data->heightmap_texture;
|
||||
|
||||
if (m_enable_shaders && data->mode.type == MINIMAP_TYPE_SURFACE) {
|
||||
u16 sid = m_shdrsrc->getShader("minimap_shader", 1, 1);
|
||||
u16 sid = m_shdrsrc->getShader("minimap_shader", TILE_MATERIAL_ALPHA);
|
||||
material.MaterialType = m_shdrsrc->getShaderInfo(sid).material;
|
||||
} else {
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
|
@ -36,7 +36,7 @@ void RenderingCoreInterlaced::initMaterial()
|
||||
mat.UseMipMaps = false;
|
||||
mat.ZBuffer = false;
|
||||
mat.ZWriteEnable = false;
|
||||
u32 shader = s->getShader("3d_interlaced_merge", TILE_MATERIAL_BASIC, 0);
|
||||
u32 shader = s->getShader("3d_interlaced_merge", TILE_MATERIAL_BASIC);
|
||||
mat.MaterialType = s->getShaderInfo(shader).material;
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
mat.TextureLayer[k].AnisotropicFilter = false;
|
||||
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <iterator>
|
||||
#include "shader.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "irr_ptr.h"
|
||||
#include "debug.h"
|
||||
#include "filesys.h"
|
||||
#include "util/container.h"
|
||||
@ -189,19 +190,14 @@ private:
|
||||
|
||||
class ShaderCallback : public video::IShaderConstantSetCallBack
|
||||
{
|
||||
std::vector<IShaderConstantSetter*> m_setters;
|
||||
std::vector<std::unique_ptr<IShaderConstantSetter>> m_setters;
|
||||
|
||||
public:
|
||||
ShaderCallback(const std::vector<IShaderConstantSetterFactory *> &factories)
|
||||
template <typename Factories>
|
||||
ShaderCallback(const Factories &factories)
|
||||
{
|
||||
for (IShaderConstantSetterFactory *factory : factories)
|
||||
m_setters.push_back(factory->create());
|
||||
}
|
||||
|
||||
~ShaderCallback()
|
||||
{
|
||||
for (IShaderConstantSetter *setter : m_setters)
|
||||
delete setter;
|
||||
for (auto &&factory : factories)
|
||||
m_setters.push_back(std::unique_ptr<IShaderConstantSetter>(factory->create()));
|
||||
}
|
||||
|
||||
virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData) override
|
||||
@ -209,15 +205,13 @@ public:
|
||||
video::IVideoDriver *driver = services->getVideoDriver();
|
||||
sanity_check(driver != NULL);
|
||||
|
||||
bool is_highlevel = userData;
|
||||
|
||||
for (IShaderConstantSetter *setter : m_setters)
|
||||
setter->onSetConstants(services, is_highlevel);
|
||||
for (auto &&setter : m_setters)
|
||||
setter->onSetConstants(services);
|
||||
}
|
||||
|
||||
virtual void OnSetMaterial(const video::SMaterial& material) override
|
||||
{
|
||||
for (IShaderConstantSetter *setter : m_setters)
|
||||
for (auto &&setter : m_setters)
|
||||
setter->onSetMaterial(material);
|
||||
}
|
||||
};
|
||||
@ -252,47 +246,39 @@ public:
|
||||
{}
|
||||
~MainShaderConstantSetter() = default;
|
||||
|
||||
virtual void onSetConstants(video::IMaterialRendererServices *services,
|
||||
bool is_highlevel)
|
||||
virtual void onSetConstants(video::IMaterialRendererServices *services) override
|
||||
{
|
||||
video::IVideoDriver *driver = services->getVideoDriver();
|
||||
sanity_check(driver);
|
||||
|
||||
// Set world matrix
|
||||
core::matrix4 world = driver->getTransform(video::ETS_WORLD);
|
||||
if (is_highlevel)
|
||||
m_world.set(*reinterpret_cast<float(*)[16]>(world.pointer()), services);
|
||||
else
|
||||
services->setVertexShaderConstant(world.pointer(), 4, 4);
|
||||
m_world.set(*reinterpret_cast<float(*)[16]>(world.pointer()), services);
|
||||
|
||||
// Set clip matrix
|
||||
core::matrix4 worldView;
|
||||
worldView = driver->getTransform(video::ETS_VIEW);
|
||||
worldView *= world;
|
||||
|
||||
core::matrix4 worldViewProj;
|
||||
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
|
||||
worldViewProj *= worldView;
|
||||
if (is_highlevel)
|
||||
m_world_view_proj.set(*reinterpret_cast<float(*)[16]>(worldViewProj.pointer()), services);
|
||||
else
|
||||
services->setVertexShaderConstant(worldViewProj.pointer(), 0, 4);
|
||||
m_world_view_proj.set(*reinterpret_cast<float(*)[16]>(worldViewProj.pointer()), services);
|
||||
|
||||
#if ENABLE_GLES
|
||||
if (is_highlevel) {
|
||||
core::matrix4 texture = driver->getTransform(video::ETS_TEXTURE_0);
|
||||
m_world_view.set(*reinterpret_cast<float(*)[16]>(worldView.pointer()), services);
|
||||
m_texture.set(*reinterpret_cast<float(*)[16]>(texture.pointer()), services);
|
||||
core::matrix4 texture = driver->getTransform(video::ETS_TEXTURE_0);
|
||||
m_world_view.set(*reinterpret_cast<float(*)[16]>(worldView.pointer()), services);
|
||||
m_texture.set(*reinterpret_cast<float(*)[16]>(texture.pointer()), services);
|
||||
|
||||
core::matrix4 normal;
|
||||
worldView.getTransposed(normal);
|
||||
sanity_check(normal.makeInverse());
|
||||
float m[9] = {
|
||||
normal[0], normal[1], normal[2],
|
||||
normal[4], normal[5], normal[6],
|
||||
normal[8], normal[9], normal[10],
|
||||
};
|
||||
m_normal.set(m, services);
|
||||
}
|
||||
core::matrix4 normal;
|
||||
worldView.getTransposed(normal);
|
||||
sanity_check(normal.makeInverse());
|
||||
float m[9] = {
|
||||
normal[0], normal[1], normal[2],
|
||||
normal[4], normal[5], normal[6],
|
||||
normal[8], normal[9], normal[10],
|
||||
};
|
||||
m_normal.set(m, services);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@ -314,7 +300,6 @@ class ShaderSource : public IWritableShaderSource
|
||||
{
|
||||
public:
|
||||
ShaderSource();
|
||||
~ShaderSource();
|
||||
|
||||
/*
|
||||
- If shader material specified by name is found from cache,
|
||||
@ -324,7 +309,7 @@ public:
|
||||
The id 0 points to a null shader. Its material is EMT_SOLID.
|
||||
*/
|
||||
u32 getShaderIdDirect(const std::string &name,
|
||||
const u8 material_type, const u8 drawtype);
|
||||
MaterialType material_type, NodeDrawType drawtype) override;
|
||||
|
||||
/*
|
||||
If shader specified by the name pointed by the id doesn't
|
||||
@ -336,26 +321,26 @@ public:
|
||||
*/
|
||||
|
||||
u32 getShader(const std::string &name,
|
||||
const u8 material_type, const u8 drawtype);
|
||||
MaterialType material_type, NodeDrawType drawtype) override;
|
||||
|
||||
ShaderInfo getShaderInfo(u32 id);
|
||||
ShaderInfo getShaderInfo(u32 id) override;
|
||||
|
||||
// Processes queued shader requests from other threads.
|
||||
// Shall be called from the main thread.
|
||||
void processQueue();
|
||||
void processQueue() override;
|
||||
|
||||
// Insert a shader program into the cache without touching the
|
||||
// filesystem. Shall be called from the main thread.
|
||||
void insertSourceShader(const std::string &name_of_shader,
|
||||
const std::string &filename, const std::string &program);
|
||||
const std::string &filename, const std::string &program) override;
|
||||
|
||||
// Rebuild shaders from the current set of source shaders
|
||||
// Shall be called from the main thread.
|
||||
void rebuildShaders();
|
||||
void rebuildShaders() override;
|
||||
|
||||
void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter)
|
||||
void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter) override
|
||||
{
|
||||
m_setter_factories.push_back(setter);
|
||||
m_setter_factories.push_back(std::unique_ptr<IShaderConstantSetterFactory>(setter));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -377,10 +362,11 @@ private:
|
||||
RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
|
||||
|
||||
// Global constant setter factories
|
||||
std::vector<IShaderConstantSetterFactory *> m_setter_factories;
|
||||
std::vector<std::unique_ptr<IShaderConstantSetterFactory>> m_setter_factories;
|
||||
|
||||
// Shader callbacks
|
||||
std::vector<ShaderCallback *> m_callbacks;
|
||||
// Generate shader given the shader name.
|
||||
ShaderInfo generateShader(const std::string &name,
|
||||
MaterialType material_type, NodeDrawType drawtype);
|
||||
};
|
||||
|
||||
IWritableShaderSource *createShaderSource()
|
||||
@ -388,22 +374,6 @@ IWritableShaderSource *createShaderSource()
|
||||
return new ShaderSource();
|
||||
}
|
||||
|
||||
/*
|
||||
Generate shader given the shader name.
|
||||
*/
|
||||
ShaderInfo generate_shader(const std::string &name,
|
||||
u8 material_type, u8 drawtype, std::vector<ShaderCallback *> &callbacks,
|
||||
const std::vector<IShaderConstantSetterFactory *> &setter_factories,
|
||||
SourceShaderCache *sourcecache);
|
||||
|
||||
/*
|
||||
Load shader programs
|
||||
*/
|
||||
void load_shaders(const std::string &name, SourceShaderCache *sourcecache,
|
||||
video::E_DRIVER_TYPE drivertype, bool enable_shaders,
|
||||
std::string &vertex_program, std::string &pixel_program,
|
||||
std::string &geometry_program, bool &is_highlevel);
|
||||
|
||||
ShaderSource::ShaderSource()
|
||||
{
|
||||
m_main_thread = std::this_thread::get_id();
|
||||
@ -415,18 +385,8 @@ ShaderSource::ShaderSource()
|
||||
addShaderConstantSetterFactory(new MainShaderConstantSetterFactory());
|
||||
}
|
||||
|
||||
ShaderSource::~ShaderSource()
|
||||
{
|
||||
for (ShaderCallback *callback : m_callbacks) {
|
||||
delete callback;
|
||||
}
|
||||
for (IShaderConstantSetterFactory *setter_factorie : m_setter_factories) {
|
||||
delete setter_factorie;
|
||||
}
|
||||
}
|
||||
|
||||
u32 ShaderSource::getShader(const std::string &name,
|
||||
const u8 material_type, const u8 drawtype)
|
||||
MaterialType material_type, NodeDrawType drawtype)
|
||||
{
|
||||
/*
|
||||
Get shader
|
||||
@ -468,7 +428,7 @@ u32 ShaderSource::getShader(const std::string &name,
|
||||
This method generates all the shaders
|
||||
*/
|
||||
u32 ShaderSource::getShaderIdDirect(const std::string &name,
|
||||
const u8 material_type, const u8 drawtype)
|
||||
MaterialType material_type, NodeDrawType drawtype)
|
||||
{
|
||||
//infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl;
|
||||
|
||||
@ -495,8 +455,7 @@ u32 ShaderSource::getShaderIdDirect(const std::string &name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
ShaderInfo info = generate_shader(name, material_type, drawtype,
|
||||
m_callbacks, m_setter_factories, &m_sourcecache);
|
||||
ShaderInfo info = generateShader(name, material_type, drawtype);
|
||||
|
||||
/*
|
||||
Add shader to caches (add dummy shaders too)
|
||||
@ -560,18 +519,14 @@ void ShaderSource::rebuildShaders()
|
||||
for (ShaderInfo &i : m_shaderinfo_cache) {
|
||||
ShaderInfo *info = &i;
|
||||
if (!info->name.empty()) {
|
||||
*info = generate_shader(info->name, info->material_type,
|
||||
info->drawtype, m_callbacks,
|
||||
m_setter_factories, &m_sourcecache);
|
||||
*info = generateShader(info->name, info->material_type, info->drawtype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtype,
|
||||
std::vector<ShaderCallback *> &callbacks,
|
||||
const std::vector<IShaderConstantSetterFactory *> &setter_factories,
|
||||
SourceShaderCache *sourcecache)
|
||||
ShaderInfo ShaderSource::generateShader(const std::string &name,
|
||||
MaterialType material_type, NodeDrawType drawtype)
|
||||
{
|
||||
ShaderInfo shaderinfo;
|
||||
shaderinfo.name = name;
|
||||
@ -604,64 +559,27 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
|
||||
return shaderinfo;
|
||||
|
||||
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_ARB_GLSL)) {
|
||||
errorstream << "Shaders are enabled but GLSL is not supported by the driver\n";
|
||||
return shaderinfo;
|
||||
}
|
||||
video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
|
||||
if(!gpu){
|
||||
errorstream<<"generate_shader(): "
|
||||
"failed to generate \""<<name<<"\", "
|
||||
"GPU programming not supported."
|
||||
<<std::endl;
|
||||
return shaderinfo;
|
||||
}
|
||||
|
||||
// Choose shader language depending on driver type and settings
|
||||
// Then load shaders
|
||||
std::string vertex_program;
|
||||
std::string pixel_program;
|
||||
std::string geometry_program;
|
||||
bool is_highlevel;
|
||||
load_shaders(name, sourcecache, driver->getDriverType(),
|
||||
enable_shaders, vertex_program, pixel_program,
|
||||
geometry_program, is_highlevel);
|
||||
// Check hardware/driver support
|
||||
if (!vertex_program.empty() &&
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
|
||||
!driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
|
||||
infostream<<"generate_shader(): vertex shaders disabled "
|
||||
"because of missing driver/hardware support."
|
||||
<<std::endl;
|
||||
vertex_program = "";
|
||||
}
|
||||
if (!pixel_program.empty() &&
|
||||
!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
|
||||
!driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
|
||||
infostream<<"generate_shader(): pixel shaders disabled "
|
||||
"because of missing driver/hardware support."
|
||||
<<std::endl;
|
||||
pixel_program = "";
|
||||
}
|
||||
if (!geometry_program.empty() &&
|
||||
!driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
|
||||
infostream<<"generate_shader(): geometry shaders disabled "
|
||||
"because of missing driver/hardware support."
|
||||
<<std::endl;
|
||||
geometry_program = "";
|
||||
}
|
||||
|
||||
// If no shaders are used, don't make a separate material type
|
||||
if (vertex_program.empty() && pixel_program.empty() && geometry_program.empty())
|
||||
return shaderinfo;
|
||||
|
||||
// Create shaders header
|
||||
bool use_gles = false;
|
||||
#if ENABLE_GLES
|
||||
use_gles = driver->getDriverType() == video::EDT_OGLES2;
|
||||
#endif
|
||||
std::string shaders_header, vertex_header, pixel_header; // geometry shaders aren’t supported in GLES<3
|
||||
std::stringstream shaders_header;
|
||||
shaders_header
|
||||
<< std::noboolalpha
|
||||
<< std::showpoint // for GLSL ES
|
||||
;
|
||||
std::string vertex_header, fragment_header, geometry_header;
|
||||
if (use_gles) {
|
||||
shaders_header =
|
||||
"#version 100\n"
|
||||
;
|
||||
shaders_header << R"(
|
||||
#version 100
|
||||
)";
|
||||
vertex_header = R"(
|
||||
uniform highp mat4 mWorldView;
|
||||
uniform highp mat4 mWorldViewProj;
|
||||
@ -675,11 +593,11 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
|
||||
attribute mediump vec4 inVertexTangent;
|
||||
attribute mediump vec4 inVertexBinormal;
|
||||
)";
|
||||
pixel_header = R"(
|
||||
fragment_header = R"(
|
||||
precision mediump float;
|
||||
)";
|
||||
} else {
|
||||
shaders_header = R"(
|
||||
shaders_header << R"(
|
||||
#version 120
|
||||
#define lowp
|
||||
#define mediump
|
||||
@ -708,224 +626,97 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
|
||||
use_discard = true;
|
||||
#endif
|
||||
if (use_discard && shaderinfo.base_material != video::EMT_SOLID)
|
||||
shaders_header += "#define USE_DISCARD\n";
|
||||
shaders_header << "#define USE_DISCARD 1\n";
|
||||
|
||||
static const char* drawTypes[] = {
|
||||
"NDT_NORMAL",
|
||||
"NDT_AIRLIKE",
|
||||
"NDT_LIQUID",
|
||||
"NDT_FLOWINGLIQUID",
|
||||
"NDT_GLASSLIKE",
|
||||
"NDT_ALLFACES",
|
||||
"NDT_ALLFACES_OPTIONAL",
|
||||
"NDT_TORCHLIKE",
|
||||
"NDT_SIGNLIKE",
|
||||
"NDT_PLANTLIKE",
|
||||
"NDT_FENCELIKE",
|
||||
"NDT_RAILLIKE",
|
||||
"NDT_NODEBOX",
|
||||
"NDT_GLASSLIKE_FRAMED",
|
||||
"NDT_FIRELIKE",
|
||||
"NDT_GLASSLIKE_FRAMED_OPTIONAL",
|
||||
"NDT_PLANTLIKE_ROOTED",
|
||||
};
|
||||
#define PROVIDE(constant) shaders_header << "#define " #constant " " << (int)constant << "\n"
|
||||
|
||||
for (int i = 0; i < 14; i++){
|
||||
shaders_header += "#define ";
|
||||
shaders_header += drawTypes[i];
|
||||
shaders_header += " ";
|
||||
shaders_header += itos(i);
|
||||
shaders_header += "\n";
|
||||
PROVIDE(NDT_NORMAL);
|
||||
PROVIDE(NDT_AIRLIKE);
|
||||
PROVIDE(NDT_LIQUID);
|
||||
PROVIDE(NDT_FLOWINGLIQUID);
|
||||
PROVIDE(NDT_GLASSLIKE);
|
||||
PROVIDE(NDT_ALLFACES);
|
||||
PROVIDE(NDT_ALLFACES_OPTIONAL);
|
||||
PROVIDE(NDT_TORCHLIKE);
|
||||
PROVIDE(NDT_SIGNLIKE);
|
||||
PROVIDE(NDT_PLANTLIKE);
|
||||
PROVIDE(NDT_FENCELIKE);
|
||||
PROVIDE(NDT_RAILLIKE);
|
||||
PROVIDE(NDT_NODEBOX);
|
||||
PROVIDE(NDT_GLASSLIKE_FRAMED);
|
||||
PROVIDE(NDT_FIRELIKE);
|
||||
PROVIDE(NDT_GLASSLIKE_FRAMED_OPTIONAL);
|
||||
PROVIDE(NDT_PLANTLIKE_ROOTED);
|
||||
|
||||
PROVIDE(TILE_MATERIAL_BASIC);
|
||||
PROVIDE(TILE_MATERIAL_ALPHA);
|
||||
PROVIDE(TILE_MATERIAL_LIQUID_TRANSPARENT);
|
||||
PROVIDE(TILE_MATERIAL_LIQUID_OPAQUE);
|
||||
PROVIDE(TILE_MATERIAL_WAVING_LEAVES);
|
||||
PROVIDE(TILE_MATERIAL_WAVING_PLANTS);
|
||||
PROVIDE(TILE_MATERIAL_OPAQUE);
|
||||
PROVIDE(TILE_MATERIAL_WAVING_LIQUID_BASIC);
|
||||
PROVIDE(TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT);
|
||||
PROVIDE(TILE_MATERIAL_WAVING_LIQUID_OPAQUE);
|
||||
PROVIDE(TILE_MATERIAL_PLAIN);
|
||||
PROVIDE(TILE_MATERIAL_PLAIN_ALPHA);
|
||||
|
||||
#undef PROVIDE
|
||||
|
||||
shaders_header << "#define MATERIAL_TYPE " << (int)material_type << "\n";
|
||||
shaders_header << "#define DRAW_TYPE " << (int)drawtype << "\n";
|
||||
|
||||
bool enable_waving_water = g_settings->getBool("enable_waving_water");
|
||||
shaders_header << "#define ENABLE_WAVING_WATER " << enable_waving_water << "\n";
|
||||
if (enable_waving_water) {
|
||||
shaders_header << "#define WATER_WAVE_HEIGHT " << g_settings->getFloat("water_wave_height") << "\n";
|
||||
shaders_header << "#define WATER_WAVE_LENGTH " << g_settings->getFloat("water_wave_length") << "\n";
|
||||
shaders_header << "#define WATER_WAVE_SPEED " << g_settings->getFloat("water_wave_speed") << "\n";
|
||||
}
|
||||
|
||||
static const char* materialTypes[] = {
|
||||
"TILE_MATERIAL_BASIC",
|
||||
"TILE_MATERIAL_ALPHA",
|
||||
"TILE_MATERIAL_LIQUID_TRANSPARENT",
|
||||
"TILE_MATERIAL_LIQUID_OPAQUE",
|
||||
"TILE_MATERIAL_WAVING_LEAVES",
|
||||
"TILE_MATERIAL_WAVING_PLANTS",
|
||||
"TILE_MATERIAL_OPAQUE",
|
||||
"TILE_MATERIAL_WAVING_LIQUID_BASIC",
|
||||
"TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT",
|
||||
"TILE_MATERIAL_WAVING_LIQUID_OPAQUE",
|
||||
"TILE_MATERIAL_PLAIN",
|
||||
"TILE_MATERIAL_PLAIN_ALPHA",
|
||||
};
|
||||
shaders_header << "#define ENABLE_WAVING_LEAVES " << g_settings->getBool("enable_waving_leaves") << "\n";
|
||||
shaders_header << "#define ENABLE_WAVING_PLANTS " << g_settings->getBool("enable_waving_plants") << "\n";
|
||||
shaders_header << "#define ENABLE_TONE_MAPPING " << g_settings->getBool("tone_mapping") << "\n";
|
||||
|
||||
for (int i = 0; i < 12; i++){
|
||||
shaders_header += "#define ";
|
||||
shaders_header += materialTypes[i];
|
||||
shaders_header += " ";
|
||||
shaders_header += itos(i);
|
||||
shaders_header += "\n";
|
||||
shaders_header << "#define FOG_START " << core::clamp(g_settings->getFloat("fog_start"), 0.0f, 0.99f) << "\n";
|
||||
|
||||
std::string common_header = shaders_header.str();
|
||||
|
||||
std::string vertex_shader = m_sourcecache.getOrLoad(name, "opengl_vertex.glsl");
|
||||
std::string fragment_shader = m_sourcecache.getOrLoad(name, "opengl_fragment.glsl");
|
||||
std::string geometry_shader = m_sourcecache.getOrLoad(name, "opengl_geometry.glsl");
|
||||
|
||||
vertex_shader = common_header + vertex_header + vertex_shader;
|
||||
fragment_shader = common_header + fragment_header + fragment_shader;
|
||||
const char *geometry_shader_ptr = nullptr; // optional
|
||||
if (!geometry_shader.empty()) {
|
||||
geometry_shader = common_header + geometry_header + geometry_shader;
|
||||
geometry_shader_ptr = geometry_shader.c_str();
|
||||
}
|
||||
|
||||
shaders_header += "#define MATERIAL_TYPE ";
|
||||
shaders_header += itos(material_type);
|
||||
shaders_header += "\n";
|
||||
shaders_header += "#define DRAW_TYPE ";
|
||||
shaders_header += itos(drawtype);
|
||||
shaders_header += "\n";
|
||||
|
||||
if (g_settings->getBool("enable_waving_water")){
|
||||
shaders_header += "#define ENABLE_WAVING_WATER 1\n";
|
||||
shaders_header += "#define WATER_WAVE_HEIGHT ";
|
||||
shaders_header += std::to_string(g_settings->getFloat("water_wave_height"));
|
||||
shaders_header += "\n";
|
||||
shaders_header += "#define WATER_WAVE_LENGTH ";
|
||||
shaders_header += std::to_string(g_settings->getFloat("water_wave_length"));
|
||||
shaders_header += "\n";
|
||||
shaders_header += "#define WATER_WAVE_SPEED ";
|
||||
shaders_header += std::to_string(g_settings->getFloat("water_wave_speed"));
|
||||
shaders_header += "\n";
|
||||
} else{
|
||||
shaders_header += "#define ENABLE_WAVING_WATER 0\n";
|
||||
irr_ptr<ShaderCallback> cb{new ShaderCallback(m_setter_factories)};
|
||||
infostream<<"Compiling high level shaders for "<<name<<std::endl;
|
||||
s32 shadermat = gpu->addHighLevelShaderMaterial(
|
||||
vertex_shader.c_str(), nullptr, video::EVST_VS_1_1,
|
||||
fragment_shader.c_str(), nullptr, video::EPST_PS_1_1,
|
||||
geometry_shader_ptr, nullptr, video::EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLES, 0,
|
||||
cb.get(), shaderinfo.base_material, 1);
|
||||
if (shadermat == -1) {
|
||||
errorstream<<"generate_shader(): "
|
||||
"failed to generate \""<<name<<"\", "
|
||||
"addHighLevelShaderMaterial failed."
|
||||
<<std::endl;
|
||||
dumpShaderProgram(warningstream, "Vertex", vertex_shader);
|
||||
dumpShaderProgram(warningstream, "Fragment", fragment_shader);
|
||||
dumpShaderProgram(warningstream, "Geometry", geometry_shader);
|
||||
return shaderinfo;
|
||||
}
|
||||
|
||||
shaders_header += "#define ENABLE_WAVING_LEAVES ";
|
||||
if (g_settings->getBool("enable_waving_leaves"))
|
||||
shaders_header += "1\n";
|
||||
else
|
||||
shaders_header += "0\n";
|
||||
|
||||
shaders_header += "#define ENABLE_WAVING_PLANTS ";
|
||||
if (g_settings->getBool("enable_waving_plants"))
|
||||
shaders_header += "1\n";
|
||||
else
|
||||
shaders_header += "0\n";
|
||||
|
||||
if (g_settings->getBool("tone_mapping"))
|
||||
shaders_header += "#define ENABLE_TONE_MAPPING\n";
|
||||
|
||||
shaders_header += "#define FOG_START ";
|
||||
shaders_header += std::to_string(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f));
|
||||
shaders_header += "\n";
|
||||
|
||||
// Call addHighLevelShaderMaterial() or addShaderMaterial()
|
||||
const c8* vertex_program_ptr = 0;
|
||||
const c8* pixel_program_ptr = 0;
|
||||
const c8* geometry_program_ptr = 0;
|
||||
if (!vertex_program.empty()) {
|
||||
vertex_program = shaders_header + vertex_header + vertex_program;
|
||||
vertex_program_ptr = vertex_program.c_str();
|
||||
}
|
||||
if (!pixel_program.empty()) {
|
||||
pixel_program = shaders_header + pixel_header + pixel_program;
|
||||
pixel_program_ptr = pixel_program.c_str();
|
||||
}
|
||||
if (!geometry_program.empty()) {
|
||||
geometry_program = shaders_header + geometry_program;
|
||||
geometry_program_ptr = geometry_program.c_str();
|
||||
}
|
||||
ShaderCallback *cb = new ShaderCallback(setter_factories);
|
||||
s32 shadermat = -1;
|
||||
if(is_highlevel){
|
||||
infostream<<"Compiling high level shaders for "<<name<<std::endl;
|
||||
shadermat = gpu->addHighLevelShaderMaterial(
|
||||
vertex_program_ptr, // Vertex shader program
|
||||
"vertexMain", // Vertex shader entry point
|
||||
video::EVST_VS_1_1, // Vertex shader version
|
||||
pixel_program_ptr, // Pixel shader program
|
||||
"pixelMain", // Pixel shader entry point
|
||||
video::EPST_PS_1_2, // Pixel shader version
|
||||
geometry_program_ptr, // Geometry shader program
|
||||
"geometryMain", // Geometry shader entry point
|
||||
video::EGST_GS_4_0, // Geometry shader version
|
||||
scene::EPT_TRIANGLES, // Geometry shader input
|
||||
scene::EPT_TRIANGLE_STRIP, // Geometry shader output
|
||||
0, // Support maximum number of vertices
|
||||
cb, // Set-constant callback
|
||||
shaderinfo.base_material, // Base material
|
||||
1 // Userdata passed to callback
|
||||
);
|
||||
if(shadermat == -1){
|
||||
errorstream<<"generate_shader(): "
|
||||
"failed to generate \""<<name<<"\", "
|
||||
"addHighLevelShaderMaterial failed."
|
||||
<<std::endl;
|
||||
dumpShaderProgram(warningstream, "Vertex", vertex_program);
|
||||
dumpShaderProgram(warningstream, "Pixel", pixel_program);
|
||||
dumpShaderProgram(warningstream, "Geometry", geometry_program);
|
||||
delete cb;
|
||||
return shaderinfo;
|
||||
}
|
||||
}
|
||||
else{
|
||||
infostream<<"Compiling assembly shaders for "<<name<<std::endl;
|
||||
shadermat = gpu->addShaderMaterial(
|
||||
vertex_program_ptr, // Vertex shader program
|
||||
pixel_program_ptr, // Pixel shader program
|
||||
cb, // Set-constant callback
|
||||
shaderinfo.base_material, // Base material
|
||||
0 // Userdata passed to callback
|
||||
);
|
||||
|
||||
if(shadermat == -1){
|
||||
errorstream<<"generate_shader(): "
|
||||
"failed to generate \""<<name<<"\", "
|
||||
"addShaderMaterial failed."
|
||||
<<std::endl;
|
||||
dumpShaderProgram(warningstream, "Vertex", vertex_program);
|
||||
dumpShaderProgram(warningstream,"Pixel", pixel_program);
|
||||
delete cb;
|
||||
return shaderinfo;
|
||||
}
|
||||
}
|
||||
callbacks.push_back(cb);
|
||||
|
||||
// HACK, TODO: investigate this better
|
||||
// Grab the material renderer once more so minetest doesn't crash on exit
|
||||
driver->getMaterialRenderer(shadermat)->grab();
|
||||
|
||||
// Apply the newly created material type
|
||||
shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
|
||||
return shaderinfo;
|
||||
}
|
||||
|
||||
void load_shaders(const std::string &name, SourceShaderCache *sourcecache,
|
||||
video::E_DRIVER_TYPE drivertype, bool enable_shaders,
|
||||
std::string &vertex_program, std::string &pixel_program,
|
||||
std::string &geometry_program, bool &is_highlevel)
|
||||
{
|
||||
vertex_program = "";
|
||||
pixel_program = "";
|
||||
geometry_program = "";
|
||||
is_highlevel = false;
|
||||
|
||||
if (!enable_shaders)
|
||||
return;
|
||||
|
||||
// Look for high level shaders
|
||||
switch (drivertype) {
|
||||
case video::EDT_DIRECT3D9:
|
||||
// Direct3D 9: HLSL
|
||||
// (All shaders in one file)
|
||||
vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
|
||||
pixel_program = vertex_program;
|
||||
geometry_program = vertex_program;
|
||||
break;
|
||||
|
||||
case video::EDT_OPENGL:
|
||||
#if ENABLE_GLES
|
||||
case video::EDT_OGLES2:
|
||||
#endif
|
||||
// OpenGL: GLSL
|
||||
vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
|
||||
pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
|
||||
geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
|
||||
break;
|
||||
|
||||
default:
|
||||
// e.g. OpenGL ES 1 (with no shader support)
|
||||
break;
|
||||
}
|
||||
if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){
|
||||
is_highlevel = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void dumpShaderProgram(std::ostream &output_stream,
|
||||
const std::string &program_type, const std::string &program)
|
||||
{
|
||||
|
@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <IMaterialRendererServices.h>
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <string>
|
||||
#include "tile.h"
|
||||
#include "nodedef.h"
|
||||
|
||||
class IGameDef;
|
||||
|
||||
@ -46,8 +48,8 @@ struct ShaderInfo {
|
||||
std::string name = "";
|
||||
video::E_MATERIAL_TYPE base_material = video::EMT_SOLID;
|
||||
video::E_MATERIAL_TYPE material = video::EMT_SOLID;
|
||||
u8 drawtype = 0;
|
||||
u8 material_type = 0;
|
||||
NodeDrawType drawtype = NDT_NORMAL;
|
||||
MaterialType material_type = TILE_MATERIAL_BASIC;
|
||||
|
||||
ShaderInfo() = default;
|
||||
virtual ~ShaderInfo() = default;
|
||||
@ -65,8 +67,7 @@ namespace irr { namespace video {
|
||||
class IShaderConstantSetter {
|
||||
public:
|
||||
virtual ~IShaderConstantSetter() = default;
|
||||
virtual void onSetConstants(video::IMaterialRendererServices *services,
|
||||
bool is_highlevel) = 0;
|
||||
virtual void onSetConstants(video::IMaterialRendererServices *services) = 0;
|
||||
virtual void onSetMaterial(const video::SMaterial& material)
|
||||
{ }
|
||||
};
|
||||
@ -128,10 +129,10 @@ public:
|
||||
virtual ~IShaderSource() = default;
|
||||
|
||||
virtual u32 getShaderIdDirect(const std::string &name,
|
||||
const u8 material_type, const u8 drawtype){return 0;}
|
||||
MaterialType material_type, NodeDrawType drawtype = NDT_NORMAL){return 0;}
|
||||
virtual ShaderInfo getShaderInfo(u32 id){return ShaderInfo();}
|
||||
virtual u32 getShader(const std::string &name,
|
||||
const u8 material_type, const u8 drawtype){return 0;}
|
||||
MaterialType material_type, NodeDrawType drawtype = NDT_NORMAL){return 0;}
|
||||
};
|
||||
|
||||
class IWritableShaderSource : public IShaderSource {
|
||||
@ -139,16 +140,12 @@ public:
|
||||
IWritableShaderSource() = default;
|
||||
virtual ~IWritableShaderSource() = default;
|
||||
|
||||
virtual u32 getShaderIdDirect(const std::string &name,
|
||||
const u8 material_type, const u8 drawtype){return 0;}
|
||||
virtual ShaderInfo getShaderInfo(u32 id){return ShaderInfo();}
|
||||
virtual u32 getShader(const std::string &name,
|
||||
const u8 material_type, const u8 drawtype){return 0;}
|
||||
|
||||
virtual void processQueue()=0;
|
||||
virtual void insertSourceShader(const std::string &name_of_shader,
|
||||
const std::string &filename, const std::string &program)=0;
|
||||
virtual void rebuildShaders()=0;
|
||||
|
||||
/// @note Takes ownership of @p setter.
|
||||
virtual void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter) = 0;
|
||||
};
|
||||
|
||||
|
@ -65,7 +65,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc, IShaderSource *ssrc) :
|
||||
// Create materials
|
||||
|
||||
m_materials[0] = baseMaterial();
|
||||
m_materials[0].MaterialType = ssrc->getShaderInfo(ssrc->getShader("stars_shader", TILE_MATERIAL_ALPHA, 0)).material;
|
||||
m_materials[0].MaterialType = ssrc->getShaderInfo(ssrc->getShader("stars_shader", TILE_MATERIAL_ALPHA)).material;
|
||||
m_materials[0].Lighting = true;
|
||||
m_materials[0].ColorMaterial = video::ECM_NONE;
|
||||
|
||||
|
@ -1633,6 +1633,13 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||
/* IMPORTANT: When changing this, getTextureForMesh() needs to be
|
||||
* updated too. */
|
||||
|
||||
if (!baseimg) {
|
||||
errorstream << "generateImagePart(): baseimg == NULL "
|
||||
<< "for part_of_name=\"" << part_of_name
|
||||
<< "\", cancelling." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Apply the "clean transparent" filter, if configured.
|
||||
if (g_settings->getBool("texture_clean_transparent"))
|
||||
imageCleanTransparent(baseimg, 127);
|
||||
|
@ -347,6 +347,7 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("joystick_type", "");
|
||||
settings->setDefault("repeat_joystick_button_time", "0.17");
|
||||
settings->setDefault("joystick_frustum_sensitivity", "170");
|
||||
settings->setDefault("joystick_deadzone", "2048");
|
||||
|
||||
// Main menu
|
||||
settings->setDefault("main_menu_path", "");
|
||||
@ -453,6 +454,8 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("chat_message_limit_per_10sec", "8.0");
|
||||
settings->setDefault("chat_message_limit_trigger_kick", "50");
|
||||
settings->setDefault("sqlite_synchronous", "2");
|
||||
settings->setDefault("map_compression_level_disk", "3");
|
||||
settings->setDefault("map_compression_level_net", "-1");
|
||||
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||
settings->setDefault("dedicated_server_step", "0.09");
|
||||
settings->setDefault("active_block_mgmt_interval", "2.0");
|
||||
@ -538,6 +541,8 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("fps_max_unfocused", "10");
|
||||
settings->setDefault("max_objects_per_block", "20");
|
||||
settings->setDefault("sqlite_synchronous", "1");
|
||||
settings->setDefault("map_compression_level_disk", "-1");
|
||||
settings->setDefault("map_compression_level_net", "3");
|
||||
settings->setDefault("server_map_save_interval", "15");
|
||||
settings->setDefault("client_mapblock_limit", "1000");
|
||||
settings->setDefault("active_block_range", "2");
|
||||
|
@ -295,31 +295,26 @@ bool RecursiveDelete(const std::string &path)
|
||||
|
||||
infostream<<"Removing \""<<path<<"\""<<std::endl;
|
||||
|
||||
//return false;
|
||||
|
||||
pid_t child_pid = fork();
|
||||
|
||||
if(child_pid == 0)
|
||||
{
|
||||
// Child
|
||||
char argv_data[3][10000];
|
||||
const char *argv[4] = {
|
||||
#ifdef __ANDROID__
|
||||
strcpy(argv_data[0], "/system/bin/rm");
|
||||
"/system/bin/rm",
|
||||
#else
|
||||
strcpy(argv_data[0], "/bin/rm");
|
||||
"/bin/rm",
|
||||
#endif
|
||||
strcpy(argv_data[1], "-rf");
|
||||
strncpy(argv_data[2], path.c_str(), sizeof(argv_data[2]) - 1);
|
||||
char *argv[4];
|
||||
argv[0] = argv_data[0];
|
||||
argv[1] = argv_data[1];
|
||||
argv[2] = argv_data[2];
|
||||
argv[3] = NULL;
|
||||
"-rf",
|
||||
path.c_str(),
|
||||
NULL
|
||||
};
|
||||
|
||||
verbosestream<<"Executing '"<<argv[0]<<"' '"<<argv[1]<<"' '"
|
||||
<<argv[2]<<"'"<<std::endl;
|
||||
|
||||
execv(argv[0], argv);
|
||||
execv(argv[0], const_cast<char**>(argv));
|
||||
|
||||
// Execv shouldn't return. Failed.
|
||||
_exit(1);
|
||||
@ -331,7 +326,6 @@ bool RecursiveDelete(const std::string &path)
|
||||
pid_t tpid;
|
||||
do{
|
||||
tpid = wait(&child_status);
|
||||
//if(tpid != child_pid) process_terminated(tpid);
|
||||
}while(tpid != child_pid);
|
||||
return (child_status == 0);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ set(gui_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiButtonItemImage.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiConfirmRegistration.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiEditBox.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiEditBoxWithScrollbar.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiEngine.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiFormSpecMenu.cpp
|
||||
|
95
src/gui/guiEditBox.cpp
Normal file
95
src/gui/guiEditBox.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2021 Minetest
|
||||
|
||||
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 2.1 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.
|
||||
*/
|
||||
|
||||
#include "guiEditBox.h"
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIFont.h"
|
||||
|
||||
GUIEditBox::~GUIEditBox()
|
||||
{
|
||||
if (m_override_font)
|
||||
m_override_font->drop();
|
||||
}
|
||||
|
||||
void GUIEditBox::setOverrideFont(IGUIFont *font)
|
||||
{
|
||||
if (m_override_font == font)
|
||||
return;
|
||||
|
||||
if (m_override_font)
|
||||
m_override_font->drop();
|
||||
|
||||
m_override_font = font;
|
||||
|
||||
if (m_override_font)
|
||||
m_override_font->grab();
|
||||
|
||||
breakText();
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont *GUIEditBox::getActiveFont() const
|
||||
{
|
||||
if (m_override_font)
|
||||
return m_override_font;
|
||||
IGUISkin *skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets another color for the text.
|
||||
void GUIEditBox::setOverrideColor(video::SColor color)
|
||||
{
|
||||
m_override_color = color;
|
||||
m_override_color_enabled = true;
|
||||
}
|
||||
|
||||
video::SColor GUIEditBox::getOverrideColor() const
|
||||
{
|
||||
return m_override_color;
|
||||
}
|
||||
|
||||
//! Sets if the text should use the overide color or the color in the gui skin.
|
||||
void GUIEditBox::enableOverrideColor(bool enable)
|
||||
{
|
||||
m_override_color_enabled = enable;
|
||||
}
|
||||
|
||||
//! Enables or disables word wrap
|
||||
void GUIEditBox::setWordWrap(bool enable)
|
||||
{
|
||||
m_word_wrap = enable;
|
||||
breakText();
|
||||
}
|
||||
|
||||
//! Enables or disables newlines.
|
||||
void GUIEditBox::setMultiLine(bool enable)
|
||||
{
|
||||
m_multiline = enable;
|
||||
}
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
void GUIEditBox::setAutoScroll(bool enable)
|
||||
{
|
||||
m_autoscroll = enable;
|
||||
}
|
103
src/gui/guiEditBox.h
Normal file
103
src/gui/guiEditBox.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2021 Minetest
|
||||
|
||||
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 2.1 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IOSOperator.h"
|
||||
#include "guiScrollBar.h"
|
||||
|
||||
using namespace irr;
|
||||
using namespace irr::gui;
|
||||
|
||||
class GUIEditBox : public IGUIEditBox
|
||||
{
|
||||
public:
|
||||
GUIEditBox(IGUIEnvironment *environment, IGUIElement *parent, s32 id,
|
||||
core::rect<s32> rectangle) :
|
||||
IGUIEditBox(environment, parent, id, rectangle)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~GUIEditBox();
|
||||
|
||||
//! Sets another skin independent font.
|
||||
virtual void setOverrideFont(IGUIFont *font = 0);
|
||||
|
||||
virtual IGUIFont *getOverrideFont() const { return m_override_font; }
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont *getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
//! Gets the override color
|
||||
virtual video::SColor getOverrideColor() const;
|
||||
|
||||
//! Sets if the text should use the overide color or the
|
||||
//! color in the gui skin.
|
||||
virtual void enableOverrideColor(bool enable);
|
||||
|
||||
//! Checks if an override color is enabled
|
||||
/** \return true if the override color is enabled, false otherwise */
|
||||
virtual bool isOverrideColorEnabled(void) const
|
||||
{
|
||||
return m_override_color_enabled;
|
||||
}
|
||||
|
||||
//! Enables or disables word wrap for using the edit box as multiline text editor.
|
||||
virtual void setWordWrap(bool enable);
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
//! \return true if word wrap is enabled, false otherwise
|
||||
virtual bool isWordWrapEnabled() const { return m_word_wrap; }
|
||||
|
||||
//! Enables or disables newlines.
|
||||
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
|
||||
instead a newline character will be inserted. */
|
||||
virtual void setMultiLine(bool enable);
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
//! \return true if mult-line is enabled, false otherwise
|
||||
virtual bool isMultiLineEnabled() const { return m_multiline; }
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor
|
||||
//! position
|
||||
virtual void setAutoScroll(bool enable);
|
||||
|
||||
//! Checks to see if automatic scrolling is enabled
|
||||
//! \return true if automatic scrolling is enabled, false if not
|
||||
virtual bool isAutoScrollEnabled() const { return m_autoscroll; }
|
||||
|
||||
protected:
|
||||
virtual void breakText() = 0;
|
||||
|
||||
gui::IGUIFont *m_override_font = nullptr;
|
||||
|
||||
bool m_override_color_enabled = false;
|
||||
bool m_word_wrap = false;
|
||||
bool m_multiline = false;
|
||||
bool m_autoscroll = true;
|
||||
|
||||
video::SColor m_override_color = video::SColor(101, 255, 255, 255);
|
||||
};
|
@ -22,16 +22,14 @@ optional? dragging selected text
|
||||
numerical
|
||||
*/
|
||||
|
||||
|
||||
//! constructor
|
||||
GUIEditBoxWithScrollBar::GUIEditBoxWithScrollBar(const wchar_t* text, bool border,
|
||||
IGUIEnvironment* environment, IGUIElement* parent, s32 id,
|
||||
const core::rect<s32>& rectangle, bool writable, bool has_vscrollbar)
|
||||
: IGUIEditBox(environment, parent, id, rectangle), m_mouse_marking(false),
|
||||
m_border(border), m_background(true), m_override_color_enabled(false), m_mark_begin(0), m_mark_end(0),
|
||||
m_override_color(video::SColor(101, 255, 255, 255)), m_override_font(0), m_last_break_font(0),
|
||||
: GUIEditBox(environment, parent, id, rectangle), m_mouse_marking(false),
|
||||
m_border(border), m_background(true), m_mark_begin(0), m_mark_end(0), m_last_break_font(0),
|
||||
m_operator(0), m_blink_start_time(0), m_cursor_pos(0), m_hscroll_pos(0), m_vscroll_pos(0), m_max(0),
|
||||
m_word_wrap(false), m_multiline(false), m_autoscroll(true), m_passwordbox(false),
|
||||
m_passwordbox(false),
|
||||
m_passwordchar(L'*'), m_halign(EGUIA_UPPERLEFT), m_valign(EGUIA_CENTER),
|
||||
m_current_text_rect(0, 0, 1, 1), m_frame_rect(rectangle),
|
||||
m_scrollbar_width(0), m_vscrollbar(NULL), m_writable(writable),
|
||||
@ -69,9 +67,6 @@ GUIEditBoxWithScrollBar::GUIEditBoxWithScrollBar(const wchar_t* text, bool borde
|
||||
//! destructor
|
||||
GUIEditBoxWithScrollBar::~GUIEditBoxWithScrollBar()
|
||||
{
|
||||
if (m_override_font)
|
||||
m_override_font->drop();
|
||||
|
||||
if (m_operator)
|
||||
m_operator->drop();
|
||||
|
||||
@ -80,54 +75,6 @@ GUIEditBoxWithScrollBar::~GUIEditBoxWithScrollBar()
|
||||
}
|
||||
|
||||
|
||||
//! Sets another skin independent font.
|
||||
void GUIEditBoxWithScrollBar::setOverrideFont(IGUIFont* font)
|
||||
{
|
||||
if (m_override_font == font)
|
||||
return;
|
||||
|
||||
if (m_override_font)
|
||||
m_override_font->drop();
|
||||
|
||||
m_override_font = font;
|
||||
|
||||
if (m_override_font)
|
||||
m_override_font->grab();
|
||||
|
||||
breakText();
|
||||
}
|
||||
|
||||
//! Gets the override font (if any)
|
||||
IGUIFont * GUIEditBoxWithScrollBar::getOverrideFont() const
|
||||
{
|
||||
return m_override_font;
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont* GUIEditBoxWithScrollBar::getActiveFont() const
|
||||
{
|
||||
if (m_override_font)
|
||||
return m_override_font;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets another color for the text.
|
||||
void GUIEditBoxWithScrollBar::setOverrideColor(video::SColor color)
|
||||
{
|
||||
m_override_color = color;
|
||||
m_override_color_enabled = true;
|
||||
}
|
||||
|
||||
|
||||
video::SColor GUIEditBoxWithScrollBar::getOverrideColor() const
|
||||
{
|
||||
return m_override_color;
|
||||
}
|
||||
|
||||
|
||||
//! Turns the border on or off
|
||||
void GUIEditBoxWithScrollBar::setDrawBorder(bool border)
|
||||
{
|
||||
@ -140,24 +87,6 @@ void GUIEditBoxWithScrollBar::setDrawBackground(bool draw)
|
||||
m_background = draw;
|
||||
}
|
||||
|
||||
//! Sets if the text should use the overide color or the color in the gui skin.
|
||||
void GUIEditBoxWithScrollBar::enableOverrideColor(bool enable)
|
||||
{
|
||||
m_override_color_enabled = enable;
|
||||
}
|
||||
|
||||
bool GUIEditBoxWithScrollBar::isOverrideColorEnabled() const
|
||||
{
|
||||
return m_override_color_enabled;
|
||||
}
|
||||
|
||||
//! Enables or disables word wrap
|
||||
void GUIEditBoxWithScrollBar::setWordWrap(bool enable)
|
||||
{
|
||||
m_word_wrap = enable;
|
||||
breakText();
|
||||
}
|
||||
|
||||
|
||||
void GUIEditBoxWithScrollBar::updateAbsolutePosition()
|
||||
{
|
||||
@ -170,26 +99,6 @@ void GUIEditBoxWithScrollBar::updateAbsolutePosition()
|
||||
}
|
||||
}
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
bool GUIEditBoxWithScrollBar::isWordWrapEnabled() const
|
||||
{
|
||||
return m_word_wrap;
|
||||
}
|
||||
|
||||
|
||||
//! Enables or disables newlines.
|
||||
void GUIEditBoxWithScrollBar::setMultiLine(bool enable)
|
||||
{
|
||||
m_multiline = enable;
|
||||
}
|
||||
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
bool GUIEditBoxWithScrollBar::isMultiLineEnabled() const
|
||||
{
|
||||
return m_multiline;
|
||||
}
|
||||
|
||||
|
||||
void GUIEditBoxWithScrollBar::setPasswordBox(bool password_box, wchar_t password_char)
|
||||
{
|
||||
@ -850,22 +759,6 @@ void GUIEditBoxWithScrollBar::setText(const wchar_t* text)
|
||||
}
|
||||
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
void GUIEditBoxWithScrollBar::setAutoScroll(bool enable)
|
||||
{
|
||||
m_autoscroll = enable;
|
||||
}
|
||||
|
||||
|
||||
//! Checks to see if automatic scrolling is enabled
|
||||
//! \return true if automatic scrolling is enabled, false if not
|
||||
bool GUIEditBoxWithScrollBar::isAutoScrollEnabled() const
|
||||
{
|
||||
return m_autoscroll;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the area of the text in the edit box
|
||||
//! \return Returns the size in pixels of the text
|
||||
core::dimension2du GUIEditBoxWithScrollBar::getTextDimension()
|
||||
|
@ -5,15 +5,10 @@
|
||||
#ifndef GUIEDITBOXWITHSCROLLBAR_HEADER
|
||||
#define GUIEDITBOXWITHSCROLLBAR_HEADER
|
||||
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IOSOperator.h"
|
||||
#include "guiScrollBar.h"
|
||||
#include "guiEditBox.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace irr;
|
||||
using namespace irr::gui;
|
||||
|
||||
class GUIEditBoxWithScrollBar : public IGUIEditBox
|
||||
class GUIEditBoxWithScrollBar : public GUIEditBox
|
||||
{
|
||||
public:
|
||||
|
||||
@ -25,61 +20,13 @@ public:
|
||||
//! destructor
|
||||
virtual ~GUIEditBoxWithScrollBar();
|
||||
|
||||
//! Sets another skin independent font.
|
||||
virtual void setOverrideFont(IGUIFont* font = 0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
//! Gets the override color
|
||||
virtual video::SColor getOverrideColor() const;
|
||||
|
||||
//! Sets if the text should use the overide color or the
|
||||
//! color in the gui skin.
|
||||
virtual void enableOverrideColor(bool enable);
|
||||
|
||||
//! Checks if an override color is enabled
|
||||
/** \return true if the override color is enabled, false otherwise */
|
||||
virtual bool isOverrideColorEnabled(void) const;
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw);
|
||||
|
||||
//! Turns the border on or off
|
||||
virtual void setDrawBorder(bool border);
|
||||
|
||||
//! Enables or disables word wrap for using the edit box as multiline text editor.
|
||||
virtual void setWordWrap(bool enable);
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
//! \return true if word wrap is enabled, false otherwise
|
||||
virtual bool isWordWrapEnabled() const;
|
||||
|
||||
//! Enables or disables newlines.
|
||||
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
|
||||
instead a newline character will be inserted. */
|
||||
virtual void setMultiLine(bool enable);
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
//! \return true if mult-line is enabled, false otherwise
|
||||
virtual bool isMultiLineEnabled() const;
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
virtual void setAutoScroll(bool enable);
|
||||
|
||||
//! Checks to see if automatic scrolling is enabled
|
||||
//! \return true if automatic scrolling is enabled, false if not
|
||||
virtual bool isAutoScrollEnabled() const;
|
||||
|
||||
//! Gets the size area of the text in the edit box
|
||||
//! \return Returns the size in pixels of the text
|
||||
@ -137,7 +84,7 @@ public:
|
||||
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
virtual void breakText();
|
||||
//! sets the area of the given line
|
||||
void setTextRect(s32 line);
|
||||
//! returns the line number that the cursor is on
|
||||
@ -164,12 +111,11 @@ protected:
|
||||
bool m_mouse_marking;
|
||||
bool m_border;
|
||||
bool m_background;
|
||||
bool m_override_color_enabled;
|
||||
|
||||
s32 m_mark_begin;
|
||||
s32 m_mark_end;
|
||||
|
||||
video::SColor m_override_color;
|
||||
gui::IGUIFont *m_override_font, *m_last_break_font;
|
||||
gui::IGUIFont *m_last_break_font;
|
||||
IOSOperator* m_operator;
|
||||
|
||||
u32 m_blink_start_time;
|
||||
@ -177,7 +123,7 @@ protected:
|
||||
s32 m_hscroll_pos, m_vscroll_pos; // scroll position in characters
|
||||
u32 m_max;
|
||||
|
||||
bool m_word_wrap, m_multiline, m_autoscroll, m_passwordbox;
|
||||
bool m_passwordbox;
|
||||
wchar_t m_passwordchar;
|
||||
EGUI_ALIGNMENT m_halign, m_valign;
|
||||
|
||||
|
@ -70,7 +70,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#define MY_CHECKPOS(a,b) \
|
||||
if (v_pos.size() != 2) { \
|
||||
errorstream<< "Invalid pos for element " << a << "specified: \"" \
|
||||
errorstream<< "Invalid pos for element " << a << " specified: \"" \
|
||||
<< parts[b] << "\"" << std::endl; \
|
||||
return; \
|
||||
}
|
||||
@ -78,7 +78,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define MY_CHECKGEOM(a,b) \
|
||||
if (v_geom.size() != 2) { \
|
||||
errorstream<< "Invalid geometry for element " << a << \
|
||||
"specified: \"" << parts[b] << "\"" << std::endl; \
|
||||
" specified: \"" << parts[b] << "\"" << std::endl; \
|
||||
return; \
|
||||
}
|
||||
/*
|
||||
@ -2725,7 +2725,7 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
|
||||
{
|
||||
std::vector<std::string> parts = split(element, ';');
|
||||
|
||||
if (parts.size() < 5 || (parts.size() > 8 &&
|
||||
if (parts.size() < 5 || (parts.size() > 9 &&
|
||||
m_formspec_version <= FORMSPEC_API_VERSION)) {
|
||||
errorstream << "Invalid model element (" << parts.size() << "): '" << element
|
||||
<< "'" << std::endl;
|
||||
@ -2733,8 +2733,8 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
|
||||
}
|
||||
|
||||
// Avoid length checks by resizing
|
||||
if (parts.size() < 8)
|
||||
parts.resize(8);
|
||||
if (parts.size() < 9)
|
||||
parts.resize(9);
|
||||
|
||||
std::vector<std::string> v_pos = split(parts[0], ',');
|
||||
std::vector<std::string> v_geom = split(parts[1], ',');
|
||||
@ -2744,6 +2744,7 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
|
||||
std::vector<std::string> vec_rot = split(parts[5], ',');
|
||||
bool inf_rotation = is_yes(parts[6]);
|
||||
bool mousectrl = is_yes(parts[7]) || parts[7].empty(); // default true
|
||||
std::vector<std::string> frame_loop = split(parts[8], ',');
|
||||
|
||||
MY_CHECKPOS("model", 0);
|
||||
MY_CHECKGEOM("model", 1);
|
||||
@ -2786,7 +2787,7 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
|
||||
auto meshnode = e->setMesh(mesh);
|
||||
|
||||
for (u32 i = 0; i < textures.size() && i < meshnode->getMaterialCount(); ++i)
|
||||
e->setTexture(i, m_tsrc->getTexture(textures[i]));
|
||||
e->setTexture(i, m_tsrc->getTexture(unescape_string(textures[i])));
|
||||
|
||||
if (vec_rot.size() >= 2)
|
||||
e->setRotation(v2f(stof(vec_rot[0]), stof(vec_rot[1])));
|
||||
@ -2794,6 +2795,16 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
|
||||
e->enableContinuousRotation(inf_rotation);
|
||||
e->enableMouseControl(mousectrl);
|
||||
|
||||
s32 frame_loop_begin = 0;
|
||||
s32 frame_loop_end = 0x7FFFFFFF;
|
||||
|
||||
if (frame_loop.size() == 2) {
|
||||
frame_loop_begin = stoi(frame_loop[0]);
|
||||
frame_loop_end = stoi(frame_loop[1]);
|
||||
}
|
||||
|
||||
e->setFrameLoop(frame_loop_begin, frame_loop_end);
|
||||
|
||||
auto style = getStyleForElement("model", spec.fname);
|
||||
e->setStyles(style);
|
||||
e->drop();
|
||||
@ -3707,7 +3718,8 @@ void GUIFormSpecMenu::showTooltip(const std::wstring &text,
|
||||
{
|
||||
EnrichedString ntext(text);
|
||||
ntext.setDefaultColor(color);
|
||||
ntext.setBackground(bgcolor);
|
||||
if (!ntext.hasBackground())
|
||||
ntext.setBackground(bgcolor);
|
||||
|
||||
setStaticText(m_tooltip_element, ntext);
|
||||
|
||||
|
@ -152,6 +152,15 @@ void GUIScene::setStyles(const std::array<StyleSpec, StyleSpec::NUM_STATES> &sty
|
||||
setBackgroundColor(style.getColor(StyleSpec::BGCOLOR, m_bgcolor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the frame loop range for the mesh
|
||||
*/
|
||||
void GUIScene::setFrameLoop(s32 begin, s32 end)
|
||||
{
|
||||
if (m_mesh->getStartFrame() != begin || m_mesh->getEndFrame() != end)
|
||||
m_mesh->setFrameLoop(begin, end);
|
||||
}
|
||||
|
||||
/* Camera control functions */
|
||||
|
||||
inline void GUIScene::calcOptimalDistance()
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
scene::IAnimatedMeshSceneNode *setMesh(scene::IAnimatedMesh *mesh = nullptr);
|
||||
void setTexture(u32 idx, video::ITexture *texture);
|
||||
void setBackgroundColor(const video::SColor &color) noexcept { m_bgcolor = color; };
|
||||
void setFrameLoop(s32 begin, s32 end);
|
||||
void enableMouseControl(bool enable) noexcept { m_mouse_ctrl = enable; };
|
||||
void setRotation(v2f rot) noexcept { m_custom_rot = rot; };
|
||||
void enableContinuousRotation(bool enable) noexcept { m_inf_rot = enable; };
|
||||
|
@ -59,7 +59,7 @@ namespace gui
|
||||
intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border,
|
||||
IGUIEnvironment* environment, IGUIElement* parent, s32 id,
|
||||
const core::rect<s32>& rectangle, bool writable, bool has_vscrollbar)
|
||||
: IGUIEditBox(environment, parent, id, rectangle),
|
||||
: GUIEditBox(environment, parent, id, rectangle),
|
||||
Border(border), FrameRect(rectangle),
|
||||
m_scrollbar_width(0), m_vscrollbar(NULL), m_writable(writable)
|
||||
{
|
||||
@ -108,9 +108,6 @@ intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border,
|
||||
//! destructor
|
||||
intlGUIEditBox::~intlGUIEditBox()
|
||||
{
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
|
||||
if (Operator)
|
||||
Operator->drop();
|
||||
|
||||
@ -118,52 +115,6 @@ intlGUIEditBox::~intlGUIEditBox()
|
||||
m_vscrollbar->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Sets another skin independent font.
|
||||
void intlGUIEditBox::setOverrideFont(IGUIFont* font)
|
||||
{
|
||||
if (OverrideFont == font)
|
||||
return;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
|
||||
OverrideFont = font;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->grab();
|
||||
|
||||
breakText();
|
||||
}
|
||||
|
||||
IGUIFont * intlGUIEditBox::getOverrideFont() const
|
||||
{
|
||||
return OverrideFont;
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont* intlGUIEditBox::getActiveFont() const
|
||||
{
|
||||
if ( OverrideFont )
|
||||
return OverrideFont;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets another color for the text.
|
||||
void intlGUIEditBox::setOverrideColor(video::SColor color)
|
||||
{
|
||||
OverrideColor = color;
|
||||
OverrideColorEnabled = true;
|
||||
}
|
||||
|
||||
video::SColor intlGUIEditBox::getOverrideColor() const
|
||||
{
|
||||
return OverrideColor;
|
||||
}
|
||||
|
||||
//! Turns the border on or off
|
||||
void intlGUIEditBox::setDrawBorder(bool border)
|
||||
{
|
||||
@ -175,25 +126,6 @@ void intlGUIEditBox::setDrawBackground(bool draw)
|
||||
{
|
||||
}
|
||||
|
||||
//! Sets if the text should use the overide color or the color in the gui skin.
|
||||
void intlGUIEditBox::enableOverrideColor(bool enable)
|
||||
{
|
||||
OverrideColorEnabled = enable;
|
||||
}
|
||||
|
||||
bool intlGUIEditBox::isOverrideColorEnabled() const
|
||||
{
|
||||
return OverrideColorEnabled;
|
||||
}
|
||||
|
||||
//! Enables or disables word wrap
|
||||
void intlGUIEditBox::setWordWrap(bool enable)
|
||||
{
|
||||
WordWrap = enable;
|
||||
breakText();
|
||||
}
|
||||
|
||||
|
||||
void intlGUIEditBox::updateAbsolutePosition()
|
||||
{
|
||||
core::rect<s32> oldAbsoluteRect(AbsoluteRect);
|
||||
@ -204,28 +136,6 @@ void intlGUIEditBox::updateAbsolutePosition()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
bool intlGUIEditBox::isWordWrapEnabled() const
|
||||
{
|
||||
return WordWrap;
|
||||
}
|
||||
|
||||
|
||||
//! Enables or disables newlines.
|
||||
void intlGUIEditBox::setMultiLine(bool enable)
|
||||
{
|
||||
MultiLine = enable;
|
||||
}
|
||||
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
bool intlGUIEditBox::isMultiLineEnabled() const
|
||||
{
|
||||
return MultiLine;
|
||||
}
|
||||
|
||||
|
||||
void intlGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar)
|
||||
{
|
||||
PasswordBox = passwordBox;
|
||||
@ -464,7 +374,7 @@ bool intlGUIEditBox::processKey(const SEvent& event)
|
||||
case KEY_END:
|
||||
{
|
||||
s32 p = Text.size();
|
||||
if (WordWrap || MultiLine)
|
||||
if (m_word_wrap || m_multiline)
|
||||
{
|
||||
p = getLineFromPos(CursorPos);
|
||||
p = BrokenTextPositions[p] + (s32)BrokenText[p].size();
|
||||
@ -492,7 +402,7 @@ bool intlGUIEditBox::processKey(const SEvent& event)
|
||||
{
|
||||
|
||||
s32 p = 0;
|
||||
if (WordWrap || MultiLine)
|
||||
if (m_word_wrap || m_multiline)
|
||||
{
|
||||
p = getLineFromPos(CursorPos);
|
||||
p = BrokenTextPositions[p];
|
||||
@ -514,7 +424,7 @@ bool intlGUIEditBox::processKey(const SEvent& event)
|
||||
}
|
||||
break;
|
||||
case KEY_RETURN:
|
||||
if (MultiLine)
|
||||
if (m_multiline)
|
||||
{
|
||||
inputChar(L'\n');
|
||||
return true;
|
||||
@ -567,7 +477,7 @@ bool intlGUIEditBox::processKey(const SEvent& event)
|
||||
BlinkStartTime = porting::getTimeMs();
|
||||
break;
|
||||
case KEY_UP:
|
||||
if (MultiLine || (WordWrap && BrokenText.size() > 1) )
|
||||
if (m_multiline || (m_word_wrap && BrokenText.size() > 1) )
|
||||
{
|
||||
s32 lineNo = getLineFromPos(CursorPos);
|
||||
s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd);
|
||||
@ -598,7 +508,7 @@ bool intlGUIEditBox::processKey(const SEvent& event)
|
||||
}
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
if (MultiLine || (WordWrap && BrokenText.size() > 1) )
|
||||
if (m_multiline || (m_word_wrap && BrokenText.size() > 1) )
|
||||
{
|
||||
s32 lineNo = getLineFromPos(CursorPos);
|
||||
s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd);
|
||||
@ -791,8 +701,8 @@ void intlGUIEditBox::draw()
|
||||
|
||||
// draw the text
|
||||
|
||||
IGUIFont* font = OverrideFont;
|
||||
if (!OverrideFont)
|
||||
IGUIFont* font = m_override_font;
|
||||
if (!m_override_font)
|
||||
font = skin->getFont();
|
||||
|
||||
s32 cursorLine = 0;
|
||||
@ -813,7 +723,7 @@ void intlGUIEditBox::draw()
|
||||
core::stringw s, s2;
|
||||
|
||||
// get mark position
|
||||
const bool ml = (!PasswordBox && (WordWrap || MultiLine));
|
||||
const bool ml = (!PasswordBox && (m_word_wrap || m_multiline));
|
||||
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
||||
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
||||
const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0;
|
||||
@ -822,14 +732,14 @@ void intlGUIEditBox::draw()
|
||||
|
||||
// Save the override color information.
|
||||
// Then, alter it if the edit box is disabled.
|
||||
const bool prevOver = OverrideColorEnabled;
|
||||
const video::SColor prevColor = OverrideColor;
|
||||
const bool prevOver = m_override_color_enabled;
|
||||
const video::SColor prevColor = m_override_color;
|
||||
|
||||
if (!Text.empty()) {
|
||||
if (!IsEnabled && !OverrideColorEnabled)
|
||||
if (!IsEnabled && !m_override_color_enabled)
|
||||
{
|
||||
OverrideColorEnabled = true;
|
||||
OverrideColor = skin->getColor(EGDC_GRAY_TEXT);
|
||||
m_override_color_enabled = true;
|
||||
m_override_color = skin->getColor(EGDC_GRAY_TEXT);
|
||||
}
|
||||
|
||||
for (s32 i=0; i < lineCount; ++i)
|
||||
@ -870,7 +780,7 @@ void intlGUIEditBox::draw()
|
||||
|
||||
// draw normal text
|
||||
font->draw(txtLine->c_str(), CurrentTextRect,
|
||||
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
|
||||
m_override_color_enabled ? m_override_color : skin->getColor(EGDC_BUTTON_TEXT),
|
||||
false, true, &localClipRect);
|
||||
|
||||
// draw mark and marked text
|
||||
@ -914,20 +824,20 @@ void intlGUIEditBox::draw()
|
||||
|
||||
if (!s.empty())
|
||||
font->draw(s.c_str(), CurrentTextRect,
|
||||
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT),
|
||||
m_override_color_enabled ? m_override_color : skin->getColor(EGDC_HIGH_LIGHT_TEXT),
|
||||
false, true, &localClipRect);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Return the override color information to its previous settings.
|
||||
OverrideColorEnabled = prevOver;
|
||||
OverrideColor = prevColor;
|
||||
m_override_color_enabled = prevOver;
|
||||
m_override_color = prevColor;
|
||||
}
|
||||
|
||||
// draw cursor
|
||||
|
||||
if (WordWrap || MultiLine)
|
||||
if (m_word_wrap || m_multiline)
|
||||
{
|
||||
cursorLine = getLineFromPos(CursorPos);
|
||||
txtLine = &BrokenText[cursorLine];
|
||||
@ -943,7 +853,7 @@ void intlGUIEditBox::draw()
|
||||
CurrentTextRect.UpperLeftCorner.X += charcursorpos;
|
||||
|
||||
font->draw(L"_", CurrentTextRect,
|
||||
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
|
||||
m_override_color_enabled ? m_override_color : skin->getColor(EGDC_BUTTON_TEXT),
|
||||
false, true, &localClipRect);
|
||||
}
|
||||
}
|
||||
@ -965,22 +875,6 @@ void intlGUIEditBox::setText(const wchar_t* text)
|
||||
}
|
||||
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
void intlGUIEditBox::setAutoScroll(bool enable)
|
||||
{
|
||||
AutoScroll = enable;
|
||||
}
|
||||
|
||||
|
||||
//! Checks to see if automatic scrolling is enabled
|
||||
//! \return true if automatic scrolling is enabled, false if not
|
||||
bool intlGUIEditBox::isAutoScrollEnabled() const
|
||||
{
|
||||
return AutoScroll;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the area of the text in the edit box
|
||||
//! \return Returns the size in pixels of the text
|
||||
core::dimension2du intlGUIEditBox::getTextDimension()
|
||||
@ -1096,12 +990,12 @@ bool intlGUIEditBox::processMouse(const SEvent& event)
|
||||
|
||||
s32 intlGUIEditBox::getCursorPos(s32 x, s32 y)
|
||||
{
|
||||
IGUIFont* font = OverrideFont;
|
||||
IGUIFont* font = m_override_font;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!OverrideFont)
|
||||
if (!m_override_font)
|
||||
font = skin->getFont();
|
||||
|
||||
const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
|
||||
const u32 lineCount = (m_word_wrap || m_multiline) ? BrokenText.size() : 1;
|
||||
|
||||
core::stringw *txtLine = NULL;
|
||||
s32 startPos = 0;
|
||||
@ -1118,8 +1012,8 @@ s32 intlGUIEditBox::getCursorPos(s32 x, s32 y)
|
||||
// is it inside this region?
|
||||
if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y) {
|
||||
// we've found the clicked line
|
||||
txtLine = (WordWrap || MultiLine) ? &BrokenText[curr_line_idx] : &Text;
|
||||
startPos = (WordWrap || MultiLine) ? BrokenTextPositions[curr_line_idx] : 0;
|
||||
txtLine = (m_word_wrap || m_multiline) ? &BrokenText[curr_line_idx] : &Text;
|
||||
startPos = (m_word_wrap || m_multiline) ? BrokenTextPositions[curr_line_idx] : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1144,14 +1038,14 @@ void intlGUIEditBox::breakText()
|
||||
{
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
if ((!WordWrap && !MultiLine) || !skin)
|
||||
if ((!m_word_wrap && !m_multiline) || !skin)
|
||||
return;
|
||||
|
||||
BrokenText.clear(); // need to reallocate :/
|
||||
BrokenTextPositions.set_used(0);
|
||||
|
||||
IGUIFont* font = OverrideFont;
|
||||
if (!OverrideFont)
|
||||
IGUIFont* font = m_override_font;
|
||||
if (!m_override_font)
|
||||
font = skin->getFont();
|
||||
|
||||
if (!font)
|
||||
@ -1190,7 +1084,7 @@ void intlGUIEditBox::breakText()
|
||||
}
|
||||
|
||||
// don't break if we're not a multi-line edit box
|
||||
if (!MultiLine)
|
||||
if (!m_multiline)
|
||||
lineBreak = false;
|
||||
|
||||
if (c == L' ' || c == 0 || i == (size-1))
|
||||
@ -1201,7 +1095,7 @@ void intlGUIEditBox::breakText()
|
||||
s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
|
||||
s32 worldlgth = font->getDimension(word.c_str()).Width;
|
||||
|
||||
if (WordWrap && length + worldlgth + whitelgth > elWidth)
|
||||
if (m_word_wrap && length + worldlgth + whitelgth > elWidth)
|
||||
{
|
||||
// break to next line
|
||||
length = worldlgth;
|
||||
@ -1260,14 +1154,14 @@ void intlGUIEditBox::setTextRect(s32 line)
|
||||
if (!skin)
|
||||
return;
|
||||
|
||||
IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
|
||||
IGUIFont* font = m_override_font ? m_override_font : skin->getFont();
|
||||
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
// get text dimension
|
||||
const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
|
||||
if (WordWrap || MultiLine)
|
||||
const u32 lineCount = (m_word_wrap || m_multiline) ? BrokenText.size() : 1;
|
||||
if (m_word_wrap || m_multiline)
|
||||
{
|
||||
d = font->getDimension(BrokenText[line].c_str());
|
||||
}
|
||||
@ -1328,7 +1222,7 @@ void intlGUIEditBox::setTextRect(s32 line)
|
||||
|
||||
s32 intlGUIEditBox::getLineFromPos(s32 pos)
|
||||
{
|
||||
if (!WordWrap && !MultiLine)
|
||||
if (!m_word_wrap && !m_multiline)
|
||||
return 0;
|
||||
|
||||
s32 i=0;
|
||||
@ -1387,7 +1281,7 @@ void intlGUIEditBox::inputChar(wchar_t c)
|
||||
|
||||
void intlGUIEditBox::calculateScrollPos()
|
||||
{
|
||||
if (!AutoScroll)
|
||||
if (!m_autoscroll)
|
||||
return;
|
||||
|
||||
// calculate horizontal scroll position
|
||||
@ -1395,18 +1289,18 @@ void intlGUIEditBox::calculateScrollPos()
|
||||
setTextRect(cursLine);
|
||||
|
||||
// don't do horizontal scrolling when wordwrap is enabled.
|
||||
if (!WordWrap)
|
||||
if (!m_word_wrap)
|
||||
{
|
||||
// get cursor position
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
|
||||
IGUIFont* font = m_override_font ? m_override_font : skin->getFont();
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
core::stringw *txtLine = MultiLine ? &BrokenText[cursLine] : &Text;
|
||||
s32 cPos = MultiLine ? CursorPos - BrokenTextPositions[cursLine] : CursorPos;
|
||||
core::stringw *txtLine = m_multiline ? &BrokenText[cursLine] : &Text;
|
||||
s32 cPos = m_multiline ? CursorPos - BrokenTextPositions[cursLine] : CursorPos;
|
||||
|
||||
s32 cStart = CurrentTextRect.UpperLeftCorner.X + HScrollPos +
|
||||
font->getDimension(txtLine->subString(0, cPos).c_str()).Width;
|
||||
@ -1423,7 +1317,7 @@ void intlGUIEditBox::calculateScrollPos()
|
||||
// todo: adjust scrollbar
|
||||
}
|
||||
|
||||
if (!WordWrap && !MultiLine)
|
||||
if (!m_word_wrap && !m_multiline)
|
||||
return;
|
||||
|
||||
// vertical scroll position
|
||||
@ -1468,8 +1362,8 @@ void intlGUIEditBox::createVScrollBar()
|
||||
{
|
||||
s32 fontHeight = 1;
|
||||
|
||||
if (OverrideFont) {
|
||||
fontHeight = OverrideFont->getDimension(L"").Height;
|
||||
if (m_override_font) {
|
||||
fontHeight = m_override_font->getDimension(L"").Height;
|
||||
} else {
|
||||
if (IGUISkin* skin = Environment->getSkin()) {
|
||||
if (IGUIFont* font = skin->getFont()) {
|
||||
@ -1520,7 +1414,7 @@ void intlGUIEditBox::updateVScrollBar()
|
||||
m_vscrollbar->setPageSize(s32(getTextDimension().Height));
|
||||
}
|
||||
|
||||
if (!m_vscrollbar->isVisible() && MultiLine) {
|
||||
if (!m_vscrollbar->isVisible() && m_multiline) {
|
||||
AbsoluteRect.LowerRightCorner.X -= m_scrollbar_width;
|
||||
|
||||
m_vscrollbar->setVisible(true);
|
||||
@ -1548,20 +1442,20 @@ void intlGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeRea
|
||||
{
|
||||
// IGUIEditBox::serializeAttributes(out,options);
|
||||
|
||||
out->addBool ("OverrideColorEnabled",OverrideColorEnabled );
|
||||
out->addColor ("OverrideColor", OverrideColor);
|
||||
// out->addFont("OverrideFont",OverrideFont);
|
||||
out->addInt ("MaxChars", Max);
|
||||
out->addBool ("WordWrap", WordWrap);
|
||||
out->addBool ("MultiLine", MultiLine);
|
||||
out->addBool ("AutoScroll", AutoScroll);
|
||||
out->addBool ("PasswordBox", PasswordBox);
|
||||
out->addBool ("OverrideColorEnabled", m_override_color_enabled );
|
||||
out->addColor ("OverrideColor", m_override_color);
|
||||
// out->addFont("OverrideFont",m_override_font);
|
||||
out->addInt ("MaxChars", Max);
|
||||
out->addBool ("WordWrap", m_word_wrap);
|
||||
out->addBool ("MultiLine", m_multiline);
|
||||
out->addBool ("AutoScroll", m_autoscroll);
|
||||
out->addBool ("PasswordBox", PasswordBox);
|
||||
core::stringw ch = L" ";
|
||||
ch[0] = PasswordChar;
|
||||
out->addString("PasswordChar", ch.c_str());
|
||||
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
|
||||
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
|
||||
out->addBool ("Writable", m_writable);
|
||||
out->addString("PasswordChar", ch.c_str());
|
||||
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
|
||||
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
|
||||
out->addBool ("Writable", m_writable);
|
||||
|
||||
IGUIEditBox::serializeAttributes(out,options);
|
||||
}
|
||||
|
@ -7,16 +7,15 @@
|
||||
#include "IrrCompileConfig.h"
|
||||
//#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include <IGUIEditBox.h>
|
||||
#include "guiEditBox.h"
|
||||
#include "irrArray.h"
|
||||
#include "IOSOperator.h"
|
||||
#include "guiScrollBar.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class intlGUIEditBox : public IGUIEditBox
|
||||
class intlGUIEditBox : public GUIEditBox
|
||||
{
|
||||
public:
|
||||
|
||||
@ -28,32 +27,6 @@ namespace gui
|
||||
//! destructor
|
||||
virtual ~intlGUIEditBox();
|
||||
|
||||
//! Sets another skin independent font.
|
||||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
//! Gets the override color
|
||||
virtual video::SColor getOverrideColor() const;
|
||||
|
||||
//! Sets if the text should use the overide color or the
|
||||
//! color in the gui skin.
|
||||
virtual void enableOverrideColor(bool enable);
|
||||
|
||||
//! Checks if an override color is enabled
|
||||
/** \return true if the override color is enabled, false otherwise */
|
||||
virtual bool isOverrideColorEnabled(void) const;
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw);
|
||||
|
||||
@ -64,30 +37,6 @@ namespace gui
|
||||
|
||||
virtual bool isDrawBorderEnabled() const { return Border; }
|
||||
|
||||
//! Enables or disables word wrap for using the edit box as multiline text editor.
|
||||
virtual void setWordWrap(bool enable);
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
//! \return true if word wrap is enabled, false otherwise
|
||||
virtual bool isWordWrapEnabled() const;
|
||||
|
||||
//! Enables or disables newlines.
|
||||
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
|
||||
instead a newline character will be inserted. */
|
||||
virtual void setMultiLine(bool enable);
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
//! \return true if mult-line is enabled, false otherwise
|
||||
virtual bool isMultiLineEnabled() const;
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
virtual void setAutoScroll(bool enable);
|
||||
|
||||
//! Checks to see if automatic scrolling is enabled
|
||||
//! \return true if automatic scrolling is enabled, false if not
|
||||
virtual bool isAutoScrollEnabled() const;
|
||||
|
||||
//! Gets the size area of the text in the edit box
|
||||
//! \return Returns the size in pixels of the text
|
||||
virtual core::dimension2du getTextDimension();
|
||||
@ -143,7 +92,7 @@ namespace gui
|
||||
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
virtual void breakText();
|
||||
//! sets the area of the given line
|
||||
void setTextRect(s32 line);
|
||||
//! returns the line number that the cursor is on
|
||||
@ -169,12 +118,9 @@ namespace gui
|
||||
|
||||
bool MouseMarking = false;
|
||||
bool Border;
|
||||
bool OverrideColorEnabled = false;
|
||||
s32 MarkBegin = 0;
|
||||
s32 MarkEnd = 0;
|
||||
|
||||
video::SColor OverrideColor = video::SColor(101,255,255,255);
|
||||
gui::IGUIFont *OverrideFont = nullptr;
|
||||
gui::IGUIFont *LastBreakFont = nullptr;
|
||||
IOSOperator *Operator = nullptr;
|
||||
|
||||
@ -184,9 +130,6 @@ namespace gui
|
||||
s32 VScrollPos = 0; // scroll position in characters
|
||||
u32 Max = 0;
|
||||
|
||||
bool WordWrap = false;
|
||||
bool MultiLine = false;
|
||||
bool AutoScroll = true;
|
||||
bool PasswordBox = false;
|
||||
wchar_t PasswordChar = L'*';
|
||||
EGUI_ALIGNMENT HAlign = EGUIA_UPPERLEFT;
|
||||
|
@ -881,8 +881,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
|
||||
s32 dyj = event.TouchInput.Y - m_screensize.Y + button_size * 5.0f / 2.0f;
|
||||
bool inside_joystick = (dxj * dxj + dyj * dyj <= button_size * button_size * 1.5 * 1.5);
|
||||
|
||||
if (m_joystick_has_really_moved ||
|
||||
(!m_joystick_has_really_moved && inside_joystick) ||
|
||||
if (m_joystick_has_really_moved || inside_joystick ||
|
||||
(!m_fixed_joystick &&
|
||||
distance_sq > m_touchscreen_threshold * m_touchscreen_threshold)) {
|
||||
m_joystick_has_really_moved = true;
|
||||
|
@ -356,7 +356,7 @@ namespace gui
|
||||
load_flags = FT_LOAD_DEFAULT | FT_LOAD_RENDER;
|
||||
if (!useHinting()) load_flags |= FT_LOAD_NO_HINTING;
|
||||
if (!useAutoHinting()) load_flags |= FT_LOAD_NO_AUTOHINT;
|
||||
if (useMonochrome()) load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO | FT_RENDER_MODE_MONO;
|
||||
if (useMonochrome()) load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO;
|
||||
else load_flags |= FT_LOAD_TARGET_NORMAL;
|
||||
}
|
||||
u32 getWidthFromCharacter(wchar_t c) const;
|
||||
|
@ -1331,7 +1331,7 @@ public:
|
||||
{
|
||||
u32 i;
|
||||
const uchar16_t* oa = other.c_str();
|
||||
for(i=0; array[i] && oa[i] && i < n; ++i)
|
||||
for(i=0; i < n && array[i] && oa[i]; ++i)
|
||||
if (array[i] != oa[i])
|
||||
return false;
|
||||
|
||||
@ -1350,7 +1350,7 @@ public:
|
||||
if (!str)
|
||||
return false;
|
||||
u32 i;
|
||||
for(i=0; array[i] && str[i] && i < n; ++i)
|
||||
for(i=0; i < n && array[i] && str[i]; ++i)
|
||||
if (array[i] != str[i])
|
||||
return false;
|
||||
|
||||
|
@ -1250,6 +1250,8 @@ ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
|
||||
|
||||
m_save_time_counter = mb->addCounter("minetest_core_map_save_time", "Map save time (in nanoseconds)");
|
||||
|
||||
m_map_compression_level = rangelim(g_settings->getS16("map_compression_level_disk"), -1, 9);
|
||||
|
||||
try {
|
||||
// If directory exists, check contents and load if possible
|
||||
if (fs::PathExists(m_savedir)) {
|
||||
@ -1863,10 +1865,10 @@ void ServerMap::endSave()
|
||||
|
||||
bool ServerMap::saveBlock(MapBlock *block)
|
||||
{
|
||||
return saveBlock(block, dbase);
|
||||
return saveBlock(block, dbase, m_map_compression_level);
|
||||
}
|
||||
|
||||
bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db)
|
||||
bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db, int compression_level)
|
||||
{
|
||||
v3s16 p3d = block->getPos();
|
||||
|
||||
@ -1886,7 +1888,7 @@ bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db)
|
||||
*/
|
||||
std::ostringstream o(std::ios_base::binary);
|
||||
o.write((char*) &version, 1);
|
||||
block->serialize(o, version, true);
|
||||
block->serialize(o, version, true, compression_level);
|
||||
|
||||
bool ret = db->saveBlock(p3d, o.str());
|
||||
if (ret) {
|
||||
|
@ -382,7 +382,7 @@ public:
|
||||
MapgenParams *getMapgenParams();
|
||||
|
||||
bool saveBlock(MapBlock *block);
|
||||
static bool saveBlock(MapBlock *block, MapDatabase *db);
|
||||
static bool saveBlock(MapBlock *block, MapDatabase *db, int compression_level = -1);
|
||||
MapBlock* loadBlock(v3s16 p);
|
||||
// Database version
|
||||
void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false);
|
||||
@ -417,6 +417,7 @@ private:
|
||||
std::string m_savedir;
|
||||
bool m_map_saving_enabled;
|
||||
|
||||
int m_map_compression_level;
|
||||
#if 0
|
||||
// Chunk size in MapSectors
|
||||
// If 0, chunks are disabled.
|
||||
|
@ -355,7 +355,7 @@ static void correctBlockNodeIds(const NameIdMapping *nimap, MapNode *nodes,
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
||||
void MapBlock::serialize(std::ostream &os, u8 version, bool disk, int compression_level)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapBlock format not supported");
|
||||
@ -394,7 +394,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
||||
writeU8(os, content_width);
|
||||
writeU8(os, params_width);
|
||||
MapNode::serializeBulk(os, version, tmp_nodes, nodecount,
|
||||
content_width, params_width, true);
|
||||
content_width, params_width, compression_level);
|
||||
delete[] tmp_nodes;
|
||||
}
|
||||
else
|
||||
@ -404,7 +404,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
||||
writeU8(os, content_width);
|
||||
writeU8(os, params_width);
|
||||
MapNode::serializeBulk(os, version, data, nodecount,
|
||||
content_width, params_width, true);
|
||||
content_width, params_width, compression_level);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -412,7 +412,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
||||
*/
|
||||
std::ostringstream oss(std::ios_base::binary);
|
||||
m_node_metadata.serialize(oss, version, disk);
|
||||
compressZlib(oss.str(), os);
|
||||
compressZlib(oss.str(), os, compression_level);
|
||||
|
||||
/*
|
||||
Data that goes to disk, but not the network
|
||||
@ -485,7 +485,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
|
||||
if(params_width != 2)
|
||||
throw SerializationError("MapBlock::deSerialize(): invalid params_width");
|
||||
MapNode::deSerializeBulk(is, version, data, nodecount,
|
||||
content_width, params_width, true);
|
||||
content_width, params_width);
|
||||
|
||||
/*
|
||||
NodeMetadata
|
||||
|
@ -482,7 +482,7 @@ public:
|
||||
// These don't write or read version by itself
|
||||
// Set disk to true for on-disk format, false for over-the-network format
|
||||
// Precondition: version >= SER_FMT_VER_LOWEST_WRITE
|
||||
void serialize(std::ostream &os, u8 version, bool disk);
|
||||
void serialize(std::ostream &os, u8 version, bool disk, int compression_level);
|
||||
// If disk == true: In addition to doing other things, will add
|
||||
// unknown blocks from id-name mapping to wndef
|
||||
void deSerialize(std::istream &is, u8 version, bool disk);
|
||||
|
@ -297,7 +297,7 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
|
||||
int iters = 256;
|
||||
while (iters > 0 && y <= max_spawn_y) {
|
||||
if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) {
|
||||
if (y <= water_level || y > max_spawn_y)
|
||||
if (y <= water_level)
|
||||
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
|
||||
|
||||
// y + 1 due to biome 'dust'
|
||||
|
@ -334,7 +334,7 @@ bool Schematic::deserializeFromMts(std::istream *is,
|
||||
schemdata = new MapNode[nodecount];
|
||||
|
||||
MapNode::deSerializeBulk(ss, SER_FMT_VER_HIGHEST_READ, schemdata,
|
||||
nodecount, 2, 2, true);
|
||||
nodecount, 2, 2);
|
||||
|
||||
// Fix probability values for nodes that were ignore; removed in v2
|
||||
if (version < 2) {
|
||||
@ -376,7 +376,7 @@ bool Schematic::serializeToMts(std::ostream *os,
|
||||
|
||||
// compressed bulk node data
|
||||
MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE,
|
||||
schemdata, size.X * size.Y * size.Z, 2, 2, true);
|
||||
schemdata, size.X * size.Y * size.Z, 2, 2, -1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -406,7 +406,8 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0,
|
||||
v3f(position.X, position.Y, position.Z - 1),
|
||||
tree_definition
|
||||
);
|
||||
} if (!stack_orientation.empty()) {
|
||||
}
|
||||
if (!stack_orientation.empty()) {
|
||||
s16 size = 1;
|
||||
for (x = -size; x <= size; x++)
|
||||
for (y = -size; y <= size; y++)
|
||||
|
@ -706,7 +706,7 @@ void MapNode::deSerialize(u8 *source, u8 version)
|
||||
}
|
||||
void MapNode::serializeBulk(std::ostream &os, int version,
|
||||
const MapNode *nodes, u32 nodecount,
|
||||
u8 content_width, u8 params_width, bool compressed)
|
||||
u8 content_width, u8 params_width, int compression_level)
|
||||
{
|
||||
if (!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
@ -737,10 +737,7 @@ void MapNode::serializeBulk(std::ostream &os, int version,
|
||||
Compress data to output stream
|
||||
*/
|
||||
|
||||
if (compressed)
|
||||
compressZlib(databuf, databuf_size, os);
|
||||
else
|
||||
os.write((const char*) &databuf[0], databuf_size);
|
||||
compressZlib(databuf, databuf_size, os, compression_level);
|
||||
|
||||
delete [] databuf;
|
||||
}
|
||||
@ -748,7 +745,7 @@ void MapNode::serializeBulk(std::ostream &os, int version,
|
||||
// Deserialize bulk node data
|
||||
void MapNode::deSerializeBulk(std::istream &is, int version,
|
||||
MapNode *nodes, u32 nodecount,
|
||||
u8 content_width, u8 params_width, bool compressed)
|
||||
u8 content_width, u8 params_width)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
@ -760,24 +757,13 @@ void MapNode::deSerializeBulk(std::istream &is, int version,
|
||||
|
||||
// Uncompress or read data
|
||||
u32 len = nodecount * (content_width + params_width);
|
||||
SharedBuffer<u8> databuf(len);
|
||||
if(compressed)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
decompressZlib(is, os);
|
||||
std::string s = os.str();
|
||||
if(s.size() != len)
|
||||
throw SerializationError("deSerializeBulkNodes: "
|
||||
"decompress resulted in invalid size");
|
||||
memcpy(&databuf[0], s.c_str(), len);
|
||||
}
|
||||
else
|
||||
{
|
||||
is.read((char*) &databuf[0], len);
|
||||
if(is.eof() || is.fail())
|
||||
throw SerializationError("deSerializeBulkNodes: "
|
||||
"failed to read bulk node data");
|
||||
}
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
decompressZlib(is, os);
|
||||
std::string s = os.str();
|
||||
if(s.size() != len)
|
||||
throw SerializationError("deSerializeBulkNodes: "
|
||||
"decompress resulted in invalid size");
|
||||
const u8 *databuf = reinterpret_cast<const u8*>(s.c_str());
|
||||
|
||||
// Deserialize content
|
||||
if(content_width == 1)
|
||||
|
@ -292,10 +292,10 @@ struct MapNode
|
||||
// compressed = true to zlib-compress output
|
||||
static void serializeBulk(std::ostream &os, int version,
|
||||
const MapNode *nodes, u32 nodecount,
|
||||
u8 content_width, u8 params_width, bool compressed);
|
||||
u8 content_width, u8 params_width, int compression_level);
|
||||
static void deSerializeBulk(std::istream &is, int version,
|
||||
MapNode *nodes, u32 nodecount,
|
||||
u8 content_width, u8 params_width, bool compressed);
|
||||
u8 content_width, u8 params_width);
|
||||
|
||||
private:
|
||||
// Deprecated serialization methods
|
||||
|
@ -226,22 +226,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define PASSWORD_SIZE 28 // Maximum password length. Allows for
|
||||
// base64-encoded SHA-1 (27+\0).
|
||||
|
||||
/*
|
||||
Changes by FORMSPEC_API_VERSION:
|
||||
|
||||
FORMSPEC VERSION 1:
|
||||
(too much)
|
||||
FORMSPEC VERSION 2:
|
||||
Forced real coordinates
|
||||
background9[]: 9-slice scaling parameters
|
||||
FORMSPEC VERSION 3:
|
||||
Formspec elements are drawn in the order of definition
|
||||
bgcolor[]: use 3 parameters (bgcolor, formspec (now an enum), fbgcolor)
|
||||
box[] and image[] elements enable clipping by default
|
||||
new element: scroll_container[]
|
||||
FORMSPEC VERSION 4:
|
||||
Allow dropdown indexing events
|
||||
*/
|
||||
// See also: Formspec Version History in doc/lua_api.txt
|
||||
#define FORMSPEC_API_VERSION 4
|
||||
|
||||
#define TEXTURENAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.-"
|
||||
|
@ -316,7 +316,7 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
|
||||
// Send active objects
|
||||
{
|
||||
PlayerSAO *sao = getPlayerSAO(peer_id);
|
||||
if (client && sao)
|
||||
if (sao)
|
||||
SendActiveObjectRemoveAdd(client, sao);
|
||||
}
|
||||
|
||||
|
@ -617,7 +617,7 @@ static void fillTileAttribs(ITextureSource *tsrc, TileLayer *layer,
|
||||
bool has_scale = tiledef.scale > 0;
|
||||
bool use_autoscale = tsettings.autoscale_mode == AUTOSCALE_FORCE ||
|
||||
(tsettings.autoscale_mode == AUTOSCALE_ENABLE && !has_scale);
|
||||
if (use_autoscale && layer->texture) {
|
||||
if (use_autoscale) {
|
||||
auto texture_size = layer->texture->getOriginalSize();
|
||||
float base_size = tsettings.node_texture_size;
|
||||
float size = std::fmin(texture_size.Width, texture_size.Height);
|
||||
@ -774,7 +774,7 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
|
||||
bool is_liquid = false;
|
||||
|
||||
u8 material_type = (alpha == 255) ?
|
||||
MaterialType material_type = (alpha == 255) ?
|
||||
TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA;
|
||||
|
||||
switch (drawtype) {
|
||||
@ -892,7 +892,7 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
|
||||
u32 tile_shader = shdsrc->getShader("nodes_shader", material_type, drawtype);
|
||||
|
||||
u8 overlay_material = material_type;
|
||||
MaterialType overlay_material = material_type;
|
||||
if (overlay_material == TILE_MATERIAL_OPAQUE)
|
||||
overlay_material = TILE_MATERIAL_BASIC;
|
||||
else if (overlay_material == TILE_MATERIAL_LIQUID_OPAQUE)
|
||||
@ -913,7 +913,7 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
tdef[j].backface_culling, tsettings);
|
||||
}
|
||||
|
||||
u8 special_material = material_type;
|
||||
MaterialType special_material = material_type;
|
||||
if (drawtype == NDT_PLANTLIKE_ROOTED) {
|
||||
if (waving == 1)
|
||||
special_material = TILE_MATERIAL_WAVING_PLANTS;
|
||||
|
@ -719,29 +719,48 @@ int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...)
|
||||
return c;
|
||||
}
|
||||
|
||||
bool openURL(const std::string &url)
|
||||
static bool open_uri(const std::string &uri)
|
||||
{
|
||||
if ((url.substr(0, 7) != "http://" && url.substr(0, 8) != "https://") ||
|
||||
url.find_first_of("\r\n") != std::string::npos) {
|
||||
errorstream << "Invalid url: " << url << std::endl;
|
||||
if (uri.find_first_of("\r\n") != std::string::npos) {
|
||||
errorstream << "Unable to open URI as it is invalid, contains new line: " << uri << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
return (intptr_t)ShellExecuteA(NULL, NULL, url.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32;
|
||||
return (intptr_t)ShellExecuteA(NULL, NULL, uri.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32;
|
||||
#elif defined(__ANDROID__)
|
||||
openURLAndroid(url);
|
||||
openURIAndroid(uri);
|
||||
return true;
|
||||
#elif defined(__APPLE__)
|
||||
const char *argv[] = {"open", url.c_str(), NULL};
|
||||
const char *argv[] = {"open", uri.c_str(), NULL};
|
||||
return posix_spawnp(NULL, "open", NULL, NULL, (char**)argv,
|
||||
(*_NSGetEnviron())) == 0;
|
||||
#else
|
||||
const char *argv[] = {"xdg-open", url.c_str(), NULL};
|
||||
const char *argv[] = {"xdg-open", uri.c_str(), NULL};
|
||||
return posix_spawnp(NULL, "xdg-open", NULL, NULL, (char**)argv, environ) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool open_url(const std::string &url)
|
||||
{
|
||||
if (url.substr(0, 7) != "http://" && url.substr(0, 8) != "https://") {
|
||||
errorstream << "Unable to open browser as URL is missing schema: " << url << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return open_uri(url);
|
||||
}
|
||||
|
||||
bool open_directory(const std::string &path)
|
||||
{
|
||||
if (!fs::IsDir(path)) {
|
||||
errorstream << "Unable to open directory as it does not exist: " << path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return open_uri(path);
|
||||
}
|
||||
|
||||
// Load performance counter frequency only once at startup
|
||||
#ifdef _WIN32
|
||||
|
||||
|
@ -332,7 +332,25 @@ void attachOrCreateConsole();
|
||||
|
||||
int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...);
|
||||
|
||||
bool openURL(const std::string &url);
|
||||
/**
|
||||
* Opens URL in default web browser
|
||||
*
|
||||
* Must begin with http:// or https://, and not contain any new lines
|
||||
*
|
||||
* @param url The URL
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
bool open_url(const std::string &url);
|
||||
|
||||
/**
|
||||
* Opens a directory in the default file manager
|
||||
*
|
||||
* The directory must exist.
|
||||
*
|
||||
* @param path Path to directory
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
bool open_directory(const std::string &path);
|
||||
|
||||
} // namespace porting
|
||||
|
||||
|
@ -213,13 +213,13 @@ void showInputDialog(const std::string &acceptButton, const std::string &hint,
|
||||
jacceptButton, jhint, jcurrent, jeditType);
|
||||
}
|
||||
|
||||
void openURLAndroid(const std::string &url)
|
||||
void openURIAndroid(const std::string &url)
|
||||
{
|
||||
jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURL",
|
||||
jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURI",
|
||||
"(Ljava/lang/String;)V");
|
||||
|
||||
FATAL_ERROR_IF(url_open == nullptr,
|
||||
"porting::openURLAndroid unable to find java openURL method");
|
||||
"porting::openURIAndroid unable to find java openURI method");
|
||||
|
||||
jstring jurl = jnienv->NewStringUTF(url.c_str());
|
||||
jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl);
|
||||
|
@ -58,7 +58,7 @@ void initializePathsAndroid();
|
||||
void showInputDialog(const std::string &acceptButton,
|
||||
const std::string &hint, const std::string ¤t, int editType);
|
||||
|
||||
void openURLAndroid(const std::string &url);
|
||||
void openURIAndroid(const std::string &url);
|
||||
|
||||
/**
|
||||
* WORKAROUND for not working callbacks from java -> c++
|
||||
|
@ -38,7 +38,7 @@ ScopeProfiler::~ScopeProfiler()
|
||||
return;
|
||||
|
||||
float duration_ms = m_timer->stop(true);
|
||||
float duration = duration_ms / 1000.0;
|
||||
float duration = duration_ms;
|
||||
if (m_profiler) {
|
||||
switch (m_type) {
|
||||
case SPT_ADD:
|
||||
|
@ -103,6 +103,32 @@ void ScriptApiEntity::luaentity_Activate(u16 id,
|
||||
lua_pop(L, 2); // Pop object and error handler
|
||||
}
|
||||
|
||||
void ScriptApiEntity::luaentity_Deactivate(u16 id)
|
||||
{
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
||||
verbosestream << "scriptapi_luaentity_deactivate: id=" << id << std::endl;
|
||||
|
||||
int error_handler = PUSH_ERROR_HANDLER(L);
|
||||
|
||||
// Get the entity
|
||||
luaentity_get(L, id);
|
||||
int object = lua_gettop(L);
|
||||
|
||||
// Get on_deactivate
|
||||
lua_getfield(L, -1, "on_deactivate");
|
||||
if (!lua_isnil(L, -1)) {
|
||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||
lua_pushvalue(L, object);
|
||||
|
||||
setOriginFromTable(object);
|
||||
PCALL_RES(lua_pcall(L, 1, 0, error_handler));
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 2); // Pop object and error handler
|
||||
}
|
||||
|
||||
void ScriptApiEntity::luaentity_Remove(u16 id)
|
||||
{
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
bool luaentity_Add(u16 id, const char *name);
|
||||
void luaentity_Activate(u16 id,
|
||||
const std::string &staticdata, u32 dtime_s);
|
||||
void luaentity_Deactivate(u16 id);
|
||||
void luaentity_Remove(u16 id);
|
||||
std::string luaentity_GetStaticdata(u16 id);
|
||||
void luaentity_GetProperties(u16 id,
|
||||
|
@ -401,10 +401,9 @@ bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path, const char
|
||||
lua_pushfstring(L, "%s: %s", path, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
chunk_name = new char[strlen(display_name) + 2];
|
||||
chunk_name[0] = '@';
|
||||
chunk_name[1] = '\0';
|
||||
strcat(chunk_name, display_name);
|
||||
size_t len = strlen(display_name) + 2;
|
||||
chunk_name = new char[len];
|
||||
snprintf(chunk_name, len, "@%s", display_name);
|
||||
}
|
||||
|
||||
size_t start = 0;
|
||||
|
@ -743,6 +743,31 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_objects_in_area(pos, minp, maxp)
|
||||
int ModApiEnvMod::l_get_objects_in_area(lua_State *L)
|
||||
{
|
||||
GET_ENV_PTR;
|
||||
ScriptApiBase *script = getScriptApiBase(L);
|
||||
|
||||
v3f minp = read_v3f(L, 1) * BS;
|
||||
v3f maxp = read_v3f(L, 2) * BS;
|
||||
aabb3f box(minp, maxp);
|
||||
box.repair();
|
||||
std::vector<ServerActiveObject *> objs;
|
||||
|
||||
auto include_obj_cb = [](ServerActiveObject *obj){ return !obj->isGone(); };
|
||||
env->getObjectsInArea(objs, box, include_obj_cb);
|
||||
|
||||
int i = 0;
|
||||
lua_createtable(L, objs.size(), 0);
|
||||
for (const auto obj : objs) {
|
||||
// Insert object reference into table
|
||||
script->objectrefGetOrCreate(L, obj);
|
||||
lua_rawseti(L, -2, ++i);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_timeofday(val)
|
||||
// val = 0...1
|
||||
int ModApiEnvMod::l_set_timeofday(lua_State *L)
|
||||
@ -1571,6 +1596,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
|
||||
API_FCT(get_node_timer);
|
||||
API_FCT(get_connected_players);
|
||||
API_FCT(get_player_by_name);
|
||||
API_FCT(get_objects_in_area);
|
||||
API_FCT(get_objects_inside_radius);
|
||||
API_FCT(set_timeofday);
|
||||
API_FCT(get_timeofday);
|
||||
|
@ -115,6 +115,9 @@ private:
|
||||
// get_objects_inside_radius(pos, radius)
|
||||
static int l_get_objects_inside_radius(lua_State *L);
|
||||
|
||||
// get_objects_in_area(pos, minp, maxp)
|
||||
static int l_get_objects_in_area(lua_State *L);
|
||||
|
||||
// set_timeofday(val)
|
||||
// val = 0...1
|
||||
static int l_set_timeofday(lua_State *L);
|
||||
|
@ -686,6 +686,14 @@ int ModApiMainMenu::l_get_mapgen_names(lua_State *L)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
int ModApiMainMenu::l_get_user_path(lua_State *L)
|
||||
{
|
||||
std::string path = fs::RemoveRelativePathComponents(porting::path_user);
|
||||
lua_pushstring(L, path.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int ModApiMainMenu::l_get_modpath(lua_State *L)
|
||||
{
|
||||
@ -795,6 +803,15 @@ int ModApiMainMenu::l_copy_dir(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int ModApiMainMenu::l_is_dir(lua_State *L)
|
||||
{
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
|
||||
lua_pushboolean(L, fs::IsDir(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int ModApiMainMenu::l_extract_zip(lua_State *L)
|
||||
{
|
||||
@ -1070,7 +1087,15 @@ int ModApiMainMenu::l_get_max_supp_proto(lua_State *L)
|
||||
int ModApiMainMenu::l_open_url(lua_State *L)
|
||||
{
|
||||
std::string url = luaL_checkstring(L, 1);
|
||||
lua_pushboolean(L, porting::openURL(url));
|
||||
lua_pushboolean(L, porting::open_url(url));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int ModApiMainMenu::l_open_dir(lua_State *L)
|
||||
{
|
||||
std::string path = luaL_checkstring(L, 1);
|
||||
lua_pushboolean(L, porting::open_directory(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1116,6 +1141,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
|
||||
API_FCT(set_background);
|
||||
API_FCT(set_topleft_text);
|
||||
API_FCT(get_mapgen_names);
|
||||
API_FCT(get_user_path);
|
||||
API_FCT(get_modpath);
|
||||
API_FCT(get_clientmodpath);
|
||||
API_FCT(get_gamepath);
|
||||
@ -1125,6 +1151,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
|
||||
API_FCT(create_dir);
|
||||
API_FCT(delete_dir);
|
||||
API_FCT(copy_dir);
|
||||
API_FCT(is_dir);
|
||||
API_FCT(extract_zip);
|
||||
API_FCT(may_modify_path);
|
||||
API_FCT(get_mainmenu_path);
|
||||
@ -1137,6 +1164,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
|
||||
API_FCT(get_min_supp_proto);
|
||||
API_FCT(get_max_supp_proto);
|
||||
API_FCT(open_url);
|
||||
API_FCT(open_dir);
|
||||
API_FCT(do_async_callback);
|
||||
}
|
||||
|
||||
@ -1147,6 +1175,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top)
|
||||
API_FCT(get_games);
|
||||
API_FCT(get_favorites);
|
||||
API_FCT(get_mapgen_names);
|
||||
API_FCT(get_user_path);
|
||||
API_FCT(get_modpath);
|
||||
API_FCT(get_clientmodpath);
|
||||
API_FCT(get_gamepath);
|
||||
@ -1156,6 +1185,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top)
|
||||
API_FCT(create_dir);
|
||||
API_FCT(delete_dir);
|
||||
API_FCT(copy_dir);
|
||||
API_FCT(is_dir);
|
||||
//API_FCT(extract_zip); //TODO remove dependency to GuiEngine
|
||||
API_FCT(may_modify_path);
|
||||
API_FCT(download_file);
|
||||
|
@ -112,6 +112,8 @@ private:
|
||||
|
||||
static int l_get_mainmenu_path(lua_State *L);
|
||||
|
||||
static int l_get_user_path(lua_State *L);
|
||||
|
||||
static int l_get_modpath(lua_State *L);
|
||||
|
||||
static int l_get_clientmodpath(lua_State *L);
|
||||
@ -130,6 +132,8 @@ private:
|
||||
|
||||
static int l_copy_dir(lua_State *L);
|
||||
|
||||
static int l_is_dir(lua_State *L);
|
||||
|
||||
static int l_extract_zip(lua_State *L);
|
||||
|
||||
static int l_may_modify_path(lua_State *L);
|
||||
@ -148,6 +152,8 @@ private:
|
||||
// other
|
||||
static int l_open_url(lua_State *L);
|
||||
|
||||
static int l_open_dir(lua_State *L);
|
||||
|
||||
|
||||
// async
|
||||
static int l_do_async_callback(lua_State *L);
|
||||
|
@ -110,7 +110,7 @@ int ObjectRef::l_remove(lua_State *L)
|
||||
sao->clearParentAttachment();
|
||||
|
||||
verbosestream << "ObjectRef::l_remove(): id=" << sao->getId() << std::endl;
|
||||
sao->m_pending_removal = true;
|
||||
sao->markForRemoval();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1409,7 +1409,7 @@ int ObjectRef::l_set_physics_override(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
PlayerSAO *playersao = (PlayerSAO *) getobject(ref);
|
||||
PlayerSAO *playersao = getplayersao(ref);
|
||||
if (playersao == nullptr)
|
||||
return 0;
|
||||
|
||||
@ -1449,7 +1449,7 @@ int ObjectRef::l_get_physics_override(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
PlayerSAO *playersao = (PlayerSAO *)getobject(ref);
|
||||
PlayerSAO *playersao = getplayersao(ref);
|
||||
if (playersao == nullptr)
|
||||
return 0;
|
||||
|
||||
|
@ -239,15 +239,6 @@ int ModApiUtil::l_is_yes(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// is_nan(arg)
|
||||
int ModApiUtil::l_is_nan(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
lua_pushboolean(L, isNaN(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_builtin_path()
|
||||
int ModApiUtil::l_get_builtin_path(lua_State *L)
|
||||
{
|
||||
@ -493,7 +484,6 @@ void ModApiUtil::Initialize(lua_State *L, int top)
|
||||
API_FCT(get_password_hash);
|
||||
|
||||
API_FCT(is_yes);
|
||||
API_FCT(is_nan);
|
||||
|
||||
API_FCT(get_builtin_path);
|
||||
|
||||
@ -526,7 +516,6 @@ void ModApiUtil::InitializeClient(lua_State *L, int top)
|
||||
API_FCT(write_json);
|
||||
|
||||
API_FCT(is_yes);
|
||||
API_FCT(is_nan);
|
||||
|
||||
API_FCT(compress);
|
||||
API_FCT(decompress);
|
||||
|
@ -65,9 +65,6 @@ private:
|
||||
// is_yes(arg)
|
||||
static int l_is_yes(lua_State *L);
|
||||
|
||||
// is_nan(arg)
|
||||
static int l_is_nan(lua_State *L);
|
||||
|
||||
// get_builtin_path()
|
||||
static int l_get_builtin_path(lua_State *L);
|
||||
|
||||
|
@ -2332,9 +2332,9 @@ void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
|
||||
/*
|
||||
Create a packet with the block in the right format
|
||||
*/
|
||||
|
||||
thread_local const int net_compression_level = rangelim(g_settings->getS16("map_compression_level_net"), -1, 9);
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
block->serialize(os, ver, false);
|
||||
block->serialize(os, ver, false, net_compression_level);
|
||||
block->serializeNetworkSpecific(os);
|
||||
std::string s = os.str();
|
||||
|
||||
|
@ -127,6 +127,21 @@ void ActiveObjectMgr::getObjectsInsideRadius(const v3f &pos, float radius,
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveObjectMgr::getObjectsInArea(const aabb3f &box,
|
||||
std::vector<ServerActiveObject *> &result,
|
||||
std::function<bool(ServerActiveObject *obj)> include_obj_cb)
|
||||
{
|
||||
for (auto &activeObject : m_active_objects) {
|
||||
ServerActiveObject *obj = activeObject.second;
|
||||
const v3f &objectpos = obj->getBasePosition();
|
||||
if (!box.isPointInside(objectpos))
|
||||
continue;
|
||||
|
||||
if (!include_obj_cb || include_obj_cb(obj))
|
||||
result.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveObjectMgr::getAddedActiveObjectsAroundPos(const v3f &player_pos, f32 radius,
|
||||
f32 player_radius, std::set<u16> ¤t_objects,
|
||||
std::queue<u16> &added_objects)
|
||||
|
@ -38,6 +38,9 @@ public:
|
||||
void getObjectsInsideRadius(const v3f &pos, float radius,
|
||||
std::vector<ServerActiveObject *> &result,
|
||||
std::function<bool(ServerActiveObject *obj)> include_obj_cb);
|
||||
void getObjectsInArea(const aabb3f &box,
|
||||
std::vector<ServerActiveObject *> &result,
|
||||
std::function<bool(ServerActiveObject *obj)> include_obj_cb);
|
||||
|
||||
void getAddedActiveObjectsAroundPos(const v3f &player_pos, f32 radius,
|
||||
f32 player_radius, std::set<u16> ¤t_objects,
|
||||
|
@ -112,6 +112,15 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s)
|
||||
}
|
||||
}
|
||||
|
||||
void LuaEntitySAO::dispatchScriptDeactivate()
|
||||
{
|
||||
// Ensure that this is in fact a registered entity,
|
||||
// and that it isn't already gone.
|
||||
// The latter also prevents this from ever being called twice.
|
||||
if (m_registered && !isGone())
|
||||
m_env->getScriptIface()->luaentity_Deactivate(m_id);
|
||||
}
|
||||
|
||||
void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
if(!m_properties_sent)
|
||||
@ -302,7 +311,7 @@ u16 LuaEntitySAO::punch(v3f dir,
|
||||
{
|
||||
if (!m_registered) {
|
||||
// Delete unknown LuaEntities when punched
|
||||
m_pending_removal = true;
|
||||
markForRemoval();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -335,7 +344,7 @@ u16 LuaEntitySAO::punch(v3f dir,
|
||||
clearParentAttachment();
|
||||
clearChildAttachments();
|
||||
m_env->getScriptIface()->luaentity_on_death(m_id, puncher);
|
||||
m_pending_removal = true;
|
||||
markForRemoval();
|
||||
}
|
||||
|
||||
actionstream << puncher->getDescription() << " (id=" << puncher->getId() <<
|
||||
|
@ -71,6 +71,11 @@ public:
|
||||
bool getSelectionBox(aabb3f *toset) const;
|
||||
bool collideWithObjects() const;
|
||||
|
||||
protected:
|
||||
void dispatchScriptDeactivate();
|
||||
virtual void onMarkedForDeactivation() { dispatchScriptDeactivate(); }
|
||||
virtual void onMarkedForRemoval() { dispatchScriptDeactivate(); }
|
||||
|
||||
private:
|
||||
std::string getPropertyPacket();
|
||||
void sendPosition(bool do_interpolate, bool is_movement_end);
|
||||
|
@ -531,7 +531,7 @@ bool PlayerSAO::setWieldedItem(const ItemStack &item)
|
||||
void PlayerSAO::disconnected()
|
||||
{
|
||||
m_peer_id = PEER_ID_INEXISTENT;
|
||||
m_pending_removal = true;
|
||||
markForRemoval();
|
||||
}
|
||||
|
||||
void PlayerSAO::unlinkPlayerSessionAndSave()
|
||||
|
@ -73,3 +73,19 @@ void ServerActiveObject::dumpAOMessagesToQueue(std::queue<ActiveObjectMessage> &
|
||||
m_messages_out.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerActiveObject::markForRemoval()
|
||||
{
|
||||
if (!m_pending_removal) {
|
||||
onMarkedForRemoval();
|
||||
m_pending_removal = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ServerActiveObject::markForDeactivation()
|
||||
{
|
||||
if (!m_pending_deactivation) {
|
||||
onMarkedForDeactivation();
|
||||
m_pending_deactivation = true;
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,10 @@ public:
|
||||
virtual bool environmentDeletes() const
|
||||
{ return true; }
|
||||
|
||||
// Safely mark the object for removal or deactivation
|
||||
void markForRemoval();
|
||||
void markForDeactivation();
|
||||
|
||||
// Create a certain type of ServerActiveObject
|
||||
static ServerActiveObject* create(ActiveObjectType type,
|
||||
ServerEnvironment *env, u16 id, v3f pos,
|
||||
@ -213,25 +217,6 @@ public:
|
||||
*/
|
||||
u16 m_known_by_count = 0;
|
||||
|
||||
/*
|
||||
- Whether this object is to be removed when nobody knows about
|
||||
it anymore.
|
||||
- Removal is delayed to preserve the id for the time during which
|
||||
it could be confused to some other object by some client.
|
||||
- This is usually set to true by the step() method when the object wants
|
||||
to be deleted but can be set by anything else too.
|
||||
*/
|
||||
bool m_pending_removal = false;
|
||||
|
||||
/*
|
||||
Same purpose as m_pending_removal but for deactivation.
|
||||
deactvation = save static data in block, remove active object
|
||||
|
||||
If this is set alongside with m_pending_removal, removal takes
|
||||
priority.
|
||||
*/
|
||||
bool m_pending_deactivation = false;
|
||||
|
||||
/*
|
||||
A getter that unifies the above to answer the question:
|
||||
"Can the environment still interact with this object?"
|
||||
@ -239,6 +224,9 @@ public:
|
||||
inline bool isGone() const
|
||||
{ return m_pending_removal || m_pending_deactivation; }
|
||||
|
||||
inline bool isPendingRemoval() const
|
||||
{ return m_pending_removal; }
|
||||
|
||||
/*
|
||||
Whether the object's static data has been stored to a block
|
||||
*/
|
||||
@ -250,6 +238,9 @@ public:
|
||||
v3s16 m_static_block = v3s16(1337,1337,1337);
|
||||
|
||||
protected:
|
||||
virtual void onMarkedForDeactivation() {}
|
||||
virtual void onMarkedForRemoval() {}
|
||||
|
||||
virtual void onAttach(int parent_id) {}
|
||||
virtual void onDetach(int parent_id) {}
|
||||
|
||||
@ -257,6 +248,27 @@ protected:
|
||||
v3f m_base_position;
|
||||
std::unordered_set<u32> m_attached_particle_spawners;
|
||||
|
||||
/*
|
||||
Same purpose as m_pending_removal but for deactivation.
|
||||
deactvation = save static data in block, remove active object
|
||||
|
||||
If this is set alongside with m_pending_removal, removal takes
|
||||
priority.
|
||||
Note: Do not assign this directly, use markForDeactivation() instead.
|
||||
*/
|
||||
bool m_pending_deactivation = false;
|
||||
|
||||
/*
|
||||
- Whether this object is to be removed when nobody knows about
|
||||
it anymore.
|
||||
- Removal is delayed to preserve the id for the time during which
|
||||
it could be confused to some other object by some client.
|
||||
- This is usually set to true by the step() method when the object wants
|
||||
to be deleted but can be set by anything else too.
|
||||
Note: Do not assign this directly, use markForRemoval() instead.
|
||||
*/
|
||||
bool m_pending_removal = false;
|
||||
|
||||
/*
|
||||
Queue of messages to be sent to the client
|
||||
*/
|
||||
|
@ -1164,7 +1164,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode)
|
||||
|
||||
// If known by some client, don't delete immediately
|
||||
if (obj->m_known_by_count > 0) {
|
||||
obj->m_pending_removal = true;
|
||||
obj->markForRemoval();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1792,7 +1792,7 @@ void ServerEnvironment::removeRemovedObjects()
|
||||
/*
|
||||
Delete static data from block if removed
|
||||
*/
|
||||
if (obj->m_pending_removal)
|
||||
if (obj->isPendingRemoval())
|
||||
deleteStaticFromBlock(obj, id, MOD_REASON_REMOVE_OBJECTS_REMOVE, false);
|
||||
|
||||
// If still known by clients, don't actually remove. On some future
|
||||
@ -1803,7 +1803,7 @@ void ServerEnvironment::removeRemovedObjects()
|
||||
/*
|
||||
Move static data from active to stored if deactivated
|
||||
*/
|
||||
if (!obj->m_pending_removal && obj->m_static_exists) {
|
||||
if (!obj->isPendingRemoval() && obj->m_static_exists) {
|
||||
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
|
||||
if (block) {
|
||||
const auto i = block->m_static_objects.m_active.find(id);
|
||||
@ -1991,6 +1991,7 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
|
||||
if (!force_delete && obj->m_static_exists &&
|
||||
!m_active_blocks.contains(obj->m_static_block) &&
|
||||
m_active_blocks.contains(blockpos_o)) {
|
||||
|
||||
// Delete from block where object was located
|
||||
deleteStaticFromBlock(obj, id, MOD_REASON_STATIC_DATA_REMOVED, false);
|
||||
|
||||
@ -2068,6 +2069,10 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
|
||||
force_delete = true;
|
||||
}
|
||||
|
||||
// Regardless of what happens to the object at this point, deactivate it first.
|
||||
// This ensures that LuaEntity on_deactivate is always called.
|
||||
obj->markForDeactivation();
|
||||
|
||||
/*
|
||||
If known by some client, set pending deactivation.
|
||||
Otherwise delete it immediately.
|
||||
@ -2077,7 +2082,6 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
|
||||
<< "object id=" << id << " is known by clients"
|
||||
<< "; not deleting yet" << std::endl;
|
||||
|
||||
obj->m_pending_deactivation = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -332,6 +332,13 @@ public:
|
||||
return m_ao_manager.getObjectsInsideRadius(pos, radius, objects, include_obj_cb);
|
||||
}
|
||||
|
||||
// Find all active objects inside a box
|
||||
void getObjectsInArea(std::vector<ServerActiveObject *> &objects, const aabb3f &box,
|
||||
std::function<bool(ServerActiveObject *obj)> include_obj_cb)
|
||||
{
|
||||
return m_ao_manager.getObjectsInArea(box, objects, include_obj_cb);
|
||||
}
|
||||
|
||||
// Clear objects, loading and going through every MapBlock
|
||||
void clearObjects(ClearObjectsMode mode);
|
||||
|
||||
|
@ -1015,10 +1015,10 @@ void srp_user_process_challenge(struct SRPUser *usr,
|
||||
goto cleanup_and_exit;
|
||||
|
||||
*bytes_M = usr->M;
|
||||
if (len_M) *len_M = hash_length(usr->hash_alg);
|
||||
*len_M = hash_length(usr->hash_alg);
|
||||
} else {
|
||||
*bytes_M = NULL;
|
||||
if (len_M) *len_M = 0;
|
||||
*len_M = 0;
|
||||
}
|
||||
|
||||
cleanup_and_exit:
|
||||
|
@ -633,7 +633,7 @@ static bool parseNamedColorString(const std::string &value, video::SColor &color
|
||||
color_name = value;
|
||||
}
|
||||
|
||||
color_name = lowercase(value);
|
||||
color_name = lowercase(color_name);
|
||||
|
||||
std::map<const std::string, unsigned>::const_iterator it;
|
||||
it = named_colors.colors.find(color_name);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user